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 makeShaper()174 std::unique_ptr<SkShaper> makeShaper() const { 175 SkASSERT(fTextShapingFactory); 176 return fTextShapingFactory->makeShaper(this->fontMgr()); 177 } 178 makeBidiRunIterator(const char * utf8,size_t utf8Bytes,uint8_t bidiLevel)179 std::unique_ptr<SkShaper::BiDiRunIterator> makeBidiRunIterator(const char* utf8, 180 size_t utf8Bytes, 181 uint8_t bidiLevel) const { 182 SkASSERT(fTextShapingFactory); 183 return fTextShapingFactory->makeBidiRunIterator(utf8, utf8Bytes, bidiLevel); 184 } 185 makeScriptRunIterator(const char * utf8,size_t utf8Bytes)186 std::unique_ptr<SkShaper::ScriptRunIterator> makeScriptRunIterator(const char* utf8, 187 size_t utf8Bytes) const { 188 SkASSERT(fTextShapingFactory); 189 constexpr SkFourByteTag unknownScript = SkSetFourByteTag('Z', 'z', 'z', 'z'); 190 return fTextShapingFactory->makeScriptRunIterator(utf8, utf8Bytes, unknownScript); 191 } 192 193 private: 194 // Stack-only 195 void* operator new(size_t) = delete; 196 void* operator new(size_t, void*) = delete; 197 SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete; 198 199 void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter); 200 void applyFilter(const SkSVGFuncIRI&); 201 void applyClip(const SkSVGFuncIRI&); 202 void applyMask(const SkSVGFuncIRI&); 203 204 SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const; 205 206 const sk_sp<SkFontMgr>& fFontMgr; 207 const sk_sp<SkShapers::Factory>& fTextShapingFactory; 208 const sk_sp<skresources::ResourceProvider>& fResourceProvider; 209 const SkSVGIDMapper& fIDMapper; 210 SkTCopyOnFirstWrite<SkSVGLengthContext> fLengthContext; 211 SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext; 212 SkCanvas* fCanvas; 213 // The save count on 'fCanvas' at construction time. 214 // A restoreToCount() will be issued on destruction. 215 int fCanvasSaveCount; 216 217 // clipPath, if present for the current context (not inherited). 218 SkTLazy<SkPath> fClipPath; 219 220 // Deferred opacity optimization for leaf nodes. 221 float fDeferredPaintOpacity = 1; 222 223 // Current object bounding box scope. 224 const OBBScope fOBBScope; 225 }; 226 227 #endif // SkSVGRenderContext_DEFINED 228