1 
2 /*
3  * Copyright 2012 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #include "SkObjectParser.h"
10 #include "SkData.h"
11 #include "SkFontDescriptor.h"
12 #include "SkImage.h"
13 #include "SkPath.h"
14 #include "SkRRect.h"
15 #include "SkShader.h"
16 #include "SkStream.h"
17 #include "SkStringUtils.h"
18 #include "SkTypeface.h"
19 #include "SkUtils.h"
20 
21 /* TODO(chudy): Replace all std::strings with char */
22 
BitmapToString(const SkBitmap & bitmap)23 SkString* SkObjectParser::BitmapToString(const SkBitmap& bitmap) {
24     SkString* mBitmap = new SkString("SkBitmap: ");
25     mBitmap->append("W: ");
26     mBitmap->appendS32(bitmap.width());
27     mBitmap->append(" H: ");
28     mBitmap->appendS32(bitmap.height());
29 
30     const char* gColorTypeStrings[] = {
31         "None", "A8", "565", "4444", "RGBA", "BGRA", "Index8", "G8", "RGBAf16"
32     };
33     static_assert(kLastEnum_SkColorType + 1 == SK_ARRAY_COUNT(gColorTypeStrings),
34                   "colortype names do not match colortype enum");
35 
36     mBitmap->append(" ColorType: ");
37     mBitmap->append(gColorTypeStrings[bitmap.colorType()]);
38 
39     if (bitmap.isOpaque()) {
40         mBitmap->append(" opaque");
41     } else {
42         mBitmap->append(" not-opaque");
43     }
44 
45     if (bitmap.isImmutable()) {
46         mBitmap->append(" immutable");
47     } else {
48         mBitmap->append(" not-immutable");
49     }
50 
51     if (bitmap.isVolatile()) {
52         mBitmap->append(" volatile");
53     } else {
54         mBitmap->append(" not-volatile");
55     }
56 
57     mBitmap->append(" genID: ");
58     mBitmap->appendS32(bitmap.getGenerationID());
59 
60     return mBitmap;
61 }
62 
ImageToString(const SkImage * image)63 SkString* SkObjectParser::ImageToString(const SkImage* image) {
64     SkString* str = new SkString("SkImage: ");
65     if (!image) {
66         return str;
67     }
68 
69     str->append("W: ");
70     str->appendS32(image->width());
71     str->append(" H: ");
72     str->appendS32(image->height());
73 
74     if (image->isOpaque()) {
75         str->append(" opaque");
76     } else {
77         str->append(" not-opaque");
78     }
79 
80     str->append(" uniqueID: ");
81     str->appendS32(image->uniqueID());
82 
83     return str;
84 }
85 
BoolToString(bool doAA)86 SkString* SkObjectParser::BoolToString(bool doAA) {
87     SkString* mBool = new SkString("Bool doAA: ");
88     if (doAA) {
89         mBool->append("True");
90     } else {
91         mBool->append("False");
92     }
93     return mBool;
94 }
95 
CustomTextToString(const char * text)96 SkString* SkObjectParser::CustomTextToString(const char* text) {
97     SkString* mText = new SkString(text);
98     return mText;
99 }
100 
IntToString(int x,const char * text)101 SkString* SkObjectParser::IntToString(int x, const char* text) {
102     SkString* mInt = new SkString(text);
103     mInt->append(" ");
104     mInt->appendScalar(SkIntToScalar(x));
105     return mInt;
106 }
107 
IRectToString(const SkIRect & rect)108 SkString* SkObjectParser::IRectToString(const SkIRect& rect) {
109     SkString* mRect = new SkString("SkIRect: ");
110     mRect->append("L: ");
111     mRect->appendS32(rect.left());
112     mRect->append(", T: ");
113     mRect->appendS32(rect.top());
114     mRect->append(", R: ");
115     mRect->appendS32(rect.right());
116     mRect->append(", B: ");
117     mRect->appendS32(rect.bottom());
118     return mRect;
119 }
120 
MatrixToString(const SkMatrix & matrix)121 SkString* SkObjectParser::MatrixToString(const SkMatrix& matrix) {
122     SkString* str = new SkString("SkMatrix: ");
123 #ifndef SK_IGNORE_TO_STRING
124     matrix.toString(str);
125 #endif
126     return str;
127 }
128 
PaintToString(const SkPaint & paint)129 SkString* SkObjectParser::PaintToString(const SkPaint& paint) {
130     SkString* str = new SkString;
131 #ifndef SK_IGNORE_TO_STRING
132     paint.toString(str);
133 #endif
134     return str;
135 }
136 
PathToString(const SkPath & path)137 SkString* SkObjectParser::PathToString(const SkPath& path) {
138     SkString* mPath = new SkString;
139 
140     mPath->appendf("Path (%d) (", path.getGenerationID());
141 
142     static const char* gFillStrings[] = {
143         "Winding", "EvenOdd", "InverseWinding", "InverseEvenOdd"
144     };
145 
146     mPath->append(gFillStrings[path.getFillType()]);
147     mPath->append(", ");
148 
149     static const char* gConvexityStrings[] = {
150         "Unknown", "Convex", "Concave"
151     };
152     SkASSERT(SkPath::kConcave_Convexity == 2);
153 
154     mPath->append(gConvexityStrings[path.getConvexity()]);
155     mPath->append(", ");
156 
157     if (path.isRect(nullptr)) {
158         mPath->append("isRect, ");
159     } else {
160         mPath->append("isNotRect, ");
161     }
162 
163     if (path.isOval(nullptr)) {
164         mPath->append("isOval, ");
165     } else {
166         mPath->append("isNotOval, ");
167     }
168 
169     SkRRect rrect;
170     if (path.isRRect(&rrect)) {
171         mPath->append("isRRect, ");
172     } else {
173         mPath->append("isNotRRect, ");
174     }
175 
176     mPath->appendS32(path.countVerbs());
177     mPath->append("V, ");
178     mPath->appendS32(path.countPoints());
179     mPath->append("P): ");
180 
181     static const char* gVerbStrings[] = {
182         "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done"
183     };
184     static const int gPtsPerVerb[] = { 1, 1, 2, 2, 3, 0, 0 };
185     static const int gPtOffsetPerVerb[] = { 0, 1, 1, 1, 1, 0, 0 };
186     SkASSERT(SkPath::kDone_Verb == 6);
187 
188     SkPath::Iter iter(const_cast<SkPath&>(path), false);
189     SkPath::Verb verb;
190     SkPoint points[4];
191 
192     for(verb = iter.next(points, false);
193         verb != SkPath::kDone_Verb;
194         verb = iter.next(points, false)) {
195 
196         mPath->append(gVerbStrings[verb]);
197         mPath->append(" ");
198 
199         for (int i = 0; i < gPtsPerVerb[verb]; ++i) {
200             mPath->append("(");
201             mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fX);
202             mPath->append(", ");
203             mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fY);
204             mPath->append(")");
205         }
206 
207         if (SkPath::kConic_Verb == verb) {
208             mPath->append("(");
209             mPath->appendScalar(iter.conicWeight());
210             mPath->append(")");
211         }
212 
213         mPath->append(" ");
214     }
215 
216     SkString* boundStr = SkObjectParser::RectToString(path.getBounds(), "    Bound: ");
217 
218     if (boundStr) {
219         mPath->append(*boundStr);
220         delete boundStr;
221     }
222 
223     return mPath;
224 }
225 
PointsToString(const SkPoint pts[],size_t count)226 SkString* SkObjectParser::PointsToString(const SkPoint pts[], size_t count) {
227     SkString* mPoints = new SkString("SkPoints pts[]: ");
228     for (unsigned int i = 0; i < count; i++) {
229         mPoints->append("(");
230         mPoints->appendScalar(pts[i].fX);
231         mPoints->append(",");
232         mPoints->appendScalar(pts[i].fY);
233         mPoints->append(")");
234     }
235     return mPoints;
236 }
237 
PointModeToString(SkCanvas::PointMode mode)238 SkString* SkObjectParser::PointModeToString(SkCanvas::PointMode mode) {
239     SkString* mMode = new SkString("SkCanvas::PointMode: ");
240     if (mode == SkCanvas::kPoints_PointMode) {
241         mMode->append("kPoints_PointMode");
242     } else if (mode == SkCanvas::kLines_PointMode) {
243         mMode->append("kLines_Mode");
244     } else if (mode == SkCanvas::kPolygon_PointMode) {
245         mMode->append("kPolygon_PointMode");
246     }
247     return mMode;
248 }
249 
RectToString(const SkRect & rect,const char * title)250 SkString* SkObjectParser::RectToString(const SkRect& rect, const char* title) {
251 
252     SkString* mRect = new SkString;
253 
254     if (nullptr == title) {
255         mRect->append("SkRect: ");
256     } else {
257         mRect->append(title);
258     }
259     mRect->append("(");
260     mRect->appendScalar(rect.left());
261     mRect->append(", ");
262     mRect->appendScalar(rect.top());
263     mRect->append(", ");
264     mRect->appendScalar(rect.right());
265     mRect->append(", ");
266     mRect->appendScalar(rect.bottom());
267     mRect->append(")");
268     return mRect;
269 }
270 
RRectToString(const SkRRect & rrect,const char * title)271 SkString* SkObjectParser::RRectToString(const SkRRect& rrect, const char* title) {
272 
273     SkString* mRRect = new SkString;
274 
275     if (nullptr == title) {
276         mRRect->append("SkRRect (");
277         if (rrect.isEmpty()) {
278             mRRect->append("empty");
279         } else if (rrect.isRect()) {
280             mRRect->append("rect");
281         } else if (rrect.isOval()) {
282             mRRect->append("oval");
283         } else if (rrect.isSimple()) {
284             mRRect->append("simple");
285         } else if (rrect.isNinePatch()) {
286             mRRect->append("nine-patch");
287         } else {
288             SkASSERT(rrect.isComplex());
289             mRRect->append("complex");
290         }
291         mRRect->append("): ");
292     } else {
293         mRRect->append(title);
294     }
295     mRRect->append("(");
296     mRRect->appendScalar(rrect.rect().left());
297     mRRect->append(", ");
298     mRRect->appendScalar(rrect.rect().top());
299     mRRect->append(", ");
300     mRRect->appendScalar(rrect.rect().right());
301     mRRect->append(", ");
302     mRRect->appendScalar(rrect.rect().bottom());
303     mRRect->append(") radii: (");
304     for (int i = 0; i < 4; ++i) {
305         const SkVector& radii = rrect.radii((SkRRect::Corner) i);
306         mRRect->appendScalar(radii.fX);
307         mRRect->append(", ");
308         mRRect->appendScalar(radii.fY);
309         if (i < 3) {
310             mRRect->append(", ");
311         }
312     }
313     mRRect->append(")");
314     return mRRect;
315 }
316 
RegionOpToString(SkRegion::Op op)317 SkString* SkObjectParser::RegionOpToString(SkRegion::Op op) {
318     SkString* mOp = new SkString("SkRegion::Op: ");
319     if (op == SkRegion::kDifference_Op) {
320         mOp->append("kDifference_Op");
321     } else if (op == SkRegion::kIntersect_Op) {
322         mOp->append("kIntersect_Op");
323     } else if (op == SkRegion::kUnion_Op) {
324         mOp->append("kUnion_Op");
325     } else if (op == SkRegion::kXOR_Op) {
326         mOp->append("kXOR_Op");
327     } else if (op == SkRegion::kReverseDifference_Op) {
328         mOp->append("kReverseDifference_Op");
329     } else if (op == SkRegion::kReplace_Op) {
330         mOp->append("kReplace_Op");
331     } else {
332         mOp->append("Unknown Type");
333     }
334     return mOp;
335 }
336 
RegionToString(const SkRegion & region)337 SkString* SkObjectParser::RegionToString(const SkRegion& region) {
338     SkString* mRegion = new SkString("SkRegion: Data unavailable.");
339     return mRegion;
340 }
341 
SaveLayerFlagsToString(SkCanvas::SaveLayerFlags saveLayerFlags)342 SkString* SkObjectParser::SaveLayerFlagsToString(SkCanvas::SaveLayerFlags saveLayerFlags) {
343     SkString* mFlags = new SkString("SkCanvas::SaveFlags: ");
344     if (saveLayerFlags & SkCanvas::kIsOpaque_SaveLayerFlag) {
345         mFlags->append("kIsOpaque_SaveLayerFlag ");
346     }
347     if (saveLayerFlags & SkCanvas::kPreserveLCDText_SaveLayerFlag) {
348         mFlags->append("kPreserveLCDText_SaveLayerFlag ");
349     }
350     return mFlags;
351 }
352 
ScalarToString(SkScalar x,const char * text)353 SkString* SkObjectParser::ScalarToString(SkScalar x, const char* text) {
354     SkString* mScalar = new SkString(text);
355     mScalar->append(" ");
356     mScalar->appendScalar(x);
357     return mScalar;
358 }
359 
TextToString(const void * text,size_t byteLength,SkPaint::TextEncoding encoding)360 SkString* SkObjectParser::TextToString(const void* text, size_t byteLength,
361                                        SkPaint::TextEncoding encoding) {
362 
363     SkString* decodedText = new SkString();
364     switch (encoding) {
365         case SkPaint::kUTF8_TextEncoding: {
366             decodedText->append("UTF-8: ");
367             decodedText->append((const char*)text, byteLength);
368             break;
369         }
370         case SkPaint::kUTF16_TextEncoding: {
371             decodedText->append("UTF-16: ");
372             size_t sizeNeeded = SkUTF16_ToUTF8((uint16_t*)text,
373                                                 SkToS32(byteLength / 2),
374                                                 nullptr);
375             SkAutoSTMalloc<0x100, char> utf8(sizeNeeded);
376             SkUTF16_ToUTF8((uint16_t*)text, SkToS32(byteLength / 2), utf8);
377             decodedText->append(utf8, sizeNeeded);
378             break;
379         }
380         case SkPaint::kUTF32_TextEncoding: {
381             decodedText->append("UTF-32: ");
382             const SkUnichar* begin = (const SkUnichar*)text;
383             const SkUnichar* end = (const SkUnichar*)((const char*)text + byteLength);
384             for (const SkUnichar* unichar = begin; unichar < end; ++unichar) {
385                 decodedText->appendUnichar(*unichar);
386             }
387             break;
388         }
389         case SkPaint::kGlyphID_TextEncoding: {
390             decodedText->append("GlyphID: ");
391             const uint16_t* begin = (const uint16_t*)text;
392             const uint16_t* end = (const uint16_t*)((const char*)text + byteLength);
393             for (const uint16_t* glyph = begin; glyph < end; ++glyph) {
394                 decodedText->append("0x");
395                 decodedText->appendHex(*glyph);
396                 decodedText->append(" ");
397             }
398             break;
399         }
400         default:
401             decodedText->append("Unknown text encoding.");
402             break;
403     }
404 
405     return decodedText;
406 }
407