summaryrefslogtreecommitdiffstats
path: root/dom/svg/SVGViewportElement.h
blob: 6c62c3e8408951e5dafdbc9ab1307de3dd65abcc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef DOM_SVG_SVGVIEWPORTELEMENT_H_
#define DOM_SVG_SVGVIEWPORTELEMENT_H_

#include "mozilla/Attributes.h"
#include "mozilla/SVGImageContext.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/FromParser.h"
#include "nsIContentInlines.h"
#include "SVGAnimatedEnumeration.h"
#include "SVGAnimatedLength.h"
#include "SVGAnimatedPreserveAspectRatio.h"
#include "SVGAnimatedViewBox.h"
#include "SVGGraphicsElement.h"
#include "SVGPoint.h"
#include "SVGPreserveAspectRatio.h"

namespace mozilla {
class AutoPreserveAspectRatioOverride;
class SVGOuterSVGFrame;
class SVGViewportFrame;

namespace dom {
class DOMSVGAnimatedPreserveAspectRatio;
class SVGAnimatedRect;
class SVGViewElement;
class SVGViewportElement;

class svgFloatSize {
 public:
  svgFloatSize(float aWidth, float aHeight) : width(aWidth), height(aHeight) {}
  bool operator!=(const svgFloatSize& rhs) {
    return width != rhs.width || height != rhs.height;
  }
  float width;
  float height;
};

class SVGViewportElement : public SVGGraphicsElement {
  friend class mozilla::SVGOuterSVGFrame;
  friend class mozilla::SVGViewportFrame;

 protected:
  explicit SVGViewportElement(
      already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
  ~SVGViewportElement() = default;

 public:
  bool IsNodeOfType(uint32_t aFlags) const override;

  // nsIContent interface
  NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;

  // SVGElement specializations:
  virtual gfxMatrix PrependLocalTransformsTo(
      const gfxMatrix& aMatrix,
      SVGTransformTypes aWhich = eAllTransforms) const override;

  virtual bool HasValidDimensions() const override;

  // SVGViewportElement methods:

  float GetLength(uint8_t aCtxType);

  // public helpers:

  /**
   * Returns true if this element has a base/anim value for its "viewBox"
   * attribute that defines a viewBox rectangle with finite values, or
   * if there is a view element overriding this element's viewBox and it
   * has a valid viewBox.
   *
   * Note that this does not check whether we need to synthesize a viewBox,
   * so you must call ShouldSynthesizeViewBox() if you need to chck that too.
   *
   * Note also that this method does not pay attention to whether the width or
   * height values of the viewBox rect are positive!
   */
  bool HasViewBox() const { return GetViewBoxInternal().HasRect(); }

  /**
   * Returns true if we should synthesize a viewBox for ourselves (that is, if
   * we're the root element in an image document, and we're not currently being
   * painted for an <svg:image> element).
   *
   * Only call this method if HasViewBox() returns false.
   */
  bool ShouldSynthesizeViewBox() const;

  bool HasViewBoxOrSyntheticViewBox() const {
    return HasViewBox() || ShouldSynthesizeViewBox();
  }

  bool HasChildrenOnlyTransform() const { return mHasChildrenOnlyTransform; }

  void UpdateHasChildrenOnlyTransform();

  enum ChildrenOnlyTransformChangedFlags { eDuringReflow = 1 };

  /**
   * This method notifies the style system that the overflow rects of our
   * immediate childrens' frames need to be updated. It is called by our own
   * frame when changes (e.g. to currentScale) cause our children-only
   * transform to change.
   *
   * The reason we have this method instead of overriding
   * GetAttributeChangeHint is because we need to act on non-attribute (e.g.
   * currentScale) changes in addition to attribute (e.g. viewBox) changes.
   */
  void ChildrenOnlyTransformChanged(uint32_t aFlags = 0);

  gfx::Matrix GetViewBoxTransform() const;

  svgFloatSize GetViewportSize() const {
    return svgFloatSize(mViewportWidth, mViewportHeight);
  }

  void SetViewportSize(const svgFloatSize& aSize) {
    mViewportWidth = aSize.width;
    mViewportHeight = aSize.height;
  }

  /**
   * Returns true if either this is an SVG <svg> element that is the child of
   * another non-foreignObject SVG element, or this is a SVG <symbol> element
   * that is the root of a use-element shadow tree.
   */
  bool IsInner() const {
    const nsIContent* parent = GetFlattenedTreeParent();
    return parent && parent->IsSVGElement() &&
           !parent->IsSVGElement(nsGkAtoms::foreignObject);
  }

  // WebIDL
  already_AddRefed<SVGAnimatedRect> ViewBox();
  already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
  virtual SVGAnimatedViewBox* GetAnimatedViewBox() override;

 protected:
  // implementation helpers:

  bool IsRootSVGSVGElement() const {
    NS_ASSERTION((IsInUncomposedDoc() && !GetParent()) ==
                     (OwnerDoc()->GetRootElement() == this),
                 "Can't determine if we're root");
    return !GetParent() && IsInUncomposedDoc() && IsSVGElement(nsGkAtoms::svg);
  }

  /**
   * Returns the explicit or default preserveAspectRatio, unless we're
   * synthesizing a viewBox, in which case it returns the "none" value.
   */
  virtual SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const {
    return mPreserveAspectRatio.GetAnimValue();
  }

  /**
   * Returns the explicit viewBox rect, if specified, or else a synthesized
   * viewBox, if appropriate, or else a viewBox matching the dimensions of the
   * SVG viewport.
   */
  SVGViewBox GetViewBoxWithSynthesis(float aViewportWidth,
                                     float aViewportHeight) const;

  enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
  SVGAnimatedLength mLengthAttributes[4];
  static LengthInfo sLengthInfo[4];
  virtual LengthAttributesInfo GetLengthInfo() override;

  virtual SVGAnimatedPreserveAspectRatio* GetAnimatedPreserveAspectRatio()
      override;

  virtual const SVGAnimatedViewBox& GetViewBoxInternal() const {
    return mViewBox;
  }
  virtual SVGAnimatedTransformList* GetTransformInternal() const {
    return mTransforms.get();
  }
  SVGAnimatedViewBox mViewBox;
  SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;

  // The size of the rectangular SVG viewport into which we render. This is
  // not (necessarily) the same as the content area. See:
  //
  //   http://www.w3.org/TR/SVG11/coords.html#ViewportSpace
  //
  // XXXjwatt Currently only used for outer <svg>, but maybe we could use -1 to
  // flag this as an inner <svg> to save the overhead of GetCtx calls?
  // XXXjwatt our frame should probably reset these when it's destroyed.
  float mViewportWidth, mViewportHeight;

  bool mHasChildrenOnlyTransform;
};

}  // namespace dom

}  // namespace mozilla

#endif  // DOM_SVG_SVGVIEWPORTELEMENT_H_