1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is the Mozilla SVG project.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Crocodile Clips Ltd..
19 : * Portions created by the Initial Developer are Copyright (C) 2001
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
24 : * Jonathan Watt <jonathan.watt@strath.ac.uk>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "mozilla/Util.h"
41 :
42 : #include "nsSVGGraphicElement.h"
43 : #include "nsSVGSVGElement.h"
44 : #include "DOMSVGAnimatedTransformList.h"
45 : #include "DOMSVGMatrix.h"
46 : #include "nsGkAtoms.h"
47 : #include "nsIDOMEventTarget.h"
48 : #include "nsIFrame.h"
49 : #include "nsISVGChildFrame.h"
50 : #include "nsIDOMSVGPoint.h"
51 : #include "nsSVGUtils.h"
52 : #include "nsDOMError.h"
53 : #include "nsSVGRect.h"
54 : #include "nsContentUtils.h"
55 :
56 : using namespace mozilla;
57 :
58 : //----------------------------------------------------------------------
59 : // nsISupports methods
60 :
61 0 : NS_IMPL_ADDREF_INHERITED(nsSVGGraphicElement, nsSVGGraphicElementBase)
62 0 : NS_IMPL_RELEASE_INHERITED(nsSVGGraphicElement, nsSVGGraphicElementBase)
63 :
64 0 : NS_INTERFACE_MAP_BEGIN(nsSVGGraphicElement)
65 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLocatable)
66 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTransformable)
67 0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGGraphicElementBase)
68 :
69 : //----------------------------------------------------------------------
70 : // Implementation
71 :
72 0 : nsSVGGraphicElement::nsSVGGraphicElement(already_AddRefed<nsINodeInfo> aNodeInfo)
73 0 : : nsSVGGraphicElementBase(aNodeInfo)
74 : {
75 0 : }
76 :
77 : //----------------------------------------------------------------------
78 : // nsIDOMSVGLocatable methods
79 :
80 : /* readonly attribute nsIDOMSVGElement nearestViewportElement; */
81 0 : NS_IMETHODIMP nsSVGGraphicElement::GetNearestViewportElement(nsIDOMSVGElement * *aNearestViewportElement)
82 : {
83 0 : *aNearestViewportElement = nsSVGUtils::GetNearestViewportElement(this).get();
84 0 : return NS_OK;
85 : }
86 :
87 : /* readonly attribute nsIDOMSVGElement farthestViewportElement; */
88 0 : NS_IMETHODIMP nsSVGGraphicElement::GetFarthestViewportElement(nsIDOMSVGElement * *aFarthestViewportElement)
89 : {
90 0 : NS_IF_ADDREF(*aFarthestViewportElement = nsSVGUtils::GetOuterSVGElement(this));
91 0 : return NS_OK;
92 : }
93 :
94 : /* nsIDOMSVGRect getBBox (); */
95 0 : NS_IMETHODIMP nsSVGGraphicElement::GetBBox(nsIDOMSVGRect **_retval)
96 : {
97 0 : *_retval = nsnull;
98 :
99 0 : nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
100 :
101 0 : if (!frame || (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD))
102 0 : return NS_ERROR_FAILURE;
103 :
104 0 : nsISVGChildFrame* svgframe = do_QueryFrame(frame);
105 0 : if (svgframe) {
106 0 : return NS_NewSVGRect(_retval, nsSVGUtils::GetBBox(frame));
107 : }
108 0 : return NS_ERROR_FAILURE;
109 : }
110 :
111 : /* nsIDOMSVGMatrix getCTM (); */
112 0 : NS_IMETHODIMP nsSVGGraphicElement::GetCTM(nsIDOMSVGMatrix * *aCTM)
113 : {
114 0 : gfxMatrix m = nsSVGUtils::GetCTM(this, false);
115 0 : *aCTM = m.IsSingular() ? nsnull : new DOMSVGMatrix(m);
116 0 : NS_IF_ADDREF(*aCTM);
117 0 : return NS_OK;
118 : }
119 :
120 : /* nsIDOMSVGMatrix getScreenCTM (); */
121 0 : NS_IMETHODIMP nsSVGGraphicElement::GetScreenCTM(nsIDOMSVGMatrix * *aCTM)
122 : {
123 0 : gfxMatrix m = nsSVGUtils::GetCTM(this, true);
124 0 : *aCTM = m.IsSingular() ? nsnull : new DOMSVGMatrix(m);
125 0 : NS_IF_ADDREF(*aCTM);
126 0 : return NS_OK;
127 : }
128 :
129 : /* nsIDOMSVGMatrix getTransformToElement (in nsIDOMSVGElement element); */
130 0 : NS_IMETHODIMP nsSVGGraphicElement::GetTransformToElement(nsIDOMSVGElement *element, nsIDOMSVGMatrix **_retval)
131 : {
132 0 : if (!element)
133 0 : return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
134 :
135 : nsresult rv;
136 0 : *_retval = nsnull;
137 0 : nsCOMPtr<nsIDOMSVGMatrix> ourScreenCTM;
138 0 : nsCOMPtr<nsIDOMSVGMatrix> targetScreenCTM;
139 0 : nsCOMPtr<nsIDOMSVGMatrix> tmp;
140 0 : nsCOMPtr<nsIDOMSVGLocatable> target = do_QueryInterface(element, &rv);
141 0 : if (NS_FAILED(rv)) return rv;
142 :
143 : // the easiest way to do this (if likely to increase rounding error):
144 0 : GetScreenCTM(getter_AddRefs(ourScreenCTM));
145 0 : if (!ourScreenCTM) return NS_ERROR_DOM_SVG_MATRIX_NOT_INVERTABLE;
146 0 : target->GetScreenCTM(getter_AddRefs(targetScreenCTM));
147 0 : if (!targetScreenCTM) return NS_ERROR_DOM_SVG_MATRIX_NOT_INVERTABLE;
148 0 : rv = targetScreenCTM->Inverse(getter_AddRefs(tmp));
149 0 : if (NS_FAILED(rv)) return rv;
150 0 : return tmp->Multiply(ourScreenCTM, _retval); // addrefs, so we don't
151 : }
152 :
153 : //----------------------------------------------------------------------
154 : // nsIDOMSVGTransformable methods
155 : /* readonly attribute nsIDOMSVGAnimatedTransformList transform; */
156 :
157 0 : NS_IMETHODIMP nsSVGGraphicElement::GetTransform(
158 : nsIDOMSVGAnimatedTransformList **aTransform)
159 : {
160 : *aTransform =
161 0 : DOMSVGAnimatedTransformList::GetDOMWrapper(GetAnimatedTransformList(), this)
162 0 : .get();
163 0 : return NS_OK;
164 : }
165 :
166 : //----------------------------------------------------------------------
167 : // nsIContent methods
168 :
169 : NS_IMETHODIMP_(bool)
170 0 : nsSVGGraphicElement::IsAttributeMapped(const nsIAtom* name) const
171 : {
172 : static const MappedAttributeEntry* const map[] = {
173 : sColorMap,
174 : sFillStrokeMap,
175 : sGraphicsMap
176 : };
177 :
178 0 : return FindAttributeDependence(name, map) ||
179 0 : nsSVGGraphicElementBase::IsAttributeMapped(name);
180 : }
181 :
182 : //----------------------------------------------------------------------
183 : // nsSVGElement overrides
184 :
185 : bool
186 0 : nsSVGGraphicElement::IsEventName(nsIAtom* aName)
187 : {
188 0 : return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
189 : }
190 :
191 : gfxMatrix
192 0 : nsSVGGraphicElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
193 : TransformTypes aWhich) const
194 : {
195 0 : NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
196 : "Skipping eUserSpaceToParent transforms makes no sense");
197 :
198 0 : gfxMatrix result(aMatrix);
199 :
200 0 : if (aWhich == eChildToUserSpace) {
201 : // We don't have anything to prepend.
202 : // eChildToUserSpace is not the common case, which is why we return
203 : // 'result' to benefit from NRVO rather than returning aMatrix before
204 : // creating 'result'.
205 0 : return result;
206 : }
207 :
208 0 : NS_ABORT_IF_FALSE(aWhich == eAllTransforms || aWhich == eUserSpaceToParent,
209 : "Unknown TransformTypes");
210 :
211 : // animateMotion's resulting transform is supposed to apply *on top of*
212 : // any transformations from the |transform| attribute. So since we're
213 : // PRE-multiplying, we need to apply the animateMotion transform *first*.
214 0 : if (mAnimateMotionTransform) {
215 0 : result.PreMultiply(*mAnimateMotionTransform);
216 : }
217 :
218 0 : if (mTransforms) {
219 0 : result.PreMultiply(mTransforms->GetAnimValue().GetConsolidationMatrix());
220 : }
221 :
222 0 : return result;
223 : }
224 :
225 : void
226 0 : nsSVGGraphicElement::SetAnimateMotionTransform(const gfxMatrix* aMatrix)
227 : {
228 0 : mAnimateMotionTransform = aMatrix ? new gfxMatrix(*aMatrix) : nsnull;
229 0 : DidAnimateTransformList();
230 0 : }
231 :
232 : SVGAnimatedTransformList*
233 0 : nsSVGGraphicElement::GetAnimatedTransformList()
234 : {
235 0 : if (!mTransforms) {
236 0 : mTransforms = new SVGAnimatedTransformList();
237 : }
238 0 : return mTransforms;
239 : }
|