2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "platform/graphics/LoggingCanvas.h"
34 #include "platform/geometry/IntSize.h"
35 #include "platform/graphics/ImageBuffer.h"
36 #include "platform/graphics/skia/ImagePixelLocker.h"
37 #include "platform/image-encoders/skia/PNGImageEncoder.h"
38 #include "third_party/skia/include/core/SkImage.h"
39 #include "third_party/skia/include/core/SkImageInfo.h"
40 #include "third_party/skia/include/core/SkPaint.h"
41 #include "third_party/skia/include/core/SkPath.h"
42 #include "third_party/skia/include/core/SkPicture.h"
43 #include "third_party/skia/include/core/SkRRect.h"
44 #include "third_party/skia/include/core/SkRect.h"
45 #include "wtf/HexNumber.h"
46 #include "wtf/text/Base64.h"
47 #include "wtf/text/TextEncoding.h"
58 VerbParams(const String
& name
, unsigned pointCount
, unsigned pointOffset
)
60 , pointCount(pointCount
)
61 , pointOffset(pointOffset
) { }
64 PassRefPtr
<JSONObject
> objectForSkRect(const SkRect
& rect
)
66 RefPtr
<JSONObject
> rectItem
= JSONObject::create();
67 rectItem
->setNumber("left", rect
.left());
68 rectItem
->setNumber("top", rect
.top());
69 rectItem
->setNumber("right", rect
.right());
70 rectItem
->setNumber("bottom", rect
.bottom());
71 return rectItem
.release();
74 PassRefPtr
<JSONObject
> objectForSkIRect(const SkIRect
& rect
)
76 RefPtr
<JSONObject
> rectItem
= JSONObject::create();
77 rectItem
->setNumber("left", rect
.left());
78 rectItem
->setNumber("top", rect
.top());
79 rectItem
->setNumber("right", rect
.right());
80 rectItem
->setNumber("bottom", rect
.bottom());
81 return rectItem
.release();
84 String
pointModeName(SkCanvas::PointMode mode
)
87 case SkCanvas::kPoints_PointMode
: return "Points";
88 case SkCanvas::kLines_PointMode
: return "Lines";
89 case SkCanvas::kPolygon_PointMode
: return "Polygon";
96 PassRefPtr
<JSONObject
> objectForSkPoint(const SkPoint
& point
)
98 RefPtr
<JSONObject
> pointItem
= JSONObject::create();
99 pointItem
->setNumber("x", point
.x());
100 pointItem
->setNumber("y", point
.y());
101 return pointItem
.release();
104 PassRefPtr
<JSONArray
> arrayForSkPoints(size_t count
, const SkPoint points
[])
106 RefPtr
<JSONArray
> pointsArrayItem
= JSONArray::create();
107 for (size_t i
= 0; i
< count
; ++i
)
108 pointsArrayItem
->pushObject(objectForSkPoint(points
[i
]));
109 return pointsArrayItem
.release();
112 PassRefPtr
<JSONObject
> objectForRadius(const SkRRect
& rrect
, SkRRect::Corner corner
)
114 RefPtr
<JSONObject
> radiusItem
= JSONObject::create();
115 SkVector radius
= rrect
.radii(corner
);
116 radiusItem
->setNumber("xRadius", radius
.x());
117 radiusItem
->setNumber("yRadius", radius
.y());
118 return radiusItem
.release();
121 String
rrectTypeName(SkRRect::Type type
)
124 case SkRRect::kEmpty_Type
: return "Empty";
125 case SkRRect::kRect_Type
: return "Rect";
126 case SkRRect::kOval_Type
: return "Oval";
127 case SkRRect::kSimple_Type
: return "Simple";
128 case SkRRect::kNinePatch_Type
: return "Nine-patch";
129 case SkRRect::kComplex_Type
: return "Complex";
131 ASSERT_NOT_REACHED();
136 String
radiusName(SkRRect::Corner corner
)
139 case SkRRect::kUpperLeft_Corner
: return "upperLeftRadius";
140 case SkRRect::kUpperRight_Corner
: return "upperRightRadius";
141 case SkRRect::kLowerRight_Corner
: return "lowerRightRadius";
142 case SkRRect::kLowerLeft_Corner
: return "lowerLeftRadius";
144 ASSERT_NOT_REACHED();
149 PassRefPtr
<JSONObject
> objectForSkRRect(const SkRRect
& rrect
)
151 RefPtr
<JSONObject
> rrectItem
= JSONObject::create();
152 rrectItem
->setString("type", rrectTypeName(rrect
.type()));
153 rrectItem
->setNumber("left", rrect
.rect().left());
154 rrectItem
->setNumber("top", rrect
.rect().top());
155 rrectItem
->setNumber("right", rrect
.rect().right());
156 rrectItem
->setNumber("bottom", rrect
.rect().bottom());
157 for (int i
= 0; i
< 4; ++i
)
158 rrectItem
->setObject(radiusName((SkRRect::Corner
) i
), objectForRadius(rrect
, (SkRRect::Corner
) i
));
159 return rrectItem
.release();
162 String
fillTypeName(SkPath::FillType type
)
165 case SkPath::kWinding_FillType
: return "Winding";
166 case SkPath::kEvenOdd_FillType
: return "EvenOdd";
167 case SkPath::kInverseWinding_FillType
: return "InverseWinding";
168 case SkPath::kInverseEvenOdd_FillType
: return "InverseEvenOdd";
170 ASSERT_NOT_REACHED();
175 String
convexityName(SkPath::Convexity convexity
)
178 case SkPath::kUnknown_Convexity
: return "Unknown";
179 case SkPath::kConvex_Convexity
: return "Convex";
180 case SkPath::kConcave_Convexity
: return "Concave";
182 ASSERT_NOT_REACHED();
187 VerbParams
segmentParams(SkPath::Verb verb
)
190 case SkPath::kMove_Verb
: return VerbParams("Move", 1, 0);
191 case SkPath::kLine_Verb
: return VerbParams("Line", 1, 1);
192 case SkPath::kQuad_Verb
: return VerbParams("Quad", 2, 1);
193 case SkPath::kConic_Verb
: return VerbParams("Conic", 2, 1);
194 case SkPath::kCubic_Verb
: return VerbParams("Cubic", 3, 1);
195 case SkPath::kClose_Verb
: return VerbParams("Close", 0, 0);
196 case SkPath::kDone_Verb
: return VerbParams("Done", 0, 0);
198 ASSERT_NOT_REACHED();
199 return VerbParams("?", 0, 0);
203 PassRefPtr
<JSONObject
> objectForSkPath(const SkPath
& path
)
205 RefPtr
<JSONObject
> pathItem
= JSONObject::create();
206 pathItem
->setString("fillType", fillTypeName(path
.getFillType()));
207 pathItem
->setString("convexity", convexityName(path
.getConvexity()));
208 pathItem
->setBoolean("isRect", path
.isRect(0));
209 SkPath::Iter
iter(path
, false);
211 RefPtr
<JSONArray
> pathPointsArray
= JSONArray::create();
212 for (SkPath::Verb verb
= iter
.next(points
, false); verb
!= SkPath::kDone_Verb
; verb
= iter
.next(points
, false)) {
213 VerbParams verbParams
= segmentParams(verb
);
214 RefPtr
<JSONObject
> pathPointItem
= JSONObject::create();
215 pathPointItem
->setString("verb", verbParams
.name
);
216 ASSERT(verbParams
.pointCount
+ verbParams
.pointOffset
<= WTF_ARRAY_LENGTH(points
));
217 pathPointItem
->setArray("points", arrayForSkPoints(verbParams
.pointCount
, points
+ verbParams
.pointOffset
));
218 if (SkPath::kConic_Verb
== verb
)
219 pathPointItem
->setNumber("conicWeight", iter
.conicWeight());
220 pathPointsArray
->pushObject(pathPointItem
);
222 pathItem
->setArray("pathPoints", pathPointsArray
);
223 pathItem
->setObject("bounds", objectForSkRect(path
.getBounds()));
224 return pathItem
.release();
227 String
colorTypeName(SkColorType colorType
)
230 case kUnknown_SkColorType
: return "None";
231 case kAlpha_8_SkColorType
: return "A8";
232 case kIndex_8_SkColorType
: return "Index8";
233 case kRGB_565_SkColorType
: return "RGB565";
234 case kARGB_4444_SkColorType
: return "ARGB4444";
235 case kN32_SkColorType
: return "ARGB8888";
237 ASSERT_NOT_REACHED();
242 PassRefPtr
<JSONObject
> objectForBitmapData(const SkBitmap
& bitmap
)
244 Vector
<unsigned char> output
;
246 if (RefPtr
<SkImage
> image
= adoptRef(SkImage::NewFromBitmap(bitmap
))) {
247 ImagePixelLocker
pixelLocker(image
, kUnpremul_SkAlphaType
);
248 ImageDataBuffer
imageData(IntSize(image
->width(), image
->height()),
249 static_cast<const unsigned char*>(pixelLocker
.pixels()));
251 PNGImageEncoder::encode(imageData
, &output
);
254 RefPtr
<JSONObject
> dataItem
= JSONObject::create();
255 dataItem
->setString("base64", WTF::base64Encode(reinterpret_cast<char*>(output
.data()), output
.size()));
256 dataItem
->setString("mimeType", "image/png");
257 return dataItem
.release();
260 PassRefPtr
<JSONObject
> objectForSkBitmap(const SkBitmap
& bitmap
)
262 RefPtr
<JSONObject
> bitmapItem
= JSONObject::create();
263 bitmapItem
->setNumber("width", bitmap
.width());
264 bitmapItem
->setNumber("height", bitmap
.height());
265 bitmapItem
->setString("config", colorTypeName(bitmap
.colorType()));
266 bitmapItem
->setBoolean("opaque", bitmap
.isOpaque());
267 bitmapItem
->setBoolean("immutable", bitmap
.isImmutable());
268 bitmapItem
->setBoolean("volatile", bitmap
.isVolatile());
269 bitmapItem
->setNumber("genID", bitmap
.getGenerationID());
270 bitmapItem
->setObject("data", objectForBitmapData(bitmap
));
271 return bitmapItem
.release();
274 PassRefPtr
<JSONObject
> objectForSkImage(const SkImage
* image
)
276 RefPtr
<JSONObject
> imageItem
= JSONObject::create();
277 imageItem
->setNumber("width", image
->width());
278 imageItem
->setNumber("height", image
->height());
279 imageItem
->setBoolean("opaque", image
->isOpaque());
280 imageItem
->setNumber("uniqueID", image
->uniqueID());
281 return imageItem
.release();
284 PassRefPtr
<JSONArray
> arrayForSkMatrix(const SkMatrix
& matrix
)
286 RefPtr
<JSONArray
> matrixArray
= JSONArray::create();
287 for (int i
= 0; i
< 9; ++i
)
288 matrixArray
->pushNumber(matrix
[i
]);
289 return matrixArray
.release();
292 PassRefPtr
<JSONObject
> objectForSkShader(const SkShader
& shader
)
294 RefPtr
<JSONObject
> shaderItem
= JSONObject::create();
295 const SkMatrix localMatrix
= shader
.getLocalMatrix();
296 if (!localMatrix
.isIdentity())
297 shaderItem
->setArray("localMatrix", arrayForSkMatrix(localMatrix
));
298 return shaderItem
.release();
301 String
stringForSkColor(const SkColor
& color
)
303 String colorString
= "#";
304 appendUnsignedAsHex(color
, colorString
);
308 void appendFlagToString(String
* flagsString
, bool isSet
, const String
& name
)
312 if (flagsString
->length())
313 flagsString
->append("|");
314 flagsString
->append(name
);
317 String
stringForSkPaintFlags(const SkPaint
& paint
)
319 if (!paint
.getFlags())
321 String flagsString
= "";
322 appendFlagToString(&flagsString
, paint
.isAntiAlias(), "AntiAlias");
323 appendFlagToString(&flagsString
, paint
.isDither(), "Dither");
324 appendFlagToString(&flagsString
, paint
.isUnderlineText(), "UnderlinText");
325 appendFlagToString(&flagsString
, paint
.isStrikeThruText(), "StrikeThruText");
326 appendFlagToString(&flagsString
, paint
.isFakeBoldText(), "FakeBoldText");
327 appendFlagToString(&flagsString
, paint
.isLinearText(), "LinearText");
328 appendFlagToString(&flagsString
, paint
.isSubpixelText(), "SubpixelText");
329 appendFlagToString(&flagsString
, paint
.isDevKernText(), "DevKernText");
330 appendFlagToString(&flagsString
, paint
.isLCDRenderText(), "LCDRenderText");
331 appendFlagToString(&flagsString
, paint
.isEmbeddedBitmapText(), "EmbeddedBitmapText");
332 appendFlagToString(&flagsString
, paint
.isAutohinted(), "Autohinted");
333 appendFlagToString(&flagsString
, paint
.isVerticalText(), "VerticalText");
334 appendFlagToString(&flagsString
, paint
.getFlags() & SkPaint::kGenA8FromLCD_Flag
, "GenA8FromLCD");
338 String
filterQualityName(SkFilterQuality filterQuality
)
340 switch (filterQuality
) {
341 case kNone_SkFilterQuality
: return "None";
342 case kLow_SkFilterQuality
: return "Low";
343 case kMedium_SkFilterQuality
: return "Medium";
344 case kHigh_SkFilterQuality
: return "High";
346 ASSERT_NOT_REACHED();
351 String
textAlignName(SkPaint::Align align
)
354 case SkPaint::kLeft_Align
: return "Left";
355 case SkPaint::kCenter_Align
: return "Center";
356 case SkPaint::kRight_Align
: return "Right";
358 ASSERT_NOT_REACHED();
363 String
strokeCapName(SkPaint::Cap cap
)
366 case SkPaint::kButt_Cap
: return "Butt";
367 case SkPaint::kRound_Cap
: return "Round";
368 case SkPaint::kSquare_Cap
: return "Square";
370 ASSERT_NOT_REACHED();
375 String
strokeJoinName(SkPaint::Join join
)
378 case SkPaint::kMiter_Join
: return "Miter";
379 case SkPaint::kRound_Join
: return "Round";
380 case SkPaint::kBevel_Join
: return "Bevel";
382 ASSERT_NOT_REACHED();
387 String
styleName(SkPaint::Style style
)
390 case SkPaint::kFill_Style
: return "Fill";
391 case SkPaint::kStroke_Style
: return "Stroke";
392 case SkPaint::kStrokeAndFill_Style
: return "StrokeAndFill";
394 ASSERT_NOT_REACHED();
399 String
textEncodingName(SkPaint::TextEncoding encoding
)
402 case SkPaint::kUTF8_TextEncoding
: return "UTF-8";
403 case SkPaint::kUTF16_TextEncoding
: return "UTF-16";
404 case SkPaint::kUTF32_TextEncoding
: return "UTF-32";
405 case SkPaint::kGlyphID_TextEncoding
: return "GlyphID";
407 ASSERT_NOT_REACHED();
412 String
hintingName(SkPaint::Hinting hinting
)
415 case SkPaint::kNo_Hinting
: return "None";
416 case SkPaint::kSlight_Hinting
: return "Slight";
417 case SkPaint::kNormal_Hinting
: return "Normal";
418 case SkPaint::kFull_Hinting
: return "Full";
420 ASSERT_NOT_REACHED();
425 PassRefPtr
<JSONObject
> objectForSkPaint(const SkPaint
& paint
)
427 RefPtr
<JSONObject
> paintItem
= JSONObject::create();
428 paintItem
->setNumber("textSize", paint
.getTextSize());
429 paintItem
->setNumber("textScaleX", paint
.getTextScaleX());
430 paintItem
->setNumber("textSkewX", paint
.getTextSkewX());
431 if (SkShader
* shader
= paint
.getShader())
432 paintItem
->setObject("shader", objectForSkShader(*shader
));
433 paintItem
->setString("color", stringForSkColor(paint
.getColor()));
434 paintItem
->setNumber("strokeWidth", paint
.getStrokeWidth());
435 paintItem
->setNumber("strokeMiter", paint
.getStrokeMiter());
436 paintItem
->setString("flags", stringForSkPaintFlags(paint
));
437 paintItem
->setString("filterLevel", filterQualityName(paint
.getFilterQuality()));
438 paintItem
->setString("textAlign", textAlignName(paint
.getTextAlign()));
439 paintItem
->setString("strokeCap", strokeCapName(paint
.getStrokeCap()));
440 paintItem
->setString("strokeJoin", strokeJoinName(paint
.getStrokeJoin()));
441 paintItem
->setString("styleName", styleName(paint
.getStyle()));
442 paintItem
->setString("textEncoding", textEncodingName(paint
.getTextEncoding()));
443 paintItem
->setString("hinting", hintingName(paint
.getHinting()));
444 return paintItem
.release();
447 PassRefPtr
<JSONArray
> arrayForSkScalars(size_t n
, const SkScalar scalars
[])
449 RefPtr
<JSONArray
> scalarsArray
= JSONArray::create();
450 for (size_t i
= 0; i
< n
; ++i
)
451 scalarsArray
->pushNumber(scalars
[i
]);
452 return scalarsArray
.release();
455 String
regionOpName(SkRegion::Op op
)
458 case SkRegion::kDifference_Op
: return "kDifference_Op";
459 case SkRegion::kIntersect_Op
: return "kIntersect_Op";
460 case SkRegion::kUnion_Op
: return "kUnion_Op";
461 case SkRegion::kXOR_Op
: return "kXOR_Op";
462 case SkRegion::kReverseDifference_Op
: return "kReverseDifference_Op";
463 case SkRegion::kReplace_Op
: return "kReplace_Op";
464 default: return "Unknown type";
468 String
saveFlagsToString(SkCanvas::SaveFlags flags
)
470 String flagsString
= "";
471 if (flags
& SkCanvas::kHasAlphaLayer_SaveFlag
)
472 flagsString
.append("kHasAlphaLayer_SaveFlag ");
473 if (flags
& SkCanvas::kFullColorLayer_SaveFlag
)
474 flagsString
.append("kFullColorLayer_SaveFlag ");
475 if (flags
& SkCanvas::kClipToLayer_SaveFlag
)
476 flagsString
.append("kClipToLayer_SaveFlag ");
480 String
textEncodingCanonicalName(SkPaint::TextEncoding encoding
)
482 String name
= textEncodingName(encoding
);
483 if (encoding
== SkPaint::kUTF16_TextEncoding
|| encoding
== SkPaint::kUTF32_TextEncoding
)
488 String
stringForUTFText(const void* text
, size_t length
, SkPaint::TextEncoding encoding
)
490 return WTF::TextEncoding(textEncodingCanonicalName(encoding
)).decode((const char*)text
, length
);
493 String
stringForText(const void* text
, size_t byteLength
, const SkPaint
& paint
)
495 SkPaint::TextEncoding encoding
= paint
.getTextEncoding();
497 case SkPaint::kUTF8_TextEncoding
:
498 case SkPaint::kUTF16_TextEncoding
:
499 case SkPaint::kUTF32_TextEncoding
:
500 return stringForUTFText(text
, byteLength
, encoding
);
501 case SkPaint::kGlyphID_TextEncoding
: {
502 WTF::Vector
<SkUnichar
> dataVector(byteLength
/ 2);
503 SkUnichar
* textData
= dataVector
.data();
504 paint
.glyphsToUnichars(static_cast<const uint16_t*>(text
), byteLength
/ 2, textData
);
505 return WTF::UTF32LittleEndianEncoding().decode(reinterpret_cast<const char*>(textData
), byteLength
* 2);
508 ASSERT_NOT_REACHED();
515 class AutoLogger
: InterceptingCanvasBase::CanvasInterceptorBase
<LoggingCanvas
> {
517 explicit AutoLogger(LoggingCanvas
* canvas
) : InterceptingCanvasBase::CanvasInterceptorBase
<LoggingCanvas
>(canvas
) { }
519 PassRefPtr
<JSONObject
> logItem(const String
& name
);
520 PassRefPtr
<JSONObject
> logItemWithParams(const String
& name
);
524 canvas()->m_log
->pushObject(m_logItem
);
528 RefPtr
<JSONObject
> m_logItem
;
531 PassRefPtr
<JSONObject
> AutoLogger::logItem(const String
& name
)
533 RefPtr
<JSONObject
> item
= JSONObject::create();
534 item
->setString("method", name
);
536 return item
.release();
539 PassRefPtr
<JSONObject
> AutoLogger::logItemWithParams(const String
& name
)
541 RefPtr
<JSONObject
> item
= logItem(name
);
542 RefPtr
<JSONObject
> params
= JSONObject::create();
543 item
->setObject("params", params
);
544 return params
.release();
547 LoggingCanvas::LoggingCanvas(int width
, int height
)
548 : InterceptingCanvasBase(width
, height
)
549 , m_log(JSONArray::create())
553 void LoggingCanvas::onDrawPaint(const SkPaint
& paint
)
555 AutoLogger
logger(this);
556 logger
.logItemWithParams("drawPaint")->setObject("paint", objectForSkPaint(paint
));
557 this->SkCanvas::onDrawPaint(paint
);
560 void LoggingCanvas::onDrawPoints(PointMode mode
, size_t count
, const SkPoint pts
[], const SkPaint
& paint
)
562 AutoLogger
logger(this);
563 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawPoints");
564 params
->setString("pointMode", pointModeName(mode
));
565 params
->setArray("points", arrayForSkPoints(count
, pts
));
566 params
->setObject("paint", objectForSkPaint(paint
));
567 this->SkCanvas::onDrawPoints(mode
, count
, pts
, paint
);
570 void LoggingCanvas::onDrawRect(const SkRect
& rect
, const SkPaint
& paint
)
572 AutoLogger
logger(this);
573 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawRect");
574 params
->setObject("rect", objectForSkRect(rect
));
575 params
->setObject("paint", objectForSkPaint(paint
));
576 this->SkCanvas::onDrawRect(rect
, paint
);
579 void LoggingCanvas::onDrawOval(const SkRect
& oval
, const SkPaint
& paint
)
581 AutoLogger
logger(this);
582 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawOval");
583 params
->setObject("oval", objectForSkRect(oval
));
584 params
->setObject("paint", objectForSkPaint(paint
));
585 this->SkCanvas::onDrawOval(oval
, paint
);
588 void LoggingCanvas::onDrawRRect(const SkRRect
& rrect
, const SkPaint
& paint
)
590 AutoLogger
logger(this);
591 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawRRect");
592 params
->setObject("rrect", objectForSkRRect(rrect
));
593 params
->setObject("paint", objectForSkPaint(paint
));
594 this->SkCanvas::onDrawRRect(rrect
, paint
);
597 void LoggingCanvas::onDrawPath(const SkPath
& path
, const SkPaint
& paint
)
599 AutoLogger
logger(this);
600 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawPath");
601 params
->setObject("path", objectForSkPath(path
));
602 params
->setObject("paint", objectForSkPaint(paint
));
603 this->SkCanvas::onDrawPath(path
, paint
);
606 void LoggingCanvas::onDrawBitmap(const SkBitmap
& bitmap
, SkScalar left
, SkScalar top
, const SkPaint
* paint
)
608 AutoLogger
logger(this);
609 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawBitmap");
610 params
->setNumber("left", left
);
611 params
->setNumber("top", top
);
612 params
->setObject("bitmap", objectForSkBitmap(bitmap
));
614 params
->setObject("paint", objectForSkPaint(*paint
));
615 this->SkCanvas::onDrawBitmap(bitmap
, left
, top
, paint
);
618 void LoggingCanvas::onDrawBitmapRect(const SkBitmap
& bitmap
, const SkRect
* src
, const SkRect
& dst
, const SkPaint
* paint
, SrcRectConstraint constraint
)
620 AutoLogger
logger(this);
621 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawBitmapRectToRect");
622 params
->setObject("bitmap", objectForSkBitmap(bitmap
));
624 params
->setObject("src", objectForSkRect(*src
));
625 params
->setObject("dst", objectForSkRect(dst
));
627 params
->setObject("paint", objectForSkPaint(*paint
));
628 params
->setNumber("flags", constraint
);
629 this->SkCanvas::onDrawBitmapRect(bitmap
, src
, dst
, paint
, constraint
);
632 void LoggingCanvas::onDrawBitmapNine(const SkBitmap
& bitmap
, const SkIRect
& center
, const SkRect
& dst
, const SkPaint
* paint
)
634 AutoLogger
logger(this);
635 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawBitmapNine");
636 params
->setObject("bitmap", objectForSkBitmap(bitmap
));
637 params
->setObject("center", objectForSkIRect(center
));
638 params
->setObject("dst", objectForSkRect(dst
));
640 params
->setObject("paint", objectForSkPaint(*paint
));
641 this->SkCanvas::onDrawBitmapNine(bitmap
, center
, dst
, paint
);
644 void LoggingCanvas::onDrawImage(const SkImage
* image
, SkScalar left
, SkScalar top
, const SkPaint
* paint
)
646 AutoLogger
logger(this);
647 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawImage");
648 params
->setNumber("left", left
);
649 params
->setNumber("top", top
);
650 params
->setObject("image", objectForSkImage(image
));
652 params
->setObject("paint", objectForSkPaint(*paint
));
653 this->SkCanvas::onDrawImage(image
, left
, top
, paint
);
656 void LoggingCanvas::onDrawImageRect(const SkImage
* image
, const SkRect
* src
, const SkRect
& dst
, const SkPaint
* paint
, SrcRectConstraint constraint
)
658 AutoLogger
logger(this);
659 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawImageRect");
660 params
->setObject("image", objectForSkImage(image
));
662 params
->setObject("src", objectForSkRect(*src
));
663 params
->setObject("dst", objectForSkRect(dst
));
665 params
->setObject("paint", objectForSkPaint(*paint
));
666 this->SkCanvas::onDrawImageRect(image
, src
, dst
, paint
, constraint
);
669 void LoggingCanvas::onDrawSprite(const SkBitmap
& bitmap
, int left
, int top
, const SkPaint
* paint
)
671 AutoLogger
logger(this);
672 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawSprite");
673 params
->setObject("bitmap", objectForSkBitmap(bitmap
));
674 params
->setNumber("left", left
);
675 params
->setNumber("top", top
);
677 params
->setObject("paint", objectForSkPaint(*paint
));
678 this->SkCanvas::onDrawSprite(bitmap
, left
, top
, paint
);
681 void LoggingCanvas::onDrawVertices(VertexMode vmode
, int vertexCount
, const SkPoint vertices
[], const SkPoint texs
[], const SkColor colors
[], SkXfermode
* xmode
,
682 const uint16_t indices
[], int indexCount
, const SkPaint
& paint
)
684 AutoLogger
logger(this);
685 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawVertices");
686 params
->setObject("paint", objectForSkPaint(paint
));
687 this->SkCanvas::onDrawVertices(vmode
, vertexCount
, vertices
, texs
, colors
, xmode
, indices
, indexCount
, paint
);
690 void LoggingCanvas::onDrawDRRect(const SkRRect
& outer
, const SkRRect
& inner
, const SkPaint
& paint
)
692 AutoLogger
logger(this);
693 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawDRRect");
694 params
->setObject("outer", objectForSkRRect(outer
));
695 params
->setObject("inner", objectForSkRRect(inner
));
696 params
->setObject("paint", objectForSkPaint(paint
));
697 this->SkCanvas::onDrawDRRect(outer
, inner
, paint
);
700 void LoggingCanvas::onDrawText(const void* text
, size_t byteLength
, SkScalar x
, SkScalar y
, const SkPaint
& paint
)
702 AutoLogger
logger(this);
703 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawText");
704 params
->setString("text", stringForText(text
, byteLength
, paint
));
705 params
->setNumber("x", x
);
706 params
->setNumber("y", y
);
707 params
->setObject("paint", objectForSkPaint(paint
));
708 this->SkCanvas::onDrawText(text
, byteLength
, x
, y
, paint
);
711 void LoggingCanvas::onDrawPosText(const void* text
, size_t byteLength
, const SkPoint pos
[], const SkPaint
& paint
)
713 AutoLogger
logger(this);
714 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawPosText");
715 params
->setString("text", stringForText(text
, byteLength
, paint
));
716 size_t pointsCount
= paint
.countText(text
, byteLength
);
717 params
->setArray("pos", arrayForSkPoints(pointsCount
, pos
));
718 params
->setObject("paint", objectForSkPaint(paint
));
719 this->SkCanvas::onDrawPosText(text
, byteLength
, pos
, paint
);
722 void LoggingCanvas::onDrawPosTextH(const void* text
, size_t byteLength
, const SkScalar xpos
[], SkScalar constY
, const SkPaint
& paint
)
724 AutoLogger
logger(this);
725 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawPosTextH");
726 params
->setString("text", stringForText(text
, byteLength
, paint
));
727 size_t pointsCount
= paint
.countText(text
, byteLength
);
728 params
->setArray("xpos", arrayForSkScalars(pointsCount
, xpos
));
729 params
->setNumber("constY", constY
);
730 params
->setObject("paint", objectForSkPaint(paint
));
731 this->SkCanvas::onDrawPosTextH(text
, byteLength
, xpos
, constY
, paint
);
734 void LoggingCanvas::onDrawTextOnPath(const void* text
, size_t byteLength
, const SkPath
& path
, const SkMatrix
* matrix
, const SkPaint
& paint
)
736 AutoLogger
logger(this);
737 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawTextOnPath");
738 params
->setString("text", stringForText(text
, byteLength
, paint
));
739 params
->setObject("path", objectForSkPath(path
));
741 params
->setArray("matrix", arrayForSkMatrix(*matrix
));
742 params
->setObject("paint", objectForSkPaint(paint
));
743 this->SkCanvas::onDrawTextOnPath(text
, byteLength
, path
, matrix
, paint
);
746 void LoggingCanvas::onDrawTextBlob(const SkTextBlob
*blob
, SkScalar x
, SkScalar y
, const SkPaint
&paint
)
748 AutoLogger
logger(this);
749 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("drawTextBlob");
750 params
->setNumber("x", x
);
751 params
->setNumber("y", y
);
752 params
->setObject("paint", objectForSkPaint(paint
));
753 this->SkCanvas::onDrawTextBlob(blob
, x
, y
, paint
);
756 void LoggingCanvas::onClipRect(const SkRect
& rect
, SkRegion::Op op
, ClipEdgeStyle style
)
758 AutoLogger
logger(this);
759 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("clipRect");
760 params
->setObject("rect", objectForSkRect(rect
));
761 params
->setString("SkRegion::Op", regionOpName(op
));
762 params
->setBoolean("softClipEdgeStyle", kSoft_ClipEdgeStyle
== style
);
763 this->SkCanvas::onClipRect(rect
, op
, style
);
766 void LoggingCanvas::onClipRRect(const SkRRect
& rrect
, SkRegion::Op op
, ClipEdgeStyle style
)
768 AutoLogger
logger(this);
769 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("clipRRect");
770 params
->setObject("rrect", objectForSkRRect(rrect
));
771 params
->setString("SkRegion::Op", regionOpName(op
));
772 params
->setBoolean("softClipEdgeStyle", kSoft_ClipEdgeStyle
== style
);
773 this->SkCanvas::onClipRRect(rrect
, op
, style
);
776 void LoggingCanvas::onClipPath(const SkPath
& path
, SkRegion::Op op
, ClipEdgeStyle style
)
778 AutoLogger
logger(this);
779 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("clipPath");
780 params
->setObject("path", objectForSkPath(path
));
781 params
->setString("SkRegion::Op", regionOpName(op
));
782 params
->setBoolean("softClipEdgeStyle", kSoft_ClipEdgeStyle
== style
);
783 this->SkCanvas::onClipPath(path
, op
, style
);
786 void LoggingCanvas::onClipRegion(const SkRegion
& region
, SkRegion::Op op
)
788 AutoLogger
logger(this);
789 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("clipRegion");
790 params
->setString("op", regionOpName(op
));
791 this->SkCanvas::onClipRegion(region
, op
);
794 void LoggingCanvas::onDrawPicture(const SkPicture
* picture
, const SkMatrix
* matrix
, const SkPaint
* paint
)
796 this->unrollDrawPicture(picture
, matrix
, paint
, nullptr);
799 void LoggingCanvas::didSetMatrix(const SkMatrix
& matrix
)
801 AutoLogger
logger(this);
802 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("setMatrix");
803 params
->setArray("matrix", arrayForSkMatrix(matrix
));
804 this->SkCanvas::didSetMatrix(matrix
);
807 void LoggingCanvas::didConcat(const SkMatrix
& matrix
)
809 AutoLogger
logger(this);
810 RefPtr
<JSONObject
> params
;
812 switch (matrix
.getType()) {
813 case SkMatrix::kTranslate_Mask
:
814 params
= logger
.logItemWithParams("translate");
815 params
->setNumber("dx", matrix
.getTranslateX());
816 params
->setNumber("dy", matrix
.getTranslateY());
819 case SkMatrix::kScale_Mask
:
820 params
= logger
.logItemWithParams("scale");
821 params
->setNumber("scaleX", matrix
.getScaleX());
822 params
->setNumber("scaleY", matrix
.getScaleY());
826 params
= logger
.logItemWithParams("concat");
827 params
->setArray("matrix", arrayForSkMatrix(matrix
));
829 this->SkCanvas::didConcat(matrix
);
832 void LoggingCanvas::willSave()
834 AutoLogger
logger(this);
835 RefPtr
<JSONObject
> params
= logger
.logItem("save");
836 this->SkCanvas::willSave();
839 SkCanvas::SaveLayerStrategy
LoggingCanvas::willSaveLayer(const SkRect
* bounds
, const SkPaint
* paint
, SaveFlags flags
)
841 AutoLogger
logger(this);
842 RefPtr
<JSONObject
> params
= logger
.logItemWithParams("saveLayer");
844 params
->setObject("bounds", objectForSkRect(*bounds
));
846 params
->setObject("paint", objectForSkPaint(*paint
));
847 params
->setString("saveFlags", saveFlagsToString(flags
));
848 return this->SkCanvas::willSaveLayer(bounds
, paint
, flags
);
851 void LoggingCanvas::willRestore()
853 AutoLogger
logger(this);
854 logger
.logItem("restore");
855 this->SkCanvas::willRestore();
858 PassRefPtr
<JSONArray
> LoggingCanvas::log()
864 String
pictureAsDebugString(const SkPicture
* picture
)
866 const SkIRect bounds
= picture
->cullRect().roundOut();
867 LoggingCanvas
canvas(bounds
.width(), bounds
.height());
868 picture
->playback(&canvas
);
869 RefPtr
<JSONObject
> pictureAsJSON
= JSONObject::create();
870 pictureAsJSON
->setObject("cullRect", objectForSkRect(picture
->cullRect()));
871 pictureAsJSON
->setArray("operations", canvas
.log());
872 RefPtr
<JSONArray
> operationsInJson
= canvas
.log();
873 return pictureAsJSON
->toPrettyJSONString();
876 void showSkPicture(const SkPicture
* picture
)
878 WTFLogAlways("%s\n", pictureAsDebugString(picture
).utf8().data());