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) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "mozilla/Util.h"
40 :
41 : #include "nsSVGGraphicElement.h"
42 : #include "nsGkAtoms.h"
43 : #include "nsIDOMSVGTextElement.h"
44 : #include "nsCOMPtr.h"
45 : #include "nsSVGSVGElement.h"
46 : #include "nsSVGTextPositioningElement.h"
47 : #include "nsIFrame.h"
48 : #include "nsDOMError.h"
49 : #include "SVGAnimatedLengthList.h"
50 : #include "DOMSVGAnimatedLengthList.h"
51 : #include "SVGLengthList.h"
52 : #include "SVGNumberList.h"
53 : #include "SVGAnimatedNumberList.h"
54 : #include "DOMSVGAnimatedNumberList.h"
55 : #include "DOMSVGPoint.h"
56 : #include "DOMSVGTests.h"
57 :
58 : using namespace mozilla;
59 :
60 : typedef nsSVGGraphicElement nsSVGTextElementBase;
61 :
62 : /**
63 : * This class does not inherit nsSVGTextPositioningElement - it reimplements it
64 : * instead.
65 : *
66 : * Ideally this class would inherit nsSVGTextPositioningElement in addition to
67 : * nsSVGGraphicElement, but we don't want two instances of nsSVGStylableElement
68 : * and all the classes it inherits. Instead we choose to inherit one of the
69 : * classes (nsSVGGraphicElement) and reimplement the missing pieces from the
70 : * other (nsSVGTextPositioningElement (and thus nsSVGTextContentElement)). Care
71 : * must be taken when making changes to the reimplemented pieces to keep
72 : * nsSVGTextPositioningElement in sync (and vice versa).
73 : */
74 : class nsSVGTextElement : public nsSVGTextElementBase,
75 : public nsIDOMSVGTextElement, // nsIDOMSVGTextPositioningElement
76 : public DOMSVGTests
77 0 : {
78 : protected:
79 : friend nsresult NS_NewSVGTextElement(nsIContent **aResult,
80 : already_AddRefed<nsINodeInfo> aNodeInfo);
81 : nsSVGTextElement(already_AddRefed<nsINodeInfo> aNodeInfo);
82 :
83 : public:
84 : // interfaces:
85 :
86 : NS_DECL_ISUPPORTS_INHERITED
87 : NS_DECL_NSIDOMSVGTEXTELEMENT
88 : NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
89 : NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
90 :
91 : // xxx If xpcom allowed virtual inheritance we wouldn't need to
92 : // forward here :-(
93 0 : NS_FORWARD_NSIDOMNODE(nsSVGTextElementBase::)
94 0 : NS_FORWARD_NSIDOMELEMENT(nsSVGTextElementBase::)
95 0 : NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextElementBase::)
96 :
97 : // nsIContent interface
98 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
99 :
100 : virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
101 :
102 : virtual nsXPCClassInfo* GetClassInfo();
103 : protected:
104 0 : nsSVGTextContainerFrame* GetTextContainerFrame() {
105 0 : return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
106 : }
107 :
108 : virtual LengthListAttributesInfo GetLengthListInfo();
109 : virtual NumberListAttributesInfo GetNumberListInfo();
110 :
111 : // nsIDOMSVGTextPositioning properties:
112 :
113 : enum { X, Y, DX, DY };
114 : SVGAnimatedLengthList mLengthListAttributes[4];
115 : static LengthListInfo sLengthListInfo[4];
116 :
117 : enum { ROTATE };
118 : SVGAnimatedNumberList mNumberListAttributes[1];
119 : static NumberListInfo sNumberListInfo[1];
120 : };
121 :
122 :
123 0 : NS_IMPL_NS_NEW_SVG_ELEMENT(Text)
124 :
125 :
126 : //----------------------------------------------------------------------
127 : // nsISupports methods
128 :
129 0 : NS_IMPL_ADDREF_INHERITED(nsSVGTextElement,nsSVGTextElementBase)
130 0 : NS_IMPL_RELEASE_INHERITED(nsSVGTextElement,nsSVGTextElementBase)
131 :
132 0 : DOMCI_NODE_DATA(SVGTextElement, nsSVGTextElement)
133 :
134 0 : NS_INTERFACE_TABLE_HEAD(nsSVGTextElement)
135 0 : NS_NODE_INTERFACE_TABLE7(nsSVGTextElement, nsIDOMNode, nsIDOMElement,
136 : nsIDOMSVGElement, nsIDOMSVGTextElement,
137 : nsIDOMSVGTextPositioningElement,
138 : nsIDOMSVGTextContentElement,
139 : nsIDOMSVGTests)
140 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGTextElement)
141 0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGTextElementBase)
142 :
143 : //----------------------------------------------------------------------
144 : // Implementation
145 :
146 0 : nsSVGTextElement::nsSVGTextElement(already_AddRefed<nsINodeInfo> aNodeInfo)
147 0 : : nsSVGTextElementBase(aNodeInfo)
148 : {
149 :
150 0 : }
151 :
152 : //----------------------------------------------------------------------
153 : // nsIDOMNode methods
154 :
155 :
156 0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTextElement)
157 :
158 :
159 : //----------------------------------------------------------------------
160 : // nsIDOMSVGTextElement methods
161 :
162 : // - no methods -
163 :
164 :
165 : //----------------------------------------------------------------------
166 : // nsIDOMSVGTextPositioningElement methods
167 :
168 : /* readonly attribute nsIDOMSVGAnimatedLengthList x; */
169 : NS_IMETHODIMP
170 0 : nsSVGTextElement::GetX(nsIDOMSVGAnimatedLengthList * *aX)
171 : {
172 : *aX = DOMSVGAnimatedLengthList::GetDOMWrapper(&mLengthListAttributes[X],
173 0 : this, X, nsSVGUtils::X).get();
174 0 : return NS_OK;
175 : }
176 :
177 : /* readonly attribute nsIDOMSVGAnimatedLengthList y; */
178 : NS_IMETHODIMP
179 0 : nsSVGTextElement::GetY(nsIDOMSVGAnimatedLengthList * *aY)
180 : {
181 : *aY = DOMSVGAnimatedLengthList::GetDOMWrapper(&mLengthListAttributes[Y],
182 0 : this, Y, nsSVGUtils::Y).get();
183 0 : return NS_OK;
184 : }
185 :
186 : /* readonly attribute nsIDOMSVGAnimatedLengthList dx; */
187 : NS_IMETHODIMP
188 0 : nsSVGTextElement::GetDx(nsIDOMSVGAnimatedLengthList * *aDx)
189 : {
190 : *aDx = DOMSVGAnimatedLengthList::GetDOMWrapper(&mLengthListAttributes[DX],
191 0 : this, DX, nsSVGUtils::X).get();
192 0 : return NS_OK;
193 : }
194 :
195 : /* readonly attribute nsIDOMSVGAnimatedLengthList dy; */
196 : NS_IMETHODIMP
197 0 : nsSVGTextElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy)
198 : {
199 : *aDy = DOMSVGAnimatedLengthList::GetDOMWrapper(&mLengthListAttributes[DY],
200 0 : this, DY, nsSVGUtils::Y).get();
201 0 : return NS_OK;
202 : }
203 :
204 : /* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
205 : NS_IMETHODIMP
206 0 : nsSVGTextElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
207 : {
208 : *aRotate = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[ROTATE],
209 0 : this, ROTATE).get();
210 0 : return NS_OK;
211 : }
212 :
213 :
214 : //----------------------------------------------------------------------
215 : // nsIDOMSVGTextContentElement methods
216 :
217 : /* readonly attribute nsIDOMSVGAnimatedLength textLength; */
218 : NS_IMETHODIMP
219 0 : nsSVGTextElement::GetTextLength(nsIDOMSVGAnimatedLength * *aTextLength)
220 : {
221 0 : NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetTextLength");
222 0 : return NS_ERROR_NOT_IMPLEMENTED;
223 : }
224 :
225 : /* readonly attribute nsIDOMSVGAnimatedEnumeration lengthAdjust; */
226 : NS_IMETHODIMP
227 0 : nsSVGTextElement::GetLengthAdjust(nsIDOMSVGAnimatedEnumeration * *aLengthAdjust)
228 : {
229 0 : NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetLengthAdjust");
230 0 : return NS_ERROR_NOT_IMPLEMENTED;
231 : }
232 :
233 : /* long getNumberOfChars (); */
234 : NS_IMETHODIMP
235 0 : nsSVGTextElement::GetNumberOfChars(PRInt32 *_retval)
236 : {
237 0 : *_retval = 0;
238 :
239 0 : nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
240 0 : if (metrics)
241 0 : *_retval = metrics->GetNumberOfChars();
242 :
243 0 : return NS_OK;
244 : }
245 :
246 : /* float getComputedTextLength (); */
247 : NS_IMETHODIMP
248 0 : nsSVGTextElement::GetComputedTextLength(float *_retval)
249 : {
250 0 : *_retval = 0.0;
251 :
252 0 : nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
253 0 : if (metrics)
254 0 : *_retval = metrics->GetComputedTextLength();
255 :
256 0 : return NS_OK;
257 : }
258 :
259 : /* float getSubStringLength (in unsigned long charnum, in unsigned long nchars); */
260 : NS_IMETHODIMP
261 0 : nsSVGTextElement::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
262 : {
263 0 : *_retval = 0.0f;
264 0 : nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
265 0 : if (!metrics)
266 0 : return NS_OK;
267 :
268 0 : PRUint32 charcount = metrics->GetNumberOfChars();
269 0 : if (charcount <= charnum || nchars > charcount - charnum)
270 0 : return NS_ERROR_DOM_INDEX_SIZE_ERR;
271 :
272 0 : if (nchars == 0)
273 0 : return NS_OK;
274 :
275 0 : *_retval = metrics->GetSubStringLength(charnum, nchars);
276 0 : return NS_OK;
277 : }
278 :
279 : /* nsIDOMSVGPoint getStartPositionOfChar (in unsigned long charnum); */
280 : NS_IMETHODIMP
281 0 : nsSVGTextElement::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
282 : {
283 0 : *_retval = nsnull;
284 0 : nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
285 :
286 0 : if (!metrics) return NS_ERROR_FAILURE;
287 :
288 0 : return metrics->GetStartPositionOfChar(charnum, _retval);
289 : }
290 :
291 : /* nsIDOMSVGPoint getEndPositionOfChar (in unsigned long charnum); */
292 : NS_IMETHODIMP
293 0 : nsSVGTextElement::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
294 : {
295 0 : *_retval = nsnull;
296 0 : nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
297 :
298 0 : if (!metrics) return NS_ERROR_FAILURE;
299 :
300 0 : return metrics->GetEndPositionOfChar(charnum, _retval);
301 : }
302 :
303 : /* nsIDOMSVGRect getExtentOfChar (in unsigned long charnum); */
304 : NS_IMETHODIMP
305 0 : nsSVGTextElement::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
306 : {
307 0 : *_retval = nsnull;
308 0 : nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
309 :
310 0 : if (!metrics) return NS_ERROR_FAILURE;
311 :
312 0 : return metrics->GetExtentOfChar(charnum, _retval);
313 : }
314 :
315 : /* float getRotationOfChar (in unsigned long charnum); */
316 : NS_IMETHODIMP
317 0 : nsSVGTextElement::GetRotationOfChar(PRUint32 charnum, float *_retval)
318 : {
319 0 : *_retval = 0.0;
320 :
321 0 : nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
322 :
323 0 : if (!metrics) return NS_ERROR_FAILURE;
324 :
325 0 : return metrics->GetRotationOfChar(charnum, _retval);
326 : }
327 :
328 : /* long getCharNumAtPosition (in nsIDOMSVGPoint point); */
329 : NS_IMETHODIMP
330 0 : nsSVGTextElement::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
331 : {
332 0 : nsCOMPtr<DOMSVGPoint> p = do_QueryInterface(point);
333 0 : if (!p)
334 0 : return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
335 :
336 0 : *_retval = -1;
337 :
338 0 : nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
339 0 : if (metrics)
340 0 : *_retval = metrics->GetCharNumAtPosition(point);
341 :
342 0 : return NS_OK;
343 : }
344 :
345 : /* void selectSubString (in unsigned long charnum, in unsigned long nchars); */
346 : NS_IMETHODIMP
347 0 : nsSVGTextElement::SelectSubString(PRUint32 charnum, PRUint32 nchars)
348 : {
349 0 : NS_NOTYETIMPLEMENTED("nsSVGTextElement::SelectSubString");
350 0 : return NS_ERROR_NOT_IMPLEMENTED;
351 : }
352 :
353 :
354 : //----------------------------------------------------------------------
355 : // nsIContent methods
356 :
357 : NS_IMETHODIMP_(bool)
358 0 : nsSVGTextElement::IsAttributeMapped(const nsIAtom* name) const
359 : {
360 : static const MappedAttributeEntry* const map[] = {
361 : sTextContentElementsMap,
362 : sFontSpecificationMap
363 : };
364 :
365 0 : return FindAttributeDependence(name, map) ||
366 0 : nsSVGTextElementBase::IsAttributeMapped(name);
367 : }
368 :
369 : //----------------------------------------------------------------------
370 : // nsSVGElement methods
371 :
372 : nsSVGElement::LengthListInfo nsSVGTextElement::sLengthListInfo[4] =
373 : {
374 : { &nsGkAtoms::x, nsSVGUtils::X, false },
375 : { &nsGkAtoms::y, nsSVGUtils::Y, false },
376 : { &nsGkAtoms::dx, nsSVGUtils::X, true },
377 : { &nsGkAtoms::dy, nsSVGUtils::Y, true }
378 : };
379 :
380 : nsSVGElement::LengthListAttributesInfo
381 0 : nsSVGTextElement::GetLengthListInfo()
382 : {
383 : return LengthListAttributesInfo(mLengthListAttributes, sLengthListInfo,
384 0 : ArrayLength(sLengthListInfo));
385 : }
386 :
387 : nsSVGElement::NumberListInfo nsSVGTextElement::sNumberListInfo[1] =
388 : {
389 : { &nsGkAtoms::rotate }
390 : };
391 :
392 : nsSVGElement::NumberListAttributesInfo
393 0 : nsSVGTextElement::GetNumberListInfo()
394 : {
395 : return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
396 0 : ArrayLength(sNumberListInfo));
397 : }
398 :
|