Back to index

lightning-sunbird  0.9+nobinonly
nsRenderingContextQt.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Lars Knoll <knoll@kde.org>
00024  *   Zack Rusin <zack@kde.org>
00025  *   John C. Griggs <jcgriggs@sympatico.ca>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsFontMetricsQt.h"
00042 #include "nsRenderingContextQt.h"
00043 #include "nsRegionQt.h"
00044 #include "nsImageQt.h"
00045 #include "nsGfxCIID.h"
00046 #include "nsICharRepresentable.h"
00047 #include <math.h>
00048 
00049 #include <qwidget.h>
00050 #include <qpaintdevicemetrics.h>
00051 #include <qstring.h>
00052 #include "prmem.h"
00053 
00054 #include "qtlog.h"
00055 
00056 class GraphicsState
00057 {
00058 public:
00059   GraphicsState();
00060   ~GraphicsState();
00061 
00062   nsTransform2D       *mMatrix;
00063   nsRect              mLocalClip;
00064   nsCOMPtr<nsIRegion> mClipRegion;
00065   nscolor             mColor;
00066   nsLineStyle         mLineStyle;
00067   nsIFontMetrics      *mFontMetrics;
00068 };
00069 
00070 GraphicsState::GraphicsState()
00071 {
00072   mMatrix      = nsnull;
00073   mLocalClip.x = mLocalClip.y = mLocalClip.width = mLocalClip.height = 0;
00074   mClipRegion  = nsnull;
00075   mColor       = NS_RGB(0,0,0);
00076   mLineStyle   = nsLineStyle_kSolid;
00077   mFontMetrics = nsnull;
00078 }
00079 
00080 GraphicsState::~GraphicsState()
00081 {
00082 }
00083 
00084 NS_IMPL_THREADSAFE_ISUPPORTS1(nsRenderingContextQt, nsIRenderingContext)
00085 
00086 static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
00087 
00088 nsRenderingContextQt::nsRenderingContextQt()
00089 {
00090   mFontMetrics        = nsnull;
00091   mContext            = nsnull;
00092   mSurface            = nsnull;
00093   mOffscreenSurface   = nsnull;
00094   mCurrentColor       = NS_RGB(255,255,255);  // set it to white
00095   mCurrentLineStyle   = nsLineStyle_kSolid;
00096   mCurrentFont        = nsnull;
00097   mTranMatrix         = nsnull;
00098   mP2T                = 1.0f;
00099   mClipRegion         = nsnull;
00100 
00101   mFunction           = Qt::CopyROP;
00102   mQLineStyle         = Qt::SolidLine;
00103 
00104   PushState();
00105 }
00106 
00107 nsRenderingContextQt::~nsRenderingContextQt()
00108 {
00109   // Destroy the State Machine
00110   PRInt32 cnt = mStateCache.Count();
00111 
00112   while (--cnt >= 0) {
00113       PopState();
00114   }
00115 
00116   delete mTranMatrix;
00117 
00118   NS_IF_RELEASE(mOffscreenSurface);
00119   NS_IF_RELEASE(mFontMetrics);
00120   NS_IF_RELEASE(mContext);
00121 }
00122 
00123 NS_IMETHODIMP nsRenderingContextQt::Init(nsIDeviceContext *aContext,
00124                                          nsIWidget *aWindow)
00125 {
00126   mContext = aContext;
00127   NS_IF_ADDREF(mContext);
00128 
00129   mSurface = new nsDrawingSurfaceQt();
00130 
00131   QPaintDevice *pdevice = (QWidget*)aWindow->GetNativeData(NS_NATIVE_WINDOW);
00132   Q_ASSERT(pdevice);
00133   QPainter *gc = new QPainter();
00134 
00135   mSurface->Init(pdevice,gc);
00136 
00137   mOffscreenSurface = mSurface;
00138 
00139   NS_ADDREF(mSurface);
00140 
00141   return(CommonInit());
00142 }
00143 
00144 NS_IMETHODIMP nsRenderingContextQt::Init(nsIDeviceContext *aContext,
00145                                          nsIDrawingSurface* aSurface)
00146 {
00147   mContext = aContext;
00148   NS_IF_ADDREF(mContext);
00149 
00150   mSurface = (nsDrawingSurfaceQt*)aSurface;
00151   NS_ADDREF(mSurface);
00152   return (CommonInit());
00153 }
00154 
00155 NS_IMETHODIMP nsRenderingContextQt::CommonInit()
00156 {
00157   mP2T = mContext->DevUnitsToAppUnits();
00158   float app2dev;
00159 
00160   app2dev = mContext->AppUnitsToDevUnits();
00161   mTranMatrix->SetToIdentity();
00162   mTranMatrix->AddScale(app2dev,app2dev);
00163 
00164   return NS_OK;
00165 }
00166 
00167 NS_IMETHODIMP nsRenderingContextQt::GetHints(PRUint32 &aResult)
00168 {
00169   PRUint32 result = 0;
00170 
00171   // Most X servers implement 8 bit text rendering alot faster than
00172   // XChar2b rendering. In addition, we can avoid the PRUnichar to
00173   // XChar2b conversion. So we set this bit...
00174   //result |= NS_RENDERING_HINT_FAST_8BIT_TEXT;
00175 
00176   // XXX see if we are rendering to the local display or to a remote
00177   // dispaly and set the NS_RENDERING_HINT_REMOTE_RENDERING accordingly
00178   aResult = result;
00179   return NS_OK;
00180 }
00181 
00182 NS_IMETHODIMP nsRenderingContextQt::LockDrawingSurface(PRInt32 aX,
00183                                                        PRInt32 aY,
00184                                                        PRUint32 aWidth,
00185                                                        PRUint32 aHeight,
00186                                                        void **aBits,
00187                                                        PRInt32 *aStride,
00188                                                        PRInt32 *aWidthBytes,
00189                                                        PRUint32 aFlags)
00190 {
00191   PushState();
00192   return mSurface->Lock(aX,aY,aWidth,aHeight,aBits,aStride,
00193                         aWidthBytes,aFlags);
00194 }
00195 
00196 NS_IMETHODIMP nsRenderingContextQt::UnlockDrawingSurface(void)
00197 {
00198   PopState();
00199   mSurface->Unlock();
00200   return NS_OK;
00201 }
00202 
00203 NS_IMETHODIMP
00204 nsRenderingContextQt::SelectOffScreenDrawingSurface(nsIDrawingSurface* aSurface)
00205 {
00206   if (nsnull == aSurface)
00207     mSurface = mOffscreenSurface;
00208   else
00209     mSurface = (nsDrawingSurfaceQt*)aSurface;
00210   return NS_OK;
00211 }
00212 
00213 NS_IMETHODIMP
00214 nsRenderingContextQt::GetDrawingSurface(nsIDrawingSurface* *aSurface)
00215 {
00216   *aSurface = mSurface;
00217   return NS_OK;
00218 }
00219 
00220 NS_IMETHODIMP nsRenderingContextQt::Reset()
00221 {
00222   return NS_OK;
00223 }
00224 
00225 NS_IMETHODIMP
00226 nsRenderingContextQt::GetDeviceContext(nsIDeviceContext *&aContext)
00227 {
00228   NS_IF_ADDREF(mContext);
00229   aContext = mContext;
00230   return NS_OK;
00231 }
00232 
00233 NS_IMETHODIMP nsRenderingContextQt::PushState(void)
00234 {
00235 #ifdef USE_GS_POOL
00236   nsGraphicsState *state = nsGraphicsStatePool::GetNewGS();
00237 #else
00238   GraphicsState *state = new GraphicsState();
00239 #endif
00240   if (!state)
00241     return NS_ERROR_FAILURE;
00242 
00243   // Push into this state object, add to vector
00244   state->mMatrix = mTranMatrix;
00245 
00246   if (nsnull == mTranMatrix)
00247     mTranMatrix = new nsTransform2D();
00248   else
00249     mTranMatrix = new nsTransform2D(mTranMatrix);
00250 
00251   state->mClipRegion = mClipRegion;
00252 
00253   NS_IF_ADDREF(mFontMetrics);
00254   state->mFontMetrics = mFontMetrics;
00255 
00256   state->mColor = mCurrentColor;
00257   state->mLineStyle = mCurrentLineStyle;
00258 
00259   mStateCache.AppendElement(state);
00260   return NS_OK;
00261 }
00262 
00263 NS_IMETHODIMP nsRenderingContextQt::PopState()
00264 {
00265   GraphicsState *state;
00266   PRUint32 cnt = mStateCache.Count();
00267 
00268   if (cnt > 0) {
00269     state = (GraphicsState*)mStateCache.ElementAt(cnt - 1);
00270     mStateCache.RemoveElementAt(cnt - 1);
00271 
00272     // Assign all local attributes from the state object just popped
00273     if (state->mMatrix) {
00274         delete mTranMatrix;
00275         mTranMatrix = state->mMatrix;
00276     }
00277     mClipRegion.swap(state->mClipRegion);
00278 
00279     if (state->mColor != mCurrentColor)
00280       SetColor(state->mColor);
00281 
00282     if (state->mLineStyle != mCurrentLineStyle)
00283       SetLineStyle(state->mLineStyle);
00284 
00285     if (state->mFontMetrics && (mFontMetrics != state->mFontMetrics))
00286       SetFont(state->mFontMetrics);
00287 
00288     // Delete this graphics state object
00289 #ifdef USE_GS_POOL
00290     nsGraphicsStatePool::ReleaseGS(state);
00291 #else
00292     delete state;
00293 #endif
00294   }
00295 
00296   return NS_OK;
00297 }
00298 
00299 NS_IMETHODIMP nsRenderingContextQt::IsVisibleRect(const nsRect &aRect,
00300                                                   PRBool &aVisible)
00301 {
00302   aVisible = PR_TRUE;
00303   return NS_OK;
00304 }
00305 
00306 NS_IMETHODIMP nsRenderingContextQt::GetClipRect(nsRect &aRect,
00307                                                 PRBool &aClipValid)
00308 {
00309   PRInt32 x,y,w,h;
00310 
00311   if (!mClipRegion)
00312     return NS_ERROR_FAILURE;
00313 
00314   if (!mClipRegion->IsEmpty()) {
00315     mClipRegion->GetBoundingBox(&x,&y,&w,&h);
00316     aRect.SetRect(x,y,w,h);
00317     aClipValid = PR_TRUE;
00318   }
00319   else {
00320     aRect.SetRect(0,0,0,0);
00321     aClipValid = PR_FALSE;
00322   }
00323   return NS_OK;
00324 }
00325 
00329 NS_IMETHODIMP nsRenderingContextQt::CopyClipRegion(nsIRegion &aRegion)
00330 {
00331   if (!mClipRegion)
00332     return NS_ERROR_FAILURE;
00333 
00334   aRegion.SetTo(*mClipRegion);
00335   return NS_OK;
00336 }
00337 
00338 void nsRenderingContextQt::CreateClipRegion()
00339 {
00340   if (mClipRegion)
00341     return;
00342 
00343   mClipRegion = do_CreateInstance(kRegionCID);
00344   if (mClipRegion) {
00345     PRUint32 w,h;
00346 
00347     mSurface->GetDimensions(&w,&h);
00348     mClipRegion->Init();
00349     mClipRegion->SetTo(0,0,w,h);
00350   }
00351 }
00352 
00353 NS_IMETHODIMP nsRenderingContextQt::SetClipRect(const nsRect &aRect,
00354                                                 nsClipCombine aCombine)
00355 {
00356   GraphicsState *state = nsnull;
00357   PRUint32 cnt = mStateCache.Count();
00358 
00359   if (cnt > 0) {
00360     state = (GraphicsState*)mStateCache.ElementAt(cnt - 1);
00361   }
00362   if (state) {
00363     if (state->mClipRegion) {
00364       if (state->mClipRegion == mClipRegion) {
00365         nsCOMPtr<nsIRegion> tmpRgn;
00366 
00367         GetClipRegion(getter_AddRefs(tmpRgn));
00368         mClipRegion = tmpRgn;
00369       }
00370     }
00371   }
00372   CreateClipRegion();
00373 
00374   nsRect trect = aRect;
00375 
00376   mTranMatrix->TransformCoord(&trect.x,&trect.y,
00377                               &trect.width,&trect.height);
00378 
00379   switch (aCombine) {
00380     case nsClipCombine_kIntersect:
00381       mClipRegion->Intersect(trect.x,trect.y,trect.width,trect.height);
00382       break;
00383 
00384     case nsClipCombine_kUnion:
00385       mClipRegion->Union(trect.x,trect.y,trect.width,trect.height);
00386       break;
00387 
00388     case nsClipCombine_kSubtract:
00389       mClipRegion->Subtract(trect.x,trect.y,trect.width,trect.height);
00390       break;
00391 
00392     case nsClipCombine_kReplace:
00393       mClipRegion->SetTo(trect.x,trect.y,trect.width,trect.height);
00394       break;
00395   }
00396 
00397   return NS_OK;
00398 }
00399 
00400 NS_IMETHODIMP nsRenderingContextQt::SetClipRegion(const nsIRegion &aRegion,
00401                                                   nsClipCombine aCombine)
00402 {
00403   PRUint32 cnt = mStateCache.Count();
00404   GraphicsState *state = nsnull;
00405 
00406   if (cnt > 0) {
00407     state = (GraphicsState *)mStateCache.ElementAt(cnt - 1);
00408   }
00409   if (state) {
00410     if (state->mClipRegion) {
00411       if (state->mClipRegion == mClipRegion) {
00412         nsCOMPtr<nsIRegion> tmpRgn;
00413 
00414         GetClipRegion(getter_AddRefs(tmpRgn));
00415         mClipRegion = tmpRgn;
00416       }
00417     }
00418   }
00419   CreateClipRegion();
00420 
00421   switch(aCombine) {
00422     case nsClipCombine_kIntersect:
00423       mClipRegion->Intersect(aRegion);
00424       break;
00425 
00426     case nsClipCombine_kUnion:
00427       mClipRegion->Union(aRegion);
00428       break;
00429 
00430     case nsClipCombine_kSubtract:
00431       mClipRegion->Subtract(aRegion);
00432       break;
00433 
00434     case nsClipCombine_kReplace:
00435       mClipRegion->SetTo(aRegion);
00436       break;
00437   }
00438 
00439   return NS_OK;
00440 }
00441 
00442 NS_IMETHODIMP nsRenderingContextQt::GetClipRegion(nsIRegion **aRegion)
00443 {
00444   nsresult  rv = NS_ERROR_FAILURE;
00445 
00446   if (!aRegion || !mClipRegion)
00447     return NS_ERROR_NULL_POINTER;
00448 
00449   if (*aRegion) {
00450     (*aRegion)->SetTo(*mClipRegion);
00451     rv = NS_OK;
00452   }
00453   else {
00454     nsCOMPtr<nsIRegion> newRegion = do_CreateInstance(kRegionCID,&rv);
00455     if (NS_SUCCEEDED(rv)) {
00456       newRegion->Init();
00457       newRegion->SetTo(*mClipRegion);
00458       NS_ADDREF(*aRegion = newRegion);
00459     }
00460   }
00461   return rv;
00462 }
00463 
00464 NS_IMETHODIMP nsRenderingContextQt::SetColor(nscolor aColor)
00465 {
00466   if (nsnull == mContext)
00467     return NS_ERROR_FAILURE;
00468 
00469   mCurrentColor = aColor;
00470   return NS_OK;
00471 }
00472 
00473 NS_IMETHODIMP nsRenderingContextQt::GetColor(nscolor &aColor) const
00474 {
00475   aColor = mCurrentColor;
00476   return NS_OK;
00477 }
00478 
00479 NS_IMETHODIMP nsRenderingContextQt::SetFont(const nsFont &aFont, nsIAtom* aLangGroup)
00480 {
00481   nsCOMPtr<nsIFontMetrics> newMetrics;
00482   nsresult rv = mContext->GetMetricsFor(aFont, aLangGroup, *getter_AddRefs(newMetrics));
00483 
00484   if (NS_SUCCEEDED(rv)) {
00485     rv = SetFont(newMetrics);
00486   }
00487   return rv;
00488 }
00489 
00490 NS_IMETHODIMP nsRenderingContextQt::SetFont(nsIFontMetrics *aFontMetrics)
00491 {
00492   NS_IF_RELEASE(mFontMetrics);
00493   mFontMetrics = aFontMetrics;
00494   NS_IF_ADDREF(mFontMetrics);
00495 
00496   if (mFontMetrics) {
00497     nsFontHandle fontHandle;
00498 
00499     mFontMetrics->GetFontHandle(fontHandle);
00500     mCurrentFont = (nsFontQt*)fontHandle;
00501   }
00502   return NS_OK;
00503 }
00504 
00505 NS_IMETHODIMP nsRenderingContextQt::SetLineStyle(nsLineStyle aLineStyle)
00506 {
00507   if (aLineStyle != mCurrentLineStyle) {
00508     switch (aLineStyle) {
00509       case nsLineStyle_kSolid:
00510         mQLineStyle = QPen::SolidLine;
00511         break;
00512 
00513       case nsLineStyle_kDashed:
00514         mQLineStyle = QPen::DashLine;
00515         break;
00516 
00517       case nsLineStyle_kDotted:
00518         mQLineStyle = QPen::DotLine;
00519         break;
00520 
00521       default:
00522         break;
00523     }
00524     mCurrentLineStyle = aLineStyle ;
00525   }
00526   return NS_OK;
00527 }
00528 
00529 NS_IMETHODIMP nsRenderingContextQt::GetLineStyle(nsLineStyle &aLineStyle)
00530 {
00531   aLineStyle = mCurrentLineStyle;
00532   return NS_OK;
00533 }
00534 
00535 NS_IMETHODIMP
00536 nsRenderingContextQt::GetFontMetrics(nsIFontMetrics *&aFontMetrics)
00537 {
00538   NS_IF_ADDREF(mFontMetrics);
00539   aFontMetrics = mFontMetrics;
00540   return NS_OK;
00541 }
00542 
00543 // add the passed in translation to the current translation
00544 NS_IMETHODIMP nsRenderingContextQt::Translate(nscoord aX,nscoord aY)
00545 {
00546     mTranMatrix->AddTranslation((float)aX,(float)aY);
00547     return NS_OK;
00548 }
00549 
00550 // add the passed in scale to the current scale
00551 NS_IMETHODIMP nsRenderingContextQt::Scale(float aSx,float aSy)
00552 {
00553     mTranMatrix->AddScale(aSx,aSy);
00554     return NS_OK;
00555 }
00556 
00557 NS_IMETHODIMP
00558 nsRenderingContextQt::GetCurrentTransform(nsTransform2D *&aTransform)
00559 {
00560   aTransform = mTranMatrix;
00561   return NS_OK;
00562 }
00563 
00564 NS_IMETHODIMP
00565 nsRenderingContextQt::CreateDrawingSurface(const nsRect& aBounds,
00566                                            PRUint32 aSurfFlags,
00567                                            nsIDrawingSurface* &aSurface)
00568 {
00569   if (nsnull == mSurface) {
00570     aSurface = nsnull;
00571     return NS_ERROR_FAILURE;
00572   }
00573   if (aBounds.width <= 0 || aBounds.height <= 0)
00574     return NS_ERROR_FAILURE;
00575 
00576   nsDrawingSurfaceQt *surface = new nsDrawingSurfaceQt();
00577 
00578   if (surface) {
00579     //QPainter *gc = mSurface->GetGC();
00580     QPainter *gc = new QPainter();
00581     NS_ADDREF(surface);
00582     //PushState();
00583     surface->Init(gc,aBounds.width,aBounds.height,aSurfFlags);
00584     //PopState();
00585   }
00586   else {
00587     aSurface = nsnull;
00588     return NS_ERROR_FAILURE;
00589   }
00590   aSurface = surface;
00591   return NS_OK;
00592 }
00593 
00594 NS_IMETHODIMP nsRenderingContextQt::DestroyDrawingSurface(nsIDrawingSurface* aDS)
00595 {
00596   nsDrawingSurfaceQt *surface = (nsDrawingSurfaceQt*)aDS;
00597 
00598   if (surface == NULL)
00599     return NS_ERROR_FAILURE;
00600 
00601   NS_IF_RELEASE(surface);
00602   return NS_OK;
00603 }
00604 
00605 void nsRenderingContextQt::UpdateGC()
00606 {
00607   QPainter *pGC;
00608   QColor color(NS_GET_R(mCurrentColor),
00609                NS_GET_G(mCurrentColor),
00610                NS_GET_B(mCurrentColor));
00611   QPen   pen(color,0,mQLineStyle);
00612   QBrush brush(color);
00613 
00614   pGC = mSurface->GetGC();
00615   pGC->setPen(pen);
00616   pGC->setBrush(brush);
00617   pGC->setRasterOp(mFunction);
00618   if (mCurrentFont)
00619     pGC->setFont(mCurrentFont->font);
00620   if (mClipRegion) {
00621      QRegion *rgn = nsnull;
00622 
00623      pGC->setClipping(TRUE);
00624      mClipRegion->GetNativeRegion((void*&)rgn);
00625      pGC->setClipRegion(*rgn);
00626   }
00627   else {
00628     pGC->setClipping(FALSE);
00629   }
00630 }
00631 
00632 NS_IMETHODIMP nsRenderingContextQt::DrawLine(nscoord aX0,nscoord aY0,
00633                                              nscoord aX1,nscoord aY1)
00634 {
00635   nscoord diffX,diffY;
00636 
00637   if (nsnull == mTranMatrix || nsnull == mSurface
00638       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00639     return NS_ERROR_FAILURE;
00640 
00641   mTranMatrix->TransformCoord(&aX0,&aY0);
00642   mTranMatrix->TransformCoord(&aX1,&aY1);
00643 
00644   diffX = aX1 - aX0;
00645   diffY = aY1 - aY0;
00646 
00647   if (0 != diffX) {
00648     diffX = (diffX > 0 ? 1 : -1);
00649   }
00650   if (0 != diffY) {
00651     diffY = (diffY > 0 ? 1 : -1);
00652   }
00653   UpdateGC();
00654   mSurface->GetGC()->drawLine(aX0,aY0,aX1 - diffX,aY1 - diffY);
00655   return NS_OK;
00656 }
00657 
00658 NS_IMETHODIMP nsRenderingContextQt::DrawStdLine(nscoord aX0,nscoord aY0,
00659                                                 nscoord aX1,nscoord aY1)
00660 {
00661   nscoord diffX,diffY;
00662 
00663   if (nsnull == mTranMatrix || nsnull == mSurface
00664       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00665     return NS_ERROR_FAILURE;
00666 
00667   mTranMatrix->TransformCoord(&aX0,&aY0);
00668   mTranMatrix->TransformCoord(&aX1,&aY1);
00669 
00670   diffX = aX1 - aX0;
00671   diffY = aY1 - aY0;
00672 
00673   if (0 != diffX) {
00674     diffX = (diffX > 0 ? 1 : -1);
00675   }
00676   if (0 != diffY) {
00677     diffY = (diffY > 0 ? 1 : -1);
00678   }
00679   UpdateGC();
00680   mSurface->GetGC()->drawLine(aX0,aY0,aX1 - diffX,aY1 - diffY);
00681   return NS_OK;
00682 }
00683 
00684 NS_IMETHODIMP nsRenderingContextQt::DrawPolyline(const nsPoint aPoints[],
00685                                                  PRInt32 aNumPoints)
00686 {
00687   PRInt32 i;
00688 
00689   if (nsnull == mTranMatrix || nsnull == mSurface
00690       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00691     return NS_ERROR_FAILURE;
00692 
00693   QPointArray pts(aNumPoints);
00694   for (i = 0; i < aNumPoints; i++) {
00695     nsPoint p = aPoints[i];
00696 
00697     mTranMatrix->TransformCoord(&p.x,&p.y);
00698     pts.setPoint(i,p.x,p.y);
00699   }
00700   UpdateGC();
00701 
00702   mSurface->GetGC()->drawPolyline(pts);
00703 
00704   return NS_OK;
00705 }
00706 
00707 void nsRenderingContextQt::ConditionRect(nscoord &x,nscoord &y,
00708                                          nscoord &w,nscoord &h)
00709 {
00710   if (y < -32766) {
00711     y = -32766;
00712   }
00713   if (y + h > 32766) {
00714     h  = 32766 - y;
00715   }
00716   if (x < -32766) {
00717     x = -32766;
00718   }
00719   if (x + w > 32766) {
00720     w  = 32766 - x;
00721   }
00722 }
00723 
00724 NS_IMETHODIMP nsRenderingContextQt::DrawRect(const nsRect &aRect)
00725 {
00726   return DrawRect(aRect.x,aRect.y,aRect.width,aRect.height);
00727 }
00728 
00729 NS_IMETHODIMP nsRenderingContextQt::DrawRect(nscoord aX,nscoord aY,
00730                                              nscoord aWidth,nscoord aHeight)
00731 {
00732   if (nsnull == mTranMatrix || nsnull == mSurface
00733       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00734     return NS_ERROR_FAILURE;
00735 
00736   nscoord x,y,w,h;
00737 
00738   x = aX;
00739   y = aY;
00740   w = aWidth;
00741   h = aHeight;
00742   mTranMatrix->TransformCoord(&x,&y,&w,&h);
00743 
00744   // After the transform, if the numbers are huge, chop them, because
00745   // they're going to be converted from 32 bit to 16 bit.
00746   // It's all way off the screen anyway.
00747   ConditionRect(x,y,w,h);
00748 
00749   if (w && h) {
00750     UpdateGC();
00751     mSurface->GetGC()->drawRect(x,y,w,h);
00752   }
00753   return NS_OK;
00754 }
00755 
00756 NS_IMETHODIMP nsRenderingContextQt::FillRect(const nsRect &aRect)
00757 {
00758   return FillRect(aRect.x,aRect.y,aRect.width,aRect.height);
00759 }
00760 
00761 NS_IMETHODIMP nsRenderingContextQt::FillRect(nscoord aX,nscoord aY,
00762                                              nscoord aWidth,nscoord aHeight)
00763 {
00764   if (nsnull == mTranMatrix || nsnull == mSurface
00765       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00766     return NS_ERROR_FAILURE;
00767 
00768   nscoord x,y,w,h;
00769 
00770   x = aX;
00771   y = aY;
00772   w = aWidth;
00773   h = aHeight;
00774   mTranMatrix->TransformCoord(&x,&y,&w,&h);
00775 
00776   // After the transform, if the numbers are huge, chop them, because
00777   // they're going to be converted from 32 bit to 16 bit.
00778   // It's all way off the screen anyway.
00779   ConditionRect(x,y,w,h);
00780   UpdateGC();
00781 
00782   QColor color(NS_GET_R(mCurrentColor),
00783                NS_GET_G(mCurrentColor),
00784                NS_GET_B(mCurrentColor));
00785 
00786   mSurface->GetGC()->fillRect(x,y,w,h,color);
00787   return NS_OK;
00788 }
00789 
00790 NS_IMETHODIMP nsRenderingContextQt::InvertRect(const nsRect &aRect)
00791 {
00792   return InvertRect(aRect.x,aRect.y,aRect.width,aRect.height);
00793 }
00794 
00795 NS_IMETHODIMP nsRenderingContextQt::InvertRect(nscoord aX,nscoord aY,
00796                                                nscoord aWidth,nscoord aHeight)
00797 {
00798   if (nsnull == mTranMatrix || nsnull == mSurface
00799       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00800     return NS_ERROR_FAILURE;
00801 
00802   nscoord x,y,w,h;
00803 
00804   x = aX;
00805   y = aY;
00806   w = aWidth;
00807   h = aHeight;
00808   mTranMatrix->TransformCoord(&x,&y,&w,&h);
00809 
00810   // After the transform, if the numbers are huge, chop them, because
00811   // they're going to be converted from 32 bit to 16 bit.
00812   // It's all way off the screen anyway.
00813   ConditionRect(x,y,w,h);
00814 
00815   // Set XOR drawing mode
00816   mFunction = Qt::XorROP;
00817   UpdateGC();
00818 
00819   // Fill the rect
00820   QColor color(NS_GET_R(mCurrentColor),
00821                NS_GET_G(mCurrentColor),
00822                NS_GET_B(mCurrentColor));
00823 
00824   mSurface->GetGC()->fillRect(x,y,w,h,color);
00825 
00826   // Back to normal copy drawing mode
00827   mFunction = Qt::CopyROP;
00828   return NS_OK;
00829 }
00830 
00831 NS_IMETHODIMP nsRenderingContextQt::DrawPolygon(const nsPoint aPoints[],
00832                                                 PRInt32 aNumPoints)
00833 {
00834   if (nsnull == mTranMatrix || nsnull == mSurface
00835       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00836     return NS_ERROR_FAILURE;
00837 
00838   QPointArray pts(aNumPoints);
00839   for (PRInt32 i = 0; i < aNumPoints; i++) {
00840     nsPoint p = aPoints[i];
00841 
00842     mTranMatrix->TransformCoord(&p.x,&p.y);
00843     pts.setPoint(i,p.x,p.y);
00844   }
00845   UpdateGC();
00846 
00847   mSurface->GetGC()->drawPolyline(pts);
00848 
00849   return NS_OK;
00850 }
00851 
00852 NS_IMETHODIMP nsRenderingContextQt::FillPolygon(const nsPoint aPoints[],
00853                                                 PRInt32 aNumPoints)
00854 {
00855   if (nsnull == mTranMatrix || nsnull == mSurface
00856       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00857     return NS_ERROR_FAILURE;
00858 
00859   QPointArray pts(aNumPoints);
00860   for (PRInt32 i = 0; i < aNumPoints; i++) {
00861     nsPoint p = aPoints[i];
00862 
00863     mTranMatrix->TransformCoord(&p.x,&p.y);
00864     pts.setPoint(i,p.x,p.y);
00865   }
00866   UpdateGC();
00867 
00868   mSurface->GetGC()->drawPolygon(pts);
00869 
00870   return NS_OK;
00871 }
00872 
00873 NS_IMETHODIMP nsRenderingContextQt::DrawEllipse(const nsRect &aRect)
00874 {
00875   return DrawEllipse(aRect.x,aRect.y,aRect.width,aRect.height);
00876 }
00877 
00878 NS_IMETHODIMP nsRenderingContextQt::DrawEllipse(nscoord aX,nscoord aY,
00879                                                 nscoord aWidth,nscoord aHeight)
00880 {
00881   if (nsnull == mTranMatrix || nsnull == mSurface
00882       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00883     return NS_ERROR_FAILURE;
00884 
00885   nscoord x,y,w,h;
00886 
00887   x = aX;
00888   y = aY;
00889   w = aWidth;
00890   h = aHeight;
00891   mTranMatrix->TransformCoord(&x,&y,&w,&h);
00892   UpdateGC();
00893 
00894   mSurface->GetGC()->drawEllipse(x,y,w,h);
00895   return NS_OK;
00896 }
00897 
00898 NS_IMETHODIMP nsRenderingContextQt::FillEllipse(const nsRect &aRect)
00899 {
00900   return FillEllipse(aRect.x,aRect.y,aRect.width,aRect.height);
00901 }
00902 
00903 NS_IMETHODIMP nsRenderingContextQt::FillEllipse(nscoord aX,nscoord aY,
00904                                                 nscoord aWidth,nscoord aHeight)
00905 {
00906   if (nsnull == mTranMatrix || nsnull == mSurface
00907       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00908     return NS_ERROR_FAILURE;
00909 
00910   nscoord x,y,w,h;
00911 
00912   x = aX;
00913   y = aY;
00914   w = aWidth;
00915   h = aHeight;
00916   mTranMatrix->TransformCoord(&x,&y,&w,&h);
00917   UpdateGC();
00918 
00919   mSurface->GetGC()->drawChord(x,y,w,h,0,16 * 360);
00920   return NS_OK;
00921 }
00922 
00923 NS_IMETHODIMP nsRenderingContextQt::DrawArc(const nsRect &aRect,
00924                                             float aStartAngle,float aEndAngle)
00925 {
00926   return DrawArc(aRect.x,aRect.y,aRect.width,aRect.height,
00927                  aStartAngle,aEndAngle);
00928 }
00929 
00930 NS_IMETHODIMP nsRenderingContextQt::DrawArc(nscoord aX,nscoord aY,
00931                                             nscoord aWidth,nscoord aHeight,
00932                                             float aStartAngle,float aEndAngle)
00933 {
00934   if (nsnull == mTranMatrix || nsnull == mSurface
00935       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00936     return NS_ERROR_FAILURE;
00937 
00938   nscoord x,y,w,h;
00939 
00940   x = aX;
00941   y = aY;
00942   w = aWidth;
00943   h = aHeight;
00944   mTranMatrix->TransformCoord(&x,&y,&w,&h);
00945   UpdateGC();
00946 
00947    mSurface->GetGC()->drawArc(x,y,w,h,NSToIntRound(aStartAngle * 16.0f),
00948                               NSToIntRound(aEndAngle * 16.0f));
00949   return NS_OK;
00950 }
00951 
00952 NS_IMETHODIMP nsRenderingContextQt::FillArc(const nsRect &aRect,
00953                                             float aStartAngle,float aEndAngle)
00954 {
00955   return FillArc(aRect.x,aRect.y,aRect.width,aRect.height,
00956                  aStartAngle,aEndAngle);
00957 }
00958 
00959 NS_IMETHODIMP nsRenderingContextQt::FillArc(nscoord aX,nscoord aY,
00960                                             nscoord aWidth,nscoord aHeight,
00961                                             float aStartAngle,float aEndAngle)
00962 {
00963   if (nsnull == mTranMatrix || nsnull == mSurface
00964       || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice())
00965     return NS_ERROR_FAILURE;
00966 
00967   nscoord x,y,w,h;
00968 
00969   x = aX;
00970   y = aY;
00971   w = aWidth;
00972   h = aHeight;
00973   mTranMatrix->TransformCoord(&x,&y,&w,&h);
00974   UpdateGC();
00975 
00976   mSurface->GetGC()->drawPie(x,y,w,h,NSToIntRound(aStartAngle * 16.0f),
00977                              NSToIntRound(aEndAngle * 16.0f));
00978   return NS_OK;
00979 }
00980 
00981 NS_IMETHODIMP nsRenderingContextQt::GetWidth(char aC, nscoord &aWidth)
00982 {
00983     if (!mFontMetrics)
00984         return NS_ERROR_FAILURE;
00985     if (aC == ' ') {
00986         aWidth = mCurrentFont->mSpaceWidth;
00987     } else {
00988         QFontMetrics fm(mCurrentFont->font);
00989         aWidth = NSToCoordRound(fm.width(aC) * mP2T);
00990     }
00991     return NS_OK;
00992 }
00993 
00994 NS_IMETHODIMP nsRenderingContextQt::GetWidth(PRUnichar aC,nscoord &aWidth,
00995                                              PRInt32 *aFontID)
00996 {
00997     if (!mFontMetrics)
00998         return NS_ERROR_FAILURE;
00999     if (aC == ' ') {
01000         aWidth = mCurrentFont->mSpaceWidth;
01001     } else {
01002         QFontMetrics fm(mCurrentFont->font);
01003         aWidth = NSToCoordRound(fm.width(QChar(aC)) * mP2T);
01004     }
01005     return NS_OK;
01006 }
01007 
01008 NS_IMETHODIMP nsRenderingContextQt::GetWidth(const nsString &aString, nscoord &aWidth,PRInt32 *aFontID)
01009 {
01010   return GetWidth(aString.get(), aString.Length(), aWidth, aFontID);
01011 }
01012 
01013 NS_IMETHODIMP nsRenderingContextQt::GetWidth(const char *aString, nscoord &aWidth)
01014 {
01015   return GetWidth(aString,strlen(aString),aWidth);
01016 }
01017 
01018 NS_IMETHODIMP nsRenderingContextQt::GetWidth(const char *aString, PRUint32 aLength,nscoord &aWidth)
01019 {
01020     if (0 == aLength) {
01021     aWidth = 0;
01022     return NS_OK;
01023     }
01024     if (nsnull == aString || nsnull == mCurrentFont)
01025         return NS_ERROR_FAILURE;
01026 
01027     QFontMetrics curFontMetrics(mCurrentFont->font);
01028     int rawWidth = curFontMetrics.width(QString::fromLatin1(aString, aLength));
01029     aWidth = NSToCoordRound(rawWidth * mP2T);
01030     return NS_OK;
01031 }
01032 
01033 NS_IMETHODIMP nsRenderingContextQt::GetWidth(const PRUnichar *aString,
01034                                              PRUint32 aLength,nscoord &aWidth,
01035                                              PRInt32 *aFontID)
01036 {
01037     if (aFontID)
01038         *aFontID = 0;
01039     if (0 == aLength) {
01040         aWidth = 0;
01041         return NS_OK;
01042     }
01043     if (!aString || !mFontMetrics)
01044         return NS_ERROR_FAILURE;
01045 
01046     QConstString cstr((const QChar *)aString, aLength);
01047     QFontMetrics curFontMetrics(mCurrentFont->font);
01048     int rawWidth = curFontMetrics.width(cstr.string());
01049     aWidth = NSToCoordRound(rawWidth * mP2T);
01050     return NS_OK;
01051 }
01052 
01053 NS_IMETHODIMP
01054 nsRenderingContextQt::GetTextDimensions(const char* aString, PRUint32 aLength,
01055                                         nsTextDimensions& aDimensions)
01056 {
01057     aDimensions.Clear();
01058     if (aLength == 0)
01059         return NS_OK;
01060     if (nsnull == aString)
01061         return NS_ERROR_FAILURE;
01062 
01063     QString str = QString::fromLatin1(aString, aLength);
01064     QFontMetrics fm(mCurrentFont->font);
01065     aDimensions.ascent = NSToCoordRound(fm.ascent()*mP2T);
01066     aDimensions.descent = NSToCoordRound(fm.descent()*mP2T);
01067     aDimensions.width = NSToCoordRound(fm.width(str)*mP2T);
01068     return NS_OK;
01069 }
01070 
01071 NS_IMETHODIMP
01072 nsRenderingContextQt::GetTextDimensions(const PRUnichar *aString,
01073                                         PRUint32 aLength,
01074                                         nsTextDimensions &aDimensions,
01075                                         PRInt32 *aFontID)
01076 {
01077     aDimensions.Clear();
01078     if (0 == aLength)
01079         return NS_OK;
01080     if (nsnull == aString)
01081         return NS_ERROR_FAILURE;
01082 
01083     QConstString str((const QChar *)aString, aLength);
01084     QFontMetrics fm(mCurrentFont->font);
01085     aDimensions.ascent = NSToCoordRound(fm.ascent()*mP2T);
01086     aDimensions.descent = NSToCoordRound(fm.descent()*mP2T);
01087     aDimensions.width = NSToCoordRound(fm.width(str.string())*mP2T);
01088 
01089     if (nsnull != aFontID)
01090         *aFontID = 0;
01091 
01092     return NS_OK;
01093 }
01094 
01095 NS_IMETHODIMP
01096 nsRenderingContextQt::GetTextDimensions(const char*       aString,
01097                                         PRInt32           aLength,
01098                                         PRInt32           aAvailWidth,
01099                                         PRInt32*          aBreaks,
01100                                         PRInt32           aNumBreaks,
01101                                         nsTextDimensions& aDimensions,
01102                                         PRInt32&          aNumCharsFit,
01103                                         nsTextDimensions& aLastWordDimensions,
01104                                         PRInt32*          aFontID)
01105 {
01106     NS_NOTREACHED("nsRenderingContextQt::GetTextDimensions not implemented\n");
01107     return NS_ERROR_NOT_IMPLEMENTED;
01108 }
01109 NS_IMETHODIMP
01110 nsRenderingContextQt::GetTextDimensions(const PRUnichar*  aString,
01111                                         PRInt32           aLength,
01112                                         PRInt32           aAvailWidth,
01113                                         PRInt32*          aBreaks,
01114                                         PRInt32           aNumBreaks,
01115                                         nsTextDimensions& aDimensions,
01116                                         PRInt32&          aNumCharsFit,
01117                                         nsTextDimensions& aLastWordDimensions,
01118                                         PRInt32*          aFontID)
01119 {
01120     NS_NOTREACHED("nsRenderingContextQt::GetTextDimensions not implemented\n");
01121     return NS_ERROR_NOT_IMPLEMENTED;
01122 }
01123 
01124 
01125 NS_IMETHODIMP nsRenderingContextQt::DrawString(const char *aString,
01126                                                PRUint32 aLength,
01127                                                nscoord aX, nscoord aY,
01128                                                const nscoord *aSpacing)
01129 {
01130     if (0 == aLength)
01131         return NS_OK;
01132 
01133     if (!mCurrentFont || nsnull == mTranMatrix || nsnull == mSurface
01134         || nsnull == mSurface->GetGC() || nsnull == mSurface->GetPaintDevice()
01135         || nsnull == aString)
01136         return NS_ERROR_FAILURE;
01137 
01138     nscoord x = aX;
01139     nscoord y = aY;
01140 
01141     UpdateGC();
01142 
01143     QString str = QString::fromLatin1(aString, aLength);
01144 
01145     if (nsnull != aSpacing) {
01146         // Render the string, one character at a time...
01147         for (uint i = 0; i < aLength; ++i) {
01148             nscoord xx = x;
01149             nscoord yy = y;
01150             mTranMatrix->TransformCoord(&xx,&yy);
01151             mSurface->GetGC()->drawText(xx, yy, str, i, 1);
01152             x += *aSpacing++;
01153         }
01154     } else {
01155         mTranMatrix->TransformCoord(&x,&y);
01156         mSurface->GetGC()->drawText(x, y, str, aLength, QPainter::LTR);
01157     }
01158     return NS_OK;
01159 }
01160 
01161 NS_IMETHODIMP nsRenderingContextQt::DrawString(const PRUnichar *aString,
01162                                                PRUint32 aLength,
01163                                                nscoord aX,nscoord aY,
01164                                                PRInt32 aFontID,
01165                                                const nscoord *aSpacing)
01166 {
01167     if (!aLength)
01168         return NS_OK;
01169 
01170     if (!mCurrentFont || nsnull == mTranMatrix || nsnull == mSurface
01171         || nsnull == mSurface->GetGC()
01172         || nsnull == mSurface->GetPaintDevice() || nsnull == aString)
01173         return NS_ERROR_FAILURE;
01174 
01175     nscoord x = aX;
01176     nscoord y = aY;
01177 
01178     UpdateGC();
01179     QConstString str((const QChar *)aString, aLength);
01180 
01181     if (nsnull != aSpacing) {
01182         // Render the string, one character at a time...
01183         for (uint i = 0; i < aLength; ++i) {
01184             nscoord xx = x;
01185             nscoord yy = y;
01186             mTranMatrix->TransformCoord(&xx,&yy);
01187             mSurface->GetGC()->drawText(xx, yy, str.string(), i, 1);
01188             x += *aSpacing++;
01189         }
01190     }
01191     else {
01192         mTranMatrix->TransformCoord(&x,&y);
01193         mSurface->GetGC()->drawText(x, y, str.string(), aLength, QPainter::LTR);
01194     }
01195     return NS_OK;
01196 }
01197 
01198 NS_IMETHODIMP nsRenderingContextQt::DrawString(const nsString &aString,
01199                                                nscoord aX,nscoord aY,
01200                                                PRInt32 aFontID,
01201                                                const nscoord *aSpacing)
01202 {
01203   return DrawString(aString.get(), aString.Length(), aX, aY, aFontID, aSpacing);
01204 }
01205 
01206 NS_IMETHODIMP
01207 nsRenderingContextQt::CopyOffScreenBits(nsIDrawingSurface* aSrcSurf,
01208                                         PRInt32 aSrcX,
01209                                         PRInt32 aSrcY,
01210                                         const nsRect &aDestBounds,
01211                                         PRUint32 aCopyFlags)
01212 {
01213     PRInt32            x = aSrcX;
01214     PRInt32            y = aSrcY;
01215     nsRect             drect = aDestBounds;
01216     nsDrawingSurfaceQt *destsurf;
01217 
01218     if (nsnull == aSrcSurf || nsnull == mTranMatrix || nsnull == mSurface
01219         || nsnull == mSurface->GetPaintDevice() || nsnull == mSurface->GetGC())
01220         return NS_ERROR_FAILURE;
01221 
01222     if (aCopyFlags & NS_COPYBITS_TO_BACK_BUFFER) {
01223         NS_ASSERTION(!(nsnull == mSurface), "no back buffer");
01224         destsurf = mSurface;
01225     }
01226     else
01227         destsurf = mOffscreenSurface;
01228 
01229     if (aCopyFlags & NS_COPYBITS_XFORM_SOURCE_VALUES)
01230         mTranMatrix->TransformCoord(&x,&y);
01231 
01232     if (aCopyFlags & NS_COPYBITS_XFORM_DEST_VALUES)
01233         mTranMatrix->TransformCoord(&drect.x,&drect.y,
01234                                     &drect.width,&drect.height);
01235     QPixmap pm = *(QPixmap*)((nsDrawingSurfaceQt*)aSrcSurf)->GetPaintDevice();
01236 
01237     QPainter *p = destsurf->GetGC();
01238     UpdateGC();
01239 
01240 //     qDebug("copy offscreen bits: aSrcX=%d, aSrcY=%d, w/h = %d/%d aCopyFlags=%d",
01241 //            aSrcX, aSrcY, pm.width(), pm.height(), aCopyFlags);
01242 
01243     //XXX flags are unused. that would seem to mean that there is
01244     //inefficiency somewhere... MMP
01245 
01246     p->drawPixmap(drect.x,drect.y, pm, x, y, drect.width, drect.height);
01247     return NS_OK;
01248 }
01249 
01250 NS_IMETHODIMP
01251 nsRenderingContextQt::RetrieveCurrentNativeGraphicData(PRUint32 *ngd)
01252 {
01253   return NS_OK;
01254 }
01255 
01256 #ifdef MOZ_MATHML
01257 NS_IMETHODIMP
01258 nsRenderingContextQt::GetBoundingMetrics(const char *aString,PRUint32 aLength,
01259                                          nsBoundingMetrics &aBoundingMetrics)
01260 {
01261     aBoundingMetrics.Clear();
01262     if (0 >= aLength || !aString || !mCurrentFont)
01263         return(NS_ERROR_FAILURE);
01264 
01265     QString str = QString::fromLatin1(aString, aLength);
01266     QFontMetrics fm(mCurrentFont->font);
01267     QRect br = fm.boundingRect(str);
01268     aBoundingMetrics.width = NSToCoordRound(br.width() * mP2T);
01269     aBoundingMetrics.ascent = NSToCoordRound(-br.y() * mP2T);
01270     aBoundingMetrics.descent = NSToCoordRound(br.bottom() * mP2T);
01271     aBoundingMetrics.leftBearing = NSToCoordRound(br.x() * mP2T);
01272     aBoundingMetrics.rightBearing = NSToCoordRound(fm.rightBearing(str.at(aLength - 1)) * mP2T);
01273     return NS_OK;
01274 }
01275 
01276 NS_IMETHODIMP
01277 nsRenderingContextQt::GetBoundingMetrics(const PRUnichar *aString,
01278                                          PRUint32 aLength,
01279                                          nsBoundingMetrics &aBoundingMetrics,
01280                                          PRInt32 *aFontID)
01281 {
01282     aBoundingMetrics.Clear();
01283     if (0 >= aLength || !aString || !mCurrentFont)
01284         return(NS_ERROR_FAILURE);
01285 
01286     QConstString str((const QChar *)aString, aLength);
01287     QFontMetrics fm(mCurrentFont->font);
01288     QRect br = fm.boundingRect(str.string());
01289     aBoundingMetrics.width = NSToCoordRound(br.width() * mP2T);
01290     aBoundingMetrics.ascent = NSToCoordRound(-br.y() * mP2T);
01291     aBoundingMetrics.descent = NSToCoordRound(br.bottom() * mP2T);
01292     aBoundingMetrics.leftBearing = NSToCoordRound(br.x() * mP2T);
01293     aBoundingMetrics.rightBearing = NSToCoordRound(fm.rightBearing(str.string().at(aLength - 1)) * mP2T);
01294     return NS_OK;
01295 }
01296 #endif /* MOZ_MATHML */