netscape-revival
sun-java/awt/win/awt_graphics.cpp
#include <limits.h>
#include <math.h>
#include "awt_graphics.h"
#include "awt_component.h"
#include "awt_image.h"
#include "awt_dc.h"
#include "awt_font.h"
#include "awt_toolkit.h"
#if !defined(_AWT_IDCSERVICE_H)
#include "awt_IDCService.h"
#endif
// All java header files are extern "C"
extern "C" {
#include "java_awt_Font.h"
#include "java_awt_Color.h"
#include "java_awt_Rectangle.h"
#include "java_awt_Graphics.h"
#include "sun_awt_image_ImageRepresentation.h"
#include "sun_awt_windows_WComponentPeer.h"
#include "sun_awt_windows_WGraphics.h"
#include "java_awt_image_ImageObserver.h"
};
//#define DEBUG_GDI
// Does origin translation
#define OX ((int)(unhand((HWGraphics *)m_pJavaPeer)->originX))
#define OY ((int)(unhand((HWGraphics *)m_pJavaPeer)->originY) )
#define TX(x) ((int)((x) + OX))
#define TY(y) ((int)((y) + OY))
//------------------------------------------------------------------------
//
// Graphics constructor. Build a graphic object for a component
//
//------------------------------------------------------------------------
AwtGraphics::AwtGraphics(HWGraphics *self, HWComponentPeer *canvas) : AwtObject((JHandle *)self)
{
DEFINE_AWT_SENTINAL("GRA");
// assign yourself to the peer object
unhand(self)->pData = (long)this;
AwtComponent* pComp = GET_OBJ_FROM_PEER(AwtComponent, canvas);
// assign yourself a DC
if (pComp) {
m_pAwtDC = AwtDC::Create((IDCService*) pComp);
//set the clipping region to be the size of the client window (if any)
::SetRect(&m_ClipRect, 0, 0, 0, 0);
HWND hOwnerWnd = ((AwtComponent*)pComp)->GetWindowHandle();
if (hOwnerWnd)
{
::GetClientRect(hOwnerWnd, &m_ClipRect);
}
if( IsRectEmpty(&m_ClipRect) )
{
//::SetRect(&m_ClipRect, LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX);
//SetRectRgn() has problems with LONG_MIN, LONG_MAX
::SetRect(&m_ClipRect, 0, 0, 16383, 16383);
}
}
else
m_pAwtDC = 0;
// assign default values
m_pFont = 0;
m_pBrush = AwtCachedBrush::Create(RGB(255, 255, 255));
m_pPen = AwtCachedPen::Create(RGB(0, 0, 0));
// get the palette
//m_pPalette = NULL;
//!DR watch out
m_pPalette = AwtToolkit::GetToolkitDefaultPalette(); //REMIND : get the actual AwtPalette from Toolkit.
m_pPalette->AddRef();
m_pImage = 0;
m_color = RGB(0, 0, 0);
m_xorcolor = RGB(255, 255, 255);
m_rop = R2_COPYPEN;
m_pImage = NULL;
#ifdef DEBUG_GDI
char buf[100];
wsprintf(buf, "Create pGraphics = 0x%x, thrid=%d\n",m_hObject, PR_GetCurrentThreadID() );
OutputDebugString(buf);
#endif
}
//------------------------------------------------------------------------
//
// Graphics constructor. Build a graphic object for an image
//
//------------------------------------------------------------------------
AwtGraphics::AwtGraphics(HWGraphics *self, HImageRepresentation *irh) : AwtObject((JHandle *)self)
{
DEFINE_AWT_SENTINAL("GRA");
// assign yoursel to the java peer
unhand(self)->pData = (long)this;
// the image must exist
AwtImage *pFromImage = (AwtImage *) unhand(irh)->pData;
CHECK_NULL(pFromImage, "Null image to create graphics for");
// Setup defaults.
m_pFont = 0;
m_pPen = AwtCachedPen::Create(RGB(255, 0, 0));
m_pBrush = AwtCachedBrush::Create(RGB(255, 255, 255));
// watch out palette reference counting
//m_pPalette = NULL;
//!DR watch out
m_pPalette = AwtToolkit::GetToolkitDefaultPalette();
m_pPalette->AddRef();
m_color = RGB(0, 0, 0);
m_rop = R2_COPYPEN;
m_xorcolor = RGB(255, 255, 255);
if(pFromImage != NULL)
{
::SetRect(&m_ClipRect, 0, 0, pFromImage->GetWidth(), pFromImage->GetHeight());
m_pImage = pFromImage;
// Note that the following DC will be the same as the one
// allocated in BOOL AwtImage::Create(HImageRepresentation *pJavaObject,
// long nW, long nH) with a added reference count.
m_pAwtDC = AwtDC::Create((IDCService*) pFromImage);
}
else
{
//REMIND: When is the case when a G is created without a component?
m_pAwtDC = 0;
m_pImage = 0;
//::SetRect(&m_ClipRect, LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX);
::SetRect(&m_ClipRect, 0, 0, 16383, 16383);
}
}
//-------------------------------------------------------------------------
//
// Destructor and dispose. Free resources
//
//-------------------------------------------------------------------------
AwtGraphics::~AwtGraphics()
{
if (m_pAwtDC != NULL)
m_pAwtDC->Release();
if (m_pFont != NULL)
m_pFont->Release();
if (m_pBrush != NULL)
m_pBrush->Release();
if (m_pPen != NULL)
m_pPen->Release();
if(m_pPalette != NULL)
m_pPalette->Release();
if (m_pJavaPeer != NULL) {
unhand((HWGraphics *)m_pJavaPeer)->pData = NULL;
m_pJavaPeer = NULL;
}
#ifdef DEBUG_GDI
char buf[100];
wsprintf(buf, "Destroy pGraphics = 0x%x, thrid=%d\n",m_hObject, PR_GetCurrentThreadID() );
OutputDebugString(buf);
#endif
}
//-------------------------------------------------------------------------
//
// Called after the copy constructor from the stub to update some basic info
//
//-------------------------------------------------------------------------
void AwtGraphics::InitCopy(HWGraphics *self)
{
m_pJavaPeer = (JHandle *)self;
unhand(self)->pData = (long)this;
// for any cached resources AddRef to keep counter right
if (m_pAwtDC != NULL)
m_pAwtDC->AddRef();
if (m_pFont != NULL)
m_pFont->AddRef();
if (m_pBrush != NULL)
m_pBrush->AddRef();
if (m_pPen != NULL)
m_pPen->AddRef();
if(m_pPalette != NULL)
m_pPalette->AddRef();
}
//-------------------------------------------------------------------------
//
// Update font. Find the native font from the java one
//
//-------------------------------------------------------------------------
void AwtGraphics::SetFont(Hjava_awt_Font *font)
{
//AwtFont *pFont = AwtFont::FindFont(font);
AwtFont * pFont = AwtFont::GetFontFromObject(font);
pFont->AddRef();
// select the font in the dc
if (pFont && m_pAwtDC) {
m_pAwtDC->SetFont(this, pFont);
}
if (m_pFont) {
m_pFont->Release();
}
m_pFont = pFont;
}
//-------------------------------------------------------------------------
//
// Calculates the appropriate new COLORREF according to the
// current ROP and calls ChangeColor on the new COLORREF
//
//-------------------------------------------------------------------------
void AwtGraphics::SetColor(COLORREF color)
{
ChangeColor( (m_rop == R2_XORPEN) ? XorResult(color, m_xorcolor) : color );
}
//-------------------------------------------------------------------------
//
// change the color for pen, brush and text
//
//-------------------------------------------------------------------------
void AwtGraphics::ChangeColor(COLORREF color)
{
if (m_color != color)
{
AwtCachedPen* pPen;
AwtCachedBrush* pBrush;
VERIFY(pPen = AwtCachedPen::Create(color));
VERIFY(pBrush = AwtCachedBrush::Create(color));
// notify DC
if( m_pAwtDC != NULL)
{
m_pAwtDC->SetPen(this, pPen);
m_pAwtDC->SetBrush(this, pBrush);
m_pAwtDC->SetTxtColor(this, color);
}
// release old pen
if (m_pPen) {
m_pPen->Release();
}
// release old brush
if (m_pBrush) {
m_pBrush->Release();
}
// assign new values
m_pPen = pPen;
m_pBrush = pBrush;
m_color = color;
}
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
COLORREF AwtGraphics::XorResult(COLORREF fgcolor, COLORREF xorcolor)
{
COLORREF c;
//c = (fgcolor & 0xff000000) | ((fgcolor ^ xorcolor) & 0x00ffffff);
if (m_pPalette->GetBitsPerPixel() > 8) {
c = (fgcolor & 0xff000000L) | ((fgcolor ^ xorcolor) & 0x00ffffffL);
} else {
c = PALETTEINDEX(GetNearestPaletteIndex(m_pPalette->GetPalette(), fgcolor) ^
GetNearestPaletteIndex(m_pPalette->GetPalette(), xorcolor));
}
return c;
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
void AwtGraphics::SetRop(DWORD rop, COLORREF fgcolor, COLORREF color)
{
if (m_rop != rop) {
m_rop = rop;
}
if (m_rop == R2_XORPEN) {
ChangeColor(XorResult(fgcolor, color));
m_xorcolor = color;
} else {
ChangeColor(fgcolor);
}
if( m_pAwtDC != NULL) {
m_pAwtDC->SetRop(this, m_rop);
}
}
//-------------------------------------------------------------------------
//
// set the clip rect for this graphic
//
//-------------------------------------------------------------------------
void AwtGraphics::SetClipRect(long nX, long nY, long nW, long nH)
{
int x1, y1, x2, y2;
x1 = TX(nX);
y1 = TY(nY);
if (nW <= 0 || nH <= 0) {
x2 = x1;
y2 = y1;
} else {
x2 = x1 + nW;
y2 = y1 + nH;
}
/*
m_ClipRect.left = x1;
m_ClipRect.top = y1;
m_ClipRect.right = x2;
m_ClipRect.bottom = y2;
*/
//{
RECT newRect;
newRect.left = x1;
newRect.top = y1;
newRect.right = x2;
newRect.bottom = y2;
::IntersectRect(&m_ClipRect, &m_ClipRect, &newRect);
//}
// we always push a clipping region on lock so there is no reason
// to push it here
//if( m_pAwtDC != NULL)
//{
// m_pAwtDC->SetRgn(this, &m_ClipRect);
//}
}
//-------------------------------------------------------------------------
//
// return the clipping region
//
//-------------------------------------------------------------------------
void AwtGraphics::GetClipRect(RECT *rect)
{
rect->left = (m_ClipRect.left - OX);
rect->top = (m_ClipRect.top - OY);
rect->right = (m_ClipRect.right - OX);
rect->bottom = (m_ClipRect.bottom - OY);
}
//-------------------------------------------------------------------------
//
// Draw a line from point (nX1, NY1) to point (nX2 NY2)
//
//-------------------------------------------------------------------------
void AwtGraphics::DrawLine(long nX1, long nY1, long nX2, long nY2)
{
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
VERIFY(::MoveToEx(hDC, TX(nX1), TY(nY1), NULL));
VERIFY(::LineTo(hDC, TX(nX2), TY(nY2)));
// Paint the end-point.
VERIFY(::LineTo(hDC, TX(nX2+1), TY(nY2)));
}
m_pAwtDC->Unlock(this);
}
//-------------------------------------------------------------------------
//
// Draw a polygon given an array of points
//
//-------------------------------------------------------------------------
void AwtGraphics::Polygon(POINT *pPoints, int nPoints)
{
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
// select the NULL_BRUSH
m_pAwtDC->SetBrush(this, 0);
int i;
POINT *p = pPoints;
// translate points
for (i=0; i < nPoints; i++) {
p->x = TX(p->x);
p->y = TY(p->y);
p++;
}
VERIFY(::Polyline(hDC, pPoints, nPoints));
// select old brush back
m_pAwtDC->SetBrush(this, m_pBrush);
}
m_pAwtDC->Unlock(this);
}
//-------------------------------------------------------------------------
//
// Draw a polygon given an array of points and fill it with the current brush
//
//-------------------------------------------------------------------------
void AwtGraphics::FillPolygon(POINT *pPoints, int nPoints)
{
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
int i;
POINT *p = pPoints;
for (i=0; i < nPoints; i++) {
p->x = TX(p->x);
p->y = TY(p->y);
p++;
}
m_pAwtDC->SetPen(this, 0);
VERIFY(::Polygon(hDC, pPoints, nPoints));
m_pAwtDC->SetPen(this, m_pPen);
}
m_pAwtDC->Unlock(this);
}
//-------------------------------------------------------------------------
//
// Draw a rect
//
//-------------------------------------------------------------------------
void AwtGraphics::DrawRect(long nX, long nY, long nW, long nH)
{
// don't process empty rect
if (nW >= 0 && nH >= 0) {
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
// select the NULL_BRUSH in the DC
m_pAwtDC->SetBrush(this, 0);
VERIFY(::Rectangle(hDC, TX(nX), TY(nY), TX(nX+nW+1), TY(nY+nH+1)));
// select old brush back
m_pAwtDC->SetBrush(this, m_pBrush);
}
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Draw a rect and fill with the current brush
//
//-------------------------------------------------------------------------
void AwtGraphics::FillRect(long nX, long nY, long nW, long nH)
{
if (nW > 0 && nH > 0) {
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
m_pAwtDC->SetPen(this, 0);
VERIFY(::Rectangle(hDC, TX(nX), TY(nY), TX(nX+nW+1), TY(nY+nH+1)));
m_pAwtDC->SetPen(this, m_pPen);
}
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Clear the specifed rect and fill with the current component brush
//
//-------------------------------------------------------------------------
void AwtGraphics::ClearRect(long nX, long nY, long nW, long nH)
{
if (nW > 0 && nH > 0) {
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
// try to get the component background brush (what if we fail?)
HBRUSH hBkgnd = m_pAwtDC->GetComponentBkgnd();
if (hBkgnd != NULL) {
RECT rect;
rect.left = TX(nX);
rect.top = TX(nY);
rect.right = TX(nX+nW+1);
rect.bottom = TX(nY+nH+1);
::FillRect(hDC, &rect, hBkgnd);
}
}
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Draw a round rectangle
//
//-------------------------------------------------------------------------
void AwtGraphics::RoundRect(long nX, long nY, long nW, long nH, long nArcW, long nArcH)
{
if (nW >= 0 && nH >= 0) {
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
// select the NULL_BRUSH into the DC
m_pAwtDC->SetBrush(this, 0);
::RoundRect(hDC, TX(nX), TY(nY), TX(nX+nW+1), TY(nY+nH+1), nArcW, nArcH);
// select old brush back
m_pAwtDC->SetBrush(this, m_pBrush);
}
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Draw a round rectangle and fill with the current brush
//
//-------------------------------------------------------------------------
void AwtGraphics::FillRoundRect(long nX, long nY, long nW, long nH, long nArcW, long nArcH)
{
if (nW > 0 && nH > 0) {
HDC hDC = m_pAwtDC->Lock(this);
m_pAwtDC->SetPen(this, 0);
if (hDC != NULL) {
::RoundRect(hDC, TX(nX), TY(nY), TX(nX+nW+1), TY(nY+nH+1), nArcW, nArcH);
}
m_pAwtDC->SetPen(this, m_pPen);
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Draw an ellipse
//
//-------------------------------------------------------------------------
void AwtGraphics::Ellipse(long nX, long nY, long nW, long nH)
{
if (nW >= 0 && nH >= 0) {
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
// select the NULL_BRUSH
m_pAwtDC->SetBrush(this, 0);
VERIFY(::Ellipse(hDC, TX(nX), TY(nY), TX(nX+nW+1), TY(nY+nH+1)));
// select old brush back
m_pAwtDC->SetBrush(this, m_pBrush);
}
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Draw an ellipse and fill with the current brush
//
//-------------------------------------------------------------------------
void AwtGraphics::FillEllipse(long nX, long nY, long nW, long nH)
{
if (nW > 0 && nH > 0) {
HDC hDC = m_pAwtDC->Lock(this);
m_pAwtDC->SetPen(this, 0);
if (hDC != NULL) {
VERIFY(::Ellipse(hDC, TX(nX), TY(nY), TX(nX+nW+1), TY(nY+nH+1)));
}
m_pAwtDC->SetPen(this, m_pPen);
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Converts an angle given in 1/64ths of a degree to a pair of coordinates
// that intersects the line produced by the angle.
//
//-------------------------------------------------------------------------
void AngleToCoord(long nAngle, long nW, long nH, long *nX, long *nY)
{
const double pi = 3.1415926535;
const double toRadians = 2 * pi / 360;
*nX = (long)(cos((double)nAngle * toRadians) * nW);
*nY = -(long)(sin((double)nAngle * toRadians) * nH);
}
//-------------------------------------------------------------------------
//
// Draw an arc
//
//-------------------------------------------------------------------------
void AwtGraphics::Arc(long nX, long nY, long nW, long nH, long nStartAngle, long nEndAngle)
{
if (nW >= 0 && nH >= 0) {
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
long nSX, nSY, nDX, nDY;
BOOL bEndAngleNeg = nEndAngle < 0;
nEndAngle += nStartAngle;
if (bEndAngleNeg)
{
// swap angles
long tmp = nStartAngle;
nStartAngle = nEndAngle;
nEndAngle = tmp;
}
AngleToCoord(nStartAngle, nW, nH, &nSX, &nSY);
nSX += nX + nW/2;
nSY += nY + nH/2;
AngleToCoord(nEndAngle, nW, nH, &nDX, &nDY);
nDX += nX + nW/2;
nDY += nY + nH/2;
// an arc is not filled
VERIFY(::Arc(hDC,
TX(nX), TY(nY), TX(nX+nW+1), TY(nY+nH+1),
TX(nSX), TY(nSY), TX(nDX), TY(nDY)));
}
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Draw a pie
//
//-------------------------------------------------------------------------
void AwtGraphics::FillArc(long nX, long nY, long nW, long nH, long nStartAngle, long nEndAngle)
{
if (nW > 0 && nH > 0) {
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
long nSX, nSY, nDX, nDY;
BOOL bEndAngleNeg = nEndAngle < 0;
nEndAngle += nStartAngle;
if (bEndAngleNeg)
{
// swap angles
long tmp = nStartAngle;
nStartAngle = nEndAngle;
nEndAngle = tmp;
}
AngleToCoord(nStartAngle, nW, nH, &nSX, &nSY);
nSX += nX + nW/2;
nSY += nY + nH/2;
AngleToCoord(nEndAngle, nW, nH, &nDX, &nDY);
nDX += nX + nW/2;
nDY += nY + nH/2;
m_pAwtDC->SetPen(this, 0);
VERIFY(::Pie(hDC,
TX(nX), TY(nY), TX(nX+nW+1), TY(nY+nH+1),
TX(nSX), TY(nSY), TX(nDX), TY(nDY)));
m_pAwtDC->SetPen(this, m_pPen);
}
m_pAwtDC->Unlock(this);
}
}
//-------------------------------------------------------------------------
//
// Draw a string
//
//-------------------------------------------------------------------------
#ifdef INTLUNICODE
void AwtGraphics::DrawString(WinCompStr *pzString, long nX, long nY)
#else // INTLUNICODE
void AwtGraphics::DrawString(char *pzString, long nX, long nY)
#endif // INTLUNICODE
{
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
#ifdef _WIN32_UNDEF
if (m_rop == R2_XORPEN)
{
BeginPath(hDC);
}
#endif //_WIN32
#ifdef INTLUNICODE
if(pzString != NULL)
pzString->TextOutWidth(hDC, TX(nX), TY(nY), m_pFont);
#else // INTLUNICODE
VERIFY(::TextOut(hDC,
TX(nX),
TY(nY - (m_pFont ? m_pFont->GetFontAscent() : 0)),
pzString,
strlen(pzString)));
#endif // INTLUNICODE
#ifdef _WIN32_UNDEF
if (m_rop == R2_XORPEN) {
EndPath(hDC);
FillPath(hDC);
}
#endif //_WIN32
}
m_pAwtDC->Unlock(this);
}
//-------------------------------------------------------------------------
//
// Draw a string and return the length
//
//-------------------------------------------------------------------------
#ifdef INTLUNICODE
long AwtGraphics::DrawStringWidth(WinCompStr *pzString, long nX, long nY)
#else // INTLUNICODE
long AwtGraphics::DrawStringWidth(char *pzString, long nX, long nY)
#endif // INTLUNICODE
{
SIZE size;
HDC hDC = m_pAwtDC->Lock(this);
// draw the string
DrawString(pzString, nX, nY);
if (hDC != NULL) {
#ifdef INTLUNICODE
if(pzString != NULL)
pzString->GetTextExtent(hDC, m_pFont, &size);
#else // INTLUNICODE
// get the string length
#ifdef _WIN32_UNDEF
VERIFY(::GetTextExtentPoint32(hDC, pzString, strlen(pzString), &size));
#else //_WIN32
VERIFY(::GetTextExtentPoint(hDC, pzString, strlen(pzString), &size));
#endif //_WIN32
#endif // INTLUNICODE
}
m_pAwtDC->Unlock(this);
return size.cx;
}
//-------------------------------------------------------------------------
//
// Draw an image
//
//-------------------------------------------------------------------------
void AwtGraphics::DrawImage(AwtImage *pImage, long nX, long nY, Hjava_awt_Color *c)
{
HBRUSH hOldBrush = NULL;
HBRUSH hBrush = NULL;
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
if (m_rop == R2_XORPEN) {
hBrush = ::CreateSolidBrush(m_xorcolor);
hOldBrush = (HBRUSH) ::SelectObject(hDC, hBrush);
}
// Check to see if there is a shared DC where graphics operations
// have been done. This is the only way of distinguishing a image with
// graphics to be done from the one which has a DIB to act as a image consumer
if (pImage->m_pAwtDC != NULL)
{
//REMIND: what are the bits to be set here?
pImage->m_pAwtDC->Lock();
HDC hMemDC = pImage->m_pAwtDC->GetDC();
if (hMemDC != NULL)
{
// See comment at top of AwtImage::Draw about BitBlt rop codes...
VERIFY(::BitBlt(hDC, TX(nX), TY(nY),
pImage->m_nDstW, pImage->m_nDstH,
hMemDC, 0, 0,
(m_rop == R2_XORPEN) ? 0x00960000L : SRCCOPY));
::GdiFlush();
}
pImage->m_pAwtDC->Unlock();
}
else
{
// This image is a image consumer and all of the image
// data should be ready by now.
pImage->Draw(hDC, TX(nX), TY(nY), (m_rop == R2_XORPEN), m_xorcolor, hBrush, (HColor *)c);
::GdiFlush();
}
//
// Free the xor brush if one was created...
//
if (hBrush) {
::SelectObject(hDC, hOldBrush);
VERIFY( ::DeleteObject(hBrush) );
}
}
// REMIND: select back the appropriate stuff
m_pAwtDC->Unlock(this);
}
//-------------------------------------------------------------------------
//
// Copy an area identified by (nX, nY, nW, nH) into (nX + nDX, nY + nDY, nW, nH)
// no stretching involved
//
//-------------------------------------------------------------------------
void AwtGraphics::CopyArea(long nDX, long nDY, long nX, long nY, long nW, long nH)
{
if (nW > 0 && nH > 0) {
HDC hDC = m_pAwtDC->Lock(this);
if (hDC != NULL) {
long dX = nDX;
long dY = nDY;
RECT rectSrc;
RECT rectDst;
RECT rectInvalid;
HRGN hRgn;
// calculate source rectangle
rectSrc.left = TX(nX);
rectSrc.top = TY(nY);
rectSrc.right = TX(nX+nW);
rectSrc.bottom = TY(nY+nH);
rectDst.left = rectSrc.left + nDX;
rectDst.top = rectSrc.top + nDY;
rectDst.right = rectSrc.right + nDX;
rectDst.bottom = rectSrc.bottom + nDY;
hRgn = ::CreateRectRgn(0, 0, 0, 0);
VERIFY(::ScrollDC(hDC, dX, dY, &rectSrc, &m_ClipRect, hRgn, &rectInvalid));
//\\//\\//\\//......
::SubtractRect(&rectDst, &rectSrc, &rectDst);
if (!EqualRect(&rectDst, &rectInvalid))
m_pAwtDC->InvalidateRgn(hRgn);
if (hRgn) {
::DeleteObject(hRgn);
}
}
m_pAwtDC->Unlock(this);
}
}
#ifdef DEBUG_CONSOLE
char* AwtGraphics::PrintStatus()
{
char* buffer = new char[1024];
wsprintf(buffer, "**** [%lx] Graphics Status: ****\r\n\tClipRect = %d, %d, %d, %d\r\n\tBrush = %lx\r\n\tPen = %lx\r\n****************\r\n",
*(long*)this,
m_ClipRect.left,
m_ClipRect.top,
m_ClipRect.right,
m_ClipRect.bottom,
(m_pBrush) ? m_pBrush->GetColor() : -1L,
(m_pPen) ? m_pPen->GetColor() : -1L);
return buffer;
}
#endif
extern "C" {
void sun_awt_windows_WGraphics_createFromComponent(HWGraphics *self, HWComponentPeer *canvas)
{
AwtGraphics *pNewGraphics;
CHECK_NULL(self, "self is NULL");
CHECK_NULL(canvas, "ComponentPeer is null.");
pNewGraphics = new AwtGraphics(self, canvas);
CHECK_ALLOCATION(pNewGraphics);
}
void sun_awt_windows_WGraphics_createFromGraphics(HWGraphics *self, HWGraphics *g)
{
AwtGraphics *pNewGraphics;
AwtGraphics *pFromGraphics;
CHECK_GRAPHICS_PEER(g);
CHECK_NULL(self, "self is NULL");
// invoke the copy constructor for the graphic to be cloned
pFromGraphics = GET_OBJ_FROM_GRAPHICS(g);
pNewGraphics = new AwtGraphics(*pFromGraphics);
CHECK_ALLOCATION(pNewGraphics);
// update the values we don't want from the copy constructor (like the peer)
pNewGraphics->InitCopy(self);
}
void
sun_awt_windows_WGraphics_imageCreate(HWGraphics *self,
HImageRepresentation *ir)
{
AwtGraphics *pNewGraphics;
CHECK_NULL(self, "self is NULL");
CHECK_NULL(ir, "ImageRepresentation is null.");
pNewGraphics = new AwtGraphics(self, ir);
CHECK_ALLOCATION(pNewGraphics);
}
void
sun_awt_windows_WGraphics_pSetFont(HWGraphics *self, Hjava_awt_Font *font)
{
CHECK_GRAPHICS_PEER(self);
CHECK_NULL(font, "FontPeer is null.");
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->SetFont(font);
}
void
sun_awt_windows_WGraphics_pSetForeground(HWGraphics *self, Hjava_awt_Color *c)
{
CHECK_GRAPHICS_PEER(self);
CHECK_NULL(c, "Colorpeer is null.");
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
DWORD javaColor = c->obj->value;
COLORREF color = PALETTERGB((javaColor>>16)& 0xff,
(javaColor>>8) & 0xff,
(javaColor) & 0xff);
pGraphics->SetColor(color);
}
void
sun_awt_windows_WGraphics_dispose(HWGraphics *self)
{
CHECK_NULL(self, "self is null.");
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
if (pGraphics) {
pGraphics->Dispose();
}
}
void
sun_awt_windows_WGraphics_drawString(HWGraphics *self,
Hjava_lang_String *text,
long x,
long y)
{
CHECK_GRAPHICS_PEER(self);
CHECK_NULL(text, "StringPeer is null.");
#ifdef INTLUNICODE
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
WinCompStr* pwStr = new WinCompStr(text);
CHECK_ALLOCATION(pwStr);
pGraphics->DrawString(pwStr, x, y);
delete pwStr;
#else // INTLUNICODE
char *buffer;
int32_t len;
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
len = javaStringLength(text);
buffer = (char *)malloc(len + 1);
CHECK_ALLOCATION(buffer);
javaString2CString(text, buffer, len + 1);
pGraphics->DrawString(buffer, x, y);
free(buffer);
#endif // INTLUNICODE
}
long
sun_awt_windows_WGraphics_drawStringWidth( HWGraphics *self,
Hjava_lang_String *text,
long x,
long y)
{
long result = -1L;
CHECK_GRAPHICS_PEER_AND_RETURN(self, result);
CHECK_NULL_AND_RETURN(text, "StringPeer is null.", result);
#ifdef INTLUNICODE
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
WinCompStr* pwStr = new WinCompStr(text);
CHECK_ALLOCATION_AND_RETURN(pwStr, result);
result = pGraphics->DrawStringWidth(pwStr, x, y);
delete pwStr;
#else // INTLUNICODE
int32_t len;
char *buffer;
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
len = javaStringLength(text);
buffer = (char *)malloc(len + 1);
CHECK_ALLOCATION_AND_RETURN(buffer, result);
javaString2CString(text, buffer, len + 1);
result = pGraphics->DrawStringWidth(buffer, x, y);
free(buffer);
#endif // INTLUNICODE
return result;
}
void
sun_awt_windows_WGraphics_drawChars( HWGraphics *self,
HArrayOfChar *text,
long offset,
long length,
long x,
long y)
{
CHECK_GRAPHICS_PEER(self);
CHECK_NULL(text, "StringPeer is null.");
CHECK_BOUNDARY_CONDITION((offset < 0 || length < 0 || offset + length > (long)obj_length(text)),
"ArrayIndexOutOfBoundsException");
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
WCHAR *pSrc= unhand(text)->body + offset;
#ifdef INTLUNICODE
WCHAR *buffer;
buffer = (WCHAR *)malloc(sizeof(WCHAR)*(length + 1));
CHECK_ALLOCATION(buffer);
memcpy(buffer, pSrc, sizeof(WCHAR)*length);
buffer[length] = 0;
WinCompStr *pwStr = new WinCompStr(buffer);
free(buffer);
CHECK_ALLOCATION(pwStr);
pGraphics->DrawString(pwStr, x, y);
delete pwStr;
#else // INTLUNICODE
char *buffer;
long i;
buffer = (char *)malloc(length + 1);
CHECK_ALLOCATION(buffer);
for (i=0; i<length; i++) {
buffer[i] = (char)pSrc[i];
}
buffer[length] = 0;
pGraphics->DrawString(buffer, x, y);
free(buffer);
#endif // INTLUNICODE
}
long
sun_awt_windows_WGraphics_drawCharsWidth( HWGraphics *self,
HArrayOfChar *text,
long offset,
long length,
long x,
long y)
{
long result = -1L;
CHECK_GRAPHICS_PEER_AND_RETURN(self, result);
CHECK_NULL_AND_RETURN(text, "StringPeer is null.", result);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
WCHAR *pSrc= unhand(text)->body + offset;
#ifdef INTLUNICODE
WCHAR *buffer;
buffer = (WCHAR *)malloc(sizeof(WCHAR)*(length + 1));
CHECK_ALLOCATION_AND_RETURN(buffer, result);
memcpy(buffer, pSrc, sizeof(WCHAR)*length);
buffer[length] = 0;
WinCompStr *pwStr = new WinCompStr(buffer);
free(buffer);
CHECK_ALLOCATION_AND_RETURN(pwStr, result);
result = pGraphics->DrawStringWidth(pwStr, x, y);
delete pwStr;
#else // INTLUNICODE
char *buffer;
long i;
buffer = (char *)malloc(length + 1);
CHECK_ALLOCATION_AND_RETURN(buffer, result);
for (i=0; i<length; i++) {
buffer[i] = (char)pSrc[i];
}
buffer[length] = 0;
result = pGraphics->DrawStringWidth(buffer, x, y);
free(buffer);
#endif // INTLUNICODE
return result;
}
void
sun_awt_windows_WGraphics_drawBytes( HWGraphics *self,
HArrayOfByte *text,
long offset,
long length,
long x,
long y)
{
CHECK_GRAPHICS_PEER(self);
CHECK_NULL(text, "StringPeer is null.");
CHECK_BOUNDARY_CONDITION((offset < 0 || length < 0 || offset + length > (long)obj_length(text)),
"ArrayIndexOutOfBoundsException");
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
char *pSrc= unhand(text)->body + offset;
#ifdef INTLUNICODE
WCHAR *buffer;
buffer = (WCHAR*) malloc(sizeof(WCHAR)*sizeof(length + 1));
CHECK_ALLOCATION(buffer);
for(long i = 0; i < length ; i++)
buffer[i] = (WCHAR) (0x00ff & pSrc[i]);
buffer[length] = 0;
WinCompStr *pwStr = new WinCompStr(buffer);
free(buffer);
CHECK_ALLOCATION(pwStr);
pGraphics->DrawString(pwStr, x, y);
delete pwStr;
#else // INTLUNICODE
char *buffer;
buffer = (char *)malloc(length + 1);
CHECK_ALLOCATION(buffer);
memcpy(buffer, pSrc, length);
buffer[length] = 0;
pGraphics->DrawString(buffer, x, y);
free(buffer);
#endif // INTLUNICODE
}
long
sun_awt_windows_WGraphics_drawBytesWidth( HWGraphics *self,
HArrayOfByte *text,
long offset,
long length,
long x,
long y)
{
long result = -1L;
CHECK_GRAPHICS_PEER_AND_RETURN(self, result);
CHECK_NULL_AND_RETURN(text, "StringPeer is null.", result);
CHECK_BOUNDARY_CONDITION_RETURN((offset < 0 || length < 0 || offset + length > (long)obj_length(text)),
"ArrayIndexOutOfBoundsException", result);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
char *pSrc= unhand(text)->body + offset;
#ifdef INTLUNICODE
WCHAR *buffer;
buffer = (WCHAR*) malloc(sizeof(WCHAR)*sizeof(length + 1));
CHECK_ALLOCATION_AND_RETURN(buffer, result);
for(long i = 0; i < length ; i++)
buffer[i] = (WCHAR) (0x00ff & pSrc[i]);
buffer[length] = 0;
WinCompStr *pwStr = new WinCompStr(buffer);
free(buffer);
CHECK_ALLOCATION_AND_RETURN(pwStr, result);
result = pGraphics->DrawStringWidth(pwStr, x, y);
delete pwStr;
#else // INTLUNICODE
char *buffer;
buffer = (char *)malloc(length + 1);
CHECK_ALLOCATION_AND_RETURN(buffer, result);
memcpy(buffer, pSrc, length);
buffer[length] = 0;
result = pGraphics->DrawStringWidth(buffer, x, y);
free(buffer);
#endif // INTLUNICODE
return result;
}
void
sun_awt_windows_WGraphics_drawLine( HWGraphics *self,
long x1, long y1,
long x2, long y2)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->DrawLine(x1, y1, x2, y2);
}
void
sun_awt_windows_WGraphics_clearRect( HWGraphics *self,
long x, long y,
long w, long h)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->ClearRect(x, y, w, h);
}
void
sun_awt_windows_WGraphics_fillRect( HWGraphics *self,
long x, long y,
long w, long h)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->FillRect(x, y, w, h);
}
void
sun_awt_windows_WGraphics_drawRect( HWGraphics *self,
long x, long y,
long w, long h)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->DrawRect(x, y, w, h);
}
void
sun_awt_windows_WGraphics_drawRoundRect( HWGraphics *self,
long x, long y, long w, long h,
long arcWidth, long arcHeight)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->RoundRect(x, y, w, h, arcWidth, arcHeight);
}
void
sun_awt_windows_WGraphics_fillRoundRect( HWGraphics *self,
long x, long y, long w, long h,
long arcWidth, long arcHeight)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->FillRoundRect(x, y, w, h, arcWidth, arcHeight);
}
void
sun_awt_windows_WGraphics_setPaintMode( HWGraphics *self)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
Hjava_awt_Color *fg = unhand(self)->foreground;
if (fg) {
DWORD javaColor = fg->obj->value;
COLORREF fgcolor = PALETTERGB((javaColor>>16)& 0xff,
(javaColor>>8) & 0xff,
(javaColor) & 0xff);
pGraphics->SetRop(R2_COPYPEN, fgcolor, RGB(0, 0, 0));
}
}
void
sun_awt_windows_WGraphics_setXORMode( HWGraphics *self,
Hjava_awt_Color *c)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
Hjava_awt_Color *fg = unhand(self)->foreground;
if (fg) {
DWORD javaColor, xorColor;
COLORREF color, fgcolor;
javaColor = fg->obj->value;
xorColor = c->obj->value;
color = PALETTERGB((xorColor>>16)& 0xff,
(xorColor>>8) & 0xff,
(xorColor) & 0xff);
fgcolor = PALETTERGB((javaColor>>16)& 0xff,
(javaColor>>8) & 0xff,
(javaColor) & 0xff);
pGraphics->SetRop(R2_XORPEN, fgcolor, color);
}
}
void
sun_awt_windows_WGraphics_clipRect( HWGraphics *self,
long x, long y,
long w, long h)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->SetClipRect(x, y, w, h);
}
void
sun_awt_windows_WGraphics_getClipRect( HWGraphics *self,
Hjava_awt_Rectangle *clip)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
RECT rect;
CHECK_BOUNDARY_CONDITION((clip == 0), "null clip");
pGraphics->GetClipRect(&rect);
unhand(clip)->x = rect.left;
unhand(clip)->y = rect.top;
unhand(clip)->width = rect.right - rect.left;
unhand(clip)->height = rect.bottom - rect.top;
}
void
sun_awt_windows_WGraphics_copyArea( HWGraphics *self,
long x, long y,
long width, long height,
long dx, long dy)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->CopyArea(dx, dy, x, y, width, height);
}
static POINT *
transformPoints(HWGraphics *self, HArrayOfInt *xpoints, HArrayOfInt *ypoints,
long npoints)
{
ArrayOfInt *xpoints_array = unhand(xpoints);
ArrayOfInt *ypoints_array = unhand(ypoints);
POINT *points;
int i;
CHECK_BOUNDARY_CONDITION_RETURN(((int)obj_length(ypoints) < npoints || (int)obj_length(xpoints) < npoints),
"IllegalArgumentException", NULL);
points = (POINT*)malloc(sizeof(POINT) * npoints);
CHECK_ALLOCATION_AND_RETURN(points, NULL);
for (i=0; i<npoints; ++i) {
points[i].x = (xpoints_array->body)[i];
points[i].y = (ypoints_array->body)[i];
}
return points;
}
void
sun_awt_windows_WGraphics_drawPolygon( HWGraphics *self,
HArrayOfInt *xpoints,
HArrayOfInt *ypoints,
long npoints)
{
CHECK_GRAPHICS_PEER(self);
CHECK_BOUNDARY_CONDITION((xpoints == NULL || ypoints == NULL),
"NullPointerException");
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
POINT *points = transformPoints(self, xpoints, ypoints, npoints);
if (points) {
pGraphics->Polygon(points, npoints);
free(points);
}
}
void
sun_awt_windows_WGraphics_fillPolygon( HWGraphics *self,
HArrayOfInt *xpoints,
HArrayOfInt *ypoints,
long npoints)
{
CHECK_GRAPHICS_PEER(self);
CHECK_BOUNDARY_CONDITION((xpoints == NULL || ypoints == NULL),
"NullPointerException");
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
POINT *points = transformPoints(self, xpoints, ypoints, npoints);
if (points) {
pGraphics->FillPolygon(points, npoints);
free(points);
}
}
void
sun_awt_windows_WGraphics_drawOval( HWGraphics *self,
long x, long y, long w, long h)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->Ellipse(x, y, w, h);
}
void
sun_awt_windows_WGraphics_fillOval( HWGraphics *self,
long x, long y, long w, long h)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
pGraphics->FillEllipse(x, y, w, h);
}
void
sun_awt_windows_WGraphics_drawArc( HWGraphics *self,
long x, long y, long w, long h,
long startAngle, long endAngle)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
if (endAngle != 0) {
pGraphics->Arc(x, y, w, h, startAngle, endAngle);
}
}
void
sun_awt_windows_WGraphics_fillArc( HWGraphics *self,
long x, long y, long w, long h,
long startAngle, long endAngle)
{
CHECK_GRAPHICS_PEER(self);
AwtGraphics *pGraphics = GET_OBJ_FROM_GRAPHICS(self);
if (endAngle != 0) {
pGraphics->FillArc(x, y, w, h, startAngle, endAngle);
}
}
}; // end of extern "C"