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 SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2); |
| 442 |
| 443 AutoElement elem("text", fWriter, fResourceBucket, draw, paint); |
| 444 elem.addFontAttributes(paint); |
| 445 |
| 446 SkString xStr; |
| 447 SkString yStr; |
| 448 for (int i = 0; i < paint.countText(text, len); ++i) { |
| 449 xStr.appendf("%.8g, ", offset.x() + pos[i * scalarsPerPos]); |
| 450 |
| 451 if (scalarsPerPos == 2) { |
| 452 yStr.appendf("%.8g, ", offset.y() + pos[i * scalarsPerPos + 1]); |
| 453 } |
| 454 } |
| 455 |
| 456 if (scalarsPerPos != 2) { |
| 457 yStr.appendScalar(offset.y()); |
| 458 } |
| 459 |
| 460 elem.addAttribute("x", xStr); |
| 461 elem.addAttribute("y", yStr); |
| 462 elem.addText(svg_text(text, len, paint)); |
346 } | 463 } |
347 | 464 |
348 void SkSVGDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, co
nst SkPath& path, | 465 void SkSVGDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, co
nst SkPath& path, |
349 const SkMatrix* matrix, const SkPaint& paint) { | 466 const SkMatrix* matrix, const SkPaint& paint) { |
350 // todo | 467 // todo |
351 SkDebugf("unsupported operation: drawTextOnPath()"); | 468 SkDebugf("unsupported operation: drawTextOnPath()\n"); |
352 } | 469 } |
353 | 470 |
354 void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCo
unt, | 471 void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCo
unt, |
355 const SkPoint verts[], const SkPoint texs[], | 472 const SkPoint verts[], const SkPoint texs[], |
356 const SkColor colors[], SkXfermode* xmode, | 473 const SkColor colors[], SkXfermode* xmode, |
357 const uint16_t indices[], int indexCount, | 474 const uint16_t indices[], int indexCount, |
358 const SkPaint& paint) { | 475 const SkPaint& paint) { |
359 // todo | 476 // todo |
360 SkDebugf("unsupported operation: drawVertices()"); | 477 SkDebugf("unsupported operation: drawVertices()\n"); |
361 } | 478 } |
362 | 479 |
363 void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, | 480 void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, |
364 const SkPaint&) { | 481 const SkPaint&) { |
365 // todo | 482 // todo |
366 SkDebugf("unsupported operation: drawDevice()"); | 483 SkDebugf("unsupported operation: drawDevice()\n"); |
367 } | 484 } |
OLD | NEW |