Back to index

lightning-sunbird  0.9+nobinonly
nsSVGRect.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  *   Jonathan Watt <jonathan.watt@strath.ac.uk>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsSVGRect.h"
00041 #include "prdtoa.h"
00042 #include "nsSVGValue.h"
00043 #include "nsISVGValueUtils.h"
00044 #include "nsTextFormatter.h"
00045 #include "nsCRT.h"
00046 #include "nsWeakReference.h"
00047 #include "nsIDOMSVGLength.h"
00048 #include "nsContentUtils.h"
00049 #include "nsDOMError.h"
00050 
00052 // nsSVGRect class
00053 
00054 class nsSVGRect : public nsIDOMSVGRect,
00055                   public nsSVGValue
00056 {
00057 public:
00058   nsSVGRect(float x=0.0f, float y=0.0f, float w=0.0f, float h=0.0f);
00059   
00060   // nsISupports interface:
00061   NS_DECL_ISUPPORTS
00062 
00063   // nsIDOMSVGRect interface:
00064   NS_DECL_NSIDOMSVGRECT
00065 
00066   // nsISVGValue interface:
00067   NS_IMETHOD SetValueString(const nsAString& aValue);
00068   NS_IMETHOD GetValueString(nsAString& aValue);
00069 
00070 
00071 protected:
00072   float mX, mY, mWidth, mHeight;
00073 };
00074 
00075 //----------------------------------------------------------------------
00076 // implementation:
00077 
00078 nsSVGRect::nsSVGRect(float x, float y, float w, float h)
00079     : mX(x), mY(y), mWidth(w), mHeight(h)
00080 {
00081 }
00082 
00083 //----------------------------------------------------------------------
00084 // nsISupports methods:
00085 
00086 NS_IMPL_ADDREF(nsSVGRect)
00087 NS_IMPL_RELEASE(nsSVGRect)
00088 
00089 NS_INTERFACE_MAP_BEGIN(nsSVGRect)
00090   NS_INTERFACE_MAP_ENTRY(nsISVGValue)
00091   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGRect)
00092   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGRect)
00093   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
00094 NS_INTERFACE_MAP_END
00095 
00096 //----------------------------------------------------------------------
00097 // nsISVGValue methods:
00098 
00099 NS_IMETHODIMP
00100 nsSVGRect::SetValueString(const nsAString& aValue)
00101 {
00102   nsresult rv = NS_OK;
00103 
00104   char* str = ToNewCString(aValue);
00105 
00106   char* rest = str;
00107   char* token;
00108   const char* delimiters = ",\x20\x9\xD\xA";
00109 
00110   double vals[4];
00111   int i;
00112   for (i=0;i<4;++i) {
00113     if (!(token = nsCRT::strtok(rest, delimiters, &rest))) break; // parse error
00114 
00115     char *end;
00116     vals[i] = PR_strtod(token, &end);
00117     if (*end != '\0') break; // parse error
00118   }
00119   if (i!=4 || (nsCRT::strtok(rest, delimiters, &rest)!=0)) {
00120     // there was a parse error.
00121     rv = NS_ERROR_FAILURE;
00122   }
00123   else {
00124     WillModify();
00125     mX      = float(vals[0]);
00126     mY      = float(vals[1]);
00127     mWidth  = float(vals[2]);
00128     mHeight = float(vals[3]);
00129     DidModify();
00130   }
00131 
00132   nsMemory::Free(str);
00133 
00134   return rv;
00135 }
00136 
00137 NS_IMETHODIMP
00138 nsSVGRect::GetValueString(nsAString& aValue)
00139 {
00140   PRUnichar buf[200];
00141   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
00142                             NS_LITERAL_STRING("%g %g %g %g").get(),
00143                             (double)mX, (double)mY,
00144                             (double)mWidth, (double)mHeight);
00145   aValue.Assign(buf);
00146 
00147   return NS_OK;
00148 }
00149 
00150 //----------------------------------------------------------------------
00151 // nsIDOMSVGRect methods:
00152 
00153 /* attribute float x; */
00154 NS_IMETHODIMP nsSVGRect::GetX(float *aX)
00155 {
00156   *aX = mX;
00157   return NS_OK;
00158 }
00159 NS_IMETHODIMP nsSVGRect::SetX(float aX)
00160 {
00161   WillModify();
00162   mX = aX;
00163   DidModify();
00164   return NS_OK;
00165 }
00166 
00167 /* attribute float y; */
00168 NS_IMETHODIMP nsSVGRect::GetY(float *aY)
00169 {
00170   *aY = mY;
00171   return NS_OK;
00172 }
00173 NS_IMETHODIMP nsSVGRect::SetY(float aY)
00174 {
00175   WillModify();
00176   mY = aY;
00177   DidModify();
00178   return NS_OK;
00179 }
00180 
00181 /* attribute float width; */
00182 NS_IMETHODIMP nsSVGRect::GetWidth(float *aWidth)
00183 {
00184   *aWidth = mWidth;
00185   return NS_OK;
00186 }
00187 NS_IMETHODIMP nsSVGRect::SetWidth(float aWidth)
00188 {
00189   WillModify();
00190   mWidth = aWidth;
00191   DidModify();
00192   return NS_OK;
00193 }
00194 
00195 /* attribute float height; */
00196 NS_IMETHODIMP nsSVGRect::GetHeight(float *aHeight)
00197 {
00198   *aHeight = mHeight;
00199   return NS_OK;
00200 }
00201 NS_IMETHODIMP nsSVGRect::SetHeight(float aHeight)
00202 {
00203   WillModify();
00204   mHeight = aHeight;
00205   DidModify();
00206   return NS_OK;
00207 }
00208 
00209 
00210 
00212 // Implement a readonly version of SVGRect
00213 //
00214 // We need this because attributes of some SVG interfaces *and* the objects the
00215 // attributes refer to (including SVGRects) are supposed to be readonly
00216 
00217 class nsSVGReadonlyRect : public nsSVGRect
00218 {
00219 public:
00220   nsSVGReadonlyRect(float x, float y, float width, float height)
00221     : nsSVGRect(x, y, width, height)
00222   {
00223   };
00224 
00225   // override setters to make the whole object readonly
00226   NS_IMETHODIMP SetX(float) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
00227   NS_IMETHODIMP SetY(float) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
00228   NS_IMETHODIMP SetWidth(float) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
00229   NS_IMETHODIMP SetHeight(float) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
00230   NS_IMETHODIMP SetValueString(const nsAString&) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
00231 };
00232 
00233 
00234 
00236 // nsSVGViewBox : a special kind of nsIDOMSVGRect that defaults to
00237 // (0,0,viewportWidth.value,viewportHeight.value) until set explicitly.
00238 
00239 class nsSVGViewBox : public nsSVGRect,
00240                      public nsISVGValueObserver,
00241                      public nsSupportsWeakReference
00242 {
00243 public:
00244   nsSVGViewBox(nsIDOMSVGLength* viewportWidth,
00245                nsIDOMSVGLength* viewportHeight);
00246   virtual ~nsSVGViewBox();
00247 
00248   // nsISupports interface:
00249   NS_DECL_ISUPPORTS
00250   
00251   // nsISVGValueObserver interface:
00252   NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
00253                                      modificationType aModType);
00254   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
00255                                      modificationType aModType);
00256 
00257   // nsIDOMSVGRect specializations:
00258   NS_IMETHOD SetX(float aX);
00259   NS_IMETHOD SetY(float aY);
00260   NS_IMETHOD SetWidth(float aWidth);
00261   NS_IMETHOD SetHeight(float aHeight);
00262 
00263   // nsISVGValue specializations:
00264   NS_IMETHOD SetValueString(const nsAString& aValue);
00265   
00266 private:
00267   void MarkSet();
00268   
00269   PRBool mIsSet;
00270   nsCOMPtr<nsIDOMSVGLength> mViewportWidth;
00271   nsCOMPtr<nsIDOMSVGLength> mViewportHeight;
00272 };
00273 
00274 //----------------------------------------------------------------------
00275 // implementation:
00276 nsSVGViewBox::nsSVGViewBox(nsIDOMSVGLength* viewportWidth, nsIDOMSVGLength* viewportHeight)
00277     : mIsSet(PR_FALSE),
00278       mViewportWidth(viewportWidth),
00279       mViewportHeight(viewportHeight)
00280 {
00281   mViewportWidth->GetValue(&mWidth);
00282   mViewportHeight->GetValue(&mHeight);
00283   NS_ADDREF(this);
00284   NS_ADD_SVGVALUE_OBSERVER(mViewportWidth);
00285   NS_ADD_SVGVALUE_OBSERVER(mViewportHeight);
00286 }
00287 
00288 nsSVGViewBox::~nsSVGViewBox()
00289 {
00290   if (!mIsSet) {
00291     NS_REMOVE_SVGVALUE_OBSERVER(mViewportWidth);
00292     NS_REMOVE_SVGVALUE_OBSERVER(mViewportHeight);
00293   }
00294 }
00295 
00296 void nsSVGViewBox::MarkSet()
00297 {
00298   if (mIsSet) return;
00299   mIsSet = PR_TRUE;
00300   NS_REMOVE_SVGVALUE_OBSERVER(mViewportWidth);
00301   NS_REMOVE_SVGVALUE_OBSERVER(mViewportHeight);
00302 }
00303 
00304 //----------------------------------------------------------------------
00305 // nsISupports:
00306 
00307 NS_IMPL_ADDREF_INHERITED(nsSVGViewBox, nsSVGRect)
00308 NS_IMPL_RELEASE_INHERITED(nsSVGViewBox, nsSVGRect)
00309 
00310 NS_INTERFACE_MAP_BEGIN(nsSVGViewBox)
00311   NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
00312   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
00313 NS_INTERFACE_MAP_END_INHERITING(nsSVGRect)
00314 
00315 //----------------------------------------------------------------------
00316 // nsISVGValueObserver methods:
00317 
00318 NS_IMETHODIMP
00319 nsSVGViewBox::WillModifySVGObservable(nsISVGValue* observable,
00320                                       modificationType aModType)
00321 {
00322   return NS_OK;
00323 }
00324 
00325 NS_IMETHODIMP
00326 nsSVGViewBox::DidModifySVGObservable(nsISVGValue* observable,
00327                                      modificationType aModType)
00328 {
00329   NS_ASSERTION(!mIsSet, "inconsistent state");
00330   WillModify(aModType);
00331   mViewportWidth->GetValue(&mWidth);
00332   mViewportHeight->GetValue(&mHeight);  
00333   DidModify(aModType);
00334   return NS_OK;
00335 }
00336 
00337 //----------------------------------------------------------------------
00338 // nsIDOMSVGRect specializations:
00339 NS_IMETHODIMP
00340 nsSVGViewBox::SetX(float aX)
00341 {
00342   MarkSet();
00343   return nsSVGRect::SetX(aX);
00344 }
00345 
00346 NS_IMETHODIMP
00347 nsSVGViewBox::SetY(float aY)
00348 {
00349   MarkSet();
00350   return nsSVGRect::SetY(aY);
00351 }
00352 
00353 NS_IMETHODIMP
00354 nsSVGViewBox::SetWidth(float aWidth)
00355 {
00356   MarkSet();
00357   return nsSVGRect::SetWidth(aWidth);
00358 }
00359 
00360 NS_IMETHODIMP
00361 nsSVGViewBox::SetHeight(float aHeight)
00362 {
00363   MarkSet();
00364   return nsSVGRect::SetHeight(aHeight);
00365 }
00366 
00367 
00368 //----------------------------------------------------------------------
00369 // nsISVGValue specializations:
00370 
00371 NS_IMETHODIMP
00372 nsSVGViewBox::SetValueString(const nsAString& aValue)
00373 {
00374   MarkSet();
00375   return nsSVGRect::SetValueString(aValue);
00376 }
00377 
00378 
00380 // Exported creation functions:
00381 
00382 nsresult
00383 NS_NewSVGRect(nsIDOMSVGRect** result, float x, float y,
00384               float width, float height)
00385 {
00386   *result = new nsSVGRect(x, y, width, height);
00387   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00388   NS_ADDREF(*result);
00389   return NS_OK;
00390 }
00391 
00392 nsresult
00393 NS_NewSVGReadonlyRect(nsIDOMSVGRect** result, float x, float y,
00394                       float width, float height)
00395 {
00396   *result = new nsSVGReadonlyRect(x, y, width, height);
00397   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00398   NS_ADDREF(*result);
00399   return NS_OK;
00400 }
00401 
00402 nsresult
00403 NS_NewSVGViewBox(nsIDOMSVGRect** result,
00404                  nsIDOMSVGLength *viewportWidth,
00405                  nsIDOMSVGLength *viewportHeight)
00406 {
00407   if (!viewportHeight || !viewportWidth) {
00408     NS_ERROR("need viewport height/width for viewbox");
00409     return NS_ERROR_FAILURE;
00410   }
00411   
00412   *result = new nsSVGViewBox(viewportWidth, viewportHeight);
00413   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00414 
00415   return NS_OK;  
00416 }