Mozilla/mozilla/gfx/src/windows/nsRenderingContextWin.cpp
troy 1f60015e7e Changed to set the polygon fill mode in CommonInit() instead of when drawing
polygons


git-svn-id: svn://10.0.0.236/trunk@3793 18797224-902f-48f8-a5cc-f745e15eee43
1998-06-15 18:50:08 +00:00

1066 lines
26 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsRenderingContextWin.h"
#include "nsRegionWin.h"
#include <math.h>
#define FLAG_CLIP_VALID 0x0001
#define FLAG_CLIP_CHANGED 0x0002
#define FLAG_LOCAL_CLIP_VALID 0x0004
#define FLAGS_ALL (FLAG_CLIP_VALID | FLAG_CLIP_CHANGED | FLAG_LOCAL_CLIP_VALID)
class GraphicsState
{
public:
GraphicsState();
GraphicsState(GraphicsState &aState);
~GraphicsState();
GraphicsState *mNext;
nsTransform2D mMatrix;
nsRect mLocalClip;
HRGN mClipRegion;
nscolor mBrushColor;
HBRUSH mSolidBrush;
nsIFontMetrics *mFontMetrics;
HFONT mFont;
nscolor mPenColor;
HPEN mSolidPen;
PRInt32 mFlags;
};
GraphicsState :: GraphicsState()
{
mNext = nsnull;
mMatrix.SetToIdentity();
mLocalClip.x = mLocalClip.y = mLocalClip.width = mLocalClip.height = 0;
mClipRegion = NULL;
mBrushColor = NS_RGB(0, 0, 0);
mSolidBrush = NULL;
mFontMetrics = nsnull;
mFont = NULL;
mPenColor = NS_RGB(0, 0, 0);
mSolidPen = NULL;
mFlags = ~FLAGS_ALL;
}
GraphicsState :: GraphicsState(GraphicsState &aState) :
mMatrix(&aState.mMatrix),
mLocalClip(aState.mLocalClip)
{
mNext = &aState;
mClipRegion = NULL;
mBrushColor = aState.mBrushColor;
mSolidBrush = NULL;
mFontMetrics = nsnull;
mFont = NULL;
mPenColor = aState.mPenColor;
mSolidPen = NULL;
mFlags = ~FLAGS_ALL;
}
GraphicsState :: ~GraphicsState()
{
if (NULL != mClipRegion)
{
::DeleteObject(mClipRegion);
mClipRegion = NULL;
}
if (NULL != mSolidBrush)
{
::DeleteObject(mSolidBrush);
mSolidBrush = NULL;
}
//don't delete this because it lives in the font metrics
mFont = NULL;
if (NULL != mSolidPen)
{
::DeleteObject(mSolidPen);
mSolidPen = NULL;
}
}
static NS_DEFINE_IID(kRenderingContextIID, NS_IRENDERING_CONTEXT_IID);
nsRenderingContextWin :: nsRenderingContextWin()
{
NS_INIT_REFCNT();
mDC = NULL;
mMainDC = NULL;
mDCOwner = nsnull;
mFontMetrics = nsnull;
mFontCache = nsnull;
mOrigSolidBrush = NULL;
mBlackBrush = NULL;
mOrigFont = NULL;
mDefFont = NULL;
mOrigSolidPen = NULL;
mBlackPen = NULL;
mCurrBrushColor = NULL;
mCurrFontMetrics = nsnull;
mCurrPenColor = NULL;
mNullPen = NULL;
#ifdef NS_DEBUG
mInitialized = PR_FALSE;
#endif
mStateCache = new nsVoidArray();
//create an initial GraphicsState
PushState();
mP2T = 1.0f;
}
nsRenderingContextWin :: ~nsRenderingContextWin()
{
NS_IF_RELEASE(mContext);
NS_IF_RELEASE(mFontMetrics);
NS_IF_RELEASE(mFontCache);
//destroy the initial GraphicsState
PopState();
//cleanup the DC so that we can just destroy objects
//in the graphics state without worrying that we are
//ruining the dc
if (NULL != mDC)
{
if (NULL != mOrigSolidBrush)
{
::SelectObject(mDC, mOrigSolidBrush);
mOrigSolidBrush = NULL;
}
if (NULL != mOrigFont)
{
::SelectObject(mDC, mOrigFont);
mOrigFont = NULL;
}
if (NULL != mDefFont)
{
::DeleteObject(mDefFont);
mDefFont = NULL;
}
if (NULL != mOrigSolidPen)
{
::SelectObject(mDC, mOrigSolidPen);
mOrigSolidPen = NULL;
}
if (NULL != mCurrBrush)
::DeleteObject(mCurrBrush);
if ((NULL != mBlackBrush) && (mBlackBrush != mCurrBrush))
::DeleteObject(mBlackBrush);
mCurrBrush = NULL;
mBlackBrush = NULL;
//don't kill the font because the font cache/metrics owns it
mCurrFont = NULL;
if (NULL != mCurrPen)
::DeleteObject(mCurrPen);
if ((NULL != mBlackPen) && (mBlackPen != mCurrPen))
::DeleteObject(mBlackPen);
if ((NULL != mNullPen) && (mNullPen != mCurrPen))
::DeleteObject(mNullPen);
mCurrPen = NULL;
mBlackPen = NULL;
mNullPen = NULL;
}
if (nsnull != mStateCache)
{
PRInt32 cnt = mStateCache->Count();
while (--cnt >= 0)
{
GraphicsState *state = (GraphicsState *)mStateCache->ElementAt(cnt);
mStateCache->RemoveElementAt(cnt);
if (nsnull != state)
delete state;
}
delete mStateCache;
mStateCache = nsnull;
}
if (nsnull != mDCOwner)
{
//first try to get rid of a DC originally associated with the window
//but pushed over to a dest DC for offscreen rendering. if there is no
//rolled over DC, then the mDC is the one associated with the window.
if (nsnull != mMainDC)
ReleaseDC((HWND)mDCOwner->GetNativeData(NS_NATIVE_WINDOW), mMainDC);
else if (nsnull != mDC)
ReleaseDC((HWND)mDCOwner->GetNativeData(NS_NATIVE_WINDOW), mDC);
}
NS_IF_RELEASE(mDCOwner);
mTMatrix = nsnull;
mDC = NULL;
mMainDC = NULL;
}
NS_IMPL_QUERY_INTERFACE(nsRenderingContextWin, kRenderingContextIID)
NS_IMPL_ADDREF(nsRenderingContextWin)
NS_IMPL_RELEASE(nsRenderingContextWin)
nsresult nsRenderingContextWin :: Init(nsIDeviceContext* aContext,
nsIWidget *aWindow)
{
NS_PRECONDITION(PR_FALSE == mInitialized, "double init");
mContext = aContext;
NS_IF_ADDREF(mContext);
mDC = (HWND)aWindow->GetNativeData(NS_NATIVE_GRAPHIC);
mDCOwner = aWindow;
if (mDCOwner)
NS_ADDREF(mDCOwner);
return CommonInit();
}
nsresult nsRenderingContextWin :: Init(nsIDeviceContext* aContext,
nsDrawingSurface aSurface)
{
NS_PRECONDITION(PR_FALSE == mInitialized, "double init");
mContext = aContext;
NS_IF_ADDREF(mContext);
mDC = (HDC)aSurface;
mDCOwner = nsnull;
return CommonInit();
}
nsresult nsRenderingContextWin :: CommonInit(void)
{
::SetPolyFillMode(mDC, WINDING);
mTMatrix->AddScale(mContext->GetAppUnitsToDevUnits(),
mContext->GetAppUnitsToDevUnits());
mP2T = mContext->GetDevUnitsToAppUnits();
mFontCache = mContext->GetFontCache();
#ifdef NS_DEBUG
mInitialized = PR_TRUE;
#endif
mBlackBrush = ::CreateSolidBrush(RGB(0, 0, 0));
mOrigSolidBrush = ::SelectObject(mDC, mBlackBrush);
mDefFont = ::CreateFont(12, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FF_ROMAN | VARIABLE_PITCH, "Times New Roman");
mOrigFont = ::SelectObject(mDC, mDefFont);
mBlackPen = ::CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
mOrigSolidPen = ::SelectObject(mDC, mBlackPen);
mGammaTable = mContext->GetGammaTable();
return NS_OK;
}
nsresult nsRenderingContextWin :: SelectOffScreenDrawingSurface(nsDrawingSurface aSurface)
{
mMainDC = mDC;
mDC = (HDC)aSurface;
return NS_OK;
}
void nsRenderingContextWin :: Reset()
{
}
nsIDeviceContext * nsRenderingContextWin :: GetDeviceContext(void)
{
NS_IF_ADDREF(mContext);
return mContext;
}
void nsRenderingContextWin :: PushState(void)
{
PRInt32 cnt = mStateCache->Count();
if (cnt == 0)
{
if (nsnull == mStates)
mStates = new GraphicsState();
else
mStates = new GraphicsState(*mStates);
}
else
{
GraphicsState *state = (GraphicsState *)mStateCache->ElementAt(cnt - 1);
mStateCache->RemoveElementAt(cnt - 1);
state->mNext = mStates;
//clone state info
state->mMatrix = mStates->mMatrix;
state->mLocalClip = mStates->mLocalClip;
state->mClipRegion = NULL;
state->mBrushColor = mStates->mBrushColor;
state->mSolidBrush = NULL;
state->mFontMetrics = mStates->mFontMetrics;
state->mFont = NULL;
state->mPenColor = mStates->mPenColor;
state->mSolidPen = NULL;
state->mFlags = ~FLAGS_ALL;
mStates = state;
}
mTMatrix = &mStates->mMatrix;
}
void nsRenderingContextWin :: PopState(void)
{
if (nsnull == mStates)
{
NS_ASSERTION(!(nsnull == mStates), "state underflow");
}
else
{
GraphicsState *oldstate = mStates;
mStates = mStates->mNext;
mStateCache->AppendElement(oldstate);
if (nsnull != mStates)
{
mTMatrix = &mStates->mMatrix;
GraphicsState *pstate;
if (oldstate->mFlags & FLAG_CLIP_CHANGED)
{
pstate = mStates;
//the clip rect has changed from state to state, so
//install the previous clip rect
while ((nsnull != pstate) && !(pstate->mFlags & FLAG_CLIP_VALID))
pstate = pstate->mNext;
if (nsnull != pstate)
::SelectClipRgn(mDC, pstate->mClipRegion);
}
oldstate->mFlags &= ~FLAGS_ALL;
oldstate->mSolidBrush = NULL;
oldstate->mFont = NULL;
oldstate->mSolidPen = NULL;
}
else
mTMatrix = nsnull;
}
}
PRBool nsRenderingContextWin :: IsVisibleRect(const nsRect& aRect)
{
return PR_TRUE;
}
PRBool nsRenderingContextWin :: SetClipRect(const nsRect& aRect, nsClipCombine aCombine)
{
nsRect trect = aRect;
int cliptype;
mStates->mLocalClip = aRect;
mTMatrix->TransformCoord(&trect.x, &trect.y,
&trect.width, &trect.height);
mStates->mFlags |= FLAG_LOCAL_CLIP_VALID;
//how we combine the new rect with the previous?
if (aCombine == nsClipCombine_kIntersect)
{
PushClipState();
cliptype = ::IntersectClipRect(mDC, trect.x,
trect.y,
trect.XMost(),
trect.YMost());
}
else if (aCombine == nsClipCombine_kUnion)
{
PushClipState();
HRGN tregion = ::CreateRectRgn(trect.x,
trect.y,
trect.XMost(),
trect.YMost());
cliptype = ::ExtSelectClipRgn(mDC, tregion, RGN_OR);
::DeleteObject(tregion);
}
else if (aCombine == nsClipCombine_kSubtract)
{
PushClipState();
cliptype = ::ExcludeClipRect(mDC, trect.x,
trect.y,
trect.XMost(),
trect.YMost());
}
else if (aCombine == nsClipCombine_kReplace)
{
PushClipState();
HRGN tregion = ::CreateRectRgn(trect.x,
trect.y,
trect.XMost(),
trect.YMost());
cliptype = ::SelectClipRgn(mDC, tregion);
::DeleteObject(tregion);
}
else
NS_ASSERTION(FALSE, "illegal clip combination");
if (cliptype == NULLREGION)
return PR_TRUE;
else
return PR_FALSE;
}
PRBool nsRenderingContextWin :: GetClipRect(nsRect &aRect)
{
if (mStates->mFlags & FLAG_LOCAL_CLIP_VALID)
{
aRect = mStates->mLocalClip;
return PR_TRUE;
}
else
return PR_FALSE;
}
PRBool nsRenderingContextWin :: SetClipRegion(const nsIRegion& aRegion, nsClipCombine aCombine)
{
nsRegionWin *pRegion = (nsRegionWin *)&aRegion;
HRGN hrgn = pRegion->GetHRGN();
int cmode, cliptype;
switch (aCombine)
{
case nsClipCombine_kIntersect:
cmode = RGN_AND;
break;
case nsClipCombine_kUnion:
cmode = RGN_OR;
break;
case nsClipCombine_kSubtract:
cmode = RGN_DIFF;
break;
default:
case nsClipCombine_kReplace:
cmode = RGN_COPY;
break;
}
if (NULL != hrgn)
{
mStates->mFlags &= ~FLAG_LOCAL_CLIP_VALID;
PushClipState();
cliptype = ::ExtSelectClipRgn(mDC, hrgn, cmode);
}
else
return PR_FALSE;
if (cliptype == NULLREGION)
return PR_TRUE;
else
return PR_FALSE;
}
void nsRenderingContextWin :: GetClipRegion(nsIRegion **aRegion)
{
//XXX wow, needs to do something.
}
void nsRenderingContextWin :: SetColor(nscolor aColor)
{
mCurrentColor = aColor;
mColor = RGB(mGammaTable[NS_GET_R(aColor)],
mGammaTable[NS_GET_G(aColor)],
mGammaTable[NS_GET_B(aColor)]);
}
nscolor nsRenderingContextWin :: GetColor() const
{
return mCurrentColor;
}
void nsRenderingContextWin :: SetFont(const nsFont& aFont)
{
NS_IF_RELEASE(mFontMetrics);
mFontMetrics = mFontCache->GetMetricsFor(aFont);
}
const nsFont& nsRenderingContextWin :: GetFont()
{
return mFontMetrics->GetFont();
}
nsIFontMetrics* nsRenderingContextWin :: GetFontMetrics()
{
return mFontMetrics;
}
// add the passed in translation to the current translation
void nsRenderingContextWin :: Translate(nscoord aX, nscoord aY)
{
mTMatrix->AddTranslation((float)aX,(float)aY);
}
// add the passed in scale to the current scale
void nsRenderingContextWin :: Scale(float aSx, float aSy)
{
mTMatrix->AddScale(aSx, aSy);
}
nsTransform2D * nsRenderingContextWin :: GetCurrentTransform()
{
return mTMatrix;
}
nsDrawingSurface nsRenderingContextWin :: CreateDrawingSurface(nsRect *aBounds)
{
HDC hDC = ::CreateCompatibleDC(mDC);
if (nsnull != aBounds)
{
HBITMAP hBits = ::CreateCompatibleBitmap(mDC, aBounds->width, aBounds->height);
::SelectObject(hDC, hBits);
}
else
{
HBITMAP hBits = ::CreateCompatibleBitmap(mDC, 2, 2);
::SelectObject(hDC, hBits);
}
return hDC;
}
void nsRenderingContextWin :: DestroyDrawingSurface(nsDrawingSurface aDS)
{
HDC hDC = (HDC)aDS;
HBITMAP hTempBits = ::CreateCompatibleBitmap(hDC, 2, 2);
HBITMAP hBits = ::SelectObject(hDC, hTempBits);
if (nsnull != hBits)
::DeleteObject(hBits);
::DeleteObject(hTempBits);
::DeleteDC(hDC);
}
void nsRenderingContextWin :: DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1)
{
mTMatrix->TransformCoord(&aX0,&aY0);
mTMatrix->TransformCoord(&aX1,&aY1);
SetupSolidPen();
::MoveToEx(mDC, (int)(aX0), (int)(aY0), NULL);
::LineTo(mDC, (int)(aX1), (int)(aY1));
}
void nsRenderingContextWin :: DrawRect(const nsRect& aRect)
{
RECT nr;
nsRect tr;
tr = aRect;
mTMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height);
nr.left = tr.x;
nr.top = tr.y;
nr.right = tr.x+tr.width;
nr.bottom = tr.y+tr.height;
::FrameRect(mDC, &nr, SetupSolidBrush());
}
void nsRenderingContextWin :: DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
{
RECT nr;
mTMatrix->TransformCoord(&aX,&aY,&aWidth,&aHeight);
nr.left = aX;
nr.top = aY;
nr.right = aX+aWidth;
nr.bottom = aY+aHeight;
::FrameRect(mDC, &nr, SetupSolidBrush());
}
void nsRenderingContextWin :: FillRect(const nsRect& aRect)
{
RECT nr;
nsRect tr;
tr = aRect;
mTMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height);
nr.left = tr.x;
nr.top = tr.y;
nr.right = tr.x+tr.width;
nr.bottom = tr.y+tr.height;
::FillRect(mDC, &nr, SetupSolidBrush());
}
void nsRenderingContextWin :: FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
{
RECT nr;
nsRect tr;
mTMatrix->TransformCoord(&aX,&aY,&aWidth,&aHeight);
nr.left = aX;
nr.top = aY;
nr.right = aX+aWidth;
nr.bottom = aY+aHeight;
::FillRect(mDC, &nr, SetupSolidBrush());
}
void nsRenderingContextWin::DrawPolygon(nsPoint aPoints[], PRInt32 aNumPoints)
{
// First transform nsPoint's into POINT's; perform coordinate space
// transformation at the same time
POINT pts[20];
POINT* pp0 = pts;
if (aNumPoints > 20)
pp0 = new POINT[aNumPoints];
POINT* pp = pp0;
const nsPoint* np = &aPoints[0];
for (PRInt32 i = 0; i < aNumPoints; i++, pp++, np++)
{
pp->x = np->x;
pp->y = np->y;
mTMatrix->TransformCoord((int*)&pp->x,(int*)&pp->y);
}
// Outline the polygon
LOGBRUSH lb;
lb.lbStyle = BS_NULL;
lb.lbColor = 0;
lb.lbHatch = 0;
SetupSolidPen();
HBRUSH brush = ::CreateBrushIndirect(&lb);
HBRUSH oldBrush = ::SelectObject(mDC, brush);
::Polygon(mDC, pp0, int(aNumPoints));
::SelectObject(mDC, oldBrush);
::DeleteObject(brush);
// Release temporary storage if necessary
if (pp0 != pts)
delete pp0;
}
void nsRenderingContextWin::FillPolygon(nsPoint aPoints[], PRInt32 aNumPoints)
{
// First transform nsPoint's into POINT's; perform coordinate space
// transformation at the same time
POINT pts[20];
POINT* pp0 = pts;
if (aNumPoints > 20)
pp0 = new POINT[aNumPoints];
POINT* pp = pp0;
const nsPoint* np = &aPoints[0];
for (PRInt32 i = 0; i < aNumPoints; i++, pp++, np++)
{
pp->x = np->x;
pp->y = np->y;
mTMatrix->TransformCoord((int*)&pp->x,(int*)&pp->y);
}
// Fill the polygon
SetupSolidBrush();
if (NULL == mNullPen)
mNullPen = ::CreatePen(PS_NULL, 0, 0);
HPEN oldPen = ::SelectObject(mDC, mNullPen);
::Polygon(mDC, pp0, int(aNumPoints));
::SelectObject(mDC, oldPen);
// Release temporary storage if necessary
if (pp0 != pts)
delete pp0;
}
void nsRenderingContextWin :: DrawEllipse(const nsRect& aRect)
{
DrawEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
}
void nsRenderingContextWin :: DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
{
mTMatrix->TransformCoord(&aX, &aY, &aWidth, &aHeight);
SetupSolidPen();
HBRUSH oldBrush = ::SelectObject(mDC, ::GetStockObject(NULL_BRUSH));
::Ellipse(mDC, aX, aY, aX + aWidth, aY + aHeight);
::SelectObject(mDC, oldBrush);
}
void nsRenderingContextWin :: FillEllipse(const nsRect& aRect)
{
FillEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
}
void nsRenderingContextWin :: FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
{
mTMatrix->TransformCoord(&aX, &aY, &aWidth, &aHeight);
SetupSolidPen();
SetupSolidBrush();
::Ellipse(mDC, aX, aY, aX + aWidth, aY + aHeight);
}
void nsRenderingContextWin :: DrawArc(const nsRect& aRect,
float aStartAngle, float aEndAngle)
{
this->DrawArc(aRect.x,aRect.y,aRect.width,aRect.height,aStartAngle,aEndAngle);
}
void nsRenderingContextWin :: DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle)
{
PRInt32 quad1, quad2, sx, sy, ex, ey, cx, cy;
float anglerad, distance;
mTMatrix->TransformCoord(&aX, &aY, &aWidth, &aHeight);
SetupSolidPen();
SetupSolidBrush();
// figure out the the coordinates of the arc from the angle
distance = (float)sqrt((float)(aWidth * aWidth + aHeight * aHeight));
cx = aX + aWidth / 2;
cy = aY + aHeight / 2;
anglerad = (float)(aStartAngle / (180.0 / 3.14159265358979323846));
quad1 = (PRInt32)(aStartAngle / 90.0);
sx = (PRInt32)(distance * cos(anglerad) + cx);
sy = (PRInt32)(cy - distance * sin(anglerad));
anglerad = (float)(aEndAngle / (180.0 / 3.14159265358979323846));
quad2 = (PRInt32)(aEndAngle / 90.0);
ex = (PRInt32)(distance * cos(anglerad) + cx);
ey = (PRInt32)(cy - distance * sin(anglerad));
// this just makes it consitent, on windows 95 arc will always draw CC, nt this sets direction
::SetArcDirection(mDC, AD_COUNTERCLOCKWISE);
::Arc(mDC, aX, aY, aX + aWidth, aY + aHeight, sx, sy, ex, ey);
}
void nsRenderingContextWin :: FillArc(const nsRect& aRect,
float aStartAngle, float aEndAngle)
{
this->FillArc(aRect.x, aRect.y, aRect.width, aRect.height, aStartAngle, aEndAngle);
}
void nsRenderingContextWin :: FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle)
{
PRInt32 quad1, quad2, sx, sy, ex, ey, cx, cy;
float anglerad, distance;
mTMatrix->TransformCoord(&aX, &aY, &aWidth, &aHeight);
SetupSolidPen();
SetupSolidBrush();
// figure out the the coordinates of the arc from the angle
distance = (float)sqrt((float)(aWidth * aWidth + aHeight * aHeight));
cx = aX + aWidth / 2;
cy = aY + aHeight / 2;
anglerad = (float)(aStartAngle / (180.0 / 3.14159265358979323846));
quad1 = (PRInt32)(aStartAngle / 90.0);
sx = (PRInt32)(distance * cos(anglerad) + cx);
sy = (PRInt32)(cy - distance * sin(anglerad));
anglerad = (float)(aEndAngle / (180.0 / 3.14159265358979323846));
quad2 = (PRInt32)(aEndAngle / 90.0);
ex = (PRInt32)(distance * cos(anglerad) + cx);
ey = (PRInt32)(cy - distance * sin(anglerad));
// this just makes it consitent, on windows 95 arc will always draw CC, nt this sets direction
::SetArcDirection(mDC, AD_COUNTERCLOCKWISE);
::Pie(mDC, aX, aY, aX + aWidth, aY + aHeight, sx, sy, ex, ey);
}
void nsRenderingContextWin :: DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
nscoord aWidth)
{
int oldBkMode = ::SetBkMode(mDC, TRANSPARENT);
int x,y;
SetupFont();
COLORREF oldColor = ::SetTextColor(mDC, mColor);
x = aX;
y = aY;
mTMatrix->TransformCoord(&x,&y);
::TextOut(mDC,x,y,aString,aLength);
if (mFontMetrics->GetFont().decorations & NS_FONT_DECORATION_OVERLINE)
DrawLine(aX, aY, aX + aWidth, aY);
::SetBkMode(mDC, oldBkMode);
::SetTextColor(mDC, oldColor);
}
void nsRenderingContextWin :: DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY, nscoord aWidth)
{
int x,y;
int oldBkMode = ::SetBkMode(mDC, TRANSPARENT);
SetupFont();
COLORREF oldColor = ::SetTextColor(mDC, mColor);
x = aX;
y = aY;
mTMatrix->TransformCoord(&x,&y);
::TextOutW(mDC,x,y,aString,aLength);
if (mFontMetrics->GetFont().decorations & NS_FONT_DECORATION_OVERLINE)
DrawLine(aX, aY, aX + aWidth, aY);
::SetBkMode(mDC, oldBkMode);
::SetTextColor(mDC, oldColor);
}
void nsRenderingContextWin :: DrawString(const nsString& aString,
nscoord aX, nscoord aY, nscoord aWidth)
{
DrawString(aString.GetUnicode(), aString.Length(), aX, aY, aWidth);
}
void nsRenderingContextWin :: DrawImage(nsIImage *aImage, nscoord aX, nscoord aY)
{
NS_PRECONDITION(PR_TRUE == mInitialized, "!initialized");
nscoord width, height;
width = NS_TO_INT_ROUND(mP2T * aImage->GetWidth());
height = NS_TO_INT_ROUND(mP2T * aImage->GetHeight());
this->DrawImage(aImage, aX, aY, width, height);
}
void nsRenderingContextWin :: DrawImage(nsIImage *aImage, nscoord aX, nscoord aY,
nscoord aWidth, nscoord aHeight)
{
nsRect tr;
tr.x = aX;
tr.y = aY;
tr.width = aWidth;
tr.height = aHeight;
this->DrawImage(aImage, tr);
}
void nsRenderingContextWin :: DrawImage(nsIImage *aImage, const nsRect& aSRect, const nsRect& aDRect)
{
nsRect sr,dr;
sr = aSRect;
mTMatrix->TransformCoord(&sr.x, &sr.y, &sr.width, &sr.height);
dr = aDRect;
mTMatrix->TransformCoord(&dr.x, &dr.y, &dr.width, &dr.height);
((nsImageWin *)aImage)->Draw(*this, mDC, sr.x, sr.y, sr.width, sr.height, dr.x, dr.y, dr.width, dr.height);
}
void nsRenderingContextWin :: DrawImage(nsIImage *aImage, const nsRect& aRect)
{
nsRect tr;
tr = aRect;
mTMatrix->TransformCoord(&tr.x, &tr.y, &tr.width, &tr.height);
((nsImageWin *)aImage)->Draw(*this, mDC, tr.x, tr.y, tr.width, tr.height);
}
nsresult nsRenderingContextWin :: CopyOffScreenBits(nsRect &aBounds)
{
if ((nsnull != mDC) && (nsnull != mMainDC))
{
HRGN tregion = ::CreateRectRgn(0, 0, 0, 0);
if (::GetClipRgn(mDC, tregion) == 1)
::SelectClipRgn(mMainDC, tregion);
// else
// ::SelectClipRgn(mMainDC, NULL);
::DeleteObject(tregion);
#if 0
GraphicsState *pstate = mStates;
//look for a cliprect somewhere in the stack...
while ((nsnull != pstate) && !(pstate->mFlags & FLAG_CLIP_VALID))
pstate = pstate->mNext;
if (nsnull != pstate)
::SelectClipRgn(mMainDC, pstate->mClipRegion);
else
::SelectClipRgn(mMainDC, NULL);
#endif
::BitBlt(mMainDC, 0, 0, aBounds.width, aBounds.height, mDC, 0, 0, SRCCOPY);
}
else
NS_ASSERTION(0, "attempt to blit with bad DCs");
return NS_OK;
}
static numpen = 0;
static numbrush = 0;
static numfont = 0;
HBRUSH nsRenderingContextWin :: SetupSolidBrush(void)
{
if ((mCurrentColor != mCurrBrushColor) || (NULL == mCurrBrush))
{
HBRUSH tbrush = ::CreateSolidBrush(mColor);
::SelectObject(mDC, tbrush);
if (NULL != mCurrBrush)
::DeleteObject(mCurrBrush);
mStates->mSolidBrush = mCurrBrush = tbrush;
mStates->mBrushColor = mCurrBrushColor = mCurrentColor;
//printf("brushes: %d\n", ++numbrush);
}
return mCurrBrush;
}
void nsRenderingContextWin :: SetupFont(void)
{
if ((mFontMetrics != mCurrFontMetrics) || (NULL == mCurrFontMetrics))
{
HFONT tfont = (HFONT)mFontMetrics->GetFontHandle();
::SelectObject(mDC, tfont);
mStates->mFont = mCurrFont = tfont;
mStates->mFontMetrics = mCurrFontMetrics = mFontMetrics;
//printf("fonts: %d\n", ++numfont);
}
}
HPEN nsRenderingContextWin :: SetupSolidPen(void)
{
if ((mCurrentColor != mCurrPenColor) || (NULL == mCurrPen))
{
HPEN tpen = ::CreatePen(PS_SOLID, 0, mColor);
::SelectObject(mDC, tpen);
if (NULL != mCurrPen)
::DeleteObject(mCurrPen);
mStates->mSolidPen = mCurrPen = tpen;
mStates->mPenColor = mCurrPenColor = mCurrentColor;
//printf("pens: %d\n", ++numpen);
}
return mCurrPen;
}
void nsRenderingContextWin :: PushClipState(void)
{
if (!(mStates->mFlags & FLAG_CLIP_CHANGED))
{
GraphicsState *tstate = mStates->mNext;
//we have never set a clip on this state before, so
//remember the current clip state in the next state on the
//stack. kind of wacky, but avoids selecting stuff in the DC
//all the damned time.
if (nsnull != tstate)
{
if (NULL == tstate->mClipRegion)
tstate->mClipRegion = ::CreateRectRgn(0, 0, 0, 0);
if (::GetClipRgn(mDC, tstate->mClipRegion) == 1)
tstate->mFlags |= FLAG_CLIP_VALID;
else
tstate->mFlags &= ~FLAG_CLIP_VALID;
}
mStates->mFlags |= FLAG_CLIP_CHANGED;
}
}