michael@0: michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "SkObjectParser.h" michael@0: #include "SkData.h" michael@0: #include "SkFontDescriptor.h" michael@0: #include "SkRRect.h" michael@0: #include "SkShader.h" michael@0: #include "SkStream.h" michael@0: #include "SkStringUtils.h" michael@0: #include "SkTypeface.h" michael@0: #include "SkUtils.h" michael@0: michael@0: /* TODO(chudy): Replace all std::strings with char */ michael@0: michael@0: SkString* SkObjectParser::BitmapToString(const SkBitmap& bitmap) { michael@0: SkString* mBitmap = new SkString("SkBitmap: "); michael@0: mBitmap->append("W: "); michael@0: mBitmap->appendS32(bitmap.width()); michael@0: mBitmap->append(" H: "); michael@0: mBitmap->appendS32(bitmap.height()); michael@0: michael@0: const char* gConfigStrings[] = { michael@0: "None", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888" michael@0: }; michael@0: SkASSERT(SkBitmap::kConfigCount == SK_ARRAY_COUNT(gConfigStrings)); michael@0: michael@0: mBitmap->append(" Config: "); michael@0: mBitmap->append(gConfigStrings[bitmap.config()]); michael@0: michael@0: if (bitmap.isOpaque()) { michael@0: mBitmap->append(" opaque"); michael@0: } else { michael@0: mBitmap->append(" not-opaque"); michael@0: } michael@0: michael@0: if (bitmap.isImmutable()) { michael@0: mBitmap->append(" immutable"); michael@0: } else { michael@0: mBitmap->append(" not-immutable"); michael@0: } michael@0: michael@0: if (bitmap.isVolatile()) { michael@0: mBitmap->append(" volatile"); michael@0: } else { michael@0: mBitmap->append(" not-volatile"); michael@0: } michael@0: michael@0: mBitmap->append(" genID: "); michael@0: mBitmap->appendS32(bitmap.getGenerationID()); michael@0: michael@0: return mBitmap; michael@0: } michael@0: michael@0: SkString* SkObjectParser::BoolToString(bool doAA) { michael@0: SkString* mBool = new SkString("Bool doAA: "); michael@0: if (doAA) { michael@0: mBool->append("True"); michael@0: } else { michael@0: mBool->append("False"); michael@0: } michael@0: return mBool; michael@0: } michael@0: michael@0: SkString* SkObjectParser::CustomTextToString(const char* text) { michael@0: SkString* mText = new SkString(text); michael@0: return mText; michael@0: } michael@0: michael@0: SkString* SkObjectParser::IntToString(int x, const char* text) { michael@0: SkString* mInt = new SkString(text); michael@0: mInt->append(" "); michael@0: mInt->appendScalar(SkIntToScalar(x)); michael@0: return mInt; michael@0: } michael@0: michael@0: SkString* SkObjectParser::IRectToString(const SkIRect& rect) { michael@0: SkString* mRect = new SkString("SkIRect: "); michael@0: mRect->append("L: "); michael@0: mRect->appendS32(rect.left()); michael@0: mRect->append(", T: "); michael@0: mRect->appendS32(rect.top()); michael@0: mRect->append(", R: "); michael@0: mRect->appendS32(rect.right()); michael@0: mRect->append(", B: "); michael@0: mRect->appendS32(rect.bottom()); michael@0: return mRect; michael@0: } michael@0: michael@0: SkString* SkObjectParser::MatrixToString(const SkMatrix& matrix) { michael@0: SkString* str = new SkString("SkMatrix: "); michael@0: #ifndef SK_IGNORE_TO_STRING michael@0: matrix.toString(str); michael@0: #endif michael@0: return str; michael@0: } michael@0: michael@0: SkString* SkObjectParser::PaintToString(const SkPaint& paint) { michael@0: SkString* str = new SkString; michael@0: #ifndef SK_IGNORE_TO_STRING michael@0: paint.toString(str); michael@0: #endif michael@0: return str; michael@0: } michael@0: michael@0: SkString* SkObjectParser::PathToString(const SkPath& path) { michael@0: SkString* mPath = new SkString("Path ("); michael@0: michael@0: static const char* gFillStrings[] = { michael@0: "Winding", "EvenOdd", "InverseWinding", "InverseEvenOdd" michael@0: }; michael@0: michael@0: mPath->append(gFillStrings[path.getFillType()]); michael@0: mPath->append(", "); michael@0: michael@0: static const char* gConvexityStrings[] = { michael@0: "Unknown", "Convex", "Concave" michael@0: }; michael@0: SkASSERT(SkPath::kConcave_Convexity == 2); michael@0: michael@0: mPath->append(gConvexityStrings[path.getConvexity()]); michael@0: mPath->append(", "); michael@0: michael@0: if (path.isRect(NULL)) { michael@0: mPath->append("isRect, "); michael@0: } else { michael@0: mPath->append("isNotRect, "); michael@0: } michael@0: michael@0: mPath->appendS32(path.countVerbs()); michael@0: mPath->append("V, "); michael@0: mPath->appendS32(path.countPoints()); michael@0: mPath->append("P): "); michael@0: michael@0: static const char* gVerbStrings[] = { michael@0: "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" michael@0: }; michael@0: static const int gPtsPerVerb[] = { 1, 1, 2, 2, 3, 0, 0 }; michael@0: static const int gPtOffsetPerVerb[] = { 0, 1, 1, 1, 1, 0, 0 }; michael@0: SkASSERT(SkPath::kDone_Verb == 6); michael@0: michael@0: SkPath::Iter iter(const_cast(path), false); michael@0: SkPath::Verb verb; michael@0: SkPoint points[4]; michael@0: michael@0: for(verb = iter.next(points, false); michael@0: verb != SkPath::kDone_Verb; michael@0: verb = iter.next(points, false)) { michael@0: michael@0: mPath->append(gVerbStrings[verb]); michael@0: mPath->append(" "); michael@0: michael@0: for (int i = 0; i < gPtsPerVerb[verb]; ++i) { michael@0: mPath->append("("); michael@0: mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fX); michael@0: mPath->append(", "); michael@0: mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fY); michael@0: mPath->append(")"); michael@0: } michael@0: michael@0: if (SkPath::kConic_Verb == verb) { michael@0: mPath->append("("); michael@0: mPath->appendScalar(iter.conicWeight()); michael@0: mPath->append(")"); michael@0: } michael@0: michael@0: mPath->append(" "); michael@0: } michael@0: michael@0: SkString* boundStr = SkObjectParser::RectToString(path.getBounds(), " Bound: "); michael@0: michael@0: if (NULL != boundStr) { michael@0: mPath->append(*boundStr); michael@0: SkDELETE(boundStr); michael@0: } michael@0: michael@0: return mPath; michael@0: } michael@0: michael@0: SkString* SkObjectParser::PointsToString(const SkPoint pts[], size_t count) { michael@0: SkString* mPoints = new SkString("SkPoints pts[]: "); michael@0: for (unsigned int i = 0; i < count; i++) { michael@0: mPoints->append("("); michael@0: mPoints->appendScalar(pts[i].fX); michael@0: mPoints->append(","); michael@0: mPoints->appendScalar(pts[i].fY); michael@0: mPoints->append(")"); michael@0: } michael@0: return mPoints; michael@0: } michael@0: michael@0: SkString* SkObjectParser::PointModeToString(SkCanvas::PointMode mode) { michael@0: SkString* mMode = new SkString("SkCanvas::PointMode: "); michael@0: if (mode == SkCanvas::kPoints_PointMode) { michael@0: mMode->append("kPoints_PointMode"); michael@0: } else if (mode == SkCanvas::kLines_PointMode) { michael@0: mMode->append("kLines_Mode"); michael@0: } else if (mode == SkCanvas::kPolygon_PointMode) { michael@0: mMode->append("kPolygon_PointMode"); michael@0: } michael@0: return mMode; michael@0: } michael@0: michael@0: SkString* SkObjectParser::RectToString(const SkRect& rect, const char* title) { michael@0: michael@0: SkString* mRect = new SkString; michael@0: michael@0: if (NULL == title) { michael@0: mRect->append("SkRect: "); michael@0: } else { michael@0: mRect->append(title); michael@0: } michael@0: mRect->append("("); michael@0: mRect->appendScalar(rect.left()); michael@0: mRect->append(", "); michael@0: mRect->appendScalar(rect.top()); michael@0: mRect->append(", "); michael@0: mRect->appendScalar(rect.right()); michael@0: mRect->append(", "); michael@0: mRect->appendScalar(rect.bottom()); michael@0: mRect->append(")"); michael@0: return mRect; michael@0: } michael@0: michael@0: SkString* SkObjectParser::RRectToString(const SkRRect& rrect, const char* title) { michael@0: michael@0: SkString* mRRect = new SkString; michael@0: michael@0: if (NULL == title) { michael@0: mRRect->append("SkRRect ("); michael@0: if (rrect.isEmpty()) { michael@0: mRRect->append("empty"); michael@0: } else if (rrect.isRect()) { michael@0: mRRect->append("rect"); michael@0: } else if (rrect.isOval()) { michael@0: mRRect->append("oval"); michael@0: } else if (rrect.isSimple()) { michael@0: mRRect->append("simple"); michael@0: } else { michael@0: SkASSERT(rrect.isComplex()); michael@0: mRRect->append("complex"); michael@0: } michael@0: mRRect->append("): "); michael@0: } else { michael@0: mRRect->append(title); michael@0: } michael@0: mRRect->append("("); michael@0: mRRect->appendScalar(rrect.rect().left()); michael@0: mRRect->append(", "); michael@0: mRRect->appendScalar(rrect.rect().top()); michael@0: mRRect->append(", "); michael@0: mRRect->appendScalar(rrect.rect().right()); michael@0: mRRect->append(", "); michael@0: mRRect->appendScalar(rrect.rect().bottom()); michael@0: mRRect->append(") radii: ("); michael@0: for (int i = 0; i < 4; ++i) { michael@0: const SkVector& radii = rrect.radii((SkRRect::Corner) i); michael@0: mRRect->appendScalar(radii.fX); michael@0: mRRect->append(", "); michael@0: mRRect->appendScalar(radii.fY); michael@0: if (i < 3) { michael@0: mRRect->append(", "); michael@0: } michael@0: } michael@0: mRRect->append(")"); michael@0: return mRRect; michael@0: } michael@0: michael@0: SkString* SkObjectParser::RegionOpToString(SkRegion::Op op) { michael@0: SkString* mOp = new SkString("SkRegion::Op: "); michael@0: if (op == SkRegion::kDifference_Op) { michael@0: mOp->append("kDifference_Op"); michael@0: } else if (op == SkRegion::kIntersect_Op) { michael@0: mOp->append("kIntersect_Op"); michael@0: } else if (op == SkRegion::kUnion_Op) { michael@0: mOp->append("kUnion_Op"); michael@0: } else if (op == SkRegion::kXOR_Op) { michael@0: mOp->append("kXOR_Op"); michael@0: } else if (op == SkRegion::kReverseDifference_Op) { michael@0: mOp->append("kReverseDifference_Op"); michael@0: } else if (op == SkRegion::kReplace_Op) { michael@0: mOp->append("kReplace_Op"); michael@0: } else { michael@0: mOp->append("Unknown Type"); michael@0: } michael@0: return mOp; michael@0: } michael@0: michael@0: SkString* SkObjectParser::RegionToString(const SkRegion& region) { michael@0: SkString* mRegion = new SkString("SkRegion: Data unavailable."); michael@0: return mRegion; michael@0: } michael@0: michael@0: SkString* SkObjectParser::SaveFlagsToString(SkCanvas::SaveFlags flags) { michael@0: SkString* mFlags = new SkString("SkCanvas::SaveFlags: "); michael@0: if (flags & SkCanvas::kMatrix_SaveFlag) { michael@0: mFlags->append("kMatrix_SaveFlag "); michael@0: } michael@0: if (flags & SkCanvas::kClip_SaveFlag) { michael@0: mFlags->append("kClip_SaveFlag "); michael@0: } michael@0: if (flags & SkCanvas::kHasAlphaLayer_SaveFlag) { michael@0: mFlags->append("kHasAlphaLayer_SaveFlag "); michael@0: } michael@0: if (flags & SkCanvas::kFullColorLayer_SaveFlag) { michael@0: mFlags->append("kFullColorLayer_SaveFlag "); michael@0: } michael@0: if (flags & SkCanvas::kClipToLayer_SaveFlag) { michael@0: mFlags->append("kClipToLayer_SaveFlag "); michael@0: } michael@0: return mFlags; michael@0: } michael@0: michael@0: SkString* SkObjectParser::ScalarToString(SkScalar x, const char* text) { michael@0: SkString* mScalar = new SkString(text); michael@0: mScalar->append(" "); michael@0: mScalar->appendScalar(x); michael@0: return mScalar; michael@0: } michael@0: michael@0: SkString* SkObjectParser::TextToString(const void* text, size_t byteLength, michael@0: SkPaint::TextEncoding encoding) { michael@0: michael@0: SkString* decodedText = new SkString(); michael@0: switch (encoding) { michael@0: case SkPaint::kUTF8_TextEncoding: { michael@0: decodedText->append("UTF-8: "); michael@0: decodedText->append((const char*)text, byteLength); michael@0: break; michael@0: } michael@0: case SkPaint::kUTF16_TextEncoding: { michael@0: decodedText->append("UTF-16: "); michael@0: size_t sizeNeeded = SkUTF16_ToUTF8((uint16_t*)text, michael@0: SkToS32(byteLength / 2), michael@0: NULL); michael@0: SkAutoSTMalloc<0x100, char> utf8(sizeNeeded); michael@0: SkUTF16_ToUTF8((uint16_t*)text, SkToS32(byteLength / 2), utf8); michael@0: decodedText->append(utf8, sizeNeeded); michael@0: break; michael@0: } michael@0: case SkPaint::kUTF32_TextEncoding: { michael@0: decodedText->append("UTF-32: "); michael@0: const SkUnichar* begin = (const SkUnichar*)text; michael@0: const SkUnichar* end = (const SkUnichar*)((const char*)text + byteLength); michael@0: for (const SkUnichar* unichar = begin; unichar < end; ++unichar) { michael@0: decodedText->appendUnichar(*unichar); michael@0: } michael@0: break; michael@0: } michael@0: case SkPaint::kGlyphID_TextEncoding: { michael@0: decodedText->append("GlyphID: "); michael@0: const uint16_t* begin = (const uint16_t*)text; michael@0: const uint16_t* end = (const uint16_t*)((const char*)text + byteLength); michael@0: for (const uint16_t* glyph = begin; glyph < end; ++glyph) { michael@0: decodedText->append("0x"); michael@0: decodedText->appendHex(*glyph); michael@0: decodedText->append(" "); michael@0: } michael@0: break; michael@0: } michael@0: default: michael@0: decodedText->append("Unknown text encoding."); michael@0: break; michael@0: } michael@0: michael@0: return decodedText; michael@0: }