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

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

Issue 959883003: [SkSVGDevice] drawBitmap* support (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: win warning fix Created 5 years, 9 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 | « src/svg/SkSVGDevice.h ('k') | 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 "SkBase64.h"
10 #include "SkBitmap.h" 11 #include "SkBitmap.h"
11 #include "SkChecksum.h" 12 #include "SkChecksum.h"
13 #include "SkData.h"
12 #include "SkDraw.h" 14 #include "SkDraw.h"
15 #include "SkImageEncoder.h"
13 #include "SkPaint.h" 16 #include "SkPaint.h"
14 #include "SkParsePath.h" 17 #include "SkParsePath.h"
15 #include "SkPathOps.h"
16 #include "SkShader.h" 18 #include "SkShader.h"
17 #include "SkStream.h" 19 #include "SkStream.h"
18 #include "SkTHash.h" 20 #include "SkTHash.h"
19 #include "SkTypeface.h" 21 #include "SkTypeface.h"
20 #include "SkUtils.h" 22 #include "SkUtils.h"
21 #include "SkXMLWriter.h" 23 #include "SkXMLWriter.h"
22 24
23 namespace { 25 namespace {
24 26
25 static SkString svg_color(SkColor color) { 27 static SkString svg_color(SkColor color) {
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 SkString fText, fPosX, fPosY; 246 SkString fText, fPosX, fPosY;
245 bool fLastCharWasWhitespace; 247 bool fLastCharWasWhitespace;
246 }; 248 };
247 249
248 } 250 }
249 251
250 // For now all this does is serve unique serial IDs, but it will eventually evol ve to track 252 // For now all this does is serve unique serial IDs, but it will eventually evol ve to track
251 // and deduplicate resources. 253 // and deduplicate resources.
252 class SkSVGDevice::ResourceBucket : ::SkNoncopyable { 254 class SkSVGDevice::ResourceBucket : ::SkNoncopyable {
253 public: 255 public:
254 ResourceBucket() : fGradientCount(0), fClipCount(0), fPathCount(0) {} 256 ResourceBucket() : fGradientCount(0), fClipCount(0), fPathCount(0), fImageCo unt(0) {}
255 257
256 SkString addLinearGradient() { 258 SkString addLinearGradient() {
257 return SkStringPrintf("gradient_%d", fGradientCount++); 259 return SkStringPrintf("gradient_%d", fGradientCount++);
258 } 260 }
259 261
260 SkString addClip() { 262 SkString addClip() {
261 return SkStringPrintf("clip_%d", fClipCount++); 263 return SkStringPrintf("clip_%d", fClipCount++);
262 } 264 }
263 265
264 SkString addPath() { 266 SkString addPath() {
265 return SkStringPrintf("path_%d", fPathCount++); 267 return SkStringPrintf("path_%d", fPathCount++);
266 } 268 }
267 269
270 SkString addImage() {
271 return SkStringPrintf("img_%d", fImageCount++);
272 }
273
268 private: 274 private:
269 uint32_t fGradientCount; 275 uint32_t fGradientCount;
270 uint32_t fClipCount; 276 uint32_t fClipCount;
271 uint32_t fPathCount; 277 uint32_t fPathCount;
278 uint32_t fImageCount;
272 }; 279 };
273 280
274 class SkSVGDevice::AutoElement : ::SkNoncopyable { 281 class SkSVGDevice::AutoElement : ::SkNoncopyable {
275 public: 282 public:
276 AutoElement(const char name[], SkXMLWriter* writer) 283 AutoElement(const char name[], SkXMLWriter* writer)
277 : fWriter(writer) 284 : fWriter(writer)
278 , fResourceBucket(NULL) { 285 , fResourceBucket(NULL) {
279 fWriter->startElement(name); 286 fWriter->startElement(name);
280 } 287 }
281 288
282 AutoElement(const char name[], SkXMLWriter* writer, ResourceBucket* bucket, 289 AutoElement(const char name[], SkXMLWriter* writer, ResourceBucket* bucket,
283 const SkDraw& draw, const SkPaint& paint) 290 const SkDraw& draw, const SkPaint& paint)
284 : fWriter(writer) 291 : fWriter(writer)
285 , fResourceBucket(bucket) { 292 , fResourceBucket(bucket) {
286 293
287 Resources res = this->addResources(draw, paint); 294 Resources res = this->addResources(draw, paint);
295 if (!res.fClip.isEmpty()) {
296 // The clip is in device space. Apply it via a <g> wrapper to avoid local transform
297 // interference.
298 fClipGroup.reset(SkNEW_ARGS(AutoElement, ("g", fWriter)));
299 fClipGroup->addAttribute("clip-path",res.fClip);
300 }
288 301
289 fWriter->startElement(name); 302 fWriter->startElement(name);
290 303
291 this->addPaint(paint, res); 304 this->addPaint(paint, res);
292 305
293 if (!draw.fMatrix->isIdentity()) { 306 if (!draw.fMatrix->isIdentity()) {
294 this->addAttribute("transform", svg_transform(*draw.fMatrix)); 307 this->addAttribute("transform", svg_transform(*draw.fMatrix));
295 } 308 }
296 } 309 }
297 310
(...skipping 27 matching lines...) Expand all
325 338
326 private: 339 private:
327 Resources addResources(const SkDraw& draw, const SkPaint& paint); 340 Resources addResources(const SkDraw& draw, const SkPaint& paint);
328 void addClipResources(const SkDraw& draw, Resources* resources); 341 void addClipResources(const SkDraw& draw, Resources* resources);
329 void addShaderResources(const SkPaint& paint, Resources* resources); 342 void addShaderResources(const SkPaint& paint, Resources* resources);
330 343
331 void addPaint(const SkPaint& paint, const Resources& resources); 344 void addPaint(const SkPaint& paint, const Resources& resources);
332 345
333 SkString addLinearGradientDef(const SkShader::GradientInfo& info, const SkSh ader* shader); 346 SkString addLinearGradientDef(const SkShader::GradientInfo& info, const SkSh ader* shader);
334 347
335 SkXMLWriter* fWriter; 348 SkXMLWriter* fWriter;
336 ResourceBucket* fResourceBucket; 349 ResourceBucket* fResourceBucket;
350 SkAutoTDelete<AutoElement> fClipGroup;
337 }; 351 };
338 352
339 void SkSVGDevice::AutoElement::addPaint(const SkPaint& paint, const Resources& r esources) { 353 void SkSVGDevice::AutoElement::addPaint(const SkPaint& paint, const Resources& r esources) {
340 SkPaint::Style style = paint.getStyle(); 354 SkPaint::Style style = paint.getStyle();
341 if (style == SkPaint::kFill_Style || style == SkPaint::kStrokeAndFill_Style) { 355 if (style == SkPaint::kFill_Style || style == SkPaint::kStrokeAndFill_Style) {
342 this->addAttribute("fill", resources.fPaintServer); 356 this->addAttribute("fill", resources.fPaintServer);
343 357
344 if (SK_AlphaOPAQUE != SkColorGetA(paint.getColor())) { 358 if (SK_AlphaOPAQUE != SkColorGetA(paint.getColor())) {
345 this->addAttribute("fill-opacity", svg_opacity(paint.getColor())); 359 this->addAttribute("fill-opacity", svg_opacity(paint.getColor()));
346 } 360 }
(...skipping 25 matching lines...) Expand all
372 this->addAttribute("stroke-miterlimit", paint.getStrokeMiter()); 386 this->addAttribute("stroke-miterlimit", paint.getStrokeMiter());
373 } 387 }
374 388
375 if (SK_AlphaOPAQUE != SkColorGetA(paint.getColor())) { 389 if (SK_AlphaOPAQUE != SkColorGetA(paint.getColor())) {
376 this->addAttribute("stroke-opacity", svg_opacity(paint.getColor())); 390 this->addAttribute("stroke-opacity", svg_opacity(paint.getColor()));
377 } 391 }
378 } else { 392 } else {
379 SkASSERT(style == SkPaint::kFill_Style); 393 SkASSERT(style == SkPaint::kFill_Style);
380 this->addAttribute("stroke", "none"); 394 this->addAttribute("stroke", "none");
381 } 395 }
382
383 if (!resources.fClip.isEmpty()) {
384 this->addAttribute("clip-path", resources.fClip);
385 }
386 } 396 }
387 397
388 Resources SkSVGDevice::AutoElement::addResources(const SkDraw& draw, const SkPai nt& paint) { 398 Resources SkSVGDevice::AutoElement::addResources(const SkDraw& draw, const SkPai nt& paint) {
389 Resources resources(paint); 399 Resources resources(paint);
390 400
391 // FIXME: this is a weak heuristic and we end up with LOTS of redundant clip s. 401 // FIXME: this is a weak heuristic and we end up with LOTS of redundant clip s.
392 bool hasClip = !draw.fClipStack->isWideOpen(); 402 bool hasClip = !draw.fClipStack->isWideOpen();
393 bool hasShader = SkToBool(paint.getShader()); 403 bool hasShader = SkToBool(paint.getShader());
394 404
395 if (hasClip || hasShader) { 405 if (hasClip || hasShader) {
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 // todo 632 // todo
623 SkDebugf("unsupported operation: drawRRect()\n"); 633 SkDebugf("unsupported operation: drawRRect()\n");
624 } 634 }
625 635
626 void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint & paint, 636 void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint & paint,
627 const SkMatrix* prePathMatrix, bool pathIsMutable) { 637 const SkMatrix* prePathMatrix, bool pathIsMutable) {
628 AutoElement elem("path", fWriter, fResourceBucket, draw, paint); 638 AutoElement elem("path", fWriter, fResourceBucket, draw, paint);
629 elem.addPathAttributes(path); 639 elem.addPathAttributes(path);
630 } 640 }
631 641
632 void SkSVGDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, 642 void SkSVGDevice::drawBitmapCommon(const SkDraw& draw, const SkBitmap& bm,
633 const SkMatrix& matrix, const SkPaint& paint) { 643 const SkPaint& paint) {
634 // todo 644 SkAutoTUnref<const SkData> pngData(
635 SkDebugf("unsupported operation: drawBitmap()\n"); 645 SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, SkImageEncoder ::kDefaultQuality));
646 if (!pngData) {
647 return;
648 }
649
650 size_t b64Size = SkBase64::Encode(pngData->data(), pngData->size(), NULL);
651 SkAutoTMalloc<char> b64Data(b64Size);
652 SkBase64::Encode(pngData->data(), pngData->size(), b64Data.get());
653
654 SkString svgImageData("data:image/png;base64,");
655 svgImageData.append(b64Data.get(), b64Size);
656
657 SkString imageID = fResourceBucket->addImage();
658 {
659 AutoElement defs("defs", fWriter);
660 {
661 AutoElement image("image", fWriter);
662 image.addAttribute("id", imageID);
663 image.addAttribute("width", bm.width());
664 image.addAttribute("height", bm.height());
665 image.addAttribute("xlink:href", svgImageData);
666 }
667 }
668
669 {
670 AutoElement imageUse("use", fWriter, fResourceBucket, draw, paint);
671 imageUse.addAttribute("xlink:href", SkStringPrintf("#%s", imageID.c_str( )));
672 }
636 } 673 }
637 674
638 void SkSVGDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, 675 void SkSVGDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
639 int x, int y, const SkPaint& paint) { 676 const SkMatrix& matrix, const SkPaint& paint) {
640 // todo 677 SkMatrix adjustedMatrix = *draw.fMatrix;
641 SkDebugf("unsupported operation: drawSprite()\n"); 678 adjustedMatrix.preConcat(matrix);
679 SkDraw adjustedDraw(draw);
680 adjustedDraw.fMatrix = &adjustedMatrix;
681
682 drawBitmapCommon(adjustedDraw, bitmap, paint);
642 } 683 }
643 684
644 void SkSVGDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* s rcOrNull, 685 void SkSVGDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
686 int x, int y, const SkPaint& paint) {
687 SkMatrix adjustedMatrix = *draw.fMatrix;
688 adjustedMatrix.preTranslate(SkIntToScalar(x), SkIntToScalar(y));
689 SkDraw adjustedDraw(draw);
690 adjustedDraw.fMatrix = &adjustedMatrix;
691
692 drawBitmapCommon(adjustedDraw, bitmap, paint);
693 }
694
695 void SkSVGDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bm, const S kRect* srcOrNull,
645 const SkRect& dst, const SkPaint& paint, 696 const SkRect& dst, const SkPaint& paint,
646 SkCanvas::DrawBitmapRectFlags flags) { 697 SkCanvas::DrawBitmapRectFlags) {
647 // todo 698 SkMatrix adjustedMatrix;
648 SkDebugf("unsupported operation: drawBitmapRect()\n"); 699 adjustedMatrix.setRectToRect(srcOrNull ? *srcOrNull : SkRect::Make(bm.bounds ()),
700 dst,
701 SkMatrix::kFill_ScaleToFit);
702 adjustedMatrix.postConcat(*draw.fMatrix);
703
704 SkDraw adjustedDraw(draw);
705 adjustedDraw.fMatrix = &adjustedMatrix;
706
707 SkClipStack adjustedClipStack;
708 if (srcOrNull && *srcOrNull != SkRect::Make(bm.bounds())) {
709 SkRect devClipRect;
710 draw.fMatrix->mapRect(&devClipRect, dst);
711
712 adjustedClipStack = *draw.fClipStack;
713 adjustedClipStack.clipDevRect(devClipRect, SkRegion::kIntersect_Op, pain t.isAntiAlias());
714 adjustedDraw.fClipStack = &adjustedClipStack;
715 }
716
717 drawBitmapCommon(adjustedDraw, bm, paint);
649 } 718 }
650 719
651 void SkSVGDevice::drawText(const SkDraw& draw, const void* text, size_t len, 720 void SkSVGDevice::drawText(const SkDraw& draw, const void* text, size_t len,
652 SkScalar x, SkScalar y, const SkPaint& paint) { 721 SkScalar x, SkScalar y, const SkPaint& paint) {
653 AutoElement elem("text", fWriter, fResourceBucket, draw, paint); 722 AutoElement elem("text", fWriter, fResourceBucket, draw, paint);
654 elem.addTextAttributes(paint); 723 elem.addTextAttributes(paint);
655 724
656 SVGTextBuilder builder(text, len, paint, SkPoint::Make(x, y), 0); 725 SVGTextBuilder builder(text, len, paint, SkPoint::Make(x, y), 0);
657 elem.addAttribute("x", builder.posX()); 726 elem.addAttribute("x", builder.posX());
658 elem.addAttribute("y", builder.posY()); 727 elem.addAttribute("y", builder.posY());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 const SkPaint& paint) { 786 const SkPaint& paint) {
718 // todo 787 // todo
719 SkDebugf("unsupported operation: drawVertices()\n"); 788 SkDebugf("unsupported operation: drawVertices()\n");
720 } 789 }
721 790
722 void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, 791 void SkSVGDevice::drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
723 const SkPaint&) { 792 const SkPaint&) {
724 // todo 793 // todo
725 SkDebugf("unsupported operation: drawDevice()\n"); 794 SkDebugf("unsupported operation: drawDevice()\n");
726 } 795 }
OLDNEW
« no previous file with comments | « src/svg/SkSVGDevice.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698