| Index: experimental/svg/SkSVGDevice.cpp
|
| diff --git a/experimental/svg/SkSVGDevice.cpp b/experimental/svg/SkSVGDevice.cpp
|
| index c0ca612cdec3b877f774bc018d885ec16b40e032..bd503b7d8fb29d074d7a625d84590beff036af21 100644
|
| --- a/experimental/svg/SkSVGDevice.cpp
|
| +++ b/experimental/svg/SkSVGDevice.cpp
|
| @@ -13,6 +13,8 @@
|
| #include "SkParsePath.h"
|
| #include "SkShader.h"
|
| #include "SkStream.h"
|
| +#include "SkTypeface.h"
|
| +#include "SkUtils.h"
|
| #include "SkXMLWriter.h"
|
|
|
| namespace {
|
| @@ -30,6 +32,71 @@ static SkScalar svg_opacity(SkColor color) {
|
| return SkIntToScalar(SkColorGetA(color)) / SK_AlphaOPAQUE;
|
| }
|
|
|
| +static void append_escaped_unichar(SkUnichar c, SkString* text) {
|
| + switch(c) {
|
| + case '&':
|
| + text->append("&");
|
| + break;
|
| + case '"':
|
| + text->append(""");
|
| + break;
|
| + case '\'':
|
| + text->append("'");
|
| + break;
|
| + case '<':
|
| + text->append("<");
|
| + break;
|
| + case '>':
|
| + text->append(">");
|
| + break;
|
| + default:
|
| + text->appendUnichar(c);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +static SkString svg_text(const void* text, size_t byteLen, const SkPaint& paint) {
|
| + SkString svgText;
|
| + int count = paint.countText(text, byteLen);
|
| +
|
| + switch(paint.getTextEncoding()) {
|
| + case SkPaint::kGlyphID_TextEncoding: {
|
| + SkASSERT(count * sizeof(uint16_t) == byteLen);
|
| + SkAutoSTArray<64, SkUnichar> unichars(count);
|
| + paint.glyphsToUnichars((const uint16_t*)text, count, unichars.get());
|
| + for (int i = 0; i < count; ++i) {
|
| + append_escaped_unichar(unichars[i], &svgText);
|
| + }
|
| + } break;
|
| + case SkPaint::kUTF8_TextEncoding: {
|
| + const char* c8 = reinterpret_cast<const char*>(text);
|
| + for (int i = 0; i < count; ++i) {
|
| + append_escaped_unichar(SkUTF8_NextUnichar(&c8), &svgText);
|
| + }
|
| + SkASSERT(reinterpret_cast<const char*>(text) + byteLen == c8);
|
| + } break;
|
| + case SkPaint::kUTF16_TextEncoding: {
|
| + const uint16_t* c16 = reinterpret_cast<const uint16_t*>(text);
|
| + for (int i = 0; i < count; ++i) {
|
| + append_escaped_unichar(SkUTF16_NextUnichar(&c16), &svgText);
|
| + }
|
| + SkASSERT(SkIsAlign2(byteLen));
|
| + SkASSERT(reinterpret_cast<const uint16_t*>(text) + (byteLen / 2) == c16);
|
| + } break;
|
| + case SkPaint::kUTF32_TextEncoding: {
|
| + SkASSERT(count * sizeof(uint32_t) == byteLen);
|
| + const uint32_t* c32 = reinterpret_cast<const uint32_t*>(text);
|
| + for (int i = 0; i < count; ++i) {
|
| + append_escaped_unichar(c32[i], &svgText);
|
| + }
|
| + } break;
|
| + default:
|
| + SkFAIL("unknown text encoding");
|
| + }
|
| +
|
| + return svgText;
|
| +}
|
| +
|
| struct Resources {
|
| Resources(const SkPaint& paint)
|
| : fPaintServer(svg_color(paint.getColor())) {}
|
| @@ -96,6 +163,12 @@ public:
|
| fWriter->addScalarAttribute(name, val);
|
| }
|
|
|
| + void addText(const SkString& text) {
|
| + fWriter->addText(text.c_str());
|
| + }
|
| +
|
| + void addFontAttributes(const SkPaint&);
|
| +
|
| private:
|
| Resources addResources(const SkPaint& paint);
|
| void addResourceDefs(const SkPaint& paint, Resources* resources);
|
| @@ -234,6 +307,26 @@ SkString SkSVGDevice::AutoElement::addLinearGradientDef(const SkShader::Gradient
|
| return id;
|
| }
|
|
|
| +void SkSVGDevice::AutoElement::addFontAttributes(const SkPaint& paint) {
|
| + this->addAttribute("font-size", paint.getTextSize());
|
| +
|
| + SkTypeface::Style style = paint.getTypeface()->style();
|
| + if (style & SkTypeface::kItalic) {
|
| + this->addAttribute("font-style", "italic");
|
| + }
|
| + if (style & SkTypeface::kBold) {
|
| + this->addAttribute("font-weight", "bold");
|
| + }
|
| +
|
| + SkAutoTUnref<const SkTypeface> tface(paint.getTypeface() ?
|
| + SkRef(paint.getTypeface()) : SkTypeface::RefDefault(style));
|
| + SkString familyName;
|
| + tface->getFamilyName(&familyName);
|
| + if (!familyName.isEmpty()) {
|
| + this->addAttribute("font-family", familyName);
|
| + }
|
| +}
|
| +
|
| SkBaseDevice* SkSVGDevice::Create(const SkISize& size, SkWStream* wstream) {
|
| if (!SkToBool(wstream)) {
|
| return NULL;
|
| @@ -281,7 +374,7 @@ void SkSVGDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
|
| void SkSVGDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
|
| const SkPoint[], const SkPaint& paint) {
|
| // todo
|
| - SkDebugf("unsupported operation: drawPoints()");
|
| + SkDebugf("unsupported operation: drawPoints()\n");
|
| }
|
|
|
| void SkSVGDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
|
| @@ -302,7 +395,7 @@ void SkSVGDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint
|
|
|
| void SkSVGDevice::drawRRect(const SkDraw&, const SkRRect& rr, const SkPaint& paint) {
|
| // todo
|
| - SkDebugf("unsupported operation: drawRRect()");
|
| + SkDebugf("unsupported operation: drawRRect()\n");
|
| }
|
|
|
| void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint& paint,
|
| @@ -317,38 +410,62 @@ void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint
|
| void SkSVGDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
|
| const SkMatrix& matrix, const SkPaint& paint) {
|
| // todo
|
| - SkDebugf("unsupported operation: drawBitmap()");
|
| + SkDebugf("unsupported operation: drawBitmap()\n");
|
| }
|
|
|
| void SkSVGDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
|
| int x, int y, const SkPaint& paint) {
|
| // todo
|
| - SkDebugf("unsupported operation: drawSprite()");
|
| + SkDebugf("unsupported operation: drawSprite()\n");
|
| }
|
|
|
| void SkSVGDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* srcOrNull,
|
| const SkRect& dst, const SkPaint& paint,
|
| SkCanvas::DrawBitmapRectFlags flags) {
|
| // todo
|
| - SkDebugf("unsupported operation: drawBitmapRect()");
|
| + SkDebugf("unsupported operation: drawBitmapRect()\n");
|
| }
|
|
|
| -void SkSVGDevice::drawText(const SkDraw&, const void* text, size_t len,
|
| +void SkSVGDevice::drawText(const SkDraw& draw, const void* text, size_t len,
|
| SkScalar x, SkScalar y, const SkPaint& paint) {
|
| - // todo
|
| - SkDebugf("unsupported operation: drawText()");
|
| + AutoElement elem("text", fWriter, fResourceBucket, draw, paint);
|
| + elem.addFontAttributes(paint);
|
| + elem.addAttribute("x", x);
|
| + elem.addAttribute("y", y);
|
| + elem.addText(svg_text(text, len, paint));
|
| }
|
|
|
| -void SkSVGDevice::drawPosText(const SkDraw&, const void* text, size_t len,const SkScalar pos[],
|
| - int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) {
|
| - // todo
|
| - SkDebugf("unsupported operation: drawPosText()");
|
| +void SkSVGDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
|
| + const SkScalar pos[], int scalarsPerPos, const SkPoint& offset,
|
| + const SkPaint& paint) {
|
| + SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);
|
| +
|
| + AutoElement elem("text", fWriter, fResourceBucket, draw, paint);
|
| + elem.addFontAttributes(paint);
|
| +
|
| + SkString xStr;
|
| + SkString yStr;
|
| + for (int i = 0; i < paint.countText(text, len); ++i) {
|
| + xStr.appendf("%.8g, ", offset.x() + pos[i * scalarsPerPos]);
|
| +
|
| + if (scalarsPerPos == 2) {
|
| + yStr.appendf("%.8g, ", offset.y() + pos[i * scalarsPerPos + 1]);
|
| + }
|
| + }
|
| +
|
| + if (scalarsPerPos != 2) {
|
| + yStr.appendScalar(offset.y());
|
| + }
|
| +
|
| + elem.addAttribute("x", xStr);
|
| + elem.addAttribute("y", yStr);
|
| + elem.addText(svg_text(text, len, paint));
|
| }
|
|
|
| void SkSVGDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath& path,
|
| const SkMatrix* matrix, const SkPaint& paint) {
|
| // todo
|
| - SkDebugf("unsupported operation: drawTextOnPath()");
|
| + SkDebugf("unsupported operation: drawTextOnPath()\n");
|
| }
|
|
|
| void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
|
| @@ -357,11 +474,11 @@ void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCo
|
| const uint16_t indices[], int indexCount,
|
| const SkPaint& paint) {
|
| // todo
|
| - SkDebugf("unsupported operation: drawVertices()");
|
| + SkDebugf("unsupported operation: drawVertices()\n");
|
| }
|
|
|
| void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
|
| const SkPaint&) {
|
| // todo
|
| - SkDebugf("unsupported operation: drawDevice()");
|
| + SkDebugf("unsupported operation: drawDevice()\n");
|
| }
|
|
|