void onDraw(SkCanvas* canvas) override {
canvas->save();
- canvas->translate(-2, 20);
+ canvas->translate(-2, 120);
drawOne(canvas, fPath, SkRect::MakeLTRB(0, 0, 80, 150));
canvas->translate(0, 170);
drawOne(canvas, fPath, SkRect::MakeLTRB(0, 0, 80, 100));
canvas->translate(0, 170);
drawOne(canvas, fPath, SkRect::MakeLTRB(0, 0, 10, 150));
canvas->restore();
+ canvas->save();
+ canvas->translate(20, -2);
+ drawOne(canvas, fFlipped, SkRect::MakeLTRB(0, 0, 150, 80));
+ canvas->translate(170, 0);
+ drawOne(canvas, fFlipped, SkRect::MakeLTRB(0, 0, 100, 80));
+ canvas->translate(170, 0);
+ drawOne(canvas, fFlipped, SkRect::MakeLTRB(0, 0, 150, 30));
+ canvas->translate(170, 0);
+ drawOne(canvas, fFlipped, SkRect::MakeLTRB(0, 0, 150, 10));
+ canvas->restore();
}
void drawOne(SkCanvas* canvas, const SkPath& path, const SkRect& clip) {
fPath.cubicTo( 11.608591683531916f, 87.33115f, -0.010765133872116195f, 109.16448333333332f,
-0.013089005235602302f, 131);
fPath.close();
+ fFlipped = fPath;
+ SkMatrix matrix;
+ matrix.reset();
+ matrix.setScaleX(0);
+ matrix.setScaleY(0);
+ matrix.setSkewX(1);
+ matrix.setSkewY(1);
+ fFlipped.transform(matrix);
}
SkPath fPath;
+ SkPath fFlipped;
private:
typedef skiagm::GM INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
-// Modify pts[] in place so that it is clipped in Y to the clip rect
-static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) {
-
- // are we partially above
- if (pts[0].fY < clip.fTop) {
- SkPoint tmp[7];
- if (SkChopMonoCubicAtY(pts, clip.fTop, tmp)) {
- // tmp[3, 4].fY should all be to the below clip.fTop.
- // Since we can't trust the numerics of
- // the chopper, we force those conditions now
- tmp[3].fY = clip.fTop;
- clamp_ge(tmp[4].fY, clip.fTop);
-
- pts[0] = tmp[3];
- pts[1] = tmp[4];
- pts[2] = tmp[5];
- } else {
- // if chopMonoCubicAtY failed, then we may have hit inexact numerics
- // so we just clamp against the top
- for (int i = 0; i < 4; i++) {
- clamp_ge(pts[i].fY, clip.fTop);
- }
- }
- }
-
- // are we partially below
- if (pts[3].fY > clip.fBottom) {
- SkPoint tmp[7];
- if (SkChopMonoCubicAtY(pts, clip.fBottom, tmp)) {
- tmp[3].fY = clip.fBottom;
- clamp_le(tmp[2].fY, clip.fBottom);
-
- pts[1] = tmp[1];
- pts[2] = tmp[2];
- pts[3] = tmp[3];
- } else {
- // if chopMonoCubicAtY failed, then we may have hit inexact numerics
- // so we just clamp against the bottom
- for (int i = 0; i < 4; i++) {
- clamp_le(pts[i].fY, clip.fBottom);
- }
- }
- }
-}
-
-static void chop_mono_cubic_at_x(SkPoint pts[4], SkScalar x, SkPoint tmp[7]) {
- if (SkChopMonoCubicAtX(pts, x, tmp)) {
- return;
- }
+static SkScalar mono_cubic_closestT(const SkScalar src[], SkScalar x) {
SkScalar t = 0.5f;
SkScalar lastT;
SkScalar bestT SK_INIT_TO_AVOID_WARNING;
SkScalar step = 0.25f;
- SkScalar D = pts[0].fX;
- SkScalar A = pts[3].fX + 3*(pts[1].fX - pts[2].fX) - D;
- SkScalar B = 3*(pts[2].fX - pts[1].fX - pts[1].fX + D);
- SkScalar C = 3*(pts[1].fX - D);
+ SkScalar D = src[0];
+ SkScalar A = src[6] + 3*(src[2] - src[4]) - D;
+ SkScalar B = 3*(src[4] - src[2] - src[2] + D);
+ SkScalar C = 3*(src[2] - D);
x -= D;
SkScalar closest = SK_ScalarMax;
do {
t += loc < x ? step : -step;
step *= 0.5f;
} while (closest > 0.25f && lastT != t);
- SkChopCubicAt(pts, tmp, bestT);
+ return bestT;
+}
+
+static void chop_mono_cubic_at_y(SkPoint src[4], SkScalar y, SkPoint dst[7]) {
+ if (SkChopMonoCubicAtY(src, y, dst)) {
+ return;
+ }
+ SkChopCubicAt(src, dst, mono_cubic_closestT(&src->fY, y));
+}
+
+// Modify pts[] in place so that it is clipped in Y to the clip rect
+static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) {
+
+ // are we partially above
+ if (pts[0].fY < clip.fTop) {
+ SkPoint tmp[7];
+ chop_mono_cubic_at_y(pts, clip.fTop, tmp);
+ // tmp[3, 4].fY should all be to the below clip.fTop.
+ // Since we can't trust the numerics of
+ // the chopper, we force those conditions now
+ tmp[3].fY = clip.fTop;
+ clamp_ge(tmp[4].fY, clip.fTop);
+
+ pts[0] = tmp[3];
+ pts[1] = tmp[4];
+ pts[2] = tmp[5];
+ }
+
+ // are we partially below
+ if (pts[3].fY > clip.fBottom) {
+ SkPoint tmp[7];
+ chop_mono_cubic_at_y(pts, clip.fBottom, tmp);
+ tmp[3].fY = clip.fBottom;
+ clamp_le(tmp[2].fY, clip.fBottom);
+
+ pts[1] = tmp[1];
+ pts[2] = tmp[2];
+ pts[3] = tmp[3];
+ }
+}
+
+static void chop_mono_cubic_at_x(SkPoint src[4], SkScalar x, SkPoint dst[7]) {
+ if (SkChopMonoCubicAtX(src, x, dst)) {
+ return;
+ }
+ SkChopCubicAt(src, dst, mono_cubic_closestT(&src->fX, x));
}
// srcPts[] must be monotonic in X and Y