📄 graph.cxx
字号:
/*
* graph.cxx
*
* Graphics classes implementation.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (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 Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: graph.cxx,v $
* Revision 1.27 1999/08/17 03:46:41 robertj
* Fixed usage of inlines in optimised version.
*
* Revision 1.26 1998/12/12 00:44:03 robertj
* Added functions for user request on printing selection only.
* Fixed transfer of start and end pages from PPrintDialog.
*
* Revision 1.25 1998/10/15 11:32:55 robertj
* New memory leak detection system.
*
* Revision 1.24 1998/09/24 03:42:42 robertj
* Added open software license.
*
* Revision 1.23 1998/09/07 14:34:01 robertj
* Fixed setting of print info parameters from DEVMODE structure.
*
* Revision 1.22 1998/09/04 07:01:38 robertj
* Added a lot of DEVMODE infor for win95 to propagate from PrintDlg to PPrintCanvas.
*
* Revision 1.21 1998/01/26 00:20:42 robertj
* Fixed creation of pattern bitmaps (word alignment).
*
* Revision 1.20 1997/04/27 05:50:29 robertj
* DLL support.
*
* Revision 1.19 1996/10/31 12:39:56 robertj
* Added RCS keywords.
*
*/
#include <pwlib.h>
#if !P_USE_INLINES
#include <pwlib/graphics.inl>
#endif
#define new PNEW
///////////////////////////////////////////////////////////////////////////////
PPoint::PPoint(DWORD dw)
{
#if defined(_WIN32)
POINTS ps = MAKEPOINTS(dw);
p.x = ps.x;
p.y = ps.y;
#else
p = MAKEPOINT(dw);
#endif
}
///////////////////////////////////////////////////////////////////////////////
PRect::PRect(PORDINATE x, PORDINATE y, PDIMENSION dx, PDIMENSION dy)
{
r.left = x;
r.top = y;
r.right = x + dx;
r.bottom = y + dy;
}
PRect::PRect(const PDim & dim)
{
r.left = r.top = 0;
r.right = dim.Width();
r.bottom = dim.Height();
}
PRect::PRect(const PPoint & p1, const PPoint & p2)
{
if (p1.X() > p2.X()) {
r.left = p2.X();
r.right = p1.X();
}
else {
r.left = p1.X();
r.right = p2.X();
}
if (p1.Y() > p2.Y()) {
r.top = p2.Y();
r.bottom = p1.Y();
}
else {
r.top = p1.Y();
r.bottom = p2.Y();
}
}
PRect::PRect(const PPoint & topLeft, const PDim & dim)
{
r.left = topLeft.X();
r.top = topLeft.Y();
r.right = topLeft.X() + dim.Width();
r.bottom = topLeft.Y() + dim.Height();
}
PObject::Comparison PRect::Compare(const PObject & obj) const
{
PAssert(obj.IsDescendant(PRect::Class()), PInvalidCast);
return EqualRect(&r, &((const PRect &)obj).r) ? EqualTo : GreaterThan;
}
void PRect::SetX(PORDINATE nx)
{
PORDINATE diff = nx - (PORDINATE)r.left;
r.left = nx;
r.right += diff;
}
void PRect::SetY(PORDINATE ny)
{
PORDINATE diff = ny - (PORDINATE)r.top;
r.top = ny;
r.bottom += diff;
}
void PRect::SetTop(PORDINATE t)
{
r.top = t;
if (t > r.bottom)
r.bottom = t;
}
void PRect::SetLeft(PORDINATE l)
{
r.left = l;
if (l > r.right)
r.right = l;
}
void PRect::SetBottom(PORDINATE b)
{
r.bottom = b;
if (b < r.top)
r.top = b;
}
void PRect::SetRight(PORDINATE rt)
{
r.right = rt;
if (rt < r.left)
r.left = rt;
}
PRect PRect::Intersection(const PRect & rect) const
{
PRect newRect;
IntersectRect(newRect, &r, rect);
return newRect;
}
PRect PRect::Union(const PRect & rect) const
{
PRect newRect;
UnionRect(newRect, &r, rect);
return newRect;
}
///////////////////////////////////////////////////////////////////////////////
PRegion::PRegion(const PRect & rect)
{
hRegion = CreateRectRgnIndirect(rect);
PAssertNULL(hRegion);
}
PRegion::PRegion(const PRegion & rgn)
{
hRegion = CreateRectRgn(0, 0, 0, 0);
PAssertNULL(hRegion);
PAssertOS(CombineRgn(hRegion, rgn.hRegion, NULL, RGN_COPY) != ERROR);
}
PRegion & PRegion::operator=(const PRegion & rgn)
{
PAssertOS(DeleteObject(hRegion));
hRegion = CreateRectRgn(0, 0, 0, 0);
PAssertNULL(hRegion);
PAssertOS(CombineRgn(hRegion, rgn.hRegion, NULL, RGN_COPY) != ERROR);
return *this;
}
PObject::Comparison PRegion::Compare(const PObject & obj) const
{
PAssert(obj.IsDescendant(PRegion::Class()), PInvalidCast);
return EqualRgn(hRegion, ((const PRegion &)obj).hRegion)
? EqualTo : GreaterThan;
}
void PRegion::Add(const PRect & rect)
{
HRGN hRgnNew = CreateRectRgn(0, 0, 0, 0);
HRGN hRgnRect = CreateRectRgnIndirect(rect);
PAssertNULL(hRgnNew);
PAssertNULL(hRgnRect);
PAssertOS(CombineRgn(hRgnNew, hRegion, hRgnRect, RGN_OR) != ERROR);
PAssertOS(DeleteObject(hRgnRect));
PAssertOS(DeleteObject(hRegion));
hRegion = PAssertNULL(hRgnNew);
}
void PRegion::Add(const PRegion & rgn)
{
HRGN hRgnNew = CreateRectRgn(0, 0, 0, 0);
PAssertNULL(hRgnNew);
PAssertOS(CombineRgn(hRgnNew, hRegion, rgn.hRegion, RGN_OR) != ERROR);
PAssertOS(DeleteObject(hRegion));
hRegion = PAssertNULL(hRgnNew);
}
BOOL PRegion::OverlapsRect(const PRect & rect) const
{
HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
HRGN hRect = CreateRectRgnIndirect(rect);
PAssertNULL(hRgn);
PAssertNULL(hRect);
PAssertOS(CombineRgn(hRgn, hRect, hRegion, RGN_AND) != ERROR);
PAssertOS(DeleteObject(hRect));
RECT dummy;
BOOL empty = GetRgnBox(PAssertNULL(hRgn), &dummy) == NULLREGION;
PAssertOS(DeleteObject(hRgn));
return !empty;
}
BOOL PRegion::IsEmpty() const
{
RECT dummy;
return GetRgnBox(hRegion, &dummy) == NULLREGION;
}
PRect PRegion::GetBounds() const
{
PRect rect;
GetRgnBox(hRegion, rect);
return rect;
}
PRegion PRegion::Intersection(const PRegion & rgn) const
{
HRGN hRgnNew = CreateRectRgn(0, 0, 0, 0);
PAssertNULL(hRgnNew);
PAssertOS(CombineRgn(hRgnNew, hRegion, rgn.hRegion, RGN_AND) != ERROR);
return PRegion(PAssertNULL(hRgnNew));
}
PRegion PRegion::Union(const PRegion & rgn) const
{
HRGN hRgnNew = CreateRectRgn(0, 0, 0, 0);
PAssertNULL(hRgnNew);
PAssertOS(CombineRgn(hRgnNew, hRegion, rgn.hRegion, RGN_OR) != ERROR);
return PRegion(PAssertNULL(hRgnNew));
}
///////////////////////////////////////////////////////////////////////////////
PColour::PColour(const PString & description)
{
memset(component, 0, sizeof(component));
PStringArray compstr = description.Tokenise(" ,");
switch (compstr.GetSize()) {
case 4 :
component[AlphaComponent] = (BYTE)compstr[3].AsInteger();
// Then execute next case
case 3 :
component[BlueComponent] = (BYTE)compstr[2].AsInteger();
// Then execute next case
case 2 :
component[GreenComponent] = (BYTE)compstr[1].AsInteger();
// Then execute next case
case 1 :
component[RedComponent] = (BYTE)compstr[0].AsInteger();
}
}
PString PColour::GetDescription() const
{
return psprintf("%u,%u,%u,%u", GetRed(), GetGreen(), GetBlue(), GetAlpha());
}
PColour & PColour::FromCOLORREF(COLORREF col)
{
component[RedComponent] = GetRValue(col);
component[GreenComponent] = GetGValue(col);
component[BlueComponent] = GetBValue(col);
component[AlphaComponent] = 0xff;
return *this;
}
//////////////////////////////////////////////////////////////////////////////
#ifdef NOTYET
PRealColour::PRealColour()
{
HDC hDC = CreateCompatibleDC(NULL);
FromCOLORREF(GetNearestColor(hDC, ToCOLORREF()));
DeleteDC(hDC);
}
PRealColour::PRealColour(const PColour & colour)
: PColour(colour)
{
if (colour.GetAlpha() != 0) {
HDC hDC = CreateCompatibleDC(NULL);
FromCOLORREF(GetNearestColor(hDC, colour.ToCOLORREF()));
DeleteDC(hDC);
}
}
#endif
PRealColour::PRealColour(PCanvas & canvas, const PColour & colour)
: PColour(colour)
{
if (colour.GetAlpha() != 0)
FromCOLORREF(GetNearestColor(canvas.GetHDC(), colour.ToCOLORREF()));
}
//////////////////////////////////////////////////////////////////////////////
PPalette::PPalette()
{
LOGPALETTE logPal;
logPal.palVersion = 0x300;
logPal.palNumEntries = 1;
logPal.palPalEntry[0].peRed = 0;
logPal.palPalEntry[0].peGreen = 0;
logPal.palPalEntry[0].peBlue = 0;
logPal.palPalEntry[0].peFlags = 0;
hPalette = CreatePalette(&logPal);
PAssertNULL(hPalette);
}
void PPalette::DestroyContents()
{
PAssertOS(DeleteObject(hPalette));
}
PObject::Comparison PPalette::Compare(const PObject & obj) const
{
PAssert(obj.IsDescendant(PPalette::Class()), PInvalidCast);
return hPalette == ((const PPalette &)obj).hPalette ? EqualTo : GreaterThan;
}
PINDEX PPalette::AddColour(const PColour & colour)
{
PINDEX count = GetSize();
PAssertOS(SetColour(count, colour));
return count;
}
BOOL PPalette::RemoveColour(const PColour & colour)
{
PINDEX index = GetNearestPaletteIndex(hPalette, colour.ToCOLORREF());
if (colour != GetColour(index))
return FALSE;
return RemoveColour(index);
}
BOOL PPalette::RemoveColour(PINDEX index)
{
PINDEX numColours = GetSize()-1;
if (index > numColours)
return FALSE;
PINDEX colourCount = numColours - index;
if (colourCount > 0) {
PALETTEENTRY * entries = new PALETTEENTRY[colourCount];
GetPaletteEntries(hPalette, index+1, colourCount, entries);
SetPaletteEntries(hPalette, index, colourCount, entries);
delete [] entries;
}
return ResizePalette(hPalette, numColours);
}
BOOL PPalette::HasColour(const PColour & colour) const
{
return GetColour(GetIndex(colour)) == colour;
}
PINDEX PPalette::GetIndex(const PColour & colour) const
{
return GetNearestPaletteIndex(hPalette, colour.ToCOLORREF());
}
PColour PPalette::GetColour(PINDEX index) const
{
PALETTEENTRY entry;
GetPaletteEntries(hPalette, index, 1, &entry);
return PColour(entry.peRed, entry.peGreen, entry.peBlue);
}
BOOL PPalette::SetColour(PINDEX index, const PColour & colour)
{
if (!SetMinSize(index+1))
return FALSE;
PALETTEENTRY entry;
entry.peRed = colour.GetRed();
entry.peGreen = colour.GetGreen();
entry.peBlue = colour.GetBlue();
entry.peFlags = 0;
SetPaletteEntries(hPalette, index, 1, &entry);
return TRUE;
}
PINDEX PPalette::GetSize() const
{
short count;
PAssertOS(GetObject(hPalette, sizeof(count), (LPSTR)&count)==sizeof(count));
return count;
}
BOOL PPalette::SetSize(PINDEX size)
{
return ResizePalette(hPalette, size);
}
///////////////////////////////////////////////////////////////////////////////
PRealFont::PRealFont()
: PFont(PApplication::Current().GetSystemFont())
{
Construct(CreateCompatibleDC(NULL));
}
PRealFont::PRealFont(const PFont & font)
: PFont(font)
{
Construct(CreateCompatibleDC(NULL));
}
PRealFont::PRealFont(PCanvas & canvas, const PFont & font)
: PFont(font)
{
Construct(CreateCompatibleDC(canvas.GetHDC()));
}
PRealFont::PRealFont(HFONT hFont)
: PFont("", 0)
{
if (hFont == NULL)
hFont = (HFONT)GetStockObject(SYSTEM_FONT);
HDC dc = CreateCompatibleDC(NULL);
deviceResY = (PDIMENSION)GetDeviceCaps(dc, LOGPIXELSY);
PAssert(deviceResY != 0, PInvalidParameter);
LOGFONT lf;
GetObject(hFont, sizeof(lf), (LPSTR)&lf);
facename = PCaselessString(lf.lfFaceName);
size = PixelsToPointsY((PDIMENSION)PABS(lf.lfHeight));
styles = Regular;
if (lf.lfWeight > FW_NORMAL)
styles |= Bold;
if (lf.lfItalic)
styles |= Italic;
if (lf.lfUnderline)
styles |= Underline;
Construct(dc);
}
void PRealFont::Construct(HDC dc)
{
SetMapMode(PAssertNULL(dc), MM_TEXT);
deviceResX = (PDIMENSION)GetDeviceCaps(dc, LOGPIXELSX);
PAssert(deviceResX != 0, PInvalidParameter);
deviceResY = (PDIMENSION)GetDeviceCaps(dc, LOGPIXELSY);
PAssert(deviceResY != 0, PInvalidParameter);
HFONT hFont = GetHFONT();
HGDIOBJ oldFont = SelectObject(dc, hFont);
TEXTMETRIC t;
GetTextMetrics(dc, &t);
PAssertOS(SelectObject(dc, PAssertNULL(oldFont)) != NULL);
PAssertOS(DeleteObject(hFont));
PAssertOS(DeleteDC(dc));
size = PixelsToPointsY((PDIMENSION)t.tmHeight);
height = PixelsToPointsY((PDIMENSION)(t.tmHeight + t.tmExternalLeading));
avgWidth = PixelsToPointsX((PDIMENSION)t.tmAveCharWidth);
maxWidth = PixelsToPointsX((PDIMENSION)t.tmMaxCharWidth);
ascent = PixelsToPointsY((PDIMENSION)t.tmAscent);
descent = PixelsToPointsY((PDIMENSION)t.tmDescent);
leading = PixelsToPointsY((PDIMENSION)t.tmExternalLeading);
styles = Regular;
if (t.tmWeight > FW_NORMAL)
styles |= Bold;
if (t.tmItalic)
styles |= Italic;
if (t.tmUnderlined)
styles |= Underline;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -