Commit b9eb6a0e authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Refactor SVGMarkerData

This CL reworks the core of SVGMarkerData so that it first extracts the
"features" of the current segment/PathElement, and then uses those
features to determine the orientation.

The state of SVGMarkerData is also changed from two pairs of points to
two vectors, since this is the representation that's actually used by
CurrentAngle(). It should also be a better representation when handling
of degenerate curves is added.

CurrentAngle() is changed to return a 'double', and the clamping
previously done in the method is now done by the callers. Additionally
The code that computes the bisected angle is split out to a separate
function.

Bug: 450368
Change-Id: Ic9561cab3bbf9c3f5cbc9f3607cfc9bfe90fea05
Reviewed-on: https://chromium-review.googlesource.com/1193847Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#587220}
parent 4e05f182
......@@ -56,8 +56,8 @@ class SVGMarkerData {
}
void PathIsDone() {
positions_.push_back(
MarkerPosition(kEndMarker, origin_, CurrentAngle(kEndMarker)));
float angle = clampTo<float>(CurrentAngle(kEndMarker));
positions_.push_back(MarkerPosition(kEndMarker, origin_, angle));
}
static inline LayoutSVGResourceMarker* MarkerForType(
......@@ -79,97 +79,104 @@ class SVGMarkerData {
}
private:
float CurrentAngle(SVGMarkerType type) const {
static double BisectingAngle(double in_angle, double out_angle) {
// WK193015: Prevent bugs due to angles being non-continuous.
if (fabs(in_angle - out_angle) > 180)
in_angle += 360;
return (in_angle + out_angle) / 2;
}
double CurrentAngle(SVGMarkerType type) const {
// For details of this calculation, see:
// http://www.w3.org/TR/SVG/single-page.html#painting-MarkerElement
FloatPoint in_slope(inslope_points_[1] - inslope_points_[0]);
FloatPoint out_slope(outslope_points_[1] - outslope_points_[0]);
double in_angle = rad2deg(in_slope.SlopeAngleRadians());
double out_angle = rad2deg(out_slope.SlopeAngleRadians());
double in_angle = rad2deg(FloatPoint(in_slope_).SlopeAngleRadians());
double out_angle = rad2deg(FloatPoint(out_slope_).SlopeAngleRadians());
switch (type) {
case kStartMarker:
if (auto_start_reverse_)
out_angle += 180;
return clampTo<float>(out_angle);
return out_angle;
case kMidMarker:
// WK193015: Prevent bugs due to angles being non-continuous.
if (fabs(in_angle - out_angle) > 180)
in_angle += 360;
return clampTo<float>((in_angle + out_angle) / 2);
return BisectingAngle(in_angle, out_angle);
case kEndMarker:
return clampTo<float>(in_angle);
return in_angle;
}
NOTREACHED();
return 0;
}
void UpdateOutslope(const PathElement& element) {
outslope_points_[0] = origin_;
FloatPoint point = element.type == kPathElementCloseSubpath
? subpath_start_
: element.points[0];
outslope_points_[1] = point;
struct SegmentData {
FloatSize start_tangent; // Tangent in the start point of the segment.
FloatSize end_tangent; // Tangent in the end point of the segment.
FloatPoint position; // The end point of the segment.
};
SegmentData ExtractPathElementFeatures(const PathElement& element) const {
SegmentData data;
const FloatPoint* points = element.points;
switch (element.type) {
case kPathElementAddCurveToPoint:
data.position = points[2];
data.start_tangent = points[0] - origin_;
data.end_tangent = points[2] - points[1];
break;
case kPathElementAddQuadCurveToPoint:
data.position = points[1];
data.start_tangent = points[0] - origin_;
data.end_tangent = points[1] - points[0];
break;
case kPathElementMoveToPoint:
case kPathElementAddLineToPoint:
data.position = points[0];
data.start_tangent = data.position - origin_;
data.end_tangent = data.position - origin_;
break;
case kPathElementCloseSubpath:
data.position = subpath_start_;
data.start_tangent = data.position - origin_;
data.end_tangent = data.position - origin_;
break;
}
return data;
}
void UpdateFromPathElement(const PathElement& element) {
// First update the outslope for the previous element.
UpdateOutslope(element);
SegmentData segment_data = ExtractPathElementFeatures(element);
// First update the outgoing slope for the previous element.
out_slope_ = segment_data.start_tangent;
// Record the marker for the previous element.
if (element_index_ > 0) {
SVGMarkerType marker_type =
element_index_ == 1 ? kStartMarker : kMidMarker;
positions_.push_back(
MarkerPosition(marker_type, origin_, CurrentAngle(marker_type)));
float angle = clampTo<float>(CurrentAngle(marker_type));
positions_.push_back(MarkerPosition(marker_type, origin_, angle));
}
// Update our marker data for this element.
UpdateMarkerDataForPathElement(element);
++element_index_;
}
// Update the incoming slope for this marker position.
in_slope_ = segment_data.end_tangent;
void UpdateMarkerDataForPathElement(const PathElement& element) {
const FloatPoint* points = element.points;
// Update marker position.
origin_ = segment_data.position;
switch (element.type) {
case kPathElementAddQuadCurveToPoint:
inslope_points_[0] = points[0];
inslope_points_[1] = points[1];
origin_ = points[1];
break;
case kPathElementAddCurveToPoint:
inslope_points_[0] = points[1];
inslope_points_[1] = points[2];
origin_ = points[2];
break;
case kPathElementMoveToPoint:
subpath_start_ = points[0];
FALLTHROUGH;
case kPathElementAddLineToPoint:
UpdateInslope(points[0]);
origin_ = points[0];
break;
case kPathElementCloseSubpath:
UpdateInslope(subpath_start_);
origin_ = subpath_start_;
subpath_start_ = FloatPoint();
}
}
// If this is a 'move to' segment, save the point for use with 'close'.
if (element.type == kPathElementMoveToPoint)
subpath_start_ = element.points[0];
else if (element.type == kPathElementCloseSubpath)
subpath_start_ = FloatPoint();
void UpdateInslope(const FloatPoint& point) {
inslope_points_[0] = origin_;
inslope_points_[1] = point;
++element_index_;
}
Vector<MarkerPosition>& positions_;
unsigned element_index_;
FloatPoint origin_;
FloatPoint subpath_start_;
FloatPoint inslope_points_[2];
FloatPoint outslope_points_[2];
FloatSize in_slope_;
FloatSize out_slope_;
bool auto_start_reverse_;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment