1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkSVGRenderContext_DEFINED 9 #define SkSVGRenderContext_DEFINED 10 11 #include "include/core/SkFontMgr.h" 12 #include "include/core/SkM44.h" 13 #include "include/core/SkPaint.h" 14 #include "include/core/SkPath.h" 15 #include "include/core/SkRect.h" 16 #include "include/core/SkSize.h" 17 #include "include/core/SkTypes.h" 18 #include "modules/skresources/include/SkResources.h" 19 #include "modules/skshaper/include/SkShaper.h" 20 #include "modules/skshaper/include/SkShaper_factory.h" 21 #include "modules/svg/include/SkSVGAttribute.h" 22 #include "modules/svg/include/SkSVGIDMapper.h" 23 #include "src/base/SkTLazy.h" 24 #include "src/core/SkTHash.h" 25 26 class SkCanvas; 27 class SkSVGLength; 28 29 class SK_API SkSVGLengthContext { 30 public: 31 SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90) fViewport(viewport)32 : fViewport(viewport), fDPI(dpi) {} 33 34 enum class LengthType { 35 kHorizontal, 36 kVertical, 37 kOther, 38 }; 39 viewPort()40 const SkSize& viewPort() const { return fViewport; } setViewPort(const SkSize & viewport)41 void setViewPort(const SkSize& viewport) { fViewport = viewport; } 42 43 SkScalar resolve(const SkSVGLength&, LengthType) const; 44 SkRect resolveRect(const SkSVGLength& x, const SkSVGLength& y, 45 const SkSVGLength& w, const SkSVGLength& h) const; 46 47 private: 48 SkSize fViewport; 49 SkScalar fDPI; 50 }; 51 52 struct SK_API SkSVGPresentationContext { 53 SkSVGPresentationContext(); 54 SkSVGPresentationContext(const SkSVGPresentationContext&) = default; 55 SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default; 56 57 const skia_private::THashMap<SkString, SkSVGColorType>* fNamedColors = nullptr; 58 59 // Inherited presentation attributes, computed for the current node. 60 SkSVGPresentationAttributes fInherited; 61 }; 62 63 class SK_API SkSVGRenderContext { 64 public: 65 // Captures data required for object bounding box resolution. 66 struct OBBScope { 67 const SkSVGNode* fNode; 68 const SkSVGRenderContext* fCtx; 69 }; 70 71 SkSVGRenderContext(SkCanvas*, 72 const sk_sp<SkFontMgr>&, 73 const sk_sp<skresources::ResourceProvider>&, 74 const SkSVGIDMapper&, 75 const SkSVGLengthContext&, 76 const SkSVGPresentationContext&, 77 const OBBScope&, 78 const sk_sp<SkShapers::Factory>&); 79 SkSVGRenderContext(const SkSVGRenderContext&); 80 SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*); 81 // Establish a new OBB scope. Normally used when entering a node's render scope. 82 SkSVGRenderContext(const SkSVGRenderContext&, const SkSVGNode*); 83 ~SkSVGRenderContext(); 84 lengthContext()85 const SkSVGLengthContext& lengthContext() const { return *fLengthContext; } writableLengthContext()86 SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); } 87 presentationContext()88 const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; } 89 canvas()90 SkCanvas* canvas() const { return fCanvas; } 91 void saveOnce(); 92 93 enum ApplyFlags { 94 kLeaf = 1 << 0, // the target node doesn't have descendants 95 }; 96 void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags); 97 98 // Scoped wrapper that temporarily clears the original node reference. 99 class BorrowedNode { 100 public: BorrowedNode(sk_sp<SkSVGNode> * node)101 explicit BorrowedNode(sk_sp<SkSVGNode>* node) 102 : fOwner(node) { 103 if (fOwner) { 104 fBorrowed = std::move(*fOwner); 105 *fOwner = nullptr; 106 } 107 } 108 ~BorrowedNode()109 ~BorrowedNode() { 110 if (fOwner) { 111 *fOwner = std::move(fBorrowed); 112 } 113 } 114 get()115 const SkSVGNode* get() const { return fBorrowed.get(); } 116 const SkSVGNode* operator->() const { return fBorrowed.get(); } 117 const SkSVGNode& operator*() const { return *fBorrowed; } 118 119 explicit operator bool() const { return !!fBorrowed; } 120 121 private: 122 // noncopyable 123 BorrowedNode(const BorrowedNode&) = delete; 124 BorrowedNode& operator=(BorrowedNode&) = delete; 125 126 sk_sp<SkSVGNode>* fOwner; 127 sk_sp<SkSVGNode> fBorrowed; 128 }; 129 130 // Note: the id->node association is cleared for the lifetime of the returned value 131 // (effectively breaks reference cycles, assuming appropriate return value scoping). 132 BorrowedNode findNodeById(const SkSVGIRI&) const; 133 134 SkTLazy<SkPaint> fillPaint() const; 135 SkTLazy<SkPaint> strokePaint() const; 136 137 SkSVGColorType resolveSvgColor(const SkSVGColor&) const; 138 139 // The local computed clip path (not inherited). clipPath()140 const SkPath* clipPath() const { return fClipPath.getMaybeNull(); } 141 resourceProvider()142 const sk_sp<skresources::ResourceProvider>& resourceProvider() const { 143 return fResourceProvider; 144 } 145 fontMgr()146 sk_sp<SkFontMgr> fontMgr() const { 147 // It is probably an oversight to try to render <text> without having set the SkFontMgr. 148 // We will assert this in debug mode, but fallback to an empty fontmgr in release builds. 149 SkASSERT(fFontMgr); 150 return fFontMgr ? fFontMgr : SkFontMgr::RefEmpty(); 151 } 152 153 // Returns the translate/scale transformation required to map into the current OBB scope, 154 // with the specified units. 155 struct OBBTransform { 156 SkV2 offset, scale; 157 }; 158 OBBTransform transformForCurrentOBB(SkSVGObjectBoundingBoxUnits) const; 159 160 SkRect resolveOBBRect(const SkSVGLength& x, const SkSVGLength& y, 161 const SkSVGLength& w, const SkSVGLength& h, 162 SkSVGObjectBoundingBoxUnits) const; 163 makeShaper()164 std::unique_ptr<SkShaper> makeShaper() const { 165 SkASSERT(fTextShapingFactory); 166 return fTextShapingFactory->makeShaper(this->fontMgr()); 167 } 168 makeBidiRunIterator(const char * utf8,size_t utf8Bytes,uint8_t bidiLevel)169 std::unique_ptr<SkShaper::BiDiRunIterator> makeBidiRunIterator(const char* utf8, 170 size_t utf8Bytes, 171 uint8_t bidiLevel) const { 172 SkASSERT(fTextShapingFactory); 173 return fTextShapingFactory->makeBidiRunIterator(utf8, utf8Bytes, bidiLevel); 174 } 175 makeScriptRunIterator(const char * utf8,size_t utf8Bytes)176 std::unique_ptr<SkShaper::ScriptRunIterator> makeScriptRunIterator(const char* utf8, 177 size_t utf8Bytes) const { 178 SkASSERT(fTextShapingFactory); 179 constexpr SkFourByteTag unknownScript = SkSetFourByteTag('Z', 'z', 'z', 'z'); 180 return fTextShapingFactory->makeScriptRunIterator(utf8, utf8Bytes, unknownScript); 181 } 182 183 private: 184 // Stack-only 185 void* operator new(size_t) = delete; 186 void* operator new(size_t, void*) = delete; 187 SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete; 188 189 void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter); 190 void applyFilter(const SkSVGFuncIRI&); 191 void applyClip(const SkSVGFuncIRI&); 192 void applyMask(const SkSVGFuncIRI&); 193 194 SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const; 195 196 const sk_sp<SkFontMgr>& fFontMgr; 197 const sk_sp<SkShapers::Factory>& fTextShapingFactory; 198 const sk_sp<skresources::ResourceProvider>& fResourceProvider; 199 const SkSVGIDMapper& fIDMapper; 200 SkTCopyOnFirstWrite<SkSVGLengthContext> fLengthContext; 201 SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext; 202 SkCanvas* fCanvas; 203 // The save count on 'fCanvas' at construction time. 204 // A restoreToCount() will be issued on destruction. 205 int fCanvasSaveCount; 206 207 // clipPath, if present for the current context (not inherited). 208 SkTLazy<SkPath> fClipPath; 209 210 // Deferred opacity optimization for leaf nodes. 211 float fDeferredPaintOpacity = 1; 212 213 // Current object bounding box scope. 214 const OBBScope fOBBScope; 215 }; 216 217 #endif // SkSVGRenderContext_DEFINED 218