Back to index

lightning-sunbird  0.9+nobinonly
nsSVGMarkerElement.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 IBM Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2004
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either of the GNU General Public License Version 2 or later (the "GPL"),
00025  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "nsIDOMSVGFitToViewBox.h"
00038 #include "nsSVGGraphicElement.h"
00039 #include "nsSVGAtoms.h"
00040 #include "nsSVGAnimatedLength.h"
00041 #include "nsSVGAnimatedAngle.h"
00042 #include "nsSVGAnimatedRect.h"
00043 #include "nsSVGLength.h"
00044 #include "nsSVGEnum.h"
00045 #include "nsSVGAngle.h"
00046 #include "nsSVGRect.h"
00047 #include "nsSVGAnimatedEnumeration.h"
00048 #include "nsIDOMSVGMarkerElement.h"
00049 #include "nsCOMPtr.h"
00050 #include "nsSVGCoordCtxProvider.h"
00051 #include "nsISVGValueUtils.h"
00052 #include "nsSVGAnimatedPreserveAspectRatio.h"
00053 #include "nsSVGPreserveAspectRatio.h"
00054 #include "nsSVGMatrix.h"
00055 #include "nsDOMError.h"
00056 
00057 typedef nsSVGGraphicElement nsSVGMarkerElementBase;
00058 
00059 class nsSVGMarkerElement : public nsSVGMarkerElementBase,
00060                            public nsIDOMSVGMarkerElement,
00061                            public nsIDOMSVGFitToViewBox,
00062                            public nsSVGCoordCtxProvider
00063 {
00064 protected:
00065   friend nsresult NS_NewSVGMarkerElement(nsIContent **aResult,
00066                                          nsINodeInfo *aNodeInfo);
00067   nsSVGMarkerElement(nsINodeInfo* aNodeInfo);
00068   virtual ~nsSVGMarkerElement();
00069   nsresult Init();
00070 
00071 public:
00072   // interfaces:
00073 
00074   NS_DECL_ISUPPORTS_INHERITED
00075   NS_DECL_NSIDOMSVGMARKERELEMENT
00076   NS_DECL_NSIDOMSVGFITTOVIEWBOX
00077 
00078   // xxx I wish we could use virtual inheritance
00079   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGElement::)
00080   NS_FORWARD_NSIDOMELEMENT(nsSVGElement::)
00081   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::)
00082 
00083   // nsISVGValueObserver
00084   NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
00085                                      nsISVGValue::modificationType aModType);
00086   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
00087                                      nsISVGValue::modificationType aModType);
00088 
00089   // nsIContent interface
00090   NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
00091 
00092 protected:
00093   
00094   nsCOMPtr<nsIDOMSVGAnimatedLength>      mRefX;
00095   nsCOMPtr<nsIDOMSVGAnimatedLength>      mRefY;
00096   nsCOMPtr<nsIDOMSVGAnimatedEnumeration> mMarkerUnits;
00097   nsCOMPtr<nsIDOMSVGAnimatedLength>      mMarkerWidth;
00098   nsCOMPtr<nsIDOMSVGAnimatedLength>      mMarkerHeight;
00099   nsCOMPtr<nsIDOMSVGAnimatedAngle>       mOrient;
00100 
00101   nsCOMPtr<nsIDOMSVGAnimatedRect>        mViewBox;
00102   nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> mPreserveAspectRatio;
00103   nsCOMPtr<nsIDOMSVGMatrix>         mViewBoxToViewportTransform;
00104 };
00105 
00106 NS_IMPL_NS_NEW_SVG_ELEMENT(Marker)
00107 
00108 //----------------------------------------------------------------------
00109 // nsISupports methods
00110 
00111 NS_IMPL_ADDREF_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase)
00112 NS_IMPL_RELEASE_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase)
00113 
00114 NS_INTERFACE_MAP_BEGIN(nsSVGMarkerElement)
00115   NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
00116   NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
00117   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
00118   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFitToViewBox)
00119   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGMarkerElement)
00120   NS_INTERFACE_MAP_ENTRY(nsSVGCoordCtxProvider)
00121   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGMarkerElement)
00122 NS_INTERFACE_MAP_END_INHERITING(nsSVGMarkerElementBase)
00123 
00124 //----------------------------------------------------------------------
00125 // Implementation
00126 
00127   nsSVGMarkerElement::nsSVGMarkerElement(nsINodeInfo *aNodeInfo)
00128     : nsSVGMarkerElementBase(aNodeInfo)
00129 {
00130 }
00131 
00132 nsSVGMarkerElement::~nsSVGMarkerElement()
00133 {
00134 }
00135 
00136 nsresult
00137 nsSVGMarkerElement::Init()
00138 {
00139   nsresult rv = nsSVGMarkerElementBase::Init();
00140   NS_ENSURE_SUCCESS(rv,rv);
00141 
00142   // enumeration mappings
00143   static struct nsSVGEnumMapping gMarkerUnits[] = {
00144     {&nsSVGAtoms::strokeWidth, SVG_MARKERUNITS_STROKEWIDTH},
00145     {&nsSVGAtoms::userSpaceOnUse, SVG_MARKERUNITS_USERSPACEONUSE},
00146     {nsnull, 0}
00147   };
00148   
00149   // Create mapped properties:
00150 
00151   // DOM property: refX
00152   {
00153     nsCOMPtr<nsISVGLength> length;
00154     rv = NS_NewSVGLength(getter_AddRefs(length), 0.0f);
00155     NS_ENSURE_SUCCESS(rv,rv);
00156     rv = NS_NewSVGAnimatedLength(getter_AddRefs(mRefX), length);
00157     NS_ENSURE_SUCCESS(rv,rv);
00158     rv = AddMappedSVGValue(nsSVGAtoms::refX, mRefX);
00159     NS_ENSURE_SUCCESS(rv,rv);
00160   }
00161 
00162   // DOM property: refY
00163   {
00164     nsCOMPtr<nsISVGLength> length;
00165     rv = NS_NewSVGLength(getter_AddRefs(length), 0.0f);
00166     NS_ENSURE_SUCCESS(rv,rv);
00167     rv = NS_NewSVGAnimatedLength(getter_AddRefs(mRefY), length);
00168     NS_ENSURE_SUCCESS(rv,rv);
00169     rv = AddMappedSVGValue(nsSVGAtoms::refY, mRefY);
00170     NS_ENSURE_SUCCESS(rv,rv);
00171   }
00172 
00173   // DOM property: markerWidth
00174   {
00175     nsCOMPtr<nsISVGLength> length;
00176     rv = NS_NewSVGLength(getter_AddRefs(length), 3.0f);
00177     NS_ENSURE_SUCCESS(rv,rv);
00178     rv = NS_NewSVGAnimatedLength(getter_AddRefs(mMarkerWidth), length);
00179     NS_ENSURE_SUCCESS(rv,rv);
00180     rv = AddMappedSVGValue(nsSVGAtoms::markerWidth, mMarkerWidth);
00181     NS_ENSURE_SUCCESS(rv,rv);
00182   }
00183 
00184   // DOM property: markerHeight
00185   {
00186     nsCOMPtr<nsISVGLength> length;
00187     rv = NS_NewSVGLength(getter_AddRefs(length), 3.0f);
00188     NS_ENSURE_SUCCESS(rv,rv);
00189     rv = NS_NewSVGAnimatedLength(getter_AddRefs(mMarkerHeight), length);
00190     NS_ENSURE_SUCCESS(rv,rv);
00191     rv = AddMappedSVGValue(nsSVGAtoms::markerHeight, mMarkerHeight);
00192     NS_ENSURE_SUCCESS(rv,rv);
00193   }
00194 
00195   // DOM property: markerUnits
00196   {
00197     nsCOMPtr<nsISVGEnum> units;
00198     rv = NS_NewSVGEnum(getter_AddRefs(units), SVG_MARKERUNITS_STROKEWIDTH, gMarkerUnits);
00199     NS_ENSURE_SUCCESS(rv,rv);
00200     rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mMarkerUnits), units);
00201     NS_ENSURE_SUCCESS(rv,rv);
00202     rv = AddMappedSVGValue(nsSVGAtoms::markerUnits, mMarkerUnits);
00203     NS_ENSURE_SUCCESS(rv,rv);
00204   }
00205 
00206   // DOM property: orient
00207   {
00208     nsCOMPtr<nsIDOMSVGAngle> angle;
00209     rv = NS_NewSVGAngle(getter_AddRefs(angle), 0.0f);
00210     NS_ENSURE_SUCCESS(rv,rv);
00211     rv = NS_NewSVGAnimatedAngle(getter_AddRefs(mOrient), angle);
00212     NS_ENSURE_SUCCESS(rv,rv);
00213     rv = AddMappedSVGValue(nsSVGAtoms::orient, mOrient);
00214     NS_ENSURE_SUCCESS(rv,rv);
00215   }
00216 
00217   // DOM property: viewBox
00218   {
00219     nsCOMPtr<nsIDOMSVGRect> viewbox;
00220     nsCOMPtr<nsIDOMSVGLength> animWidth, animHeight;
00221     mMarkerWidth->GetAnimVal(getter_AddRefs(animWidth));
00222     mMarkerHeight->GetAnimVal(getter_AddRefs(animHeight));
00223     rv = NS_NewSVGViewBox(getter_AddRefs(viewbox), animWidth, animHeight);
00224     NS_ENSURE_SUCCESS(rv,rv);
00225     rv = NS_NewSVGAnimatedRect(getter_AddRefs(mViewBox), viewbox);
00226     NS_ENSURE_SUCCESS(rv,rv);
00227     rv = AddMappedSVGValue(nsSVGAtoms::viewBox, mViewBox);
00228     NS_ENSURE_SUCCESS(rv,rv);
00229     // initialize coordinate context with viewbox:
00230     SetCoordCtxRect(viewbox);
00231   }
00232 
00233   // DOM property: preserveAspectRatio
00234   {
00235     nsCOMPtr<nsIDOMSVGPreserveAspectRatio> preserveAspectRatio;
00236     rv = NS_NewSVGPreserveAspectRatio(getter_AddRefs(preserveAspectRatio));
00237     NS_ENSURE_SUCCESS(rv,rv);
00238     rv = NS_NewSVGAnimatedPreserveAspectRatio(
00239       getter_AddRefs(mPreserveAspectRatio),
00240       preserveAspectRatio);
00241     NS_ENSURE_SUCCESS(rv,rv);
00242     rv = AddMappedSVGValue(nsSVGAtoms::preserveAspectRatio,
00243                            mPreserveAspectRatio);
00244     NS_ENSURE_SUCCESS(rv,rv);
00245   }
00246   
00247   return NS_OK;
00248 }
00249 
00250 //----------------------------------------------------------------------
00251 // nsIDOMNode methods
00252 
00253 NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGMarkerElement)
00254 
00255 //----------------------------------------------------------------------
00256 // nsIDOMSVGFitToViewBox methods
00257 
00258 /* readonly attribute nsIDOMSVGAnimatedRect viewBox; */
00259   NS_IMETHODIMP nsSVGMarkerElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox)
00260 {
00261   *aViewBox = mViewBox;
00262   NS_ADDREF(*aViewBox);
00263   return NS_OK;
00264 }
00265 
00266 /* readonly attribute nsIDOMSVGAnimatedPreserveAspectRatio preserveAspectRatio; */
00267 NS_IMETHODIMP
00268 nsSVGMarkerElement::GetPreserveAspectRatio(nsIDOMSVGAnimatedPreserveAspectRatio * *aPreserveAspectRatio)
00269 {
00270   *aPreserveAspectRatio = mPreserveAspectRatio;
00271   NS_ADDREF(*aPreserveAspectRatio);
00272   return NS_OK;
00273 }
00274 
00275 //----------------------------------------------------------------------
00276 // nsIDOMSVGMarkerElement methods
00277 
00278 /* readonly attribute nsIDOMSVGAnimatedLength refX; */
00279 NS_IMETHODIMP nsSVGMarkerElement::GetRefX(nsIDOMSVGAnimatedLength * *aRefX)
00280 {
00281   *aRefX = mRefX;
00282   NS_IF_ADDREF(*aRefX);
00283   return NS_OK;
00284 }
00285 
00286 /* readonly attribute nsIDOMSVGAnimatedLength refY; */
00287 NS_IMETHODIMP nsSVGMarkerElement::GetRefY(nsIDOMSVGAnimatedLength * *aRefY)
00288 {
00289   *aRefY = mRefY;
00290   NS_IF_ADDREF(*aRefY);
00291   return NS_OK;
00292 }
00293 
00294 /* readonly attribute nsIDOMSVGAnimatedEnumeration markerUnits; */
00295 NS_IMETHODIMP nsSVGMarkerElement::GetMarkerUnits(nsIDOMSVGAnimatedEnumeration * *aMarkerUnits)
00296 {
00297   *aMarkerUnits = mMarkerUnits;
00298   NS_IF_ADDREF(*aMarkerUnits);
00299   return NS_OK;
00300 }
00301 
00302 /* readonly attribute nsIDOMSVGAnimatedLength markerWidth; */
00303 NS_IMETHODIMP nsSVGMarkerElement::GetMarkerWidth(nsIDOMSVGAnimatedLength * *aMarkerWidth)
00304 {
00305   *aMarkerWidth = mMarkerWidth;
00306   NS_IF_ADDREF(*aMarkerWidth);
00307   return NS_OK;
00308 }
00309 
00310 /* readonly attribute nsIDOMSVGAnimatedLength markerHeight; */
00311 NS_IMETHODIMP nsSVGMarkerElement::GetMarkerHeight(nsIDOMSVGAnimatedLength * *aMarkerHeight)
00312 {
00313   *aMarkerHeight = mMarkerHeight;
00314   NS_IF_ADDREF(*aMarkerHeight);
00315   return NS_OK;
00316 }
00317 
00318 /* readonly attribute nsIDOMSVGAnimatedEnumeration orientType; */
00319 NS_IMETHODIMP nsSVGMarkerElement::GetOrientType(nsIDOMSVGAnimatedEnumeration * *aOrientType)
00320 {
00321   static struct nsSVGEnumMapping gOrientType[] = {
00322     {&nsSVGAtoms::_auto, SVG_MARKER_ORIENT_AUTO},
00323     {nsnull, 0}
00324   };
00325 
00326   nsresult rv;
00327   nsCOMPtr<nsISVGEnum> orient;
00328   rv = NS_NewSVGEnum(getter_AddRefs(orient), SVG_MARKER_ORIENT_ANGLE, gOrientType);
00329   NS_ENSURE_SUCCESS(rv,rv);
00330   nsCOMPtr<nsIDOMSVGAnimatedEnumeration> orientType;
00331   rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(orientType), orient);
00332   NS_ENSURE_SUCCESS(rv,rv);
00333 
00334   nsIDOMSVGAngle *a;
00335   mOrient->GetBaseVal(&a);
00336   nsAutoString value;
00337   a->GetValueAsString(value);
00338   if (value.EqualsLiteral("auto")) {
00339     orientType->SetBaseVal(SVG_MARKER_ORIENT_AUTO);
00340   } else {
00341     orientType->SetBaseVal(SVG_MARKER_ORIENT_ANGLE);
00342   }
00343 
00344   *aOrientType = orientType;
00345   NS_IF_ADDREF(*aOrientType);
00346   return NS_OK;
00347 }
00348 
00349 /* readonly attribute nsIDOMSVGAnimatedLength orientAngle; */
00350 NS_IMETHODIMP nsSVGMarkerElement::GetOrientAngle(nsIDOMSVGAnimatedAngle * *aOrientAngle)
00351 {
00352   *aOrientAngle = mOrient;
00353   NS_IF_ADDREF(*aOrientAngle);
00354   return NS_OK;
00355 }
00356 
00357 /* void setOrientToAuto (); */
00358 NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAuto()
00359 {
00360   nsIDOMSVGAngle *a;
00361   mOrient->GetBaseVal(&a);
00362   a->SetValueAsString(NS_LITERAL_STRING("auto"));
00363   return NS_OK;
00364 }
00365 
00366 /* void setOrientToAngle (in nsIDOMSVGAngle angle); */
00367 NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAngle(nsIDOMSVGAngle *angle)
00368 {
00369   if (!angle)
00370     return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
00371 
00372   nsIDOMSVGAngle *a;
00373   mOrient->GetBaseVal(&a);
00374   float f;
00375   angle->GetValue(&f);
00376   a->SetValue(f);
00377   return NS_OK;
00378 }
00379 
00380 NS_IMETHODIMP
00381 nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth,
00382                                        float aX, float aY, float aAngle,
00383                                        nsIDOMSVGMatrix **_retval)
00384 {
00385   float scale = 1.0;
00386   PRUint16 val;
00387   mMarkerUnits->GetAnimVal(&val);
00388   if (val == SVG_MARKERUNITS_STROKEWIDTH)
00389     scale = aStrokeWidth;
00390 
00391   nsCOMPtr<nsIDOMSVGAngle> a;
00392   mOrient->GetAnimVal(getter_AddRefs(a));
00393   nsAutoString value;
00394   a->GetValueAsString(value);
00395   if (!value.EqualsLiteral("auto"))
00396      a->GetValue(&aAngle);
00397 
00398   nsCOMPtr<nsIDOMSVGMatrix> matrix;
00399   NS_NewSVGMatrix(getter_AddRefs(matrix),
00400                   cos(aAngle) * scale,   sin(aAngle) * scale,
00401                   -sin(aAngle) * scale,  cos(aAngle) * scale,
00402                   aX,                    aY);
00403     
00404   *_retval = matrix;
00405   NS_IF_ADDREF(*_retval);
00406   return NS_OK;
00407 }
00408 
00409 
00410 /* nsIDOMSVGMatrix getViewboxToViewportTransform (); */
00411 NS_IMETHODIMP
00412 nsSVGMarkerElement::GetViewboxToViewportTransform(nsIDOMSVGMatrix **_retval)
00413 {
00414   nsresult rv = NS_OK;
00415 
00416   if (!mViewBoxToViewportTransform) {
00417     float viewportWidth;
00418     {
00419       nsCOMPtr<nsIDOMSVGLength> l;
00420       mMarkerWidth->GetAnimVal(getter_AddRefs(l));
00421       l->GetValue(&viewportWidth);
00422     }
00423     float viewportHeight;
00424     {
00425       nsCOMPtr<nsIDOMSVGLength> l;
00426       mMarkerHeight->GetAnimVal(getter_AddRefs(l));
00427       l->GetValue(&viewportHeight);
00428     }
00429 
00430     float viewboxX, viewboxY, viewboxWidth, viewboxHeight;
00431     {
00432       nsCOMPtr<nsIDOMSVGRect> vb;
00433       mViewBox->GetAnimVal(getter_AddRefs(vb));
00434       NS_ASSERTION(vb, "could not get viewbox");
00435       vb->GetX(&viewboxX);
00436       vb->GetY(&viewboxY);
00437       vb->GetWidth(&viewboxWidth);
00438       vb->GetHeight(&viewboxHeight);
00439     }
00440     if (viewboxWidth==0.0f || viewboxHeight==0.0f) {
00441       NS_ERROR("XXX. We shouldn't get here. Viewbox width/height is set to 0. Need to disable display of element as per specs.");
00442       viewboxWidth = 1.0f;
00443       viewboxHeight = 1.0f;
00444     }
00445     
00446     PRUint16 align, meetOrSlice;
00447     {
00448       nsCOMPtr<nsIDOMSVGPreserveAspectRatio> par;
00449       mPreserveAspectRatio->GetAnimVal(getter_AddRefs(par));
00450       NS_ASSERTION(par, "could not get preserveAspectRatio");
00451       par->GetAlign(&align);
00452       par->GetMeetOrSlice(&meetOrSlice);
00453     }
00454 
00455     // default to the defaults
00456     if (align == nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_UNKNOWN)
00457       align = nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID;
00458     if (meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_UNKNOWN)
00459       meetOrSlice = nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_MEET;
00460     
00461     float a, d, e, f;
00462     a = viewportWidth/viewboxWidth;
00463     d = viewportHeight/viewboxHeight;
00464     e = 0.0f;
00465     f = 0.0f;
00466 
00467     if (align != nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE &&
00468         a != d) {
00469       if (meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_MEET &&
00470           a < d ||
00471           meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE &&
00472           d < a) {
00473         d = a;
00474       }
00475       else if (
00476         meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_MEET &&
00477         d < a ||
00478         meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE &&
00479         a < d) {
00480         a = d;
00481       }
00482       else NS_NOTREACHED("Unknown value for meetOrSlice");
00483     }
00484 
00485     if (viewboxX) e += -a * viewboxX;
00486     if (viewboxY) f += -d * viewboxY;
00487 
00488     float refX;
00489     {
00490       nsCOMPtr<nsIDOMSVGLength> l;
00491       mRefX->GetAnimVal(getter_AddRefs(l));
00492       l->GetValue(&refX);
00493     }
00494 
00495     float refY;
00496     {
00497       nsCOMPtr<nsIDOMSVGLength> l;
00498       mRefY->GetAnimVal(getter_AddRefs(l));
00499       l->GetValue(&refY);
00500     }
00501 
00502     e -= refX * a;
00503     f -= refY * d;
00504     
00505 #ifdef DEBUG
00506     printf("Marker Viewport=(0?,0?,%f,%f)\n", viewportWidth, viewportHeight);
00507     printf("Marker Viewbox=(%f,%f,%f,%f)\n", viewboxX, viewboxY, viewboxWidth, viewboxHeight);
00508     printf("Marker Viewbox->Viewport xform [a c e] = [%f,   0, %f]\n", a, e);
00509     printf("                            [b d f] = [   0,  %f, %f]\n", d, f);
00510 #endif
00511     
00512     rv = NS_NewSVGMatrix(getter_AddRefs(mViewBoxToViewportTransform),
00513                          a,     0.0f,
00514                          0.0f,  d,
00515                          e,     f);
00516   }
00517 
00518   *_retval = mViewBoxToViewportTransform;
00519   NS_IF_ADDREF(*_retval);
00520   return rv;
00521 }
00522 
00523 //----------------------------------------------------------------------
00524 // nsISVGValueObserver methods:
00525 
00526 NS_IMETHODIMP
00527 nsSVGMarkerElement::WillModifySVGObservable(nsISVGValue* observable,
00528                                             nsISVGValue::modificationType aModType)
00529 {
00530   return NS_OK;
00531 }
00532 
00533 
00534 NS_IMETHODIMP
00535 nsSVGMarkerElement::DidModifySVGObservable(nsISVGValue* observable,
00536                                            nsISVGValue::modificationType aModType)
00537 {
00538   mViewBoxToViewportTransform = nsnull;
00539 
00540   nsCOMPtr<nsIDOMSVGAnimatedLength> l = do_QueryInterface(observable);
00541   nsCOMPtr<nsIDOMSVGAnimatedRect> r = do_QueryInterface(observable);
00542   if ((l && (l == mMarkerWidth || l == mMarkerHeight)) || (r && (r == mViewBox))) {
00543     // sync coordinate context with viewbox:
00544     nsIDOMSVGRect *viewbox;
00545     mViewBox->GetBaseVal(&viewbox);
00546     SetCoordCtxRect(viewbox);
00547   }
00548 
00549   return NS_OK;
00550 }
00551 
00552 //----------------------------------------------------------------------
00553 // nsIContent methods
00554 
00555 NS_IMETHODIMP_(PRBool)
00556 nsSVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const
00557 {
00558   static const MappedAttributeEntry* const map[] = {
00559     sViewportsMap,
00560   };
00561   
00562   return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
00563     nsSVGMarkerElementBase::IsAttributeMapped(name);
00564 }