more zero-length changes for svg compatibility
If a path contains a moveTo followed by a line or curve, even if the line or curve has no length, SVG expects the end caps to draw if the cap style is round or square. Fredrik Söderquist attached a patch to the chrome bug (slightly modified here) that fixes layout test failures resulting from deleting special-case code in SVG dealing with zero-length path segments. R=reed@google.com,fs@opera.com BUG=22974 Review URL: https://codereview.chromium.org/1330623003
This commit is contained in:
parent
a1254acdb3
commit
62fb1ba178
@ -84,12 +84,16 @@ private:
|
||||
*/
|
||||
class ZeroLenStrokesGM : public skiagm::GM {
|
||||
SkPath fMoveHfPath, fMoveZfPath, fDashedfPath, fRefPath[4];
|
||||
SkPath fCubicPath, fQuadPath, fLinePath;
|
||||
protected:
|
||||
void onOnceBeforeDraw() override {
|
||||
|
||||
SkAssertResult(SkParsePath::FromSVGString("M0,0h0M10,0h0M20,0h0", &fMoveHfPath));
|
||||
SkAssertResult(SkParsePath::FromSVGString("M0,0zM10,0zM20,0z", &fMoveZfPath));
|
||||
SkAssertResult(SkParsePath::FromSVGString("M0,0h25", &fDashedfPath));
|
||||
SkAssertResult(SkParsePath::FromSVGString("M 0 0 C 0 0 0 0 0 0", &fCubicPath));
|
||||
SkAssertResult(SkParsePath::FromSVGString("M 0 0 Q 0 0 0 0", &fQuadPath));
|
||||
SkAssertResult(SkParsePath::FromSVGString("M 0 0 L 0 0", &fLinePath));
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
fRefPath[0].addCircle(i * 10.f, 0, 5);
|
||||
@ -140,6 +144,12 @@ protected:
|
||||
canvas->translate(0, 30);
|
||||
fillPaint.setAlpha(127);
|
||||
canvas->drawPath(fRefPath[1 + i * 2], fillPaint);
|
||||
canvas->translate(0, 30);
|
||||
canvas->drawPath(fCubicPath, strokePaint);
|
||||
canvas->translate(0, 30);
|
||||
canvas->drawPath(fQuadPath, strokePaint);
|
||||
canvas->translate(0, 30);
|
||||
canvas->drawPath(fLinePath, strokePaint);
|
||||
canvas->restore();
|
||||
}
|
||||
}
|
||||
|
@ -2124,8 +2124,8 @@ void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
|
||||
if (r.width() <= 0 && r.height() <= 0) {
|
||||
if (path.isInverseFillType()) {
|
||||
this->internalDrawPaint(paint);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
|
||||
|
@ -619,6 +619,10 @@ void SkPathStroker::conicTo(const SkPoint& pt1, const SkPoint& pt2, SkScalar wei
|
||||
SkPoint reduction;
|
||||
ReductionType reductionType = CheckConicLinear(conic, &reduction);
|
||||
if (kPoint_ReductionType == reductionType) {
|
||||
/* If the stroke consists of a moveTo followed by a degenerate curve, treat it
|
||||
as if it were followed by a zero-length line. Lines without length
|
||||
can have square and round end caps. */
|
||||
this->lineTo(pt2);
|
||||
return;
|
||||
}
|
||||
if (kLine_ReductionType == reductionType) {
|
||||
@ -653,6 +657,10 @@ void SkPathStroker::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
|
||||
SkPoint reduction;
|
||||
ReductionType reductionType = CheckQuadLinear(quad, &reduction);
|
||||
if (kPoint_ReductionType == reductionType) {
|
||||
/* If the stroke consists of a moveTo followed by a degenerate curve, treat it
|
||||
as if it were followed by a zero-length line. Lines without length
|
||||
can have square and round end caps. */
|
||||
this->lineTo(pt2);
|
||||
return;
|
||||
}
|
||||
if (kLine_ReductionType == reductionType) {
|
||||
@ -1168,6 +1176,10 @@ void SkPathStroker::cubicTo(const SkPoint& pt1, const SkPoint& pt2,
|
||||
const SkPoint* tangentPt;
|
||||
ReductionType reductionType = CheckCubicLinear(cubic, reduction, &tangentPt);
|
||||
if (kPoint_ReductionType == reductionType) {
|
||||
/* If the stroke consists of a moveTo followed by a degenerate curve, treat it
|
||||
as if it were followed by a zero-length line. Lines without length
|
||||
can have square and round end caps. */
|
||||
this->lineTo(pt3);
|
||||
return;
|
||||
}
|
||||
if (kLine_ReductionType == reductionType) {
|
||||
|
@ -54,7 +54,13 @@ static void drawAndTest(skiatest::Reporter* reporter, const SkPath& path,
|
||||
}
|
||||
}
|
||||
|
||||
static void iter_paint(skiatest::Reporter* reporter, const SkPath& path, bool shouldDraw) {
|
||||
enum DrawCaps {
|
||||
kDontDrawCaps,
|
||||
kDrawCaps
|
||||
};
|
||||
|
||||
static void iter_paint(skiatest::Reporter* reporter, const SkPath& path, bool shouldDraw,
|
||||
DrawCaps drawCaps) {
|
||||
static const SkPaint::Cap gCaps[] = {
|
||||
SkPaint::kButt_Cap,
|
||||
SkPaint::kRound_Cap,
|
||||
@ -73,6 +79,11 @@ static void iter_paint(skiatest::Reporter* reporter, const SkPath& path, bool sh
|
||||
for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
|
||||
for (size_t join = 0; join < SK_ARRAY_COUNT(gJoins); ++join) {
|
||||
for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
|
||||
if (drawCaps && SkPaint::kButt_Cap != gCaps[cap]
|
||||
&& SkPaint::kFill_Style != gStyles[style]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SkPaint paint;
|
||||
paint.setStrokeWidth(SkIntToScalar(10));
|
||||
|
||||
@ -127,10 +138,14 @@ static void test_emptydrawing(skiatest::Reporter* reporter) {
|
||||
if (doClose) {
|
||||
path.close();
|
||||
}
|
||||
/* zero length segments and close following moves draw round and square caps */
|
||||
bool allowCaps = make_L == gMakeProc[i] || make_Q == gMakeProc[i]
|
||||
|| make_C == gMakeProc[i] || make_MZM == gMakeProc[i];
|
||||
allowCaps |= SkToBool(doClose);
|
||||
for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
|
||||
path.setFillType(gFills[fill]);
|
||||
bool shouldDraw = path.isInverseFillType();
|
||||
iter_paint(reporter, path, shouldDraw);
|
||||
iter_paint(reporter, path, shouldDraw, allowCaps ? kDrawCaps : kDontDrawCaps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user