Back to index

lightning-sunbird  0.9+nobinonly
nsSVGImageElement.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) 2003
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 "nsIDOMSVGImageElement.h"
00042 #include "nsIDOMSVGURIReference.h"
00043 #include "nsSVGLength.h"
00044 #include "nsSVGAnimatedLength.h"
00045 #include "nsSVGAnimatedString.h"
00046 #include "nsCOMPtr.h"
00047 #include "nsISVGSVGElement.h"
00048 #include "nsSVGCoordCtxProvider.h"
00049 #include "nsIURI.h"
00050 #include "nsNetUtil.h"
00051 #include "nsSVGAnimatedPreserveAspectRatio.h"
00052 #include "nsSVGPreserveAspectRatio.h"
00053 #include "nsImageLoadingContent.h"
00054 #include "imgIContainer.h"
00055 #include "imgIDecoderObserver.h"
00056 
00057 typedef nsSVGGraphicElement nsSVGImageElementBase;
00058 
00059 class nsSVGImageElement : public nsSVGImageElementBase,
00060                           public nsIDOMSVGImageElement,
00061                           public nsIDOMSVGURIReference,
00062                           public nsImageLoadingContent
00063 {
00064 protected:
00065   friend nsresult NS_NewSVGImageElement(nsIContent **aResult,
00066                                         nsINodeInfo *aNodeInfo);
00067   nsSVGImageElement(nsINodeInfo *aNodeInfo);
00068   virtual ~nsSVGImageElement();
00069   nsresult Init();
00070 
00071 public:
00072   // interfaces:
00073   
00074   NS_DECL_ISUPPORTS_INHERITED
00075   NS_DECL_NSIDOMSVGIMAGEELEMENT
00076   NS_DECL_NSIDOMSVGURIREFERENCE
00077 
00078   // xxx I wish we could use virtual inheritance
00079   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGImageElementBase::)
00080   NS_FORWARD_NSIDOMELEMENT(nsSVGImageElementBase::)
00081   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGImageElementBase::)
00082 
00083   // nsISVGContent specializations:
00084   virtual void ParentChainChanged();
00085 
00086   // nsISVGValueObserver specializations:
00087   NS_IMETHOD DidModifySVGObservable(nsISVGValue *observable,
00088                                     nsISVGValue::modificationType aModType);
00089 
00090   // nsIContent interface
00091   NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
00092 
00093 protected:
00094   void GetSrc(nsAString& src);
00095   
00096   nsCOMPtr<nsIDOMSVGAnimatedLength> mX;
00097   nsCOMPtr<nsIDOMSVGAnimatedLength> mY;
00098   nsCOMPtr<nsIDOMSVGAnimatedLength> mWidth;
00099   nsCOMPtr<nsIDOMSVGAnimatedLength> mHeight;
00100   nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
00101   nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> mPreserveAspectRatio;
00102 };
00103 
00104 
00105 NS_IMPL_NS_NEW_SVG_ELEMENT(Image)
00106 
00107 
00108 //----------------------------------------------------------------------
00109 // nsISupports methods
00110 
00111 NS_IMPL_ADDREF_INHERITED(nsSVGImageElement,nsSVGImageElementBase)
00112 NS_IMPL_RELEASE_INHERITED(nsSVGImageElement,nsSVGImageElementBase)
00113 
00114 NS_INTERFACE_MAP_BEGIN(nsSVGImageElement)
00115   NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
00116   NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
00117   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
00118   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGImageElement)
00119   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGURIReference)
00120   NS_INTERFACE_MAP_ENTRY(imgIDecoderObserver)
00121   NS_INTERFACE_MAP_ENTRY(imgIDecoderObserver_MOZILLA_1_8_BRANCH)
00122   NS_INTERFACE_MAP_ENTRY(nsIImageLoadingContent)
00123   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGImageElement)
00124 NS_INTERFACE_MAP_END_INHERITING(nsSVGImageElementBase)
00125 
00126 //----------------------------------------------------------------------
00127 // Implementation
00128 
00129 nsSVGImageElement::nsSVGImageElement(nsINodeInfo *aNodeInfo)
00130   : nsSVGImageElementBase(aNodeInfo)
00131 {
00132 
00133 }
00134 
00135 nsSVGImageElement::~nsSVGImageElement()
00136 {
00137   DestroyImageLoadingContent();
00138 }
00139 
00140   
00141 nsresult
00142 nsSVGImageElement::Init()
00143 {
00144   nsresult rv = nsSVGImageElementBase::Init();
00145   NS_ENSURE_SUCCESS(rv,rv);
00146 
00147   // Create mapped properties:
00148   
00149 
00150   // nsIDOMSVGImage properties
00151   
00152   // DOM property: x ,  #IMPLIED attrib: x
00153   {
00154     nsCOMPtr<nsISVGLength> length;
00155     rv = NS_NewSVGLength(getter_AddRefs(length),
00156                          0.0f);
00157     NS_ENSURE_SUCCESS(rv,rv);
00158     rv = NS_NewSVGAnimatedLength(getter_AddRefs(mX), length);
00159     NS_ENSURE_SUCCESS(rv,rv);
00160     rv = AddMappedSVGValue(nsSVGAtoms::x, mX);
00161     NS_ENSURE_SUCCESS(rv,rv);
00162   }
00163 
00164   // DOM property: y ,  #IMPLIED attrib: y
00165   {
00166     nsCOMPtr<nsISVGLength> length;
00167     rv = NS_NewSVGLength(getter_AddRefs(length),
00168                          0.0f);
00169     NS_ENSURE_SUCCESS(rv,rv);
00170     rv = NS_NewSVGAnimatedLength(getter_AddRefs(mY), length);
00171     NS_ENSURE_SUCCESS(rv,rv);
00172     rv = AddMappedSVGValue(nsSVGAtoms::y, mY);
00173     NS_ENSURE_SUCCESS(rv,rv);
00174   }
00175 
00176   // DOM property: width ,  #REQUIRED  attrib: width
00177   // XXX: enforce requiredness
00178   {
00179     nsCOMPtr<nsISVGLength> length;
00180     rv = NS_NewSVGLength(getter_AddRefs(length),
00181                          100.0f);
00182     NS_ENSURE_SUCCESS(rv,rv);
00183     rv = NS_NewSVGAnimatedLength(getter_AddRefs(mWidth), length);
00184     NS_ENSURE_SUCCESS(rv,rv);
00185     rv = AddMappedSVGValue(nsSVGAtoms::width, mWidth);
00186     NS_ENSURE_SUCCESS(rv,rv);
00187   }
00188 
00189   // DOM property: height ,  #REQUIRED  attrib: height
00190   // XXX: enforce requiredness
00191   {
00192     nsCOMPtr<nsISVGLength> length;
00193     rv = NS_NewSVGLength(getter_AddRefs(length),
00194                          100.0f);
00195     NS_ENSURE_SUCCESS(rv,rv);
00196     rv = NS_NewSVGAnimatedLength(getter_AddRefs(mHeight), length);
00197     NS_ENSURE_SUCCESS(rv,rv);
00198     rv = AddMappedSVGValue(nsSVGAtoms::height, mHeight);
00199     NS_ENSURE_SUCCESS(rv,rv);
00200   }
00201 
00202   // nsIDOMSVGURIReference properties
00203 
00204   // DOM property: href , #REQUIRED attrib: xlink:href
00205   // XXX: enforce requiredness
00206   {
00207     rv = NS_NewSVGAnimatedString(getter_AddRefs(mHref));
00208     NS_ENSURE_SUCCESS(rv,rv);
00209     rv = AddMappedSVGValue(nsSVGAtoms::href, mHref, kNameSpaceID_XLink);
00210     NS_ENSURE_SUCCESS(rv,rv);
00211   }
00212 
00213   // DOM property: preserveAspectRatio , #IMPLIED attrib: preserveAspectRatio
00214   {
00215     nsCOMPtr<nsIDOMSVGPreserveAspectRatio> preserveAspectRatio;
00216     rv = NS_NewSVGPreserveAspectRatio(getter_AddRefs(preserveAspectRatio));
00217     NS_ENSURE_SUCCESS(rv,rv);
00218     rv = NS_NewSVGAnimatedPreserveAspectRatio(
00219                                           getter_AddRefs(mPreserveAspectRatio),
00220                                           preserveAspectRatio);
00221     NS_ENSURE_SUCCESS(rv,rv);
00222     rv = AddMappedSVGValue(nsSVGAtoms::preserveAspectRatio,
00223                            mPreserveAspectRatio);
00224     NS_ENSURE_SUCCESS(rv,rv);
00225   }
00226 
00227   return rv;
00228 }
00229 
00230 //----------------------------------------------------------------------
00231 // nsIDOMNode methods
00232 
00233 
00234 NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGImageElement)
00235 
00236 
00237 //----------------------------------------------------------------------
00238 // nsIDOMSVGImageElement methods:
00239 
00240 /* readonly attribute nsIDOMSVGAnimatedLength x; */
00241 NS_IMETHODIMP nsSVGImageElement::GetX(nsIDOMSVGAnimatedLength * *aX)
00242 {
00243   *aX = mX;
00244   NS_IF_ADDREF(*aX);
00245   return NS_OK;
00246 }
00247 
00248 /* readonly attribute nsIDOMSVGAnimatedLength y; */
00249 NS_IMETHODIMP nsSVGImageElement::GetY(nsIDOMSVGAnimatedLength * *aY)
00250 {
00251   *aY = mY;
00252   NS_IF_ADDREF(*aY);
00253   return NS_OK;
00254 }
00255 
00256 /* readonly attribute nsIDOMSVGAnimatedLength width; */
00257 NS_IMETHODIMP nsSVGImageElement::GetWidth(nsIDOMSVGAnimatedLength * *aWidth)
00258 {
00259   *aWidth = mWidth;
00260   NS_IF_ADDREF(*aWidth);
00261   return NS_OK;
00262 }
00263 
00264 /* readonly attribute nsIDOMSVGAnimatedLength height; */
00265 NS_IMETHODIMP nsSVGImageElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
00266 {
00267   *aHeight = mHeight;
00268   NS_IF_ADDREF(*aHeight);
00269   return NS_OK;
00270 }
00271 
00272 /* readonly attribute nsIDOMSVGAnimatedPreserveAspectRatio preserveAspectRatio; */
00273 NS_IMETHODIMP
00274 nsSVGImageElement::GetPreserveAspectRatio(nsIDOMSVGAnimatedPreserveAspectRatio
00275                                           **aPreserveAspectRatio)
00276 {
00277   *aPreserveAspectRatio = mPreserveAspectRatio;
00278   NS_IF_ADDREF(*aPreserveAspectRatio);
00279   return NS_OK;
00280 }
00281 
00282 //----------------------------------------------------------------------
00283 // nsIDOMSVGURIReference methods:
00284 
00285 /* readonly attribute nsIDOMSVGAnimatedString href; */
00286 NS_IMETHODIMP
00287 nsSVGImageElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
00288 {
00289   *aHref = mHref;
00290   NS_IF_ADDREF(*aHref);
00291   return NS_OK;
00292 }
00293 
00294 
00295 //----------------------------------------------------------------------
00296 // nsISVGContent methods
00297 
00298 void nsSVGImageElement::ParentChainChanged()
00299 {
00300   // set new context information on our length-properties:
00301   
00302   nsCOMPtr<nsIDOMSVGSVGElement> dom_elem;
00303   GetOwnerSVGElement(getter_AddRefs(dom_elem));
00304   if (!dom_elem) return;
00305 
00306   nsCOMPtr<nsSVGCoordCtxProvider> ctx = do_QueryInterface(dom_elem);
00307   NS_ASSERTION(ctx, "<svg> element missing interface");
00308 
00309   // x:
00310   {
00311     nsCOMPtr<nsIDOMSVGLength> dom_length;
00312     mX->GetAnimVal(getter_AddRefs(dom_length));
00313     nsCOMPtr<nsISVGLength> length = do_QueryInterface(dom_length);
00314     NS_ASSERTION(length, "svg length missing interface");
00315 
00316     length->SetContext(nsRefPtr<nsSVGCoordCtx>(ctx->GetContextX()));
00317   }
00318 
00319   // y:
00320   {
00321     nsCOMPtr<nsIDOMSVGLength> dom_length;
00322     mY->GetAnimVal(getter_AddRefs(dom_length));
00323     nsCOMPtr<nsISVGLength> length = do_QueryInterface(dom_length);
00324     NS_ASSERTION(length, "svg length missing interface");
00325     
00326     length->SetContext(nsRefPtr<nsSVGCoordCtx>(ctx->GetContextY()));
00327   }
00328 
00329   // width:
00330   {
00331     nsCOMPtr<nsIDOMSVGLength> dom_length;
00332     mWidth->GetAnimVal(getter_AddRefs(dom_length));
00333     nsCOMPtr<nsISVGLength> length = do_QueryInterface(dom_length);
00334     NS_ASSERTION(length, "svg length missing interface");
00335     
00336     length->SetContext(nsRefPtr<nsSVGCoordCtx>(ctx->GetContextX()));
00337   }
00338 
00339   // height:
00340   {
00341     nsCOMPtr<nsIDOMSVGLength> dom_length;
00342     mHeight->GetAnimVal(getter_AddRefs(dom_length));
00343     nsCOMPtr<nsISVGLength> length = do_QueryInterface(dom_length);
00344     NS_ASSERTION(length, "svg length missing interface");
00345     
00346     length->SetContext(nsRefPtr<nsSVGCoordCtx>(ctx->GetContextY()));
00347   }
00348 }  
00349 
00350 
00351 //----------------------------------------------------------------------
00352 
00353 void nsSVGImageElement::GetSrc(nsAString& src)
00354 {
00355   // resolve href attribute
00356 
00357   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
00358 
00359   nsAutoString relURIStr;
00360   mHref->GetAnimVal(relURIStr);
00361   relURIStr.Trim(" \t\n\r");
00362 
00363   if (baseURI && !relURIStr.IsEmpty()) 
00364     NS_MakeAbsoluteURI(src, relURIStr, baseURI);
00365   else
00366     src = relURIStr;
00367 }
00368 
00369 //----------------------------------------------------------------------
00370 // nsISVGValueObserver methods:
00371 
00372 NS_IMETHODIMP
00373 nsSVGImageElement::DidModifySVGObservable(nsISVGValue* aObservable,
00374                                           nsISVGValue::modificationType aModType)
00375 {
00376   nsCOMPtr<nsIDOMSVGAnimatedString> s = do_QueryInterface(aObservable);
00377 
00378   if (s && mHref == s) {
00379     nsAutoString href;
00380     GetSrc(href);
00381 
00382 #ifdef DEBUG_tor
00383     fprintf(stderr, "nsSVGImageElement - URI <%s>\n", ToNewCString(href));
00384 #endif
00385 
00386     // If caller is not chrome and dom.disable_image_src_set is true,
00387     // prevent setting image.src by exiting early
00388     if (nsContentUtils::GetBoolPref("dom.disable_image_src_set") &&
00389         !nsContentUtils::IsCallerChrome()) {
00390       return NS_OK;
00391     }
00392 
00393     ImageURIChanged(href, PR_TRUE);
00394   }
00395 
00396   return nsSVGImageElementBase::DidModifySVGObservable(aObservable, aModType);
00397 }
00398 
00399 NS_IMETHODIMP_(PRBool)
00400 nsSVGImageElement::IsAttributeMapped(const nsIAtom* name) const
00401 {
00402   static const MappedAttributeEntry* const map[] = {
00403     sViewportsMap,
00404   };
00405   
00406   return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
00407     nsSVGImageElementBase::IsAttributeMapped(name);
00408 }