aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar dandov <dandov@google.com>2014-08-12 08:34:29 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-08-12 08:34:29 -0700
commitb3c9d1c33caf325aada244204215eb790c228c12 (patch)
tree067c0017914891d0aff2b6d6163f2de1c2b20c54
parent9c7695b0b59b97da933cd11014c922344a8d7654 (diff)
SkCanvas::drawPatch param SkPoint[12]
drawPatch now receives as parameter const SkPoint cubics[12] Adjusted derived classes and serialization. Ajusted GM's and benches that take into account combinations of optional parameters, the scale of the patch and 4 different types of patches. Planning on adding the extra functionality of SkPatch in another CL. BUG=skia: R=egdaniel@google.com, reed@google.com Author: dandov@google.com Review URL: https://codereview.chromium.org/463493002
-rw-r--r--bench/PatchBench.cpp325
-rw-r--r--gm/patch.cpp140
-rw-r--r--gyp/bench.gypi1
-rw-r--r--gyp/core.gypi2
-rw-r--r--include/core/SkCanvas.h21
-rw-r--r--include/core/SkDevice.h3
-rw-r--r--include/core/SkPatch.h182
-rw-r--r--include/core/SkReadBuffer.h2
-rw-r--r--include/core/SkReader32.h5
-rw-r--r--include/core/SkWriter32.h7
-rw-r--r--include/utils/SkDeferredCanvas.h6
-rw-r--r--include/utils/SkDumpCanvas.h4
-rw-r--r--include/utils/SkNWayCanvas.h6
-rw-r--r--include/utils/SkProxyCanvas.h6
-rw-r--r--src/core/SkBBoxRecord.cpp10
-rw-r--r--src/core/SkBBoxRecord.h4
-rw-r--r--src/core/SkCanvas.cpp17
-rw-r--r--src/core/SkDevice.cpp12
-rw-r--r--src/core/SkPatch.cpp262
-rw-r--r--src/core/SkPicturePlayback.cpp26
-rw-r--r--src/core/SkPictureRecord.cpp53
-rw-r--r--src/core/SkPictureRecord.h7
-rw-r--r--src/core/SkReadBuffer.cpp4
-rw-r--r--src/core/SkRecordDraw.cpp2
-rw-r--r--src/core/SkRecorder.cpp10
-rw-r--r--src/core/SkRecorder.h5
-rw-r--r--src/core/SkRecords.h20
-rw-r--r--src/core/SkValidatingReadBuffer.cpp11
-rw-r--r--src/core/SkValidatingReadBuffer.h1
-rw-r--r--src/pipe/SkGPipeRead.cpp26
-rw-r--r--src/pipe/SkGPipeWrite.cpp50
-rw-r--r--src/utils/SkDeferredCanvas.cpp10
-rw-r--r--src/utils/SkDumpCanvas.cpp26
-rw-r--r--src/utils/SkNWayCanvas.cpp6
-rw-r--r--src/utils/SkPatchUtils.cpp307
-rw-r--r--src/utils/SkPatchUtils.h104
-rw-r--r--src/utils/SkProxyCanvas.cpp6
37 files changed, 1061 insertions, 628 deletions
diff --git a/bench/PatchBench.cpp b/bench/PatchBench.cpp
new file mode 100644
index 0000000000..2e99e4efbf
--- /dev/null
+++ b/bench/PatchBench.cpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkGradientShader.h"
+#include "SkPaint.h"
+#include "SkPatchUtils.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+#include "SkTArray.h"
+
+class PatchBench : public Benchmark {
+
+public:
+
+ enum VertexMode {
+ kNone_VertexMode,
+ kColors_VertexMode,
+ kTexCoords_VertexMode,
+ kBoth_VertexMode
+ };
+
+ PatchBench(SkPoint scale, VertexMode vertexMode)
+ : fScale(scale)
+ , fVertexMode(vertexMode) { }
+
+ // to add name of specific class override this method
+ virtual void appendName(SkString* name) {
+ name->append("normal");
+ }
+
+ // to make other type of patches override this method
+ virtual void setCubics() {
+ const SkPoint points[SkPatchUtils::kNumCtrlPts] = {
+ //top points
+ {100,100},{150,50},{250,150}, {300,100},
+ //right points
+ {350, 150},{250,200},
+ //bottom points
+ {300,300},{250,250},{150,350},{100,300},
+ //left points
+ {50,250},{150,50}
+ };
+ memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
+ }
+
+ virtual void setColors() {
+ const SkColor colors[SkPatchUtils::kNumCorners] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
+ };
+ memcpy(fColors, colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
+ }
+
+ virtual void setTexCoords() {
+ const SkPoint texCoords[SkPatchUtils::kNumCorners] = {
+ {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f,1.0f}, {0.0f, 1.0f}
+ };
+ memcpy(fTexCoords, texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
+ }
+
+ // override this method to change the shader
+ virtual SkShader* getShader() {
+ const SkColor colors[] = {
+ SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE,
+ SK_ColorMAGENTA, SK_ColorBLUE, SK_ColorYELLOW,
+ };
+ const SkPoint pts[] = { { 200.f / 4.f, 0.f }, { 3.f * 200.f / 4, 200.f } };
+
+ return SkGradientShader::CreateLinear(pts, colors, NULL,
+ SK_ARRAY_COUNT(colors),
+ SkShader::kMirror_TileMode);
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ SkString vertexMode;
+ switch (fVertexMode) {
+ case kNone_VertexMode:
+ vertexMode.set("meshlines");
+ break;
+ case kColors_VertexMode:
+ vertexMode.set("colors");
+ break;
+ case kTexCoords_VertexMode:
+ vertexMode.set("texs");
+ break;
+ case kBoth_VertexMode:
+ vertexMode.set("colors&texs");
+ break;
+ default:
+ break;
+ }
+ SkString type;
+ this->appendName(&type);
+ fName.printf("patch_%s_%s_[%f,%f]", type.c_str(), vertexMode.c_str(),
+ fScale.x(), fScale.y());
+ return fName.c_str();
+ }
+
+ virtual void preDraw() {
+
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+
+ this->setCubics();
+ this->setColors();
+ this->setTexCoords();
+ this->setupPaint(&fPaint);
+ switch (fVertexMode) {
+ case kTexCoords_VertexMode:
+ case kBoth_VertexMode:
+ fPaint.setShader(getShader());
+ break;
+ default:
+ fPaint.setShader(NULL);
+ break;
+ }
+
+ canvas->scale(fScale.x(), fScale.y());
+ for (int i = 0; i < loops; i++) {
+ switch (fVertexMode) {
+ case kNone_VertexMode:
+ canvas->drawPatch(fCubics, NULL, NULL, NULL, fPaint);
+ break;
+ case kColors_VertexMode:
+ canvas->drawPatch(fCubics, fColors, NULL, NULL, fPaint);
+ break;
+ case kTexCoords_VertexMode:
+ canvas->drawPatch(fCubics, NULL, fTexCoords, NULL, fPaint);
+ break;
+ case kBoth_VertexMode:
+ canvas->drawPatch(fCubics, fColors, fTexCoords, NULL, fPaint);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ SkPaint fPaint;
+ SkString fName;
+ SkVector fScale;
+ SkPoint fCubics[12];
+ SkPoint fTexCoords[4];
+ SkColor fColors[4];
+ VertexMode fVertexMode;
+
+ typedef Benchmark INHERITED;
+};
+
+class SquarePatchBench : public PatchBench {
+public:
+ SquarePatchBench(SkPoint scale, VertexMode vertexMode)
+ : INHERITED(scale, vertexMode) { }
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("square");
+ }
+
+ virtual void setCubics() {
+ const SkPoint points[SkPatchUtils::kNumCtrlPts] = {
+ //top points
+ {100,100},{150,100},{250,100}, {300,100},
+ //right points
+ {300, 150},{300,250},
+ //bottom points
+ {300,300},{250,300},{150,300},{100,300},
+ //left points
+ {100,250},{100,150}
+ };
+ memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
+ }
+private:
+ typedef PatchBench INHERITED;
+};
+
+class LODDiffPatchBench : public PatchBench {
+public:
+ LODDiffPatchBench(SkPoint scale, VertexMode vertexMode)
+ : INHERITED(scale, vertexMode) { }
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("LOD_Diff");
+ }
+
+ virtual void setCubics() {
+ const SkPoint points[SkPatchUtils::kNumCtrlPts] = {
+ //top points
+ {100,175},{150,100},{250,100}, {300,0},
+ //right points
+ {300, 150},{300,250},
+ //bottom points
+ {300,400},{250,300},{150,300},{100,225},
+ //left points
+ {100,215},{100,185}
+ };
+ memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
+ }
+private:
+ typedef PatchBench INHERITED;
+};
+
+class LoopPatchBench : public PatchBench {
+public:
+ LoopPatchBench(SkPoint scale, VertexMode vertexMode)
+ : INHERITED(scale, vertexMode) { }
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("loop");
+ }
+
+ virtual void setCubics() {
+ const SkPoint points[SkPatchUtils::kNumCtrlPts] = {
+ //top points
+ {100,100},{300,200},{100,200}, {300,100},
+ //right points
+ {380, 400},{380,0},
+ //bottom points
+ {300,300},{250,250},{30,200},{100,300},
+ //left points
+ {140,325},{150,150}
+ };
+ memcpy(fCubics, points, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
+ }
+private:
+ typedef PatchBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(0.1f, 0.1f), PatchBench::kBoth_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(1.f, 1.0f), PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(1.0f, 1.0f), PatchBench::kBoth_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new PatchBench(SkVector::Make(3.0f, 3.0f), PatchBench::kBoth_VertexMode); )
+
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kBoth_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.f, 1.0f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kBoth_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new SquarePatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kBoth_VertexMode); )
+
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kBoth_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.f, 1.0f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kBoth_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new LODDiffPatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kBoth_VertexMode); )
+
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(0.1f, 0.1f),
+ PatchBench::kBoth_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.f, 1.0f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(1.0f, 1.0f),
+ PatchBench::kBoth_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kNone_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kColors_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kTexCoords_VertexMode); )
+DEF_BENCH( return new LoopPatchBench(SkVector::Make(3.0f, 3.0f),
+ PatchBench::kBoth_VertexMode); )
diff --git a/gm/patch.cpp b/gm/patch.cpp
index 3f1e07910b..d4fe4ff1f3 100644
--- a/gm/patch.cpp
+++ b/gm/patch.cpp
@@ -6,40 +6,45 @@
* found in the LICENSE file.
*/
-// This test only works with the GPU backend.
-
#include "gm.h"
+#include "SkGradientShader.h"
+#include "SkPatchUtils.h"
+
+static SkShader* make_shader() {
+ const SkColor colors[] = {
+ SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE, SK_ColorMAGENTA, SK_ColorBLUE,
+ SK_ColorYELLOW,
+ };
+ const SkPoint pts[] = { { 100.f / 4.f, 0.f }, { 3.f * 100.f / 4.f, 100.f } };
+
+ return SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
+ SkShader::kMirror_TileMode);
+}
-#if SK_SUPPORT_GPU
-
-#include "GrContext.h"
-#include "GrTest.h"
-#include "SkPatch.h"
-
-static void draw_control_points(SkCanvas* canvas, const SkPatch& patch) {
+static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
//draw control points
SkPaint paint;
- SkPoint bottom[SkPatch::kNumPtsCubic];
- patch.getBottomPoints(bottom);
- SkPoint top[SkPatch::kNumPtsCubic];
- patch.getTopPoints(top);
- SkPoint left[SkPatch::kNumPtsCubic];
- patch.getLeftPoints(left);
- SkPoint right[SkPatch::kNumPtsCubic];
- patch.getRightPoints(right);
+ SkPoint bottom[SkPatchUtils::kNumPtsCubic];
+ SkPatchUtils::getBottomCubic(cubics, bottom);
+ SkPoint top[SkPatchUtils::kNumPtsCubic];
+ SkPatchUtils::getTopCubic(cubics, top);
+ SkPoint left[SkPatchUtils::kNumPtsCubic];
+ SkPatchUtils::getLeftCubic(cubics, left);
+ SkPoint right[SkPatchUtils::kNumPtsCubic];
+ SkPatchUtils::getRightCubic(cubics, right);
paint.setColor(SK_ColorBLACK);
- paint.setStrokeWidth(0.5);
+ paint.setStrokeWidth(0.5f);
SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] };
canvas->drawPoints(SkCanvas::kLines_PointMode, 4, bottom, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom+1, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom + 1, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 4, top, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 4, left, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 4, right, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top+1, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left+1, paint);
- canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right+1, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top + 1, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left + 1, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right + 1, paint);
paint.setStrokeWidth(2);
@@ -47,21 +52,21 @@ static void draw_control_points(SkCanvas* canvas, const SkPatch& patch) {
canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, corners, paint);
paint.setColor(SK_ColorBLUE);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom+1, paint);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom + 1, paint);
paint.setColor(SK_ColorCYAN);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top+1, paint);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top + 1, paint);
paint.setColor(SK_ColorYELLOW);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left+1, paint);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left + 1, paint);
paint.setColor(SK_ColorGREEN);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right+1, paint);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right + 1, paint);
}
namespace skiagm {
/**
- * This GM draws a SkPatch.
+ * This GM draws a cubics coons patch using the specialized call SkCanvas::drawPatch.
*/
class SkPatchGM : public GM {
@@ -88,44 +93,63 @@ protected:
SkPaint paint;
// The order of the colors and points is clockwise starting at upper-left corner.
- SkColor colors[SkPatch::kNumColors] = {
- SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
- };
- SkPoint points[SkPatch::kNumCtrlPts] = {
+ const SkPoint cubics[SkPatchUtils::kNumCtrlPts] = {
//top points
- {50,50},{75,20},{125,80}, {150,50},
+ {100,100},{150,50},{250,150}, {300,100},
//right points
- {120,75},{180,125},
+ {250, 150},{350,250},
//bottom points
- {150,150},{125,120},{75,180},{50,150},
+ {300,300},{250,250},{150,350},{100,300},
//left points
- {20,125},{80,75}
+ {50,250},{150,150}
};
- SkPatch patch(points, colors);
- static const SkScalar kScale = 0.5f;
- canvas->translate(100, 100);
- canvas->save();
- for (SkScalar x = 0; x < 4; x++) {
- canvas->save();
- canvas->scale(kScale * (x + 1), kScale * (x + 1));
- canvas->translate(x * 100, 0);
- canvas->drawPatch(patch, paint);
- draw_control_points(canvas, patch);
- canvas->restore();
- }
+ const SkColor colors[SkPatchUtils::kNumCorners] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
+ };
+ const SkPoint texCoords[SkPatchUtils::kNumCorners] = {
+ {0.0f, 0.0f}, {100.0f, 0.0f}, {100.0f,100.0f}, {0.0f, 100.0f}}
+ ;
- canvas->translate(0, 270);
+ const SkXfermode::Mode modes[] = {
+ SkXfermode::kSrc_Mode,
+ SkXfermode::kDst_Mode,
+ SkXfermode::kModulate_Mode,
+ };
- static const SkScalar kSkew = 0.2f;
- for (SkScalar x = 0; x < 4; x++) {
- canvas->save();
- canvas->scale(kScale * (x + 1), kScale * (x + 1));
- canvas->translate(x * 100, 0);
- canvas->skew(kSkew * (x + 1), kSkew * (x + 1));
- canvas->drawPatch(patch, paint);
- draw_control_points(canvas, patch);
- canvas->restore();
+ SkAutoTUnref<SkShader> shader(make_shader());
+
+ canvas->save();
+ for (int y = 0; y < 3; y++) {
+ SkAutoTUnref<SkXfermode> xfer(SkXfermode::Create(modes[y]));
+
+ for (int x = 0; x < 4; x++) {
+ canvas->save();
+ canvas->translate(x * 350.0f, y * 350.0f);
+ switch (x) {
+ case 0:
+ canvas->drawPatch(cubics, NULL, NULL, xfer, paint);
+ break;
+ case 1:
+ canvas->drawPatch(cubics, colors, NULL, xfer, paint);
+ break;
+ case 2:
+ paint.setShader(shader);
+ canvas->drawPatch(cubics, NULL, texCoords, xfer, paint);
+ paint.setShader(NULL);
+ break;
+ case 3:
+ paint.setShader(shader);
+ canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
+ paint.setShader(NULL);
+ break;
+ default:
+ break;
+ }
+
+ draw_control_points(canvas, cubics);
+ canvas->restore();
+ }
}
canvas->restore();
}
@@ -137,5 +161,3 @@ private:
DEF_GM(return SkNEW(SkPatchGM); )
}
-
-#endif
diff --git a/gyp/bench.gypi b/gyp/bench.gypi
index c560523d20..30f0aa661c 100644
--- a/gyp/bench.gypi
+++ b/gyp/bench.gypi
@@ -69,6 +69,7 @@
'../bench/MergeBench.cpp',
'../bench/MorphologyBench.cpp',
'../bench/MutexBench.cpp',
+ '../bench/PatchBench.cpp',
'../bench/PathBench.cpp',
'../bench/PathIterBench.cpp',
'../bench/PathUtilsBench.cpp',
diff --git a/gyp/core.gypi b/gyp/core.gypi
index a6d563532b..8a7350e240 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -120,7 +120,6 @@
'<(skia_src_path)/core/SkPaintOptionsAndroid.cpp',
'<(skia_src_path)/core/SkPaintPriv.cpp',
'<(skia_src_path)/core/SkPaintPriv.h',
- '<(skia_src_path)/core/SkPatch.cpp',
'<(skia_src_path)/core/SkPath.cpp',
'<(skia_src_path)/core/SkPathEffect.cpp',
'<(skia_src_path)/core/SkPathHeap.cpp',
@@ -279,7 +278,6 @@
'<(skia_include_path)/core/SkOSFile.h',
'<(skia_include_path)/core/SkPackBits.h',
'<(skia_include_path)/core/SkPaint.h',
- '<(skia_include_path)/core/SkPatch.h',
'<(skia_include_path)/core/SkPath.h',
'<(skia_include_path)/core/SkPathEffect.h',
'<(skia_include_path)/core/SkPathMeasure.h',
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 011e3c3a03..8afeae6d5f 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -14,7 +14,6 @@
#include "SkClipStack.h"
#include "SkPaint.h"
#include "SkRefCnt.h"
-#include "SkPatch.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkXfermode.h"
@@ -1022,14 +1021,21 @@ public:
const uint16_t indices[], int indexCount,
const SkPaint& paint);
- /**
-
- Draw a SkPatch
+ /**
+ Draw a cubic coons patch
- @param patch specifies the 4 bounding cubic bezier curves of a patch.
+ @param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
+ starting at the top left corner.
+ @param colors specifies the colors for the corners which will be bilerp across the patch,
+ their order is clockwise starting at the top left corner.
+ @param texCoords specifies the texture coordinates that will be bilerp across the patch,
+ their order is the same as the colors.
+ @param xmode specifies how are the colors and the textures combined if both of them are
+ present.
@param paint Specifies the shader/texture if present.
*/
- virtual void drawPatch(const SkPatch& patch, const SkPaint& paint);
+ void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
/** Send a blob of data to the canvas.
For canvases that draw, this call is effectively a no-op, as the data
@@ -1224,6 +1230,9 @@ protected:
virtual void onDrawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint);
+
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
enum ClipEdgeStyle {
kHard_ClipEdgeStyle,
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 3d79a6517f..de2f8ddd35 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -243,7 +243,8 @@ protected:
const uint16_t indices[], int indexCount,
const SkPaint& paint) = 0;
// default implementation calls drawVertices
- virtual void drawPatch(const SkDraw&, const SkPatch& patch, const SkPaint& paint);
+ virtual void drawPatch(const SkDraw&, const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
/** The SkDevice passed will be an SkDevice which was returned by a call to
onCreateDevice on this device with kSaveLayer_Usage.
*/
diff --git a/include/core/SkPatch.h b/include/core/SkPatch.h
deleted file mode 100644
index 698b1cbf30..0000000000
--- a/include/core/SkPatch.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkPatch_DEFINED
-#define SkPatch_DEFINED
-
-#include "SkColor.h"
-#include "SkPreConfig.h"
-#include "SkPoint.h"
-
-/**
- * Class that represents a coons patch.
- */
-class SK_API SkPatch {
-
-public:
- /**
- * Structure that holds the vertex data related to the tessellation of a SkPatch. It is passed
- * as a parameter to the function getVertexData which sets the points, colors and texture
- * coordinates of the vertices and the indices for them to be drawn as triangles.
- */
- struct VertexData {
- int fVertexCount, fIndexCount;
- SkPoint* fPoints;
- SkPoint* fTexCoords;
- uint32_t* fColors;
- uint16_t* fIndices;
-
- VertexData()
- : fVertexCount(0)
- , fIndexCount(0)
- , fPoints(NULL)
- , fTexCoords(NULL)
- , fColors(NULL)
- , fIndices(NULL) { }
-
- ~VertexData() {
- SkDELETE_ARRAY(fPoints);
- SkDELETE_ARRAY(fTexCoords);
- SkDELETE_ARRAY(fColors);
- SkDELETE_ARRAY(fIndices);
- }
- };
-
- // Enums for control points based on the order specified in the constructor (clockwise).
- enum CubicCtrlPts {
- kTopP0_CubicCtrlPts = 0,
- kTopP1_CubicCtrlPts = 1,
- kTopP2_CubicCtrlPts = 2,
- kTopP3_CubicCtrlPts = 3,
-
- kRightP0_CubicCtrlPts = 3,
- kRightP1_CubicCtrlPts = 4,
- kRightP2_CubicCtrlPts = 5,
- kRightP3_CubicCtrlPts = 6,
-
- kBottomP0_CubicCtrlPts = 9,
- kBottomP1_CubicCtrlPts = 8,
- kBottomP2_CubicCtrlPts = 7,
- kBottomP3_CubicCtrlPts = 6,
-
- kLeftP0_CubicCtrlPts = 0,
- kLeftP1_CubicCtrlPts = 11,
- kLeftP2_CubicCtrlPts = 10,
- kLeftP3_CubicCtrlPts = 9,
- };
-
- // Enum for corner colors also clockwise.
- enum CornerColors {
- kTopLeft_CornerColors = 0,
- kTopRight_CornerColors,
- kBottomRight_CornerColors,
- kBottomLeft_CornerColors
- };
-
- enum {
- kNumCtrlPts = 12,
- kNumColors = 4,
- kNumPtsCubic = 4
- };
-
- /**
- * Points are in the following order:
- * (top curve)
- * 0 1 2 3
- * (left curve) 11 4 (right curve)
- * 10 5
- * 9 8 7 6
- * (bottom curve)
- */
- SkPatch() { }
- SkPatch(const SkPoint points[12], const SkColor colors[4]);
-
- /**
- * Function that evaluates the coons patch interpolation.
- * data refers to the pointer of the PatchData struct in which the tessellation data is set.
- * lod refers the level of detail for each axis.
- */
- bool getVertexData(SkPatch::VertexData* data, int lodX, int lodY) const;
-
- void getTopPoints(SkPoint points[4]) const {
- points[0] = fCtrlPoints[kTopP0_CubicCtrlPts];
- points[1] = fCtrlPoints[kTopP1_CubicCtrlPts];
- points[2] = fCtrlPoints[kTopP2_CubicCtrlPts];
- points[3] = fCtrlPoints[kTopP3_CubicCtrlPts];
- }
-
- void getBottomPoints(SkPoint points[4]) const {
- points[0] = fCtrlPoints[kBottomP0_CubicCtrlPts];
- points[1] = fCtrlPoints[kBottomP1_CubicCtrlPts];
- points[2] = fCtrlPoints[kBottomP2_CubicCtrlPts];
- points[3] = fCtrlPoints[kBottomP3_CubicCtrlPts];
- }
-
- void getLeftPoints(SkPoint points[4]) const {
- points[0] = fCtrlPoints[kLeftP0_CubicCtrlPts];
- points[1] = fCtrlPoints[kLeftP1_CubicCtrlPts];
- points[2] = fCtrlPoints[kLeftP2_CubicCtrlPts];
- points[3] = fCtrlPoints[kLeftP3_CubicCtrlPts];
- }
-
- void getRightPoints(SkPoint points[4]) const {
- points[0] = fCtrlPoints[kRightP0_CubicCtrlPts];
- points[1] = fCtrlPoints[kRightP1_CubicCtrlPts];
- points[2] = fCtrlPoints[kRightP2_CubicCtrlPts];
- points[3] = fCtrlPoints[kRightP3_CubicCtrlPts];
- }
-
- void getCornerPoints(SkPoint points[4]) const {
- points[0] = fCtrlPoints[kTopP0_CubicCtrlPts];
- points[1] = fCtrlPoints[kTopP3_CubicCtrlPts];
- points[2] = fCtrlPoints[kBottomP3_CubicCtrlPts];
- points[3] = fCtrlPoints[kBottomP0_CubicCtrlPts];
- }
-
- const SkPoint* getControlPoints() const {
- return fCtrlPoints;
- }
-
- const SkColor* getColors() const {
- return fCornerColors;
- }
-
- void setPoints(const SkPoint points[12]) {
- memcpy(fCtrlPoints, points, kNumCtrlPts * sizeof(SkPoint));
- }
-
- void setColors(const SkColor colors[4]) {
- memcpy(fCornerColors, colors, kNumColors * sizeof(SkColor));
- }
-
- void reset(const SkPoint points[12], const SkColor colors[4]) {
- this->setPoints(points);
- this->setColors(colors);
- }
-
- /**
- * Write the patch to the buffer, and return the number of bytes written.
- * If buffer is NULL, it still returns the number of bytes.
- */
- size_t writeToMemory(void* buffer) const;
-
- /**
- * Initializes the patch from the buffer
- *
- * buffer Memory to read from
- * length Amount of memory available in the buffer
- * returns the number of bytes read (must be a multiple of 4) or
- * 0 if there was not enough memory available
- */
- size_t readFromMemory(const void* buffer, size_t length);
-
-private:
- SkPoint fCtrlPoints[kNumCtrlPts];
- SkColor fCornerColors[kNumColors];
-};
-
-#endif
diff --git a/include/core/SkReadBuffer.h b/include/core/SkReadBuffer.h
index e4f33af038..2f04614a2b 100644
--- a/include/core/SkReadBuffer.h
+++ b/include/core/SkReadBuffer.h
@@ -108,7 +108,7 @@ public:
virtual void readIRect(SkIRect* rect);
virtual void readRect(SkRect* rect);
virtual void readRegion(SkRegion* region);
- virtual void readPatch(SkPatch* patch);
+
virtual void readPath(SkPath* path);
void readPaint(SkPaint* paint) { paint->unflatten(*this); }
diff --git a/include/core/SkReader32.h b/include/core/SkReader32.h
index 3ee63bed18..3d874d170a 100644
--- a/include/core/SkReader32.h
+++ b/include/core/SkReader32.h
@@ -15,7 +15,6 @@
#include "SkRegion.h"
#include "SkRRect.h"
#include "SkScalar.h"
-#include "SkPatch.h"
class SkString;
@@ -106,10 +105,6 @@ public:
uint16_t readU16() { return (uint16_t)this->readInt(); }
int32_t readS32() { return this->readInt(); }
uint32_t readU32() { return this->readInt(); }
-
- bool readPatch(SkPatch* patch) {
- return this->readObjectFromMemory(patch);
- }
bool readPath(SkPath* path) {
return this->readObjectFromMemory(path);
diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h
index 737ffd581d..fd24ba9ddf 100644
--- a/include/core/SkWriter32.h
+++ b/include/core/SkWriter32.h
@@ -12,7 +12,6 @@
#include "SkData.h"
#include "SkMatrix.h"
-#include "SkPatch.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "SkRRect.h"
@@ -138,12 +137,6 @@ public:
void writeRRect(const SkRRect& rrect) {
rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
}
-
- void writePatch(const SkPatch& patch) {
- size_t size = patch.writeToMemory(NULL);
- SkASSERT(SkAlign4(size) == size);
- patch.writeToMemory(this->reserve(size));
- }
void writePath(const SkPath& path) {
size_t size = path.writeToMemory(NULL);
diff --git a/include/utils/SkDeferredCanvas.h b/include/utils/SkDeferredCanvas.h
index 435c569149..89cb145df2 100644
--- a/include/utils/SkDeferredCanvas.h
+++ b/include/utils/SkDeferredCanvas.h
@@ -168,7 +168,6 @@ public:
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPatch(const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE;
virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
protected:
@@ -188,7 +187,10 @@ protected:
SkScalar constY, const SkPaint&) SK_OVERRIDE;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
-
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
+
virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
diff --git a/include/utils/SkDumpCanvas.h b/include/utils/SkDumpCanvas.h
index 866b40817a..043cdaa630 100644
--- a/include/utils/SkDumpCanvas.h
+++ b/include/utils/SkDumpCanvas.h
@@ -96,7 +96,6 @@ public:
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPatch(const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE;
virtual void drawData(const void*, size_t) SK_OVERRIDE;
virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
@@ -119,6 +118,9 @@ protected:
SkScalar constY, const SkPaint&) SK_OVERRIDE;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
virtual void onPushCull(const SkRect& cullRect) SK_OVERRIDE;
virtual void onPopCull() SK_OVERRIDE;
diff --git a/include/utils/SkNWayCanvas.h b/include/utils/SkNWayCanvas.h
index 8d2854dbab..5c48a831c6 100644
--- a/include/utils/SkNWayCanvas.h
+++ b/include/utils/SkNWayCanvas.h
@@ -48,7 +48,6 @@ public:
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint&) SK_OVERRIDE;
- virtual void drawPatch(const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE;
virtual void drawData(const void* data, size_t length) SK_OVERRIDE;
virtual SkDrawFilter* setDrawFilter(SkDrawFilter*) SK_OVERRIDE;
@@ -76,7 +75,10 @@ protected:
SkScalar constY, const SkPaint&) SK_OVERRIDE;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
-
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
+
virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
diff --git a/include/utils/SkProxyCanvas.h b/include/utils/SkProxyCanvas.h
index b340141d97..b5018e0309 100644
--- a/include/utils/SkProxyCanvas.h
+++ b/include/utils/SkProxyCanvas.h
@@ -47,7 +47,6 @@ public:
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPatch(const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE;
virtual void drawData(const void* data, size_t length) SK_OVERRIDE;
virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
@@ -73,7 +72,10 @@ protected:
SkScalar constY, const SkPaint&) SK_OVERRIDE;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
-
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
+
virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
diff --git a/src/core/SkBBoxRecord.cpp b/src/core/SkBBoxRecord.cpp
index 96e6500888..69139ad54d 100644
--- a/src/core/SkBBoxRecord.cpp
+++ b/src/core/SkBBoxRecord.cpp
@@ -7,6 +7,7 @@
*/
#include "SkBBoxRecord.h"
+#include "SkPatchUtils.h"
SkBBoxRecord::~SkBBoxRecord() {
fSaveStack.deleteAll();
@@ -284,12 +285,13 @@ void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
}
}
-void SkBBoxRecord::drawPatch(const SkPatch& patch, const SkPaint& paint) {
- const SkPoint* points = patch.getControlPoints();
+void SkBBoxRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) {
SkRect bbox;
- bbox.set(points, SkPatch::kNumCtrlPts);
+ bbox.set(cubics, SkPatchUtils::kNumCtrlPts);
if (this->transformBounds(bbox, &paint)) {
- INHERITED::drawPatch(patch, paint);
+ INHERITED::onDrawPatch(cubics, colors, texCoords, xmode, paint);
}
}
diff --git a/src/core/SkBBoxRecord.h b/src/core/SkBBoxRecord.h
index eafd9d465e..1d19b70054 100644
--- a/src/core/SkBBoxRecord.h
+++ b/src/core/SkBBoxRecord.h
@@ -55,7 +55,6 @@ public:
const SkColor colors[], SkXfermode* xfer,
const uint16_t indices[], int indexCount,
const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPatch(const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE;
protected:
virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
@@ -67,6 +66,9 @@ protected:
SkScalar constY, const SkPaint&) SK_OVERRIDE;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) SK_OVERRIDE;
virtual void willSave() SK_OVERRIDE;
virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index c6b57396e0..240dc9ccc5 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -15,6 +15,7 @@
#include "SkDrawLooper.h"
#include "SkMetaData.h"
#include "SkPathOps.h"
+#include "SkPatchUtils.h"
#include "SkPicture.h"
#include "SkRasterClip.h"
#include "SkRRect.h"
@@ -2254,20 +2255,30 @@ void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
LOOPER_END
}
-void SkCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+ if (NULL == cubics) {
+ return;
+ }
// Since a patch is always within the convex hull of the control points, we discard it when its
// bounding rectangle is completely outside the current clip.
SkRect bounds;
- bounds.set(patch.getControlPoints(), SkPatch::kNumCtrlPts);
+ bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
if (this->quickReject(bounds)) {
return;
}
+ this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
+}
+
+void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
while (iter.next()) {
- iter.fDevice->drawPatch(iter, patch, paint);
+ iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
}
LOOPER_END
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 6ceaffebb3..50755c94ed 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -79,15 +79,17 @@ void SkBaseDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
this->drawPath(draw, path, paint, preMatrix, pathIsMutable);
}
-void SkBaseDevice::drawPatch(const SkDraw& draw, const SkPatch& patch, const SkPaint& paint) {
- SkPatch::VertexData data;
+void SkBaseDevice::drawPatch(const SkDraw& draw, const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+ SkPatchUtils::VertexData data;
- SkISize lod = SkPatchUtils::GetLevelOfDetail(patch, draw.fMatrix);
+ SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, draw.fMatrix);
// It automatically adjusts lodX and lodY in case it exceeds the number of indices.
- patch.getVertexData(&data, lod.width(), lod.height());
+ SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height());
this->drawVertices(draw, SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints,
- data.fTexCoords, data.fColors, NULL, data.fIndices, data.fIndexCount, paint);
+ data.fTexCoords, data.fColors, xmode, data.fIndices, data.fIndexCount,
+ paint);
}
bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) {
diff --git a/src/core/SkPatch.cpp b/src/core/SkPatch.cpp
deleted file mode 100644
index 4cca2bad1d..0000000000
--- a/src/core/SkPatch.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkPatch.h"
-
-#include "SkGeometry.h"
-#include "SkColorPriv.h"
-#include "SkBuffer.h"
-
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Evaluator to sample the values of a cubic bezier using forward differences.
- * Forward differences is a method for evaluating a nth degree polynomial at a uniform step by only
- * adding precalculated values.
- * For a linear example we have the function f(t) = m*t+b, then the value of that function at t+h
- * would be f(t+h) = m*(t+h)+b. If we want to know the uniform step that we must add to the first
- * evaluation f(t) then we need to substract f(t+h) - f(t) = m*t + m*h + b - m*t + b = mh. After
- * obtaining this value (mh) we could just add this constant step to our first sampled point
- * to compute the next one.
- *
- * For the cubic case the first difference gives as a result a quadratic polynomial to which we can
- * apply again forward differences and get linear function to which we can apply again forward
- * differences to get a constant difference. This is why we keep an array of size 4, the 0th
- * position keeps the sampled value while the next ones keep the quadratic, linear and constant
- * difference values.
- */
-
-class FwDCubicEvaluator {
-
-public:
- FwDCubicEvaluator() { }
-
- /**
- * Receives the 4 control points of the cubic bezier.
- */
- FwDCubicEvaluator(SkPoint a, SkPoint b, SkPoint c, SkPoint d) {
- fPoints[0] = a;
- fPoints[1] = b;
- fPoints[2] = c;
- fPoints[3] = d;
-
- SkScalar cx[4], cy[4];
- SkGetCubicCoeff(fPoints, cx, cy);
- fCoefs[0].set(cx[0], cy[0]);
- fCoefs[1].set(cx[1], cy[1]);
- fCoefs[2].set(cx[2], cy[2]);
- fCoefs[3].set(cx[3], cy[3]);
-
- this->restart(1);
- }
-
- explicit FwDCubicEvaluator(SkPoint points[4]) {
- for (int i = 0; i< 4; i++) {
- fPoints[i] = points[i];
- }
-
- SkScalar cx[4], cy[4];
- SkGetCubicCoeff(fPoints, cx, cy);
- fCoefs[0].set(cx[0], cy[0]);
- fCoefs[1].set(cx[1], cy[1]);
- fCoefs[2].set(cx[2], cy[2]);
- fCoefs[3].set(cx[3], cy[3]);
-
- this->restart(1);
- }
-
- /**
- * Restarts the forward differences evaluator to the first value of t = 0.
- */
- void restart(int divisions) {
- fDivisions = divisions;
- SkScalar h = 1.f / fDivisions;
- fCurrent = 0;
- fMax = fDivisions + 1;
- fFwDiff[0] = fCoefs[3];
- SkScalar h2 = h * h;
- SkScalar h3 = h2 * h;
-
- fFwDiff[3].set(6.f * fCoefs[0].x() * h3, 6.f * fCoefs[0].y() * h3); //6ah^3
- fFwDiff[2].set(fFwDiff[3].x() + 2.f * fCoefs[1].x() * h2, //6ah^3 + 2bh^2
- fFwDiff[3].y() + 2.f * fCoefs[1].y() * h2);
- fFwDiff[1].set(fCoefs[0].x() * h3 + fCoefs[1].x() * h2 + fCoefs[2].x() * h,//ah^3 + bh^2 +ch
- fCoefs[0].y() * h3 + fCoefs[1].y() * h2 + fCoefs[2].y() * h);
- }
-
- /**
- * Check if the evaluator is still within the range of 0<=t<=1
- */
- bool done() const {
- return fCurrent > fMax;
- }
-
- /**
- * Call next to obtain the SkPoint sampled and move to the next one.
- */
- SkPoint next() {
- SkPoint point = fFwDiff[0];
- fFwDiff[0] += fFwDiff[1];
- fFwDiff[1] += fFwDiff[2];
- fFwDiff[2] += fFwDiff[3];
- fCurrent++;
- return point;
- }
-
- const SkPoint* getCtrlPoints() const {
- return fPoints;
- }
-
-private:
- int fMax, fCurrent, fDivisions;
- SkPoint fFwDiff[4], fCoefs[4], fPoints[4];
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-SkPatch::SkPatch(const SkPoint points[12], const SkColor colors[4]) {
- this->reset(points, colors);
-}
-
-static uint8_t bilerp(SkScalar tx, SkScalar ty, SkScalar c00, SkScalar c10, SkScalar c01,
- SkScalar c11) {
- SkScalar a = c00 * (1.f - tx) + c10 * tx;
- SkScalar b = c01 * (1.f - tx) + c11 * tx;
- return uint8_t(a * (1.f - ty) + b * ty);
-}
-
-bool SkPatch::getVertexData(SkPatch::VertexData* data, int lodX, int lodY) const {
-
- if (lodX < 1 || lodY < 1) {
- return false;
- }
-
- // premultiply colors to avoid color bleeding.
- SkPMColor colors[SkPatch::kNumColors];
- for (int i = 0; i < SkPatch::kNumColors; i++) {
- colors[i] = SkPreMultiplyColor(fCornerColors[i]);
- }
-
- // number of indices is limited by size of uint16_t, so we clamp it to avoid overflow
- data->fVertexCount = SkMin32((lodX + 1) * (lodY + 1), 65536);
- lodX = SkMin32(lodX, 255);
- lodY = SkMin32(lodY, 255);
- data->fIndexCount = lodX * lodY * 6;
-
- data->fPoints = SkNEW_ARRAY(SkPoint, data->fVertexCount);
- data->fColors = SkNEW_ARRAY(uint32_t, data->fVertexCount);
- data->fTexCoords = SkNEW_ARRAY(SkPoint, data->fVertexCount);
- data->fIndices = SkNEW_ARRAY(uint16_t, data->fIndexCount);
-
- SkPoint pts[SkPatch::kNumPtsCubic];
- this->getBottomPoints(pts);
- FwDCubicEvaluator fBottom(pts);
- this->getTopPoints(pts);
- FwDCubicEvaluator fTop(pts);
- this->getLeftPoints(pts);
- FwDCubicEvaluator fLeft(pts);
- this->getRightPoints(pts);
- FwDCubicEvaluator fRight(pts);
-
- fBottom.restart(lodX);
- fTop.restart(lodX);
-
- SkScalar u = 0.0f;
- int stride = lodY + 1;
- for (int x = 0; x <= lodX; x++) {
- SkPoint bottom = fBottom.next(), top = fTop.next();
- fLeft.restart(lodY);
- fRight.restart(lodY);
- SkScalar v = 0.f;
- for (int y = 0; y <= lodY; y++) {
- int dataIndex = x * (lodY + 1) + y;
-
- SkPoint left = fLeft.next(), right = fRight.next();
-
- SkPoint s0 = SkPoint::Make((1.0f - v) * top.x() + v * bottom.x(),
- (1.0f - v) * top.y() + v * bottom.y());
- SkPoint s1 = SkPoint::Make((1.0f - u) * left.x() + u * right.x(),
- (1.0f - u) * left.y() + u * right.y());
- SkPoint s2 = SkPoint::Make(
- (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].x()
- + u * fTop.getCtrlPoints()[3].x())
- + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].x()
- + u * fBottom.getCtrlPoints()[3].x()),
- (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].y()
- + u * fTop.getCtrlPoints()[3].y())
- + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].y()
- + u * fBottom.getCtrlPoints()[3].y()));
- data->fPoints[dataIndex] = s0 + s1 - s2;
-
- uint8_t a = bilerp(u, v,
- SkScalar(SkColorGetA(colors[kTopLeft_CornerColors])),
- SkScalar(SkColorGetA(colors[kTopRight_CornerColors])),
- SkScalar(SkColorGetA(colors[kBottomLeft_CornerColors])),
- SkScalar(SkColorGetA(colors[kBottomRight_CornerColors])));
- uint8_t r = bilerp(u, v,
- SkScalar(SkColorGetR(colors[kTopLeft_CornerColors])),
- SkScalar(SkColorGetR(colors[kTopRight_CornerColors])),
- SkScalar(SkColorGetR(colors[kBottomLeft_CornerColors])),
- SkScalar(SkColorGetR(colors[kBottomRight_CornerColors])));
- uint8_t g = bilerp(u, v,
- SkScalar(SkColorGetG(colors[kTopLeft_CornerColors])),
- SkScalar(SkColorGetG(colors[kTopRight_CornerColors])),
- SkScalar(SkColorGetG(colors[kBottomLeft_CornerColors])),
- SkScalar(SkColorGetG(colors[kBottomRight_CornerColors])));
- uint8_t b = bilerp(u, v,
- SkScalar(SkColorGetB(colors[kTopLeft_CornerColors])),
- SkScalar(SkColorGetB(colors[kTopRight_CornerColors])),
- SkScalar(SkColorGetB(colors[kBottomLeft_CornerColors])),
- SkScalar(SkColorGetB(colors[kBottomRight_CornerColors])));
- data->fColors[dataIndex] = SkPackARGB32(a,r,g,b);
-
- data->fTexCoords[dataIndex] = SkPoint::Make(u, v);
-
- if(x < lodX && y < lodY) {
- int i = 6 * (x * lodY + y);
- data->fIndices[i] = x * stride + y;
- data->fIndices[i + 1] = x * stride + 1 + y;
- data->fIndices[i + 2] = (x + 1) * stride + 1 + y;
- data->fIndices[i + 3] = data->fIndices[i];
- data->fIndices[i + 4] = data->fIndices[i + 2];
- data->fIndices[i + 5] = (x + 1) * stride + y;
- }
- v = SkScalarClampMax(v + 1.f / lodY, 1);
- }
- u = SkScalarClampMax(u + 1.f / lodX, 1);
- }
- return true;
-}
-
-size_t SkPatch::writeToMemory(void* storage) const {
- int byteCount = kNumCtrlPts * sizeof(SkPoint) + kNumColors * sizeof(SkColor);
-
- if (NULL == storage) {
- return SkAlign4(byteCount);
- }
-
- SkWBuffer buffer(storage);
-
- buffer.write(fCtrlPoints, kNumCtrlPts * sizeof(SkPoint));
- buffer.write(fCornerColors, kNumColors * sizeof(SkColor));
-
- buffer.padToAlign4();
- return buffer.pos();
-}
-
-size_t SkPatch::readFromMemory(const void* storage, size_t length) {
- SkRBufferWithSizeCheck buffer(storage, length);
-
- if (!buffer.read(fCtrlPoints, kNumCtrlPts * sizeof(SkPoint))) {
- return 0;
- }
-
- if (!buffer.read(fCornerColors, kNumColors * sizeof(SkColor))) {
- return 0;
- }
- return kNumCtrlPts * sizeof(SkPoint) + kNumColors * sizeof(SkColor);
-}
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index fd359fed89..7f3f9d75d0 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -6,6 +6,7 @@
*/
#include "SkCanvas.h"
+#include "SkPatchUtils.h"
#include "SkPictureData.h"
#include "SkPicturePlayback.h"
#include "SkPictureRecord.h"
@@ -308,9 +309,28 @@ void SkPicturePlayback::handleOp(SkReader32* reader,
break;
case DRAW_PATCH: {
const SkPaint& paint = *fPictureData->getPaint(reader);
- SkPatch patch;
- reader->readPatch(&patch);
- canvas->drawPatch(patch, paint);
+
+ const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
+ sizeof(SkPoint));
+ uint32_t flag = reader->readInt();
+ const SkColor* colors = NULL;
+ if (flag & DRAW_VERTICES_HAS_COLORS) {
+ colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
+ }
+ const SkPoint* texCoords = NULL;
+ if (flag & DRAW_VERTICES_HAS_TEXS) {
+ texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
+ sizeof(SkPoint));
+ }
+ SkAutoTUnref<SkXfermode> xfer;
+ if (flag & DRAW_VERTICES_HAS_XFER) {
+ int mode = reader->readInt();
+ if (mode < 0 || mode > SkXfermode::kLastMode) {
+ mode = SkXfermode::kModulate_Mode;
+ }
+ xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
+ }
+ canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
} break;
case DRAW_PATH: {
const SkPaint& paint = *fPictureData->getPaint(reader);
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index fc0b291912..7fc48e3c78 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -6,12 +6,13 @@
*/
#include "SkPictureRecord.h"
-#include "SkTSearch.h"
-#include "SkPixelRef.h"
-#include "SkRRect.h"
#include "SkBBoxHierarchy.h"
#include "SkDevice.h"
+#include "SkPatchUtils.h"
#include "SkPictureStateTree.h"
+#include "SkPixelRef.h"
+#include "SkRRect.h"
+#include "SkTSearch.h"
#define HEAP_BLOCK_SIZE 4096
@@ -1283,14 +1284,46 @@ void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
this->validate(initialOffset, size);
}
-void SkPictureRecord::drawPatch(const SkPatch& patch, const SkPaint& paint) {
- // op + paint index + patch 12 control points + patch 4 colors
- size_t size = 2 * kUInt32Size + SkPatch::kNumCtrlPts * sizeof(SkPoint) +
- SkPatch::kNumColors * sizeof(SkColor);
+void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) {
+ // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
+ size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
+ uint32_t flag = 0;
+ if (NULL != colors) {
+ flag |= DRAW_VERTICES_HAS_COLORS;
+ size += SkPatchUtils::kNumCorners * sizeof(SkColor);
+ }
+ if (NULL != texCoords) {
+ flag |= DRAW_VERTICES_HAS_TEXS;
+ size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
+ }
+ if (NULL != xmode) {
+ SkXfermode::Mode mode;
+ if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
+ flag |= DRAW_VERTICES_HAS_XFER;
+ size += kUInt32Size;
+ }
+ }
+
size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_PATCH, size) == fWriter.bytesWritten());
this->addPaint(paint);
- this->addPatch(patch);
+ this->addPatch(cubics);
+ this->addInt(flag);
+
+ // write optional parameters
+ if (NULL != colors) {
+ fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
+ }
+ if (NULL != texCoords) {
+ fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
+ }
+ if (flag & DRAW_VERTICES_HAS_XFER) {
+ SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
+ xmode->asMode(&mode);
+ this->addInt(mode);
+ }
this->validate(initialOffset, size);
}
@@ -1420,8 +1453,8 @@ void SkPictureRecord::addPath(const SkPath& path) {
this->addInt(this->addPathToHeap(path));
}
-void SkPictureRecord::addPatch(const SkPatch& patch) {
- fWriter.writePatch(patch);
+void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
+ fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
}
void SkPictureRecord::addPicture(const SkPicture* picture) {
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index d0c099e040..8fd40bc230 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -58,7 +58,6 @@ public:
const SkColor colors[], SkXfermode*,
const uint16_t indices[], int indexCount,
const SkPaint&) SK_OVERRIDE;
- virtual void drawPatch(const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE;
virtual void drawData(const void*, size_t) SK_OVERRIDE;
virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
@@ -170,7 +169,7 @@ private:
const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); }
const SkFlatData* addPaintPtr(const SkPaint* paint);
void addFlatPaint(const SkFlatData* flatPaint);
- void addPatch(const SkPatch& patch);
+ void addPatch(const SkPoint cubics[12]);
void addPath(const SkPath& path);
void addPicture(const SkPicture* picture);
void addPoint(const SkPoint& point);
@@ -214,6 +213,10 @@ protected:
SkScalar constY, const SkPaint&) SK_OVERRIDE;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
+
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
diff --git a/src/core/SkReadBuffer.cpp b/src/core/SkReadBuffer.cpp
index 27f2d2b3ac..43587862b9 100644
--- a/src/core/SkReadBuffer.cpp
+++ b/src/core/SkReadBuffer.cpp
@@ -148,10 +148,6 @@ void SkReadBuffer::readRegion(SkRegion* region) {
fReader.readRegion(region);
}
-void SkReadBuffer::readPatch(SkPatch* patch) {
- fReader.readPatch(patch);
-}
-
void SkReadBuffer::readPath(SkPath* path) {
fReader.readPath(path);
}
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 0e2a4701fe..8be9e005f6 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -84,7 +84,7 @@ DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint));
DRAW(DrawOval, drawOval(r.oval, r.paint));
DRAW(DrawPaint, drawPaint(r.paint));
DRAW(DrawPath, drawPath(r.path, r.paint));
-DRAW(DrawPatch, drawPatch(r.patch, r.paint));
+DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode.get(), r.paint));
DRAW(DrawPicture, drawPicture(r.picture, r.matrix, r.paint));
DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint));
DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 6b3eac9866..327a97acdb 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -6,6 +6,7 @@
*/
#include "SkRecorder.h"
+#include "SkPatchUtils.h"
#include "SkPicture.h"
// SkCanvas will fail in mysterious ways if it doesn't know the real width and height.
@@ -206,8 +207,13 @@ void SkRecorder::drawVertices(VertexMode vmode,
indexCount);
}
-void SkRecorder::drawPatch(const SkPatch& patch, const SkPaint& paint) {
- APPEND(DrawPatch, delay_copy(paint), delay_copy(patch));
+void SkRecorder::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+ APPEND(DrawPatch, delay_copy(paint),
+ cubics ? this->copy(cubics, SkPatchUtils::kNumCtrlPts) : NULL,
+ colors ? this->copy(colors, SkPatchUtils::kNumCorners) : NULL,
+ texCoords ? this->copy(texCoords, SkPatchUtils::kNumCorners) : NULL,
+ xmode);
}
void SkRecorder::willSave() {
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index be8924846e..2c7234ac86 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -61,7 +61,6 @@ public:
const uint16_t indices[],
int indexCount,
const SkPaint& paint) SK_OVERRIDE;
- void drawPatch(const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE;
void willSave() SK_OVERRIDE;
SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SkCanvas::SaveFlags) SK_OVERRIDE;
@@ -90,6 +89,10 @@ public:
const SkPath& path,
const SkMatrix* matrix,
const SkPaint& paint) SK_OVERRIDE;
+ void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
+
void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) SK_OVERRIDE;
void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) SK_OVERRIDE;
void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) SK_OVERRIDE;
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index 6aefd195c9..1efdf28b14 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -232,7 +232,7 @@ RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
RECORD1(DrawPaint, SkPaint, paint);
RECORD2(DrawPath, SkPaint, paint, SkPath, path);
-RECORD2(DrawPatch, SkPaint, paint, SkPatch, patch);
+//RECORD2(DrawPatch, SkPaint, paint, SkPatch, patch);
RECORD3(DrawPicture, Optional<SkPaint>, paint, SkPictureBox, picture, Optional<SkMatrix>, matrix);
RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
RECORD4(DrawPosText, SkPaint, paint,
@@ -291,6 +291,24 @@ struct DrawVertices {
PODArray<uint16_t> indices;
int indexCount;
};
+
+struct DrawPatch {
+ static const Type kType = DrawPatch_Type;
+
+ DrawPatch(const SkPaint& paint, SkPoint cubics[12], SkColor colors[4],
+ SkPoint texCoords[4], SkXfermode* xmode)
+ : paint(paint)
+ , cubics(cubics)
+ , colors(colors)
+ , texCoords(texCoords)
+ , xmode(SkSafeRef(xmode)) { }
+
+ SkPaint paint;
+ PODArray<SkPoint> cubics;
+ PODArray<SkColor> colors;
+ PODArray<SkPoint> texCoords;
+ SkAutoTUnref<SkXfermode> xmode;
+};
#undef RECORD0
#undef RECORD1
diff --git a/src/core/SkValidatingReadBuffer.cpp b/src/core/SkValidatingReadBuffer.cpp
index 8202149cc1..037a99465b 100644
--- a/src/core/SkValidatingReadBuffer.cpp
+++ b/src/core/SkValidatingReadBuffer.cpp
@@ -171,17 +171,6 @@ void SkValidatingReadBuffer::readPath(SkPath* path) {
}
}
-void SkValidatingReadBuffer::readPatch(SkPatch* patch) {
- size_t size = 0;
- if (!fError) {
- size = patch->readFromMemory(fReader.peek(), fReader.available());
- this->validate((SkAlign4(size) == size) && (0 != size));
- }
- if (!fError) {
- (void)this->skip(size);
- }
-}
-
bool SkValidatingReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
const uint32_t count = this->getArrayCount();
this->validate(size == count);
diff --git a/src/core/SkValidatingReadBuffer.h b/src/core/SkValidatingReadBuffer.h
index 8850a07646..5cf3abed68 100644
--- a/src/core/SkValidatingReadBuffer.h
+++ b/src/core/SkValidatingReadBuffer.h
@@ -46,7 +46,6 @@ public:
virtual void readIRect(SkIRect* rect) SK_OVERRIDE;
virtual void readRect(SkRect* rect) SK_OVERRIDE;
virtual void readRegion(SkRegion* region) SK_OVERRIDE;
- virtual void readPatch(SkPatch* patch) SK_OVERRIDE;
virtual void readPath(SkPath* path) SK_OVERRIDE;
// binary data and arrays
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index 35b0a94570..35de638e05 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -21,6 +21,7 @@
#include "SkImageFilter.h"
#include "SkMaskFilter.h"
#include "SkReadBuffer.h"
+#include "SkPatchUtils.h"
#include "SkPathEffect.h"
#include "SkRasterizer.h"
#include "SkRRect.h"
@@ -406,10 +407,29 @@ static void drawDRRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
static void drawPatch_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
- SkPatch patch;
- reader->readPatch(&patch);
+
+ unsigned flags = DrawOp_unpackFlags(op32);
+
+ const SkPoint* cubics = skip<SkPoint>(reader, SkPatchUtils::kNumCtrlPts);
+
+ const SkColor* colors = NULL;
+ if (flags & kDrawVertices_HasColors_DrawOpFlag) {
+ colors = skip<SkColor>(reader, SkPatchUtils::kNumCorners);
+ }
+ const SkPoint* texCoords = NULL;
+ if (flags & kDrawVertices_HasTexs_DrawOpFlag) {
+ texCoords = skip<SkPoint>(reader, SkPatchUtils::kNumCorners);
+ }
+ SkAutoTUnref<SkXfermode> xfer;
+ if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
+ int mode = reader->readInt();
+ if (mode < 0 || mode > SkXfermode::kLastMode) {
+ mode = SkXfermode::kModulate_Mode;
+ }
+ xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
+ }
if (state->shouldDraw()) {
- canvas->drawPatch(patch, state->paint());
+ canvas->drawPatch(cubics, colors, texCoords, xfer, state->paint());
}
}
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index d796e8a99b..94a30a34e2 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -19,6 +19,7 @@
#include "SkMaskFilter.h"
#include "SkWriteBuffer.h"
#include "SkPaint.h"
+#include "SkPatchUtils.h"
#include "SkPathEffect.h"
#include "SkPictureFlat.h"
#include "SkRasterizer.h"
@@ -254,7 +255,6 @@ public:
const SkColor colors[], SkXfermode*,
const uint16_t indices[], int indexCount,
const SkPaint&) SK_OVERRIDE;
- virtual void drawPatch(const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE;
virtual void drawData(const void*, size_t) SK_OVERRIDE;
virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
@@ -283,7 +283,9 @@ protected:
SkScalar constY, const SkPaint&) SK_OVERRIDE;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
-
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
@@ -1003,12 +1005,48 @@ void SkGPipeCanvas::drawVertices(VertexMode vmode, int vertexCount,
}
}
-void SkGPipeCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+void SkGPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) {
NOTIFY_SETUP(this);
+
+ size_t size = SkPatchUtils::kNumCtrlPts * sizeof(SkPoint);
+ unsigned flags = 0;
+ if (NULL != colors) {
+ flags |= kDrawVertices_HasColors_DrawOpFlag;
+ size += SkPatchUtils::kNumCorners * sizeof(SkColor);
+ }
+ if (NULL != texCoords) {
+ flags |= kDrawVertices_HasTexs_DrawOpFlag;
+ size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
+ }
+ if (NULL != xmode) {
+ SkXfermode::Mode mode;
+ if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
+ flags |= kDrawVertices_HasXfermode_DrawOpFlag;
+ size += sizeof(int32_t);
+ }
+ }
+
this->writePaint(paint);
- if (this->needOpBytes(patch.writeToMemory(NULL))) {
- this->writeOp(kDrawPatch_DrawOp);
- fWriter.writePatch(patch);
+ if (this->needOpBytes(size)) {
+ this->writeOp(kDrawPatch_DrawOp, flags, 0);
+
+ fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
+
+ if (NULL != colors) {
+ fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
+ }
+
+ if (NULL != texCoords) {
+ fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
+ }
+
+ if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
+ SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
+ SkAssertResult(xmode->asMode(&mode));
+ fWriter.write32(mode);
+ }
}
}
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index 128f8a564d..de3958adbc 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -224,7 +224,9 @@ protected:
SkXfermode* xmode, const uint16_t indices[],
int indexCount, const SkPaint& paint) SK_OVERRIDE
{SkASSERT(0);}
- virtual void drawPatch(const SkDraw&, const SkPatch& patch, const SkPaint& paint) SK_OVERRIDE
+ virtual void drawPatch(const SkDraw&, const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE
{SkASSERT(0);}
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
const SkPaint&) SK_OVERRIDE
@@ -917,9 +919,11 @@ void SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount,
this->recordedDrawCommand();
}
-void SkDeferredCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+void SkDeferredCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) {
AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
- this->drawingCanvas()->drawPatch(patch, paint);
+ this->drawingCanvas()->drawPatch(cubics, colors, texCoords, xmode, paint);
this->recordedDrawCommand();
}
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index 946aaa33be..661f0d8860 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -9,6 +9,7 @@
#include "SkDumpCanvas.h"
#ifdef SK_DEVELOPER
+#include "SkPatchUtils.h"
#include "SkPicture.h"
#include "SkPixelRef.h"
#include "SkRRect.h"
@@ -443,17 +444,24 @@ void SkDumpCanvas::drawVertices(VertexMode vmode, int vertexCount,
SkScalarToFloat(vertices[0].fY));
}
-void SkDumpCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
- const SkPoint* points = patch.getControlPoints();
- const SkColor* color = patch.getColors();
+void SkDumpCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) {
//dumps corner points and colors in clockwise order starting on upper-left corner
this->dump(kDrawPatch_Verb, &paint, "drawPatch(Vertices{[%f, %f], [%f, %f], [%f, %f], [%f, %f]}\
- | Colors{[0x%x], [0x%x], [0x%x], [0x%x]})",
- points[SkPatch::kTopP0_CubicCtrlPts].fX, points[SkPatch::kTopP0_CubicCtrlPts].fY,
- points[SkPatch::kTopP3_CubicCtrlPts].fX, points[SkPatch::kTopP3_CubicCtrlPts].fY,
- points[SkPatch::kBottomP3_CubicCtrlPts].fX,points[SkPatch::kBottomP3_CubicCtrlPts].fY,
- points[SkPatch::kBottomP0_CubicCtrlPts].fX,points[SkPatch::kBottomP0_CubicCtrlPts].fY,
- color[0], color[1], color[2], color[3]);
+ | Colors{[0x%x], [0x%x], [0x%x], [0x%x]} | TexCoords{[%f,%f], [%f,%f], [%f,%f], \
+ [%f,%f]})",
+ cubics[SkPatchUtils::kTopP0_CubicCtrlPts].fX,
+ cubics[SkPatchUtils::kTopP0_CubicCtrlPts].fY,
+ cubics[SkPatchUtils::kTopP3_CubicCtrlPts].fX,
+ cubics[SkPatchUtils::kTopP3_CubicCtrlPts].fY,
+ cubics[SkPatchUtils::kBottomP3_CubicCtrlPts].fX,
+ cubics[SkPatchUtils::kBottomP3_CubicCtrlPts].fY,
+ cubics[SkPatchUtils::kBottomP0_CubicCtrlPts].fX,
+ cubics[SkPatchUtils::kBottomP0_CubicCtrlPts].fY,
+ colors[0], colors[1], colors[2], colors[3],
+ texCoords[0].x(), texCoords[0].y(), texCoords[1].x(), texCoords[1].y(),
+ texCoords[2].x(), texCoords[2].y(), texCoords[3].x(), texCoords[3].y());
}
void SkDumpCanvas::drawData(const void* data, size_t length) {
diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp
index d02835af65..d436bd4a6b 100644
--- a/src/utils/SkNWayCanvas.cpp
+++ b/src/utils/SkNWayCanvas.cpp
@@ -285,10 +285,12 @@ void SkNWayCanvas::drawVertices(VertexMode vmode, int vertexCount,
}
}
-void SkNWayCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+void SkNWayCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) {
Iter iter(fList);
while (iter.next()) {
- iter->drawPatch(patch, paint);
+ iter->drawPatch(cubics, colors, texCoords, xmode, paint);
}
}
diff --git a/src/utils/SkPatchUtils.cpp b/src/utils/SkPatchUtils.cpp
index ab15290a34..d12019551d 100644
--- a/src/utils/SkPatchUtils.cpp
+++ b/src/utils/SkPatchUtils.cpp
@@ -7,8 +7,121 @@
#include "SkPatchUtils.h"
+#include "SkColorPriv.h"
+#include "SkGeometry.h"
+
+/**
+ * Evaluator to sample the values of a cubic bezier using forward differences.
+ * Forward differences is a method for evaluating a nth degree polynomial at a uniform step by only
+ * adding precalculated values.
+ * For a linear example we have the function f(t) = m*t+b, then the value of that function at t+h
+ * would be f(t+h) = m*(t+h)+b. If we want to know the uniform step that we must add to the first
+ * evaluation f(t) then we need to substract f(t+h) - f(t) = m*t + m*h + b - m*t + b = mh. After
+ * obtaining this value (mh) we could just add this constant step to our first sampled point
+ * to compute the next one.
+ *
+ * For the cubic case the first difference gives as a result a quadratic polynomial to which we can
+ * apply again forward differences and get linear function to which we can apply again forward
+ * differences to get a constant difference. This is why we keep an array of size 4, the 0th
+ * position keeps the sampled value while the next ones keep the quadratic, linear and constant
+ * difference values.
+ */
+
+class FwDCubicEvaluator {
+
+public:
+ FwDCubicEvaluator()
+ : fMax(0)
+ , fCurrent(0)
+ , fDivisions(0) {
+ memset(fPoints, 0, 4 * sizeof(SkPoint));
+ memset(fPoints, 0, 4 * sizeof(SkPoint));
+ memset(fPoints, 0, 4 * sizeof(SkPoint));
+ }
+
+ /**
+ * Receives the 4 control points of the cubic bezier.
+ */
+ FwDCubicEvaluator(SkPoint a, SkPoint b, SkPoint c, SkPoint d) {
+ fPoints[0] = a;
+ fPoints[1] = b;
+ fPoints[2] = c;
+ fPoints[3] = d;
+
+ SkScalar cx[4], cy[4];
+ SkGetCubicCoeff(fPoints, cx, cy);
+ fCoefs[0].set(cx[0], cy[0]);
+ fCoefs[1].set(cx[1], cy[1]);
+ fCoefs[2].set(cx[2], cy[2]);
+ fCoefs[3].set(cx[3], cy[3]);
+
+ this->restart(1);
+ }
+
+ explicit FwDCubicEvaluator(const SkPoint points[4]) {
+ memcpy(fPoints, points, 4 * sizeof(SkPoint));
+
+ SkScalar cx[4], cy[4];
+ SkGetCubicCoeff(fPoints, cx, cy);
+ fCoefs[0].set(cx[0], cy[0]);
+ fCoefs[1].set(cx[1], cy[1]);
+ fCoefs[2].set(cx[2], cy[2]);
+ fCoefs[3].set(cx[3], cy[3]);
+
+ this->restart(1);
+ }
+
+ /**
+ * Restarts the forward differences evaluator to the first value of t = 0.
+ */
+ void restart(int divisions) {
+ fDivisions = divisions;
+ SkScalar h = 1.f / fDivisions;
+ fCurrent = 0;
+ fMax = fDivisions + 1;
+ fFwDiff[0] = fCoefs[3];
+ SkScalar h2 = h * h;
+ SkScalar h3 = h2 * h;
+
+ fFwDiff[3].set(6.f * fCoefs[0].x() * h3, 6.f * fCoefs[0].y() * h3); //6ah^3
+ fFwDiff[2].set(fFwDiff[3].x() + 2.f * fCoefs[1].x() * h2, //6ah^3 + 2bh^2
+ fFwDiff[3].y() + 2.f * fCoefs[1].y() * h2);
+ fFwDiff[1].set(fCoefs[0].x() * h3 + fCoefs[1].x() * h2 + fCoefs[2].x() * h,//ah^3 + bh^2 +ch
+ fCoefs[0].y() * h3 + fCoefs[1].y() * h2 + fCoefs[2].y() * h);
+ }
+
+ /**
+ * Check if the evaluator is still within the range of 0<=t<=1
+ */
+ bool done() const {
+ return fCurrent > fMax;
+ }
+
+ /**
+ * Call next to obtain the SkPoint sampled and move to the next one.
+ */
+ SkPoint next() {
+ SkPoint point = fFwDiff[0];
+ fFwDiff[0] += fFwDiff[1];
+ fFwDiff[1] += fFwDiff[2];
+ fFwDiff[2] += fFwDiff[3];
+ fCurrent++;
+ return point;
+ }
+
+ const SkPoint* getCtrlPoints() const {
+ return fPoints;
+ }
+
+private:
+ int fMax, fCurrent, fDivisions;
+ SkPoint fFwDiff[4], fCoefs[4], fPoints[4];
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
// size in pixels of each partition per axis, adjust this knob
-static const int kPartitionSize = 15;
+static const int kPartitionSize = 10;
/**
* Calculate the approximate arc length given a bezier curve's control points.
@@ -24,32 +137,188 @@ static SkScalar approx_arc_length(SkPoint* points, int count) {
return arcLength;
}
-SkISize SkPatchUtils::GetLevelOfDetail(const SkPatch& patch, const SkMatrix* matrix) {
-
- SkPoint mapPts[12];
- matrix->mapPoints(mapPts, patch.getControlPoints(), 12);
+static SkScalar bilerp(SkScalar tx, SkScalar ty, SkScalar c00, SkScalar c10, SkScalar c01,
+ SkScalar c11) {
+ SkScalar a = c00 * (1.f - tx) + c10 * tx;
+ SkScalar b = c01 * (1.f - tx) + c11 * tx;
+ return a * (1.f - ty) + b * ty;
+}
+
+SkISize SkPatchUtils::GetLevelOfDetail(const SkPoint cubics[12], const SkMatrix* matrix) {
// Approximate length of each cubic.
- SkPoint pts[4];
- patch.getTopPoints(pts);
- matrix->mapPoints(pts, 4);
- SkScalar topLength = approx_arc_length(pts, 4);
+ SkPoint pts[kNumPtsCubic];
+ SkPatchUtils::getTopCubic(cubics, pts);
+ matrix->mapPoints(pts, kNumPtsCubic);
+ SkScalar topLength = approx_arc_length(pts, kNumPtsCubic);
- patch.getBottomPoints(pts);
- matrix->mapPoints(pts, 4);
- SkScalar bottomLength = approx_arc_length(pts, 4);
+ SkPatchUtils::getBottomCubic(cubics, pts);
+ matrix->mapPoints(pts, kNumPtsCubic);
+ SkScalar bottomLength = approx_arc_length(pts, kNumPtsCubic);
- patch.getLeftPoints(pts);
- matrix->mapPoints(pts, 4);
- SkScalar leftLength = approx_arc_length(pts, 4);
+ SkPatchUtils::getLeftCubic(cubics, pts);
+ matrix->mapPoints(pts, kNumPtsCubic);
+ SkScalar leftLength = approx_arc_length(pts, kNumPtsCubic);
- patch.getRightPoints(pts);
- matrix->mapPoints(pts, 4);
- SkScalar rightLength = approx_arc_length(pts, 4);
+ SkPatchUtils::getRightCubic(cubics, pts);
+ matrix->mapPoints(pts, kNumPtsCubic);
+ SkScalar rightLength = approx_arc_length(pts, kNumPtsCubic);
// Level of detail per axis, based on the larger side between top and bottom or left and right
int lodX = static_cast<int>(SkMaxScalar(topLength, bottomLength) / kPartitionSize);
int lodY = static_cast<int>(SkMaxScalar(leftLength, rightLength) / kPartitionSize);
- return SkISize::Make(SkMax32(4, lodX), SkMax32(4, lodY));
+ return SkISize::Make(SkMax32(8, lodX), SkMax32(8, lodY));
+}
+
+void SkPatchUtils::getTopCubic(const SkPoint cubics[12], SkPoint points[4]) {
+ points[0] = cubics[kTopP0_CubicCtrlPts];
+ points[1] = cubics[kTopP1_CubicCtrlPts];
+ points[2] = cubics[kTopP2_CubicCtrlPts];
+ points[3] = cubics[kTopP3_CubicCtrlPts];
+}
+
+void SkPatchUtils::getBottomCubic(const SkPoint cubics[12], SkPoint points[4]) {
+ points[0] = cubics[kBottomP0_CubicCtrlPts];
+ points[1] = cubics[kBottomP1_CubicCtrlPts];
+ points[2] = cubics[kBottomP2_CubicCtrlPts];
+ points[3] = cubics[kBottomP3_CubicCtrlPts];
+}
+
+void SkPatchUtils::getLeftCubic(const SkPoint cubics[12], SkPoint points[4]) {
+ points[0] = cubics[kLeftP0_CubicCtrlPts];
+ points[1] = cubics[kLeftP1_CubicCtrlPts];
+ points[2] = cubics[kLeftP2_CubicCtrlPts];
+ points[3] = cubics[kLeftP3_CubicCtrlPts];
+}
+
+void SkPatchUtils::getRightCubic(const SkPoint cubics[12], SkPoint points[4]) {
+ points[0] = cubics[kRightP0_CubicCtrlPts];
+ points[1] = cubics[kRightP1_CubicCtrlPts];
+ points[2] = cubics[kRightP2_CubicCtrlPts];
+ points[3] = cubics[kRightP3_CubicCtrlPts];
+}
+
+bool SkPatchUtils::getVertexData(SkPatchUtils::VertexData* data, const SkPoint cubics[12],
+ const SkColor colors[4], const SkPoint texCoords[4], int lodX, int lodY) {
+ if (lodX < 1 || lodY < 1 || NULL == cubics || NULL == data) {
+ return false;
+ }
+
+ // number of indices is limited by size of uint16_t, so we clamp it to avoid overflow
+ data->fVertexCount = SkMin32((lodX + 1) * (lodY + 1), 65536);
+ lodX = SkMin32(lodX, 255);
+ lodY = SkMin32(lodY, 255);
+ data->fIndexCount = lodX * lodY * 6;
+
+ data->fPoints = SkNEW_ARRAY(SkPoint, data->fVertexCount);
+ data->fIndices = SkNEW_ARRAY(uint16_t, data->fIndexCount);
+
+ // if colors is not null then create array for colors
+ SkPMColor colorsPM[kNumCorners];
+ if (NULL != colors) {
+ // premultiply colors to avoid color bleeding.
+ for (int i = 0; i < kNumCorners; i++) {
+ colorsPM[i] = SkPreMultiplyColor(colors[i]);
+ }
+ data->fColors = SkNEW_ARRAY(uint32_t, data->fVertexCount);
+ }
+
+ // if texture coordinates are not null then create array for them
+ if (NULL != texCoords) {
+ data->fTexCoords = SkNEW_ARRAY(SkPoint, data->fVertexCount);
+ }
+
+ SkPoint pts[kNumPtsCubic];
+ SkPatchUtils::getBottomCubic(cubics, pts);
+ FwDCubicEvaluator fBottom(pts);
+ SkPatchUtils::getTopCubic(cubics, pts);
+ FwDCubicEvaluator fTop(pts);
+ SkPatchUtils::getLeftCubic(cubics, pts);
+ FwDCubicEvaluator fLeft(pts);
+ SkPatchUtils::getRightCubic(cubics, pts);
+ FwDCubicEvaluator fRight(pts);
+
+ fBottom.restart(lodX);
+ fTop.restart(lodX);
+
+ SkScalar u = 0.0f;
+ int stride = lodY + 1;
+ for (int x = 0; x <= lodX; x++) {
+ SkPoint bottom = fBottom.next(), top = fTop.next();
+ fLeft.restart(lodY);
+ fRight.restart(lodY);
+ SkScalar v = 0.f;
+ for (int y = 0; y <= lodY; y++) {
+ int dataIndex = x * (lodY + 1) + y;
+
+ SkPoint left = fLeft.next(), right = fRight.next();
+
+ SkPoint s0 = SkPoint::Make((1.0f - v) * top.x() + v * bottom.x(),
+ (1.0f - v) * top.y() + v * bottom.y());
+ SkPoint s1 = SkPoint::Make((1.0f - u) * left.x() + u * right.x(),
+ (1.0f - u) * left.y() + u * right.y());
+ SkPoint s2 = SkPoint::Make(
+ (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].x()
+ + u * fTop.getCtrlPoints()[3].x())
+ + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].x()
+ + u * fBottom.getCtrlPoints()[3].x()),
+ (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].y()
+ + u * fTop.getCtrlPoints()[3].y())
+ + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].y()
+ + u * fBottom.getCtrlPoints()[3].y()));
+ data->fPoints[dataIndex] = s0 + s1 - s2;
+
+ if (NULL != colors) {
+ uint8_t a = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetA(colorsPM[kTopLeft_Corner])),
+ SkScalar(SkColorGetA(colorsPM[kTopRight_Corner])),
+ SkScalar(SkColorGetA(colorsPM[kBottomLeft_Corner])),
+ SkScalar(SkColorGetA(colorsPM[kBottomRight_Corner]))));
+ uint8_t r = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetR(colorsPM[kTopLeft_Corner])),
+ SkScalar(SkColorGetR(colorsPM[kTopRight_Corner])),
+ SkScalar(SkColorGetR(colorsPM[kBottomLeft_Corner])),
+ SkScalar(SkColorGetR(colorsPM[kBottomRight_Corner]))));
+ uint8_t g = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetG(colorsPM[kTopLeft_Corner])),
+ SkScalar(SkColorGetG(colorsPM[kTopRight_Corner])),
+ SkScalar(SkColorGetG(colorsPM[kBottomLeft_Corner])),
+ SkScalar(SkColorGetG(colorsPM[kBottomRight_Corner]))));
+ uint8_t b = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetB(colorsPM[kTopLeft_Corner])),
+ SkScalar(SkColorGetB(colorsPM[kTopRight_Corner])),
+ SkScalar(SkColorGetB(colorsPM[kBottomLeft_Corner])),
+ SkScalar(SkColorGetB(colorsPM[kBottomRight_Corner]))));
+ data->fColors[dataIndex] = SkPackARGB32(a,r,g,b);
+ }
+
+ if (NULL != texCoords) {
+ data->fTexCoords[dataIndex] = SkPoint::Make(
+ bilerp(u, v, texCoords[kTopLeft_Corner].x(),
+ texCoords[kTopRight_Corner].x(),
+ texCoords[kBottomLeft_Corner].x(),
+ texCoords[kBottomRight_Corner].x()),
+ bilerp(u, v, texCoords[kTopLeft_Corner].y(),
+ texCoords[kTopRight_Corner].y(),
+ texCoords[kBottomLeft_Corner].y(),
+ texCoords[kBottomRight_Corner].y()));
+
+ }
+
+ if(x < lodX && y < lodY) {
+ int i = 6 * (x * lodY + y);
+ data->fIndices[i] = x * stride + y;
+ data->fIndices[i + 1] = x * stride + 1 + y;
+ data->fIndices[i + 2] = (x + 1) * stride + 1 + y;
+ data->fIndices[i + 3] = data->fIndices[i];
+ data->fIndices[i + 4] = data->fIndices[i + 2];
+ data->fIndices[i + 5] = (x + 1) * stride + y;
+ }
+ v = SkScalarClampMax(v + 1.f / lodY, 1);
+ }
+ u = SkScalarClampMax(u + 1.f / lodX, 1);
+ }
+ return true;
+
}
diff --git a/src/utils/SkPatchUtils.h b/src/utils/SkPatchUtils.h
index f2e3b43ed1..879053ad0c 100644
--- a/src/utils/SkPatchUtils.h
+++ b/src/utils/SkPatchUtils.h
@@ -8,16 +8,114 @@
#ifndef SkPatchUtils_DEFINED
#define SkPatchUtils_DEFINED
-#include "SkPatch.h"
+#include "SkColorPriv.h"
#include "SkMatrix.h"
class SK_API SkPatchUtils {
-
+
public:
/**
+ * Structure that holds the vertex data related to the tessellation of a patch. It is passed
+ * as a parameter to the function getVertexData which sets the points, colors and texture
+ * coordinates of the vertices and the indices for them to be drawn as triangles.
+ */
+ struct VertexData {
+ int fVertexCount, fIndexCount;
+ SkPoint* fPoints;
+ SkPoint* fTexCoords;
+ uint32_t* fColors;
+ uint16_t* fIndices;
+
+ VertexData()
+ : fVertexCount(0)
+ , fIndexCount(0)
+ , fPoints(NULL)
+ , fTexCoords(NULL)
+ , fColors(NULL)
+ , fIndices(NULL) { }
+
+ ~VertexData() {
+ SkDELETE_ARRAY(fPoints);
+ SkDELETE_ARRAY(fTexCoords);
+ SkDELETE_ARRAY(fColors);
+ SkDELETE_ARRAY(fIndices);
+ }
+ };
+
+ // Enums for control points based on the order specified in the constructor (clockwise).
+ enum CubicCtrlPts {
+ kTopP0_CubicCtrlPts = 0,
+ kTopP1_CubicCtrlPts = 1,
+ kTopP2_CubicCtrlPts = 2,
+ kTopP3_CubicCtrlPts = 3,
+
+ kRightP0_CubicCtrlPts = 3,
+ kRightP1_CubicCtrlPts = 4,
+ kRightP2_CubicCtrlPts = 5,
+ kRightP3_CubicCtrlPts = 6,
+
+ kBottomP0_CubicCtrlPts = 9,
+ kBottomP1_CubicCtrlPts = 8,
+ kBottomP2_CubicCtrlPts = 7,
+ kBottomP3_CubicCtrlPts = 6,
+
+ kLeftP0_CubicCtrlPts = 0,
+ kLeftP1_CubicCtrlPts = 11,
+ kLeftP2_CubicCtrlPts = 10,
+ kLeftP3_CubicCtrlPts = 9,
+ };
+
+ // Enum for corner also clockwise.
+ enum Corner {
+ kTopLeft_Corner = 0,
+ kTopRight_Corner,
+ kBottomRight_Corner,
+ kBottomLeft_Corner
+ };
+
+ enum {
+ kNumCtrlPts = 12,
+ kNumCorners = 4,
+ kNumPtsCubic = 4
+ };
+
+ /**
* Method that calculates a level of detail (number of subdivisions) for a patch in both axis.
*/
- static SkISize GetLevelOfDetail(const SkPatch& patch, const SkMatrix* matrix);
+ static SkISize GetLevelOfDetail(const SkPoint cubics[12], const SkMatrix* matrix);
+
+ /**
+ * Get the points corresponding to the top cubic of cubics.
+ */
+ static void getTopCubic(const SkPoint cubics[12], SkPoint points[4]);
+
+ /**
+ * Get the points corresponding to the bottom cubic of cubics.
+ */
+ static void getBottomCubic(const SkPoint cubics[12], SkPoint points[4]);
+
+ /**
+ * Get the points corresponding to the left cubic of cubics.
+ */
+ static void getLeftCubic(const SkPoint cubics[12], SkPoint points[4]);
+
+ /**
+ * Get the points corresponding to the right cubic of cubics.
+ */
+ static void getRightCubic(const SkPoint cubics[12], SkPoint points[4]);
+
+ /**
+ * Function that evaluates the coons patch interpolation.
+ * data refers to the pointer of the PatchData struct in which the tessellation data is set.
+ * cubics refers to the points of the cubics.
+ * lod refers the level of detail for each axis.
+ * colors refers to the corner colors that will be bilerp across the patch (optional parameter)
+ * texCoords refers to the corner texture coordinates that will be bilerp across the patch
+ (optional parameter)
+ */
+ static bool getVertexData(SkPatchUtils::VertexData* data, const SkPoint cubics[12],
+ const SkColor colors[4], const SkPoint texCoords[4],
+ int lodX, int lodY);
};
#endif
diff --git a/src/utils/SkProxyCanvas.cpp b/src/utils/SkProxyCanvas.cpp
index 773fd201ab..c15acaa78f 100644
--- a/src/utils/SkProxyCanvas.cpp
+++ b/src/utils/SkProxyCanvas.cpp
@@ -150,8 +150,10 @@ void SkProxyCanvas::drawVertices(VertexMode vmode, int vertexCount,
xmode, indices, indexCount, paint);
}
-void SkProxyCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
- fProxy->drawPatch(patch, paint);
+void SkProxyCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) {
+ fProxy->drawPatch(cubics, colors, texCoords, xmode, paint);
}
void SkProxyCanvas::drawData(const void* data, size_t length) {