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 "SkPaint.h"
12#include "SkPath.h"
13#include "SkRect.h"
14#include "SkSize.h"
15#include "SkSVGAttribute.h"
16#include "SkSVGIDMapper.h"
17#include "SkTLazy.h"
18#include "SkTypes.h"
19
20class SkCanvas;
21class SkSVGLength;
22
23class SkSVGLengthContext {
24public:
25    SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90)
26        : fViewport(viewport), fDPI(dpi) {}
27
28    enum class LengthType {
29        kHorizontal,
30        kVertical,
31        kOther,
32    };
33
34    const SkSize& viewPort() const { return fViewport; }
35    void setViewPort(const SkSize& viewport) { fViewport = viewport; }
36
37    SkScalar resolve(const SkSVGLength&, LengthType) const;
38    SkRect   resolveRect(const SkSVGLength& x, const SkSVGLength& y,
39                         const SkSVGLength& w, const SkSVGLength& h) const;
40
41private:
42    SkSize   fViewport;
43    SkScalar fDPI;
44};
45
46struct SkSVGPresentationContext {
47    SkSVGPresentationContext();
48    SkSVGPresentationContext(const SkSVGPresentationContext&)            = default;
49    SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default;
50
51    // Inherited presentation attributes, computed for the current node.
52    SkSVGPresentationAttributes fInherited;
53
54    // Cached paints, reflecting the current presentation attributes.
55    SkPaint fFillPaint;
56    SkPaint fStrokePaint;
57};
58
59class SkSVGRenderContext {
60public:
61    SkSVGRenderContext(SkCanvas*, const SkSVGIDMapper&, const SkSVGLengthContext&,
62                       const SkSVGPresentationContext&);
63    SkSVGRenderContext(const SkSVGRenderContext&);
64    ~SkSVGRenderContext();
65
66    const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
67    SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
68
69    const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
70
71    SkCanvas* canvas() const { return fCanvas; }
72
73    enum ApplyFlags {
74        kLeaf = 1 << 0, // the target node doesn't have descendants
75    };
76    void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags);
77
78    const SkSVGNode* findNodeById(const SkString&) const;
79
80    const SkPaint* fillPaint() const;
81    const SkPaint* strokePaint() const;
82
83    // The local computed clip path (not inherited).
84    const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
85
86private:
87    // Stack-only
88    void* operator new(size_t)                               = delete;
89    void* operator new(size_t, void*)                        = delete;
90    SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
91
92    void applyOpacity(SkScalar opacity, uint32_t flags);
93    void applyClip(const SkSVGClip&);
94
95    const SkSVGIDMapper&                          fIDMapper;
96    SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
97    SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
98    SkCanvas*                                     fCanvas;
99    // The save count on 'fCanvas' at construction time.
100    // A restoreToCount() will be issued on destruction.
101    int                                           fCanvasSaveCount;
102
103    // clipPath, if present for the current context (not inherited).
104    SkTLazy<SkPath>                               fClipPath;
105};
106
107#endif // SkSVGRenderContext_DEFINED
108