OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkSVGDevice.h" | 8 #include "SkSVGDevice.h" |
9 | 9 |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
11 #include "SkDraw.h" | 11 #include "SkDraw.h" |
12 #include "SkPaint.h" | 12 #include "SkPaint.h" |
13 #include "SkParsePath.h" | 13 #include "SkParsePath.h" |
14 #include "SkShader.h" | 14 #include "SkShader.h" |
15 #include "SkStream.h" | 15 #include "SkStream.h" |
16 #include "SkTypeface.h" | |
17 #include "SkUtils.h" | |
16 #include "SkXMLWriter.h" | 18 #include "SkXMLWriter.h" |
17 | 19 |
18 namespace { | 20 namespace { |
19 | 21 |
20 static SkString svg_color(SkColor color) { | 22 static SkString svg_color(SkColor color) { |
21 SkString colorStr; | 23 SkString colorStr; |
22 colorStr.printf("rgb(%u,%u,%u)", | 24 colorStr.printf("rgb(%u,%u,%u)", |
23 SkColorGetR(color), | 25 SkColorGetR(color), |
24 SkColorGetG(color), | 26 SkColorGetG(color), |
25 SkColorGetB(color)); | 27 SkColorGetB(color)); |
26 return colorStr; | 28 return colorStr; |
27 } | 29 } |
28 | 30 |
29 static SkScalar svg_opacity(SkColor color) { | 31 static SkScalar svg_opacity(SkColor color) { |
30 return SkIntToScalar(SkColorGetA(color)) / SK_AlphaOPAQUE; | 32 return SkIntToScalar(SkColorGetA(color)) / SK_AlphaOPAQUE; |
31 } | 33 } |
32 | 34 |
35 static void append_escaped_unichar(SkUnichar c, SkString* text) { | |
36 switch(c) { | |
37 case '&': | |
38 text->append("&"); | |
39 break; | |
40 case '"': | |
41 text->append("""); | |
42 break; | |
43 case '\'': | |
44 text->append("'"); | |
45 break; | |
46 case '<': | |
47 text->append("<"); | |
48 break; | |
49 case '>': | |
50 text->append(">"); | |
51 break; | |
52 default: | |
53 text->appendUnichar(c); | |
54 break; | |
55 } | |
56 } | |
57 | |
58 static SkString svg_text(const void* text, size_t byteLen, const SkPaint& paint) { | |
59 SkString svgText; | |
60 int count = paint.countText(text, byteLen); | |
61 | |
62 switch(paint.getTextEncoding()) { | |
63 case SkPaint::kGlyphID_TextEncoding: { | |
64 SkASSERT(count * sizeof(uint16_t) == byteLen); | |
65 SkAutoSTArray<64, SkUnichar> unichars(count); | |
66 paint.glyphsToUnichars((const uint16_t*)text, count, unichars.get()); | |
67 for (int i = 0; i < count; ++i) { | |
68 append_escaped_unichar(unichars[i], &svgText); | |
69 } | |
70 } break; | |
71 case SkPaint::kUTF8_TextEncoding: { | |
72 const char* c8 = reinterpret_cast<const char*>(text); | |
73 for (int i = 0; i < count; ++i) { | |
74 append_escaped_unichar(SkUTF8_NextUnichar(&c8), &svgText); | |
75 } | |
76 SkASSERT(reinterpret_cast<const char*>(text) + byteLen == c8); | |
77 } break; | |
78 case SkPaint::kUTF16_TextEncoding: { | |
79 const uint16_t* c16 = reinterpret_cast<const uint16_t*>(text); | |
80 for (int i = 0; i < count; ++i) { | |
81 append_escaped_unichar(SkUTF16_NextUnichar(&c16), &svgText); | |
82 } | |
83 SkASSERT(SkIsAlign2(byteLen)); | |
84 SkASSERT(reinterpret_cast<const uint16_t*>(text) + (byteLen / 2) == c16) ; | |
85 } break; | |
86 case SkPaint::kUTF32_TextEncoding: { | |
87 SkASSERT(count * sizeof(uint32_t) == byteLen); | |
88 const uint32_t* c32 = reinterpret_cast<const uint32_t*>(text); | |
89 for (int i = 0; i < count; ++i) { | |
90 append_escaped_unichar(c32[i], &svgText); | |
91 } | |
92 } break; | |
93 default: | |
94 SkFAIL("unknown text encoding"); | |
95 } | |
96 | |
97 return svgText; | |
98 } | |
99 | |
33 struct Resources { | 100 struct Resources { |
34 Resources(const SkPaint& paint) | 101 Resources(const SkPaint& paint) |
35 : fPaintServer(svg_color(paint.getColor())) {} | 102 : fPaintServer(svg_color(paint.getColor())) {} |
36 | 103 |
37 SkString fPaintServer; | 104 SkString fPaintServer; |
38 }; | 105 }; |
39 | 106 |
40 } | 107 } |
41 | 108 |
42 // For now all this does is serve unique serial IDs, but it will eventually evol ve to track | 109 // For now all this does is serve unique serial IDs, but it will eventually evol ve to track |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 } | 156 } |
90 | 157 |
91 void addAttribute(const char name[], int32_t val) { | 158 void addAttribute(const char name[], int32_t val) { |
92 fWriter->addS32Attribute(name, val); | 159 fWriter->addS32Attribute(name, val); |
93 } | 160 } |
94 | 161 |
95 void addAttribute(const char name[], SkScalar val) { | 162 void addAttribute(const char name[], SkScalar val) { |
96 fWriter->addScalarAttribute(name, val); | 163 fWriter->addScalarAttribute(name, val); |
97 } | 164 } |
98 | 165 |
166 void addText(const SkString& text) { | |
167 fWriter->addText(text); | |
168 } | |
169 | |
170 void addFontAttributes(const SkPaint&); | |
171 | |
99 private: | 172 private: |
100 Resources addResources(const SkPaint& paint); | 173 Resources addResources(const SkPaint& paint); |
101 void addResourceDefs(const SkPaint& paint, Resources* resources); | 174 void addResourceDefs(const SkPaint& paint, Resources* resources); |
102 | 175 |
103 void addPaint(const SkPaint& paint, const Resources& resources); | 176 void addPaint(const SkPaint& paint, const Resources& resources); |
104 void addTransform(const SkMatrix& transform, const char name[] = "transform" ); | 177 void addTransform(const SkMatrix& transform, const char name[] = "transform" ); |
105 | 178 |
106 SkString addLinearGradientDef(const SkShader::GradientInfo& info, const SkSh ader* shader); | 179 SkString addLinearGradientDef(const SkShader::GradientInfo& info, const SkSh ader* shader); |
107 | 180 |
108 SkXMLWriter* fWriter; | 181 SkXMLWriter* fWriter; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 if (SK_AlphaOPAQUE != SkColorGetA(color)) { | 300 if (SK_AlphaOPAQUE != SkColorGetA(color)) { |
228 stop.addAttribute("stop-opacity", svg_opacity(color)); | 301 stop.addAttribute("stop-opacity", svg_opacity(color)); |
229 } | 302 } |
230 } | 303 } |
231 } | 304 } |
232 } | 305 } |
233 | 306 |
234 return id; | 307 return id; |
235 } | 308 } |
236 | 309 |
310 void SkSVGDevice::AutoElement::addFontAttributes(const SkPaint& paint) { | |
311 this->addAttribute("font-size", paint.getTextSize()); | |
312 | |
313 SkTypeface::Style style = paint.getTypeface()->style(); | |
314 if (style & SkTypeface::kItalic) { | |
315 this->addAttribute("font-style", "italic"); | |
316 } | |
317 if (style & SkTypeface::kBold) { | |
318 this->addAttribute("font-weight", "bold"); | |
319 } | |
320 | |
321 SkAutoTUnref<const SkTypeface> tface(paint.getTypeface() ? | |
322 SkRef(paint.getTypeface()) : SkTypeface::RefDefault(style)); | |
323 SkString familyName; | |
324 tface->getFamilyName(&familyName); | |
325 if (!familyName.isEmpty()) { | |
326 this->addAttribute("font-family", familyName); | |
327 } | |
328 } | |
329 | |
237 SkBaseDevice* SkSVGDevice::Create(const SkISize& size, SkWStream* wstream) { | 330 SkBaseDevice* SkSVGDevice::Create(const SkISize& size, SkWStream* wstream) { |
238 if (!SkToBool(wstream)) { | 331 if (!SkToBool(wstream)) { |
239 return NULL; | 332 return NULL; |
240 } | 333 } |
241 | 334 |
242 return SkNEW_ARGS(SkSVGDevice, (size, wstream)); | 335 return SkNEW_ARGS(SkSVGDevice, (size, wstream)); |
243 } | 336 } |
244 | 337 |
245 SkSVGDevice::SkSVGDevice(const SkISize& size, SkWStream* wstream) | 338 SkSVGDevice::SkSVGDevice(const SkISize& size, SkWStream* wstream) |
246 : fWriter(SkNEW_ARGS(SkXMLStreamWriter, (wstream))) | 339 : fWriter(SkNEW_ARGS(SkXMLStreamWriter, (wstream))) |
(...skipping 27 matching lines...) Expand all Loading... | |
274 AutoElement rect("rect", fWriter, fResourceBucket, draw, paint); | 367 AutoElement rect("rect", fWriter, fResourceBucket, draw, paint); |
275 rect.addAttribute("x", 0); | 368 rect.addAttribute("x", 0); |
276 rect.addAttribute("y", 0); | 369 rect.addAttribute("y", 0); |
277 rect.addAttribute("width", this->width()); | 370 rect.addAttribute("width", this->width()); |
278 rect.addAttribute("height", this->height()); | 371 rect.addAttribute("height", this->height()); |
279 } | 372 } |
280 | 373 |
281 void SkSVGDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t cou nt, | 374 void SkSVGDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t cou nt, |
282 const SkPoint[], const SkPaint& paint) { | 375 const SkPoint[], const SkPaint& paint) { |
283 // todo | 376 // todo |
284 SkDebugf("unsupported operation: drawPoints()"); | 377 SkDebugf("unsupported operation: drawPoints()\n"); |
285 } | 378 } |
286 | 379 |
287 void SkSVGDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& p aint) { | 380 void SkSVGDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& p aint) { |
288 AutoElement rect("rect", fWriter, fResourceBucket, draw, paint); | 381 AutoElement rect("rect", fWriter, fResourceBucket, draw, paint); |
289 rect.addAttribute("x", r.fLeft); | 382 rect.addAttribute("x", r.fLeft); |
290 rect.addAttribute("y", r.fTop); | 383 rect.addAttribute("y", r.fTop); |
291 rect.addAttribute("width", r.width()); | 384 rect.addAttribute("width", r.width()); |
292 rect.addAttribute("height", r.height()); | 385 rect.addAttribute("height", r.height()); |
293 } | 386 } |
294 | 387 |
295 void SkSVGDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint & paint) { | 388 void SkSVGDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint & paint) { |
296 AutoElement ellipse("ellipse", fWriter, fResourceBucket, draw, paint); | 389 AutoElement ellipse("ellipse", fWriter, fResourceBucket, draw, paint); |
297 ellipse.addAttribute("cx", oval.centerX()); | 390 ellipse.addAttribute("cx", oval.centerX()); |
298 ellipse.addAttribute("cy", oval.centerY()); | 391 ellipse.addAttribute("cy", oval.centerY()); |
299 ellipse.addAttribute("rx", oval.width() / 2); | 392 ellipse.addAttribute("rx", oval.width() / 2); |
300 ellipse.addAttribute("ry", oval.height() / 2); | 393 ellipse.addAttribute("ry", oval.height() / 2); |
301 } | 394 } |
302 | 395 |
303 void SkSVGDevice::drawRRect(const SkDraw&, const SkRRect& rr, const SkPaint& pai nt) { | 396 void SkSVGDevice::drawRRect(const SkDraw&, const SkRRect& rr, const SkPaint& pai nt) { |
304 // todo | 397 // todo |
305 SkDebugf("unsupported operation: drawRRect()"); | 398 SkDebugf("unsupported operation: drawRRect()\n"); |
306 } | 399 } |
307 | 400 |
308 void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint & paint, | 401 void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint & paint, |
309 const SkMatrix* prePathMatrix, bool pathIsMutable) { | 402 const SkMatrix* prePathMatrix, bool pathIsMutable) { |
310 AutoElement elem("path", fWriter, fResourceBucket, draw, paint); | 403 AutoElement elem("path", fWriter, fResourceBucket, draw, paint); |
311 | 404 |
312 SkString pathStr; | 405 SkString pathStr; |
313 SkParsePath::ToSVGString(path, &pathStr); | 406 SkParsePath::ToSVGString(path, &pathStr); |
314 elem.addAttribute("d", pathStr.c_str()); | 407 elem.addAttribute("d", pathStr.c_str()); |
315 } | 408 } |
316 | 409 |
317 void SkSVGDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, | 410 void SkSVGDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, |
318 const SkMatrix& matrix, const SkPaint& paint) { | 411 const SkMatrix& matrix, const SkPaint& paint) { |
319 // todo | 412 // todo |
320 SkDebugf("unsupported operation: drawBitmap()"); | 413 SkDebugf("unsupported operation: drawBitmap()\n"); |
321 } | 414 } |
322 | 415 |
323 void SkSVGDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, | 416 void SkSVGDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, |
324 int x, int y, const SkPaint& paint) { | 417 int x, int y, const SkPaint& paint) { |
325 // todo | 418 // todo |
326 SkDebugf("unsupported operation: drawSprite()"); | 419 SkDebugf("unsupported operation: drawSprite()\n"); |
327 } | 420 } |
328 | 421 |
329 void SkSVGDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* s rcOrNull, | 422 void SkSVGDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* s rcOrNull, |
330 const SkRect& dst, const SkPaint& paint, | 423 const SkRect& dst, const SkPaint& paint, |
331 SkCanvas::DrawBitmapRectFlags flags) { | 424 SkCanvas::DrawBitmapRectFlags flags) { |
332 // todo | 425 // todo |
333 SkDebugf("unsupported operation: drawBitmapRect()"); | 426 SkDebugf("unsupported operation: drawBitmapRect()\n"); |
334 } | 427 } |
335 | 428 |
336 void SkSVGDevice::drawText(const SkDraw&, const void* text, size_t len, | 429 void SkSVGDevice::drawText(const SkDraw& draw, const void* text, size_t len, |
337 SkScalar x, SkScalar y, const SkPaint& paint) { | 430 SkScalar x, SkScalar y, const SkPaint& paint) { |
338 // todo | 431 AutoElement elem("text", fWriter, fResourceBucket, draw, paint); |
339 SkDebugf("unsupported operation: drawText()"); | 432 elem.addFontAttributes(paint); |
433 elem.addAttribute("x", x); | |
434 elem.addAttribute("y", y); | |
435 elem.addText(svg_text(text, len, paint)); | |
340 } | 436 } |
341 | 437 |
342 void SkSVGDevice::drawPosText(const SkDraw&, const void* text, size_t len,const SkScalar pos[], | 438 void SkSVGDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, |
343 int scalarsPerPos, const SkPoint& offset, const Sk Paint& paint) { | 439 const SkScalar pos[], int scalarsPerPos, const SkP oint& offset, |
344 // todo | 440 const SkPaint& paint) { |
345 SkDebugf("unsupported operation: drawPosText()"); | 441 AutoElement elem("text", fWriter, fResourceBucket, draw, paint); |
442 elem.addFontAttributes(paint); | |
443 | |
444 SkString xStr; | |
445 SkString yStr; | |
446 for (int i = 0; i < paint.countText(text, len); ++i) { | |
447 xStr.appendf("%.8g, ", offset.x() + pos[i * scalarsPerPos]); | |
448 | |
449 if (scalarsPerPos == 2) { | |
450 yStr.appendf("%.8g, ", offset.y() + pos[i * scalarsPerPos + 1]); | |
451 } | |
452 } | |
453 | |
mtklein
2015/02/03 23:56:08
SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2)
f(malita)
2015/02/04 00:46:13
Done.
| |
454 if (scalarsPerPos != 2) { | |
455 yStr.appendScalar(offset.y()); | |
456 } | |
457 | |
458 elem.addAttribute("x", xStr); | |
459 elem.addAttribute("y", yStr); | |
460 elem.addText(svg_text(text, len, paint)); | |
346 } | 461 } |
347 | 462 |
348 void SkSVGDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, co nst SkPath& path, | 463 void SkSVGDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, co nst SkPath& path, |
349 const SkMatrix* matrix, const SkPaint& paint) { | 464 const SkMatrix* matrix, const SkPaint& paint) { |
350 // todo | 465 // todo |
351 SkDebugf("unsupported operation: drawTextOnPath()"); | 466 SkDebugf("unsupported operation: drawTextOnPath()\n"); |
352 } | 467 } |
353 | 468 |
354 void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCo unt, | 469 void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCo unt, |
355 const SkPoint verts[], const SkPoint texs[], | 470 const SkPoint verts[], const SkPoint texs[], |
356 const SkColor colors[], SkXfermode* xmode, | 471 const SkColor colors[], SkXfermode* xmode, |
357 const uint16_t indices[], int indexCount, | 472 const uint16_t indices[], int indexCount, |
358 const SkPaint& paint) { | 473 const SkPaint& paint) { |
359 // todo | 474 // todo |
360 SkDebugf("unsupported operation: drawVertices()"); | 475 SkDebugf("unsupported operation: drawVertices()\n"); |
361 } | 476 } |
362 | 477 |
363 void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, | 478 void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, |
364 const SkPaint&) { | 479 const SkPaint&) { |
365 // todo | 480 // todo |
366 SkDebugf("unsupported operation: drawDevice()"); | 481 SkDebugf("unsupported operation: drawDevice()\n"); |
367 } | 482 } |
OLD | NEW |