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

Handle degenerate curve segments for marker orientation

When a cubic or quadratic curve have a point that coincide with another
of its point such that either the start or end tangent vector is
degenerate, the orientation in that point will be 0. In such cases try
to use the next/previous non-degenerate tangent vector (if any) instead.

Bug: 450368
Change-Id: I35db404b3f82cf61b10427678feecc2157eeeb26
Reviewed-on: https://chromium-review.googlesource.com/1196503Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#587743}
parent 3d00d1e7
<!DOCTYPE html>
<div style="width: 400px; height: 100px; background-color: green"></div>
<!DOCTYPE html>
<svg width="400">
<marker id="me" orient="auto" overflow="visible">
<rect x="-1" y="-0.5" width="1" height="1" fill="green"/>
</marker>
<g marker-end="url(#me)" stroke-width="100" stroke="red">
<!-- Points 3 and 4 coincident -->
<path d="M50,0C50,50 50,100 50,100"/>
<!-- Points 2, 3 and 4 coincident -->
<path d="M50,0C50,100 50,100 50,100" transform="translate(100 0)"/>
</g>
<marker id="ms" orient="auto" overflow="visible">
<rect x="0" y="-0.5" width="1" height="1" fill="green"/>
</marker>
<g marker-start="url(#ms)" stroke-width="100" stroke="red" transform="translate(200 0)">
<!-- Points 1 and 2 coincident -->
<path d="M50,0C50,0 50,50 50,100"/>
<!-- Points 1, 2 and 3 coincident -->
<path d="M50,0C50,0 50,0 50,100" transform="translate(100 0)"/>
</g>
</svg>
<!DOCTYPE html>
<div style="width: 200px; height: 100px; background-color: green"></div>
<!DOCTYPE html>
<svg width="400">
<marker id="me" orient="auto" overflow="visible">
<rect x="-1" y="-0.5" width="1" height="1" fill="green"/>
</marker>
<g marker-end="url(#me)" stroke-width="100" stroke="red">
<!-- Points 2 and 3 coincident -->
<path d="M50,0Q50,100 50,100"/>
</g>
<marker id="ms" orient="auto" overflow="visible">
<rect x="0" y="-0.5" width="1" height="1" fill="green"/>
</marker>
<g marker-start="url(#ms)" stroke-width="100" stroke="red" transform="translate(100 0)">
<!-- Points 1 and 2 coincident -->
<path d="M50,0Q50,0 50,100"/>
</g>
</svg>
...@@ -113,6 +113,18 @@ class SVGMarkerData { ...@@ -113,6 +113,18 @@ class SVGMarkerData {
FloatPoint position; // The end point of the segment. FloatPoint position; // The end point of the segment.
}; };
static void ComputeQuadTangents(SegmentData& data,
const FloatPoint& start,
const FloatPoint& control,
const FloatPoint& end) {
data.start_tangent = control - start;
data.end_tangent = end - control;
if (data.start_tangent.IsZero())
data.start_tangent = data.end_tangent;
else if (data.end_tangent.IsZero())
data.end_tangent = data.start_tangent;
}
SegmentData ExtractPathElementFeatures(const PathElement& element) const { SegmentData ExtractPathElementFeatures(const PathElement& element) const {
SegmentData data; SegmentData data;
const FloatPoint* points = element.points; const FloatPoint* points = element.points;
...@@ -121,11 +133,14 @@ class SVGMarkerData { ...@@ -121,11 +133,14 @@ class SVGMarkerData {
data.position = points[2]; data.position = points[2];
data.start_tangent = points[0] - origin_; data.start_tangent = points[0] - origin_;
data.end_tangent = points[2] - points[1]; data.end_tangent = points[2] - points[1];
if (data.start_tangent.IsZero())
ComputeQuadTangents(data, points[0], points[1], points[2]);
else if (data.end_tangent.IsZero())
ComputeQuadTangents(data, origin_, points[0], points[1]);
break; break;
case kPathElementAddQuadCurveToPoint: case kPathElementAddQuadCurveToPoint:
data.position = points[1]; data.position = points[1];
data.start_tangent = points[0] - origin_; ComputeQuadTangents(data, origin_, points[0], points[1]);
data.end_tangent = points[1] - points[0];
break; break;
case kPathElementMoveToPoint: case kPathElementMoveToPoint:
case kPathElementAddLineToPoint: case kPathElementAddLineToPoint:
......
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