Back to index

lightning-sunbird  0.9+nobinonly
nsSVGLibartRegion.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) 2002
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 "nsCOMPtr.h"
00040 #include "nsISVGLibartRegion.h"
00041 #include "nsSVGLibartRegion.h"
00042 #include "nsISVGRectangleSink.h"
00043 #include <math.h>
00044 
00049 
00050 
00053 class nsSVGLibartRegion : public nsISVGLibartRegion // : nsISVGRendererRegion
00054 {
00055 protected:
00056   friend nsresult NS_NewSVGLibartRectRegion(nsISVGRendererRegion** result,
00057                                             float x, float y,
00058                                             float width, float height);
00059   friend nsresult NS_NewSVGLibartSVPRegion(nsISVGRendererRegion** result,
00060                                            ArtSVP *path);
00061   nsSVGLibartRegion(ArtIRect *rect);
00062   nsSVGLibartRegion(ArtSVP* path);
00063   nsSVGLibartRegion(ArtUta* uta); // takes ownership
00064   
00065   ~nsSVGLibartRegion();
00066 
00067 public:
00068   // nsISupports interface:
00069   NS_DECL_ISUPPORTS
00070 
00071   // nsISVGLibartRegion interface:
00072   NS_IMETHOD_(ArtUta*) GetUta();
00073   
00074   // nsISVGRendererRegion interface:
00075   NS_DECL_NSISVGRENDERERREGION
00076   
00077 private:
00078   ArtUta* mUta;
00079 };
00080 
00083 //----------------------------------------------------------------------
00084 // implementation:
00085 
00086 nsSVGLibartRegion::nsSVGLibartRegion(ArtIRect *rect)
00087 {
00088   mUta = art_uta_from_irect(rect);
00089 }
00090 
00091 nsSVGLibartRegion::nsSVGLibartRegion(ArtSVP* path)
00092 {
00093   mUta = path ? art_uta_from_svp(path) : nsnull;  
00094 }
00095 
00096 nsSVGLibartRegion::nsSVGLibartRegion(ArtUta* uta)
00097     : mUta(uta)
00098 {
00099 }
00100 
00101 nsSVGLibartRegion::~nsSVGLibartRegion()
00102 {
00103   if (mUta)
00104     art_uta_free(mUta);
00105 }
00106 
00107 nsresult
00108 NS_NewSVGLibartRectRegion(nsISVGRendererRegion** result,
00109                           float x, float y,
00110                           float width, float height)
00111 {
00112   if (width<=0.0f || height<=0.0f) {
00113     *result = new nsSVGLibartRegion((ArtUta*)nsnull);
00114   }
00115   else {
00116     ArtIRect irect;
00117     irect.x0 = (int)x; // floor(x)
00118     irect.y0 = (int)y; // floor(y)
00119     irect.x1 = (int)ceil(x+width);
00120     irect.y1 = (int)ceil(y+height);
00121     NS_ASSERTION(irect.x0!=irect.x1 && irect.y0!=irect.y1, "empty region");
00122     *result = new nsSVGLibartRegion(&irect);
00123   }
00124   
00125   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00126   
00127   NS_ADDREF(*result);
00128   return NS_OK;
00129 }
00130 
00131 nsresult
00132 NS_NewSVGLibartSVPRegion(nsISVGRendererRegion** result,
00133                          ArtSVP* path)
00134 {
00135   *result = new nsSVGLibartRegion(path);
00136   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00137 
00138   NS_ADDREF(*result);
00139   return NS_OK;  
00140 }
00141 
00142 
00143 //----------------------------------------------------------------------
00144 // nsISupports methods:
00145 
00146 NS_IMPL_ADDREF(nsSVGLibartRegion)
00147 NS_IMPL_RELEASE(nsSVGLibartRegion)
00148 
00149 NS_INTERFACE_MAP_BEGIN(nsSVGLibartRegion)
00150   NS_INTERFACE_MAP_ENTRY(nsISVGLibartRegion)
00151   NS_INTERFACE_MAP_ENTRY(nsISVGRendererRegion)
00152   NS_INTERFACE_MAP_ENTRY(nsISupports)
00153 NS_INTERFACE_MAP_END
00154 
00155 //----------------------------------------------------------------------
00156 // nsISVGLibartRegion interface:
00157 
00158 NS_IMETHODIMP_(ArtUta*)
00159 nsSVGLibartRegion::GetUta()
00160 {
00161   return mUta;
00162 }
00163 
00164 //----------------------------------------------------------------------
00165 // nsISVGRendererRegion methods:
00166 
00168 NS_IMETHODIMP
00169 nsSVGLibartRegion::Combine(nsISVGRendererRegion *other,
00170                            nsISVGRendererRegion **_retval)
00171 {
00172   *_retval = nsnull;
00173 
00174   nsCOMPtr<nsISVGLibartRegion> other2 = do_QueryInterface(other);
00175   if (!other2) {
00176     NS_WARNING("Union operation on incompatible regions");
00177     return NS_ERROR_FAILURE;
00178   }
00179 
00180   nsISVGLibartRegion *regions[2];
00181   int count = 0;
00182 
00183   if (mUta)
00184     regions[count++]=this;
00185 
00186   if (other2->GetUta())
00187     regions[count++]=other2;
00188 
00189   switch (count) {
00190     case 0:
00191       break;
00192     case 1:
00193       *_retval = regions[0];
00194       NS_ADDREF(*_retval);
00195       break;
00196     case 2:
00197       *_retval = new nsSVGLibartRegion(art_uta_union(regions[0]->GetUta(),
00198                                                      regions[1]->GetUta()));
00199       NS_IF_ADDREF(*_retval);
00200       break;
00201   }
00202   
00203   return NS_OK;
00204 }
00205 
00207 NS_IMETHODIMP
00208 nsSVGLibartRegion::GetRectangleScans(nsISVGRectangleSink *sink)
00209 {
00210   if (!mUta) return NS_OK;
00211   
00212   int nRects=0;
00213   ArtIRect* rectList = art_rect_list_from_uta(mUta, 200, 200, &nRects);
00214     for (int i=0; i<nRects; ++i) {
00215       int x,y,w,h;
00216       x = PR_MIN(rectList[i].x0,rectList[i].x1)-2;
00217       y = PR_MIN(rectList[i].y0,rectList[i].y1)-2;
00218       w = PR_ABS(rectList[i].x0-rectList[i].x1)+4;
00219       h = PR_ABS(rectList[i].y0-rectList[i].y1)+4;
00220 
00221       sink->SinkRectangle(x,y,w,h);
00222     }
00223         
00224     art_free(rectList);
00225   
00226   return NS_OK;
00227 }