Fix several bugs in SkDebugCanvas/SkDrawCommand
This adds drawImageNine and drawRegion support, actually
serializes regions (badly) for clipRegion, and fixes bugs
in quite a few other draw commands (wrong op type, missing
factory registration, JSON attribute mismatch, etc...)
There are still some other draw virtuals missing, but even
getting Lattice to round-trip through JSON is going to be
a bunch of new code, and I didn't want to combine too much
new code with the fixes for existing bugs.
Change-Id: I13749a2d21f4a5ca5f5948b60fc11185bc46645f
Reviewed-on: https://skia-review.googlesource.com/113707
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp
index 5766689..7138596 100644
--- a/tools/debugger/SkDrawCommand.cpp
+++ b/tools/debugger/SkDrawCommand.cpp
@@ -214,6 +214,7 @@
const char* SkDrawCommand::GetCommandString(OpType type) {
switch (type) {
case kBeginDrawPicture_OpType: return "BeginDrawPicture";
+ case kClear_OpType: return "DrawClear";
case kClipPath_OpType: return "ClipPath";
case kClipRegion_OpType: return "ClipRegion";
case kClipRect_OpType: return "ClipRect";
@@ -223,20 +224,22 @@
case kDrawBitmap_OpType: return "DrawBitmap";
case kDrawBitmapNine_OpType: return "DrawBitmapNine";
case kDrawBitmapRect_OpType: return "DrawBitmapRect";
- case kDrawClear_OpType: return "DrawClear";
case kDrawDRRect_OpType: return "DrawDRRect";
case kDrawImage_OpType: return "DrawImage";
case kDrawImageLattice_OpType: return "DrawImageLattice";
+ case kDrawImageNine_OpType: return "DrawImageNine";
case kDrawImageRect_OpType: return "DrawImageRect";
case kDrawOval_OpType: return "DrawOval";
case kDrawPaint_OpType: return "DrawPaint";
case kDrawPatch_OpType: return "DrawPatch";
case kDrawPath_OpType: return "DrawPath";
+ case kDrawArc_OpType: return "DrawArc";
case kDrawPoints_OpType: return "DrawPoints";
case kDrawPosText_OpType: return "DrawPosText";
case kDrawPosTextH_OpType: return "DrawPosTextH";
case kDrawRect_OpType: return "DrawRect";
case kDrawRRect_OpType: return "DrawRRect";
+ case kDrawRegion_OpType: return "DrawRegion";
case kDrawText_OpType: return "DrawText";
case kDrawTextBlob_OpType: return "DrawTextBlob";
case kDrawTextOnPath_OpType: return "DrawTextOnPath";
@@ -275,6 +278,7 @@
if (!initialized) {
initialized = true;
INSTALL_FACTORY(Restore);
+ INSTALL_FACTORY(Clear);
INSTALL_FACTORY(ClipPath);
INSTALL_FACTORY(ClipRegion);
INSTALL_FACTORY(ClipRect);
@@ -282,14 +286,18 @@
INSTALL_FACTORY(Concat);
INSTALL_FACTORY(DrawAnnotation);
INSTALL_FACTORY(DrawBitmap);
- INSTALL_FACTORY(DrawBitmapRect);
INSTALL_FACTORY(DrawBitmapNine);
+ INSTALL_FACTORY(DrawBitmapRect);
INSTALL_FACTORY(DrawImage);
+ INSTALL_FACTORY(DrawImageLattice);
+ INSTALL_FACTORY(DrawImageNine);
INSTALL_FACTORY(DrawImageRect);
INSTALL_FACTORY(DrawOval);
+ INSTALL_FACTORY(DrawArc);
INSTALL_FACTORY(DrawPaint);
INSTALL_FACTORY(DrawPath);
INSTALL_FACTORY(DrawPoints);
+ INSTALL_FACTORY(DrawRegion);
INSTALL_FACTORY(DrawText);
INSTALL_FACTORY(DrawPosText);
INSTALL_FACTORY(DrawPosTextH);
@@ -351,6 +359,24 @@
canvas->drawPath(path, p);
}
+void render_region(SkCanvas* canvas, const SkRegion& region) {
+ canvas->clear(0xFFFFFFFF);
+
+ const SkIRect& bounds = region.getBounds();
+ if (bounds.isEmpty()) {
+ return;
+ }
+
+ SkAutoCanvasRestore acr(canvas, true);
+ xlate_and_scale_to_bounds(canvas, SkRect::MakeFromIRect(bounds));
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawRegion(region, p);
+}
+
void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = nullptr) {
const SkISize& size = canvas->getBaseLayerSize();
@@ -657,7 +683,10 @@
}
Json::Value SkDrawCommand::MakeJsonRegion(const SkRegion& region) {
- return Json::Value("<unimplemented>");
+ // TODO: Actually serialize the rectangles, rather than just devolving to path
+ SkPath path;
+ region.getBoundaryPath(&path);
+ return MakeJsonPath(path);
}
static Json::Value make_json_regionop(SkClipOp op) {
@@ -1753,6 +1782,12 @@
}
}
+static void extract_json_region(Json::Value& region, SkRegion* result) {
+ SkPath path;
+ extract_json_path(region, &path);
+ result->setPath(path, SkRegion(path.getBounds().roundOut()));
+}
+
SkClipOp get_json_clipop(Json::Value& jsonOp) {
const char* op = jsonOp.asCString();
if (!strcmp(op, SKDEBUGCANVAS_REGIONOP_DIFFERENCE)) {
@@ -1777,7 +1812,7 @@
return kIntersect_SkClipOp;
}
-SkClearCommand::SkClearCommand(SkColor color) : INHERITED(kDrawClear_OpType) {
+SkClearCommand::SkClearCommand(SkColor color) : INHERITED(kClear_OpType) {
fColor = color;
fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
}
@@ -1855,8 +1890,10 @@
SkClipRegionCommand* SkClipRegionCommand::fromJSON(Json::Value& command,
UrlDataManager& urlDataManager) {
- SkASSERT(false);
- return nullptr;
+ SkRegion region;
+ extract_json_region(command[SKDEBUGCANVAS_ATTRIBUTE_REGION], ®ion);
+ return new SkClipRegionCommand(region,
+ get_json_clipop(command[SKDEBUGCANVAS_ATTRIBUTE_REGIONOP]));
}
SkClipRectCommand::SkClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA)
@@ -2366,7 +2403,7 @@
Json::Value result = INHERITED::toJSON(urlDataManager);
Json::Value encoded;
if (flatten(*fImage.get(), &encoded, urlDataManager)) {
- result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
+ result[SKDEBUGCANVAS_ATTRIBUTE_IMAGE] = encoded;
result[SKDEBUGCANVAS_ATTRIBUTE_LATTICE] = MakeJsonLattice(fLattice);
result[SKDEBUGCANVAS_ATTRIBUTE_DST] = MakeJsonRect(fDst);
if (fPaint.isValid()) {
@@ -2380,6 +2417,12 @@
return result;
}
+SkDrawImageLatticeCommand* SkDrawImageLatticeCommand::fromJSON(Json::Value& command,
+ UrlDataManager& urlDataManager) {
+ SkDEBUGFAIL("Not implemented yet.");
+ return nullptr;
+}
+
SkDrawImageRectCommand::SkDrawImageRectCommand(const SkImage* image, const SkRect* src,
const SkRect& dst, const SkPaint* paint,
SkCanvas::SrcRectConstraint constraint)
@@ -2426,7 +2469,7 @@
Json::Value result = INHERITED::toJSON(urlDataManager);
Json::Value encoded;
if (flatten(*fImage.get(), &encoded, urlDataManager)) {
- result[SKDEBUGCANVAS_ATTRIBUTE_BITMAP] = encoded;
+ result[SKDEBUGCANVAS_ATTRIBUTE_IMAGE] = encoded;
if (fSrc.isValid()) {
result[SKDEBUGCANVAS_ATTRIBUTE_SRC] = MakeJsonRect(*fSrc.get());
}
@@ -2484,6 +2527,77 @@
return result;
}
+SkDrawImageNineCommand::SkDrawImageNineCommand(const SkImage* image, const SkIRect& center,
+ const SkRect& dst, const SkPaint* paint)
+ : INHERITED(kDrawImageNine_OpType)
+ , fImage(SkRef(image))
+ , fCenter(center)
+ , fDst(dst) {
+ if (paint) {
+ fPaint = *paint;
+ fPaintPtr = &fPaint;
+ } else {
+ fPaintPtr = nullptr;
+ }
+
+ fInfo.push(SkObjectParser::ImageToString(image));
+ fInfo.push(SkObjectParser::IRectToString(center));
+ fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
+ if (paint) {
+ fInfo.push(SkObjectParser::PaintToString(*paint));
+ }
+}
+
+void SkDrawImageNineCommand::execute(SkCanvas* canvas) const {
+ canvas->drawImageNine(fImage.get(), fCenter, fDst, fPaintPtr);
+}
+
+bool SkDrawImageNineCommand::render(SkCanvas* canvas) const {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clear(0xFFFFFFFF);
+
+ xlate_and_scale_to_bounds(canvas, fDst);
+
+ this->execute(canvas);
+ return true;
+}
+
+Json::Value SkDrawImageNineCommand::toJSON(UrlDataManager& urlDataManager) const {
+ Json::Value result = INHERITED::toJSON(urlDataManager);
+ Json::Value encoded;
+ if (flatten(*fImage.get(), &encoded, urlDataManager)) {
+ result[SKDEBUGCANVAS_ATTRIBUTE_IMAGE] = encoded;
+ result[SKDEBUGCANVAS_ATTRIBUTE_CENTER] = MakeJsonIRect(fCenter);
+ result[SKDEBUGCANVAS_ATTRIBUTE_DST] = MakeJsonRect(fDst);
+ if (fPaintPtr != nullptr) {
+ result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(*fPaintPtr, urlDataManager);
+ }
+ }
+ return result;
+}
+
+SkDrawImageNineCommand* SkDrawImageNineCommand::fromJSON(Json::Value& command,
+ UrlDataManager& urlDataManager) {
+ sk_sp<SkImage> image = load_image(command[SKDEBUGCANVAS_ATTRIBUTE_IMAGE], urlDataManager);
+ if (image == nullptr) {
+ return nullptr;
+ }
+ SkIRect center;
+ extract_json_irect(command[SKDEBUGCANVAS_ATTRIBUTE_CENTER], ¢er);
+ SkRect dst;
+ extract_json_rect(command[SKDEBUGCANVAS_ATTRIBUTE_DST], &dst);
+ SkPaint* paintPtr;
+ SkPaint paint;
+ if (command.isMember(SKDEBUGCANVAS_ATTRIBUTE_PAINT)) {
+ extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
+ paintPtr = &paint;
+ } else {
+ paintPtr = nullptr;
+ }
+ SkDrawImageNineCommand* result = new SkDrawImageNineCommand(image.get(), center, dst, paintPtr);
+ return result;
+}
+
SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint)
: INHERITED(kDrawOval_OpType) {
fOval = oval;
@@ -2531,7 +2645,7 @@
SkDrawArcCommand::SkDrawArcCommand(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
bool useCenter, const SkPaint& paint)
- : INHERITED(kDrawOval_OpType) {
+ : INHERITED(kDrawArc_OpType) {
fOval = oval;
fStartAngle = startAngle;
fSweepAngle = sweepAngle;
@@ -2651,6 +2765,40 @@
return new SkDrawPathCommand(path, paint);
}
+SkDrawRegionCommand::SkDrawRegionCommand(const SkRegion& region, const SkPaint& paint)
+ : INHERITED(kDrawRegion_OpType) {
+ fRegion = region;
+ fPaint = paint;
+
+ fInfo.push(SkObjectParser::RegionToString(region));
+ fInfo.push(SkObjectParser::PaintToString(paint));
+}
+
+void SkDrawRegionCommand::execute(SkCanvas* canvas) const {
+ canvas->drawRegion(fRegion, fPaint);
+}
+
+bool SkDrawRegionCommand::render(SkCanvas* canvas) const {
+ render_region(canvas, fRegion);
+ return true;
+}
+
+Json::Value SkDrawRegionCommand::toJSON(UrlDataManager& urlDataManager) const {
+ Json::Value result = INHERITED::toJSON(urlDataManager);
+ result[SKDEBUGCANVAS_ATTRIBUTE_REGION] = MakeJsonRegion(fRegion);
+ result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
+ return result;
+}
+
+SkDrawRegionCommand* SkDrawRegionCommand::fromJSON(Json::Value& command,
+ UrlDataManager& urlDataManager) {
+ SkRegion region;
+ extract_json_region(command[SKDEBUGCANVAS_ATTRIBUTE_REGION], ®ion);
+ SkPaint paint;
+ extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
+ return new SkDrawRegionCommand(region, paint);
+}
+
SkBeginDrawPictureCommand::SkBeginDrawPictureCommand(const SkPicture* picture,
const SkMatrix* matrix,
const SkPaint* paint)