Back to index

lightning-sunbird  0.9+nobinonly
nsSVGGDIPlusRegion.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 <windows.h>
00040 
00041 // unknwn.h is needed to build with WIN32_LEAN_AND_MEAN
00042 #include <unknwn.h>
00043 
00044 #include <Gdiplus.h>
00045 using namespace Gdiplus;
00046 
00047 #include "nsCOMPtr.h"
00048 #include "nsISVGGDIPlusRegion.h"
00049 #include "nsSVGGDIPlusRegion.h"
00050 #include "nsISVGRectangleSink.h"
00051 #include "nsPresContext.h"
00052 #include "nsDeviceContextWin.h"
00053 
00058 
00059 
00062 class nsSVGGDIPlusRegion : public nsISVGGDIPlusRegion
00063 {
00064 protected:
00065   friend nsresult NS_NewSVGGDIPlusRectRegion(nsISVGRendererRegion** result,
00066                                              float x, float y,
00067                                              float width, float height);
00068   friend nsresult NS_NewSVGGDIPlusPathRegion(nsISVGRendererRegion** result,
00069                                              const GraphicsPath* path);
00070   friend nsresult NS_NewSVGGDIPlusClonedRegion(nsISVGRendererRegion** result,
00071                                                const Region* region,
00072                                                nsPresContext *presContext);
00073   nsSVGGDIPlusRegion(RectF& rect);
00074   nsSVGGDIPlusRegion(const GraphicsPath* path);
00075   nsSVGGDIPlusRegion(const nsSVGGDIPlusRegion& other);
00076   nsSVGGDIPlusRegion(const Region* other
00077 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00078                      , const Graphics* graphics
00079 #endif
00080                      );
00081   
00082   ~nsSVGGDIPlusRegion();
00083 
00084 public:
00085   // nsISupports interface:
00086   NS_DECL_ISUPPORTS
00087 
00088   // nsISVGGDIPlusRegion interface:
00089 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00090   NS_IMETHOD_(const RectF*) GetRect()const;
00091 #else
00092   NS_IMETHOD_(const Region*) GetRegion()const;
00093 #endif
00094   
00095   // nsISVGRendererRegion interface:
00096   NS_DECL_NSISVGRENDERERREGION
00097   
00098 private:
00099 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00100   RectF mRect;
00101 #else
00102   Region mRegion;
00103 #endif
00104 };
00105 
00108 //----------------------------------------------------------------------
00109 // implementation:
00110 
00111 nsSVGGDIPlusRegion::nsSVGGDIPlusRegion(RectF& rect)
00112 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00113     : mRect(rect.X, rect.Y, rect.Width, rect.Height)
00114 #else
00115     : mRegion(rect)
00116 #endif
00117 {
00118 }
00119 
00120 nsSVGGDIPlusRegion::nsSVGGDIPlusRegion(const GraphicsPath* path)
00121 #ifndef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00122     : mRegion(path)
00123 #endif
00124 {
00125 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00126   path->GetBounds(&mRect);
00127 #endif
00128 }
00129 
00130 nsSVGGDIPlusRegion::nsSVGGDIPlusRegion(const nsSVGGDIPlusRegion& other)
00131 {
00132   
00133 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00134   mRect.X = other.GetRect()->X;
00135   mRect.Y = other.GetRect()->Y;
00136   mRect.Width = other.GetRect()->Width;
00137   mRect.Height = other.GetRect()->Height;
00138 #else
00139   mRegion.MakeEmpty();
00140   mRegion.Union(other.GetRegion());
00141 #endif
00142 }
00143 
00144 nsSVGGDIPlusRegion::nsSVGGDIPlusRegion(const Region* other
00145 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00146                                        , const Graphics* graphics
00147 #endif
00148                                       )
00149 {
00150   
00151 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00152   other->GetBounds(&mRect, graphics);
00153 #else
00154   mRegion.MakeEmpty();
00155   mRegion.Union(other);
00156 #endif
00157 }
00158 
00159 
00160 nsSVGGDIPlusRegion::~nsSVGGDIPlusRegion()
00161 {
00162 }
00163 
00164 nsresult
00165 NS_NewSVGGDIPlusRectRegion(nsISVGRendererRegion** result,
00166                            float x, float y,
00167                            float width, float height)
00168 {
00169   *result = new nsSVGGDIPlusRegion(RectF(x, y, width, height));
00170   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00171 
00172   NS_ADDREF(*result);
00173   return NS_OK;
00174 }
00175 
00176 nsresult
00177 NS_NewSVGGDIPlusPathRegion(nsISVGRendererRegion** result,
00178                            const GraphicsPath* path)
00179 {
00180   *result = new nsSVGGDIPlusRegion(path);
00181   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00182 
00183   NS_ADDREF(*result);
00184   return NS_OK;  
00185 }
00186 
00187 nsresult NS_NewSVGGDIPlusClonedRegion(nsISVGRendererRegion** result,
00188                                       const Region* region,
00189                                       nsPresContext *presContext)
00190 {
00191 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00192   HWND win;
00193   HDC devicehandle;
00194   {
00195     nsIDeviceContext* devicecontext = presContext->DeviceContext();
00196     // this better be what we think it is:
00197     win = (HWND)((nsDeviceContextWin *)devicecontext)->mWidget;
00198     devicehandle = ::GetDC(win);
00199   }
00200 
00201   {
00202     // wrap this in a block so that the Graphics-object goes out of
00203     // scope before we release the HDC.
00204     
00205     Graphics graphics(devicehandle);
00206     
00207     *result = new nsSVGGDIPlusRegion(region, &graphics);  
00208   }
00209   
00210   ::ReleaseDC(win, devicehandle);
00211 #else
00212     *result = new nsSVGGDIPlusRegion(region);
00213 #endif
00214   
00215   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00216 
00217   NS_ADDREF(*result);
00218   return NS_OK;  
00219 }
00220 
00221 //----------------------------------------------------------------------
00222 // nsISupports methods:
00223 
00224 NS_IMPL_ADDREF(nsSVGGDIPlusRegion)
00225 NS_IMPL_RELEASE(nsSVGGDIPlusRegion)
00226 
00227 NS_INTERFACE_MAP_BEGIN(nsSVGGDIPlusRegion)
00228   NS_INTERFACE_MAP_ENTRY(nsISVGGDIPlusRegion)
00229   NS_INTERFACE_MAP_ENTRY(nsISVGRendererRegion)
00230   NS_INTERFACE_MAP_ENTRY(nsISupports)
00231 NS_INTERFACE_MAP_END
00232 
00233 //----------------------------------------------------------------------
00234 // nsISVGGDIPlusRegion methods:
00235 
00236 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00237 NS_IMETHODIMP_(const RectF*)
00238 nsSVGGDIPlusRegion::GetRect()const
00239 {
00240   return &mRect;
00241 }
00242 #else
00243 NS_IMETHODIMP_(const Region*)
00244 nsSVGGDIPlusRegion::GetRegion()const
00245 {
00246   return &mRegion;
00247 }
00248 #endif
00249 
00250 //----------------------------------------------------------------------
00251 // nsISVGRendererRegion methods:
00252 
00254 NS_IMETHODIMP
00255 nsSVGGDIPlusRegion::Combine(nsISVGRendererRegion *other, nsISVGRendererRegion **_retval)
00256 {
00257   *_retval = nsnull;
00258 
00259   nsSVGGDIPlusRegion *union_region = new nsSVGGDIPlusRegion(*this);
00260   NS_ADDREF(union_region);
00261   *_retval = union_region;
00262 
00263   if (!other) return NS_OK;
00264   
00265   nsCOMPtr<nsISVGGDIPlusRegion> other2 = do_QueryInterface(other);
00266   if (!other2) {
00267     NS_WARNING("Union operation on incompatible regions");
00268     return NS_OK;
00269   }
00270   
00271 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00272   RectF::Union(union_region->mRect, mRect, *(other2->GetRect()));
00273 #else
00274   union_region->mRegion.Union(other2->GetRegion());
00275 #endif
00276   
00277   return NS_OK;
00278 }
00279 
00281 NS_IMETHODIMP
00282 nsSVGGDIPlusRegion::GetRectangleScans(nsISVGRectangleSink *sink)
00283 {
00284 #ifdef NS_SVG_GDIPLUS_RENDERER_USE_RECT_REGIONS
00285   sink->SinkRectangle(mRect.X-1, mRect.Y-1, mRect.Width+2, mRect.Height+2);
00286 #else
00287   Matrix matrix;
00288   INT count = mRegion.GetRegionScansCount(&matrix);
00289   if (count == 0) return NS_OK;
00290   
00291   RectF* rects = (RectF*)malloc(count*sizeof(RectF));
00292   mRegion.GetRegionScans(&matrix, rects, &count);
00293 
00294   for (INT i=0; i<count; ++i) 
00295     sink->SinkRectangle(rects[i].X-1, rects[i].Y-1, rects[i].Width+2, rects[i].Height+2);
00296 
00297   free(rects);
00298 #endif
00299   
00300   return NS_OK;
00301 }