Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1397)

Unified Diff: experimental/svg/SkSVGDevice.cpp

Issue 899683002: [SkSVGDevice] Initial text support (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « experimental/svg/SkSVGDevice.h ('k') | include/xml/SkXMLWriter.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: experimental/svg/SkSVGDevice.cpp
diff --git a/experimental/svg/SkSVGDevice.cpp b/experimental/svg/SkSVGDevice.cpp
index c0ca612cdec3b877f774bc018d885ec16b40e032..61ecf3c76143fcad8a5990a95cddb3737647850f 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,66 @@ 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("&lt;");
+ break;
+ case '>':
+ text->append("&gt;");
+ 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);
+
mtklein 2015/02/03 20:51:08 Worth asserting byteLen alignment for each of thes
f(malita) 2015/02/03 22:51:25 We can probably be even more opinionated and asser
+ switch(paint.getTextEncoding()) {
+ case SkPaint::kGlyphID_TextEncoding: {
+ 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);
+ }
+ } 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);
+ }
+ } break;
+ case SkPaint::kUTF32_TextEncoding: {
+ 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 +158,10 @@ public:
fWriter->addScalarAttribute(name, val);
}
+ void addText(const SkString& text) {
+ fWriter->addText(text);
+ }
+
private:
Resources addResources(const SkPaint& paint);
void addResourceDefs(const SkPaint& paint, Resources* resources);
@@ -333,16 +399,58 @@ void SkSVGDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* s
SkDebugf("unsupported operation: drawBitmapRect()");
}
-void SkSVGDevice::drawText(const SkDraw&, const void* text, size_t len,
+void SkSVGDevice::AddFontAttributes(const SkPaint& paint, AutoElement* elem) {
mtklein 2015/02/03 20:51:08 void AutoElement::addFontAttributes(const SkPaint&
f(malita) 2015/02/03 22:51:25 Done.
+ elem->addAttribute("font-size", paint.getTextSize());
+
+ SkTypeface::Style style = paint.getTypeface()->style();
+ if (style & SkTypeface::kItalic) {
+ elem->addAttribute("font-style", "italic");
+ }
+ if (style & SkTypeface::kBold) {
+ elem->addAttribute("font-weight", "bold");
+ }
+
+ SkAutoTUnref<const SkTypeface> tface(paint.getTypeface() ?
+ SkRef(paint.getTypeface()) : SkTypeface::RefDefault(style));
+ SkString familyName;
+ tface->getFamilyName(&familyName);
+ if (!familyName.isEmpty()) {
+ elem->addAttribute("font-family", familyName);
+ }
+}
+
+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);
+ AddFontAttributes(paint, &elem);
+ 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) {
+ AutoElement elem("text", fWriter, fResourceBucket, draw, paint);
+ AddFontAttributes(paint, &elem);
+
+ SkString xStr;
+ SkString yStr;
+ for (int i = 0; i < paint.countText(text, len); ++i) {
+ SkScalar x = offset.x() + pos[i * scalarsPerPos];
mtklein 2015/02/03 20:51:08 Are offset.x() and offset.y() "dx" and "dy"? If s
f(malita) 2015/02/03 22:51:25 The syntactic rules are quirky though and this wou
+ SkScalar y = offset.y() + (scalarsPerPos > 1 ? pos[i * scalarsPerPos + 1] : 0);
mtklein 2015/02/03 20:51:08 When scalarsPerPos == 1, can we just use a single
f(malita) 2015/02/03 22:51:25 Yeah, I think that will work. Done.
+
+ if (i > 0) {
+ xStr.append(", ");
+ yStr.append(", ");
+ }
+ xStr.appendScalar(x);
+ yStr.appendScalar(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,
« no previous file with comments | « experimental/svg/SkSVGDevice.h ('k') | include/xml/SkXMLWriter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698