Back to index

lightning-sunbird  0.9+nobinonly
nsSVGRendererGDIPlusShim.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 "nsISVGRenderer.h"
00049 #include "nsSVGRendererGDIPlus.h"
00050 
00051 extern "C" {
00052   static Status (WINAPI *pGdiplusStartup)(OUT ULONG_PTR *, const GdiplusStartupInput *, OUT GdiplusStartupOutput *) = nsnull;
00053   static VOID (WINAPI *pGdiplusShutdown)(ULONG_PTR) = nsnull;
00054 }
00055 static nsSVGRendererGDIPlusFunctions *rendererFunctions = nsnull;
00056 
00061 
00062 
00065 class nsSVGRendererGDIPlus : public nsISVGRenderer
00066 {
00067 protected:
00068   friend nsresult NS_NewSVGRendererGDIPlus(nsISVGRenderer** aResult);
00069   friend void NS_InitSVGRendererGDIPlusGlobals();
00070   friend void NS_FreeSVGRendererGDIPlusGlobals();
00071   
00072 public:
00073   nsSVGRendererGDIPlus();
00074 
00075   // nsISupports interface
00076   NS_DECL_ISUPPORTS
00077 
00078   // nsISVGRenderer interface
00079   NS_DECL_NSISVGRENDERER
00080 private:
00081   static PRBool sGdiplusStarted;
00082   static ULONG_PTR sGdiplusToken;
00083   static GdiplusStartupOutput sGdiplusStartupOutput;
00084 };
00085 
00088 //----------------------------------------------------------------------
00089 // implementation:
00090 
00091 PRBool nsSVGRendererGDIPlus::sGdiplusStarted = PR_FALSE;
00092 ULONG_PTR nsSVGRendererGDIPlus::sGdiplusToken;
00093 GdiplusStartupOutput nsSVGRendererGDIPlus::sGdiplusStartupOutput;
00094 
00095 
00096 nsSVGRendererGDIPlus::nsSVGRendererGDIPlus()
00097 {
00098   if (!sGdiplusStarted) {
00099     GdiplusStartupInput gdiplusStartupInput;
00100     pGdiplusStartup(&sGdiplusToken, &gdiplusStartupInput,&sGdiplusStartupOutput);
00101     sGdiplusStarted = PR_TRUE;
00102   }
00103 }
00104 
00105 static PRBool
00106 TryLoadLibraries()
00107 {
00108   static PRBool attemptedLoad = PR_FALSE, successfulLoad = PR_FALSE;
00109 
00110   if (attemptedLoad)
00111     return successfulLoad;
00112   else
00113     attemptedLoad = PR_TRUE;
00114 
00115   HMODULE gdiplus, gkgdiplus;
00116 
00117   if ((gdiplus = LoadLibrary("gdiplus.dll")) == NULL)
00118     return PR_FALSE;
00119   pGdiplusStartup =
00120     (Status (WINAPI *)(OUT ULONG_PTR *, const GdiplusStartupInput *, OUT GdiplusStartupOutput *))GetProcAddress(gdiplus, "GdiplusStartup");
00121   pGdiplusShutdown =
00122      (VOID (WINAPI *)(ULONG_PTR))GetProcAddress(gdiplus, "GdiplusShutdown");
00123 
00124   if (!pGdiplusStartup || !pGdiplusShutdown)
00125     return PR_FALSE;
00126   
00127   if ((gkgdiplus = LoadLibrary("gksvggdiplus.dll")) == NULL)
00128     return PR_FALSE;
00129 
00130   nsSVGRendererGDIPlusFunctions *(*getFuncs)() = nsnull;
00131 
00132   getFuncs = (nsSVGRendererGDIPlusFunctions *(*)())GetProcAddress(gkgdiplus, "NS_GetSVGRendererGDIPlusFunctions");
00133 
00134   if (!getFuncs)
00135     return PR_FALSE;
00136   rendererFunctions = getFuncs();
00137   
00138   successfulLoad = PR_TRUE;
00139   return PR_TRUE;
00140 }  
00141 
00142 nsresult
00143 NS_NewSVGRendererGDIPlus(nsISVGRenderer** aResult)
00144 {
00145   NS_PRECONDITION(aResult != nsnull, "null ptr");
00146   if (! aResult)
00147     return NS_ERROR_NULL_POINTER;
00148 
00149   if (!TryLoadLibraries())
00150     return NS_ERROR_FAILURE;
00151 
00152   nsSVGRendererGDIPlus* result = new nsSVGRendererGDIPlus();
00153   if (! result)
00154     return NS_ERROR_OUT_OF_MEMORY;
00155 
00156   NS_ADDREF(result);
00157   *aResult = result;
00158   return NS_OK;
00159 }
00160 
00161 void
00162 NS_InitSVGRendererGDIPlusGlobals()
00163 {
00164   if (!TryLoadLibraries())
00165     return;
00166 
00167   rendererFunctions->NS_InitSVGGDIPlusGlyphMetricsGlobals();
00168   
00169   // initialize gdi+ lazily in nsSVGRendererGDIPlus CTOR
00170 }
00171 
00172 void
00173 NS_FreeSVGRendererGDIPlusGlobals()
00174 {
00175   if (!TryLoadLibraries())
00176     return;
00177 
00178   rendererFunctions->NS_FreeSVGGDIPlusGlyphMetricsGlobals();
00179   
00180   if (nsSVGRendererGDIPlus::sGdiplusStarted) {
00181     pGdiplusShutdown(nsSVGRendererGDIPlus::sGdiplusToken);
00182   }
00183 }
00184 
00185 //----------------------------------------------------------------------
00186 // nsISupports methods
00187 
00188 NS_IMPL_ISUPPORTS1(nsSVGRendererGDIPlus, nsISVGRenderer);
00189 
00190 //----------------------------------------------------------------------
00191 // nsISVGRenderer methods
00192 
00194 NS_IMETHODIMP
00195 nsSVGRendererGDIPlus::CreatePathGeometry(nsISVGPathGeometrySource *src,
00196                                          nsISVGRendererPathGeometry **_retval)
00197 {
00198   return rendererFunctions->NS_NewSVGGDIPlusPathGeometry(_retval, src);
00199 }
00200 
00202 NS_IMETHODIMP
00203 nsSVGRendererGDIPlus::CreateGlyphMetrics(nsISVGGlyphMetricsSource *src,
00204                                          nsISVGRendererGlyphMetrics **_retval)
00205 {
00206   return rendererFunctions->NS_NewSVGGDIPlusGlyphMetrics(_retval, src);
00207 }
00208 
00210 NS_IMETHODIMP
00211 nsSVGRendererGDIPlus::CreateGlyphGeometry(nsISVGGlyphGeometrySource *src,
00212                                           nsISVGRendererGlyphGeometry **_retval)
00213 {
00214   return rendererFunctions->NS_NewSVGGDIPlusGlyphGeometry(_retval, src);
00215 }
00216 
00219 NS_IMETHODIMP
00220 nsSVGRendererGDIPlus::CreateCanvas(nsIRenderingContext *ctx,
00221                                    nsPresContext *presContext,
00222                                    const nsRect & dirtyRect,
00223                                    nsISVGRendererCanvas **_retval)
00224 {
00225   return rendererFunctions->NS_NewSVGGDIPlusCanvas(_retval, ctx, presContext, dirtyRect);
00226 }
00227 
00229 NS_IMETHODIMP
00230 nsSVGRendererGDIPlus::CreateRectRegion(float x, float y, float width, float height,
00231                                        nsISVGRendererRegion **_retval)
00232 {
00233   return rendererFunctions->NS_NewSVGGDIPlusRectRegion(_retval, x, y, width, height);
00234 }
00235 
00237 NS_IMETHODIMP
00238 nsSVGRendererGDIPlus::CreateSurface(PRUint32 width, PRUint32 height,
00239                                     nsISVGRendererSurface **_retval)
00240 {
00241   return rendererFunctions->NS_NewSVGGDIPlusSurface(_retval, width, height);
00242 }