graphics.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:51k
- /*
- * graphics.cxx
- *
- * Graphics, Canvas and drawing classes.
- *
- * 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: graphics.cxx,v $
- * Revision 1.38 1999/09/05 14:39:22 robertj
- * GNU 2.95 compatibility
- *
- * Revision 1.37 1998/10/16 11:08:15 robertj
- * GNU compatibility.
- *
- * Revision 1.36 1998/09/23 06:29:38 robertj
- * Added open source copyright license.
- *
- * Revision 1.35 1998/09/22 15:06:38 robertj
- * Added delayed HDC creation in PDrawCanvas.
- *
- * Revision 1.34 1998/03/20 03:14:11 robertj
- * Added function to get physical bounds of canvas. Allows to scale drawing.
- *
- * Revision 1.33 1997/04/27 05:50:21 robertj
- * DLL support.
- *
- * Revision 1.32 1996/11/04 03:39:34 robertj
- * Fixed warning about uninitialised variable.
- *
- * Revision 1.31 1996/07/15 10:34:21 robertj
- * Fixed uninitialised variable.
- * Changed endian classes to be memory mapped.
- *
- * Revision 1.30 1996/06/28 13:17:37 robertj
- * Removed integer size mismatch warnings
- *
- * Revision 1.29 1996/06/17 11:42:16 robertj
- * Creation of a default palette for 24 bit images.
- *
- * Revision 1.28 1996/01/28 02:52:02 robertj
- * Added assert into all Compare functions to assure comparison between compatible objects.
- *
- * Revision 1.27 1995/12/10 11:38:21 robertj
- * Removed eatwhite() as not in GNU library.
- * Fixed automatic operator translation incompatibility amongst compilers.
- *
- * Revision 1.26 1995/11/21 11:52:35 robertj
- * Improved streams compatibility.
- * Added 16 bit windows support for bitmap reading.
- *
- * Revision 1.24 1995/10/14 15:09:57 robertj
- * Changed return values to references for efficency.
- *
- * Revision 1.23 1995/08/12 22:33:42 robertj
- * Changed DrawBevelledRect() so does not change background colour.
- *
- * Revision 1.22 1995/04/25 11:29:20 robertj
- * Fixed Borland compiler warnings.
- *
- * Revision 1.21 1995/02/22 10:50:36 robertj
- * Changes required for compiling release (optimised) version.
- *
- * Revision 1.20 1995/01/27 11:13:43 robertj
- * Added pattern origin.
- *
- * Revision 1.19 1995/01/21 05:14:31 robertj
- * Added origin changing function, simpler than setting rectangles.
- * Fixed rounding error for negative numbers in coordinate system conversions.
- *
- * Revision 1.18 1995/01/06 10:43:59 robertj
- * Changed PRealFont usage from pointer to reference.
- *
- * Revision 1.17 1994/12/14 11:17:17 robertj
- * Changed PDIMENSION to be unsigned causing untold number of changes.
- *
- * Revision 1.16 1994/12/12 10:07:15 robertj
- * Made depth member of PPixels and removed virtual function.
- *
- * Revision 1.15 1994/12/05 11:34:25 robertj
- * Major rewrite of images, pictures and pixmaps.
- * Renamed PPict, PPixels and PImage to make sure all uses are found.
- *
- * Revision 1.14 1994/11/01 11:57:47 robertj
- * Removed lots of signed/unsigned mismatch warnings.
- *
- * Revision 1.13 1994/10/30 11:51:29 robertj
- * Added ability to change interactor foreground colour on a per interactor basis.
- *
- * Revision 1.12 1994/10/23 03:45:22 robertj
- * Added multiply and divide operators for points and dims.
- * Changed PPixels to have subclasses for each pixel size and be fully polymorhic.
- *
- * Revision 1.11 1994/08/21 23:43:02 robertj
- * Optimisation of DrawString() for transparent background.
- *
- * Revision 1.10 1994/08/01 03:41:24 robertj
- * Use of PNEW instead of new for heap debugging. Need undef for Unix end.
- *
- * Revision 1.9 1994/07/27 05:58:07 robertj
- * Synchronisation.
- *
- * Revision 1.8 1994/06/25 11:55:15 robertj
- * Unix version synchronisation.
- *
- * Revision 1.7 1994/04/20 12:17:44 robertj
- * assert changes
- *
- * Revision 1.6 1994/03/07 07:47:00 robertj
- * Major upgrade
- *
- * Revision 1.5 1994/01/03 04:42:23 robertj
- * Mass changes to common container classes and interactors etc etc etc.
- *
- * Revision 1.4 1993/12/31 06:53:02 robertj
- * Made inlines optional for debugging purposes.
- *
- * Revision 1.3 1993/12/15 23:41:27 robertj
- * Removed triadic conditional expressions as GCC can't do it.
- *
- * Revision 1.2 1993/12/04 05:23:25 robertj
- * More implementation
- *
- * Revision 1.1 1993/11/20 17:26:28 robertj
- * Initial revision
- */
- #include <pwlib.h>
- #include <ctype.h>
- #define new PNEW
- ///////////////////////////////////////////////////////////////////////////////
- // PDim
- #if defined(_PDIM)
- PObject * PDim::Clone() const
- {
- return new PDim(width, height);
- }
- PObject::Comparison PDim::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PDim::Class()), PInvalidCast);
- const PDim & other = (const PDim &)obj;
- if (height == other.height && width == other.width)
- return EqualTo;
- else
- return width*height < other.width*other.height ? LessThan : GreaterThan;
- }
- PDim PDim::operator+(const PDim & dim) const
- {
- return PDim(width+dim.width, height+dim.height);
- }
- PDim PDim::operator+(const PPoint & pt) const
- {
- return PDim(width+pt.X(), height+pt.Y());
- }
- PDim & PDim::operator+=(const PDim & dim)
- {
- width += dim.width;
- height += dim.height;
- return *this;
- }
- PDim & PDim::operator+=(const PPoint & pt)
- {
- width += (PDIMENSION)pt.X();
- height += (PDIMENSION)pt.Y();
- return *this;
- }
- PDim PDim::operator-(const PDim & dim) const
- {
- return PDim(width-dim.width, height-dim.height);
- }
- PDim & PDim::operator-=(const PDim & dim)
- {
- width -= dim.width;
- height -= dim.height;
- return *this;
- }
- PDim & PDim::operator-=(const PPoint & pt)
- {
- width -= (PDIMENSION)pt.X();
- height -= (PDIMENSION)pt.Y();
- return *this;
- }
- PDim PDim::operator*(PDIMENSION scale) const
- {
- return PDim(width*scale, height*scale);
- }
- PDim & PDim::operator*=(PDIMENSION scale)
- {
- width *= scale;
- height *= scale;
- return *this;
- }
- PDim PDim::operator/(PDIMENSION scale) const
- {
- return PDim(width/scale, height/scale);
- }
- PDim & PDim::operator/=(PDIMENSION scale)
- {
- width /= scale;
- height /= scale;
- return *this;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // PPoint
- #if defined(_PPOINT)
- PObject * PPoint::Clone() const
- {
- return new PPoint(*this);
- }
- PObject::Comparison PPoint::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PPoint::Class()), PInvalidCast);
- const PPoint & other = (const PPoint &)obj;
- if (X() == other.X() && Y() == other.Y())
- return EqualTo;
- return X()+Y() < other.X()+other.Y() ? LessThan : GreaterThan;
- }
- PPoint PPoint::operator+(const PPoint & pt) const
- {
- return PPoint(X()+pt.X(), Y()+pt.Y());
- }
- PPoint PPoint::operator+(const PDim & dim) const
- {
- return PPoint(X()+dim.Width(), Y()+dim.Height());
- }
- PPoint PPoint::operator-(const PPoint & pt) const
- {
- return PPoint(X()-pt.X(), Y()-pt.Y());
- }
- PPoint PPoint::operator-(const PDim & dim) const
- {
- return PPoint(X()-dim.Width(), Y()-dim.Height());
- }
- PPoint PPoint::operator*(const PPoint & pt) const
- {
- return PPoint(X()*pt.X(), Y()*pt.Y());
- }
- PPoint PPoint::operator*(const PDim & dim) const
- {
- return PPoint(X()*dim.Width(), Y()*dim.Height());
- }
- PPoint PPoint::operator*(PORDINATE scale) const
- {
- return PPoint(X()*scale, Y()*scale);
- }
- PPoint PPoint::operator/(const PPoint & pt) const
- {
- return PPoint(X()/pt.X(), Y()/pt.Y());
- }
- PPoint PPoint::operator/(const PDim & dim) const
- {
- return PPoint(X()/dim.Width(), Y()/dim.Height());
- }
- PPoint PPoint::operator/(PORDINATE scale) const
- {
- return PPoint(X()/scale, Y()/scale);
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // PRect
- #if defined(_PRECT)
- PObject * PRect::Clone() const
- {
- return new PRect(*this);
- }
- PPoint PRect::Centre() const
- {
- return PPoint(X()+Width()/2, Y()+Height()/2);
- }
- void PRect::SetOrigin(PORDINATE nx, PORDINATE ny)
- {
- SetX(nx);
- SetY(ny);
- }
- void PRect::SetOrigin(const PPoint & org)
- {
- SetX(org.X());
- SetY(org.Y());
- }
- void PRect::SetCorner(PORDINATE nx, PORDINATE ny)
- {
- SetRight(nx);
- SetBottom(ny);
- }
- void PRect::SetCorner(const PPoint & cnr)
- {
- SetRight(cnr.X());
- SetBottom(cnr.Y());
- }
- void PRect::SetDimensions(PDIMENSION dx, PDIMENSION dy)
- {
- SetWidth(dx);
- SetHeight(dy);
- }
- void PRect::SetDimensions(const PDim & dim)
- {
- SetWidth(dim.Width());
- SetHeight(dim.Height());
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // PPixels
- PPixelImage::PPixelImage(PDIMENSION dx, PDIMENSION dy, BYTE depth)
- {
- switch (depth) {
- case 32 :
- operator=(PPixelImage(new PPixels32(dx, dy)));
- break;
- case 24 :
- operator=(PPixelImage(new PPixels24(dx, dy)));
- break;
- case 8 :
- operator=(PPixelImage(new PPixels8(dx, dy)));
- break;
- case 4 :
- operator=(PPixelImage(new PPixels4(dx, dy)));
- break;
- case 2 :
- operator=(PPixelImage(new PPixels2(dx, dy)));
- break;
- case 1 :
- operator=(PPixelImage(new PPixels1(dx, dy)));
- break;
- default:
- PAssertAlways(PUnsupportedFeature);
- }
- }
- struct P_BITMAPINFOHEADER {
- P_BITMAPINFOHEADER(istream & s)
- { s >> biWidth >> biHeight >> biPlanes >> biBitCount
- >> biCompression >> biSizeImage >> biXPelsPerMeter
- >> biYPelsPerMeter >> biClrUsed >> biClrImportant;
- }
- PUInt32l biWidth;
- PUInt32l biHeight;
- PUInt16l biPlanes;
- PUInt16l biBitCount;
- PUInt32l biCompression;
- PUInt32l biSizeImage;
- PUInt32l biXPelsPerMeter;
- PUInt32l biYPelsPerMeter;
- PUInt32l biClrUsed;
- PUInt32l biClrImportant;
- };
- struct P_RGBQUAD {
- P_RGBQUAD(istream & s)
- { s >> rgbBlue >> rgbGreen >> rgbRed >> rgbReserved; }
- operator PColour() const { return PColour(rgbRed, rgbGreen, rgbBlue); }
- PUInt8 rgbBlue;
- PUInt8 rgbGreen;
- PUInt8 rgbRed;
- PUInt8 rgbReserved;
- };
- struct P_BITMAPCOREHEADER {
- P_BITMAPCOREHEADER(istream & s)
- { s >> bcWidth >> bcHeight >> bcPlanes >> bcBitCount; }
- PUInt16l bcWidth;
- PUInt16l bcHeight;
- PUInt16l bcPlanes;
- PUInt16l bcBitCount;
- };
- struct P_RGBTRIPLE {
- P_RGBTRIPLE(istream & s)
- { s >> rgbtBlue >> rgbtGreen >> rgbtRed; }
- operator PColour() const { return PColour(rgbtRed, rgbtGreen, rgbtBlue); }
- PUInt8 rgbtBlue;
- PUInt8 rgbtGreen;
- PUInt8 rgbtRed;
- };
- static void ReadBMP(istream & stream, PPixelImage & image)
- {
- stream.ignore(12); // Skip rest of BITMAPFILEHEADER structure
- PUInt32l hdrsize; // Read size of header for bitmap
- stream >> hdrsize;
- PPalette palette;
- DWORD width, height, imageSize;
- WORD bitCount;
- PINDEX colourCount;
- switch ((DWORD)hdrsize) {
- case 40 : {
- P_BITMAPINFOHEADER bmih(stream);
- if (!stream.good())
- return;
- width = bmih.biWidth;
- height = bmih.biHeight;
- bitCount = bmih.biBitCount;
- imageSize = bmih.biSizeImage;
- if (bitCount < 24 && (DWORD)bmih.biClrUsed == 0)
- colourCount = 1 << bitCount;
- else
- colourCount = (PINDEX)(DWORD)bmih.biClrUsed;
- for (PINDEX i = 0; i < colourCount; i++) {
- P_RGBQUAD rgb(stream);
- palette.SetColour(i, rgb);
- }
- break;
- }
- case 12 : {
- P_BITMAPCOREHEADER bmch(stream);
- if (!stream.good())
- return;
- width = (WORD)bmch.bcWidth;
- height = (WORD)bmch.bcHeight;
- bitCount = (WORD)bmch.bcBitCount;
- imageSize = (width*bitCount+31)/32*height*4;
- colourCount = 1 << bitCount;
- for (PINDEX i = 0; i < colourCount; i++) {
- P_RGBTRIPLE rgb(stream);
- palette.SetColour(i, rgb);
- }
- break;
- }
- default :
- return;
- }
- if (!stream.good())
- return;
- if (colourCount == 0) {
- for (PINDEX i = 0; i < 256; i++) {
- PColour col((BYTE)(i&0xe0), (BYTE)((i<<3)&0xe0), (BYTE)(i<<6));
- palette.SetColour(i, col);
- }
- }
- image = PPixelImage((PDIMENSION)width, (PDIMENSION)height, (BYTE)bitCount);
- image->SetPalette(palette);
- #if defined(_WINDOWS) && !defined(_WIN32)
- PPixelDataPtr pixPtr = image->GetPixelDataPtr();
- while (imageSize > 0x4000) {
- stream.read(pixPtr, 0x4000);
- imageSize -= 0x4000;
- pixPtr += 0x4000;
- }
- stream.read(pixPtr, (int)imageSize);
- #else
- stream.read(image->GetPixelDataPtr(), imageSize);
- #endif
- }
- static int PPM_read_number(istream & stream)
- {
- while (isspace(stream.peek()))
- stream.get();
- while (stream.peek() == '#') { // if the line is a comment, then ignore it
- stream.ignore(P_MAX_INDEX, 'n');
- while (isspace(stream.peek()))
- stream.get();
- }
- // Read number
- int num;
- stream >> num;
- return num;
- }
- #if 0
- void PPixelImage::ReadPPM(istream & stream, BYTE format)
- {
- // get the width and height
- PDIMENSION width = PPM_read_number(stream);
- PDIMENSION height = PPM_read_number(stream);
- PPalette palette;
- BYTE bitCount;
- // for each image type, we have to set depth and pixelData
- int black, white, max_value;
- switch (format) {
- case '1':
- case '4':
- bitCount = 1;
- max_value = -1;
- black = palette.AddColour(PColour::Black);
- white = palette.AddColour(PColour::White);
- break;
- case '2':
- case '5':
- bitCount = 8;
- max_value = PPM_read_number(stream);
- for (int i = 0; i < 128; i++)
- palette.AddColour(PColour(i*2, i*2, i*2));
- break;
- case '3':
- case '6':
- bitCount = 24;
- max_value = PPM_read_number(stream);
- break;
- }
- PPixelImage pix(width, height, bitCount);
- // calculate the shift for max_value
- int shift;
- if (max_value > 0) {
- shift = 0;
- while ((max_value << (shift+1)) < 255)
- shift++;
- }
- // remove single whitespace after header if in raw format
- if (format == '2' || format == '4' || format == '6')
- stream.ignore();
- int x, y;
- // declare a line buffer when needed
- PBYTEArray line(width * 3);
- BYTE * linePtr = line.GetPointer();
- switch (format) {
- // PBM ASCII
- case '1':
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++)
- line[x] = PPM_read_number(stream);
- operator->()->SetRaster(y, line, width);
- }
- break;
- // PGM ASCII
- case '2':
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++)
- line[x] = PPM_read_number(stream);
- operator->()->SetRaster(y, line, width);
- }
- break;
- // PPM ASCII
- case '3':
- for (y = 0; y < height; y++) {
- for (x = 0; x < width*3; x++)
- line[x] = PPM_read_number(stream);
- operator->()->SetRaster(y, line, width);
- }
- break;
- // PBM binary
- case '4':
- break;
- // PGM binary
- case '5':
- break;
- // PPM binary
- case '6':
- for (y = 0; y < height; y++) {
- if (shift == 0)
- file.Read (operator->()->GetRasterDataPtr(y), width*3);
- else {
- file.Read (linePtr, width*3);
- BYTE * ptr = linePtr;
- BYTE * optr = operator->()->GetRasterDataPtr(y);
- for (PINDEX x = width; x > 0; x--)
- *optr++ = *ptr++ << shift;
- }
- }
- break;
- }
- }
- #endif
- static void ReadPBMa(istream & stream, PPixelImage & image)
- {
- PDIMENSION width = PPM_read_number(stream);
- PDIMENSION height = PPM_read_number(stream);
- image = PPixelImage(width, height, 1);
- PPalette pal;
- pal.AddColour(PColour::Black);
- pal.AddColour(PColour::White);
- image->SetPalette(pal);
- for (PDIMENSION y = 0; y < height; y++)
- for (PDIMENSION x = 0; x < width; x++)
- image->SetPixel(x, y, (BYTE)PPM_read_number(stream));
- }
- static void ReadPBMb(istream & stream, PPixelImage & image)
- {
- PDIMENSION width = PPM_read_number(stream);
- PDIMENSION height = PPM_read_number(stream);
- image = PPixelImage(width, height, 1);
- PPalette pal;
- pal.AddColour(PColour::Black);
- pal.AddColour(PColour::White);
- image->SetPalette(pal);
- stream.ignore(); // Skip blank before binary data
- for (PDIMENSION y = 0; y < height; y++)
- stream.read(image->GetRasterDataPtr(y), width);
- }
- static void ReadPGMa(istream & stream, PPixelImage & image)
- {
- PDIMENSION width = PPM_read_number(stream);
- PDIMENSION height = PPM_read_number(stream);
- /*int max_value =*/ PPM_read_number(stream);
- image = PPixelImage(width, height, 8);
- PPalette pal;
- for (BYTE i = 0; i < 256; i += 2)
- pal.AddColour(PColour(i, i, i));
- image->SetPalette(pal);
- for (PDIMENSION y = 0; y < height; y++)
- for (PDIMENSION x = 0; x < width; x++)
- image->SetPixel(x, y, (BYTE)PPM_read_number(stream));
- }
- static void ReadPGMb(istream & stream, PPixelImage & image)
- {
- PDIMENSION width = PPM_read_number(stream);
- PDIMENSION height = PPM_read_number(stream);
- int max_value = PPM_read_number(stream);
- // calculate the shift for max_value
- int shift = 0;
- if (max_value > 0) {
- while ((max_value << (shift+1)) < 255)
- shift++;
- }
- image = PPixelImage(width, height, 8);
- PPalette pal;
- for (BYTE i = 0; i < 256; i += 2)
- pal.AddColour(PColour(i, i, i));
- image->SetPalette(pal);
- stream.ignore(); // Skip blank before binary data
- for (PDIMENSION y = 0; y < height; y++) {
- BYTE * line = image->GetRasterDataPtr(y);
- stream.read(line, width*3);
- if (shift != 0) {
- for (PINDEX x = width; x > 0; x--)
- *line++ <<= shift;
- }
- }
- }
- static void ReadPPMa(istream & stream, PPixelImage & image)
- {
- PDIMENSION width = PPM_read_number(stream);
- PDIMENSION height = PPM_read_number(stream);
- /*int max_value =*/ PPM_read_number(stream);
- image = PPixelImage(width, height, 24);
- for (PDIMENSION y = 0; y < height; y++) {
- BYTE * line = image->GetRasterDataPtr(y);
- for (PDIMENSION x = 0; x < width*3; x++)
- *line++ = (BYTE)PPM_read_number(stream);
- }
- }
- static void ReadPPMb(istream & stream, PPixelImage & image)
- {
- PDIMENSION width = PPM_read_number(stream);
- PDIMENSION height = PPM_read_number(stream);
- int max_value = PPM_read_number(stream);
- // calculate the shift for max_value
- int shift = 0;
- if (max_value > 0) {
- while ((max_value << (shift+1)) < 255)
- shift++;
- }
- image = PPixelImage(width, height, 24);
- stream.ignore(); // Skip blank before binary data
- for (PDIMENSION y = 0; y < height; y++) {
- BYTE * line = image->GetRasterDataPtr(y);
- stream.read(line, width*3);
- if (shift != 0) {
- for (PDIMENSION x = width; x > 0; x--)
- *line++ <<= shift;
- }
- }
- }
- PPixelImage::PPixelImage(istream & stream)
- {
- // read the magic number
- char magic[2];
- stream.read(magic, 2);
- if (!stream.good())
- return;
- // determine the format
- if (magic[0] == 'B' && magic[1] == 'M')
- ReadBMP(stream, *this);
- else if (magic[0] == 'P')
- switch (magic[1]) {
- case '1': // PBM ASCII
- ReadPBMa(stream, *this);
- break;
- case '2': // PGM ASCII
- ReadPGMa(stream, *this);
- break;
- case '3': // PPM ASCII
- ReadPPMa(stream, *this);
- break;
- case '4': // PBM binary
- ReadPBMb(stream, *this);
- break;
- case '5': // PGM binary
- ReadPGMb(stream, *this);
- break;
- case '6': // PPM binary
- ReadPPMb(stream, *this);
- }
- }
- void PPixelBase::SetDirtyArea(PORDINATE x, PORDINATE y, PDIMENSION width)
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- if (x < dirtyArea.Left())
- dirtyArea.SetLeft(x);
- if (x+(PORDINATE)width > dirtyArea.Right())
- dirtyArea.SetRight(x+width);
- if (y < dirtyArea.Top())
- dirtyArea.SetTop(y);
- if (y > dirtyArea.Bottom())
- dirtyArea.SetBottom(y);
- }
- void PPixelBase::SetPixelColour(PORDINATE x,PORDINATE y,const PColour & colour)
- {
- SetPixel(x, y, (BYTE)palette.GetIndex(colour));
- }
- void PPixels24::SetPixelColour(PORDINATE x,PORDINATE y,const PColour & colour)
- {
- SetDirtyArea(x, y);
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x*3;
- *pixel++ = colour.GetRed();
- *pixel++ = colour.GetGreen();
- *pixel = colour.GetBlue();
- }
- void PPixels32::SetPixelColour(PORDINATE x,PORDINATE y,const PColour & colour)
- {
- SetDirtyArea(x, y);
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x*4;
- *pixel++ = colour.GetRed();
- *pixel++ = colour.GetGreen();
- *pixel++ = colour.GetBlue();
- *pixel = colour.GetAlpha();
- }
- void PPixels1::SetPixel(PORDINATE x, PORDINATE y, BYTE val)
- {
- SetDirtyArea(x, y);
- PPixelDataPtr pixel = GetRasterDataPtr(y) + (x >> 3);
- x &= 7;
- *pixel = (BYTE)((*pixel & ~(1 << x)) | (val << x));
- }
- void PPixels2::SetPixel(PORDINATE x, PORDINATE y, BYTE val)
- {
- SetDirtyArea(x, y);
- PPixelDataPtr pixel = GetRasterDataPtr(y) + (x >> 2);
- x &= 3;
- *pixel = (BYTE)((*pixel & ~(3 << x)) | (val << (x << 1)));
- }
- void PPixels4::SetPixel(PORDINATE x, PORDINATE y, BYTE val)
- {
- SetDirtyArea(x, y);
- PPixelDataPtr pixel = GetRasterDataPtr(y) + (x >> 1);
- x &= 1;
- *pixel = (BYTE)((*pixel & ~(0xf << x)) | (val << (x << 2)));
- }
- void PPixels8::SetPixel(PORDINATE x, PORDINATE y, BYTE val)
- {
- SetDirtyArea(x, y);
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x;
- *pixel = val;
- }
- void PPixels24::SetPixel(PORDINATE x, PORDINATE y, BYTE val)
- {
- SetDirtyArea(x, y);
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x*3;
- *pixel++ = val;
- *pixel++ = val;
- *pixel = val;
- }
- void PPixels32::SetPixel(PORDINATE x, PORDINATE y, BYTE val)
- {
- SetDirtyArea(x, y);
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x*4;
- *pixel++ = val;
- *pixel++ = val;
- *pixel++ = val;
- *pixel = 0;
- }
- PColour PPixelBase::GetPixelColour(PORDINATE x, PORDINATE y) const
- {
- return palette.GetColour(GetPixel(x, y));
- }
- PColour PPixels24::GetPixelColour(PORDINATE x, PORDINATE y) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x*3;
- return PColour(pixel[0], pixel[1], pixel[2]);
- }
- PColour PPixels32::GetPixelColour(PORDINATE x, PORDINATE y) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x*4;
- return PColour(pixel[0], pixel[1], pixel[2], pixel[3]);
- }
- BYTE PPixels1::GetPixel(PORDINATE x, PORDINATE y) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- PPixelDataPtr pixel = GetRasterDataPtr(y) + (x >> 3);
- return (BYTE)((*pixel >> (x&7))&1);
- }
- BYTE PPixels2::GetPixel(PORDINATE x, PORDINATE y) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- PPixelDataPtr pixel = GetRasterDataPtr(y) + (x >> 2);
- return (BYTE)((*pixel >> ((x&3) << 1))&3);
- }
- BYTE PPixels4::GetPixel(PORDINATE x, PORDINATE y) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- PPixelDataPtr pixel = GetRasterDataPtr(y) + (x >> 1);
- return (BYTE)((*pixel >> ((x&1) << 2))&0xf);
- }
- BYTE PPixels8::GetPixel(PORDINATE x, PORDINATE y) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x;
- return *pixel;
- }
- BYTE PPixels24::GetPixel(PORDINATE x, PORDINATE y) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x*3;
- return (BYTE)((pixel[0]*30 + pixel[1]*59 + pixel[2]*11)/100);
- }
- BYTE PPixels32::GetPixel(PORDINATE x, PORDINATE y) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- PPixelDataPtr pixel = GetRasterDataPtr(y) + x*4;
- return (BYTE)((pixel[0]*30 + pixel[1]*59 + pixel[2]*11)/100);
- }
- PPixelDataPtr PPixelBase::CalculateRaster(PORDINATE x, PORDINATE y,
- PDIMENSION & lastX) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width(), "Pixel out of bounds");
- lastX += (PDIMENSION)x;
- if (lastX > Width())
- lastX = Width();
- return GetRasterDataPtr(y) + x*GetDepth()/8;
- }
- void PPixelBase::SetRaster(PORDINATE x, PORDINATE y,
- const PBYTEArray & raster, PDIMENSION width)
- {
- if (width > (PDIMENSION)raster.GetSize())
- width = (PDIMENSION)raster.GetSize();
- SetRasterValues(x, y, raster, width);
- }
-
- void PPixelBase::GetRaster(PORDINATE x, PORDINATE y,
- PBYTEArray & raster, PDIMENSION width) const
- {
- if (width > Width())
- width = Width();
- GetRasterValues(x, y, raster.GetPointer(width), width);
- }
-
- void PPixelBase::SetRasterColours(PORDINATE x, PORDINATE y,
- const PColourArray & raster, PDIMENSION width)
- {
- if (width > (PDIMENSION)raster.GetSize())
- width = (PDIMENSION)raster.GetSize();
- while ((PDIMENSION)x < width) {
- SetPixel(x, y, (BYTE)palette.GetIndex(raster[x]));
- x++;
- }
- }
- void PPixels24::SetRasterColours(PORDINATE x, PORDINATE y,
- const PColourArray & raster, PDIMENSION width)
- {
- if (width > (PDIMENSION)raster.GetSize())
- width = (PDIMENSION)raster.GetSize();
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- SetDirtyArea(x, y, width);
- while ((PDIMENSION)x < width) {
- *pixel++ = raster[x].GetRed();
- *pixel++ = raster[x].GetGreen();
- *pixel++ = raster[x++].GetBlue();
- }
- }
- void PPixels32::SetRasterColours(PORDINATE x, PORDINATE y,
- const PColourArray & raster, PDIMENSION width)
- {
- if (width > (PDIMENSION)raster.GetSize())
- width = (PDIMENSION)raster.GetSize();
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- SetDirtyArea(x, y, width);
- while ((PDIMENSION)x < width) {
- *pixel++ = raster[x].GetRed();
- *pixel++ = raster[x].GetGreen();
- *pixel++ = raster[x].GetBlue();
- *pixel++ = raster[x++].GetAlpha();
- }
- }
- void PPixels1::SetRasterValues(PORDINATE x, PORDINATE y,
- const BYTE * raster, PDIMENSION width)
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- BYTE mask = (BYTE)(0x80 >> (x&7));
- *pixel = 0;
- while ((PDIMENSION)x < width) {
- if (*raster++ != 0)
- *pixel |= mask;
- mask >>= 1;
- if (mask == 0) {
- *++pixel = 0;
- mask = 0x80;
- }
- x++;
- }
- }
- void PPixels2::SetRasterValues(PORDINATE x, PORDINATE y,
- const BYTE * raster, PDIMENSION width)
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- SetDirtyArea(x, y, width);
- while ((PDIMENSION)(x += 4) <= width) {
- *pixel++ = (BYTE)((raster[0] << 6)|(raster[1] << 4)|
- (raster[2] << 2)| raster[3]);
- raster += 4;
- }
- switch (x&3) {
- case 1 :
- *pixel = (BYTE)((raster[0] << 6)|(raster[1] << 4)|
- (raster[2] << 2));
- break;
- case 2 :
- *pixel = (BYTE)((raster[0] << 6)|(raster[1] << 4));
- break;
- case 3 :
- *pixel = (BYTE)(raster[0] << 6);
- break;
- }
- }
- void PPixels4::SetRasterValues(PORDINATE x, PORDINATE y,
- const BYTE * raster, PDIMENSION width)
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- SetDirtyArea(x, y, width);
- while ((PDIMENSION)(x += 2) <= width) {
- *pixel++ = (BYTE)((raster[0] << 4)|raster[1]);
- raster += 2;
- }
- if ((x&1) != 0)
- *pixel = (BYTE)(*raster << 4);
- }
- void PPixels8::SetRasterValues(PORDINATE x, PORDINATE y,
- const BYTE * raster, PDIMENSION width)
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- SetDirtyArea(x, y, width);
- memcpy(pixel, raster, width);
- }
- void PPixels24::SetRasterValues(PORDINATE x, PORDINATE y,
- const BYTE * raster, PDIMENSION width)
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- SetDirtyArea(x, y, width);
- while ((PDIMENSION)x < width) {
- *pixel++ = *raster;
- *pixel++ = *raster;
- *pixel++ = *raster;
- raster++;
- x++;
- }
- }
- void PPixels32::SetRasterValues(PORDINATE x, PORDINATE y,
- const BYTE * raster, PDIMENSION width)
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- SetDirtyArea(x, y, width);
- while ((PDIMENSION)x < width) {
- *pixel++ = *raster;
- *pixel++ = *raster;
- *pixel++ = *raster;
- *pixel++ = 0;
- raster++;
- x++;
- }
- }
- void PPixelBase::GetRasterColours(PORDINATE x, PORDINATE y,
- PColourArray & raster, PDIMENSION width) const
- {
- CalculateRaster(x, y, width);
- raster.SetMinSize(width);
- while ((PDIMENSION)x < width) {
- raster[x] = palette.GetColour(GetPixel(x, y));
- x++;
- }
- }
- void PPixels24::GetRasterColours(PORDINATE x, PORDINATE y,
- PColourArray & raster, PDIMENSION width) const
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- raster.SetMinSize(width);
- while ((PDIMENSION)x < width) {
- raster[x++] = PColour(pixel[0], pixel[1], pixel[2]);
- pixel += 3;
- }
- }
- void PPixels32::GetRasterColours(PORDINATE x, PORDINATE y,
- PColourArray & raster, PDIMENSION width) const
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- raster.SetMinSize(width);
- while ((PDIMENSION)x < width) {
- raster[x++] = PColour(pixel[0], pixel[1], pixel[2], pixel[3]);
- pixel += 4;
- }
- }
- void PPixels1::GetRasterValues(PORDINATE x, PORDINATE y,
- BYTE * raster, PDIMENSION width) const
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- int mask = 0x80 >> (x&7);
- *pixel = 0;
- while ((PDIMENSION)x < width) {
- *raster++ = (BYTE)((*pixel & mask) != 0);
- mask >>= 1;
- if (mask == 0) {
- *++pixel = 0;
- mask = 0x80;
- }
- x++;
- }
- }
- void PPixels2::GetRasterValues(PORDINATE x, PORDINATE y,
- BYTE * raster, PDIMENSION width) const
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- while ((PDIMENSION)x < width) {
- *raster++ = (BYTE)(*pixel >> 6);
- if ((PDIMENSION)++x < width) {
- *raster++ = (BYTE)((*pixel >> 4)&3);
- if ((PDIMENSION)++x < width) {
- *raster++ = (BYTE)((*pixel >> 2)&3);
- if ((PDIMENSION)++x < width)
- *raster++ = (BYTE)(*pixel&3);
- }
- }
- pixel++;
- }
- }
- void PPixels4::GetRasterValues(PORDINATE x, PORDINATE y,
- BYTE * raster, PDIMENSION width) const
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- while ((PDIMENSION)x < width) {
- *raster++ = (BYTE)(*pixel >> 4);
- if ((PDIMENSION)++x < width)
- *raster++ = (BYTE)(*pixel&0xf);
- pixel++;
- }
- }
- void PPixels8::GetRasterValues(PORDINATE x, PORDINATE y,
- BYTE * raster, PDIMENSION width) const
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- memcpy(raster, pixel, width);
- }
- void PPixels24::GetRasterValues(PORDINATE x, PORDINATE y,
- BYTE * raster, PDIMENSION width) const
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- while ((PDIMENSION)x < width) {
- *raster++ = (BYTE)((pixel[0]*30 + pixel[1]*59 + pixel[2]*11)/100);
- pixel += 3;
- x++;
- }
- }
- void PPixels32::GetRasterValues(PORDINATE x, PORDINATE y,
- BYTE * raster, PDIMENSION width) const
- {
- PPixelDataPtr pixel = CalculateRaster(x, y, width);
- while ((PDIMENSION)x < width) {
- *raster++ = (BYTE)((pixel[0]*30 + pixel[1]*59 + pixel[2]*11)/100);
- pixel += 4;
- x++;
- }
- }
- PPixelImage PPixelBase::ExtractPixels(PORDINATE x, PORDINATE y,
- PDIMENSION width, PDIMENSION height) const
- {
- PAssert(x >= 0 && (PDIMENSION)x < Width() &&
- y >= 0 && (PDIMENSION)y < Height(), "Pixel out of bounds");
- if (width > Width() - x)
- width = Width() - x;
- if (height > Height() - y)
- height = Height() - y;
- PPixelImage pix(width, height, GetDepth());
- if (GetDepth() >= 8 || x%(8/GetDepth()) == 0) {
- for (PDIMENSION py = 0; py < height; py++)
- memcpy(pix->GetRasterDataPtr(py),
- GetRasterDataPtr(y++) + x*GetDepth()/8, pix->pixelLineBytes);
- }
- else {
- PBYTEArray raster(width);
- for (PDIMENSION py = 0; py < height; py++) {
- GetRaster(x, y++, raster, width);
- pix->SetRaster(py, raster, width);
- }
- }
- return pix;
- }
- //////////////////////////////////////////////////////////////////////////////
- // PCanvasState
- #if defined(_PCANVASSTATE)
- PCanvasState::PCanvasState()
- : penStyle(PCanvas::Solid),
- penWidth(0),
- penMode(PCanvas::SrcCopy),
- penFgColour(PColour::Black),
- penBkColour(PColour::White),
- fillFgColour(PColour::Clear),
- fillBkColour(PColour::Clear),
- fillMode(PCanvas::SrcCopy),
- font("System", 10),
- textFgColour(PColour::Black),
- textBkColour(PColour::White),
- palette(),
- polyFillMode(PCanvas::Winding),
- viewport(0, 0, 100, 100),
- map(0, 0, 100, 100)
- {
- }
- PCanvasState::PCanvasState(const PCanvasState & s)
- : penStyle(s.penStyle),
- penWidth(s.penWidth),
- penMode(s.penMode),
- penFgColour(s.penFgColour),
- penBkColour(s.penBkColour),
- fillFgColour(s.fillFgColour),
- fillBkColour(s.fillBkColour),
- fillPattern(s.fillPattern),
- fillMode(s.fillMode),
- font(s.font),
- textFgColour(s.textFgColour),
- textBkColour(s.textBkColour),
- palette(s.palette),
- polyFillMode(s.polyFillMode),
- viewport(s.viewport),
- map(s.map)
- {
- }
- BOOL PCanvasState::SetPenStyle(PenStyles style)
- {
- if (penStyle == style)
- return FALSE;
- penStyle = style;
- return TRUE;
- }
- BOOL PCanvasState::SetPenWidth(int width)
- {
- if (penWidth == width)
- return FALSE;
- penWidth = width;
- return TRUE;
- }
- BOOL PCanvasState::SetPenMode(DrawingModes mode)
- {
- if (penMode == mode)
- return FALSE;
- penMode = mode;
- return TRUE;
- }
- BOOL PCanvasState::SetPenFgColour(const PColour & colour)
- {
- if (colour == penFgColour)
- return FALSE;
- penFgColour = colour;
- return TRUE;
- }
- BOOL PCanvasState::SetPenBkColour(const PColour & colour)
- {
- if (colour == penBkColour)
- return FALSE;
- penBkColour = colour;
- return TRUE;
- }
- BOOL PCanvasState::SetFillPattern(const PPattern & pattern)
- {
- if (fillPattern == pattern)
- return FALSE;
- fillPattern = pattern;
- return TRUE;
- }
- BOOL PCanvasState::SetPatternOrigin(const PPoint & pt)
- {
- if (patternOrigin == pt)
- return FALSE;
- patternOrigin = pt;
- return TRUE;
- }
- BOOL PCanvasState::SetFillMode(DrawingModes mode)
- {
- if (fillMode == mode)
- return FALSE;
- fillMode = mode;
- return TRUE;
- }
- BOOL PCanvasState::SetFillFgColour(const PColour & colour)
- {
- if (colour == fillFgColour)
- return FALSE;
- fillFgColour = colour;
- return TRUE;
- }
- BOOL PCanvasState::SetFillBkColour(const PColour & colour)
- {
- if (colour == fillBkColour)
- return FALSE;
- fillBkColour = colour;
- return TRUE;
- }
- BOOL PCanvasState::SetFont(const PFont & newFont)
- {
- if (font == newFont)
- return FALSE;
- font = newFont;
- return TRUE;
- }
- BOOL PCanvasState::SetTextFgColour(const PColour & colour)
- {
- if (colour == textFgColour)
- return FALSE;
- textFgColour = colour;
- return TRUE;
- }
- BOOL PCanvasState::SetTextBkColour(const PColour & colour)
- {
- if (colour == textBkColour)
- return FALSE;
- textBkColour = colour;
- return TRUE;
- }
- BOOL PCanvasState::SetPalette(const PPalette & newPal)
- {
- if (palette == newPal)
- return FALSE;
- palette = newPal;
- return TRUE;
- }
- BOOL PCanvasState::SetPolyFillMode(PolyFillMode newMode)
- {
- if (polyFillMode == newMode)
- return FALSE;
- polyFillMode = newMode;
- return TRUE;
- }
- BOOL PCanvasState::SetViewportRect(const PRect & rect)
- {
- if (viewport == rect)
- return FALSE;
- viewport = rect;
- return TRUE;
- }
- BOOL PCanvasState::SetMappingRect(const PRect & rect)
- {
- if (map == rect)
- return FALSE;
- map = rect;
- return TRUE;
- }
- void PCanvasState::SetOrigin(const PPoint & pt)
- {
- PRect newMap = map;
- newMap.SetOrigin(pt);
- SetMappingRect(newMap);
- }
- #endif
- //////////////////////////////////////////////////////////////////////////////
- // PCanvas
- #if defined(_PCANVAS)
- inline static long CalculateScaledValue(long value,
- int innerOffset, int innerWidth,
- int outerOffset, int outerWidth)
- {
- long tmp = (1000L*(value-innerOffset)*outerWidth)/innerWidth;
- if (tmp < 0)
- tmp -= 500;
- else
- tmp += 500;
- return tmp/1000L + outerOffset;
- }
- PDIMENSION PCanvas::FromPixelsDX(PDIMENSION dx) const
- {
- return (PDIMENSION)CalculateScaledValue(dx,
- 0, viewport.Width(), 0, map.Width());
- }
- PDIMENSION PCanvas::FromPixelsDY(PDIMENSION dy) const
- {
- return (PDIMENSION)CalculateScaledValue(dy,
- 0, viewport.Height(), 0, map.Height());
- }
- PORDINATE PCanvas::FromPixelsX(PORDINATE x) const
- {
- return (PORDINATE)CalculateScaledValue(x,
- viewport.X(), viewport.Width(), map.X(), map.Width());
- }
- PORDINATE PCanvas::FromPixelsY(PORDINATE y) const
- {
- return (PORDINATE)CalculateScaledValue(y,
- viewport.Y(), viewport.Height(), map.Y(), map.Height());
- }
- PDIMENSION PCanvas::ToPixelsDX(PDIMENSION dx) const
- {
- return (PDIMENSION)CalculateScaledValue(dx,
- 0, map.Width(), 0, viewport.Width());
- }
- PDIMENSION PCanvas::ToPixelsDY(PDIMENSION dy) const
- {
- return (PDIMENSION)CalculateScaledValue(dy,
- 0, map.Height(), 0, viewport.Height());
- }
- PORDINATE PCanvas::ToPixelsX(PORDINATE x) const
- {
- return (PORDINATE)CalculateScaledValue(x,
- map.X(), map.Width(), viewport.X(), viewport.Width());
- }
- PORDINATE PCanvas::ToPixelsY(PORDINATE y) const
- {
- return (PORDINATE)CalculateScaledValue(y,
- map.Y(), map.Height(), viewport.Y(), viewport.Height());
- }
- PDIMENSION PCanvas::ToPointsX(PDIMENSION x)
- {
- long tmp1 = 7200L*x*viewport.Width();
- long tmp2 = map.Width()*deviceResX*100L;
- if (tmp1 < 0)
- tmp1 -= tmp2/2;
- else
- tmp1 += tmp2/2;
- return (PDIMENSION)(tmp1/tmp2);
- }
-
- PDIMENSION PCanvas::ToPointsY(PDIMENSION y)
- {
- long tmp1 = 7200L*y*viewport.Height();
- long tmp2 = map.Height()*deviceResY*100L;
- if (tmp1 < 0)
- tmp1 -= tmp2/2;
- else
- tmp1 += tmp2/2;
- return (PDIMENSION)(tmp1/tmp2);
- }
- PDIMENSION PCanvas::FromPointsX(PDIMENSION x)
- {
- long tmp = (100L*x*deviceResX*map.Width())/viewport.Width();
- if (tmp < 0)
- tmp -= 3600;
- else
- tmp += 3600;
- return (PDIMENSION)(tmp/7200L);
- }
-
- PDIMENSION PCanvas::FromPointsY(PDIMENSION y)
- {
- long tmp = (100L*y*deviceResY*map.Height())/viewport.Height();
- if (tmp < 0)
- tmp -= 3600;
- else
- tmp += 3600;
- return (PDIMENSION)(tmp/7200L);
- }
-
- void PCanvas::DrawBevelledRect(const PRect & rect, BOOL raised, BOOL deep)
- {
- Save();
- PRect bounds = ToPixels(rect);
- PDim border = PApplication::Current().GetBorderSize();
- SetMappingRect(GetViewportRect());
- const PColour & shadowColour = PApplication::Current().GetButtonShadowColour();
- const PColour & lightColour = PApplication::Current().GetButtonLightingColour();
- const PColour & bkColour = GetFillFgColour();
- SetPenFgColour(bkColour);
- SetFillFgColour(bkColour);
- SetFillBkColour(bkColour);
- DrawRect(bounds);
- PORDINATE left = bounds.Left();
- PORDINATE top = bounds.Top();
- PORDINATE right = bounds.Right()-border.Width();
- PORDINATE bottom = bounds.Bottom()-border.Height();
- if (raised)
- SetPenFgColour(shadowColour);
- else
- SetPenFgColour(lightColour);
- SetPenWidth(border.Height());
- DrawLine(left, bottom, right+border.Width(), bottom);
- bottom -= border.Height();
- if (deep)
- DrawLine(left+border.Width(), bottom, right+border.Width(), bottom);
- SetPenWidth(border.Width());
- DrawLine(right, top, right, bottom+border.Height());
- right -= border.Width();
- if (deep)
- DrawLine(right, top+border.Height(), right, bottom+border.Height());
- if (raised)
- SetPenFgColour(lightColour);
- else
- SetPenFgColour(shadowColour);
- SetPenWidth(border.Width());
- DrawLine(left, top, left, bottom+border.Height());
- left += border.Width();
- if (deep)
- DrawLine(left, top, left, bottom);
- SetPenWidth(border.Height());
- DrawLine(left, top, right+border.Width(), top);
- if (deep) {
- top += border.Height();
- DrawLine(left, top, right, top);
- }
- Restore();
- }
- static PString AddEllipses(PCanvas & canvas,
- PDIMENSION width, const PString & line, int alignment)
- {
- int amtTooBig = canvas.MeasureString(line).Width() - width;
- if (amtTooBig <= 0)
- return line;
- PDIMENSION fontWidth = canvas.FromPointsY(canvas.GetFont().GetAvgWidth());
- PINDEX numChars = line.GetLength() - (amtTooBig+fontWidth-1)/fontWidth - 5;
- PString ellipses, str;
- switch (alignment) {
- default :
- case PCanvas::LeftAlign :
- ellipses = " ...";
- str = line.Left(numChars) + ellipses;
- break;
- case PCanvas::RightAlign :
- ellipses = "... ";
- str = ellipses + line.Right(numChars);
- break;
- case PCanvas::Centred :
- ellipses = " ... ";
- str = line.Left((numChars+1)/2) + ellipses + line.Right(numChars/2);
- break;
- }
- while (canvas.MeasureString(str).Width() - width <= 0) {
- numChars++;
- switch (alignment) {
- default :
- case PCanvas::LeftAlign :
- str = line.Left(numChars) + ellipses;
- break;
- case PCanvas::RightAlign :
- str = ellipses + line.Right(numChars);
- break;
- case PCanvas::Centred :
- str = line.Left((numChars+1)/2) + ellipses + line.Right(numChars/2);
- break;
- }
- }
- numChars--;
- switch (alignment) {
- default :
- case PCanvas::LeftAlign :
- return line.Left(numChars) + ellipses;
- case PCanvas::RightAlign :
- return ellipses + line.Right(numChars);
- case PCanvas::Centred :
- return line.Left((numChars+1)/2) + ellipses + line.Right(numChars/2);
- }
- }
- PDIMENSION PCanvas::DrawString(const PRect & rect, const PString & str, int options)
- {
- if (GetTextBkColour().GetAlpha() != 0) {
- Save();
- SetPenStyle(Solid);
- SetPenWidth(0);
- SetPenMode(SrcCopy);
- SetPenFgColour(GetTextBkColour());
- SetFillPattern(PPattern());
- SetFillMode(SrcCopy);
- SetFillFgColour(GetTextBkColour());
- DrawRect(rect);
- Restore();
- }
- PDIMENSION spaceWidth = MeasureString(" ").Width();
- PStringArray unbrokenLines = str.Lines();
- PStringArray lines(unbrokenLines.GetSize());
- PINDEX line = 0;
- for (PINDEX i = 0; i < unbrokenLines.GetSize(); i++) {
- if (MeasureString(unbrokenLines[i]).Width() <= rect.Width())
- lines[line++] = unbrokenLines[i];
- else {
- switch (options&HorizontalWrapMask) {
- case NoWrapping :
- lines[line++] = unbrokenLines[i];
- break;
- // break the lines into new lines that are no wider than the rectangle
- case WordWrap : {
- PString str;
- PDIMENSION w = 0;
- PStringArray words = unbrokenLines[i].Tokenise(" t", FALSE);
- for (PINDEX k = 0; k < words.GetSize(); k++) {
- PDIMENSION x = MeasureString(words[k]).Width();
- if (w + x > rect.Width()) {
- if (w != 0)
- lines[line++] = str;
- str = "";
- w = 0;
- }
- else if (w != 0) {
- str += " ";
- x += spaceWidth;
- }
- str += words[k];
- w += x;
- }
- lines[line++] = str;
- break;
- }
- // Chop text out of the line so that is no wider than the rectangle
- case CentreEllipses :
- lines[line++] = AddEllipses(*this,
- rect.Width(), unbrokenLines[i], Centred);
- break;
- case EndEllipses :
- lines[line++] = AddEllipses(*this,
- rect.Width(), unbrokenLines[i], options&HorizontalAlignmentMask);
- break;
- }
- }
- }
- PDIMENSION fontHeight = FromPointsY(realFont.GetHeight());
- PDIMENSION totalHeight = fontHeight*lines.GetSize();
- if (totalHeight > rect.Height()) {
- int numLinesToKill = (totalHeight-rect.Height()+fontHeight-1)/fontHeight+1;
- int firstLineToKill;
- switch (options&VerticalTruncationMask) {
- case CentreTruncation :
- firstLineToKill = lines.GetSize()/2 - numLinesToKill/2;
- break;
- case EndTruncation :
- switch (options&VerticalAlignmentMask) {
- case PCanvas::TopAlign :
- firstLineToKill = lines.GetSize() - numLinesToKill;
- break;
- case PCanvas::CentreVertical :
- firstLineToKill = lines.GetSize()/2 - numLinesToKill/2;
- break;
- default : // BottomAlign and BaseLine
- firstLineToKill = 0;
- }
- break;
- default :
- firstLineToKill = numLinesToKill = 0;
- }
- if (numLinesToKill > 0) {
- PDIMENSION eWidth = MeasureString(" ... ").Width();
- PString s = AddEllipses(*this, rect.Width()/2-eWidth/2,
- lines[firstLineToKill], LeftAlign) +
- " ... " +
- AddEllipses(*this, rect.Width()/2-eWidth/2,
- lines[firstLineToKill+numLinesToKill-1], RightAlign);
- while (numLinesToKill-- > 0)
- lines.RemoveAt(firstLineToKill);
- lines.InsertAt(firstLineToKill, new PString(s));
- totalHeight = fontHeight*lines.GetSize();
- }
- }
- PORDINATE y;
- switch (options&VerticalAlignmentMask) {
- case TopAlign :
- y = rect.Top();
- break;
- case CentreVertical :
- y = rect.Top() + (rect.Height()-totalHeight)/2;
- break;
- default : // BottomAlign and BaseLine
- y = rect.Bottom() - totalHeight;
- }
- for (line = 0; line < lines.GetSize(); line++, y += fontHeight) {
- switch (options&HorizontalAlignmentMask) {
- case LeftAlign :
- DrawString(rect.Left(), y, lines[line], LeftAlign);
- break;
-
- case RightAlign :
- DrawString(rect.Right(), y, lines[line], RightAlign);
- break;
-
- case Centred :
- DrawString((rect.Left()+rect.Right())/2, y, lines[line], Centred);
- break;
-
- case Justified :
- // Split the line into space separated words
- PStringArray words = lines[line].Tokenise(" ", FALSE);
- if (words.GetSize() <= 1)
- DrawString(rect.Left(), y, lines[line], LeftAlign);
- else {
- // Now get the width inpixesl of each word
- PWORDArray wordWidths(words.GetSize());
- PDIMENSION totalWidth = 0;
- PINDEX word;
- for (word = 0; word < words.GetSize(); word++) {
- wordWidths[word] = (WORD)MeasureString(words[word]).Width();
- totalWidth += wordWidths[word];
- }
- if (rect.Width() <= totalWidth)
- DrawString(rect.Left(), y, lines[line], LeftAlign);
- else {
- // Now calculate the size of each space
- PORDINATE spaceWidth = (rect.Width()-totalWidth)/(words.GetSize()-1);
- // Finally, output each word at x location determined by space width
- PORDINATE x = rect.Left();
- for (word = 0; word < words.GetSize(); word++) {
- DrawString(x, y, words[word], LeftAlign);
- x += wordWidths[word] + spaceWidth;
- }
- }
- }
- }
- }
- return lines.GetSize()*fontHeight;
- }
- PDIMENSION PCanvas::MeasureString(const PString & str, PDIMENSION width)
- {
- PStringArray lines = str.Lines();
- PDIMENSION height = 0;
- for (PINDEX line = 0; line < lines.GetSize(); line++) {
- PDim lineDim(MeasureString(lines[line]));
- if (lineDim.Width() > width) {
-
- }
- height += lineDim.Height();
- }
- return height;
- }
- void PCanvas::Restore()
- {
- State * old = stack.Pop();
- SetPenStyle(old->GetPenStyle());
- SetPenWidth(old->GetPenWidth());
- SetPenMode(old->GetPenMode());
- SetPenFgColour(old->GetPenFgColour());
- SetPenBkColour(old->GetPenBkColour());
- SetFillFgColour(old->GetFillFgColour());
- SetFillBkColour(old->GetFillBkColour());
- SetFillPattern(old->GetFillPattern());
- SetFillMode(old->GetFillMode());
- SetFont(old->font);
- SetTextFgColour(old->GetTextFgColour());
- SetTextBkColour(old->GetTextBkColour());
- SetPalette(old->GetPalette());
- SetPolyFillMode(old->GetPolyFillMode());
- SetViewportRect(old->GetViewportRect());
- SetMappingRect(old->GetMappingRect());
- delete old;
- }
- #endif
- //////////////////////////////////////////////////////////////////////////////
- // PInteractorCanvas
- #if defined(_PINTERACTORCANVAS)
- void PInteractorCanvas::Construct(BOOL inPixels)
- {
- PCanvasState::SetMappingRect(PRect(0, 0, 100, 100));
- if (inPixels)
- PCanvasState::SetViewportRect(map);
- else
- PCanvasState::SetViewportRect(PRect(0, 0,
- (PDIMENSION)interactor->ToPixelsX(100),
- (PDIMENSION)interactor->ToPixelsY(100)));
- const PColour & fgColour = interactor->GetForegroundColour();
- const PColour & bkColour = interactor->GetBackgroundColour();
- PCanvasState::SetPenFgColour(fgColour);
- PCanvasState::SetPenBkColour(bkColour);
- PCanvasState::SetFillFgColour(bkColour);
- PCanvasState::SetFillBkColour(fgColour);
- PCanvasState::SetTextFgColour(fgColour);
- PCanvasState::SetTextBkColour(bkColour);
- PCanvasState::SetFont(interactor->GetFont());
- }
- void PInteractorCanvas::Scroll(PORDINATE dx, PORDINATE dy)
- {
- Scroll(dx, dy, GetDrawingBounds());
- }
- void PInteractorCanvas::Scroll(const PPoint & amt)
- {
- Scroll(amt.X(), amt.Y(), GetDrawingBounds());
- }
- void PInteractorCanvas::Scroll(const PPoint & amt, const PRect & rect)
- {
- Scroll(amt.X(), amt.Y(), rect);
- }
- #endif
- //////////////////////////////////////////////////////////////////////////////
- // PMemoryCanvas
- PRect PMemoryCanvas::GetDrawingBounds() const
- {
- return FromPixels(PRect(0, 0, image->Width(), image->Height()));
- }
- #undef new
- // End Of File ///////////////////////////////////////////////////////////////