diff options
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) { |