| Index: src/svg/SkSVGDevice.cpp
|
| diff --git a/src/svg/SkSVGDevice.cpp b/src/svg/SkSVGDevice.cpp
|
| index a56a6314464fa46c00d2e26cdca758cb4ae79031..45e616b3f618b2717fb4fadb31690da12bcbf49c 100644
|
| --- a/src/svg/SkSVGDevice.cpp
|
| +++ b/src/svg/SkSVGDevice.cpp
|
| @@ -7,12 +7,14 @@
|
|
|
| #include "SkSVGDevice.h"
|
|
|
| +#include "SkBase64.h"
|
| #include "SkBitmap.h"
|
| #include "SkChecksum.h"
|
| +#include "SkData.h"
|
| #include "SkDraw.h"
|
| +#include "SkImageEncoder.h"
|
| #include "SkPaint.h"
|
| #include "SkParsePath.h"
|
| -#include "SkPathOps.h"
|
| #include "SkShader.h"
|
| #include "SkStream.h"
|
| #include "SkTHash.h"
|
| @@ -251,7 +253,7 @@ private:
|
| // and deduplicate resources.
|
| class SkSVGDevice::ResourceBucket : ::SkNoncopyable {
|
| public:
|
| - ResourceBucket() : fGradientCount(0), fClipCount(0), fPathCount(0) {}
|
| + ResourceBucket() : fGradientCount(0), fClipCount(0), fPathCount(0), fImageCount(0) {}
|
|
|
| SkString addLinearGradient() {
|
| return SkStringPrintf("gradient_%d", fGradientCount++);
|
| @@ -265,10 +267,15 @@ public:
|
| return SkStringPrintf("path_%d", fPathCount++);
|
| }
|
|
|
| + SkString addImage() {
|
| + return SkStringPrintf("img_%d", fImageCount++);
|
| + }
|
| +
|
| private:
|
| uint32_t fGradientCount;
|
| uint32_t fClipCount;
|
| uint32_t fPathCount;
|
| + uint32_t fImageCount;
|
| };
|
|
|
| class SkSVGDevice::AutoElement : ::SkNoncopyable {
|
| @@ -285,6 +292,12 @@ public:
|
| , fResourceBucket(bucket) {
|
|
|
| Resources res = this->addResources(draw, paint);
|
| + if (!res.fClip.isEmpty()) {
|
| + // The clip is in device space. Apply it via a <g> wrapper to avoid local transform
|
| + // interference.
|
| + fClipGroup.reset(SkNEW_ARGS(AutoElement, ("g", fWriter)));
|
| + fClipGroup->addAttribute("clip-path",res.fClip);
|
| + }
|
|
|
| fWriter->startElement(name);
|
|
|
| @@ -332,8 +345,9 @@ private:
|
|
|
| SkString addLinearGradientDef(const SkShader::GradientInfo& info, const SkShader* shader);
|
|
|
| - SkXMLWriter* fWriter;
|
| - ResourceBucket* fResourceBucket;
|
| + SkXMLWriter* fWriter;
|
| + ResourceBucket* fResourceBucket;
|
| + SkAutoTDelete<AutoElement> fClipGroup;
|
| };
|
|
|
| void SkSVGDevice::AutoElement::addPaint(const SkPaint& paint, const Resources& resources) {
|
| @@ -379,10 +393,6 @@ void SkSVGDevice::AutoElement::addPaint(const SkPaint& paint, const Resources& r
|
| SkASSERT(style == SkPaint::kFill_Style);
|
| this->addAttribute("stroke", "none");
|
| }
|
| -
|
| - if (!resources.fClip.isEmpty()) {
|
| - this->addAttribute("clip-path", resources.fClip);
|
| - }
|
| }
|
|
|
| Resources SkSVGDevice::AutoElement::addResources(const SkDraw& draw, const SkPaint& paint) {
|
| @@ -629,23 +639,82 @@ void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint
|
| elem.addPathAttributes(path);
|
| }
|
|
|
| -void SkSVGDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
|
| +void SkSVGDevice::drawBitmapCommon(const SkDraw& draw, const SkBitmap& bm,
|
| + const SkPaint& paint) {
|
| + SkAutoTUnref<const SkData> pngData(
|
| + SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality));
|
| + if (!pngData) {
|
| + return;
|
| + }
|
| +
|
| + size_t b64Size = SkBase64::Encode(pngData->data(), pngData->size(), NULL);
|
| + SkAutoTMalloc<char> b64Data(b64Size);
|
| + SkBase64::Encode(pngData->data(), pngData->size(), b64Data.get());
|
| +
|
| + SkString svgImageData("data:image/png;base64,");
|
| + svgImageData.append(b64Data.get(), b64Size);
|
| +
|
| + SkString imageID = fResourceBucket->addImage();
|
| + {
|
| + AutoElement defs("defs", fWriter);
|
| + {
|
| + AutoElement image("image", fWriter);
|
| + image.addAttribute("id", imageID);
|
| + image.addAttribute("width", bm.width());
|
| + image.addAttribute("height", bm.height());
|
| + image.addAttribute("xlink:href", svgImageData);
|
| + }
|
| + }
|
| +
|
| + {
|
| + AutoElement imageUse("use", fWriter, fResourceBucket, draw, paint);
|
| + imageUse.addAttribute("xlink:href", SkStringPrintf("#%s", imageID.c_str()));
|
| + }
|
| +}
|
| +
|
| +void SkSVGDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
|
| const SkMatrix& matrix, const SkPaint& paint) {
|
| - // todo
|
| - SkDebugf("unsupported operation: drawBitmap()\n");
|
| + SkMatrix adjustedMatrix = *draw.fMatrix;
|
| + adjustedMatrix.preConcat(matrix);
|
| + SkDraw adjustedDraw(draw);
|
| + adjustedDraw.fMatrix = &adjustedMatrix;
|
| +
|
| + drawBitmapCommon(adjustedDraw, bitmap, paint);
|
| }
|
|
|
| -void SkSVGDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
|
| +void SkSVGDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
|
| int x, int y, const SkPaint& paint) {
|
| - // todo
|
| - SkDebugf("unsupported operation: drawSprite()\n");
|
| + SkMatrix adjustedMatrix = *draw.fMatrix;
|
| + adjustedMatrix.preTranslate(SkIntToScalar(x), SkIntToScalar(y));
|
| + SkDraw adjustedDraw(draw);
|
| + adjustedDraw.fMatrix = &adjustedMatrix;
|
| +
|
| + drawBitmapCommon(adjustedDraw, bitmap, paint);
|
| }
|
|
|
| -void SkSVGDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* srcOrNull,
|
| +void SkSVGDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bm, const SkRect* srcOrNull,
|
| const SkRect& dst, const SkPaint& paint,
|
| - SkCanvas::DrawBitmapRectFlags flags) {
|
| - // todo
|
| - SkDebugf("unsupported operation: drawBitmapRect()\n");
|
| + SkCanvas::DrawBitmapRectFlags) {
|
| + SkMatrix adjustedMatrix;
|
| + adjustedMatrix.setRectToRect(srcOrNull ? *srcOrNull : SkRect::Make(bm.bounds()),
|
| + dst,
|
| + SkMatrix::kFill_ScaleToFit);
|
| + adjustedMatrix.postConcat(*draw.fMatrix);
|
| +
|
| + SkDraw adjustedDraw(draw);
|
| + adjustedDraw.fMatrix = &adjustedMatrix;
|
| +
|
| + SkClipStack adjustedClipStack;
|
| + if (srcOrNull && *srcOrNull != SkRect::Make(bm.bounds())) {
|
| + SkRect devClipRect;
|
| + draw.fMatrix->mapRect(&devClipRect, dst);
|
| +
|
| + adjustedClipStack = *draw.fClipStack;
|
| + adjustedClipStack.clipDevRect(devClipRect, SkRegion::kIntersect_Op, paint.isAntiAlias());
|
| + adjustedDraw.fClipStack = &adjustedClipStack;
|
| + }
|
| +
|
| + drawBitmapCommon(adjustedDraw, bm, paint);
|
| }
|
|
|
| void SkSVGDevice::drawText(const SkDraw& draw, const void* text, size_t len,
|
|
|