diff options
author | 2017-02-17 14:38:11 -0500 | |
---|---|---|
committer | 2017-02-17 21:03:43 +0000 | |
commit | c5e641cc9947b8b2d3c63f908c7b98fa5b3d0f07 (patch) | |
tree | b17cc0ae0a104ec61876ea932fc3bc4be96b73be | |
parent | 9c58306f87ff342bf30ed645be3332aa6f2b2fee (diff) |
use common intermediate device class for clipstack management
BUG=skia:6214
Change-Id: I64b849ad7c8dafe423e24e6fccfb3f0c1d096ab0
Reviewed-on: https://skia-review.googlesource.com/8669
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
-rw-r--r-- | gn/core.gni | 2 | ||||
-rw-r--r-- | src/core/SkClipStackDevice.cpp | 51 | ||||
-rw-r--r-- | src/core/SkClipStackDevice.h | 37 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 2 | ||||
-rw-r--r-- | src/core/SkDevice.h | 6 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 52 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 16 | ||||
-rw-r--r-- | src/svg/SkSVGDevice.cpp | 102 | ||||
-rw-r--r-- | src/svg/SkSVGDevice.h | 9 |
9 files changed, 158 insertions, 119 deletions
diff --git a/gn/core.gni b/gn/core.gni index bc6035be9d..7097983016 100644 --- a/gn/core.gni +++ b/gn/core.gni @@ -69,6 +69,8 @@ skia_core_sources = [ "$_src/core/SkChunkAlloc.cpp", "$_src/core/SkClipStack.cpp", "$_src/core/SkClipStack.h", + "$_src/core/SkClipStackDevice.cpp", + "$_src/core/SkClipStackDevice.h", "$_src/core/SkColor.cpp", "$_src/core/SkColorFilter.cpp", "$_src/core/SkColorFilterShader.cpp", diff --git a/src/core/SkClipStackDevice.cpp b/src/core/SkClipStackDevice.cpp new file mode 100644 index 0000000000..e1014e98b6 --- /dev/null +++ b/src/core/SkClipStackDevice.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkClipStackDevice.h" + +void SkClipStackDevice::onSave() { + fClipStack.save(); +} + +void SkClipStackDevice::onRestore() { + fClipStack.restore(); +} + +void SkClipStackDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) { + fClipStack.clipRect(rect, this->ctm(), op, aa); +} + +void SkClipStackDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { + fClipStack.clipRRect(rrect, this->ctm(), op, aa); +} + +void SkClipStackDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) { + fClipStack.clipPath(path, this->ctm(), op, aa); +} + +void SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) { + SkIPoint origin = this->getOrigin(); + SkRegion tmp; + const SkRegion* ptr = &rgn; + if (origin.fX | origin.fY) { + // translate from "global/canvas" coordinates to relative to this device + rgn.translate(-origin.fX, -origin.fY, &tmp); + ptr = &tmp; + } + fClipStack.clipDevRect(ptr->getBounds(), op); +} + +void SkClipStackDevice::onSetDeviceClipRestriction(SkIRect* clipRestriction) { + if (clipRestriction->isEmpty()) { + fClipStack.setDeviceClipRestriction(*clipRestriction); + } else { + SkIPoint origin = this->getOrigin(); + SkIRect rect = clipRestriction->makeOffset(-origin.x(), -origin.y()); + fClipStack.setDeviceClipRestriction(rect); + fClipStack.clipDevRect(rect, SkClipOp::kIntersect); + } +} diff --git a/src/core/SkClipStackDevice.h b/src/core/SkClipStackDevice.h new file mode 100644 index 0000000000..ef18a0009a --- /dev/null +++ b/src/core/SkClipStackDevice.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkClipStackDevice_DEFINED +#define SkClipStackDevice_DEFINED + +#include "SkClipStack.h" +#include "SkDevice.h" + +class SK_API SkClipStackDevice : public SkBaseDevice { +public: + SkClipStackDevice(const SkImageInfo& info, const SkSurfaceProps& props) + : SkBaseDevice(info, props) + {} + + const SkClipStack& cs() const { return fClipStack; } + +protected: + void onSave() override; + void onRestore() override; + void onClipRect(const SkRect& rect, SkClipOp, bool aa) override; + void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override; + void onClipPath(const SkPath& path, SkClipOp, bool aa) override; + void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override; + void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override; + +private: + SkClipStack fClipStack; + + typedef SkBaseDevice INHERITED; +}; + +#endif diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index ad9df5b144..cd3bf502c7 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -35,8 +35,6 @@ SkBaseDevice::SkBaseDevice(const SkImageInfo& info, const SkSurfaceProps& surfac fCTM.reset(); } -SkBaseDevice::~SkBaseDevice() {} - void SkBaseDevice::setOrigin(const SkMatrix& globalCTM, int x, int y) { fOrigin.set(x, y); fCTM = globalCTM; diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h index 66a6e1d1f0..cd0e1d01ea 100644 --- a/src/core/SkDevice.h +++ b/src/core/SkDevice.h @@ -26,11 +26,7 @@ class GrRenderTarget; class SK_API SkBaseDevice : public SkRefCnt { public: - /** - * Construct a new device. - */ - explicit SkBaseDevice(const SkImageInfo&, const SkSurfaceProps&); - virtual ~SkBaseDevice(); + SkBaseDevice(const SkImageInfo&, const SkSurfaceProps&); /** * Return ImageInfo for this device. If the canvas is not backed by pixels diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 791d4353c7..6ab2d60b91 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -238,7 +238,7 @@ void SkGpuDevice::prepareDraw(const SkDraw& draw) { #ifdef SK_USE_DEVICE_CLIPPING SkASSERT(*draw.fMatrix == this->ctm()); - fClip.reset(&fClipStack, nullptr); + fClip.reset(&this->cs(), nullptr); #else fClip.reset(draw.fClipStack, &this->getOrigin()); #endif @@ -1825,54 +1825,4 @@ SkImageFilterCache* SkGpuDevice::getImageFilterCache() { return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize); } -/////////////////////////////////////////////////////////////////////////////////////////////////// - -void SkGpuDevice::onSave() { - fClipStack.save(); -} - -void SkGpuDevice::onRestore() { - fClipStack.restore(); -} - -void SkGpuDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) { - fClipStack.clipRect(rect, this->ctm(), op, aa); -} - -void SkGpuDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { - fClipStack.clipRRect(rrect, this->ctm(), op, aa); -} - -void SkGpuDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) { - fClipStack.clipPath(path, this->ctm(), op, aa); -} - -void SkGpuDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) { - SkIPoint origin = this->getOrigin(); - SkRegion tmp; - const SkRegion* ptr = &rgn; - if (origin.fX | origin.fY) { - // translate from "global/canvas" coordinates to relative to this device - rgn.translate(-origin.fX, -origin.fY, &tmp); - ptr = &tmp; - } - fClipStack.clipDevRect(ptr->getBounds(), op); -} - -void SkGpuDevice::onSetDeviceClipRestriction(SkIRect* clipRestriction) { - if (clipRestriction->isEmpty()) { - fClipStack.setDeviceClipRestriction(*clipRestriction); - } else { - SkIPoint origin = this->getOrigin(); - SkIRect rect = clipRestriction->makeOffset(-origin.x(), -origin.y()); - fClipStack.setDeviceClipRestriction(rect); - fClipStack.clipDevRect(rect, SkClipOp::kIntersect); - } -} - -void SkGpuDevice::validateDevBounds(const SkIRect& drawClipBounds) { -#ifdef SK_DEBUG -#endif -} - #endif diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index ab3fb3f462..31ade05f4c 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -11,7 +11,7 @@ #include "SkGr.h" #include "SkGrPriv.h" #include "SkBitmap.h" -#include "SkDevice.h" +#include "SkClipStackDevice.h" #include "SkPicture.h" #include "SkRegion.h" #include "SkSurface.h" @@ -31,7 +31,7 @@ class SkSpecialImage; * Subclass of SkBaseDevice, which directs all drawing to the GrGpu owned by the * canvas. */ -class SK_API SkGpuDevice : public SkBaseDevice { +class SK_API SkGpuDevice : public SkClipStackDevice { public: enum InitContents { kClear_InitContents, @@ -134,7 +134,6 @@ private: sk_sp<GrRenderTargetContext> fRenderTargetContext; SkIPoint fClipOrigin; - SkClipStack fClipStack; GrClipStackClip fClip; SkISize fSize; bool fOpaque; @@ -238,15 +237,6 @@ private: bool drawDashLine(const SkPoint pts[2], const SkPaint& paint); void drawStrokedLine(const SkPoint pts[2], const SkDraw&, const SkPaint&); - void onSave() override; - void onRestore() override; - void onClipRect(const SkRect& rect, SkClipOp, bool aa) override; - void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override; - void onClipPath(const SkPath& path, SkClipOp, bool aa) override; - void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override; - void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override; - void validateDevBounds(const SkIRect& r) override; - static sk_sp<GrRenderTargetContext> MakeRenderTargetContext(GrContext*, SkBudgeted, const SkImageInfo&, @@ -256,7 +246,7 @@ private: friend class GrAtlasTextContext; friend class SkSurface_Gpu; // for access to surfaceProps - typedef SkBaseDevice INHERITED; + typedef SkClipStackDevice INHERITED; }; #endif diff --git a/src/svg/SkSVGDevice.cpp b/src/svg/SkSVGDevice.cpp index 06679daf9e..261ad22d6d 100644 --- a/src/svg/SkSVGDevice.cpp +++ b/src/svg/SkSVGDevice.cpp @@ -274,6 +274,21 @@ private: uint32_t fImageCount; }; +struct SkSVGDevice::MxCp { + const SkMatrix* fMatrix; + const SkClipStack* fClipStack; + + MxCp(SkSVGDevice* device, const SkDraw& draw) { +#ifdef SK_USE_DEVICE_CLIPPING + fMatrix = &device->ctm(); + fClipStack = &device->cs(); +#else + fMatrix = draw.fMatrix; + fClipStack = draw.fClipStack; +#endif + } +}; + class SkSVGDevice::AutoElement : ::SkNoncopyable { public: AutoElement(const char name[], SkXMLWriter* writer) @@ -283,11 +298,11 @@ public: } AutoElement(const char name[], SkXMLWriter* writer, ResourceBucket* bucket, - const SkDraw& draw, const SkPaint& paint) + const MxCp& mc, const SkPaint& paint) : fWriter(writer) , fResourceBucket(bucket) { - Resources res = this->addResources(draw, paint); + Resources res = this->addResources(mc, paint); if (!res.fClip.isEmpty()) { // The clip is in device space. Apply it via a <g> wrapper to avoid local transform // interference. @@ -299,8 +314,8 @@ public: this->addPaint(paint, res); - if (!draw.fMatrix->isIdentity()) { - this->addAttribute("transform", svg_transform(*draw.fMatrix)); + if (!mc.fMatrix->isIdentity()) { + this->addAttribute("transform", svg_transform(*mc.fMatrix)); } } @@ -333,8 +348,8 @@ public: void addTextAttributes(const SkPaint&); private: - Resources addResources(const SkDraw& draw, const SkPaint& paint); - void addClipResources(const SkDraw& draw, Resources* resources); + Resources addResources(const MxCp&, const SkPaint& paint); + void addClipResources(const MxCp&, Resources* resources); void addShaderResources(const SkPaint& paint, Resources* resources); void addPaint(const SkPaint& paint, const Resources& resources); @@ -391,18 +406,18 @@ void SkSVGDevice::AutoElement::addPaint(const SkPaint& paint, const Resources& r } } -Resources SkSVGDevice::AutoElement::addResources(const SkDraw& draw, const SkPaint& paint) { +Resources SkSVGDevice::AutoElement::addResources(const MxCp& mc, const SkPaint& paint) { Resources resources(paint); // FIXME: this is a weak heuristic and we end up with LOTS of redundant clips. - bool hasClip = !draw.fClipStack->isWideOpen(); + bool hasClip = !mc.fClipStack->isWideOpen(); bool hasShader = SkToBool(paint.getShader()); if (hasClip || hasShader) { AutoElement defs("defs", fWriter); if (hasClip) { - this->addClipResources(draw, &resources); + this->addClipResources(mc, &resources); } if (hasShader) { @@ -438,11 +453,11 @@ void SkSVGDevice::AutoElement::addShaderResources(const SkPaint& paint, Resource resources->fPaintServer.printf("url(#%s)", addLinearGradientDef(grInfo, shader).c_str()); } -void SkSVGDevice::AutoElement::addClipResources(const SkDraw& draw, Resources* resources) { - SkASSERT(!draw.fClipStack->isWideOpen()); +void SkSVGDevice::AutoElement::addClipResources(const MxCp& mc, Resources* resources) { + SkASSERT(!mc.fClipStack->isWideOpen()); SkPath clipPath; - (void) draw.fClipStack->asPath(&clipPath); + (void) mc.fClipStack->asPath(&clipPath); SkString clipID = fResourceBucket->addClip(); const char* clipRule = clipPath.getFillType() == SkPath::kEvenOdd_FillType ? @@ -592,7 +607,7 @@ SkSVGDevice::~SkSVGDevice() { } void SkSVGDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { - AutoElement rect("rect", fWriter, fResourceBucket.get(), draw, paint); + AutoElement rect("rect", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); rect.addRectAttributes(SkRect::MakeWH(SkIntToScalar(this->width()), SkIntToScalar(this->height()))); } @@ -612,7 +627,7 @@ void SkSVGDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_ path.rewind(); path.moveTo(pts[i]); path.lineTo(pts[i+1]); - AutoElement elem("path", fWriter, fResourceBucket.get(), draw, paint); + AutoElement elem("path", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); elem.addPathAttributes(path); } break; @@ -620,7 +635,7 @@ void SkSVGDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_ if (count > 1) { path.addPoly(pts, SkToInt(count), false); path.moveTo(pts[0]); - AutoElement elem("path", fWriter, fResourceBucket.get(), draw, paint); + AutoElement elem("path", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); elem.addPathAttributes(path); } break; @@ -628,12 +643,12 @@ void SkSVGDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_ } void SkSVGDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) { - AutoElement rect("rect", fWriter, fResourceBucket.get(), draw, paint); + AutoElement rect("rect", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); rect.addRectAttributes(r); } void SkSVGDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { - AutoElement ellipse("ellipse", fWriter, fResourceBucket.get(), draw, paint); + AutoElement ellipse("ellipse", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); ellipse.addAttribute("cx", oval.centerX()); ellipse.addAttribute("cy", oval.centerY()); ellipse.addAttribute("rx", oval.width() / 2); @@ -644,13 +659,13 @@ void SkSVGDevice::drawRRect(const SkDraw& draw, const SkRRect& rr, const SkPaint SkPath path; path.addRRect(rr); - AutoElement elem("path", fWriter, fResourceBucket.get(), draw, paint); + AutoElement elem("path", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); elem.addPathAttributes(path); } void SkSVGDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) { - AutoElement elem("path", fWriter, fResourceBucket.get(), draw, paint); + AutoElement elem("path", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); elem.addPathAttributes(path); // TODO: inverse fill types? @@ -664,8 +679,7 @@ static sk_sp<SkData> encode(const SkBitmap& src) { return SkEncodeImage(&buf, src, SkEncodedImageFormat::kPNG, 80) ? buf.detachAsData() : nullptr; } -void SkSVGDevice::drawBitmapCommon(const SkDraw& draw, const SkBitmap& bm, - const SkPaint& paint) { +void SkSVGDevice::drawBitmapCommon(const MxCp& mc, const SkBitmap& bm, const SkPaint& paint) { sk_sp<SkData> pngData = encode(bm); if (!pngData) { return; @@ -691,57 +705,57 @@ void SkSVGDevice::drawBitmapCommon(const SkDraw& draw, const SkBitmap& bm, } { - AutoElement imageUse("use", fWriter, fResourceBucket.get(), draw, paint); + AutoElement imageUse("use", fWriter, fResourceBucket.get(), mc, 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) { - SkMatrix adjustedMatrix = *draw.fMatrix; + MxCp mc(this, draw); + SkMatrix adjustedMatrix = *mc.fMatrix; adjustedMatrix.preConcat(matrix); - SkDraw adjustedDraw(draw); - adjustedDraw.fMatrix = &adjustedMatrix; + mc.fMatrix = &adjustedMatrix; - drawBitmapCommon(adjustedDraw, bitmap, paint); + drawBitmapCommon(mc, bitmap, paint); } void SkSVGDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, int x, int y, const SkPaint& paint) { - SkMatrix adjustedMatrix = *draw.fMatrix; + MxCp mc(this, draw); + SkMatrix adjustedMatrix = *mc.fMatrix; adjustedMatrix.preTranslate(SkIntToScalar(x), SkIntToScalar(y)); - SkDraw adjustedDraw(draw); - adjustedDraw.fMatrix = &adjustedMatrix; + mc.fMatrix = &adjustedMatrix; - drawBitmapCommon(adjustedDraw, bitmap, paint); + drawBitmapCommon(mc, bitmap, paint); } void SkSVGDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bm, const SkRect* srcOrNull, const SkRect& dst, const SkPaint& paint, SkCanvas::SrcRectConstraint) { - SkMatrix adjustedMatrix; - adjustedMatrix.setRectToRect(srcOrNull ? *srcOrNull : SkRect::Make(bm.bounds()), - dst, - SkMatrix::kFill_ScaleToFit); - adjustedMatrix.postConcat(*draw.fMatrix); - - SkDraw adjustedDraw(draw); - adjustedDraw.fMatrix = &adjustedMatrix; + MxCp mc(this, draw); SkClipStack adjustedClipStack; if (srcOrNull && *srcOrNull != SkRect::Make(bm.bounds())) { - adjustedClipStack = *draw.fClipStack; - adjustedClipStack.clipRect(dst, *draw.fMatrix, kIntersect_SkClipOp, + adjustedClipStack = *mc.fClipStack; + adjustedClipStack.clipRect(dst, *mc.fMatrix, kIntersect_SkClipOp, paint.isAntiAlias()); - adjustedDraw.fClipStack = &adjustedClipStack; + mc.fClipStack = &adjustedClipStack; } - drawBitmapCommon(adjustedDraw, bm, paint); + SkMatrix adjustedMatrix; + adjustedMatrix.setRectToRect(srcOrNull ? *srcOrNull : SkRect::Make(bm.bounds()), + dst, + SkMatrix::kFill_ScaleToFit); + adjustedMatrix.postConcat(*mc.fMatrix); + mc.fMatrix = &adjustedMatrix; + + drawBitmapCommon(mc, bm, paint); } void SkSVGDevice::drawText(const SkDraw& draw, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { - AutoElement elem("text", fWriter, fResourceBucket.get(), draw, paint); + AutoElement elem("text", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); elem.addTextAttributes(paint); SVGTextBuilder builder(text, len, paint, SkPoint::Make(x, y), 0); @@ -755,7 +769,7 @@ void SkSVGDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, const SkPaint& paint) { SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2); - AutoElement elem("text", fWriter, fResourceBucket.get(), draw, paint); + AutoElement elem("text", fWriter, fResourceBucket.get(), MxCp(this, draw), paint); elem.addTextAttributes(paint); SVGTextBuilder builder(text, len, paint, offset, scalarsPerPos, pos); diff --git a/src/svg/SkSVGDevice.h b/src/svg/SkSVGDevice.h index 5de7735f22..106537e4ed 100644 --- a/src/svg/SkSVGDevice.h +++ b/src/svg/SkSVGDevice.h @@ -8,12 +8,12 @@ #ifndef SkSVGDevice_DEFINED #define SkSVGDevice_DEFINED -#include "SkDevice.h" +#include "SkClipStackDevice.h" #include "SkTemplates.h" class SkXMLWriter; -class SkSVGDevice : public SkBaseDevice { +class SkSVGDevice : public SkClipStackDevice { public: static SkBaseDevice* Create(const SkISize& size, SkXMLWriter* writer); @@ -58,7 +58,8 @@ private: SkSVGDevice(const SkISize& size, SkXMLWriter* writer); virtual ~SkSVGDevice(); - void drawBitmapCommon(const SkDraw& draw, const SkBitmap& bm, const SkPaint& paint); + struct MxCp; + void drawBitmapCommon(const MxCp&, const SkBitmap& bm, const SkPaint& paint); class AutoElement; class ResourceBucket; @@ -67,7 +68,7 @@ private: std::unique_ptr<AutoElement> fRootElement; std::unique_ptr<ResourceBucket> fResourceBucket; - typedef SkBaseDevice INHERITED; + typedef SkClipStackDevice INHERITED; }; #endif // SkSVGDevice_DEFINED |