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