Back to index

lightning-sunbird  0.9+nobinonly
nsSVGPathElement.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Mozilla SVG project.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Crocodile Clips Ltd..
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsSVGGraphicElement.h"
00040 #include "nsSVGAtoms.h"
00041 #include "nsSVGPathSegList.h"
00042 #include "nsIDOMSVGPathElement.h"
00043 #include "nsIDOMSVGAnimatedPathData.h"
00044 #include "nsIDOMSVGPathSeg.h"
00045 #include "nsSVGPathSeg.h"
00046 #include "nsCOMPtr.h"
00047 #include "nsISVGPathFlatten.h"
00048 #include "nsIDocument.h"
00049 #include "nsIFrame.h"
00050 #include "nsISVGGlyphMetricsSource.h"
00051 #include "nsSVGPoint.h"
00052 
00053 typedef nsSVGGraphicElement nsSVGPathElementBase;
00054 
00055 class nsSVGPathElement : public nsSVGPathElementBase,
00056                          public nsIDOMSVGPathElement,
00057                          public nsIDOMSVGAnimatedPathData
00058 {
00059 protected:
00060   friend nsresult NS_NewSVGPathElement(nsIContent **aResult,
00061                                        nsINodeInfo *aNodeInfo);
00062   nsSVGPathElement(nsINodeInfo *aNodeInfo);
00063   virtual ~nsSVGPathElement();
00064   nsresult Init();
00065 
00066 public:
00067   // interfaces:
00068   
00069   NS_DECL_ISUPPORTS_INHERITED
00070   NS_DECL_NSIDOMSVGPATHELEMENT
00071   NS_DECL_NSIDOMSVGANIMATEDPATHDATA
00072 
00073   // xxx I wish we could use virtual inheritance
00074   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGPathElementBase::)
00075   NS_FORWARD_NSIDOMELEMENT(nsSVGPathElementBase::)
00076   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGPathElementBase::)
00077 
00078   // nsIStyledContent interface
00079   NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
00080   
00081 protected:
00082 
00083   already_AddRefed<nsISVGPathFlatten> GetPathFlatten();
00084 
00085   nsCOMPtr<nsIDOMSVGPathSegList> mSegments;
00086 };
00087 
00088 
00089 NS_IMPL_NS_NEW_SVG_ELEMENT(Path)
00090 
00091 
00092 //----------------------------------------------------------------------
00093 // nsISupports methods
00094 
00095 NS_IMPL_ADDREF_INHERITED(nsSVGPathElement,nsSVGPathElementBase)
00096 NS_IMPL_RELEASE_INHERITED(nsSVGPathElement,nsSVGPathElementBase)
00097 
00098 NS_INTERFACE_MAP_BEGIN(nsSVGPathElement)
00099   NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
00100   NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
00101   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
00102   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGPathElement)
00103   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedPathData)
00104   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGPathElement)
00105 NS_INTERFACE_MAP_END_INHERITING(nsSVGPathElementBase)
00106 
00107 //----------------------------------------------------------------------
00108 // Implementation
00109 
00110 nsSVGPathElement::nsSVGPathElement(nsINodeInfo* aNodeInfo)
00111   : nsSVGPathElementBase(aNodeInfo)
00112 {
00113 
00114 }
00115 
00116 nsSVGPathElement::~nsSVGPathElement()
00117 {
00118 }
00119 
00120   
00121 nsresult
00122 nsSVGPathElement::Init()
00123 {
00124   nsresult rv = nsSVGPathElementBase::Init();
00125   NS_ENSURE_SUCCESS(rv,rv);
00126 
00127   // Create mapped properties:
00128 
00129   // d #REQUIRED
00130   rv = NS_NewSVGPathSegList(getter_AddRefs(mSegments));
00131   NS_ENSURE_SUCCESS(rv,rv);
00132   rv = AddMappedSVGValue(nsSVGAtoms::d, mSegments);
00133   NS_ENSURE_SUCCESS(rv,rv);
00134   
00135   return rv;
00136 }
00137 
00138 //----------------------------------------------------------------------
00139 // nsIDOMNode methods
00140 
00141 
00142 NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGPathElement)
00143 
00144 
00145 //----------------------------------------------------------------------
00146 // nsIDOMSVGPathElement methods:
00147 
00148 /* readonly attribute nsIDOMSVGAnimatedNumber pathLength; */
00149 NS_IMETHODIMP
00150 nsSVGPathElement::GetPathLength(nsIDOMSVGAnimatedNumber * *aPathLength)
00151 {
00152   return NS_ERROR_NOT_IMPLEMENTED;
00153 }
00154 
00155 /* float getTotalLength (); */
00156 NS_IMETHODIMP
00157 nsSVGPathElement::GetTotalLength(float *_retval)
00158 {
00159   *_retval = 0;
00160   nsCOMPtr<nsISVGPathFlatten> flattener = GetPathFlatten();
00161   if (!flattener)
00162     return NS_ERROR_FAILURE;
00163 
00164   nsSVGPathData *data;
00165   flattener->GetFlattenedPath(&data);
00166   *_retval = data->Length();
00167 
00168   delete data;
00169 
00170   return NS_OK;
00171 }
00172 
00173 void
00174 NS_SVGFindPointOnPath(nsSVGPathData *data,
00175                       float aX, float aY, float aAdvance,
00176                       nsSVGCharacterPosition *aCP);
00177 
00178 /* nsIDOMSVGPoint getPointAtLength (in float distance); */
00179 NS_IMETHODIMP
00180 nsSVGPathElement::GetPointAtLength(float distance, nsIDOMSVGPoint **_retval)
00181 {
00182   *_retval = nsnull;
00183   nsCOMPtr<nsISVGPathFlatten> flattener = GetPathFlatten();
00184   if (!flattener)
00185     return NS_ERROR_FAILURE;
00186 
00187   nsSVGPathData *data;
00188   flattener->GetFlattenedPath(&data);
00189   if (!data)
00190     return NS_ERROR_OUT_OF_MEMORY;
00191 
00192   float length = data->Length();
00193   distance = PR_MAX(0,      distance);
00194   distance = PR_MIN(length, distance);
00195 
00196   nsSVGCharacterPosition cp;
00197   NS_SVGFindPointOnPath(data, distance, 0, 0, &cp);
00198 
00199   delete data;
00200 
00201   return NS_NewSVGPoint(_retval, cp.x, cp.y);
00202 }
00203 
00204 /* unsigned long getPathSegAtLength (in float distance); */
00205 NS_IMETHODIMP
00206 nsSVGPathElement::GetPathSegAtLength(float distance, PRUint32 *_retval)
00207 {
00208   return NS_ERROR_NOT_IMPLEMENTED;
00209 }
00210 
00211 /* nsIDOMSVGPathSegClosePath createSVGPathSegClosePath (); */
00212 NS_IMETHODIMP
00213 nsSVGPathElement::CreateSVGPathSegClosePath(nsIDOMSVGPathSegClosePath **_retval)
00214 {
00215   return NS_NewSVGPathSegClosePath(_retval);
00216 }
00217 
00218 /* nsIDOMSVGPathSegMovetoAbs createSVGPathSegMovetoAbs (in float x, in float y); */
00219 NS_IMETHODIMP
00220 nsSVGPathElement::CreateSVGPathSegMovetoAbs(float x, float y, nsIDOMSVGPathSegMovetoAbs **_retval)
00221 {
00222   return NS_NewSVGPathSegMovetoAbs(_retval, x, y);
00223 }
00224 
00225 /* nsIDOMSVGPathSegMovetoRel createSVGPathSegMovetoRel (in float x, in float y); */
00226 NS_IMETHODIMP
00227 nsSVGPathElement::CreateSVGPathSegMovetoRel(float x, float y, nsIDOMSVGPathSegMovetoRel **_retval)
00228 {
00229   return NS_NewSVGPathSegMovetoRel(_retval, x, y);
00230 }
00231 
00232 /* nsIDOMSVGPathSegLinetoAbs createSVGPathSegLinetoAbs (in float x, in float y); */
00233 NS_IMETHODIMP
00234 nsSVGPathElement::CreateSVGPathSegLinetoAbs(float x, float y, nsIDOMSVGPathSegLinetoAbs **_retval)
00235 {
00236   return NS_NewSVGPathSegLinetoAbs(_retval, x, y);
00237 }
00238 
00239 /* nsIDOMSVGPathSegLinetoRel createSVGPathSegLinetoRel (in float x, in float y); */
00240 NS_IMETHODIMP
00241 nsSVGPathElement::CreateSVGPathSegLinetoRel(float x, float y, nsIDOMSVGPathSegLinetoRel **_retval)
00242 {
00243   return NS_NewSVGPathSegLinetoRel(_retval, x, y);
00244 }
00245 
00246 /* nsIDOMSVGPathSegCurvetoCubicAbs createSVGPathSegCurvetoCubicAbs (in float x, in float y, in float x1, in float y1, in float x2, in float y2); */
00247 NS_IMETHODIMP
00248 nsSVGPathElement::CreateSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2, nsIDOMSVGPathSegCurvetoCubicAbs **_retval)
00249 {
00250   return NS_NewSVGPathSegCurvetoCubicAbs(_retval, x, y, x1, y1, x2, y2);
00251 }
00252 
00253 /* nsIDOMSVGPathSegCurvetoCubicRel createSVGPathSegCurvetoCubicRel (in float x, in float y, in float x1, in float y1, in float x2, in float y2); */
00254 NS_IMETHODIMP
00255 nsSVGPathElement::CreateSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2, nsIDOMSVGPathSegCurvetoCubicRel **_retval)
00256 {
00257   return NS_NewSVGPathSegCurvetoCubicRel(_retval, x, y, x1, y1, x2, y2);
00258 }
00259 
00260 /* nsIDOMSVGPathSegCurvetoQuadraticAbs createSVGPathSegCurvetoQuadraticAbs (in float x, in float y, in float x1, in float y1); */
00261 NS_IMETHODIMP
00262 nsSVGPathElement::CreateSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1, nsIDOMSVGPathSegCurvetoQuadraticAbs **_retval)
00263 {
00264   return NS_NewSVGPathSegCurvetoQuadraticAbs(_retval, x, y, x1, y1);
00265 }
00266 
00267 /* nsIDOMSVGPathSegCurvetoQuadraticRel createSVGPathSegCurvetoQuadraticRel (in float x, in float y, in float x1, in float y1); */
00268 NS_IMETHODIMP
00269 nsSVGPathElement::CreateSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1, nsIDOMSVGPathSegCurvetoQuadraticRel **_retval)
00270 {
00271   return NS_NewSVGPathSegCurvetoQuadraticRel(_retval, x, y, x1, y1);
00272 }
00273 
00274 /* nsIDOMSVGPathSegArcAbs createSVGPathSegArcAbs (in float x, in float y, in float r1, in float r2, in float angle, in boolean largeArcFlag, in boolean sweepFlag); */
00275 NS_IMETHODIMP
00276 nsSVGPathElement::CreateSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, PRBool largeArcFlag, PRBool sweepFlag, nsIDOMSVGPathSegArcAbs **_retval)
00277 {
00278   return NS_NewSVGPathSegArcAbs(_retval, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
00279 }
00280 
00281 /* nsIDOMSVGPathSegArcRel createSVGPathSegArcRel (in float x, in float y, in float r1, in float r2, in float angle, in boolean largeArcFlag, in boolean sweepFlag); */
00282 NS_IMETHODIMP
00283 nsSVGPathElement::CreateSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, PRBool largeArcFlag, PRBool sweepFlag, nsIDOMSVGPathSegArcRel **_retval)
00284 {
00285   return NS_NewSVGPathSegArcRel(_retval, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
00286 }
00287 
00288 /* nsIDOMSVGPathSegLinetoHorizontalAbs createSVGPathSegLinetoHorizontalAbs (in float x); */
00289 NS_IMETHODIMP
00290 nsSVGPathElement::CreateSVGPathSegLinetoHorizontalAbs(float x, nsIDOMSVGPathSegLinetoHorizontalAbs **_retval)
00291 {
00292   return NS_NewSVGPathSegLinetoHorizontalAbs(_retval, x);
00293 }
00294 
00295 /* nsIDOMSVGPathSegLinetoHorizontalRel createSVGPathSegLinetoHorizontalRel (in float x); */
00296 NS_IMETHODIMP
00297 nsSVGPathElement::CreateSVGPathSegLinetoHorizontalRel(float x, nsIDOMSVGPathSegLinetoHorizontalRel **_retval)
00298 {
00299   return NS_NewSVGPathSegLinetoHorizontalRel(_retval, x);
00300 }
00301 
00302 /* nsIDOMSVGPathSegLinetoVerticalAbs createSVGPathSegLinetoVerticalAbs (in float y); */
00303 NS_IMETHODIMP
00304 nsSVGPathElement::CreateSVGPathSegLinetoVerticalAbs(float y, nsIDOMSVGPathSegLinetoVerticalAbs **_retval)
00305 {
00306   return NS_NewSVGPathSegLinetoVerticalAbs(_retval, y);
00307 }
00308 
00309 /* nsIDOMSVGPathSegLinetoVerticalRel createSVGPathSegLinetoVerticalRel (in float y); */
00310 NS_IMETHODIMP
00311 nsSVGPathElement::CreateSVGPathSegLinetoVerticalRel(float y, nsIDOMSVGPathSegLinetoVerticalRel **_retval)
00312 {
00313   return NS_NewSVGPathSegLinetoVerticalRel(_retval, y);
00314 }
00315 
00316 /* nsIDOMSVGPathSegCurvetoCubicSmoothAbs createSVGPathSegCurvetoCubicSmoothAbs (in float x, in float y, in float x2, in float y2); */
00317 NS_IMETHODIMP
00318 nsSVGPathElement::CreateSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2, nsIDOMSVGPathSegCurvetoCubicSmoothAbs **_retval)
00319 {
00320   return NS_NewSVGPathSegCurvetoCubicSmoothAbs(_retval, x, y, x2, y2);
00321 }
00322 
00323 /* nsIDOMSVGPathSegCurvetoCubicSmoothRel createSVGPathSegCurvetoCubicSmoothRel (in float x, in float y, in float x2, in float y2); */
00324 NS_IMETHODIMP
00325 nsSVGPathElement::CreateSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2, nsIDOMSVGPathSegCurvetoCubicSmoothRel **_retval)
00326 {
00327   return NS_NewSVGPathSegCurvetoCubicSmoothRel(_retval, x, y, x2, y2);
00328 }
00329 
00330 /* nsIDOMSVGPathSegCurvetoQuadraticSmoothAbs createSVGPathSegCurvetoQuadraticSmoothAbs (in float x, in float y); */
00331 NS_IMETHODIMP
00332 nsSVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y, nsIDOMSVGPathSegCurvetoQuadraticSmoothAbs **_retval)
00333 {
00334   return NS_NewSVGPathSegCurvetoQuadraticSmoothAbs(_retval, x, y);
00335 }
00336 
00337 /* nsIDOMSVGPathSegCurvetoQuadraticSmoothRel createSVGPathSegCurvetoQuadraticSmoothRel (in float x, in float y); */
00338 NS_IMETHODIMP
00339 nsSVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothRel(float x, float y, nsIDOMSVGPathSegCurvetoQuadraticSmoothRel **_retval)
00340 {
00341   return NS_NewSVGPathSegCurvetoQuadraticSmoothRel(_retval, x, y);
00342 }
00343 
00344 
00345 //----------------------------------------------------------------------
00346 // nsIDOMSVGAnimatedPathData methods:
00347 
00348 /* readonly attribute nsIDOMSVGPathSegList pathSegList; */
00349 NS_IMETHODIMP nsSVGPathElement::GetPathSegList(nsIDOMSVGPathSegList * *aPathSegList)
00350 {
00351   *aPathSegList = mSegments;
00352   NS_ADDREF(*aPathSegList);
00353   return NS_OK;
00354 }
00355 
00356 /* readonly attribute nsIDOMSVGPathSegList normalizedPathSegList; */
00357 NS_IMETHODIMP nsSVGPathElement::GetNormalizedPathSegList(nsIDOMSVGPathSegList * *aNormalizedPathSegList)
00358 {
00359   return NS_ERROR_NOT_IMPLEMENTED;
00360 }
00361 
00362 /* readonly attribute nsIDOMSVGPathSegList animatedPathSegList; */
00363 NS_IMETHODIMP nsSVGPathElement::GetAnimatedPathSegList(nsIDOMSVGPathSegList * *aAnimatedPathSegList)
00364 {
00365   *aAnimatedPathSegList = mSegments;
00366   NS_ADDREF(*aAnimatedPathSegList);
00367   return NS_OK;
00368 }
00369 
00370 /* readonly attribute nsIDOMSVGPathSegList animatedNormalizedPathSegList; */
00371 NS_IMETHODIMP nsSVGPathElement::GetAnimatedNormalizedPathSegList(nsIDOMSVGPathSegList * *aAnimatedNormalizedPathSegList)
00372 {
00373   return NS_ERROR_NOT_IMPLEMENTED;
00374 }
00375 
00376 //----------------------------------------------------------------------
00377 // nsIStyledContent methods
00378 
00379 NS_IMETHODIMP_(PRBool)
00380 nsSVGPathElement::IsAttributeMapped(const nsIAtom* name) const
00381 {
00382   static const MappedAttributeEntry* const map[] = {
00383     sMarkersMap,
00384   };
00385   
00386   return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
00387     nsSVGPathElementBase::IsAttributeMapped(name);
00388 }
00389 
00390 //----------------------------------------------------------------------
00391 // implementation helpers:
00392 
00393 already_AddRefed<nsISVGPathFlatten>
00394 nsSVGPathElement::GetPathFlatten()
00395 {
00396   nsIDocument* doc = GetCurrentDoc();
00397   if (!doc) {
00398     NS_ERROR("no document");
00399     return nsnull;
00400   }
00401   
00402   nsIPresShell* presShell = doc->GetShellAt(0);
00403   if (!presShell) {
00404     NS_ERROR("no presshell");
00405     return nsnull;
00406   }
00407 
00408   nsIFrame* frame;
00409   presShell->GetPrimaryFrameFor(NS_STATIC_CAST(nsIStyledContent*, this), &frame);
00410 
00411   if (!frame) {
00412     NS_ERROR("no frame");
00413     return nsnull;
00414   }
00415   
00416   nsISVGPathFlatten* flattener;
00417   frame->QueryInterface(NS_GET_IID(nsISVGPathFlatten),(void**)&flattener);
00418   NS_ASSERTION(flattener, "wrong frame type");
00419   return flattener;
00420 }