graph.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:27k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * graph.cxx
  3.  *
  4.  * Graphics classes implementation.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: graph.cxx,v $
  30.  * Revision 1.27  1999/08/17 03:46:41  robertj
  31.  * Fixed usage of inlines in optimised version.
  32.  *
  33.  * Revision 1.26  1998/12/12 00:44:03  robertj
  34.  * Added functions for user request on printing selection only.
  35.  * Fixed transfer of start and end pages from PPrintDialog.
  36.  *
  37.  * Revision 1.25  1998/10/15 11:32:55  robertj
  38.  * New memory leak detection system.
  39.  *
  40.  * Revision 1.24  1998/09/24 03:42:42  robertj
  41.  * Added open software license.
  42.  *
  43.  * Revision 1.23  1998/09/07 14:34:01  robertj
  44.  * Fixed setting of print info parameters from DEVMODE structure.
  45.  *
  46.  * Revision 1.22  1998/09/04 07:01:38  robertj
  47.  * Added a lot of DEVMODE infor for win95 to propagate from PrintDlg to PPrintCanvas.
  48.  *
  49.  * Revision 1.21  1998/01/26 00:20:42  robertj
  50.  * Fixed creation of pattern bitmaps (word alignment).
  51.  *
  52.  * Revision 1.20  1997/04/27 05:50:29  robertj
  53.  * DLL support.
  54.  *
  55.  * Revision 1.19  1996/10/31 12:39:56  robertj
  56.  * Added RCS keywords.
  57.  *
  58.  */
  59. #include <pwlib.h>
  60. #if !P_USE_INLINES
  61. #include <pwlib/graphics.inl>
  62. #endif
  63. #define new PNEW
  64. ///////////////////////////////////////////////////////////////////////////////
  65. PPoint::PPoint(DWORD dw)
  66. {
  67. #if defined(_WIN32)
  68.   POINTS ps = MAKEPOINTS(dw);
  69.   p.x = ps.x;
  70.   p.y = ps.y;
  71. #else
  72.   p = MAKEPOINT(dw);
  73. #endif
  74. }
  75. ///////////////////////////////////////////////////////////////////////////////
  76. PRect::PRect(PORDINATE x, PORDINATE y, PDIMENSION dx, PDIMENSION dy)
  77. {
  78.   r.left = x;
  79.   r.top = y;
  80.   r.right = x + dx;
  81.   r.bottom = y + dy;
  82. }
  83. PRect::PRect(const PDim & dim)
  84. {
  85.   r.left = r.top = 0;
  86.   r.right = dim.Width();
  87.   r.bottom = dim.Height();
  88. }
  89. PRect::PRect(const PPoint & p1, const PPoint & p2)
  90. {
  91.   if (p1.X() > p2.X()) {
  92.     r.left = p2.X();
  93.     r.right = p1.X();
  94.   }
  95.   else {
  96.     r.left = p1.X();
  97.     r.right = p2.X();
  98.   }
  99.   if (p1.Y() > p2.Y()) {
  100.     r.top = p2.Y();
  101.     r.bottom = p1.Y();
  102.   }
  103.   else {
  104.     r.top = p1.Y();
  105.     r.bottom = p2.Y();
  106.   }
  107. }
  108. PRect::PRect(const PPoint & topLeft, const PDim & dim)
  109. {
  110.   r.left = topLeft.X();
  111.   r.top = topLeft.Y();
  112.   r.right = topLeft.X() + dim.Width();
  113.   r.bottom = topLeft.Y() + dim.Height();
  114. }
  115. PObject::Comparison PRect::Compare(const PObject & obj) const
  116. {
  117.   PAssert(obj.IsDescendant(PRect::Class()), PInvalidCast);
  118.   return EqualRect(&r, &((const PRect &)obj).r) ? EqualTo : GreaterThan;
  119. }
  120. void PRect::SetX(PORDINATE nx)
  121. {
  122.   PORDINATE diff = nx - (PORDINATE)r.left;
  123.   r.left = nx;
  124.   r.right += diff;
  125. }
  126. void PRect::SetY(PORDINATE ny)
  127. {
  128.   PORDINATE diff = ny - (PORDINATE)r.top;
  129.   r.top = ny;
  130.   r.bottom += diff;
  131. }
  132. void PRect::SetTop(PORDINATE t)
  133. {
  134.   r.top = t;
  135.   if (t > r.bottom)
  136.     r.bottom = t;
  137. }
  138. void PRect::SetLeft(PORDINATE l)
  139. {
  140.   r.left = l;
  141.   if (l > r.right)
  142.     r.right = l;
  143. }
  144. void PRect::SetBottom(PORDINATE b)
  145. {
  146.   r.bottom = b;
  147.   if (b < r.top)
  148.     r.top = b;
  149. }
  150. void PRect::SetRight(PORDINATE rt)
  151. {
  152.   r.right = rt;
  153.   if (rt < r.left)
  154.     r.left = rt;
  155. }
  156. PRect PRect::Intersection(const PRect & rect) const
  157. {
  158.   PRect newRect;
  159.   IntersectRect(newRect, &r, rect);
  160.   return newRect;
  161. }
  162. PRect PRect::Union(const PRect & rect) const
  163. {
  164.   PRect newRect;
  165.   UnionRect(newRect, &r, rect);
  166.   return newRect;
  167. }
  168. ///////////////////////////////////////////////////////////////////////////////
  169. PRegion::PRegion(const PRect & rect)
  170. {
  171.   hRegion = CreateRectRgnIndirect(rect);
  172.   PAssertNULL(hRegion);
  173. }
  174. PRegion::PRegion(const PRegion & rgn)
  175. {
  176.   hRegion = CreateRectRgn(0, 0, 0, 0);
  177.   PAssertNULL(hRegion);
  178.   PAssertOS(CombineRgn(hRegion, rgn.hRegion, NULL, RGN_COPY) != ERROR);
  179. }
  180. PRegion & PRegion::operator=(const PRegion & rgn)
  181. {
  182.   PAssertOS(DeleteObject(hRegion));
  183.   hRegion = CreateRectRgn(0, 0, 0, 0);
  184.   PAssertNULL(hRegion);
  185.   PAssertOS(CombineRgn(hRegion, rgn.hRegion, NULL, RGN_COPY) != ERROR);
  186.   return *this;
  187. }
  188. PObject::Comparison PRegion::Compare(const PObject & obj) const
  189. {
  190.   PAssert(obj.IsDescendant(PRegion::Class()), PInvalidCast);
  191.   return EqualRgn(hRegion, ((const PRegion &)obj).hRegion)
  192.                                                        ? EqualTo : GreaterThan;
  193. }
  194. void PRegion::Add(const PRect & rect)
  195. {
  196.   HRGN hRgnNew = CreateRectRgn(0, 0, 0, 0);
  197.   HRGN hRgnRect = CreateRectRgnIndirect(rect);
  198.   PAssertNULL(hRgnNew);
  199.   PAssertNULL(hRgnRect);
  200.   PAssertOS(CombineRgn(hRgnNew, hRegion, hRgnRect, RGN_OR) != ERROR);
  201.   PAssertOS(DeleteObject(hRgnRect));
  202.   PAssertOS(DeleteObject(hRegion));
  203.   hRegion = PAssertNULL(hRgnNew);
  204. }
  205. void PRegion::Add(const PRegion & rgn)
  206. {
  207.   HRGN hRgnNew = CreateRectRgn(0, 0, 0, 0);
  208.   PAssertNULL(hRgnNew);
  209.   PAssertOS(CombineRgn(hRgnNew, hRegion, rgn.hRegion, RGN_OR) != ERROR);
  210.   PAssertOS(DeleteObject(hRegion));
  211.   hRegion = PAssertNULL(hRgnNew);
  212. }
  213. BOOL PRegion::OverlapsRect(const PRect & rect) const
  214. {
  215.   HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
  216.   HRGN hRect = CreateRectRgnIndirect(rect);
  217.   PAssertNULL(hRgn);
  218.   PAssertNULL(hRect);
  219.   PAssertOS(CombineRgn(hRgn, hRect, hRegion, RGN_AND) != ERROR);
  220.   PAssertOS(DeleteObject(hRect));
  221.   RECT dummy;
  222.   BOOL empty = GetRgnBox(PAssertNULL(hRgn), &dummy) == NULLREGION;
  223.   PAssertOS(DeleteObject(hRgn));
  224.   return !empty;
  225. }
  226. BOOL PRegion::IsEmpty() const
  227. {
  228.   RECT dummy;
  229.   return GetRgnBox(hRegion, &dummy) == NULLREGION;
  230. }
  231. PRect PRegion::GetBounds() const
  232. {
  233.   PRect rect;
  234.   GetRgnBox(hRegion, rect);
  235.   return rect;
  236. }
  237. PRegion PRegion::Intersection(const PRegion & rgn) const
  238. {
  239.   HRGN hRgnNew = CreateRectRgn(0, 0, 0, 0);
  240.   PAssertNULL(hRgnNew);
  241.   PAssertOS(CombineRgn(hRgnNew, hRegion, rgn.hRegion, RGN_AND) != ERROR);
  242.   return PRegion(PAssertNULL(hRgnNew));
  243. }
  244. PRegion PRegion::Union(const PRegion & rgn) const
  245. {
  246.   HRGN hRgnNew = CreateRectRgn(0, 0, 0, 0);
  247.   PAssertNULL(hRgnNew);
  248.   PAssertOS(CombineRgn(hRgnNew, hRegion, rgn.hRegion, RGN_OR) != ERROR);
  249.   return PRegion(PAssertNULL(hRgnNew));
  250. }
  251. ///////////////////////////////////////////////////////////////////////////////
  252. PColour::PColour(const PString & description)
  253. {
  254.   memset(component, 0, sizeof(component));
  255.   PStringArray compstr = description.Tokenise(" ,");
  256.   switch (compstr.GetSize()) {
  257.     case 4 :
  258.       component[AlphaComponent] = (BYTE)compstr[3].AsInteger();
  259.       // Then execute next case
  260.     case 3 :
  261.       component[BlueComponent] = (BYTE)compstr[2].AsInteger();
  262.       // Then execute next case
  263.     case 2 :
  264.       component[GreenComponent] = (BYTE)compstr[1].AsInteger();
  265.       // Then execute next case
  266.     case 1 :
  267.       component[RedComponent] = (BYTE)compstr[0].AsInteger();
  268.   }
  269. }
  270. PString PColour::GetDescription() const
  271. {
  272.   return psprintf("%u,%u,%u,%u", GetRed(), GetGreen(), GetBlue(), GetAlpha());
  273. }
  274. PColour & PColour::FromCOLORREF(COLORREF col)
  275. {
  276.   component[RedComponent] = GetRValue(col);
  277.   component[GreenComponent] = GetGValue(col);
  278.   component[BlueComponent] = GetBValue(col);
  279.   component[AlphaComponent] = 0xff;
  280.   return *this;
  281. }
  282. //////////////////////////////////////////////////////////////////////////////
  283. #ifdef NOTYET
  284. PRealColour::PRealColour()
  285. {
  286.   HDC hDC = CreateCompatibleDC(NULL);
  287.   FromCOLORREF(GetNearestColor(hDC, ToCOLORREF()));
  288.   DeleteDC(hDC);
  289. }
  290. PRealColour::PRealColour(const PColour & colour)
  291.   : PColour(colour)
  292. {
  293.   if (colour.GetAlpha() != 0) {
  294.     HDC hDC = CreateCompatibleDC(NULL);
  295.     FromCOLORREF(GetNearestColor(hDC, colour.ToCOLORREF()));
  296.     DeleteDC(hDC);
  297.   }
  298. }
  299. #endif
  300. PRealColour::PRealColour(PCanvas & canvas, const PColour & colour)
  301.   : PColour(colour)
  302. {
  303.   if (colour.GetAlpha() != 0)
  304.     FromCOLORREF(GetNearestColor(canvas.GetHDC(), colour.ToCOLORREF()));
  305. }
  306. //////////////////////////////////////////////////////////////////////////////
  307. PPalette::PPalette()
  308. {
  309.   LOGPALETTE logPal;
  310.   logPal.palVersion = 0x300;
  311.   logPal.palNumEntries = 1;
  312.   logPal.palPalEntry[0].peRed = 0;
  313.   logPal.palPalEntry[0].peGreen = 0;
  314.   logPal.palPalEntry[0].peBlue = 0;
  315.   logPal.palPalEntry[0].peFlags = 0;
  316.   hPalette = CreatePalette(&logPal);
  317.   PAssertNULL(hPalette);
  318. }
  319. void PPalette::DestroyContents()
  320. {
  321.   PAssertOS(DeleteObject(hPalette));
  322. }
  323. PObject::Comparison PPalette::Compare(const PObject & obj) const
  324. {
  325.   PAssert(obj.IsDescendant(PPalette::Class()), PInvalidCast);
  326.   return hPalette == ((const PPalette &)obj).hPalette ? EqualTo : GreaterThan;
  327. }
  328. PINDEX PPalette::AddColour(const PColour & colour)
  329. {
  330.   PINDEX count = GetSize();
  331.   PAssertOS(SetColour(count, colour));
  332.   return count;
  333. }
  334. BOOL PPalette::RemoveColour(const PColour & colour)
  335. {
  336.   PINDEX index = GetNearestPaletteIndex(hPalette, colour.ToCOLORREF());
  337.   if (colour != GetColour(index))
  338.     return FALSE;
  339.   return RemoveColour(index);
  340. }
  341. BOOL PPalette::RemoveColour(PINDEX index)
  342. {
  343.   PINDEX numColours = GetSize()-1;
  344.   if (index > numColours)
  345.     return FALSE;
  346.   PINDEX colourCount = numColours - index;
  347.   if (colourCount > 0) {
  348.     PALETTEENTRY * entries = new PALETTEENTRY[colourCount];
  349.     GetPaletteEntries(hPalette, index+1, colourCount, entries);
  350.     SetPaletteEntries(hPalette, index, colourCount, entries);
  351.     delete [] entries;
  352.   }
  353.   return ResizePalette(hPalette, numColours);
  354. }
  355. BOOL PPalette::HasColour(const PColour & colour) const
  356. {
  357.   return GetColour(GetIndex(colour)) == colour;
  358. }
  359. PINDEX PPalette::GetIndex(const PColour & colour) const
  360. {
  361.   return GetNearestPaletteIndex(hPalette, colour.ToCOLORREF());
  362. }
  363. PColour PPalette::GetColour(PINDEX index) const
  364. {
  365.   PALETTEENTRY entry;
  366.   GetPaletteEntries(hPalette, index, 1, &entry);
  367.   return PColour(entry.peRed, entry.peGreen, entry.peBlue);
  368. }
  369. BOOL PPalette::SetColour(PINDEX index, const PColour & colour)
  370. {
  371.   if (!SetMinSize(index+1))
  372.     return FALSE;
  373.   PALETTEENTRY entry;
  374.   entry.peRed = colour.GetRed();
  375.   entry.peGreen = colour.GetGreen();
  376.   entry.peBlue = colour.GetBlue();
  377.   entry.peFlags = 0;
  378.   SetPaletteEntries(hPalette, index, 1, &entry);
  379.   return TRUE;
  380. }
  381. PINDEX PPalette::GetSize() const
  382. {
  383.   short count;
  384.   PAssertOS(GetObject(hPalette, sizeof(count), (LPSTR)&count)==sizeof(count));
  385.   return count;
  386. }
  387. BOOL PPalette::SetSize(PINDEX size)
  388. {
  389.   return ResizePalette(hPalette, size);
  390. }
  391. ///////////////////////////////////////////////////////////////////////////////
  392. PRealFont::PRealFont()
  393.   : PFont(PApplication::Current().GetSystemFont())
  394. {
  395.   Construct(CreateCompatibleDC(NULL));
  396. }
  397. PRealFont::PRealFont(const PFont & font)
  398.   : PFont(font)
  399. {
  400.   Construct(CreateCompatibleDC(NULL));
  401. }
  402. PRealFont::PRealFont(PCanvas & canvas, const PFont & font)
  403.   : PFont(font)
  404. {
  405.   Construct(CreateCompatibleDC(canvas.GetHDC()));
  406. }
  407. PRealFont::PRealFont(HFONT hFont)
  408.   : PFont("", 0)
  409. {
  410.   if (hFont == NULL)
  411.     hFont = (HFONT)GetStockObject(SYSTEM_FONT);
  412.   HDC dc = CreateCompatibleDC(NULL);
  413.   deviceResY = (PDIMENSION)GetDeviceCaps(dc, LOGPIXELSY);
  414.   PAssert(deviceResY != 0, PInvalidParameter);
  415.   LOGFONT lf;
  416.   GetObject(hFont, sizeof(lf), (LPSTR)&lf);
  417.   facename = PCaselessString(lf.lfFaceName);
  418.   size = PixelsToPointsY((PDIMENSION)PABS(lf.lfHeight));
  419.   styles = Regular;
  420.   if (lf.lfWeight > FW_NORMAL)
  421.     styles |= Bold;
  422.   if (lf.lfItalic)
  423.     styles |= Italic;
  424.   if (lf.lfUnderline)
  425.     styles |= Underline;
  426.   Construct(dc);
  427. }
  428. void PRealFont::Construct(HDC dc)
  429. {
  430.   SetMapMode(PAssertNULL(dc), MM_TEXT);
  431.   deviceResX = (PDIMENSION)GetDeviceCaps(dc, LOGPIXELSX);
  432.   PAssert(deviceResX != 0, PInvalidParameter);
  433.   deviceResY = (PDIMENSION)GetDeviceCaps(dc, LOGPIXELSY);
  434.   PAssert(deviceResY != 0, PInvalidParameter);
  435.   HFONT hFont = GetHFONT();
  436.   HGDIOBJ oldFont = SelectObject(dc, hFont);
  437.   TEXTMETRIC t;
  438.   GetTextMetrics(dc, &t);
  439.   PAssertOS(SelectObject(dc, PAssertNULL(oldFont)) != NULL);
  440.   PAssertOS(DeleteObject(hFont));
  441.   PAssertOS(DeleteDC(dc));
  442.   size = PixelsToPointsY((PDIMENSION)t.tmHeight);
  443.   height = PixelsToPointsY((PDIMENSION)(t.tmHeight + t.tmExternalLeading));
  444.   avgWidth = PixelsToPointsX((PDIMENSION)t.tmAveCharWidth);
  445.   maxWidth = PixelsToPointsX((PDIMENSION)t.tmMaxCharWidth);
  446.   ascent = PixelsToPointsY((PDIMENSION)t.tmAscent);
  447.   descent = PixelsToPointsY((PDIMENSION)t.tmDescent);
  448.   leading = PixelsToPointsY((PDIMENSION)t.tmExternalLeading);
  449.   styles = Regular;
  450.   if (t.tmWeight > FW_NORMAL)
  451.     styles |= Bold;
  452.   if (t.tmItalic)
  453.     styles |= Italic;
  454.   if (t.tmUnderlined)
  455.     styles |= Underline;
  456. }
  457. HFONT PRealFont::GetHFONT() const
  458. {
  459.   HFONT hFont = ::CreateFont(PointsToPixelsY(size), 0, 0, 0,
  460.                              (styles&Bold) != 0 ? FW_BOLD : FW_NORMAL,
  461.                              (BYTE)((styles&Italic) != 0),
  462.                              (BYTE)((styles&Underline) != 0),
  463.                              0, 0, 0, 0, 0, 0, facename);
  464.   return PAssertNULL(hFont);
  465. }
  466. PDIMENSION PRealFont::GetHeight(BOOL inPixels) const
  467. {
  468.   return inPixels ? PointsToPixelsY(height) : height;
  469. }
  470. PDIMENSION PRealFont::GetAvgWidth(BOOL inPixels) const
  471. {
  472.   return inPixels ? PointsToPixelsX(avgWidth) : avgWidth;
  473. }
  474. PDIMENSION PRealFont::GetMaxWidth(BOOL inPixels) const
  475. {
  476.   return inPixels ? PointsToPixelsX(maxWidth) : maxWidth;
  477. }
  478. PDIMENSION PRealFont::GetAscent(BOOL inPixels) const
  479. {
  480.   return inPixels ? PointsToPixelsY(ascent) : ascent;
  481. }
  482. PDIMENSION PRealFont::GetDescent(BOOL inPixels) const
  483. {
  484.   return inPixels ? PointsToPixelsY(descent) : descent;
  485. }
  486. PDIMENSION PRealFont::GetLeading(BOOL inPixels) const
  487. {
  488.   return inPixels ? PointsToPixelsY(leading) : leading;
  489. }
  490. ///////////////////////////////////////////////////////////////////////////////
  491. PPattern::PPattern()
  492. {
  493.   hBitmap = NULL;
  494.   bitmap.bmWidth = bitmap.bmHeight = 1;
  495. }
  496. PPattern::PPattern(PRESOURCE_ID resID)
  497. {
  498.   Construct(LoadBitmap(PApplication::Current().GetInstance(), MAKEINTRESOURCE(resID)));
  499. }
  500. PPattern::PPattern(Bits bits)
  501. {
  502.   BYTE wordAlignedBits[16];
  503.   memset(wordAlignedBits, 0, sizeof(wordAlignedBits));
  504.   PINDEX i;
  505.   for (i = 0; i < 8; i++)
  506.     wordAlignedBits[i*2] = bits[i];
  507.   Construct(CreateBitmap(8, 8, 1, 1, wordAlignedBits));
  508. }
  509. void PPattern::Construct(HBITMAP hBm)
  510. {
  511.   hBitmap = PAssertNULL(hBm);
  512.   GetObject(hBitmap, sizeof(bitmap), (LPSTR)&bitmap);
  513. }
  514. PObject::Comparison PPattern::Compare(const PObject & obj) const
  515. {
  516.   PAssert(obj.IsDescendant(PPattern::Class()), PInvalidCast);
  517.   return hBitmap == ((const PPattern &)obj).hBitmap ? EqualTo : GreaterThan;
  518. }
  519. void PPattern::DestroyContents()
  520. {
  521.   if (hBitmap != NULL)
  522.     PAssertOS(DeleteObject((HGDIOBJ)hBitmap));
  523. }
  524. void PPattern::CopyContents(const PPattern & pat)
  525. {
  526.   hBitmap = pat.hBitmap;
  527.   bitmap = pat.bitmap;
  528. }
  529. ///////////////////////////////////////////////////////////////////////////////
  530. PPixelBase::PPixelBase(PDIMENSION dx, PDIMENSION dy, BYTE depth)
  531.   : PImageBase(dx, dy)
  532. {
  533.   pixelLineBytes = (PINDEX)((((long)Width()*depth+31)/32)*4);
  534. #if defined(_WIN32)
  535.   pixels = (PPixelDataPtr)malloc((size_t)dy*pixelLineBytes);
  536. #else
  537.   pixels = (PPixelDataPtr)_halloc((long)dy*pixelLineBytes, 1);
  538. #endif
  539.   if (pixels == NULL)
  540.     memset(&info, 0, sizeof(info));
  541.   else {
  542.     info.biWidth = dx;
  543.     info.biHeight = dy;
  544.     info.biPlanes = 1;
  545.     info.biBitCount = depth;
  546.     info.biSizeImage = info.biHeight*pixelLineBytes;
  547.     info.biCompression = BI_RGB;
  548.     info.biXPelsPerMeter = 0;
  549.     info.biYPelsPerMeter = 0;
  550.     info.biClrImportant = 0;
  551.     info.biClrUsed = info.biBitCount < 24 ? (1 << info.biBitCount) : 0;
  552.   }
  553.   info.biSize = sizeof(info);
  554.   hBitmap = NULL;
  555. }
  556. PPixelBase::~PPixelBase()
  557. {
  558.   if (hBitmap != NULL)
  559.     PAssertOS(DeleteObject((HGDIOBJ)hBitmap));
  560. #if defined(_WIN32)
  561.     free(pixels);
  562. #else
  563.     _hfree(pixels);
  564. #endif
  565. }
  566. PObject::Comparison PPixelBase::Compare(const PObject & obj) const
  567. {
  568.   PAssert(obj.IsDescendant(PPixelBase::Class()), PInvalidCast);
  569.   return pixels == ((const PPixelBase &)obj).pixels ? EqualTo : GreaterThan;
  570. }
  571. PPixelBase::DIBInfo::DIBInfo(const PPixelBase & pix, HPALETTE hPal)
  572. {
  573.   PINDEX numColours = pix.palette.GetSize();
  574.   info = (BITMAPINFO *)malloc(
  575.                        sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*numColours);
  576.   PAssertNULL(info);
  577.   info->bmiHeader = pix.info;
  578.   if (info->bmiHeader.biBitCount >= 24)
  579.     colourUse = DIB_RGB_COLORS;
  580.   else if (pix.palette.GetHPALETTE() != hPal) {
  581.     colourUse = DIB_RGB_COLORS;
  582.     for (PINDEX i = 0; i < numColours; i++) {
  583.       PColour c = pix.palette.GetColour(i);
  584.       info->bmiColors[i].rgbRed   = c.GetRed();
  585.       info->bmiColors[i].rgbGreen = c.GetGreen();
  586.       info->bmiColors[i].rgbBlue  = c.GetBlue();
  587.       info->bmiColors[i].rgbReserved = 0;
  588.     }
  589.   }
  590.   else {
  591.     colourUse = DIB_PAL_COLORS;
  592.     WORD * wp = (WORD *)info->bmiColors;
  593.     for (PINDEX i = 0; i < numColours; i++)
  594.       *wp++ = (WORD)i;
  595.   }
  596. }
  597. HBITMAP PPixelBase::GetHBITMAP(HDC hDC) const
  598. {
  599.   DIBInfo dib(*this, NULL);
  600.   HDC tempDC = NULL;
  601.   if (hDC == NULL)
  602.     hDC = tempDC = CreateCompatibleDC(NULL);
  603.   HBITMAP hBm = CreateDIBitmap(hDC, dib, CBM_INIT, pixels, dib, dib.Usage());
  604.   if (tempDC)
  605.     DeleteDC(tempDC);
  606.   return hBm;
  607. }
  608. HDC PPixelBase::CreateImageDC()
  609. {
  610.   HDC hDC = CreateCompatibleDC(NULL);
  611.   hBitmap = GetHBITMAP(hDC);
  612.   PAssertOS(SelectObject(PAssertNULL(hDC), hBitmap) != NULL);
  613.   return hDC;
  614. }
  615. void PPixelBase::CloseImageDC(HDC hDC)
  616. {
  617.   PAssertOS(SelectObject(hDC, NULL) != NULL);
  618.   if (pixels != NULL)
  619.     GetBitmapBits(hBitmap, info.biSizeImage, pixels);
  620.   hBitmap = NULL;
  621. }
  622. PPixelDataPtr PPixelBase::GetRasterDataPtr(PORDINATE y) const
  623. {
  624.   PAssert(y >= 0 && (PDIMENSION)y < Height(), "Pixel out of bounds");
  625.   PAssert(pixels != NULL, "No pixel data");
  626.   return pixels + (long)(Height()-y-1)*pixelLineBytes;
  627. }
  628. PPixelImage::PPixelImage(PRESOURCE_ID resID)
  629. {
  630.   operator=(PPixelBase::CreateBitmap(LoadBitmap(
  631.               PApplication::Current().GetInstance(), MAKEINTRESOURCE(resID))));
  632. }
  633. PPixelImage PPixelBase::CreateBitmap(HBITMAP hBm)
  634. {
  635.   BITMAP bm;
  636.   PAssertOS(GetObject(PAssertNULL(hBm), sizeof(bm), (LPSTR)&bm) > 0);
  637.   PAssert(bm.bmPlanes == 1, PUnsupportedFeature);
  638.   PPixelImage pix((PDIMENSION)bm.bmWidth,
  639.                                (PDIMENSION)bm.bmHeight, (BYTE)bm.bmBitsPixel);
  640.   if (pix->pixels != NULL)
  641.     GetBitmapBits(hBm, pix->info.biSizeImage, pix->pixels);
  642.   return pix;
  643. }
  644. BOOL PPixelBase::Write(PFile & bmpFile)
  645. {
  646.   if (!bmpFile.IsOpen())
  647.     return FALSE;
  648.   BITMAPFILEHEADER bmfh;
  649.   bmfh.bfType = 0x4d42 /*'BM'*/;
  650.   bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) +
  651.                    sizeof(BITMAPINFOHEADER) + info.biClrUsed*sizeof(RGBQUAD);
  652.   bmfh.bfSize = bmfh.bfOffBits + info.biSizeImage;
  653.   bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
  654.   if (!bmpFile.Write(&bmfh, sizeof(bmfh)))
  655.     return FALSE;
  656.   if (!bmpFile.Write(&info, sizeof(info)))
  657.     return FALSE;
  658.   for (PINDEX i = 0; i < (PINDEX)info.biClrUsed; i++) {
  659.     PColour colour = palette.GetColour(i);
  660.     RGBQUAD rgb;
  661.     rgb.rgbRed = colour.GetRed();
  662.     rgb.rgbGreen = colour.GetGreen();
  663.     rgb.rgbBlue = colour.GetBlue();
  664.     rgb.rgbReserved = 0;
  665.     if (!bmpFile.Write(&rgb, sizeof(rgb)))
  666.       return FALSE;
  667.   }
  668.   if (pixels == NULL)
  669.     return FALSE;
  670. #if defined(_WIN32)
  671.   return bmpFile.Write(pixels, (PINDEX)info.biSizeImage);
  672. #else
  673.   return _hwrite(bmpFile.GetHandle(),
  674.                             pixels, info.biSizeImage) == (long)info.biSizeImage;
  675. #endif
  676. }
  677. ///////////////////////////////////////////////////////////////////////////////
  678. PPictBase::PPictBase()
  679.   : PImageBase(0, 0)
  680. {
  681.   hMetafile = NULL;
  682. }
  683. PPictBase::PPictBase(PFile & dwg)
  684.   : PImageBase(0, 0)
  685. {
  686.   dwg.Close();
  687. #if defined(_WIN32)
  688.   hMetafile = GetEnhMetaFile(dwg.GetFilePath());
  689. #else
  690.   hMetafile = GetMetaFile(dwg.GetFilePath());
  691. #endif
  692. }
  693. PPictBase::PPictBase(PRESOURCE_ID)
  694.   : PImageBase(0, 0)
  695. {
  696.   hMetafile = NULL;
  697. }
  698. PPictBase::PPictBase(PMETAFILE hM)
  699.   : PImageBase(0, 0)
  700. {
  701.   hMetafile = PAssertNULL(hM);
  702. }
  703. PPictBase::~PPictBase()
  704. {
  705. #if defined(_WIN32)
  706.   PAssertOS(DeleteEnhMetaFile(hMetafile));
  707. #else
  708.   PAssertOS(DeleteMetaFile(hMetafile));
  709. #endif
  710. }
  711. PObject::Comparison PPictBase::Compare(const PObject & obj) const
  712. {
  713.   PAssert(obj.IsDescendant(PPictBase::Class()), PInvalidCast);
  714.   return hMetafile==((const PPictBase &)obj).hMetafile ? EqualTo : GreaterThan;
  715. }
  716. HDC PPictBase::CreateImageDC()
  717. {
  718. #if defined(_WIN32)
  719.   HDC hDC = CreateEnhMetaFile(NULL, NULL, NULL, "PWLib");
  720. #else
  721.   HDC hDC = CreateMetaFile(NULL);
  722. #endif
  723.   return PAssertNULL(hDC);
  724. }
  725. void PPictBase::CloseImageDC(HDC hDC)
  726. {
  727. #if defined(_WIN32)
  728.   hMetafile = CloseEnhMetaFile(hDC);
  729. #else
  730.   hMetafile = CloseMetaFile(hDC);
  731. #endif
  732. }
  733. BOOL PPictBase::Write(PFile & dwg)
  734. {
  735.   dwg.Close();
  736. #if defined(_WIN32)
  737.   HENHMETAFILE hCopy = CopyEnhMetaFile(hMetafile, dwg.GetFilePath());
  738.   return DeleteEnhMetaFile(PAssertNULL(hCopy));
  739. #else
  740.   HMETAFILE hCopy = CopyMetaFile(hMetafile, dwg.GetFilePath());
  741.   return DeleteMetaFile(PAssertNULL(hCopy));
  742. #endif
  743. }
  744. ///////////////////////////////////////////////////////////////////////////////
  745. PPrintInfo::PPrintInfo()
  746. {
  747.   form = A4;
  748.   startPage = 1;
  749.   endPage = UINT_MAX;
  750.   selectionOnly = NoSelectionOnly;
  751.   copies = 1;
  752.   orientation = TRUE;
  753.   draftQuality = TRUE;
  754.   PRINTDLG printDlg;
  755.   memset(&printDlg, 0, sizeof(printDlg));
  756.   printDlg.lStructSize = sizeof(printDlg);
  757.   printDlg.Flags = PD_RETURNDEFAULT;
  758.   PAssertOS(PrintDlg(&printDlg));
  759.   SetFromPrintDlg(printDlg);
  760.   if (printDlg.hDevMode != NULL)
  761.     GlobalFree(printDlg.hDevMode);
  762.   if (printDlg.hDevNames != NULL)
  763.     GlobalFree(printDlg.hDevNames);
  764. }
  765. PPrintInfo::PPrintInfo(const PString & printerType,const PString & devicePort)
  766.   : driver("WINSPOOL"),
  767.     device(devicePort),
  768.     printer(printerType)
  769. {
  770.   form = A4;
  771.   startPage = 0;
  772.   endPage = (unsigned)-1;
  773.   copies = 1;
  774.   orientation = TRUE;
  775.   draftQuality = TRUE;
  776. #if defined(_WIN32)
  777.   HANDLE          hPrinter;
  778.   if (OpenPrinter((char *)(const char *)printerType, &hPrinter, NULL)) {
  779.     devModeBuffer.SetSize(DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0));
  780.     if (DocumentProperties(NULL, hPrinter, NULL, GetDEVMODE(), NULL, DM_OUT_BUFFER) == IDOK)
  781.       ProcessDEVMODE();
  782.     PAssertOS(ClosePrinter(hPrinter));
  783.   }
  784. #else
  785.   char devLib[_MAX_PATH];
  786.   GetProfileString("devices", printerType, "", devLib, sizeof(devLib));
  787.   char * comma = strchr(devLib, ',');
  788.   if (comma != NULL)
  789.     *comma = '';
  790.   strcat(devLib, ".DRV");
  791.   HMODULE hDriver = LoadLibrary(devLib);
  792.   if (hDriver >= HINSTANCE_ERROR) {
  793.     LPFNDEVMODE extDevMode = (LPFNDEVMODE)GetProcAddress(hDriver, PROC_EXTDEVICEMODE);
  794.     if (extDevMode != NULL) {
  795.       char devType[CCHDEVICENAME];
  796.       strcpy(devType, printerType);
  797.       char devPort[_MAX_PATH];
  798.       strcpy(devPort, devicePort);
  799.       LONG bufSize = extDevMode(NULL, hDriver, NULL, pDevMode, devPort, NULL, NULL, 0);
  800.       devMode = (LPDEVMODE)new char[bufSize];
  801.       if (extDevMode(NULL, hDriver, devMode, devType, devPort,
  802.                      NULL, NULL, DM_OUT_BUFFER) == IDOK) {
  803.         ProcessDEVMODE();
  804.         driver = devicePort;
  805.         printer = printerType;
  806.       }
  807.     }
  808.     FreeLibrary(hDriver);
  809.   }
  810. #endif
  811. }
  812. void PPrintInfo::SetFromPrintDlg(const PRINTDLG & printDlg)
  813. {
  814.   if (printDlg.hDevMode != NULL) {
  815.     devModeBuffer = PBYTEArray((BYTE *)GlobalLock(printDlg.hDevMode),
  816.                                        GlobalSize(printDlg.hDevMode));
  817.     GlobalUnlock(printDlg.hDevMode);
  818.     ProcessDEVMODE();
  819.   }
  820.   if (printDlg.hDevNames != NULL) {
  821.     LPSTR devNameBase = (LPSTR)GlobalLock(printDlg.hDevNames);
  822.     LPDEVNAMES devNames = (LPDEVNAMES)devNameBase;
  823.     driver = &devNameBase[devNames->wDriverOffset];
  824.     printer = &devNameBase[devNames->wDeviceOffset];
  825.     device = &devNameBase[devNames->wOutputOffset];
  826.     GlobalUnlock(printDlg.hDevNames);
  827.   }
  828.   if ((printDlg.Flags&PD_NOPAGENUMS) != 0 || (printDlg.Flags&PD_PAGENUMS) == 0) {
  829.     startPage = 0;
  830.     endPage = UINT_MAX;
  831.   }
  832.   else {
  833.     startPage = printDlg.nFromPage;
  834.     endPage = printDlg.nToPage;
  835.   }
  836.   if ((printDlg.Flags&PD_NOSELECTION) != 0)
  837.     selectionOnly = NoSelectionOnly;
  838.   else if ((printDlg.Flags&PD_SELECTION) != 0)
  839.     selectionOnly = SelectionOnlyOn;
  840.   else
  841.     selectionOnly = SelectionOnlyOff;
  842.   copies = printDlg.nCopies;
  843. }
  844. void PPrintInfo::ProcessDEVMODE()
  845. {
  846.   LPDEVMODE devMode = GetDEVMODE();
  847.   orientation = devMode->dmOrientation == DMORIENT_PORTRAIT;
  848.   const static struct {
  849.     short form;
  850.     PDIMENSION width;
  851.     PDIMENSION height;
  852.   } PaperSizes[PPrintInfo::MaxForm] = {
  853.     { 0,              0, 0 },
  854.     { DMPAPER_A3,     2970, 4200 },
  855.     { DMPAPER_A4,     2100, 2970 },
  856.     { DMPAPER_A5,     1485, 2100 },
  857.     { DMPAPER_B4,     2500, 3540 },
  858.     { DMPAPER_B5,     1820, 2570 },
  859.     { DMPAPER_LETTER, 2163, 2800 },
  860.     { DMPAPER_LEGAL,  2163, 3563 }
  861.   };
  862.   int f;
  863.   for (f = A3; f < MaxForm; f++) {
  864.     if (PaperSizes[f].form == devMode->dmPaperSize)
  865.       break;
  866.   }
  867.   form = (Forms)f;
  868.   if (form == Custom)
  869.     paperSize = PDim((PDIMENSION)devMode->dmPaperWidth,
  870.                      (PDIMENSION)devMode->dmPaperLength);
  871.   else if (orientation)
  872.     paperSize = PDim(PaperSizes[f].width, PaperSizes[f].height);
  873.   else
  874.     paperSize = PDim(PaperSizes[f].height, PaperSizes[f].width);
  875.   draftQuality = devMode->dmPrintQuality == DMRES_DRAFT;
  876.   if (devMode->dmPrintQuality > 0)
  877.     resolution = PDim((PDIMENSION)devMode->dmPrintQuality,
  878.                       (PDIMENSION)devMode->dmYResolution);
  879.   else
  880.     resolution = PDim();
  881.   copies = devMode->dmCopies;
  882. }
  883. LPDEVMODE PPrintInfo::GetDEVMODE() const
  884. {
  885.   PAssertOS(devModeBuffer.GetSize() > 0);
  886.   return (LPDEVMODE)(const BYTE *)devModeBuffer;
  887. }
  888. HANDLE PPrintInfo::GetHDEVMODE() const
  889. {
  890.   HANDLE h = GlobalAlloc(GHND, devModeBuffer.GetSize());
  891.   memcpy(GlobalLock(h), devModeBuffer, devModeBuffer.GetSize());
  892.   GlobalUnlock(h);
  893.   return h;
  894. }
  895. HANDLE PPrintInfo::GetDevNames() const
  896. {
  897.   PINDEX driverLen = driver.GetLength();
  898.   PINDEX printerLen = printer.GetLength();
  899.   PINDEX deviceLen = device.GetLength();
  900.   HANDLE h = GlobalAlloc(GHND, sizeof(DEVNAMES)+driverLen+printerLen+deviceLen+4);
  901.   LPDEVNAMES devNames = (LPDEVNAMES)GlobalLock(h);
  902.   devNames->wDriverOffset = sizeof(DEVNAMES);
  903.   devNames->wDeviceOffset = (WORD)(sizeof(DEVNAMES)+driverLen+1);
  904.   devNames->wOutputOffset = (WORD)(sizeof(DEVNAMES)+driverLen+printerLen+2);
  905.   LPSTR p = (LPSTR)devNames+sizeof(DEVNAMES);
  906.   strcpy(p, driver);
  907.   p += driverLen+1;
  908.   strcpy(p, printer);
  909.   p += printerLen+1;
  910.   strcpy(p, device);
  911.   GlobalUnlock(h);
  912.   return h;
  913. }
  914. // End Of File ///////////////////////////////////////////////////////////////