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