/layout/svg/renderer/src/gdiplus/nsSVGGDIPlusGlyphMetrics.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
00006  * Version 1.1 (the "License"); you may not use this file except in
00007  * compliance with 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 the GNU General Public License Version 2 or later (the "GPL"), or 
00027  * 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 NPL, 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 "nsISVGGlyphMetricsSource.h"
00049 #include "nsPromiseFlatString.h"
00050 #include "nsFont.h"
00051 #include "nsIPresContext.h"
00052 #include "nsDeviceContextWin.h"
00053 #include "nsISVGGDIPlusGlyphMetrics.h"
00054 #include "nsSVGGDIPlusGlyphMetrics.h"
00055 #include "float.h"
00056 #include "nsIDOMSVGMatrix.h"
00057 #include "nsIDOMSVGRect.h"
00058 #include "nsSVGTypeCIDs.h"
00059 #include "nsIComponentManager.h"
00060 #include "nsDataHashtable.h"
00061 
00066 
00067 
00072 class nsWindowsDC {
00073 public:
00074   nsWindowsDC(nsIPresContext* presContext);
00075   ~nsWindowsDC();
00076   operator HDC() { return mHDC; }
00077 private:
00078   bool isWndDC;
00079   HWND mWND;
00080   HDC mHDC;
00081 };
00082 
00086 nsWindowsDC::nsWindowsDC(nsIPresContext* presContext)
00087 {
00088   nsCOMPtr<nsIDeviceContext> devicecontext;
00089   presContext->GetDeviceContext(getter_AddRefs(devicecontext));
00090   NS_ASSERTION(devicecontext, "no device context");
00091 
00092   isWndDC=((nsDeviceContextWin *)(devicecontext.get()))->mDC==nsnull;
00093   if (isWndDC) {
00094     mWND = (HWND)((nsDeviceContextWin *)(devicecontext.get()))->mWidget;
00095     NS_ASSERTION(mWND, "no window and no handle in devicecontext (continuing with screen dc)");
00096     mHDC = ::GetDC(mWND);
00097   }
00098   else
00099     mHDC = ((nsDeviceContextWin *)(devicecontext.get()))->mDC;
00100 }
00101 
00102 nsWindowsDC::~nsWindowsDC()
00103 {
00104   if (isWndDC)
00105     ::ReleaseDC(mWND, mHDC);
00106 }
00107 
00112 
00113 
00116 class nsSVGGDIPlusGlyphMetrics : public nsISVGGDIPlusGlyphMetrics
00117 {
00118 protected:
00119   friend nsresult NS_NewSVGGDIPlusGlyphMetrics(nsISVGRendererGlyphMetrics **result,
00120                                                nsISVGGlyphMetricsSource *src);
00121   friend void NS_InitSVGGDIPlusGlyphMetricsGlobals();
00122   friend void NS_FreeSVGGDIPlusGlyphMetricsGlobals();
00123   nsSVGGDIPlusGlyphMetrics(nsISVGGlyphMetricsSource *src);
00124   ~nsSVGGDIPlusGlyphMetrics();
00125 public:
00126   // nsISupports interface:
00127   NS_DECL_ISUPPORTS
00128 
00129   // nsISVGRendererGlyphMetrics interface:
00130   NS_DECL_NSISVGRENDERERGLYPHMETRICS
00131 
00132   // nsISVGGDIPlusGlyphMetrics interface:
00133   NS_IMETHOD_(const RectF*) GetBoundingRect();
00134   NS_IMETHOD_(void) GetSubBoundingRect(PRUint32 charoffset, PRUint32 count, RectF* retval);
00135   NS_IMETHOD_(const Font*) GetFont();
00136   NS_IMETHOD_(TextRenderingHint) GetTextRenderingHint();
00137   
00138 protected:
00139   void MarkRectForUpdate() { mRectNeedsUpdate = PR_TRUE; }
00140   void ClearFontInfo() { if (mFont) { delete mFont; mFont = nsnull; }}
00141   void InitializeFontInfo();
00142   void GetGlobalTransform(Matrix *matrix);
00143   void PrepareGraphics(Graphics &g);
00144   float GetPixelScale();
00145 
00146 private:  
00147   PRBool mRectNeedsUpdate;
00148   RectF mRect;
00149   Font *mFont;
00150   nsCOMPtr<nsISVGGlyphMetricsSource> mSource;
00151   
00152 public:
00153   static nsDataHashtable<nsStringHashKey,nsDependentString*> sFontAliases;
00154 };
00155 
00158 //----------------------------------------------------------------------
00159 // implementation:
00160 
00161 nsDataHashtable<nsStringHashKey,nsDependentString*>
00162 nsSVGGDIPlusGlyphMetrics::sFontAliases;
00163 
00164 nsSVGGDIPlusGlyphMetrics::nsSVGGDIPlusGlyphMetrics(nsISVGGlyphMetricsSource *src)
00165     : mRectNeedsUpdate(PR_TRUE), mFont(nsnull), mSource(src)
00166 {
00167 }
00168 
00169 nsSVGGDIPlusGlyphMetrics::~nsSVGGDIPlusGlyphMetrics()
00170 {
00171   ClearFontInfo();
00172 }
00173 
00174 nsresult
00175 NS_NewSVGGDIPlusGlyphMetrics(nsISVGRendererGlyphMetrics **result,
00176                              nsISVGGlyphMetricsSource *src)
00177 {
00178   *result = new nsSVGGDIPlusGlyphMetrics(src);
00179   if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00180   
00181   NS_ADDREF(*result);
00182   return NS_OK;
00183 }
00184 
00185 void NS_InitSVGGDIPlusGlyphMetricsGlobals()
00186 {
00187   NS_ASSERTION(!nsSVGGDIPlusGlyphMetrics::sFontAliases.IsInitialized(),
00188                "already initialized");
00189   nsSVGGDIPlusGlyphMetrics::sFontAliases.Init(3);
00190 
00191   static NS_NAMED_LITERAL_STRING(arial, "arial");
00192   nsSVGGDIPlusGlyphMetrics::sFontAliases.Put(NS_LITERAL_STRING("helvetica"),
00193                                              &arial);
00194 
00195   static NS_NAMED_LITERAL_STRING(courier, "courier new");
00196   nsSVGGDIPlusGlyphMetrics::sFontAliases.Put(NS_LITERAL_STRING("courier"),
00197                                              &courier);
00198 
00199   static NS_NAMED_LITERAL_STRING(times, "times new roman");
00200   nsSVGGDIPlusGlyphMetrics::sFontAliases.Put(NS_LITERAL_STRING("times"),
00201                                              &times);
00202 }
00203 
00204 void NS_FreeSVGGDIPlusGlyphMetricsGlobals()
00205 {
00206   nsSVGGDIPlusGlyphMetrics::sFontAliases.Clear();
00207 }
00208 
00209 //----------------------------------------------------------------------
00210 // nsISupports methods:
00211 
00212 NS_IMPL_ADDREF(nsSVGGDIPlusGlyphMetrics)
00213 NS_IMPL_RELEASE(nsSVGGDIPlusGlyphMetrics)
00214 
00215 NS_INTERFACE_MAP_BEGIN(nsSVGGDIPlusGlyphMetrics)
00216   NS_INTERFACE_MAP_ENTRY(nsISVGRendererGlyphMetrics)
00217   NS_INTERFACE_MAP_ENTRY(nsISVGGDIPlusGlyphMetrics)
00218   NS_INTERFACE_MAP_ENTRY(nsISupports)
00219 NS_INTERFACE_MAP_END
00220 
00221 //----------------------------------------------------------------------
00222 // nsISVGRendererGlyphMetrics methods:
00223 
00225 NS_IMETHODIMP
00226 nsSVGGDIPlusGlyphMetrics::GetBaselineOffset(PRUint16 baselineIdentifier, float *_retval)
00227 {
00228   if (!GetFont()) {
00229     NS_ERROR("no font");
00230     return NS_ERROR_FAILURE;
00231   }
00232   NS_ASSERTION(GetFont()->GetUnit()==UnitPixel, "font unit is not in world units");
00233 
00234   switch (baselineIdentifier) {
00235     case BASELINE_TEXT_BEFORE_EDGE:
00236       *_retval = GetBoundingRect()->Y;
00237       break;
00238     case BASELINE_TEXT_AFTER_EDGE:
00239       *_retval = (float)(UINT16)(GetBoundingRect()->Y + GetBoundingRect()->Height + 0.5);
00240       break;
00241     case BASELINE_CENTRAL:
00242     case BASELINE_MIDDLE:
00243       *_retval = (float)(UINT16)(GetBoundingRect()->Y + GetBoundingRect()->Height/2.0 + 0.5);
00244       break;
00245     case BASELINE_ALPHABETIC:
00246     default:
00247     {
00248       FontFamily family;
00249       GetFont()->GetFamily(&family);
00250       INT style = GetFont()->GetStyle();
00251       // alternatively to rounding here, we could set the
00252       // pixeloffsetmode to 'PixelOffsetModeHalf' on painting
00253       *_retval = (float)(UINT16)(GetBoundingRect()->Y
00254                                  + GetFont()->GetSize()
00255                                    *family.GetCellAscent(style)/family.GetEmHeight(style)
00256                                  + 0.5);
00257 #ifdef DEBUG
00258 //       printf("Glyph Metrics:\n"
00259 //              "--------------\n"
00260 //              "ascent:%d\n"
00261 //              "boundingheight:%f\n"
00262 //              "fontheight:%f\n"
00263 //              "fontsize:%f\n"
00264 //              "emheight:%d\n"
00265 //              "linespacing:%d\n"
00266 //              "calculated offset:%f\n"
00267 //              "descent:%d\n"
00268 //              "fh-bh:%f\n"
00269 //              "fontsize/emheight:%f\n"
00270 //              "fontheight/linespacing:%f\n"
00271 //              "boundingheight/(ascent+descent):%f\n"
00272 //              "boundingbox.Y:%f\n"
00273 //              "--------------\n",
00274 //              family.GetCellAscent(style),
00275 //              GetBoundingRect()->Height,
00276 //              GetFontHeight(),
00277 //              GetFont()->GetSize(),
00278 //              family.GetEmHeight(style),
00279 //              family.GetLineSpacing(style),
00280 //              *_retval,
00281 //              family.GetCellDescent(style),
00282 //              GetFontHeight()-GetBoundingRect()->Height,
00283 //              GetFont()->GetSize()/family.GetEmHeight(style),
00284 //              GetFontHeight()/family.GetLineSpacing(style),
00285 //              GetBoundingRect()->Height/(family.GetCellAscent(style)+family.GetCellDescent(style)),
00286 //              GetBoundingRect()->Y);
00287 #endif
00288     }
00289     break;
00290   }
00291   
00292   return NS_OK;
00293 }
00294 
00295 
00297 NS_IMETHODIMP
00298 nsSVGGDIPlusGlyphMetrics::GetAdvance(float *aAdvance)
00299 {
00300   // XXX
00301   *aAdvance = GetBoundingRect()->Width;
00302   return NS_OK;
00303 }
00304 
00306 NS_IMETHODIMP
00307 nsSVGGDIPlusGlyphMetrics::GetBoundingBox(nsIDOMSVGRect * *aBoundingBox)
00308 {
00309   *aBoundingBox = nsnull;
00310 
00311   nsCOMPtr<nsIDOMSVGRect> rect = do_CreateInstance(NS_SVGRECT_CONTRACTID);
00312 
00313   NS_ASSERTION(rect, "could not create rect");
00314   if (!rect) return NS_ERROR_FAILURE;
00315   
00316   rect->SetX(GetBoundingRect()->X);
00317   rect->SetY(GetBoundingRect()->Y);
00318   rect->SetWidth(GetBoundingRect()->Width);
00319   rect->SetHeight(GetBoundingRect()->Height);
00320 
00321   *aBoundingBox = rect;
00322   NS_ADDREF(*aBoundingBox);
00323   
00324   return NS_OK;
00325 }
00326 
00328 NS_IMETHODIMP
00329 nsSVGGDIPlusGlyphMetrics::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
00330 {
00331   *_retval = nsnull;
00332 
00333   RectF bounds;
00334   GetSubBoundingRect(charnum, 1, &bounds);
00335   
00336   nsCOMPtr<nsIDOMSVGRect> rect = do_CreateInstance(NS_SVGRECT_CONTRACTID);
00337 
00338   NS_ASSERTION(rect, "could not create rect");
00339   if (!rect) return NS_ERROR_FAILURE;
00340   
00341   rect->SetX(bounds.X);
00342   rect->SetY(bounds.Y);
00343   rect->SetWidth(bounds.Width);
00344   rect->SetHeight(bounds.Height);
00345 
00346   *_retval = rect;
00347   NS_ADDREF(*_retval);
00348   
00349   return NS_OK;
00350 }
00351 
00353 NS_IMETHODIMP
00354 nsSVGGDIPlusGlyphMetrics::Update(PRUint32 updatemask, PRBool *_retval)
00355 {
00356   *_retval = PR_FALSE;
00357   
00358   if (updatemask & nsISVGGlyphMetricsSource::UPDATEMASK_CHARACTER_DATA) {
00359     MarkRectForUpdate();
00360     *_retval = PR_TRUE;
00361   }
00362 
00363   if (updatemask & nsISVGGlyphMetricsSource::UPDATEMASK_FONT) {
00364     ClearFontInfo();
00365     MarkRectForUpdate();
00366     *_retval = PR_TRUE;
00367   }
00368   
00369   return NS_OK;
00370 }
00371 
00372 //----------------------------------------------------------------------
00373 // nsISVGGDIPlusGlyphMetrics methods:
00374 
00375 NS_IMETHODIMP_(const RectF*)
00376 nsSVGGDIPlusGlyphMetrics::GetBoundingRect()
00377 {
00378   if (!mRectNeedsUpdate) return &mRect;
00379   mRectNeedsUpdate = PR_FALSE;
00380   
00381   nsAutoString text;
00382   mSource->GetCharacterData(text);
00383 
00384   GetSubBoundingRect(0, text.Length(), &mRect);
00385 
00386   return &mRect;
00387 
00388 }
00389 
00390 NS_IMETHODIMP_(void)
00391 nsSVGGDIPlusGlyphMetrics::GetSubBoundingRect(PRUint32 charoffset, PRUint32 count,
00392                                              RectF* retval)
00393 {
00394   nsCOMPtr<nsIPresContext> presContext;
00395   mSource->GetPresContext(getter_AddRefs(presContext));
00396   NS_ASSERTION(presContext, "null prescontext");
00397 
00398   nsWindowsDC devicehandle(presContext);
00399   Graphics graphics(devicehandle);
00400   PrepareGraphics(graphics);
00401   
00402   nsAutoString text;
00403   mSource->GetCharacterData(text);
00404   
00405   StringFormat stringFormat(StringFormat::GenericTypographic());
00406   stringFormat.SetFormatFlags(stringFormat.GetFormatFlags() |
00407                               StringFormatFlagsMeasureTrailingSpaces);
00408   
00409   CharacterRange charRange(charoffset, count);
00410   stringFormat.SetMeasurableCharacterRanges(1, &charRange);
00411   
00412   Region region;
00413   region.MakeEmpty();
00414   
00415   // we measure in the transformed coordinate system...
00416   GraphicsState state = graphics.Save();
00417   
00418   Matrix m;
00419   GetGlobalTransform(&m);
00420   graphics.MultiplyTransform(&m);
00421   
00422   graphics.MeasureCharacterRanges(PromiseFlatString(text).get(), -1, GetFont(),
00423                                   RectF(0.0f, 0.0f, FLT_MAX, FLT_MAX), &stringFormat, 1, &region);
00424   
00425   graphics.Restore(state);
00426   
00427   // ... and obtain the bounds in our local coord system
00428   region.GetBounds(retval, &graphics);  
00429 }
00430 
00431 NS_IMETHODIMP_(const Font*)
00432 nsSVGGDIPlusGlyphMetrics::GetFont()
00433 {
00434   InitializeFontInfo();
00435   return mFont;
00436 }
00437 
00438 NS_IMETHODIMP_(TextRenderingHint)
00439 nsSVGGDIPlusGlyphMetrics::GetTextRenderingHint()
00440 {
00441   // when the text is stroked, we have to turn off hinting so that
00442   // stroke and fill match up exactely:
00443   bool forceUnhinted = PR_FALSE;
00444   {
00445     PRUint16 type;
00446     mSource->GetStrokePaintType(&type);
00447     forceUnhinted = (type != nsISVGGeometrySource::PAINT_TYPE_NONE); 
00448   }
00449 
00450   PRUint16 textRendering;
00451   mSource->GetTextRendering(&textRendering);
00452   switch (textRendering) {
00453     case nsISVGGlyphMetricsSource::TEXT_RENDERING_OPTIMIZESPEED:
00454       return TextRenderingHintSingleBitPerPixel;
00455       break;
00456     case nsISVGGlyphMetricsSource::TEXT_RENDERING_OPTIMIZELEGIBILITY:
00457       return forceUnhinted ?
00458         TextRenderingHintAntiAlias :
00459         TextRenderingHintAntiAliasGridFit;
00460       break;
00461     case nsISVGGlyphMetricsSource::TEXT_RENDERING_GEOMETRICPRECISION:
00462     case nsISVGGlyphMetricsSource::TEXT_RENDERING_AUTO:
00463     default:
00464       return TextRenderingHintAntiAlias;
00465       break;
00466   }
00467 }
00468 
00469 // helper function used in
00470 // nsSVGGDIPlusGlyphMetrics::InitializeFontInfo() to construct a gdi+
00471 // fontfamily object
00472 static PRBool FindFontFamily(const nsString& aFamily, PRBool aGeneric, void *aData)
00473 {
00474   PRBool retval = PR_TRUE;
00475   
00476 #ifdef DEBUG
00477 //   printf("trying to instantiate font %s, generic=%d\n", NS_ConvertUCS2toUTF8(aFamily).get(),
00478 //          aGeneric);
00479 #endif
00480   
00481   FontFamily *family = nsnull;
00482   if (!aGeneric)
00483     family = new FontFamily(aFamily.get());
00484   else {
00485     PRUint8 id;
00486     nsFont::GetGenericID(aFamily, &id);
00487     switch (id) {
00488       case kGenericFont_serif:
00489         family = FontFamily::GenericSerif()->Clone();
00490         break;
00491       case kGenericFont_monospace:
00492         family = FontFamily::GenericMonospace()->Clone();
00493         break;
00494       case kGenericFont_sans_serif:
00495       default:
00496         family = FontFamily::GenericSansSerif()->Clone();
00497         break;
00498     }
00499   }
00500 
00501   if (family->IsAvailable()) {
00502     retval = PR_FALSE; // break
00503     *(FontFamily**)aData = family;
00504   }
00505   else {
00506     delete family;
00507     
00508     //try alias if there is one:
00509     nsDependentString *alias = nsnull;
00510     nsAutoString canonical_name(aFamily);
00511     ToLowerCase(canonical_name);
00512     nsSVGGDIPlusGlyphMetrics::sFontAliases.Get(canonical_name, &alias);
00513     if (alias) {
00514       // XXX this might cause a stack-overflow if there are cyclic
00515       // aliases in sFontAliases
00516       retval = FindFontFamily(nsString(*alias), PR_FALSE, aData);
00517     }
00518   }
00519 
00520   return retval;
00521 }
00522 
00523 void
00524 nsSVGGDIPlusGlyphMetrics::InitializeFontInfo()
00525 {
00526   if (mFont) return; // already initialized
00527 
00528   nsCOMPtr<nsIPresContext> presContext;
00529   mSource->GetPresContext(getter_AddRefs(presContext));
00530   if (!presContext) {
00531     NS_ERROR("null prescontext");
00532     return;
00533   }
00534 
00535   float pxPerTwips;
00536   presContext->GetTwipsToPixels(&pxPerTwips);
00537   pxPerTwips/=GetPixelScale();
00538   
00539   nsFont font;
00540   mSource->GetFont(&font);
00541 
00542   FontFamily *pFamily = nsnull;
00543   font.EnumerateFamilies(FindFontFamily, (void*)&pFamily);
00544   NS_ASSERTION(pFamily, "couldn't create family");
00545 
00546   int style = FontStyleRegular;
00547   if (font.style == NS_FONT_STYLE_ITALIC) style |= FontStyleItalic;
00548   if (font.weight % 100 == 0) { // absolute case
00549     if (font.weight >= 600) style |= FontStyleBold;
00550   }
00551   else if (font.weight % 100 < 50) { // relative 'bolder' case
00552     style |= FontStyleBold;
00553   }
00554 
00555   if (font.decorations & NS_FONT_DECORATION_UNDERLINE) style |= FontStyleUnderline;
00556   if (font.decorations & NS_FONT_DECORATION_LINE_THROUGH) style |= FontStyleStrikeout;
00557   
00558   mFont = new Font(pFamily, font.size*pxPerTwips, style, UnitPixel); 
00559   NS_ASSERTION(mFont->IsAvailable(),"font not available");
00560   delete pFamily;
00561   pFamily = nsnull;
00562   
00563 #ifdef DEBUG
00564 //   {
00565 //     FontFamily fontFamily;
00566 //     mFont->GetFamily(&fontFamily);
00567 //     WCHAR familyName[100];
00568 //     fontFamily.GetFamilyName(familyName);
00569 //     printf("font loaded: "); printf(NS_ConvertUCS2toUTF8(familyName).get()); printf("\n");
00570 //   }
00571 #endif
00572 }
00573 
00574 void
00575 nsSVGGDIPlusGlyphMetrics::GetGlobalTransform(Matrix *matrix)
00576 {
00577   nsCOMPtr<nsIDOMSVGMatrix> ctm;
00578   mSource->GetCTM(getter_AddRefs(ctm));
00579   NS_ASSERTION(ctm, "graphic source didn't specify a ctm");
00580   
00581   float m[6];
00582   float val;
00583   ctm->GetA(&val);
00584   m[0] = val;
00585   
00586   ctm->GetB(&val);
00587   m[1] = val;
00588   
00589   ctm->GetC(&val);  
00590   m[2] = val;  
00591   
00592   ctm->GetD(&val);  
00593   m[3] = val;  
00594   
00595   ctm->GetE(&val);
00596   m[4] = val;
00597   
00598   ctm->GetF(&val);
00599   m[5] = val;
00600 
00601   matrix->SetElements(m[0],m[1],m[2],m[3],m[4],m[5]);
00602 }
00603 
00604 
00605 void
00606 nsSVGGDIPlusGlyphMetrics::PrepareGraphics(Graphics &g)
00607 {
00608   g.SetPageUnit(UnitPixel);
00609   // XXX for some reason the Graphics object that we derive from our
00610   // measurement dcs is never correctly scaled for devices like
00611   // printers. Hence we scale manually here:
00612   g.SetPageScale(GetPixelScale());
00613   g.SetSmoothingMode(SmoothingModeAntiAlias);
00614   //g.SetPixelOffsetMode(PixelOffsetModeHalf);
00615   g.SetTextRenderingHint(GetTextRenderingHint());
00616 }
00617 
00618 float
00619 nsSVGGDIPlusGlyphMetrics::GetPixelScale()
00620 {
00621   nsCOMPtr<nsIPresContext> presContext;
00622   mSource->GetPresContext(getter_AddRefs(presContext));
00623   if (!presContext) {
00624     NS_ERROR("null prescontext");
00625     return 1.0f;
00626   }
00627 
00628   nsCOMPtr<nsIDeviceContext> devicecontext;
00629   presContext->GetDeviceContext(getter_AddRefs(devicecontext));
00630 
00631   float scale;
00632   devicecontext->GetCanonicalPixelScale(scale);
00633   return scale;
00634 }  

Generated on Wed Sep 10 22:25:24 2003 for Mozilla SVG Project Rendering Backend by doxygen1.3