Stopped skipping tests in dm of SkPatch by implementing the
corresponding drawPath calls on classes that derive from SkCanvas.
BUG=skia:
R=egdaniel@google.com, bsalomon@google.com, mtklein@google.com, robertphillips@google.com
Author: dandov@google.com
Review URL: https://codereview.chromium.org/429343004
diff --git a/src/core/SkBBoxRecord.cpp b/src/core/SkBBoxRecord.cpp
index 448e8f6..802eb66 100644
--- a/src/core/SkBBoxRecord.cpp
+++ b/src/core/SkBBoxRecord.cpp
@@ -284,6 +284,15 @@
}
}
+void SkBBoxRecord::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+ const SkPoint* points = patch.getControlPoints();
+ SkRect bbox;
+ bbox.set(points, SkPatch::kNumCtrlPts);
+ if (this->transformBounds(bbox, &paint)) {
+ INHERITED::drawPatch(patch, paint);
+ }
+}
+
void SkBBoxRecord::onDrawPicture(const SkPicture* picture) {
if (picture->width() > 0 && picture->height() > 0 &&
this->transformBounds(SkRect::MakeWH(picture->width(), picture->height()), NULL)) {
diff --git a/src/core/SkBBoxRecord.h b/src/core/SkBBoxRecord.h
index a6edc98..d10626f 100644
--- a/src/core/SkBBoxRecord.h
+++ b/src/core/SkBBoxRecord.h
@@ -55,6 +55,7 @@
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;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 3320d18..757e711 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2258,7 +2258,7 @@
// 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(), 12);
+ bounds.set(patch.getControlPoints(), SkPatch::kNumCtrlPts);
if (this->quickReject(bounds)) {
return;
}
diff --git a/src/core/SkPatch.cpp b/src/core/SkPatch.cpp
index cc967d5..4cca2ba 100644
--- a/src/core/SkPatch.cpp
+++ b/src/core/SkPatch.cpp
@@ -9,6 +9,7 @@
#include "SkGeometry.h"
#include "SkColorPriv.h"
+#include "SkBuffer.h"
////////////////////////////////////////////////////////////////////////////////
@@ -117,18 +118,12 @@
////////////////////////////////////////////////////////////////////////////////
-SkPatch::SkPatch(SkPoint points[12], SkColor colors[4]) {
-
- for (int i = 0; i < 12; i++) {
- fCtrlPoints[i] = points[i];
- }
- for (int i = 0; i < 4; i++) {
- fCornerColors[i] = colors[i];
- }
-
+SkPatch::SkPatch(const SkPoint points[12], const SkColor colors[4]) {
+ this->reset(points, colors);
}
-uint8_t bilinear(SkScalar tx, SkScalar ty, SkScalar c00, SkScalar c10, SkScalar c01, SkScalar c11) {
+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);
@@ -141,8 +136,8 @@
}
// premultiply colors to avoid color bleeding.
- SkPMColor colors[4];
- for (int i = 0; i < 4; i++) {
+ SkPMColor colors[SkPatch::kNumColors];
+ for (int i = 0; i < SkPatch::kNumColors; i++) {
colors[i] = SkPreMultiplyColor(fCornerColors[i]);
}
@@ -157,7 +152,7 @@
data->fTexCoords = SkNEW_ARRAY(SkPoint, data->fVertexCount);
data->fIndices = SkNEW_ARRAY(uint16_t, data->fIndexCount);
- SkPoint pts[4];
+ SkPoint pts[SkPatch::kNumPtsCubic];
this->getBottomPoints(pts);
FwDCubicEvaluator fBottom(pts);
this->getTopPoints(pts);
@@ -197,22 +192,22 @@
+ u * fBottom.getCtrlPoints()[3].y()));
data->fPoints[dataIndex] = s0 + s1 - s2;
- uint8_t a = bilinear(u, v,
+ 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 = bilinear(u, v,
+ 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 = bilinear(u, v,
+ 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 = bilinear(u, v,
+ uint8_t b = bilerp(u, v,
SkScalar(SkColorGetB(colors[kTopLeft_CornerColors])),
SkScalar(SkColorGetB(colors[kTopRight_CornerColors])),
SkScalar(SkColorGetB(colors[kBottomLeft_CornerColors])),
@@ -236,3 +231,32 @@
}
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/SkPictureFlat.h b/src/core/SkPictureFlat.h
index 5d1a6b5..2be929b 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -67,8 +67,10 @@
DRAW_DRRECT,
PUSH_CULL,
POP_CULL,
+
+ DRAW_PATCH, // could not add in aphabetical order
- LAST_DRAWTYPE_ENUM = POP_CULL
+ LAST_DRAWTYPE_ENUM = DRAW_PATCH
};
// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index d16a635..59abe7c 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -306,6 +306,12 @@
case DRAW_PAINT:
canvas->drawPaint(*fPictureData->getPaint(reader));
break;
+ case DRAW_PATCH: {
+ const SkPaint& paint = *fPictureData->getPaint(reader);
+ SkPatch patch;
+ reader->readPatch(&patch);
+ canvas->drawPatch(patch, paint);
+ } break;
case DRAW_PATH: {
const SkPaint& paint = *fPictureData->getPaint(reader);
canvas->drawPath(fPictureData->getPath(reader), paint);
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index ab4c3fa..72c537b 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -122,6 +122,7 @@
1, // DRAWDRRECT - right after op code
0, // PUSH_CULL - no paint
0, // POP_CULL - no paint
+ 1, // DRAW_PATCH - right after op code
};
SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
@@ -1480,6 +1481,21 @@
this->validate(initialOffset, size);
}
+void SkPictureRecord::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
+ // op + paint index + patch 12 control points + patch 4 colors
+ size_t size = 2 * kUInt32Size + SkPatch::kNumCtrlPts * sizeof(SkPoint) +
+ SkPatch::kNumColors * sizeof(SkColor);
+ size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
+ SkASSERT(initialOffset+getPaintOffset(DRAW_PATCH, size) == fWriter.bytesWritten());
+ this->addPaint(paint);
+ this->addPatch(patch);
+ this->validate(initialOffset, size);
+}
+
void SkPictureRecord::drawData(const void* data, size_t length) {
#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
@@ -1613,6 +1629,10 @@
this->addInt(this->addPathToHeap(path));
}
+void SkPictureRecord::addPatch(const SkPatch& patch) {
+ fWriter.writePatch(patch);
+}
+
void SkPictureRecord::addPicture(const SkPicture* picture) {
int index = fPictureRefs.find(picture);
if (index < 0) { // not found
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index a1b52fb..140558d 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -61,6 +61,7 @@
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;
@@ -177,6 +178,7 @@
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 addPath(const SkPath& path);
void addPicture(const SkPicture* picture);
void addPoint(const SkPoint& point);
diff --git a/src/core/SkReadBuffer.cpp b/src/core/SkReadBuffer.cpp
index 4358786..27f2d2b 100644
--- a/src/core/SkReadBuffer.cpp
+++ b/src/core/SkReadBuffer.cpp
@@ -148,6 +148,10 @@
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 89efb8e..ac46319 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -63,6 +63,7 @@
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(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint));
DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 4c02a35..255eb39 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -206,6 +206,10 @@
indexCount);
}
+void SkRecorder::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+ APPEND(DrawPatch, delay_copy(paint), delay_copy(patch));
+}
+
void SkRecorder::willSave() {
APPEND(Save);
INHERITED(willSave);
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 0eb11d7..6eba19e 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -61,6 +61,7 @@
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;
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index 02cfc64..e6d98f7 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -45,6 +45,7 @@
M(DrawOval) \
M(DrawPaint) \
M(DrawPath) \
+ M(DrawPatch) \
M(DrawPoints) \
M(DrawPosText) \
M(DrawPosTextH) \
@@ -217,6 +218,7 @@
RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
RECORD1(DrawPaint, SkPaint, paint);
RECORD2(DrawPath, SkPaint, paint, SkPath, path);
+RECORD2(DrawPatch, SkPaint, paint, SkPatch, patch);
RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
RECORD4(DrawPosText, SkPaint, paint,
PODArray<char>, text,
diff --git a/src/core/SkValidatingReadBuffer.cpp b/src/core/SkValidatingReadBuffer.cpp
index 037a994..8202149 100644
--- a/src/core/SkValidatingReadBuffer.cpp
+++ b/src/core/SkValidatingReadBuffer.cpp
@@ -171,6 +171,17 @@
}
}
+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 5cf3abe..8850a07 100644
--- a/src/core/SkValidatingReadBuffer.h
+++ b/src/core/SkValidatingReadBuffer.h
@@ -46,6 +46,7 @@
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/SkGPipePriv.h b/src/pipe/SkGPipePriv.h
index 58cafe8..821da0f 100644
--- a/src/pipe/SkGPipePriv.h
+++ b/src/pipe/SkGPipePriv.h
@@ -48,6 +48,7 @@
kDrawDRRect_DrawOp,
kDrawOval_DrawOp,
kDrawPaint_DrawOp,
+ kDrawPatch_DrawOp,
kDrawPath_DrawOp,
kDrawPicture_DrawOp,
kDrawPoints_DrawOp,
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index 9047e82..35b0a94 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -404,6 +404,15 @@
}
}
+static void drawPatch_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
+ SkGPipeState* state) {
+ SkPatch patch;
+ reader->readPatch(&patch);
+ if (state->shouldDraw()) {
+ canvas->drawPatch(patch, state->paint());
+ }
+}
+
static void drawPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkPath path;
@@ -775,6 +784,7 @@
drawDRRect_rp,
drawOval_rp,
drawPaint_rp,
+ drawPatch_rp,
drawPath_rp,
drawPicture_rp,
drawPoints_rp,
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index 46e4260f..186b66c 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -254,6 +254,7 @@
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;
@@ -997,6 +998,15 @@
}
}
+void SkGPipeCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+ NOTIFY_SETUP(this);
+ this->writePaint(paint);
+ if (this->needOpBytes(patch.writeToMemory(NULL))) {
+ this->writeOp(kDrawPatch_DrawOp);
+ fWriter.writePatch(patch);
+ }
+}
+
void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
if (size && ptr) {
NOTIFY_SETUP(this);
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index 2820bac..17a1f6c 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -917,7 +917,9 @@
}
void SkDeferredCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
- //TODO
+ AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
+ this->drawingCanvas()->drawPatch(patch, paint);
+ this->recordedDrawCommand();
}
SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index b12928f..3c683e6 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -442,6 +442,19 @@
SkScalarToFloat(vertices[0].fY));
}
+void SkDumpCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+ const SkPoint* points = patch.getControlPoints();
+ const SkColor* color = patch.getColors();
+ //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]);
+}
+
void SkDumpCanvas::drawData(const void* data, size_t length) {
// this->dump(kDrawData_Verb, NULL, "drawData(%d)", length);
this->dump(kDrawData_Verb, NULL, "drawData(%d) %.*s", length,
diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp
index 11e4a65..b33c99e 100644
--- a/src/utils/SkNWayCanvas.cpp
+++ b/src/utils/SkNWayCanvas.cpp
@@ -284,6 +284,13 @@
}
}
+void SkNWayCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawPatch(patch, paint);
+ }
+}
+
void SkNWayCanvas::drawData(const void* data, size_t length) {
Iter iter(fList);
while (iter.next()) {
diff --git a/src/utils/SkPatchUtils.cpp b/src/utils/SkPatchUtils.cpp
index 7dd0a09..ab15290 100644
--- a/src/utils/SkPatchUtils.cpp
+++ b/src/utils/SkPatchUtils.cpp
@@ -7,10 +7,8 @@
#include "SkPatchUtils.h"
-#include "SkGeometry.h"
-
// size in pixels of each partition per axis, adjust this knob
-static const int kPartitionSize = 30;
+static const int kPartitionSize = 15;
/**
* Calculate the approximate arc length given a bezier curve's control points.
diff --git a/src/utils/SkProxyCanvas.cpp b/src/utils/SkProxyCanvas.cpp
index 3aa459c..1029f40 100644
--- a/src/utils/SkProxyCanvas.cpp
+++ b/src/utils/SkProxyCanvas.cpp
@@ -149,6 +149,10 @@
xmode, indices, indexCount, paint);
}
+void SkProxyCanvas::drawPatch(const SkPatch& patch, const SkPaint& paint) {
+ fProxy->drawPatch(patch, paint);
+}
+
void SkProxyCanvas::drawData(const void* data, size_t length) {
fProxy->drawData(data, length);
}