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

Side by Side Diff: experimental/svg/SkSVGDevice.cpp

Issue 874853003: [SkSVGDevice] drawTextOnPath() support (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: review comments Created 5 years, 10 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 "round", // kRound_Join 50 "round", // kRound_Join
51 "bevel" // kBevel_Join 51 "bevel" // kBevel_Join
52 }; 52 };
53 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(join_map) == SkPaint::kJoinCount, missing_join_ map_entry); 53 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(join_map) == SkPaint::kJoinCount, missing_join_ map_entry);
54 54
55 static const char* svg_join(SkPaint::Join join) { 55 static const char* svg_join(SkPaint::Join join) {
56 SkASSERT(join < SK_ARRAY_COUNT(join_map)); 56 SkASSERT(join < SK_ARRAY_COUNT(join_map));
57 return join_map[join]; 57 return join_map[join];
58 } 58 }
59 59
60 // Keep in sync with SkPaint::Align
61 static const char* text_align_map[] = {
62 NULL, // kLeft_Align (default)
63 "middle", // kCenter_Align
64 "end" // kRight_Align
65 };
66 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(text_align_map) == SkPaint::kAlignCount,
67 missing_text_align_map_entry);
68 static const char* svg_text_align(SkPaint::Align align) {
69 SkASSERT(align < SK_ARRAY_COUNT(text_align_map));
70 return text_align_map[align];
71 }
72
73 static SkString svg_transform(const SkMatrix& t) {
74 SkASSERT(!t.isIdentity());
75
76 SkString tstr;
77 switch (t.getType()) {
78 case SkMatrix::kPerspective_Mask:
79 SkDebugf("Can't handle perspective matrices.");
80 break;
81 case SkMatrix::kTranslate_Mask:
82 tstr.printf("translate(%g %g)", t.getTranslateX(), t.getTranslateY());
83 break;
84 case SkMatrix::kScale_Mask:
85 tstr.printf("scale(%g %g)", t.getScaleX(), t.getScaleY());
86 break;
87 default:
88 // http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined
89 // | a c e |
90 // | b d f |
91 // | 0 0 1 |
92 tstr.printf("matrix(%g %g %g %g %g %g)",
93 t.getScaleX(), t.getSkewY(),
94 t.getSkewX(), t.getScaleY(),
95 t.getTranslateX(), t.getTranslateY());
96 break;
97 }
98
99 return tstr;
100 }
101
60 static void append_escaped_unichar(SkUnichar c, SkString* text) { 102 static void append_escaped_unichar(SkUnichar c, SkString* text) {
61 switch(c) { 103 switch(c) {
62 case '&': 104 case '&':
63 text->append("&amp;"); 105 text->append("&amp;");
64 break; 106 break;
65 case '"': 107 case '"':
66 text->append("&quot;"); 108 text->append("&quot;");
67 break; 109 break;
68 case '\'': 110 case '\'':
69 text->append("&apos;"); 111 text->append("&apos;");
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 SkString fPaintServer; 171 SkString fPaintServer;
130 SkString fClip; 172 SkString fClip;
131 }; 173 };
132 174
133 } 175 }
134 176
135 // For now all this does is serve unique serial IDs, but it will eventually evol ve to track 177 // For now all this does is serve unique serial IDs, but it will eventually evol ve to track
136 // and deduplicate resources. 178 // and deduplicate resources.
137 class SkSVGDevice::ResourceBucket : ::SkNoncopyable { 179 class SkSVGDevice::ResourceBucket : ::SkNoncopyable {
138 public: 180 public:
139 ResourceBucket() : fGradientCount(0), fClipCount(0) {} 181 ResourceBucket() : fGradientCount(0), fClipCount(0), fPathCount(0) {}
140 182
141 SkString addLinearGradient() { 183 SkString addLinearGradient() {
142 return SkStringPrintf("gradient_%d", fGradientCount++); 184 return SkStringPrintf("gradient_%d", fGradientCount++);
143 } 185 }
144 186
145 SkString addClip() { 187 SkString addClip() {
146 return SkStringPrintf("clip_%d", fClipCount++); 188 return SkStringPrintf("clip_%d", fClipCount++);
147 } 189 }
148 190
191 SkString addPath() {
192 return SkStringPrintf("path_%d", fPathCount++);
193 }
194
149 private: 195 private:
150 uint32_t fGradientCount; 196 uint32_t fGradientCount;
151 uint32_t fClipCount; 197 uint32_t fClipCount;
198 uint32_t fPathCount;
152 }; 199 };
153 200
154 class SkSVGDevice::AutoElement : ::SkNoncopyable { 201 class SkSVGDevice::AutoElement : ::SkNoncopyable {
155 public: 202 public:
156 AutoElement(const char name[], SkXMLWriter* writer) 203 AutoElement(const char name[], SkXMLWriter* writer)
157 : fWriter(writer) 204 : fWriter(writer)
158 , fResourceBucket(NULL) { 205 , fResourceBucket(NULL) {
159 fWriter->startElement(name); 206 fWriter->startElement(name);
160 } 207 }
161 208
162 AutoElement(const char name[], SkXMLWriter* writer, ResourceBucket* bucket, 209 AutoElement(const char name[], SkXMLWriter* writer, ResourceBucket* bucket,
163 const SkDraw& draw, const SkPaint& paint) 210 const SkDraw& draw, const SkPaint& paint)
164 : fWriter(writer) 211 : fWriter(writer)
165 , fResourceBucket(bucket) { 212 , fResourceBucket(bucket) {
166 213
167 Resources res = this->addResources(draw, paint); 214 Resources res = this->addResources(draw, paint);
168 215
169 fWriter->startElement(name); 216 fWriter->startElement(name);
170 217
171 this->addPaint(paint, res); 218 this->addPaint(paint, res);
172 this->addTransform(*draw.fMatrix); 219
220 if (!draw.fMatrix->isIdentity()) {
221 this->addAttribute("transform", svg_transform(*draw.fMatrix));
222 }
173 } 223 }
174 224
175 ~AutoElement() { 225 ~AutoElement() {
176 fWriter->endElement(); 226 fWriter->endElement();
177 } 227 }
178 228
179 void addAttribute(const char name[], const char val[]) { 229 void addAttribute(const char name[], const char val[]) {
180 fWriter->addAttribute(name, val); 230 fWriter->addAttribute(name, val);
181 } 231 }
182 232
183 void addAttribute(const char name[], const SkString& val) { 233 void addAttribute(const char name[], const SkString& val) {
184 fWriter->addAttribute(name, val.c_str()); 234 fWriter->addAttribute(name, val.c_str());
185 } 235 }
186 236
187 void addAttribute(const char name[], int32_t val) { 237 void addAttribute(const char name[], int32_t val) {
188 fWriter->addS32Attribute(name, val); 238 fWriter->addS32Attribute(name, val);
189 } 239 }
190 240
191 void addAttribute(const char name[], SkScalar val) { 241 void addAttribute(const char name[], SkScalar val) {
192 fWriter->addScalarAttribute(name, val); 242 fWriter->addScalarAttribute(name, val);
193 } 243 }
194 244
195 void addText(const SkString& text) { 245 void addText(const SkString& text) {
196 fWriter->addText(text.c_str()); 246 fWriter->addText(text.c_str());
197 } 247 }
198 248
199 void addRectAttributes(const SkRect&); 249 void addRectAttributes(const SkRect&);
200 void addFontAttributes(const SkPaint&); 250 void addPathAttributes(const SkPath&);
251 void addTextAttributes(const SkPaint&);
201 252
202 private: 253 private:
203 Resources addResources(const SkDraw& draw, const SkPaint& paint); 254 Resources addResources(const SkDraw& draw, const SkPaint& paint);
204 void addClipResources(const SkDraw& draw, Resources* resources); 255 void addClipResources(const SkDraw& draw, Resources* resources);
205 void addShaderResources(const SkPaint& paint, Resources* resources); 256 void addShaderResources(const SkPaint& paint, Resources* resources);
206 257
207 void addPaint(const SkPaint& paint, const Resources& resources); 258 void addPaint(const SkPaint& paint, const Resources& resources);
208 void addTransform(const SkMatrix& transform, const char name[] = "transform" );
209 259
210 SkString addLinearGradientDef(const SkShader::GradientInfo& info, const SkSh ader* shader); 260 SkString addLinearGradientDef(const SkShader::GradientInfo& info, const SkSh ader* shader);
211 261
212 SkXMLWriter* fWriter; 262 SkXMLWriter* fWriter;
213 ResourceBucket* fResourceBucket; 263 ResourceBucket* fResourceBucket;
214 }; 264 };
215 265
216 void SkSVGDevice::AutoElement::addPaint(const SkPaint& paint, const Resources& r esources) { 266 void SkSVGDevice::AutoElement::addPaint(const SkPaint& paint, const Resources& r esources) {
217 SkPaint::Style style = paint.getStyle(); 267 SkPaint::Style style = paint.getStyle();
218 if (style == SkPaint::kFill_Style || style == SkPaint::kStrokeAndFill_Style) { 268 if (style == SkPaint::kFill_Style || style == SkPaint::kStrokeAndFill_Style) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 } else { 305 } else {
256 SkASSERT(style == SkPaint::kFill_Style); 306 SkASSERT(style == SkPaint::kFill_Style);
257 this->addAttribute("stroke", "none"); 307 this->addAttribute("stroke", "none");
258 } 308 }
259 309
260 if (!resources.fClip.isEmpty()) { 310 if (!resources.fClip.isEmpty()) {
261 this->addAttribute("clip-path", resources.fClip); 311 this->addAttribute("clip-path", resources.fClip);
262 } 312 }
263 } 313 }
264 314
265 void SkSVGDevice::AutoElement::addTransform(const SkMatrix& t, const char name[] ) {
266 if (t.isIdentity()) {
267 return;
268 }
269
270 SkString tstr;
271 switch (t.getType()) {
272 case SkMatrix::kPerspective_Mask:
273 SkDebugf("Can't handle perspective matrices.");
274 break;
275 case SkMatrix::kTranslate_Mask:
276 tstr.printf("translate(%g %g)",
277 SkScalarToFloat(t.getTranslateX()),
278 SkScalarToFloat(t.getTranslateY()));
279 break;
280 case SkMatrix::kScale_Mask:
281 tstr.printf("scale(%g %g)",
282 SkScalarToFloat(t.getScaleX()),
283 SkScalarToFloat(t.getScaleY()));
284 break;
285 default:
286 tstr.printf("matrix(%g %g %g %g %g %g)",
287 SkScalarToFloat(t.getScaleX()), SkScalarToFloat(t.getSkewY( )),
288 SkScalarToFloat(t.getSkewX()), SkScalarToFloat(t.getScaleY( )),
289 SkScalarToFloat(t.getTranslateX()), SkScalarToFloat(t.getTr anslateY()));
290 break;
291 }
292
293 fWriter->addAttribute(name, tstr.c_str());
294 }
295
296 Resources SkSVGDevice::AutoElement::addResources(const SkDraw& draw, const SkPai nt& paint) { 315 Resources SkSVGDevice::AutoElement::addResources(const SkDraw& draw, const SkPai nt& paint) {
297 Resources resources(paint); 316 Resources resources(paint);
298 317
299 // FIXME: this is a weak heuristic and we end up with LOTS of redundant clip s. 318 // FIXME: this is a weak heuristic and we end up with LOTS of redundant clip s.
300 bool hasClip = !draw.fClipStack->isWideOpen(); 319 bool hasClip = !draw.fClipStack->isWideOpen();
301 bool hasShader = SkToBool(paint.getShader()); 320 bool hasShader = SkToBool(paint.getShader());
302 321
303 if (hasClip || hasShader) { 322 if (hasClip || hasShader) {
304 AutoElement defs("defs", fWriter); 323 AutoElement defs("defs", fWriter);
305 324
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 AutoElement clipPathElement("clipPath", fWriter); 374 AutoElement clipPathElement("clipPath", fWriter);
356 clipPathElement.addAttribute("id", clipID); 375 clipPathElement.addAttribute("id", clipID);
357 376
358 SkRect clipRect = SkRect::MakeEmpty(); 377 SkRect clipRect = SkRect::MakeEmpty();
359 if (clipPath.isEmpty() || clipPath.isRect(&clipRect)) { 378 if (clipPath.isEmpty() || clipPath.isRect(&clipRect)) {
360 AutoElement rectElement("rect", fWriter); 379 AutoElement rectElement("rect", fWriter);
361 rectElement.addRectAttributes(clipRect); 380 rectElement.addRectAttributes(clipRect);
362 rectElement.addAttribute("clip-rule", clipRule); 381 rectElement.addAttribute("clip-rule", clipRule);
363 } else { 382 } else {
364 AutoElement pathElement("path", fWriter); 383 AutoElement pathElement("path", fWriter);
365 SkString pathStr; 384 pathElement.addPathAttributes(clipPath);
366 SkParsePath::ToSVGString(clipPath, &pathStr);
367 pathElement.addAttribute("d", pathStr.c_str());
368 pathElement.addAttribute("clip-rule", clipRule); 385 pathElement.addAttribute("clip-rule", clipRule);
369 } 386 }
370 } 387 }
371 388
372 resources->fClip.printf("url(#%s)", clipID.c_str()); 389 resources->fClip.printf("url(#%s)", clipID.c_str());
373 } 390 }
374 391
375 SkString SkSVGDevice::AutoElement::addLinearGradientDef(const SkShader::Gradient Info& info, 392 SkString SkSVGDevice::AutoElement::addLinearGradientDef(const SkShader::Gradient Info& info,
376 const SkShader* shader) { 393 const SkShader* shader) {
377 SkASSERT(fResourceBucket); 394 SkASSERT(fResourceBucket);
378 SkString id = fResourceBucket->addLinearGradient(); 395 SkString id = fResourceBucket->addLinearGradient();
379 396
380 { 397 {
381 AutoElement gradient("linearGradient", fWriter); 398 AutoElement gradient("linearGradient", fWriter);
382 399
383 gradient.addAttribute("id", id); 400 gradient.addAttribute("id", id);
384 gradient.addAttribute("gradientUnits", "userSpaceOnUse"); 401 gradient.addAttribute("gradientUnits", "userSpaceOnUse");
385 gradient.addAttribute("x1", info.fPoint[0].x()); 402 gradient.addAttribute("x1", info.fPoint[0].x());
386 gradient.addAttribute("y1", info.fPoint[0].y()); 403 gradient.addAttribute("y1", info.fPoint[0].y());
387 gradient.addAttribute("x2", info.fPoint[1].x()); 404 gradient.addAttribute("x2", info.fPoint[1].x());
388 gradient.addAttribute("y2", info.fPoint[1].y()); 405 gradient.addAttribute("y2", info.fPoint[1].y());
389 gradient.addTransform(shader->getLocalMatrix(), "gradientTransform"); 406
407 if (!shader->getLocalMatrix().isIdentity()) {
408 this->addAttribute("gradientTransform", svg_transform(shader->getLoc alMatrix()));
409 }
390 410
391 SkASSERT(info.fColorCount >= 2); 411 SkASSERT(info.fColorCount >= 2);
392 for (int i = 0; i < info.fColorCount; ++i) { 412 for (int i = 0; i < info.fColorCount; ++i) {
393 SkColor color = info.fColors[i]; 413 SkColor color = info.fColors[i];
394 SkString colorStr(svg_color(color)); 414 SkString colorStr(svg_color(color));
395 415
396 { 416 {
397 AutoElement stop("stop", fWriter); 417 AutoElement stop("stop", fWriter);
398 stop.addAttribute("offset", info.fColorOffsets[i]); 418 stop.addAttribute("offset", info.fColorOffsets[i]);
399 stop.addAttribute("stop-color", colorStr.c_str()); 419 stop.addAttribute("stop-color", colorStr.c_str());
(...skipping 14 matching lines...) Expand all
414 this->addAttribute("x", rect.x()); 434 this->addAttribute("x", rect.x());
415 } 435 }
416 if (rect.y() != 0) { 436 if (rect.y() != 0) {
417 this->addAttribute("y", rect.y()); 437 this->addAttribute("y", rect.y());
418 } 438 }
419 439
420 this->addAttribute("width", rect.width()); 440 this->addAttribute("width", rect.width());
421 this->addAttribute("height", rect.height()); 441 this->addAttribute("height", rect.height());
422 } 442 }
423 443
424 void SkSVGDevice::AutoElement::addFontAttributes(const SkPaint& paint) { 444 void SkSVGDevice::AutoElement::addPathAttributes(const SkPath& path) {
445 SkString pathData;
446 SkParsePath::ToSVGString(path, &pathData);
447 this->addAttribute("d", pathData);
448 }
449
450 void SkSVGDevice::AutoElement::addTextAttributes(const SkPaint& paint) {
425 this->addAttribute("font-size", paint.getTextSize()); 451 this->addAttribute("font-size", paint.getTextSize());
426 452
427 SkTypeface::Style style = paint.getTypeface()->style(); 453 SkTypeface::Style style = paint.getTypeface()->style();
428 if (style & SkTypeface::kItalic) { 454 if (style & SkTypeface::kItalic) {
429 this->addAttribute("font-style", "italic"); 455 this->addAttribute("font-style", "italic");
430 } 456 }
431 if (style & SkTypeface::kBold) { 457 if (style & SkTypeface::kBold) {
432 this->addAttribute("font-weight", "bold"); 458 this->addAttribute("font-weight", "bold");
433 } 459 }
434 460
435 SkAutoTUnref<const SkTypeface> tface(paint.getTypeface() ? 461 SkAutoTUnref<const SkTypeface> tface(paint.getTypeface() ?
436 SkRef(paint.getTypeface()) : SkTypeface::RefDefault(style)); 462 SkRef(paint.getTypeface()) : SkTypeface::RefDefault(style));
437 SkString familyName; 463 SkString familyName;
438 tface->getFamilyName(&familyName); 464 tface->getFamilyName(&familyName);
439 if (!familyName.isEmpty()) { 465 if (!familyName.isEmpty()) {
440 this->addAttribute("font-family", familyName); 466 this->addAttribute("font-family", familyName);
441 } 467 }
468
469 if (const char* textAlign = svg_text_align(paint.getTextAlign())) {
470 this->addAttribute("text-anchor", textAlign);
471 }
442 } 472 }
443 473
444 SkBaseDevice* SkSVGDevice::Create(const SkISize& size, SkWStream* wstream) { 474 SkBaseDevice* SkSVGDevice::Create(const SkISize& size, SkWStream* wstream) {
445 if (!SkToBool(wstream)) { 475 if (!SkToBool(wstream)) {
446 return NULL; 476 return NULL;
447 } 477 }
448 478
449 return SkNEW_ARGS(SkSVGDevice, (size, wstream)); 479 return SkNEW_ARGS(SkSVGDevice, (size, wstream));
450 } 480 }
451 481
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 } 533 }
504 534
505 void SkSVGDevice::drawRRect(const SkDraw&, const SkRRect& rr, const SkPaint& pai nt) { 535 void SkSVGDevice::drawRRect(const SkDraw&, const SkRRect& rr, const SkPaint& pai nt) {
506 // todo 536 // todo
507 SkDebugf("unsupported operation: drawRRect()\n"); 537 SkDebugf("unsupported operation: drawRRect()\n");
508 } 538 }
509 539
510 void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint & paint, 540 void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint & paint,
511 const SkMatrix* prePathMatrix, bool pathIsMutable) { 541 const SkMatrix* prePathMatrix, bool pathIsMutable) {
512 AutoElement elem("path", fWriter, fResourceBucket, draw, paint); 542 AutoElement elem("path", fWriter, fResourceBucket, draw, paint);
513 543 elem.addPathAttributes(path);
514 SkString pathStr;
515 SkParsePath::ToSVGString(path, &pathStr);
516 elem.addAttribute("d", pathStr.c_str());
517 } 544 }
518 545
519 void SkSVGDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, 546 void SkSVGDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
520 const SkMatrix& matrix, const SkPaint& paint) { 547 const SkMatrix& matrix, const SkPaint& paint) {
521 // todo 548 // todo
522 SkDebugf("unsupported operation: drawBitmap()\n"); 549 SkDebugf("unsupported operation: drawBitmap()\n");
523 } 550 }
524 551
525 void SkSVGDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, 552 void SkSVGDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
526 int x, int y, const SkPaint& paint) { 553 int x, int y, const SkPaint& paint) {
527 // todo 554 // todo
528 SkDebugf("unsupported operation: drawSprite()\n"); 555 SkDebugf("unsupported operation: drawSprite()\n");
529 } 556 }
530 557
531 void SkSVGDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* s rcOrNull, 558 void SkSVGDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* s rcOrNull,
532 const SkRect& dst, const SkPaint& paint, 559 const SkRect& dst, const SkPaint& paint,
533 SkCanvas::DrawBitmapRectFlags flags) { 560 SkCanvas::DrawBitmapRectFlags flags) {
534 // todo 561 // todo
535 SkDebugf("unsupported operation: drawBitmapRect()\n"); 562 SkDebugf("unsupported operation: drawBitmapRect()\n");
536 } 563 }
537 564
538 void SkSVGDevice::drawText(const SkDraw& draw, const void* text, size_t len, 565 void SkSVGDevice::drawText(const SkDraw& draw, const void* text, size_t len,
539 SkScalar x, SkScalar y, const SkPaint& paint) { 566 SkScalar x, SkScalar y, const SkPaint& paint) {
540 AutoElement elem("text", fWriter, fResourceBucket, draw, paint); 567 AutoElement elem("text", fWriter, fResourceBucket, draw, paint);
541 elem.addFontAttributes(paint); 568 elem.addTextAttributes(paint);
542 elem.addAttribute("x", x); 569 elem.addAttribute("x", x);
543 elem.addAttribute("y", y); 570 elem.addAttribute("y", y);
544 elem.addText(svg_text(text, len, paint)); 571 elem.addText(svg_text(text, len, paint));
545 } 572 }
546 573
547 void SkSVGDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, 574 void SkSVGDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
548 const SkScalar pos[], int scalarsPerPos, const SkP oint& offset, 575 const SkScalar pos[], int scalarsPerPos, const SkP oint& offset,
549 const SkPaint& paint) { 576 const SkPaint& paint) {
550 SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2); 577 SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);
551 578
552 AutoElement elem("text", fWriter, fResourceBucket, draw, paint); 579 AutoElement elem("text", fWriter, fResourceBucket, draw, paint);
553 elem.addFontAttributes(paint); 580 elem.addTextAttributes(paint);
554 581
555 SkString xStr; 582 SkString xStr;
556 SkString yStr; 583 SkString yStr;
557 for (int i = 0; i < paint.countText(text, len); ++i) { 584 for (int i = 0; i < paint.countText(text, len); ++i) {
558 xStr.appendf("%.8g, ", offset.x() + pos[i * scalarsPerPos]); 585 xStr.appendf("%.8g, ", offset.x() + pos[i * scalarsPerPos]);
559 586
560 if (scalarsPerPos == 2) { 587 if (scalarsPerPos == 2) {
561 yStr.appendf("%.8g, ", offset.y() + pos[i * scalarsPerPos + 1]); 588 yStr.appendf("%.8g, ", offset.y() + pos[i * scalarsPerPos + 1]);
562 } 589 }
563 } 590 }
564 591
565 if (scalarsPerPos != 2) { 592 if (scalarsPerPos != 2) {
566 yStr.appendScalar(offset.y()); 593 yStr.appendScalar(offset.y());
567 } 594 }
568 595
569 elem.addAttribute("x", xStr); 596 elem.addAttribute("x", xStr);
570 elem.addAttribute("y", yStr); 597 elem.addAttribute("y", yStr);
571 elem.addText(svg_text(text, len, paint)); 598 elem.addText(svg_text(text, len, paint));
572 } 599 }
573 600
574 void SkSVGDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, co nst SkPath& path, 601 void SkSVGDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, co nst SkPath& path,
575 const SkMatrix* matrix, const SkPaint& paint) { 602 const SkMatrix* matrix, const SkPaint& paint) {
576 // todo 603 SkString pathID = fResourceBucket->addPath();
577 SkDebugf("unsupported operation: drawTextOnPath()\n"); 604
605 {
606 AutoElement defs("defs", fWriter);
607 AutoElement pathElement("path", fWriter);
608 pathElement.addAttribute("id", pathID);
609 pathElement.addPathAttributes(path);
610
611 }
612
613 {
614 AutoElement textElement("text", fWriter);
615 textElement.addTextAttributes(paint);
616
617 if (matrix && !matrix->isIdentity()) {
618 textElement.addAttribute("transform", svg_transform(*matrix));
619 }
620
621 {
622 AutoElement textPathElement("textPath", fWriter);
623 textPathElement.addAttribute("xlink:href", SkStringPrintf("#%s", pat hID.c_str()));
624
625 if (paint.getTextAlign() != SkPaint::kLeft_Align) {
626 SkASSERT(paint.getTextAlign() == SkPaint::kCenter_Align ||
627 paint.getTextAlign() == SkPaint::kRight_Align);
628 textPathElement.addAttribute("startOffset",
629 paint.getTextAlign() == SkPaint::kCenter_Align ? "50%" : "10 0%");
630 }
631
632 textPathElement.addText(svg_text(text, len, paint));
633 }
634 }
578 } 635 }
579 636
580 void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCo unt, 637 void SkSVGDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCo unt,
581 const SkPoint verts[], const SkPoint texs[], 638 const SkPoint verts[], const SkPoint texs[],
582 const SkColor colors[], SkXfermode* xmode, 639 const SkColor colors[], SkXfermode* xmode,
583 const uint16_t indices[], int indexCount, 640 const uint16_t indices[], int indexCount,
584 const SkPaint& paint) { 641 const SkPaint& paint) {
585 // todo 642 // todo
586 SkDebugf("unsupported operation: drawVertices()\n"); 643 SkDebugf("unsupported operation: drawVertices()\n");
587 } 644 }
588 645
589 void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, 646 void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
590 const SkPaint&) { 647 const SkPaint&) {
591 // todo 648 // todo
592 SkDebugf("unsupported operation: drawDevice()\n"); 649 SkDebugf("unsupported operation: drawDevice()\n");
593 } 650 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698