/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #ifndef nsRenderingContextPh_h___ #define nsRenderingContextPh_h___ #include "nsRenderingContextImpl.h" #include "nsFont.h" #include "nsIFontMetrics.h" #include "nsPoint.h" #include "nsString.h" #include "nsCRT.h" #include "nsTransform2D.h" #include "nsIViewManager.h" #include "nsIWidget.h" #include "nsRect.h" #include "nsImagePh.h" #include "nsIDeviceContext.h" #include "nsVoidArray.h" #include "nsGfxCIID.h" #include "nsDrawingSurfacePh.h" #include "nsRegionPh.h" // Macro for converting from nscolor to PtColor_t // Photon RGB values are stored as 00 RR GG BB // nscolor RGB values are 00 BB GG RR #define NS_TO_PH_RGB(ns) (ns & 0xff) << 16 | (ns & 0xff00) | ((ns >> 16) & 0xff) #define PH_TO_NS_RGB(ns) (ns & 0xff) << 16 | (ns & 0xff00) | ((ns >> 16) & 0xff) class nsRenderingContextPh : public nsRenderingContextImpl { public: nsRenderingContextPh(); virtual ~nsRenderingContextPh(); NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW NS_DECL_ISUPPORTS NS_IMETHOD Init(nsIDeviceContext* aContext, nsIWidget *aWindow); inline NS_IMETHODIMP Init(nsIDeviceContext* aContext, nsIDrawingSurface* aSurface) { mContext = aContext; NS_IF_ADDREF(mContext); mSurface = (nsDrawingSurfacePh *) aSurface; NS_ADDREF(mSurface); mOffscreenSurface = mSurface; mGC = mSurface->GetGC(); mOwner = PR_FALSE; mSurfaceDC = ((nsDrawingSurfacePh*)mSurface)->GetDC(); return CommonInit(); } inline NS_IMETHODIMP Reset(void) { return NS_OK; } inline NS_IMETHODIMP GetDeviceContext(nsIDeviceContext *&aContext) { NS_IF_ADDREF( mContext ); aContext = mContext; return NS_OK; } inline NS_IMETHODIMP LockDrawingSurface(PRInt32 aX, PRInt32 aY, PRUint32 aWidth, PRUint32 aHeight, void **aBits, PRInt32 *aStride, PRInt32 *aWidthBytes, PRUint32 aFlags) { PushState(); return mSurface->Lock( aX, aY, aWidth, aHeight, aBits, aStride, aWidthBytes, aFlags ); } inline NS_IMETHODIMP UnlockDrawingSurface(void) { PopState(); mSurface->Unlock(); return NS_OK; } inline NS_IMETHODIMP SelectOffScreenDrawingSurface(nsIDrawingSurface* aSurface) { mSurface = ( nsnull==aSurface ) ? mOffscreenSurface : (nsDrawingSurfacePh *) aSurface; mSurfaceDC = mSurface->Select( ); return NS_OK; } inline NS_IMETHODIMP GetDrawingSurface(nsIDrawingSurface* *aSurface) { *aSurface = mSurface; return NS_OK; } inline NS_IMETHODIMP GetHints(PRUint32& aResult) { /* this flag indicates that the system prefers 8bit chars over wide chars */ /* It may or may not be faster under photon... */ aResult = NS_RENDERING_HINT_FAST_8BIT_TEXT; return NS_OK; } NS_IMETHOD PushState(void); NS_IMETHOD PopState(void); inline NS_IMETHODIMP IsVisibleRect( const nsRect& aRect, PRBool &aVisible ) { aVisible = PR_TRUE; return NS_OK; } NS_IMETHOD SetClipRect(const nsRect& aRect, nsClipCombine aCombine); NS_IMETHOD GetClipRect(nsRect &aRect, PRBool &aClipState); NS_IMETHOD SetClipRegion(const nsIRegion& aRegion, nsClipCombine aCombine); inline NS_IMETHODIMP CopyClipRegion(nsIRegion &aRegion) { if( !mClipRegion ) return NS_ERROR_FAILURE; aRegion.SetTo(*static_cast(mClipRegion)); return NS_OK; } NS_IMETHOD GetClipRegion(nsIRegion **aRegion); inline NS_IMETHODIMP SetLineStyle(nsLineStyle aLineStyle) { mCurrentLineStyle = aLineStyle; return NS_OK; } inline NS_IMETHODIMP GetLineStyle(nsLineStyle &aLineStyle) { aLineStyle = mCurrentLineStyle; return NS_OK; } inline NS_IMETHODIMP SetColor(nscolor aColor) { mCurrentColor = NS_TO_PH_RGB( aColor ); return NS_OK; } inline NS_IMETHODIMP GetColor(nscolor &aColor) const { aColor = PH_TO_NS_RGB( mCurrentColor ); return NS_OK; } inline NS_IMETHODIMP SetFont(const nsFont& aFont, nsIAtom* aLangGroup) { nsIFontMetrics* newMetrics; nsresult rv = mContext->GetMetricsFor( aFont, aLangGroup, newMetrics ); if( NS_SUCCEEDED( rv ) ) { rv = SetFont( newMetrics ); NS_RELEASE( newMetrics ); } return rv; } NS_IMETHOD SetFont(nsIFontMetrics *aFontMetrics); inline NS_IMETHODIMP GetFontMetrics(nsIFontMetrics *&aFontMetrics) { NS_IF_ADDREF(mFontMetrics); aFontMetrics = mFontMetrics; return NS_OK; } inline NS_IMETHODIMP Translate(nscoord aX, nscoord aY) { mTranMatrix->AddTranslation((float)aX,(float)aY); return NS_OK; } inline NS_IMETHODIMP Scale(float aSx, float aSy) { mTranMatrix->AddScale(aSx, aSy); return NS_OK; } inline NS_IMETHODIMP GetCurrentTransform(nsTransform2D *&aTransform) { aTransform = mTranMatrix; return NS_OK; } NS_IMETHOD CreateDrawingSurface(const nsRect &aBounds, PRUint32 aSurfFlags, nsIDrawingSurface* &aSurface); inline NS_IMETHODIMP DestroyDrawingSurface(nsIDrawingSurface* aDS) { nsDrawingSurfacePh *surf = (nsDrawingSurfacePh *) aDS; NS_IF_RELEASE(surf); return NS_OK; } NS_IMETHOD DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1); inline NS_IMETHODIMP DrawPolyline(const nsPoint aPoints[], PRInt32 aNumPoints) { return DrawPolygon( aPoints, aNumPoints ); } inline NS_IMETHODIMP DrawRect(const nsRect& aRect) { return DrawRect( aRect.x, aRect.y, aRect.width, aRect.height ); } NS_IMETHOD DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight); inline NS_IMETHODIMP FillRect(const nsRect& aRect) { return FillRect( aRect.x, aRect.y, aRect.width, aRect.height ); } NS_IMETHOD FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight); inline NS_IMETHODIMP InvertRect(const nsRect& aRect) { return InvertRect( aRect.x, aRect.y, aRect.width, aRect.height ); } NS_IMETHOD InvertRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight); NS_IMETHOD DrawPolygon(const nsPoint aPoints[], PRInt32 aNumPoints); NS_IMETHOD FillPolygon(const nsPoint aPoints[], PRInt32 aNumPoints); inline NS_IMETHODIMP DrawEllipse(const nsRect& aRect) { return DrawEllipse( aRect.x, aRect.y, aRect.width, aRect.height ); } NS_IMETHOD DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight); inline NS_IMETHODIMP FillEllipse(const nsRect& aRect) { return FillEllipse( aRect.x, aRect.y, aRect.width, aRect.height ); } NS_IMETHOD FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight); inline NS_IMETHODIMP DrawArc(const nsRect& aRect, float aStartAngle, float aEndAngle) { return DrawArc(aRect.x,aRect.y,aRect.width,aRect.height,aStartAngle,aEndAngle); } NS_IMETHOD DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight, float aStartAngle, float aEndAngle); inline NS_IMETHODIMP FillArc(const nsRect& aRect, float aStartAngle, float aEndAngle) { return FillArc(aRect.x,aRect.y,aRect.width,aRect.height,aStartAngle,aEndAngle); } NS_IMETHOD FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight, float aStartAngle, float aEndAngle); inline NS_IMETHODIMP GetWidth(char aC, nscoord& aWidth) { // Check for the very common case of trying to get the width of a single space if(aC == ' ') return mFontMetrics->GetSpaceWidth(aWidth); return GetWidth( &aC, 1, aWidth ); } inline NS_IMETHODIMP GetWidth(PRUnichar aC, nscoord& aWidth, PRInt32 *aFontID) { /* turn it into a string */ PRUnichar buf[2]; buf[0] = aC; buf[1] = nsnull; return GetWidth( buf, 1, aWidth, aFontID ); } inline NS_IMETHODIMP GetWidth(const nsString& aString, nscoord& aWidth, PRInt32 *aFontID) { return GetWidth( aString.get(), aString.Length(), aWidth, aFontID ); } inline NS_IMETHODIMP GetWidth(const char* aString, nscoord& aWidth) { return GetWidth( aString, strlen( aString ), aWidth ); } NS_IMETHOD GetWidth(const char* aString, PRUint32 aLength, nscoord& aWidth); NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength, nscoord& aWidth, PRInt32 *aFontID); NS_IMETHOD DrawString(const char *aString, PRUint32 aLength, nscoord aX, nscoord aY, const nscoord* aSpacing); inline NS_IMETHODIMP DrawString(const PRUnichar *aString, PRUint32 aLength, nscoord aX, nscoord aY, PRInt32 aFontID, const nscoord* aSpacing) { NS_ConvertUTF16toUTF8 theUnicodeString( aString, aLength ); const char *p = theUnicodeString.get( ); return DrawString( p, strlen( p ), aX, aY, aSpacing ); } inline NS_IMETHODIMP DrawString(const nsString& aString, nscoord aX, nscoord aY, PRInt32 aFontID, const nscoord* aSpacing) { NS_ConvertUTF16toUTF8 theUnicodeString( aString.get(), aString.Length() ); const char *p = theUnicodeString.get(); return DrawString( p, strlen( p ), aX, aY, aSpacing ); } inline NS_IMETHODIMP GetTextDimensions(const char* aString, PRUint32 aLength, nsTextDimensions& aDimensions) { mFontMetrics->GetMaxAscent(aDimensions.ascent); mFontMetrics->GetMaxDescent(aDimensions.descent); return GetWidth(aString, aLength, aDimensions.width); } NS_IMETHOD GetTextDimensions(const PRUnichar *aString, PRUint32 aLength, nsTextDimensions& aDimensions, PRInt32 *aFontID); inline NS_IMETHODIMP DrawImage(nsIImage *aImage, nscoord aX, nscoord aY) { // we have to do this here because we are doing a transform below return DrawImage( aImage, aX, aY, NSToCoordRound(mP2T * aImage->GetWidth()), NSToCoordRound(mP2T * aImage->GetHeight()) ); } inline NS_IMETHODIMP DrawImage(nsIImage *aImage, nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) { nscoord x, y, w, h; x = aX; y = aY; w = aWidth; h = aHeight; mTranMatrix->TransformCoord(&x, &y, &w, &h); return (aImage->Draw(*this, mSurface, x, y, w, h)); } inline NS_IMETHODIMP DrawImage(nsIImage *aImage, const nsRect& aRect) { return DrawImage( aImage, aRect.x, aRect.y, aRect.width, aRect.height ); } NS_IMETHOD DrawImage(nsIImage *aImage, const nsRect& aSRect, const nsRect& aDRect); NS_IMETHOD CopyOffScreenBits(nsIDrawingSurface* aSrcSurf, PRInt32 aSrcX, PRInt32 aSrcY, const nsRect &aDestBounds, PRUint32 aCopyFlags); #ifdef MOZ_MATHML /** * Returns metrics (in app units) of an 8-bit character string */ NS_IMETHOD GetBoundingMetrics(const char* aString, PRUint32 aLength, nsBoundingMetrics& aBoundingMetrics); /** * Returns metrics (in app units) of a Unicode character string */ NS_IMETHOD GetBoundingMetrics(const PRUnichar* aString, PRUint32 aLength, nsBoundingMetrics& aBoundingMetrics, PRInt32* aFontID = nsnull); #endif /* MOZ_MATHML */ private: inline NS_IMETHODIMP CommonInit() { if( mContext && mTranMatrix ) { mP2T = mContext->DevUnitsToAppUnits(); float app2dev; app2dev = mContext->AppUnitsToDevUnits(); mTranMatrix->AddScale(app2dev, app2dev); } return NS_OK; } void ApplyClipping( PhGC_t * ); void CreateClipRegion( ); inline void UpdateGC( ) { PgSetGCCx( mSurfaceDC, mGC ); /* new */ if( mRegionID ) mSurfaceDC->gin.rid = mRegionID; ApplyClipping( mGC ); } // ConditionRect is used to fix coordinate overflow problems for // rectangles after they are transformed to screen coordinates inline void ConditionRect(nscoord &x, nscoord &y, nscoord &w, nscoord &h) { if ( y < -32766 ) y = -32766; if ( y + h > 32766 ) h = 32766 - y; if ( x < -32766 ) x = -32766; if ( x + w > 32766 ) w = 32766 - x; } PhGC_t *mGC; PhDrawContext_t *mSurfaceDC; /* the DC of the mSurface - keep this in sync with mSurface */ PhRid_t mRegionID; nscolor mCurrentColor; nsLineStyle mCurrentLineStyle; nsIFontMetrics *mFontMetrics; nsDrawingSurfacePh *mOffscreenSurface; nsDrawingSurfacePh *mSurface; nsIDeviceContext *mContext; float mP2T; nsCOMPtrmClipRegion; char *mPhotonFontName; PRBool mOwner; //state management nsVoidArray *mStateCache; }; #endif /* nsRenderingContextPh_h___ */