| /* |
| * Copyright 2012 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "tools/debugger/DrawCommand.h" |
| |
| #include "include/core/SkAlphaType.h" |
| #include "include/core/SkBitmap.h" |
| #include "include/core/SkBlendMode.h" |
| #include "include/core/SkBlurTypes.h" |
| #include "include/core/SkClipOp.h" |
| #include "include/core/SkColorFilter.h" |
| #include "include/core/SkColorType.h" |
| #include "include/core/SkDrawable.h" |
| #include "include/core/SkFlattenable.h" |
| #include "include/core/SkFont.h" |
| #include "include/core/SkFontTypes.h" |
| #include "include/core/SkImageFilter.h" |
| #include "include/core/SkImageInfo.h" |
| #include "include/core/SkMaskFilter.h" |
| #include "include/core/SkPathEffect.h" |
| #include "include/core/SkPathTypes.h" |
| #include "include/core/SkPicture.h" |
| #include "include/core/SkPixmap.h" |
| #include "include/core/SkPoint3.h" |
| #include "include/core/SkRSXform.h" |
| #include "include/core/SkSamplingOptions.h" |
| #include "include/core/SkSize.h" |
| #include "include/core/SkStream.h" |
| #include "include/core/SkTypeface.h" |
| #include "include/encode/SkPngEncoder.h" |
| #include "include/private/base/SkDebug.h" |
| #include "include/private/base/SkMalloc.h" |
| #include "include/private/base/SkTo.h" |
| #include "include/private/gpu/ganesh/GrImageContext.h" |
| #include "include/utils/SkShadowUtils.h" |
| #include "src/base/SkAutoMalloc.h" |
| #include "src/core/SkCanvasPriv.h" |
| #include "src/core/SkFontPriv.h" |
| #include "src/core/SkMaskFilterBase.h" |
| #include "src/core/SkPaintDefaults.h" |
| #include "src/core/SkRectPriv.h" |
| #include "src/core/SkTextBlobPriv.h" |
| #include "src/core/SkWriteBuffer.h" |
| #include "src/image/SkImage_Base.h" |
| #include "src/utils/SkJSONWriter.h" |
| #include "tools/UrlDataManager.h" |
| #include "tools/debugger/DebugLayerManager.h" |
| #include "tools/debugger/JsonWriteBuffer.h" |
| |
| #include <algorithm> |
| #include <cstring> |
| #include <utility> |
| |
| class GrDirectContext; |
| |
| #if defined(SK_GANESH) |
| #include "include/gpu/GrRecordingContext.h" |
| #endif |
| |
| #define DEBUGCANVAS_ATTRIBUTE_DUMP "dump" |
| #define DEBUGCANVAS_ATTRIBUTE_COMMAND "command" |
| #define DEBUGCANVAS_ATTRIBUTE_VISIBLE "visible" |
| #define DEBUGCANVAS_ATTRIBUTE_MATRIX "matrix" |
| #define DEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS "drawDepthTranslation" |
| #define DEBUGCANVAS_ATTRIBUTE_COORDS "coords" |
| #define DEBUGCANVAS_ATTRIBUTE_EDGING "edging" |
| #define DEBUGCANVAS_ATTRIBUTE_HINTING "hinting" |
| #define DEBUGCANVAS_ATTRIBUTE_BOUNDS "bounds" |
| #define DEBUGCANVAS_ATTRIBUTE_PAINT "paint" |
| #define DEBUGCANVAS_ATTRIBUTE_OUTER "outer" |
| #define DEBUGCANVAS_ATTRIBUTE_INNER "inner" |
| #define DEBUGCANVAS_ATTRIBUTE_MODE "mode" |
| #define DEBUGCANVAS_ATTRIBUTE_POINTS "points" |
| #define DEBUGCANVAS_ATTRIBUTE_PATH "path" |
| #define DEBUGCANVAS_ATTRIBUTE_CLUSTERS "clusters" |
| #define DEBUGCANVAS_ATTRIBUTE_TEXT "text" |
| #define DEBUGCANVAS_ATTRIBUTE_COLOR "color" |
| #define DEBUGCANVAS_ATTRIBUTE_ALPHA "alpha" |
| #define DEBUGCANVAS_ATTRIBUTE_BLENDMODE "blendMode" |
| #define DEBUGCANVAS_ATTRIBUTE_SAMPLING "sampling" |
| #define DEBUGCANVAS_ATTRIBUTE_STYLE "style" |
| #define DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH "strokeWidth" |
| #define DEBUGCANVAS_ATTRIBUTE_STROKEMITER "strokeMiter" |
| #define DEBUGCANVAS_ATTRIBUTE_STROKEJOIN "strokeJoin" |
| #define DEBUGCANVAS_ATTRIBUTE_CAP "cap" |
| #define DEBUGCANVAS_ATTRIBUTE_ANTIALIAS "antiAlias" |
| #define DEBUGCANVAS_ATTRIBUTE_DITHER "dither" |
| #define DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT "fakeBoldText" |
| #define DEBUGCANVAS_ATTRIBUTE_LINEARTEXT "linearText" |
| #define DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT "subpixelText" |
| #define DEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT "devKernText" |
| #define DEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT "lcdRenderText" |
| #define DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT "embeddedBitmapText" |
| #define DEBUGCANVAS_ATTRIBUTE_AUTOHINTING "forceAutoHinting" |
| #define DEBUGCANVAS_ATTRIBUTE_REGION "region" |
| #define DEBUGCANVAS_ATTRIBUTE_REGIONOP "op" |
| #define DEBUGCANVAS_ATTRIBUTE_EDGESTYLE "edgeStyle" |
| #define DEBUGCANVAS_ATTRIBUTE_DEVICEREGION "deviceRegion" |
| #define DEBUGCANVAS_ATTRIBUTE_BLUR "blur" |
| #define DEBUGCANVAS_ATTRIBUTE_SIGMA "sigma" |
| #define DEBUGCANVAS_ATTRIBUTE_QUALITY "quality" |
| #define DEBUGCANVAS_ATTRIBUTE_TEXTSIZE "textSize" |
| #define DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX "textScaleX" |
| #define DEBUGCANVAS_ATTRIBUTE_TEXTSKEWX "textSkewX" |
| #define DEBUGCANVAS_ATTRIBUTE_DASHING "dashing" |
| #define DEBUGCANVAS_ATTRIBUTE_INTERVALS "intervals" |
| #define DEBUGCANVAS_ATTRIBUTE_PHASE "phase" |
| #define DEBUGCANVAS_ATTRIBUTE_FILLTYPE "fillType" |
| #define DEBUGCANVAS_ATTRIBUTE_VERBS "verbs" |
| #define DEBUGCANVAS_ATTRIBUTE_NAME "name" |
| #define DEBUGCANVAS_ATTRIBUTE_DATA "data" |
| #define DEBUGCANVAS_ATTRIBUTE_VALUES "values" |
| #define DEBUGCANVAS_ATTRIBUTE_SHADER "shader" |
| #define DEBUGCANVAS_ATTRIBUTE_PATHEFFECT "pathEffect" |
| #define DEBUGCANVAS_ATTRIBUTE_MASKFILTER "maskFilter" |
| #define DEBUGCANVAS_ATTRIBUTE_XFERMODE "xfermode" |
| #define DEBUGCANVAS_ATTRIBUTE_BACKDROP "backdrop" |
| #define DEBUGCANVAS_ATTRIBUTE_COLORFILTER "colorfilter" |
| #define DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER "imagefilter" |
| #define DEBUGCANVAS_ATTRIBUTE_IMAGE "image" |
| #define DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX "imageIndex" |
| #define DEBUGCANVAS_ATTRIBUTE_BITMAP "bitmap" |
| #define DEBUGCANVAS_ATTRIBUTE_SRC "src" |
| #define DEBUGCANVAS_ATTRIBUTE_DST "dst" |
| #define DEBUGCANVAS_ATTRIBUTE_CENTER "center" |
| #define DEBUGCANVAS_ATTRIBUTE_STRICT "strict" |
| #define DEBUGCANVAS_ATTRIBUTE_DESCRIPTION "description" |
| #define DEBUGCANVAS_ATTRIBUTE_X "x" |
| #define DEBUGCANVAS_ATTRIBUTE_Y "y" |
| #define DEBUGCANVAS_ATTRIBUTE_RUNS "runs" |
| #define DEBUGCANVAS_ATTRIBUTE_POSITIONS "positions" |
| #define DEBUGCANVAS_ATTRIBUTE_GLYPHS "glyphs" |
| #define DEBUGCANVAS_ATTRIBUTE_FONT "font" |
| #define DEBUGCANVAS_ATTRIBUTE_TYPEFACE "typeface" |
| #define DEBUGCANVAS_ATTRIBUTE_CUBICS "cubics" |
| #define DEBUGCANVAS_ATTRIBUTE_COLORS "colors" |
| #define DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS "textureCoords" |
| #define DEBUGCANVAS_ATTRIBUTE_STARTANGLE "startAngle" |
| #define DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE "sweepAngle" |
| #define DEBUGCANVAS_ATTRIBUTE_USECENTER "useCenter" |
| #define DEBUGCANVAS_ATTRIBUTE_SHORTDESC "shortDesc" |
| #define DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID "uniqueID" |
| #define DEBUGCANVAS_ATTRIBUTE_WIDTH "width" |
| #define DEBUGCANVAS_ATTRIBUTE_HEIGHT "height" |
| #define DEBUGCANVAS_ATTRIBUTE_ALPHA "alpha" |
| #define DEBUGCANVAS_ATTRIBUTE_LATTICE "lattice" |
| #define DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT "xCount" |
| #define DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT "yCount" |
| #define DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS "xDivs" |
| #define DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS "yDivs" |
| #define DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS "flags" |
| #define DEBUGCANVAS_ATTRIBUTE_ZPLANE "zPlane" |
| #define DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION "lightPositions" |
| #define DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR "ambientColor" |
| #define DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR "spotColor" |
| #define DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS "lightRadius" |
| #define DEBUGCANVAS_ATTRIBUTE_LAYERNODEID "layerNodeId" |
| |
| #define DEBUGCANVAS_VERB_MOVE "move" |
| #define DEBUGCANVAS_VERB_LINE "line" |
| #define DEBUGCANVAS_VERB_QUAD "quad" |
| #define DEBUGCANVAS_VERB_CUBIC "cubic" |
| #define DEBUGCANVAS_VERB_CONIC "conic" |
| #define DEBUGCANVAS_VERB_CLOSE "close" |
| |
| #define DEBUGCANVAS_STYLE_FILL "fill" |
| #define DEBUGCANVAS_STYLE_STROKE "stroke" |
| #define DEBUGCANVAS_STYLE_STROKEANDFILL "strokeAndFill" |
| |
| #define DEBUGCANVAS_POINTMODE_POINTS "points" |
| #define DEBUGCANVAS_POINTMODE_LINES "lines" |
| #define DEBUGCANVAS_POINTMODE_POLYGON "polygon" |
| |
| #define DEBUGCANVAS_CLIPOP_DIFFERENCE "difference" |
| #define DEBUGCANVAS_CLIPOP_INTERSECT "intersect" |
| |
| #define DEBUGCANVAS_BLURSTYLE_NORMAL "normal" |
| #define DEBUGCANVAS_BLURSTYLE_SOLID "solid" |
| #define DEBUGCANVAS_BLURSTYLE_OUTER "outer" |
| #define DEBUGCANVAS_BLURSTYLE_INNER "inner" |
| |
| #define DEBUGCANVAS_BLURQUALITY_LOW "low" |
| #define DEBUGCANVAS_BLURQUALITY_HIGH "high" |
| |
| #define DEBUGCANVAS_FILLTYPE_WINDING "winding" |
| #define DEBUGCANVAS_FILLTYPE_EVENODD "evenOdd" |
| #define DEBUGCANVAS_FILLTYPE_INVERSEWINDING "inverseWinding" |
| #define DEBUGCANVAS_FILLTYPE_INVERSEEVENODD "inverseEvenOdd" |
| |
| #define DEBUGCANVAS_CAP_BUTT "butt" |
| #define DEBUGCANVAS_CAP_ROUND "round" |
| #define DEBUGCANVAS_CAP_SQUARE "square" |
| |
| #define DEBUGCANVAS_MITER_JOIN "miter" |
| #define DEBUGCANVAS_ROUND_JOIN "round" |
| #define DEBUGCANVAS_BEVEL_JOIN "bevel" |
| |
| #define DEBUGCANVAS_COLORTYPE_ARGB4444 "ARGB4444" |
| #define DEBUGCANVAS_COLORTYPE_RGBA8888 "RGBA8888" |
| #define DEBUGCANVAS_COLORTYPE_BGRA8888 "BGRA8888" |
| #define DEBUGCANVAS_COLORTYPE_565 "565" |
| #define DEBUGCANVAS_COLORTYPE_GRAY8 "Gray8" |
| #define DEBUGCANVAS_COLORTYPE_INDEX8 "Index8" |
| #define DEBUGCANVAS_COLORTYPE_ALPHA8 "Alpha8" |
| |
| #define DEBUGCANVAS_ALPHATYPE_OPAQUE "opaque" |
| #define DEBUGCANVAS_ALPHATYPE_PREMUL "premul" |
| #define DEBUGCANVAS_ALPHATYPE_UNPREMUL "unpremul" |
| #define DEBUGCANVAS_ALPHATYPE_UNKNOWN "unknown" |
| |
| #define DEBUGCANVAS_HINTING_NONE "none" |
| #define DEBUGCANVAS_HINTING_SLIGHT "slight" |
| #define DEBUGCANVAS_HINTING_NORMAL "normal" |
| #define DEBUGCANVAS_HINTING_FULL "full" |
| |
| #define DEBUGCANVAS_EDGING_ALIAS "alias" |
| #define DEBUGCANVAS_EDGING_ANTIALIAS "antialias" |
| #define DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS "subpixelantialias" |
| |
| #define DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC "transparentOccluder" |
| #define DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY "geometricOnly" |
| |
| static SkString* str_append(SkString* str, const SkRect& r) { |
| str->appendf(" [%g %g %g %g]", r.left(), r.top(), r.right(), r.bottom()); |
| return str; |
| } |
| |
| DrawCommand::DrawCommand(OpType type) : fOpType(type), fVisible(true) {} |
| |
| const char* DrawCommand::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"; |
| case kClipRRect_OpType: return "ClipRRect"; |
| case kResetClip_OpType: return "ResetClip"; |
| case kConcat_OpType: return "Concat"; |
| case kConcat44_OpType: return "Concat44"; |
| case kDrawAnnotation_OpType: return "DrawAnnotation"; |
| case kDrawBitmap_OpType: return "DrawBitmap"; |
| case kDrawBitmapRect_OpType: return "DrawBitmapRect"; |
| case kDrawDRRect_OpType: return "DrawDRRect"; |
| case kDrawImage_OpType: return "DrawImage"; |
| case kDrawImageLattice_OpType: return "DrawImageLattice"; |
| case kDrawImageRect_OpType: return "DrawImageRect"; |
| case kDrawImageRectLayer_OpType: return "DrawImageRectLayer"; |
| 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 kDrawRect_OpType: return "DrawRect"; |
| case kDrawRRect_OpType: return "DrawRRect"; |
| case kDrawRegion_OpType: return "DrawRegion"; |
| case kDrawShadow_OpType: return "DrawShadow"; |
| case kDrawTextBlob_OpType: return "DrawTextBlob"; |
| case kDrawVertices_OpType: return "DrawVertices"; |
| case kDrawAtlas_OpType: return "DrawAtlas"; |
| case kDrawDrawable_OpType: return "DrawDrawable"; |
| case kDrawEdgeAAQuad_OpType: return "DrawEdgeAAQuad"; |
| case kDrawEdgeAAImageSet_OpType: return "DrawEdgeAAImageSet"; |
| case kEndDrawPicture_OpType: return "EndDrawPicture"; |
| case kRestore_OpType: return "Restore"; |
| case kSave_OpType: return "Save"; |
| case kSaveLayer_OpType: return "SaveLayer"; |
| case kSetMatrix_OpType: return "SetMatrix"; |
| case kSetM44_OpType: return "SetM44"; |
| default: |
| SkDebugf("OpType error 0x%08x\n", type); |
| SkASSERT(0); |
| break; |
| } |
| SkDEBUGFAIL("DrawType UNUSED\n"); |
| return nullptr; |
| } |
| |
| void DrawCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_COMMAND, this->GetCommandString(fOpType)); |
| writer.appendBool(DEBUGCANVAS_ATTRIBUTE_VISIBLE, this->isVisible()); |
| } |
| |
| namespace { |
| |
| void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) { |
| const SkISize& size = canvas->getBaseLayerSize(); |
| |
| static const SkScalar kInsetFrac = 0.9f; // Leave a border around object |
| |
| canvas->translate(size.fWidth / 2.0f, size.fHeight / 2.0f); |
| if (bounds.width() > bounds.height()) { |
| canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.width()), |
| SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.width())); |
| } else { |
| canvas->scale(SkDoubleToScalar((kInsetFrac * size.fWidth) / bounds.height()), |
| SkDoubleToScalar((kInsetFrac * size.fHeight) / bounds.height())); |
| } |
| canvas->translate(-bounds.centerX(), -bounds.centerY()); |
| } |
| |
| void render_path(SkCanvas* canvas, const SkPath& path) { |
| canvas->clear(0xFFFFFFFF); |
| |
| const SkRect& bounds = path.getBounds(); |
| if (bounds.isEmpty()) { |
| return; |
| } |
| |
| SkAutoCanvasRestore acr(canvas, true); |
| xlate_and_scale_to_bounds(canvas, bounds); |
| |
| SkPaint p; |
| p.setColor(SK_ColorBLACK); |
| p.setStyle(SkPaint::kStroke_Style); |
| |
| 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::Make(bounds)); |
| |
| SkPaint p; |
| p.setColor(SK_ColorBLACK); |
| p.setStyle(SkPaint::kStroke_Style); |
| |
| canvas->drawRegion(region, p); |
| } |
| |
| void render_rrect(SkCanvas* canvas, const SkRRect& rrect) { |
| canvas->clear(0xFFFFFFFF); |
| canvas->save(); |
| |
| const SkRect& bounds = rrect.getBounds(); |
| |
| xlate_and_scale_to_bounds(canvas, bounds); |
| |
| SkPaint p; |
| p.setColor(SK_ColorBLACK); |
| p.setStyle(SkPaint::kStroke_Style); |
| |
| canvas->drawRRect(rrect, p); |
| canvas->restore(); |
| } |
| |
| void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) { |
| canvas->clear(0xFFFFFFFF); |
| canvas->save(); |
| |
| const SkRect& bounds = outer.getBounds(); |
| |
| xlate_and_scale_to_bounds(canvas, bounds); |
| |
| SkPaint p; |
| p.setColor(SK_ColorBLACK); |
| p.setStyle(SkPaint::kStroke_Style); |
| |
| canvas->drawDRRect(outer, inner, p); |
| canvas->restore(); |
| } |
| |
| void render_shadow(SkCanvas* canvas, const SkPath& path, SkDrawShadowRec rec) { |
| canvas->clear(0xFFFFFFFF); |
| |
| const SkRect& bounds = path.getBounds(); |
| if (bounds.isEmpty()) { |
| return; |
| } |
| |
| SkAutoCanvasRestore acr(canvas, true); |
| xlate_and_scale_to_bounds(canvas, bounds); |
| |
| rec.fAmbientColor = SK_ColorBLACK; |
| rec.fSpotColor = SK_ColorBLACK; |
| canvas->private_draw_shadow_rec(path, rec); |
| } |
| |
| void apply_paint_blend_mode(const SkPaint& paint, SkJSONWriter& writer) { |
| const auto mode = paint.getBlendMode_or(SkBlendMode::kSrcOver); |
| if (mode != SkBlendMode::kSrcOver) { |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_BLENDMODE, SkBlendMode_Name(mode)); |
| } |
| } |
| |
| } // namespace |
| |
| void DrawCommand::MakeJsonColor(SkJSONWriter& writer, const SkColor color) { |
| writer.beginArray(nullptr, false); |
| writer.appendS32(SkColorGetA(color)); |
| writer.appendS32(SkColorGetR(color)); |
| writer.appendS32(SkColorGetG(color)); |
| writer.appendS32(SkColorGetB(color)); |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonColor4f(SkJSONWriter& writer, const SkColor4f& color) { |
| writer.beginArray(nullptr, false); |
| writer.appendFloat(color.fA); |
| writer.appendFloat(color.fR); |
| writer.appendFloat(color.fG); |
| writer.appendFloat(color.fB); |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, const SkPoint& point) { |
| writer.beginArray(nullptr, false); |
| writer.appendFloat(point.x()); |
| writer.appendFloat(point.y()); |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonPoint(SkJSONWriter& writer, SkScalar x, SkScalar y) { |
| writer.beginArray(nullptr, false); |
| writer.appendFloat(x); |
| writer.appendFloat(y); |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonPoint3(SkJSONWriter& writer, const SkPoint3& point) { |
| writer.beginArray(nullptr, false); |
| writer.appendFloat(point.x()); |
| writer.appendFloat(point.y()); |
| writer.appendFloat(point.z()); |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonRect(SkJSONWriter& writer, const SkRect& rect) { |
| writer.beginArray(nullptr, false); |
| writer.appendFloat(rect.left()); |
| writer.appendFloat(rect.top()); |
| writer.appendFloat(rect.right()); |
| writer.appendFloat(rect.bottom()); |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonIRect(SkJSONWriter& writer, const SkIRect& rect) { |
| writer.beginArray(nullptr, false); |
| writer.appendS32(rect.left()); |
| writer.appendS32(rect.top()); |
| writer.appendS32(rect.right()); |
| writer.appendS32(rect.bottom()); |
| writer.endArray(); |
| } |
| |
| static void make_json_rrect(SkJSONWriter& writer, const SkRRect& rrect) { |
| writer.beginArray(nullptr, false); |
| DrawCommand::MakeJsonRect(writer, rrect.rect()); |
| DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperLeft_Corner)); |
| DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kUpperRight_Corner)); |
| DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerRight_Corner)); |
| DrawCommand::MakeJsonPoint(writer, rrect.radii(SkRRect::kLowerLeft_Corner)); |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonMatrix(SkJSONWriter& writer, const SkMatrix& matrix) { |
| writer.beginArray(); |
| for (int r = 0; r < 3; ++r) { |
| writer.beginArray(nullptr, false); |
| for (int c = 0; c < 3; ++c) { |
| writer.appendFloat(matrix[r * 3 + c]); |
| } |
| writer.endArray(); |
| } |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonMatrix44(SkJSONWriter& writer, const SkM44& matrix) { |
| writer.beginArray(); |
| for (int r = 0; r < 4; ++r) { |
| writer.beginArray(nullptr, false); |
| for (int c = 0; c < 4; ++c) { |
| writer.appendFloat(matrix.rc(r, c)); |
| } |
| writer.endArray(); |
| } |
| writer.endArray(); |
| } |
| |
| void DrawCommand::MakeJsonPath(SkJSONWriter& writer, const SkPath& path) { |
| writer.beginObject(); |
| |
| SkDynamicMemoryWStream wstream; |
| path.dump(&wstream, false); |
| auto data = wstream.detachAsData(); |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_DUMP, |
| static_cast<const char*>(data->data()), data->size()); |
| |
| switch (path.getFillType()) { |
| case SkPathFillType::kWinding: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_WINDING); |
| break; |
| case SkPathFillType::kEvenOdd: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, DEBUGCANVAS_FILLTYPE_EVENODD); |
| break; |
| case SkPathFillType::kInverseWinding: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, |
| DEBUGCANVAS_FILLTYPE_INVERSEWINDING); |
| break; |
| case SkPathFillType::kInverseEvenOdd: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_FILLTYPE, |
| DEBUGCANVAS_FILLTYPE_INVERSEEVENODD); |
| break; |
| } |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_VERBS); |
| SkPath::Iter iter(path, false); |
| SkPoint pts[4]; |
| SkPath::Verb verb; |
| while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
| if (verb == SkPath::kClose_Verb) { |
| writer.appendNString(DEBUGCANVAS_VERB_CLOSE); |
| continue; |
| } |
| writer.beginObject(); // verb |
| switch (verb) { |
| case SkPath::kLine_Verb: { |
| writer.appendName(DEBUGCANVAS_VERB_LINE); |
| MakeJsonPoint(writer, pts[1]); |
| break; |
| } |
| case SkPath::kQuad_Verb: { |
| writer.beginArray(DEBUGCANVAS_VERB_QUAD); |
| MakeJsonPoint(writer, pts[1]); |
| MakeJsonPoint(writer, pts[2]); |
| writer.endArray(); // quad coords |
| break; |
| } |
| case SkPath::kCubic_Verb: { |
| writer.beginArray(DEBUGCANVAS_VERB_CUBIC); |
| MakeJsonPoint(writer, pts[1]); |
| MakeJsonPoint(writer, pts[2]); |
| MakeJsonPoint(writer, pts[3]); |
| writer.endArray(); // cubic coords |
| break; |
| } |
| case SkPath::kConic_Verb: { |
| writer.beginArray(DEBUGCANVAS_VERB_CONIC); |
| MakeJsonPoint(writer, pts[1]); |
| MakeJsonPoint(writer, pts[2]); |
| writer.appendFloat(iter.conicWeight()); |
| writer.endArray(); // conic coords |
| break; |
| } |
| case SkPath::kMove_Verb: { |
| writer.appendName(DEBUGCANVAS_VERB_MOVE); |
| MakeJsonPoint(writer, pts[0]); |
| break; |
| } |
| case SkPath::kClose_Verb: |
| case SkPath::kDone_Verb: |
| // Unreachable |
| break; |
| } |
| writer.endObject(); // verb |
| } |
| writer.endArray(); // verbs |
| writer.endObject(); // path |
| } |
| |
| void DrawCommand::MakeJsonRegion(SkJSONWriter& writer, const SkRegion& region) { |
| // TODO: Actually serialize the rectangles, rather than just devolving to path |
| SkPath path; |
| region.getBoundaryPath(&path); |
| MakeJsonPath(writer, path); |
| } |
| |
| void DrawCommand::MakeJsonSampling(SkJSONWriter& writer, const SkSamplingOptions& sampling) { |
| writer.beginObject(); |
| writer.appendS32("maxAniso", sampling.maxAniso); |
| writer.appendBool("useCubic", sampling.useCubic); |
| writer.appendS32("filter", (int)sampling.filter); |
| writer.appendS32("mipmap", (int)sampling.mipmap); |
| writer.appendFloat("cubic.B", sampling.cubic.B); |
| writer.appendFloat("cubic.C", sampling.cubic.C); |
| writer.endObject(); |
| } |
| |
| static const char* clipop_name(SkClipOp op) { |
| switch (op) { |
| case SkClipOp::kDifference: return DEBUGCANVAS_CLIPOP_DIFFERENCE; |
| case SkClipOp::kIntersect: return DEBUGCANVAS_CLIPOP_INTERSECT; |
| default: SkASSERT(false); return "<invalid region op>"; |
| } |
| } |
| |
| static const char* pointmode_name(SkCanvas::PointMode mode) { |
| switch (mode) { |
| case SkCanvas::kPoints_PointMode: return DEBUGCANVAS_POINTMODE_POINTS; |
| case SkCanvas::kLines_PointMode: return DEBUGCANVAS_POINTMODE_LINES; |
| case SkCanvas::kPolygon_PointMode: return DEBUGCANVAS_POINTMODE_POLYGON; |
| default: SkASSERT(false); return "<invalid point mode>"; |
| } |
| } |
| |
| static void store_scalar(SkJSONWriter& writer, |
| const char* key, |
| SkScalar value, |
| SkScalar defaultValue) { |
| if (value != defaultValue) { |
| writer.appendFloat(key, value); |
| } |
| } |
| |
| static void store_bool(SkJSONWriter& writer, const char* key, bool value, bool defaultValue) { |
| if (value != defaultValue) { |
| writer.appendBool(key, value); |
| } |
| } |
| |
| static SkString encode_data(const void* bytes, |
| size_t count, |
| const char* contentType, |
| UrlDataManager& urlDataManager) { |
| sk_sp<SkData> data(SkData::MakeWithCopy(bytes, count)); |
| return urlDataManager.addData(data.get(), contentType); |
| } |
| |
| void DrawCommand::flatten(const SkFlattenable* flattenable, |
| SkJSONWriter& writer, |
| UrlDataManager& urlDataManager) { |
| SkBinaryWriteBuffer buffer({}); // TODO(kjlubick, bungeman) feed SkSerialProcs through API |
| flattenable->flatten(buffer); |
| void* data = sk_malloc_throw(buffer.bytesWritten()); |
| buffer.writeToMemory(data); |
| SkString url = |
| encode_data(data, buffer.bytesWritten(), "application/octet-stream", urlDataManager); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_NAME, flattenable->getTypeName()); |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url); |
| |
| writer.beginObject(DEBUGCANVAS_ATTRIBUTE_VALUES); |
| JsonWriteBuffer jsonBuffer(&writer, &urlDataManager); |
| flattenable->flatten(jsonBuffer); |
| writer.endObject(); // values |
| |
| sk_free(data); |
| } |
| |
| void DrawCommand::WritePNG(const SkBitmap& bitmap, SkWStream& out) { |
| SkPixmap pm; |
| SkAssertResult(bitmap.peekPixels(&pm)); |
| |
| SkPngEncoder::Options options; |
| options.fZLibLevel = 1; |
| options.fFilterFlags = SkPngEncoder::FilterFlag::kNone; |
| SkPngEncoder::Encode(&out, pm, options); |
| } |
| |
| // flattens an image to a Json stream, also called from shader flatten |
| bool DrawCommand::flatten(const SkImage& image, |
| SkJSONWriter& writer, |
| UrlDataManager& urlDataManager) { |
| // For MSKP files, there is no need to encode the image, |
| // just report its id. |
| if (urlDataManager.hasImageIndex()) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_IMAGE_INDEX); |
| writer.appendU64(urlDataManager.lookupImage(&image)); |
| return true; |
| } |
| |
| writer.beginObject(DEBUGCANVAS_ATTRIBUTE_IMAGE); |
| size_t rowBytes = 4 * image.width(); |
| SkAutoMalloc buffer(rowBytes * image.height()); |
| SkImageInfo dstInfo = |
| SkImageInfo::Make(image.dimensions(), kN32_SkColorType, kPremul_SkAlphaType); |
| // "cheat" for this debug tool and use image's context |
| GrDirectContext* dContext = nullptr; |
| #if defined(SK_GANESH) |
| dContext = GrAsDirectContext(as_IB(&image)->context()); |
| #endif |
| if (!image.readPixels(dContext, dstInfo, buffer.get(), rowBytes, 0, 0)) { |
| SkDebugf("DrawCommand::flatten SkImage: readPixels failed\n"); |
| writer.endObject(); |
| return false; |
| } |
| |
| SkBitmap bm; |
| bm.installPixels(dstInfo, buffer.get(), rowBytes); |
| |
| SkDynamicMemoryWStream out; |
| DrawCommand::WritePNG(bm, out); |
| sk_sp<SkData> encoded = out.detachAsData(); |
| if (encoded == nullptr) { |
| SkDebugf("DrawCommand::flatten SkImage: could not encode image as PNG\n"); |
| writer.endObject(); |
| return false; |
| } |
| auto dataPtr = encoded->data(); |
| if (!dataPtr) { |
| SkDebugf("DrawCommand::flatten SkImage: encoding as PNG produced zero length data\n"); |
| writer.endObject(); |
| return false; |
| } |
| SkString url = encode_data(encoded->data(), encoded->size(), "image/png", urlDataManager); |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url); |
| writer.endObject(); |
| return true; |
| } |
| |
| static const char* color_type_name(SkColorType colorType) { |
| switch (colorType) { |
| case kARGB_4444_SkColorType: return DEBUGCANVAS_COLORTYPE_ARGB4444; |
| case kRGBA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_RGBA8888; |
| case kBGRA_8888_SkColorType: return DEBUGCANVAS_COLORTYPE_BGRA8888; |
| case kRGB_565_SkColorType: return DEBUGCANVAS_COLORTYPE_565; |
| case kGray_8_SkColorType: return DEBUGCANVAS_COLORTYPE_GRAY8; |
| case kAlpha_8_SkColorType: return DEBUGCANVAS_COLORTYPE_ALPHA8; |
| default: SkASSERT(false); return DEBUGCANVAS_COLORTYPE_RGBA8888; |
| } |
| } |
| |
| static const char* alpha_type_name(SkAlphaType alphaType) { |
| switch (alphaType) { |
| case kOpaque_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_OPAQUE; |
| case kPremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_PREMUL; |
| case kUnpremul_SkAlphaType: return DEBUGCANVAS_ALPHATYPE_UNPREMUL; |
| default: SkASSERT(false); return DEBUGCANVAS_ALPHATYPE_OPAQUE; |
| } |
| } |
| |
| bool DrawCommand::flatten(const SkBitmap& bitmap, |
| SkJSONWriter& writer, |
| UrlDataManager& urlDataManager) { |
| sk_sp<SkImage> image(bitmap.asImage()); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_COLOR, color_type_name(bitmap.colorType())); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_ALPHA, alpha_type_name(bitmap.alphaType())); |
| // Image will appear to have no uses, TODO(nifong): provide the user with a useful explanation |
| bool success = flatten(*image, writer, urlDataManager); |
| return success; |
| } |
| |
| static void apply_font_hinting(const SkFont& font, SkJSONWriter& writer) { |
| SkFontHinting hinting = font.getHinting(); |
| if (hinting != SkPaintDefaults_Hinting) { |
| switch (hinting) { |
| case SkFontHinting::kNone: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NONE); |
| break; |
| case SkFontHinting::kSlight: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_SLIGHT); |
| break; |
| case SkFontHinting::kNormal: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_NORMAL); |
| break; |
| case SkFontHinting::kFull: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_HINTING, DEBUGCANVAS_HINTING_FULL); |
| break; |
| } |
| } |
| } |
| |
| static void apply_font_edging(const SkFont& font, SkJSONWriter& writer) { |
| switch (font.getEdging()) { |
| case SkFont::Edging::kAlias: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ALIAS); |
| break; |
| case SkFont::Edging::kAntiAlias: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_EDGING, DEBUGCANVAS_EDGING_ANTIALIAS); |
| break; |
| case SkFont::Edging::kSubpixelAntiAlias: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_EDGING, |
| DEBUGCANVAS_EDGING_SUBPIXELANTIALIAS); |
| break; |
| } |
| } |
| |
| static void apply_paint_color(const SkPaint& paint, SkJSONWriter& writer) { |
| SkColor color = paint.getColor(); |
| if (color != SK_ColorBLACK) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR); |
| DrawCommand::MakeJsonColor(writer, color); |
| } |
| } |
| |
| static void apply_paint_style(const SkPaint& paint, SkJSONWriter& writer) { |
| SkPaint::Style style = paint.getStyle(); |
| if (style != SkPaint::kFill_Style) { |
| switch (style) { |
| case SkPaint::kStroke_Style: { |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKE); |
| break; |
| } |
| case SkPaint::kStrokeAndFill_Style: { |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_STYLE_STROKEANDFILL); |
| break; |
| } |
| default: SkASSERT(false); |
| } |
| } |
| } |
| |
| static void apply_paint_cap(const SkPaint& paint, SkJSONWriter& writer) { |
| SkPaint::Cap cap = paint.getStrokeCap(); |
| if (cap != SkPaint::kDefault_Cap) { |
| switch (cap) { |
| case SkPaint::kButt_Cap: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_BUTT); |
| break; |
| case SkPaint::kRound_Cap: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_ROUND); |
| break; |
| case SkPaint::kSquare_Cap: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_CAP, DEBUGCANVAS_CAP_SQUARE); |
| break; |
| default: SkASSERT(false); |
| } |
| } |
| } |
| |
| static void apply_paint_join(const SkPaint& paint, SkJSONWriter& writer) { |
| SkPaint::Join join = paint.getStrokeJoin(); |
| if (join != SkPaint::kDefault_Join) { |
| switch (join) { |
| case SkPaint::kMiter_Join: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_MITER_JOIN); |
| break; |
| case SkPaint::kRound_Join: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_ROUND_JOIN); |
| break; |
| case SkPaint::kBevel_Join: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STROKEJOIN, DEBUGCANVAS_BEVEL_JOIN); |
| break; |
| default: SkASSERT(false); |
| } |
| } |
| } |
| |
| static void apply_paint_maskfilter(const SkPaint& paint, |
| SkJSONWriter& writer, |
| UrlDataManager& urlDataManager) { |
| SkMaskFilter* maskFilter = paint.getMaskFilter(); |
| if (maskFilter != nullptr) { |
| SkMaskFilterBase::BlurRec blurRec; |
| if (as_MFB(maskFilter)->asABlur(&blurRec)) { |
| writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BLUR); |
| writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SIGMA, blurRec.fSigma); |
| switch (blurRec.fStyle) { |
| case SkBlurStyle::kNormal_SkBlurStyle: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_NORMAL); |
| break; |
| case SkBlurStyle::kSolid_SkBlurStyle: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_SOLID); |
| break; |
| case SkBlurStyle::kOuter_SkBlurStyle: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_OUTER); |
| break; |
| case SkBlurStyle::kInner_SkBlurStyle: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_STYLE, DEBUGCANVAS_BLURSTYLE_INNER); |
| break; |
| default: SkASSERT(false); |
| } |
| writer.endObject(); // blur |
| } else { |
| writer.beginObject(DEBUGCANVAS_ATTRIBUTE_MASKFILTER); |
| DrawCommand::flatten(maskFilter, writer, urlDataManager); |
| writer.endObject(); // maskFilter |
| } |
| } |
| } |
| |
| static void apply_paint_patheffect(const SkPaint& paint, |
| SkJSONWriter& writer, |
| UrlDataManager& urlDataManager) { |
| SkPathEffect* pathEffect = paint.getPathEffect(); |
| if (pathEffect != nullptr) { |
| SkPathEffect::DashInfo dashInfo; |
| SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo); |
| if (dashType == SkPathEffect::kDash_DashType) { |
| dashInfo.fIntervals = (SkScalar*)sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar)); |
| pathEffect->asADash(&dashInfo); |
| writer.beginObject(DEBUGCANVAS_ATTRIBUTE_DASHING); |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_INTERVALS, false); |
| for (int32_t i = 0; i < dashInfo.fCount; i++) { |
| writer.appendFloat(dashInfo.fIntervals[i]); |
| } |
| writer.endArray(); // intervals |
| sk_free(dashInfo.fIntervals); |
| writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_PHASE, dashInfo.fPhase); |
| writer.endObject(); // dashing |
| } else { |
| writer.beginObject(DEBUGCANVAS_ATTRIBUTE_PATHEFFECT); |
| DrawCommand::flatten(pathEffect, writer, urlDataManager); |
| writer.endObject(); // pathEffect |
| } |
| } |
| } |
| |
| static void apply_font_typeface(const SkFont& font, |
| SkJSONWriter& writer, |
| UrlDataManager& urlDataManager) { |
| SkTypeface* typeface = font.getTypeface(); |
| if (typeface != nullptr) { |
| writer.beginObject(DEBUGCANVAS_ATTRIBUTE_TYPEFACE); |
| SkDynamicMemoryWStream buffer; |
| typeface->serialize(&buffer); |
| void* data = sk_malloc_throw(buffer.bytesWritten()); |
| buffer.copyTo(data); |
| SkString url = encode_data( |
| data, buffer.bytesWritten(), "application/octet-stream", urlDataManager); |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_DATA, url); |
| sk_free(data); |
| writer.endObject(); |
| } |
| } |
| |
| static void apply_flattenable(const char* key, |
| SkFlattenable* flattenable, |
| SkJSONWriter& writer, |
| UrlDataManager& urlDataManager) { |
| if (flattenable != nullptr) { |
| writer.beginObject(key); |
| DrawCommand::flatten(flattenable, writer, urlDataManager); |
| writer.endObject(); |
| } |
| } |
| |
| void DrawCommand::MakeJsonPaint(SkJSONWriter& writer, |
| const SkPaint& paint, |
| UrlDataManager& urlDataManager) { |
| writer.beginObject(); |
| store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f); |
| store_scalar(writer, |
| DEBUGCANVAS_ATTRIBUTE_STROKEMITER, |
| paint.getStrokeMiter(), |
| SkPaintDefaults_MiterLimit); |
| store_bool(writer, DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false); |
| store_bool(writer, DEBUGCANVAS_ATTRIBUTE_DITHER, paint.isDither(), false); |
| |
| apply_paint_color(paint, writer); |
| apply_paint_style(paint, writer); |
| apply_paint_blend_mode(paint, writer); |
| apply_paint_cap(paint, writer); |
| apply_paint_join(paint, writer); |
| apply_paint_patheffect(paint, writer, urlDataManager); |
| apply_paint_maskfilter(paint, writer, urlDataManager); |
| apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, paint.getShader(), writer, urlDataManager); |
| apply_flattenable( |
| DEBUGCANVAS_ATTRIBUTE_IMAGEFILTER, paint.getImageFilter(), writer, urlDataManager); |
| apply_flattenable( |
| DEBUGCANVAS_ATTRIBUTE_COLORFILTER, paint.getColorFilter(), writer, urlDataManager); |
| writer.endObject(); // paint |
| } |
| |
| static void MakeJsonFont(const SkFont& font, SkJSONWriter& writer, UrlDataManager& urlDataManager) { |
| writer.beginObject(); |
| store_bool(writer, DEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, font.isEmbolden(), false); |
| store_bool(writer, DEBUGCANVAS_ATTRIBUTE_LINEARTEXT, font.isLinearMetrics(), false); |
| store_bool(writer, DEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, font.isSubpixel(), false); |
| store_bool(writer, DEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, font.isEmbeddedBitmaps(), false); |
| store_bool(writer, DEBUGCANVAS_ATTRIBUTE_AUTOHINTING, font.isForceAutoHinting(), false); |
| |
| store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSIZE, font.getSize(), SkPaintDefaults_TextSize); |
| store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getScaleX(), SK_Scalar1); |
| store_scalar(writer, DEBUGCANVAS_ATTRIBUTE_TEXTSCALEX, font.getSkewX(), 0.0f); |
| apply_font_edging(font, writer); |
| apply_font_hinting(font, writer); |
| apply_font_typeface(font, writer, urlDataManager); |
| writer.endObject(); // font |
| } |
| |
| void DrawCommand::MakeJsonLattice(SkJSONWriter& writer, const SkCanvas::Lattice& lattice) { |
| writer.beginObject(); |
| writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEXCOUNT, lattice.fXCount); |
| writer.appendS32(DEBUGCANVAS_ATTRIBUTE_LATTICEYCOUNT, lattice.fYCount); |
| if (nullptr != lattice.fBounds) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS); |
| MakeJsonIRect(writer, *lattice.fBounds); |
| } |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEXDIVS); |
| for (int i = 0; i < lattice.fXCount; i++) { |
| writer.appendS32(lattice.fXDivs[i]); |
| } |
| writer.endArray(); // xdivs |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEYDIVS); |
| for (int i = 0; i < lattice.fYCount; i++) { |
| writer.appendS32(lattice.fYDivs[i]); |
| } |
| writer.endArray(); // ydivs |
| if (nullptr != lattice.fRectTypes) { |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_LATTICEFLAGS); |
| int flagCount = 0; |
| for (int row = 0; row < lattice.fYCount + 1; row++) { |
| writer.beginArray(); |
| for (int column = 0; column < lattice.fXCount + 1; column++) { |
| writer.appendS32(lattice.fRectTypes[flagCount++]); |
| } |
| writer.endArray(); // row |
| } |
| writer.endArray(); |
| } |
| writer.endObject(); |
| } |
| |
| ClearCommand::ClearCommand(SkColor color) : INHERITED(kClear_OpType) { fColor = color; } |
| |
| void ClearCommand::execute(SkCanvas* canvas) const { canvas->clear(fColor); } |
| |
| void ClearCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COLOR); |
| MakeJsonColor(writer, fColor); |
| } |
| |
| ClipPathCommand::ClipPathCommand(const SkPath& path, SkClipOp op, bool doAA) |
| : INHERITED(kClipPath_OpType) { |
| fPath = path; |
| fOp = op; |
| fDoAA = doAA; |
| } |
| |
| void ClipPathCommand::execute(SkCanvas* canvas) const { canvas->clipPath(fPath, fOp, fDoAA); } |
| |
| bool ClipPathCommand::render(SkCanvas* canvas) const { |
| render_path(canvas, fPath); |
| return true; |
| } |
| |
| void ClipPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH); |
| MakeJsonPath(writer, fPath); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp)); |
| writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA); |
| } |
| |
| ClipRegionCommand::ClipRegionCommand(const SkRegion& region, SkClipOp op) |
| : INHERITED(kClipRegion_OpType) { |
| fRegion = region; |
| fOp = op; |
| } |
| |
| void ClipRegionCommand::execute(SkCanvas* canvas) const { canvas->clipRegion(fRegion, fOp); } |
| |
| void ClipRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION); |
| MakeJsonRegion(writer, fRegion); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp)); |
| } |
| |
| ClipRectCommand::ClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA) |
| : INHERITED(kClipRect_OpType) { |
| fRect = rect; |
| fOp = op; |
| fDoAA = doAA; |
| } |
| |
| void ClipRectCommand::execute(SkCanvas* canvas) const { canvas->clipRect(fRect, fOp, fDoAA); } |
| |
| void ClipRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| MakeJsonRect(writer, fRect); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp)); |
| writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA); |
| |
| SkString desc; |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, *str_append(&desc, fRect)); |
| } |
| |
| ClipRRectCommand::ClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA) |
| : INHERITED(kClipRRect_OpType) { |
| fRRect = rrect; |
| fOp = op; |
| fDoAA = doAA; |
| } |
| |
| void ClipRRectCommand::execute(SkCanvas* canvas) const { canvas->clipRRect(fRRect, fOp, fDoAA); } |
| |
| bool ClipRRectCommand::render(SkCanvas* canvas) const { |
| render_rrect(canvas, fRRect); |
| return true; |
| } |
| |
| void ClipRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| make_json_rrect(writer, fRRect); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp)); |
| writer.appendBool(DEBUGCANVAS_ATTRIBUTE_ANTIALIAS, fDoAA); |
| } |
| |
| ClipShaderCommand::ClipShaderCommand(sk_sp<SkShader> cs, SkClipOp op) |
| : INHERITED(kClipShader_OpType) { |
| fShader = std::move(cs); |
| fOp = op; |
| } |
| |
| void ClipShaderCommand::execute(SkCanvas* canvas) const { canvas->clipShader(fShader, fOp); } |
| |
| bool ClipShaderCommand::render(SkCanvas* canvas) const { |
| SkPaint paint; |
| paint.setShader(fShader); |
| canvas->drawPaint(paint); |
| return true; |
| } |
| |
| void ClipShaderCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| apply_flattenable(DEBUGCANVAS_ATTRIBUTE_SHADER, fShader.get(), writer, urlDataManager); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_REGIONOP, clipop_name(fOp)); |
| } |
| |
| ResetClipCommand::ResetClipCommand() : INHERITED(kResetClip_OpType) {} |
| |
| void ResetClipCommand::execute(SkCanvas* canvas) const { SkCanvasPriv::ResetClip(canvas); } |
| |
| ConcatCommand::ConcatCommand(const SkMatrix& matrix) : INHERITED(kConcat_OpType) { |
| fMatrix = matrix; |
| } |
| |
| void ConcatCommand::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); } |
| |
| namespace { |
| void writeMatrixType(SkJSONWriter& writer, const SkMatrix& m) { |
| switch (m.getType()) { |
| case SkMatrix::kTranslate_Mask: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (translate)"); |
| break; |
| case SkMatrix::kScale_Mask: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (scale)"); |
| break; |
| case SkMatrix::kAffine_Mask: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (rotation or skew)"); |
| break; |
| case SkMatrix::kPerspective_Mask: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, " (perspective)"); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| void ConcatCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX); |
| MakeJsonMatrix(writer, fMatrix); |
| writeMatrixType(writer, fMatrix); |
| } |
| |
| Concat44Command::Concat44Command(const SkM44& matrix) : INHERITED(kConcat44_OpType) { |
| fMatrix = matrix; |
| } |
| |
| void Concat44Command::execute(SkCanvas* canvas) const { canvas->concat(fMatrix); } |
| |
| void Concat44Command::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX); |
| MakeJsonMatrix44(writer, fMatrix); |
| } |
| |
| //// |
| |
| DrawAnnotationCommand::DrawAnnotationCommand(const SkRect& rect, |
| const char key[], |
| sk_sp<SkData> value) |
| : INHERITED(kDrawAnnotation_OpType), fRect(rect), fKey(key), fValue(std::move(value)) {} |
| |
| void DrawAnnotationCommand::execute(SkCanvas* canvas) const { |
| canvas->drawAnnotation(fRect, fKey.c_str(), fValue); |
| } |
| |
| void DrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| MakeJsonRect(writer, fRect); |
| writer.appendString("key", fKey); |
| if (fValue) { |
| writer.appendString("value", static_cast<const char*>(fValue->data()), fValue->size()); |
| } |
| |
| SkString desc; |
| str_append(&desc, fRect)->appendf(" %s", fKey.c_str()); |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, desc); |
| } |
| |
| //// |
| |
| DrawImageCommand::DrawImageCommand(const SkImage* image, |
| SkScalar left, |
| SkScalar top, |
| const SkSamplingOptions& sampling, |
| const SkPaint* paint) |
| : INHERITED(kDrawImage_OpType) |
| , fImage(SkRef(image)) |
| , fLeft(left) |
| , fTop(top) |
| , fSampling(sampling) |
| , fPaint(paint) {} |
| |
| void DrawImageCommand::execute(SkCanvas* canvas) const { |
| canvas->drawImage(fImage.get(), fLeft, fTop, fSampling, fPaint.getMaybeNull()); |
| } |
| |
| bool DrawImageCommand::render(SkCanvas* canvas) const { |
| SkAutoCanvasRestore acr(canvas, true); |
| canvas->clear(0xFFFFFFFF); |
| |
| xlate_and_scale_to_bounds( |
| canvas, |
| SkRect::MakeXYWH( |
| fLeft, fTop, SkIntToScalar(fImage->width()), SkIntToScalar(fImage->height()))); |
| this->execute(canvas); |
| return true; |
| } |
| |
| uint64_t DrawImageCommand::imageId(UrlDataManager& udm) const { |
| return udm.lookupImage(fImage.get()); |
| } |
| |
| void DrawImageCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| flatten(*fImage, writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| MakeJsonPoint(writer, fLeft, fTop); |
| if (fPaint.isValid()) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, *fPaint, urlDataManager); |
| } |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_SAMPLING); |
| MakeJsonSampling(writer, fSampling); |
| |
| writer.appendU32(DEBUGCANVAS_ATTRIBUTE_UNIQUE_ID, fImage->uniqueID()); |
| writer.appendS32(DEBUGCANVAS_ATTRIBUTE_WIDTH, fImage->width()); |
| writer.appendS32(DEBUGCANVAS_ATTRIBUTE_HEIGHT, fImage->height()); |
| switch (fImage->alphaType()) { |
| case kOpaque_SkAlphaType: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_OPAQUE); |
| break; |
| case kPremul_SkAlphaType: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_PREMUL); |
| break; |
| case kUnpremul_SkAlphaType: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNPREMUL); |
| break; |
| default: |
| writer.appendNString(DEBUGCANVAS_ATTRIBUTE_ALPHA, DEBUGCANVAS_ALPHATYPE_UNKNOWN); |
| break; |
| } |
| } |
| |
| DrawImageLatticeCommand::DrawImageLatticeCommand(const SkImage* image, |
| const SkCanvas::Lattice& lattice, |
| const SkRect& dst, |
| SkFilterMode filter, |
| const SkPaint* paint) |
| : INHERITED(kDrawImageLattice_OpType) |
| , fImage(SkRef(image)) |
| , fLattice(lattice) |
| , fDst(dst) |
| , fFilter(filter) |
| , fPaint(paint) {} |
| |
| void DrawImageLatticeCommand::execute(SkCanvas* canvas) const { |
| canvas->drawImageLattice(fImage.get(), fLattice, fDst, fFilter, fPaint.getMaybeNull()); |
| } |
| |
| bool DrawImageLatticeCommand::render(SkCanvas* canvas) const { |
| SkAutoCanvasRestore acr(canvas, true); |
| canvas->clear(0xFFFFFFFF); |
| |
| xlate_and_scale_to_bounds(canvas, fDst); |
| |
| this->execute(canvas); |
| return true; |
| } |
| |
| uint64_t DrawImageLatticeCommand::imageId(UrlDataManager& udm) const { |
| return udm.lookupImage(fImage.get()); |
| } |
| |
| void DrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| flatten(*fImage, writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_LATTICE); |
| MakeJsonLattice(writer, fLattice); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST); |
| MakeJsonRect(writer, fDst); |
| if (fPaint.isValid()) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, *fPaint, urlDataManager); |
| } |
| |
| SkString desc; |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, *str_append(&desc, fDst)); |
| } |
| |
| DrawImageRectCommand::DrawImageRectCommand(const SkImage* image, |
| const SkRect& src, |
| const SkRect& dst, |
| const SkSamplingOptions& sampling, |
| const SkPaint* paint, |
| SkCanvas::SrcRectConstraint constraint) |
| : INHERITED(kDrawImageRect_OpType) |
| , fImage(SkRef(image)) |
| , fSrc(src) |
| , fDst(dst) |
| , fSampling(sampling) |
| , fPaint(paint) |
| , fConstraint(constraint) {} |
| |
| void DrawImageRectCommand::execute(SkCanvas* canvas) const { |
| canvas->drawImageRect(fImage.get(), fSrc, fDst, fSampling, fPaint.getMaybeNull(), fConstraint); |
| } |
| |
| bool DrawImageRectCommand::render(SkCanvas* canvas) const { |
| SkAutoCanvasRestore acr(canvas, true); |
| canvas->clear(0xFFFFFFFF); |
| |
| xlate_and_scale_to_bounds(canvas, fDst); |
| |
| this->execute(canvas); |
| return true; |
| } |
| |
| uint64_t DrawImageRectCommand::imageId(UrlDataManager& udm) const { |
| return udm.lookupImage(fImage.get()); |
| } |
| |
| void DrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| flatten(*fImage, writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC); |
| MakeJsonRect(writer, fSrc); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST); |
| MakeJsonRect(writer, fDst); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_SAMPLING); |
| MakeJsonSampling(writer, fSampling); |
| if (fPaint.isValid()) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, *fPaint, urlDataManager); |
| } |
| if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) { |
| writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true); |
| } |
| |
| SkString desc; |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, *str_append(&desc, fDst)); |
| } |
| |
| DrawImageRectLayerCommand::DrawImageRectLayerCommand(DebugLayerManager* layerManager, |
| const int nodeId, |
| const int frame, |
| const SkRect& src, |
| const SkRect& dst, |
| const SkSamplingOptions& sampling, |
| const SkPaint* paint, |
| SkCanvas::SrcRectConstraint constraint) |
| : INHERITED(kDrawImageRectLayer_OpType) |
| , fLayerManager(layerManager) |
| , fNodeId(nodeId) |
| , fFrame(frame) |
| , fSrc(src) |
| , fDst(dst) |
| , fSampling(sampling) |
| , fPaint(paint) |
| , fConstraint(constraint) {} |
| |
| void DrawImageRectLayerCommand::execute(SkCanvas* canvas) const { |
| sk_sp<SkImage> snapshot = fLayerManager->getLayerAsImage(fNodeId, fFrame); |
| canvas->drawImageRect(snapshot.get(), fSrc, fDst, SkSamplingOptions(), fPaint.getMaybeNull(), fConstraint); |
| } |
| |
| bool DrawImageRectLayerCommand::render(SkCanvas* canvas) const { |
| SkAutoCanvasRestore acr(canvas, true); |
| canvas->clear(0xFFFFFFFF); |
| |
| xlate_and_scale_to_bounds(canvas, fDst); |
| |
| this->execute(canvas); |
| return true; |
| } |
| |
| void DrawImageRectLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| |
| // Don't append an image attribute here, the image can be rendered in as many different ways |
| // as there are commands in the layer, at least. the urlDataManager would save each one under |
| // a different URL. |
| // Append the node id, and the layer inspector of the debugger will know what to do with it. |
| writer.appendS64(DEBUGCANVAS_ATTRIBUTE_LAYERNODEID, fNodeId); |
| |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC); |
| MakeJsonRect(writer, fSrc); |
| |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST); |
| MakeJsonRect(writer, fDst); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_SAMPLING); |
| MakeJsonSampling(writer, fSampling); |
| if (fPaint.isValid()) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, *fPaint, urlDataManager); |
| } |
| if (fConstraint == SkCanvas::kStrict_SrcRectConstraint) { |
| writer.appendBool(DEBUGCANVAS_ATTRIBUTE_STRICT, true); |
| } |
| |
| SkString desc; |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, *str_append(&desc, fDst)); |
| } |
| |
| DrawOvalCommand::DrawOvalCommand(const SkRect& oval, const SkPaint& paint) |
| : INHERITED(kDrawOval_OpType) { |
| fOval = oval; |
| fPaint = paint; |
| } |
| |
| void DrawOvalCommand::execute(SkCanvas* canvas) const { canvas->drawOval(fOval, fPaint); } |
| |
| bool DrawOvalCommand::render(SkCanvas* canvas) const { |
| canvas->clear(0xFFFFFFFF); |
| canvas->save(); |
| |
| xlate_and_scale_to_bounds(canvas, fOval); |
| |
| SkPaint p; |
| p.setColor(SK_ColorBLACK); |
| p.setStyle(SkPaint::kStroke_Style); |
| |
| canvas->drawOval(fOval, p); |
| canvas->restore(); |
| |
| return true; |
| } |
| |
| void DrawOvalCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| MakeJsonRect(writer, fOval); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| DrawArcCommand::DrawArcCommand(const SkRect& oval, |
| SkScalar startAngle, |
| SkScalar sweepAngle, |
| bool useCenter, |
| const SkPaint& paint) |
| : INHERITED(kDrawArc_OpType) { |
| fOval = oval; |
| fStartAngle = startAngle; |
| fSweepAngle = sweepAngle; |
| fUseCenter = useCenter; |
| fPaint = paint; |
| } |
| |
| void DrawArcCommand::execute(SkCanvas* canvas) const { |
| canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, fPaint); |
| } |
| |
| bool DrawArcCommand::render(SkCanvas* canvas) const { |
| canvas->clear(0xFFFFFFFF); |
| canvas->save(); |
| |
| xlate_and_scale_to_bounds(canvas, fOval); |
| |
| SkPaint p; |
| p.setColor(SK_ColorBLACK); |
| p.setStyle(SkPaint::kStroke_Style); |
| |
| canvas->drawArc(fOval, fStartAngle, fSweepAngle, fUseCenter, p); |
| canvas->restore(); |
| |
| return true; |
| } |
| |
| void DrawArcCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| MakeJsonRect(writer, fOval); |
| writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_STARTANGLE, fStartAngle); |
| writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_SWEEPANGLE, fSweepAngle); |
| writer.appendBool(DEBUGCANVAS_ATTRIBUTE_USECENTER, fUseCenter); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| DrawPaintCommand::DrawPaintCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) { |
| fPaint = paint; |
| } |
| |
| void DrawPaintCommand::execute(SkCanvas* canvas) const { canvas->drawPaint(fPaint); } |
| |
| bool DrawPaintCommand::render(SkCanvas* canvas) const { |
| canvas->clear(0xFFFFFFFF); |
| canvas->drawPaint(fPaint); |
| return true; |
| } |
| |
| void DrawPaintCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| DrawBehindCommand::DrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) { |
| fPaint = paint; |
| } |
| |
| void DrawBehindCommand::execute(SkCanvas* canvas) const { |
| SkCanvasPriv::DrawBehind(canvas, fPaint); |
| } |
| |
| bool DrawBehindCommand::render(SkCanvas* canvas) const { |
| canvas->clear(0xFFFFFFFF); |
| SkCanvasPriv::DrawBehind(canvas, fPaint); |
| return true; |
| } |
| |
| void DrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| DrawPathCommand::DrawPathCommand(const SkPath& path, const SkPaint& paint) |
| : INHERITED(kDrawPath_OpType) { |
| fPath = path; |
| fPaint = paint; |
| } |
| |
| void DrawPathCommand::execute(SkCanvas* canvas) const { canvas->drawPath(fPath, fPaint); } |
| |
| bool DrawPathCommand::render(SkCanvas* canvas) const { |
| render_path(canvas, fPath); |
| return true; |
| } |
| |
| void DrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH); |
| MakeJsonPath(writer, fPath); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| DrawRegionCommand::DrawRegionCommand(const SkRegion& region, const SkPaint& paint) |
| : INHERITED(kDrawRegion_OpType) { |
| fRegion = region; |
| fPaint = paint; |
| } |
| |
| void DrawRegionCommand::execute(SkCanvas* canvas) const { canvas->drawRegion(fRegion, fPaint); } |
| |
| bool DrawRegionCommand::render(SkCanvas* canvas) const { |
| render_region(canvas, fRegion); |
| return true; |
| } |
| |
| void DrawRegionCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_REGION); |
| MakeJsonRegion(writer, fRegion); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| BeginDrawPictureCommand::BeginDrawPictureCommand(const SkPicture* picture, |
| const SkMatrix* matrix, |
| const SkPaint* paint) |
| : INHERITED(kBeginDrawPicture_OpType) |
| , fPicture(SkRef(picture)) |
| , fMatrix(matrix) |
| , fPaint(paint) {} |
| |
| void BeginDrawPictureCommand::execute(SkCanvas* canvas) const { |
| if (fPaint.isValid()) { |
| SkRect bounds = fPicture->cullRect(); |
| if (fMatrix.isValid()) { |
| fMatrix->mapRect(&bounds); |
| } |
| canvas->saveLayer(&bounds, fPaint.get()); |
| } |
| |
| if (fMatrix.isValid()) { |
| if (!fPaint.isValid()) { |
| canvas->save(); |
| } |
| canvas->concat(*fMatrix); |
| } |
| } |
| |
| bool BeginDrawPictureCommand::render(SkCanvas* canvas) const { |
| canvas->clear(0xFFFFFFFF); |
| canvas->save(); |
| |
| xlate_and_scale_to_bounds(canvas, fPicture->cullRect()); |
| |
| canvas->drawPicture(fPicture.get()); |
| |
| canvas->restore(); |
| |
| return true; |
| } |
| |
| EndDrawPictureCommand::EndDrawPictureCommand(bool restore) |
| : INHERITED(kEndDrawPicture_OpType), fRestore(restore) {} |
| |
| void EndDrawPictureCommand::execute(SkCanvas* canvas) const { |
| if (fRestore) { |
| canvas->restore(); |
| } |
| } |
| |
| DrawPointsCommand::DrawPointsCommand(SkCanvas::PointMode mode, |
| size_t count, |
| const SkPoint pts[], |
| const SkPaint& paint) |
| : INHERITED(kDrawPoints_OpType), fMode(mode), fPts(pts, count), fPaint(paint) {} |
| |
| void DrawPointsCommand::execute(SkCanvas* canvas) const { |
| canvas->drawPoints(fMode, fPts.size(), fPts.begin(), fPaint); |
| } |
| |
| bool DrawPointsCommand::render(SkCanvas* canvas) const { |
| canvas->clear(0xFFFFFFFF); |
| canvas->save(); |
| |
| SkRect bounds; |
| |
| bounds.setEmpty(); |
| for (int i = 0; i < fPts.size(); ++i) { |
| SkRectPriv::GrowToInclude(&bounds, fPts[i]); |
| } |
| |
| xlate_and_scale_to_bounds(canvas, bounds); |
| |
| SkPaint p; |
| p.setColor(SK_ColorBLACK); |
| p.setStyle(SkPaint::kStroke_Style); |
| |
| canvas->drawPoints(fMode, fPts.size(), fPts.begin(), p); |
| canvas->restore(); |
| |
| return true; |
| } |
| |
| void DrawPointsCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendCString(DEBUGCANVAS_ATTRIBUTE_MODE, pointmode_name(fMode)); |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POINTS); |
| for (int i = 0; i < fPts.size(); i++) { |
| MakeJsonPoint(writer, fPts[i]); |
| } |
| writer.endArray(); // points |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| DrawTextBlobCommand::DrawTextBlobCommand(sk_sp<SkTextBlob> blob, |
| SkScalar x, |
| SkScalar y, |
| const SkPaint& paint) |
| : INHERITED(kDrawTextBlob_OpType) |
| , fBlob(std::move(blob)) |
| , fXPos(x) |
| , fYPos(y) |
| , fPaint(paint) {} |
| |
| void DrawTextBlobCommand::execute(SkCanvas* canvas) const { |
| canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint); |
| } |
| |
| bool DrawTextBlobCommand::render(SkCanvas* canvas) const { |
| canvas->clear(SK_ColorWHITE); |
| canvas->save(); |
| |
| SkRect bounds = fBlob->bounds().makeOffset(fXPos, fYPos); |
| xlate_and_scale_to_bounds(canvas, bounds); |
| |
| canvas->drawTextBlob(fBlob, fXPos, fYPos, fPaint); |
| |
| canvas->restore(); |
| |
| return true; |
| } |
| |
| void DrawTextBlobCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_X, fXPos); |
| writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_Y, fYPos); |
| SkRect bounds = fBlob->bounds(); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS); |
| MakeJsonRect(writer, bounds); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_RUNS); |
| SkTextBlobRunIterator iter(fBlob.get()); |
| while (!iter.done()) { |
| writer.beginObject(); // run |
| if (iter.textSize()) { |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_TEXT, iter.text(), iter.textSize()); |
| } |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_FONT); |
| MakeJsonFont(iter.font(), writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| MakeJsonPoint(writer, iter.offset()); |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_GLYPHS); |
| for (uint32_t i = 0; i < iter.glyphCount(); i++) { |
| writer.appendU32(iter.glyphs()[i]); |
| } |
| writer.endArray(); // glyphs |
| if (iter.positioning() != SkTextBlobRunIterator::kDefault_Positioning) { |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_POSITIONS); |
| const SkScalar* iterPositions = iter.pos(); |
| for (uint32_t i = 0; i < iter.glyphCount(); i++) { |
| switch (iter.positioning()) { |
| case SkTextBlobRunIterator::kFull_Positioning: |
| MakeJsonPoint(writer, iterPositions[i * 2], iterPositions[i * 2 + 1]); |
| break; |
| case SkTextBlobRunIterator::kHorizontal_Positioning: |
| writer.appendFloat(iterPositions[i]); |
| break; |
| case SkTextBlobRunIterator::kDefault_Positioning: break; |
| case SkTextBlobRunIterator::kRSXform_Positioning: |
| // TODO_RSXFORM_BLOB |
| break; |
| } |
| } |
| writer.endArray(); // positions |
| } |
| if (iter.clusters()) { |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_CLUSTERS); |
| for (uint32_t i = 0; i < iter.glyphCount(); i++) { |
| writer.appendU32(iter.clusters()[i]); |
| } |
| writer.endArray(); // clusters |
| } |
| writer.endObject(); // run |
| iter.next(); |
| } |
| writer.endArray(); // runs |
| |
| SkString desc; |
| // make the bounds local by applying the x,y |
| bounds.offset(fXPos, fYPos); |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, *str_append(&desc, bounds)); |
| } |
| |
| DrawPatchCommand::DrawPatchCommand(const SkPoint cubics[12], |
| const SkColor colors[4], |
| const SkPoint texCoords[4], |
| SkBlendMode bmode, |
| const SkPaint& paint) |
| : INHERITED(kDrawPatch_OpType), fBlendMode(bmode) { |
| memcpy(fCubics, cubics, sizeof(fCubics)); |
| if (colors != nullptr) { |
| memcpy(fColors, colors, sizeof(fColors)); |
| fColorsPtr = fColors; |
| } else { |
| fColorsPtr = nullptr; |
| } |
| if (texCoords != nullptr) { |
| memcpy(fTexCoords, texCoords, sizeof(fTexCoords)); |
| fTexCoordsPtr = fTexCoords; |
| } else { |
| fTexCoordsPtr = nullptr; |
| } |
| fPaint = paint; |
| } |
| |
| void DrawPatchCommand::execute(SkCanvas* canvas) const { |
| canvas->drawPatch(fCubics, fColorsPtr, fTexCoordsPtr, fBlendMode, fPaint); |
| } |
| |
| void DrawPatchCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_CUBICS); |
| for (int i = 0; i < 12; i++) { |
| MakeJsonPoint(writer, fCubics[i]); |
| } |
| writer.endArray(); // cubics |
| if (fColorsPtr != nullptr) { |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_COLORS); |
| for (int i = 0; i < 4; i++) { |
| MakeJsonColor(writer, fColorsPtr[i]); |
| } |
| writer.endArray(); // colors |
| } |
| if (fTexCoordsPtr != nullptr) { |
| writer.beginArray(DEBUGCANVAS_ATTRIBUTE_TEXTURECOORDS); |
| for (int i = 0; i < 4; i++) { |
| MakeJsonPoint(writer, fTexCoords[i]); |
| } |
| writer.endArray(); // texCoords |
| } |
| // fBlendMode |
| } |
| |
| DrawRectCommand::DrawRectCommand(const SkRect& rect, const SkPaint& paint) |
| : INHERITED(kDrawRect_OpType) { |
| fRect = rect; |
| fPaint = paint; |
| } |
| |
| void DrawRectCommand::execute(SkCanvas* canvas) const { canvas->drawRect(fRect, fPaint); } |
| |
| void DrawRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| MakeJsonRect(writer, fRect); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| |
| SkString desc; |
| writer.appendString(DEBUGCANVAS_ATTRIBUTE_SHORTDESC, *str_append(&desc, fRect)); |
| } |
| |
| DrawRRectCommand::DrawRRectCommand(const SkRRect& rrect, const SkPaint& paint) |
| : INHERITED(kDrawRRect_OpType) { |
| fRRect = rrect; |
| fPaint = paint; |
| } |
| |
| void DrawRRectCommand::execute(SkCanvas* canvas) const { canvas->drawRRect(fRRect, fPaint); } |
| |
| bool DrawRRectCommand::render(SkCanvas* canvas) const { |
| render_rrect(canvas, fRRect); |
| return true; |
| } |
| |
| void DrawRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_COORDS); |
| make_json_rrect(writer, fRRect); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| DrawDRRectCommand::DrawDRRectCommand(const SkRRect& outer, |
| const SkRRect& inner, |
| const SkPaint& paint) |
| : INHERITED(kDrawDRRect_OpType) { |
| fOuter = outer; |
| fInner = inner; |
| fPaint = paint; |
| } |
| |
| void DrawDRRectCommand::execute(SkCanvas* canvas) const { |
| canvas->drawDRRect(fOuter, fInner, fPaint); |
| } |
| |
| bool DrawDRRectCommand::render(SkCanvas* canvas) const { |
| render_drrect(canvas, fOuter, fInner); |
| return true; |
| } |
| |
| void DrawDRRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_OUTER); |
| make_json_rrect(writer, fOuter); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_INNER); |
| make_json_rrect(writer, fInner); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, fPaint, urlDataManager); |
| } |
| |
| DrawShadowCommand::DrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec) |
| : INHERITED(kDrawShadow_OpType) { |
| fPath = path; |
| fShadowRec = rec; |
| } |
| |
| void DrawShadowCommand::execute(SkCanvas* canvas) const { |
| canvas->private_draw_shadow_rec(fPath, fShadowRec); |
| } |
| |
| bool DrawShadowCommand::render(SkCanvas* canvas) const { |
| render_shadow(canvas, fPath, fShadowRec); |
| return true; |
| } |
| |
| void DrawShadowCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| |
| bool geometricOnly = SkToBool(fShadowRec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag); |
| bool transparentOccluder = |
| SkToBool(fShadowRec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag); |
| |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PATH); |
| MakeJsonPath(writer, fPath); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_ZPLANE); |
| MakeJsonPoint3(writer, fShadowRec.fZPlaneParams); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_LIGHTPOSITION); |
| MakeJsonPoint3(writer, fShadowRec.fLightPos); |
| writer.appendFloat(DEBUGCANVAS_ATTRIBUTE_LIGHTRADIUS, fShadowRec.fLightRadius); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_AMBIENTCOLOR); |
| MakeJsonColor(writer, fShadowRec.fAmbientColor); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_SPOTCOLOR); |
| MakeJsonColor(writer, fShadowRec.fSpotColor); |
| store_bool(writer, DEBUGCANVAS_SHADOWFLAG_TRANSPARENT_OCC, transparentOccluder, false); |
| store_bool(writer, DEBUGCANVAS_SHADOWFLAG_GEOMETRIC_ONLY, geometricOnly, false); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| DrawEdgeAAQuadCommand::DrawEdgeAAQuadCommand(const SkRect& rect, |
| const SkPoint clip[4], |
| SkCanvas::QuadAAFlags aa, |
| const SkColor4f& color, |
| SkBlendMode mode) |
| : INHERITED(kDrawEdgeAAQuad_OpType) |
| , fRect(rect) |
| , fHasClip(clip != nullptr) |
| , fAA(aa) |
| , fColor(color) |
| , fMode(mode) { |
| if (clip) { |
| for (int i = 0; i < 4; ++i) { |
| fClip[i] = clip[i]; |
| } |
| } |
| } |
| |
| void DrawEdgeAAQuadCommand::execute(SkCanvas* canvas) const { |
| canvas->experimental_DrawEdgeAAQuad(fRect, fHasClip ? fClip : nullptr, fAA, fColor, fMode); |
| } |
| |
| DrawEdgeAAImageSetCommand::DrawEdgeAAImageSetCommand(const SkCanvas::ImageSetEntry set[], |
| int count, |
| const SkPoint dstClips[], |
| const SkMatrix preViewMatrices[], |
| const SkSamplingOptions& sampling, |
| const SkPaint* paint, |
| SkCanvas::SrcRectConstraint constraint) |
| : INHERITED(kDrawEdgeAAImageSet_OpType) |
| , fSet(count) |
| , fCount(count) |
| , fSampling(sampling) |
| , fPaint(paint) |
| , fConstraint(constraint) { |
| int totalDstClipCount, totalMatrixCount; |
| SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount); |
| |
| std::copy_n(set, count, fSet.get()); |
| fDstClips.reset(totalDstClipCount); |
| std::copy_n(dstClips, totalDstClipCount, fDstClips.get()); |
| fPreViewMatrices.reset(totalMatrixCount); |
| std::copy_n(preViewMatrices, totalMatrixCount, fPreViewMatrices.get()); |
| } |
| |
| void DrawEdgeAAImageSetCommand::execute(SkCanvas* canvas) const { |
| canvas->experimental_DrawEdgeAAImageSet(fSet.get(), |
| fCount, |
| fDstClips.get(), |
| fPreViewMatrices.get(), |
| fSampling, |
| fPaint.getMaybeNull(), |
| fConstraint); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| DrawDrawableCommand::DrawDrawableCommand(SkDrawable* drawable, const SkMatrix* matrix) |
| : INHERITED(kDrawDrawable_OpType), fDrawable(SkRef(drawable)), fMatrix(matrix) {} |
| |
| void DrawDrawableCommand::execute(SkCanvas* canvas) const { |
| canvas->drawDrawable(fDrawable.get(), fMatrix.getMaybeNull()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| DrawVerticesCommand::DrawVerticesCommand(sk_sp<SkVertices> vertices, |
| SkBlendMode bmode, |
| const SkPaint& paint) |
| : INHERITED(kDrawVertices_OpType) |
| , fVertices(std::move(vertices)) |
| , fBlendMode(bmode) |
| , fPaint(paint) {} |
| |
| void DrawVerticesCommand::execute(SkCanvas* canvas) const { |
| canvas->drawVertices(fVertices, fBlendMode, fPaint); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| DrawAtlasCommand::DrawAtlasCommand(const SkImage* image, |
| const SkRSXform xform[], |
| const SkRect tex[], |
| const SkColor colors[], |
| int count, |
| SkBlendMode bmode, |
| const SkSamplingOptions& sampling, |
| const SkRect* cull, |
| const SkPaint* paint) |
| : INHERITED(kDrawAtlas_OpType) |
| , fImage(SkRef(image)) |
| , fXform(xform, count) |
| , fTex(tex, count) |
| , fColors(colors, colors ? count : 0) |
| , fBlendMode(bmode) |
| , fSampling(sampling) |
| , fCull(cull) |
| , fPaint(paint) {} |
| |
| void DrawAtlasCommand::execute(SkCanvas* canvas) const { |
| canvas->drawAtlas(fImage.get(), |
| fXform.begin(), |
| fTex.begin(), |
| fColors.empty() ? nullptr : fColors.begin(), |
| fXform.size(), |
| fBlendMode, |
| fSampling, |
| fCull.getMaybeNull(), |
| fPaint.getMaybeNull()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| RestoreCommand::RestoreCommand() : INHERITED(kRestore_OpType) {} |
| |
| void RestoreCommand::execute(SkCanvas* canvas) const { canvas->restore(); } |
| |
| SaveCommand::SaveCommand() : INHERITED(kSave_OpType) {} |
| |
| void SaveCommand::execute(SkCanvas* canvas) const { canvas->save(); } |
| |
| SaveLayerCommand::SaveLayerCommand(const SkCanvas::SaveLayerRec& rec) |
| : INHERITED(kSaveLayer_OpType) |
| , fBounds(rec.fBounds) |
| , fPaint(rec.fPaint) |
| , fBackdrop(SkSafeRef(rec.fBackdrop)) |
| , fSaveLayerFlags(rec.fSaveLayerFlags) |
| , fBackdropScale(SkCanvasPriv::GetBackdropScaleFactor(rec)) {} |
| |
| void SaveLayerCommand::execute(SkCanvas* canvas) const { |
| // In the common case fBackdropScale == 1.f and then this is no different than a regular Rec |
| canvas->saveLayer(SkCanvasPriv::ScaledBackdropLayer(fBounds.getMaybeNull(), |
| fPaint.getMaybeNull(), |
| fBackdrop.get(), |
| fBackdropScale, |
| fSaveLayerFlags)); |
| } |
| |
| void SaveLayerCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| if (fBounds.isValid()) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_BOUNDS); |
| MakeJsonRect(writer, *fBounds); |
| } |
| if (fPaint.isValid()) { |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_PAINT); |
| MakeJsonPaint(writer, *fPaint, urlDataManager); |
| } |
| if (fBackdrop != nullptr) { |
| writer.beginObject(DEBUGCANVAS_ATTRIBUTE_BACKDROP); |
| flatten(fBackdrop.get(), writer, urlDataManager); |
| writer.endObject(); // backdrop |
| } |
| if (fSaveLayerFlags != 0) { |
| SkDebugf("unsupported: saveLayer flags\n"); |
| SkASSERT(false); |
| } |
| } |
| |
| SetMatrixCommand::SetMatrixCommand(const SkMatrix& matrix) : INHERITED(kSetMatrix_OpType) { |
| fMatrix = matrix; |
| } |
| |
| void SetMatrixCommand::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); } |
| |
| void SetMatrixCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX); |
| MakeJsonMatrix(writer, fMatrix); |
| writeMatrixType(writer, fMatrix); |
| } |
| |
| SetM44Command::SetM44Command(const SkM44& matrix) : INHERITED(kSetM44_OpType) { |
| fMatrix = matrix; |
| } |
| |
| void SetM44Command::execute(SkCanvas* canvas) const { canvas->setMatrix(fMatrix); } |
| |
| void SetM44Command::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { |
| INHERITED::toJSON(writer, urlDataManager); |
| writer.appendName(DEBUGCANVAS_ATTRIBUTE_MATRIX); |
| MakeJsonMatrix44(writer, fMatrix); |
| } |