From c25e2693ab00cfe7691b68b7d47f2159640d783a Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Mon, 12 Mar 2018 10:57:28 -0400 Subject: 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 Commit-Queue: Brian Osman --- tools/debugger/SkDebugCanvas.cpp | 9 +++ tools/debugger/SkDebugCanvas.h | 3 + tools/debugger/SkDrawCommand.cpp | 166 ++++++++++++++++++++++++++++++++++++--- tools/debugger/SkDrawCommand.h | 41 +++++++++- 4 files changed, 209 insertions(+), 10 deletions(-) (limited to 'tools/debugger') diff --git a/tools/debugger/SkDebugCanvas.cpp b/tools/debugger/SkDebugCanvas.cpp index d2dddb8d15..8644025c48 100644 --- a/tools/debugger/SkDebugCanvas.cpp +++ b/tools/debugger/SkDebugCanvas.cpp @@ -509,6 +509,11 @@ void SkDebugCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, con this->addDrawCommand(new SkDrawImageRectCommand(image, src, dst, paint, constraint)); } +void SkDebugCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, + const SkRect& dst, const SkPaint* paint) { + this->addDrawCommand(new SkDrawImageNineCommand(image, center, dst, paint)); +} + void SkDebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { this->addDrawCommand(new SkDrawOvalCommand(oval, paint)); } @@ -526,6 +531,10 @@ void SkDebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { this->addDrawCommand(new SkDrawPathCommand(path, paint)); } +void SkDebugCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) { + this->addDrawCommand(new SkDrawRegionCommand(region, paint)); +} + void SkDebugCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { diff --git a/tools/debugger/SkDebugCanvas.h b/tools/debugger/SkDebugCanvas.h index 634d5b416d..45266d3795 100644 --- a/tools/debugger/SkDebugCanvas.h +++ b/tools/debugger/SkDebugCanvas.h @@ -206,6 +206,7 @@ protected: void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override; void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override; void onDrawPath(const SkPath&, const SkPaint&) override; + void onDrawRegion(const SkRegion&, const SkPaint&) override; void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override; void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*, SrcRectConstraint) override; @@ -216,6 +217,8 @@ protected: const SkPaint*, SrcRectConstraint) override; void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; + void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, + const SkPaint*) override; void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override; void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override; void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override; diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp index 5766689103..7138596adc 100644 --- a/tools/debugger/SkDrawCommand.cpp +++ b/tools/debugger/SkDrawCommand.cpp @@ -214,6 +214,7 @@ SkDrawCommand::~SkDrawCommand() { 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 @@ const char* SkDrawCommand::GetCommandString(OpType type) { 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 @@ SkDrawCommand* SkDrawCommand::fromJSON(Json::Value& command, UrlDataManager& url if (!initialized) { initialized = true; INSTALL_FACTORY(Restore); + INSTALL_FACTORY(Clear); INSTALL_FACTORY(ClipPath); INSTALL_FACTORY(ClipRegion); INSTALL_FACTORY(ClipRect); @@ -282,14 +286,18 @@ SkDrawCommand* SkDrawCommand::fromJSON(Json::Value& command, UrlDataManager& url 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 @@ void render_path(SkCanvas* canvas, const SkPath& path) { 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::MakeJsonPath(const SkPath& path) { } Json::Value SkDrawCommand::MakeJsonRegion(const SkRegion& region) { - return Json::Value(""); + // 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_path(Json::Value& path, SkPath* result) { } } +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 @@ SkClipOp get_json_clipop(Json::Value& jsonOp) { 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 @@ Json::Value SkClipRegionCommand::toJSON(UrlDataManager& urlDataManager) const { 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 SkDrawImageLatticeCommand::toJSON(UrlDataManager& urlDataManager) co 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 @@ Json::Value SkDrawImageLatticeCommand::toJSON(UrlDataManager& urlDataManager) co 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 SkDrawImageRectCommand::toJSON(UrlDataManager& urlDataManager) const 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 @@ SkDrawImageRectCommand* SkDrawImageRectCommand::fromJSON(Json::Value& command, 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 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 @@ SkDrawOvalCommand* SkDrawOvalCommand::fromJSON(Json::Value& command, 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 @@ SkDrawPathCommand* SkDrawPathCommand::fromJSON(Json::Value& command, 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) diff --git a/tools/debugger/SkDrawCommand.h b/tools/debugger/SkDrawCommand.h index 654cbdda9a..d2eee9b63b 100644 --- a/tools/debugger/SkDrawCommand.h +++ b/tools/debugger/SkDrawCommand.h @@ -26,6 +26,7 @@ class SkDrawCommand { public: enum OpType { kBeginDrawPicture_OpType, + kClear_OpType, kClipPath_OpType, kClipRegion_OpType, kClipRect_OpType, @@ -35,12 +36,13 @@ public: kDrawBitmap_OpType, kDrawBitmapNine_OpType, kDrawBitmapRect_OpType, - kDrawClear_OpType, kDrawDRRect_OpType, kDrawImage_OpType, kDrawImageLattice_OpType, + kDrawImageNine_OpType, kDrawImageRect_OpType, kDrawOval_OpType, + kDrawArc_OpType, kDrawPaint_OpType, kDrawPatch_OpType, kDrawPath_OpType, @@ -49,6 +51,7 @@ public: kDrawPosTextH_OpType, kDrawRect_OpType, kDrawRRect_OpType, + kDrawRegion_OpType, kDrawText_OpType, kDrawTextBlob_OpType, kDrawTextOnPath_OpType, @@ -374,6 +377,8 @@ public: void execute(SkCanvas* canvas) const override; bool render(SkCanvas* canvas) const override; Json::Value toJSON(UrlDataManager& urlDataManager) const override; + static SkDrawImageLatticeCommand* fromJSON(Json::Value& command, + UrlDataManager& urlDataManager); private: sk_sp fImage; @@ -384,6 +389,25 @@ private: typedef SkDrawCommand INHERITED; }; +class SkDrawImageNineCommand : public SkDrawCommand { +public: + SkDrawImageNineCommand(const SkImage* image, const SkIRect& center, + const SkRect& dst, const SkPaint* paint); + void execute(SkCanvas* canvas) const override; + bool render(SkCanvas* canvas) const override; + Json::Value toJSON(UrlDataManager& urlDataManager) const override; + static SkDrawImageNineCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager); + +private: + sk_sp fImage; + SkIRect fCenter; + SkRect fDst; + SkPaint fPaint; + SkPaint* fPaintPtr; + + typedef SkDrawCommand INHERITED; +}; + class SkDrawImageRectCommand : public SkDrawCommand { public: SkDrawImageRectCommand(const SkImage* image, const SkRect* src, const SkRect& dst, @@ -514,6 +538,21 @@ private: typedef SkDrawCommand INHERITED; }; +class SkDrawRegionCommand : public SkDrawCommand { +public: + SkDrawRegionCommand(const SkRegion& region, const SkPaint& paint); + void execute(SkCanvas* canvas) const override; + bool render(SkCanvas* canvas) const override; + Json::Value toJSON(UrlDataManager& urlDataManager) const override; + static SkDrawRegionCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager); + +private: + SkRegion fRegion; + SkPaint fPaint; + + typedef SkDrawCommand INHERITED; +}; + class SkDrawTextCommand : public SkDrawCommand { public: SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y, -- cgit v1.2.3