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

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * canvas.cxx
  3.  *
  4.  * Canvas 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: canvas.cxx,v $
  30.  * Revision 1.49  1999/02/16 08:08:07  robertj
  31.  * MSVC 6.0 compatibility changes.
  32.  *
  33.  * Revision 1.48  1998/10/15 11:32:53  robertj
  34.  * New memory leak detection system.
  35.  *
  36.  * Revision 1.47  1998/09/24 03:42:31  robertj
  37.  * Added open software license.
  38.  *
  39.  * Revision 1.46  1998/09/22 15:09:58  robertj
  40.  * Added delayed HDC creation in PDrawCanvas.
  41.  *
  42.  * Revision 1.45  1998/09/18 13:59:31  robertj
  43.  * Fixed FillRect leaving small gaps in pattern filled rectangles next to each other.
  44.  *
  45.  * Revision 1.44  1998/09/07 14:03:41  robertj
  46.  * Fixed printing transforms being reset after each page.
  47.  *
  48.  * Revision 1.43  1998/09/04 07:00:10  robertj
  49.  * Fixed double print dialog.
  50.  * Can now print more than one page.
  51.  * Fixed uninitialised variable for win95 StartDoc()
  52.  *
  53.  * Revision 1.42  1998/03/20 03:13:25  robertj
  54.  * Added function to get physical bounds of canvas. Allows to scale drawing.
  55.  *
  56.  * Revision 1.41  1996/10/31 12:39:55  robertj
  57.  * Added RCS keywords.
  58.  *
  59.  */
  60. #include <pwlib.h>
  61. #define new PNEW
  62. PCanvas::PCanvas()
  63.   : _hDC(NULL),
  64.     _hPen((HPEN)GetStockObject(BLACK_PEN)),
  65.     _hBrush((HBRUSH)GetStockObject(HOLLOW_BRUSH)),
  66.     _hFont(NULL)
  67. {
  68.   deviceResX = deviceResY = 1;
  69.   font = realFont;
  70. }
  71. PCanvas::~PCanvas()
  72. {
  73.   if (_hDC != NULL)
  74.     PAssertOS(DeleteDC(_hDC));
  75.   if (_hPen != NULL)
  76.     PAssertOS(DeleteObject(_hPen));
  77.   if (_hBrush != NULL)
  78.     PAssertOS(DeleteObject(_hBrush));
  79.   if (_hFont != NULL)
  80.     PAssertOS(DeleteObject(_hFont));
  81. }
  82. PCanvasState & PCanvas::operator=(const PCanvasState & state)
  83. {
  84.   PCanvasState::operator=(state);
  85.   if (_hDC != NULL)
  86.     SetHDC(_hDC);
  87.   return *this;
  88. }
  89. PObject::Comparison PCanvas::Compare(const PObject & obj) const
  90. {
  91.   PAssert(obj.IsDescendant(PCanvas::Class()), PInvalidCast);
  92.   return _hDC == ((const PCanvas &)obj)._hDC ? EqualTo : GreaterThan;
  93. }
  94. int PEXPORTED PEnumFontFamilyProc(const ENUMLOGFONT FAR * lpelf,
  95.                                  const NEWTEXTMETRIC FAR *,
  96.                                  int fontType,
  97.                                  LPARAM lParam)
  98. {
  99.   PFontFamily * family = new PFontFamily(lpelf->elfLogFont.lfFaceName);
  100.   family->scalable = (fontType & RASTER_FONTTYPE) == 0;
  101.   ((PFontFamilyList *)lParam)->Append(family);
  102.   return TRUE;
  103. }
  104. int PEXPORTED PEnumFontFaceProc(const ENUMLOGFONT FAR * lpelf,
  105.                                const NEWTEXTMETRIC FAR * lpntm,
  106.                                int fontType,
  107.                                LPARAM lParam)
  108. {
  109.   PFontFamily * family = (PFontFamily *)lParam;
  110.   if ((fontType & TRUETYPE_FONTTYPE) != 0) {
  111.     if (family->sizes.GetSize() == 0) {
  112.       WORD sizes[] = {
  113.         8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72
  114.       };
  115.       family->sizes = PWORDArray(sizes, PARRAYSIZE(sizes));
  116.     }
  117.     WORD style = PFont::Regular;
  118.     if ((lpntm->ntmFlags&0x20) != 0)
  119.       style |= PFont::Bold;
  120.     if ((lpntm->ntmFlags&1) != 0)
  121.       style |= PFont::Italic;
  122.     if ((lpntm->ntmFlags&2) != 0)
  123.       style |= PFont::Underline;
  124.     family->styles[family->styles.GetSize()] = style;
  125.     family->styleNames[family->styleNames.GetSize()] =
  126.                                         PString((const char *)lpelf->elfStyle);
  127.   }
  128.   else {
  129.     family->sizes[family->sizes.GetSize()] = (WORD)lpelf->elfLogFont.lfHeight;
  130.     if (family->styles.GetSize() == 0) {
  131.       family->sizes[0] = 0;
  132.       if (lpelf->elfStyle[0] != '')
  133.         family->styleNames[0] = PString((const char *)lpelf->elfStyle);
  134.       else
  135.         family->styleNames[0] = "Regular";
  136.     }
  137.   }
  138.   return TRUE;
  139. }
  140. PFontFamilyList PCanvas::GetAvailableFonts() const
  141. {
  142.   PFontFamilyList list;
  143.   EnumFontFamilies(GetHDC(),
  144.                        NULL, (FONTENUMPROC)PEnumFontFamilyProc, (LPARAM)&list);
  145.   for (PINDEX i = 0; i < list.GetSize(); i++)
  146.     EnumFontFamilies(GetHDC(), list[i].GetFacename(),
  147.                             (FONTENUMPROC)PEnumFontFaceProc, (LPARAM)&list[i]);
  148.   return list;
  149. }
  150. void PCanvas::SetHDC(HDC newDC)
  151. {
  152.   _hDC = PAssertNULL(newDC);
  153.   deviceResX = GetDeviceCaps(_hDC, LOGPIXELSX);
  154.   deviceResY = GetDeviceCaps(_hDC, LOGPIXELSY);
  155.   realFont = PRealFont(*this, font);
  156.   SetMapMode(_hDC, MM_ANISOTROPIC);
  157.   SetTransform();
  158.   MakePen();
  159.   MakeBrush();
  160. #if defined(_WIN32)
  161.   SetBrushOrgEx(GetHDC(), patternOrigin.X(), patternOrigin.Y(), NULL);
  162. #else
  163.   SetBrushOrg(GetHDC(), patternOrigin.X(), patternOrigin.Y());
  164. #endif
  165.   PAssertOS(SelectPalette(_hDC, palette.GetHPALETTE(), TRUE) != NULL);
  166.   ::SetPolyFillMode(_hDC, polyFillMode == Winding ? WINDING : ALTERNATE);
  167.   SetTextAlign(_hDC, TA_LEFT|TA_TOP|TA_NOUPDATECP);
  168. }
  169. BOOL PCanvas::SetPenStyle(PenStyles style)
  170. {
  171.   if (PCanvasState::SetPenStyle(style)) {
  172.     MakePen();
  173.     return TRUE;
  174.   }
  175.   return FALSE;
  176. }
  177. BOOL PCanvas::SetPenWidth(int width)
  178. {
  179.   if (PCanvasState::SetPenWidth(width)) {
  180.     MakePen();
  181.     return TRUE;
  182.   }
  183.   return FALSE;
  184. }
  185. BOOL PCanvas::SetPenFgColour(const PColour & colour)
  186. {
  187.   if (PCanvasState::SetPenFgColour(colour)) {
  188.     MakePen();
  189.     return TRUE;
  190.   }
  191.   return FALSE;
  192. }
  193. void PCanvas::MakePen()
  194. {
  195.   HPEN oldPen = _hPen;
  196.   if (penFgColour.GetAlpha() == 0)
  197.     _hPen = (HPEN)GetStockObject(NULL_PEN);
  198.   else {
  199.     static int msStyle[] = { PS_SOLID, PS_DOT, PS_DASH, PS_DASHDOT };
  200.     PAssert(penStyle < sizeof(msStyle)/sizeof(msStyle[0]), PInvalidParameter);
  201.     _hPen = CreatePen(msStyle[penStyle],
  202.                           penWidth, penFgColour.ToCOLORREF());
  203.   }
  204.   PAssertNULL(_hPen);
  205.   if (_hDC != NULL)
  206.     PAssertOS(SelectObject(_hDC, _hPen) != NULL);
  207.   if (oldPen != NULL)
  208.     PAssertOS(DeleteObject(oldPen));
  209. }
  210. BOOL PCanvas::SetFillPattern(const PPattern & pattern)
  211. {
  212.   if (PCanvasState::SetFillPattern(pattern)) {
  213.     MakeBrush();
  214.     return TRUE;
  215.   }
  216.   return FALSE;
  217. }
  218. BOOL PCanvas::SetPatternOrigin(const PPoint & pt)
  219. {
  220.   if (PCanvasState::SetPatternOrigin(pt)) {
  221. #ifdef WIN32
  222.     SetBrushOrgEx(GetHDC(), pt.X(), pt.Y(), NULL);
  223. #else
  224.     SetBrushOrg(GetHDC(), pt.X(), pt.Y());
  225. #endif
  226.     return TRUE;
  227.   }
  228.   return FALSE;
  229. }
  230. BOOL PCanvas::SetFillFgColour(const PColour & colour)
  231. {
  232.   if (PCanvasState::SetFillFgColour(colour)) {
  233.     MakeBrush();
  234.     return TRUE;
  235.   }
  236.   return FALSE;
  237. }
  238. void PCanvas::MakeBrush()
  239. {
  240.   HBRUSH oldBrush = _hBrush;
  241.   if (fillFgColour.GetAlpha() == 0)
  242.     _hBrush = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
  243.   else if (fillPattern.GetHBITMAP() == NULL)
  244.     _hBrush = CreateSolidBrush(fillFgColour.ToCOLORREF());
  245.   else
  246.     _hBrush = CreatePatternBrush(fillPattern.GetHBITMAP());
  247.   PAssertNULL(_hBrush);
  248.   if (_hDC != NULL)
  249.     PAssertOS(SelectObject(_hDC, _hBrush) != NULL);
  250.   if (oldBrush != NULL)
  251.     PAssertOS(DeleteObject(oldBrush));
  252. }
  253. BOOL PCanvas::SetFont(const PFont & newFont)
  254. {
  255.   if (!PCanvasState::SetFont(newFont))
  256.     return FALSE;
  257.   GetHDC();
  258.   realFont = PRealFont(*this, newFont);
  259.   MakeFont();
  260.   return TRUE;
  261. }
  262. void PCanvas::MakeFont()
  263. {
  264.   HFONT oldFont = _hFont;
  265.   _hFont = CreateFont(FromPointsY(realFont.GetHeight()),
  266.                      0, 0, 0,
  267.                      realFont.IsBold() ? FW_BOLD : FW_NORMAL,
  268.                      (BYTE)realFont.IsItalic(),
  269.                      (BYTE)realFont.IsUnderlined(),
  270.                      0, 0, 0, 0, 0, 0,
  271.                      realFont.GetFacename());
  272.   PAssertNULL(_hFont);
  273.   if (_hDC != NULL)
  274.     PAssertOS(SelectObject(_hDC, _hFont) != NULL);
  275.   if (oldFont != NULL)
  276.     PAssertOS(DeleteObject(oldFont));
  277. }
  278. BOOL PCanvas::SetPalette(const PPalette & newPal)
  279. {
  280.   if (PCanvasState::SetPalette(newPal)) {
  281.     if (_hDC != NULL)
  282.       PAssertOS(SelectPalette(_hDC, palette.GetHPALETTE(), TRUE) != NULL);
  283.     return TRUE;
  284.   }
  285.   return FALSE;
  286. }
  287. BOOL PCanvas::SetPolyFillMode(PolyFillMode newMode)
  288. {
  289.   if (PCanvasState::SetPolyFillMode(newMode)) {
  290.     if (_hDC != NULL)
  291.       ::SetPolyFillMode(_hDC, polyFillMode == Winding ? WINDING : ALTERNATE);
  292.     return TRUE;
  293.   }
  294.   return FALSE;
  295. }
  296. BOOL PCanvas::SetViewportRect(const PRect & rect)
  297. {
  298.   if (PCanvasState::SetViewportRect(rect)) {
  299.     SetTransform();
  300.     return TRUE;
  301.   }
  302.   return FALSE;
  303. }
  304. BOOL PCanvas::SetMappingRect(const PRect & rect)
  305. {
  306.   if (PCanvasState::SetMappingRect(rect)) {
  307.     SetTransform();
  308.     return TRUE;
  309.   }
  310.   return FALSE;
  311. }
  312. void PCanvas::SetTransform()
  313. {
  314.   if (_hDC == NULL)
  315.     return;
  316.   SetViewportOrgEx(_hDC, viewport.Left(), viewport.Top(), NULL);
  317.   SetViewportExtEx(_hDC, viewport.Width(), viewport.Height(), NULL);
  318.   SetWindowOrgEx(_hDC, map.Left(), map.Top(), NULL);
  319.   SetWindowExtEx(_hDC, map.Width(), map.Height(), NULL);
  320.   if (GetPenWidth() != 0)
  321.     MakePen();
  322.   MakeFont();
  323. }
  324. void PCanvas::MoveCurrentPosition(PORDINATE x, PORDINATE y)
  325. {
  326.   POINT p;
  327.   PAssertOS(GetCurrentPositionEx(GetHDC(), &p));
  328.   MoveToEx(_hDC, p.x+x, p.y+y, NULL);
  329. }
  330. PPoint PCanvas::GetCurrentPosition() const
  331. {
  332.   PPoint p;
  333.   PAssertOS(::GetCurrentPositionEx(GetHDC(), p));
  334.   return p;
  335. }
  336. void PCanvas::DrawLine(PORDINATE x, PORDINATE y)
  337. {
  338.   SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  339.   LineTo(GetHDC(), x, y);
  340. }
  341. void PCanvas::DrawLine(PORDINATE x1, PORDINATE y1, PORDINATE x2, PORDINATE y2)
  342. {
  343.   SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  344.   POINT p;
  345.   MoveToEx(GetHDC(), x1, y1, &p);
  346.   LineTo(_hDC, x2, y2);
  347.   MoveToEx(_hDC, (int)p.x, (int)p.y, NULL);
  348. }
  349. void PCanvas::DrawLineRelative(PORDINATE x, PORDINATE y)
  350. {
  351.   SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  352.   POINT p;
  353.   PAssertOS(GetCurrentPositionEx(GetHDC(), &p));
  354.   LineTo(_hDC, p.x+x, p.y+y);
  355. }
  356. void PCanvas::_DrawRect(PORDINATE x, PORDINATE y, PDIMENSION dx, PDIMENSION dy)
  357. {
  358.   if (penMode == fillMode) {
  359.     SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  360.     Rectangle(_hDC, x, y, x+dx, y+dy);
  361.   }
  362.   else {
  363.     HGDIOBJ oldBrush =
  364.            SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
  365.     Rectangle(_hDC, x, y, x+dx, y+dy);
  366.     HGDIOBJ oldPen =
  367.       SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
  368.     Rectangle(_hDC, x, y, x+dx, y+dy);
  369.     SelectObject(_hDC, oldPen);
  370.   }
  371. }
  372. void PCanvas::_FillRect(PORDINATE x, PORDINATE y, PDIMENSION dx, PDIMENSION dy)
  373. {
  374.   SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  375.   PRect r(x, y, dx, dy);
  376.   ::FillRect(GetHDC(), r, _hBrush);
  377. }
  378. void PCanvas::DrawRoundRect(const PRect & rect,
  379.                                PDIMENSION cornerWidth, PDIMENSION cornerHeight)
  380. {
  381.   if (penMode == fillMode) {
  382.     SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  383.     RoundRect(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  384.                                                     cornerWidth, cornerHeight);
  385.   }
  386.   else {
  387.     HGDIOBJ oldBrush =
  388.            SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
  389.     RoundRect(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  390.                                                     cornerWidth, cornerHeight);
  391.     HGDIOBJ oldPen =
  392.       SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
  393.     RoundRect(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  394.                                                     cornerWidth, cornerHeight);
  395.     SelectObject(_hDC, oldPen);
  396.   }
  397. }
  398. void PCanvas::DrawEllipse(const PRect & rect)
  399. {
  400.   if (penMode == fillMode) {
  401.     SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  402.     Ellipse(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
  403.   }
  404.   else {
  405.     HGDIOBJ oldBrush =
  406.            SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
  407.     Ellipse(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
  408.     HGDIOBJ oldPen =
  409.       SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
  410.     Ellipse(_hDC, rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
  411.     SelectObject(_hDC, oldPen);
  412.   }
  413. }
  414. void PCanvas::DrawArc(const PRect & rect,
  415.                                   const PPoint & startPt, const PPoint & endPt)
  416. {
  417.   SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  418.   Arc(GetHDC(), rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  419.                                startPt.X(), startPt.Y(), endPt.X(), endPt.Y());
  420. }
  421. static PPoint PointFromAngle(int angle)
  422. {
  423.   static int sine[] = {
  424.       0,  17,  35,  52,  70,  87, 105, 122, 139, 156, 174,  191,  208,
  425.     225, 242, 259, 276, 292, 309, 326, 342, 358, 375, 391,  407,  423,
  426.     438, 454, 469, 485, 500, 515, 530, 545, 559, 574, 588,  602,  616,
  427.     629, 643, 656, 669, 682, 695, 707, 719, 731, 743, 755,  766,  777,
  428.     788, 799, 809, 819, 829, 839, 848, 857, 866, 875, 883,  891,  899,
  429.     906, 914, 921, 927, 934, 940, 946, 951, 956, 961, 966,  970,  974,
  430.     978, 982, 985, 988, 990, 993, 995, 996, 998, 999, 999, 1000, 1000
  431.   };
  432.   while (angle < 0)
  433.     angle += 360;
  434.   angle %= 360;
  435.   switch (angle/45) {
  436.     default:
  437.     case 0 :
  438.       return PPoint(1000, sine[angle]);
  439.     case 1 :
  440.       return PPoint(sine[90-angle], 1000);
  441.     case 2 :
  442.       return PPoint(sine[angle], -1000);
  443.     case 3 :
  444.       return PPoint(1000, sine[angle]);
  445.     case 4 :
  446.       return PPoint(1000, sine[angle]);
  447.     case 5 :
  448.       return PPoint(sine[90-angle], 1000);
  449.     case 6 :
  450.       return PPoint(sine[90-angle], 1000);
  451.     case 7 :
  452.       return PPoint(1000, sine[angle]);
  453.   }
  454. }
  455. void PCanvas::DrawArc(const PRect & rect, int startAngle, int endAngle)
  456. {
  457.   DrawArc(rect, PointFromAngle(startAngle), PointFromAngle(endAngle));
  458. }
  459. void PCanvas::DrawPie(const PRect & rect,
  460.                                   const PPoint & startPt, const PPoint & endPt)
  461. {
  462.   if (penMode == fillMode) {
  463.     SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  464.     Pie(GetHDC(), rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  465.                                startPt.X(), startPt.Y(), endPt.X(), endPt.Y());
  466.   }
  467.   else {
  468.     HGDIOBJ oldBrush =
  469.            SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
  470.     Pie(GetHDC(), rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  471.                                startPt.X(), startPt.Y(), endPt.X(), endPt.Y());
  472.     HGDIOBJ oldPen =
  473.       SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
  474.     Pie(GetHDC(), rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  475.                                startPt.X(), startPt.Y(), endPt.X(), endPt.Y());
  476.     SelectObject(_hDC, oldPen);
  477.   }
  478. }
  479. void PCanvas::DrawPie(const PRect & rect, int startAngle, int endAngle)
  480. {
  481.   DrawPie(rect, PointFromAngle(startAngle), PointFromAngle(endAngle));
  482. }
  483. void PCanvas::DrawChord(const PRect & rect,
  484.                                   const PPoint & startPt, const PPoint & endPt)
  485. {
  486.   if (penMode == fillMode) {
  487.     SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  488.     Chord(GetHDC(), rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  489.                                startPt.X(), startPt.Y(), endPt.X(), endPt.Y());
  490.   }
  491.   else {
  492.     HGDIOBJ oldBrush =
  493.            SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
  494.     Chord(GetHDC(), rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  495.                                startPt.X(), startPt.Y(), endPt.X(), endPt.Y());
  496.     HGDIOBJ oldPen =
  497.       SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
  498.     Chord(GetHDC(), rect.Left(), rect.Top(), rect.Right(), rect.Bottom(),
  499.                                startPt.X(), startPt.Y(), endPt.X(), endPt.Y());
  500.     SelectObject(_hDC, oldPen);
  501.   }
  502. }
  503. void PCanvas::DrawChord(const PRect & rect, int startAngle, int endAngle)
  504. {
  505.   DrawChord(rect, PointFromAngle(startAngle), PointFromAngle(endAngle));
  506. }
  507. void PCanvas::DrawPolyLine(const PPointArray & ptArray)
  508. {
  509.   DrawPolyLine(MakePOINTArray(ptArray), ptArray.GetSize());
  510. }
  511. void PCanvas::DrawPolyLine(const PPoint * ptArray, PINDEX numPts)
  512. {
  513.   DrawPolyLine(MakePOINTArray(ptArray, numPts), numPts);
  514. }
  515. void PCanvas::DrawPolyLine(LPPOINT ptArray, PINDEX numPts)
  516. {
  517.   SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, -1);
  518.   Polyline(GetHDC(), ptArray, numPts);
  519.   delete [] ptArray;
  520. }
  521. void PCanvas::DrawPolygon(const PPointArray & ptArray)
  522. {
  523.   DrawPolygon(MakePOINTArray(ptArray), ptArray.GetSize());
  524. }
  525. void PCanvas::DrawPolygon(const PPoint * ptArray, PINDEX numPts)
  526. {
  527.   DrawPolygon(MakePOINTArray(ptArray, numPts), numPts);
  528. }
  529. void PCanvas::DrawPolygon(LPPOINT ptArray, PINDEX numPts)
  530. {
  531.   if (penMode == fillMode) {
  532.     SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  533.     Polygon(GetHDC(), ptArray, numPts);
  534.   }
  535.   else {
  536.     HGDIOBJ oldBrush =
  537.            SetUpDrawModes(penMode, penFgColour, penBkColour, NULL, NULL_BRUSH);
  538.     Polygon(GetHDC(), ptArray, numPts);
  539.     HGDIOBJ oldPen =
  540.       SetUpDrawModes(fillMode, fillFgColour, fillBkColour, oldBrush, NULL_PEN);
  541.     Polygon(GetHDC(), ptArray, numPts);
  542.     SelectObject(_hDC, oldPen);
  543.   }
  544.   delete [] ptArray;
  545. }
  546. LPPOINT PCanvas::MakePOINTArray(const PPointArray & ptArray)
  547. {
  548.   PINDEX size = ptArray.GetSize();
  549.   LPPOINT pa = new POINT[size];
  550.   for (PINDEX i = 0; i < size; i++)
  551.     pa[i] = *(LPPOINT)ptArray[i];
  552.   return pa;
  553. }
  554. LPPOINT PCanvas::MakePOINTArray(const PPoint * ptArray, PINDEX numPts)
  555. {
  556.   LPPOINT pa = new POINT[numPts];
  557.   for (PINDEX i = 0; i < numPts; i++)
  558.     pa[i] = *(const POINT *)ptArray[i];
  559.   return pa;
  560. }
  561. void PCanvas::DrawImgIcon(PORDINATE x, PORDINATE y, const PImgIcon & icn)
  562. {
  563.   SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  564.   SetMapMode(_hDC, MM_TEXT);
  565.   SetViewportOrgEx(_hDC, 0, 0, NULL);
  566.   SetWindowOrgEx(_hDC, 0, 0, NULL);
  567.   HDC hSrcDC = CreateCompatibleDC(_hDC);
  568.   HGDIOBJ oldBitmap = SelectObject(PAssertNULL(hSrcDC), icn.GetHBITMAP());
  569.   BITMAP bm;
  570.   GetObject(icn.GetHBITMAP(), sizeof(bm), (LPSTR)&bm);
  571.   PAssertOS(BitBlt(_hDC,
  572.                    ToPixelsX(x), ToPixelsY(y),
  573.                    (int)bm.bmWidth, (int)bm.bmHeight,
  574.                    hSrcDC, 0, 0, SRCCOPY));
  575.   SelectObject(hSrcDC, oldBitmap);
  576.   DeleteDC(hSrcDC);
  577.   SetMapMode(_hDC, MM_ANISOTROPIC);
  578.   SetTransform();
  579. }
  580. void PCanvas::DrawIcon(PORDINATE x, PORDINATE y, const PIcon & icn)
  581. {
  582.   ::DrawIcon(GetHDC(), x, y, icn.GetHICON());
  583. }
  584. void PCanvas::DrawPixels(PORDINATE x, PORDINATE y, const PPixelImage & pix)
  585. {
  586.   if (pix->GetPixelDataPtr() != NULL) {
  587.     SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  588.     RealizePalette(_hDC);
  589.     PPixelBase::DIBInfo dib(*pix, palette.GetHPALETTE());
  590.     SetDIBitsToDevice(_hDC,
  591.                       x, y, dib.Width(), dib.Height(),
  592.                       0, 0, 0, dib.Height(),
  593.                       pix->GetPixelDataPtr(), dib, dib.Usage());
  594.   }
  595. }
  596. void PCanvas::DrawPixels(const PRect & rect, const PPixelImage & pix)
  597. {
  598.   if (pix->GetPixelDataPtr() != NULL) {
  599.     SetUpDrawModes(fillMode, fillFgColour, fillBkColour, NULL, -1);
  600.     RealizePalette(_hDC);
  601.     PPixelBase::DIBInfo dib(*pix, palette.GetHPALETTE());
  602.     StretchDIBits(_hDC,
  603.                   rect.X(), rect.Y(), rect.Width(), rect.Height(),
  604.                   0, 0, dib.Width(), dib.Height(),
  605.                   pix->GetPixelDataPtr(), dib, dib.Usage(), SRCCOPY);
  606.   }
  607. }
  608. void PCanvas::DrawPict(PORDINATE x, PORDINATE y, const PPictImage & pic)
  609. {
  610.   POINT org;
  611.   SetWindowOrgEx(_hDC, x, y, &org);
  612. #if defined(_WIN32)
  613.   PlayEnhMetaFile(GetHDC(), pic->GetMETAFILE(), NULL);
  614. #else
  615.   PlayMetaFile(GetHDC(), pic->GetMETAFILE());
  616. #endif
  617.   SetWindowOrgEx(_hDC, (int)org.x, (int)org.y, NULL);
  618. }
  619. void PCanvas::DrawPict(const PRect & rect, const PPictImage & pic)
  620. {
  621. #if defined(_WIN32)
  622.   PlayEnhMetaFile(GetHDC(), pic->GetMETAFILE(), rect);
  623. #else
  624.   POINT org;
  625.   SIZE ext;
  626.   SetWindowOrgEx(_hDC, rect.X(), rect.Y(), &org);
  627.   SetWindowExtEx(_hDC, rect.Width(), rect.Height(), &ext);
  628.   PlayMetaFile(GetHDC(), pic->GetMETAFILE());
  629.   SetWindowOrgEx(_hDC, (int)org.x, (int)org.y, NULL);
  630.   SetWindowExtEx(_hDC, (int)ext.cx, (int)ext.cy, NULL);
  631. #endif
  632. }
  633. void PCanvas::DrawString(PORDINATE x, PORDINATE y,
  634.                                               const PString & str, int options)
  635. {
  636.   SetUpDrawModes(SrcCopy, textFgColour, textBkColour, NULL, -1);
  637.   PDim dim;
  638.   switch (options&VerticalAlignmentMask) {
  639.     case BottomAlign :
  640.       if (dim.Height() == 0)
  641.         dim = MeasureString(str);
  642.       y -= dim.Height();
  643.       break;
  644.     case CentreVertical :
  645.       if (dim.Height() == 0)
  646.         dim = MeasureString(str);
  647.       y -= dim.Height()/2;
  648.       break;
  649.     case BaseLine :
  650.       y -= FromPointsY(realFont.GetAscent());
  651.   }
  652.   switch (options&HorizontalAlignmentMask) {
  653.     case RightAlign :
  654.       if (dim.Width() == 0)
  655.         dim = MeasureString(str);
  656.       x -= dim.Width();
  657.       break;
  658.     case Centred :
  659.       if (dim.Width() == 0)
  660.         dim = MeasureString(str);
  661.       x -= dim.Width()/2;
  662.   }
  663.   if (str.FindOneOf("rn") == P_MAX_INDEX)
  664.     TabbedTextOut(GetHDC(), x, y, str, str.GetLength(), 0, NULL, 0);
  665.   else {
  666.     PRect r(x, y, 10000, 10000);
  667.     DrawText(GetHDC(), str, -1, r,
  668.                  DT_LEFT|DT_TOP|DT_NOPREFIX|DT_EXPANDTABS|DT_EXTERNALLEADING);
  669.   }
  670. }
  671. PDim PCanvas::MeasureString(const PString & str)
  672. {
  673.   PDim dim;
  674.   if (str.FindOneOf("rn") == P_MAX_INDEX)
  675.     dim = PDim::FromDWORD(GetTabbedTextExtent(GetHDC(),
  676.                                               str, str.GetLength(), 0, NULL));
  677.   else {
  678.     PStringArray lines = str.Lines();
  679.     for (PINDEX line = 0; line < lines.GetSize(); line++) {
  680.       DWORD lineDim = GetTabbedTextExtent(GetHDC(),
  681.                                     lines[line], lines[line].GetLength(), 0, NULL);
  682.       if (dim.Width() < (PDIMENSION)LOWORD(lineDim))
  683.         dim.SetWidth(LOWORD(lineDim));
  684.       dim.SetHeight(dim.Height() + HIWORD(lineDim));
  685.     }
  686.   }
  687.   return dim;
  688. }
  689. void PCanvas::DrawTextLine(PORDINATE x, PORDINATE y,
  690.                            const char * textChars,
  691.                            const PDIMENSION * charWidths,
  692.                            PINDEX len)
  693. {
  694.   SetUpDrawModes(SrcCopy, textFgColour, textBkColour, NULL, -1);
  695.   PRect rect(x, y, 1, 1);
  696.   ExtTextOut(_hDC, x, y, 0, rect, textChars, len, (LPINT)charWidths);
  697. }
  698. HGDIOBJ PCanvas::SetUpDrawModes(DrawingModes mode,
  699.                                 const PColour & fg, const PColour & bg,
  700.                                 HGDIOBJ restoreObj, int saveObj)
  701. {
  702.   if (restoreObj)
  703.     SelectObject(GetHDC(), restoreObj);
  704.   static int modeTable[] = {
  705.     R2_COPYPEN, R2_NOTCOPYPEN,
  706.     R2_MASKPEN, R2_MASKNOTPEN, R2_MASKPENNOT, R2_NOTMASKPEN,
  707.     R2_MERGEPEN, R2_MERGENOTPEN, R2_MERGEPENNOT, R2_NOTMERGEPEN,
  708.     R2_XORPEN, R2_NOTXORPEN,
  709.     R2_NOT, R2_NOP
  710.   };
  711.   PAssert(mode < PARRAYSIZE(modeTable), PInvalidParameter);
  712.   SetROP2(GetHDC(), modeTable[mode]);
  713.   SetTextColor(_hDC, fg.ToCOLORREF());
  714.   SetBkColor(_hDC, bg.ToCOLORREF());
  715.   SetBkMode(_hDC, bg.GetAlpha() == 0 ? TRANSPARENT : OPAQUE);
  716.   return saveObj < 0 ? NULL : SelectObject(_hDC, GetStockObject(saveObj));
  717. }
  718. void PCanvas::SetClipRect(const PRect & rect)
  719. {
  720.   PRegion rgn = ToPixels(rect);
  721.   SelectClipRgn(GetHDC(), rgn.GetHRGN());
  722. }
  723. PRect PCanvas::GetClipRect() const
  724. {
  725.   PRect r;
  726.   GetClipBox(GetHDC(), r);
  727.   return r;
  728. }
  729. void PCanvas::SetClipRegion(const PRegion & rgn)
  730. {
  731.   SelectClipRgn(GetHDC(), rgn.GetHRGN());
  732. }
  733. PRegion PCanvas::GetClipRegion() const
  734. {
  735. #if defined(_WIN32)
  736.   PRegion rgn;
  737.   GetClipRgn(GetHDC(), rgn.GetHRGN());
  738.   return rgn;
  739. #else
  740.   PRect r;
  741.   GetClipBox(GetHDC(), r);
  742.   return r;
  743. #endif
  744. }
  745. PRect PCanvas::GetDrawingBounds() const
  746. {
  747.   return FromPixels(PRect(0, 0, (PDIMENSION)GetDeviceCaps(_hDC,HORZRES),
  748.                                        (PDIMENSION)GetDeviceCaps(_hDC,VERTRES)));
  749. }
  750. PRect PCanvas::GetPhysicalBounds(BOOL inPixels) const
  751. {
  752.   if (inPixels)
  753.     return PRect(0, 0, (PDIMENSION)GetDeviceCaps(_hDC,HORZRES),
  754.                                         (PDIMENSION)GetDeviceCaps(_hDC,VERTRES));
  755.   else
  756.     return PRect(0, 0, (PDIMENSION)GetDeviceCaps(_hDC,HORZSIZE),
  757.                                         (PDIMENSION)GetDeviceCaps(_hDC,VERTSIZE));
  758. }
  759. //////////////////////////////////////////////////////////////////////////////
  760. PRect PInteractorCanvas::GetDrawingBounds() const
  761. {
  762.   return FromPixels(interactor->GetDrawingBounds(PInteractor::PixelCoords));
  763. }
  764. //////////////////////////////////////////////////////////////////////////////
  765. PDrawCanvas::PDrawCanvas(PInteractor * theInteractor,
  766.                                      BOOL inPixels, BOOL overDrawChildWindows)
  767.   : PInteractorCanvas(theInteractor, inPixels)
  768. {
  769.   if (overDrawChildWindows)
  770.     SetWindowLong(interactor->GetHWND(), GWL_STYLE,
  771.             GetWindowLong(interactor->GetHWND(), GWL_STYLE)&~WS_CLIPCHILDREN);
  772.   Construct(inPixels);
  773.   SetHDC(GetDC(interactor->GetHWND()));
  774.   deleteDC = TRUE;
  775. }
  776. PDrawCanvas::PDrawCanvas(PInteractor * theInteractor,
  777.                                      HDC newDC, BOOL autoDelete, BOOL inPixels)
  778.   : PInteractorCanvas(theInteractor, inPixels)
  779. {
  780.   Construct(inPixels);
  781.   preAllocatedDC = newDC;
  782.   deleteDC = autoDelete;
  783. }
  784. PDrawCanvas::~PDrawCanvas()
  785. {
  786.   if (_hDC == NULL)
  787.     return;
  788.   if (deleteDC) {
  789.     PAssertOS(ReleaseDC(interactor->GetHWND(), _hDC));
  790.     SetWindowLong(interactor->GetHWND(), GWL_STYLE,
  791.              GetWindowLong(interactor->GetHWND(), GWL_STYLE)|WS_CLIPCHILDREN);
  792.   }
  793.   else {
  794.     SelectObject(_hDC, GetStockObject(BLACK_PEN));
  795.     SelectObject(_hDC, GetStockObject(WHITE_BRUSH));
  796.     SelectObject(_hDC, GetStockObject(SYSTEM_FONT));
  797.     SelectPalette(_hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
  798.   }
  799.   _hDC = NULL;
  800. }
  801. HDC PDrawCanvas::GetHDC() const
  802. {
  803.   if (_hDC == NULL)
  804.     ((PDrawCanvas*)this)->SetHDC(preAllocatedDC);
  805.   return _hDC;
  806. }
  807. //////////////////////////////////////////////////////////////////////////////
  808. PRedrawCanvas::PRedrawCanvas(PInteractor * theInteractor, BOOL inPixels)
  809.   : PInteractorCanvas(theInteractor, inPixels)
  810. {
  811.   Construct(inPixels);
  812.   SetHDC(GetDC(interactor->GetHWND()));
  813.   PAssertOS(ReleaseDC(interactor->GetHWND(), _hDC));
  814.   paint.hdc = _hDC = NULL;
  815. }
  816. PRedrawCanvas::~PRedrawCanvas()
  817. {
  818.   if (paint.hdc != NULL)
  819.     EndPaint(interactor->GetHWND(), &paint);
  820.   else if (_hDC != NULL)
  821.     PAssertOS(ReleaseDC(interactor->GetHWND(), _hDC));
  822.   _hDC = NULL;
  823. }
  824. HDC PRedrawCanvas::GetHDC() const
  825. {
  826.   if (_hDC == NULL)
  827.     ((PRedrawCanvas*)this)->SetHDC(
  828.            BeginPaint(interactor->GetHWND(), &((PRedrawCanvas*)this)->paint));
  829.   return _hDC;
  830. }
  831. //////////////////////////////////////////////////////////////////////////////
  832. PPrintCanvas::~PPrintCanvas()
  833. {
  834.   if (_hDC != NULL) {
  835.     PAssertOS(EndPage(_hDC) > 0);
  836.     EndDoc(_hDC);
  837.   }
  838. }
  839. void PPrintCanvas::Construct()
  840. {
  841.   HDC newDC = CreateDC(printInfo.GetDriver(),
  842.                        printInfo.GetPrinter(),
  843.                        printInfo.GetDevice(),
  844.                        printInfo.GetDEVMODE());
  845.   DOCINFO docInfo;
  846.   memset(&docInfo, 0, sizeof(docInfo));
  847.   docInfo.cbSize = sizeof(docInfo);
  848.   docInfo.lpszDocName = jobName;
  849.   StartDoc(newDC, &docInfo);
  850.   if (StartPage(newDC) < 0)
  851.     DeleteDC(newDC);
  852.   else
  853.     SetHDC(newDC);
  854. }
  855. BOOL PPrintCanvas::NewPage()
  856. {
  857.   if (EndPage(GetHDC()) > 0) {
  858.     if (StartPage(_hDC) > 0) {
  859.       SetHDC(_hDC);
  860.       return TRUE;
  861.     }
  862.   }
  863.   return FALSE;
  864. }
  865. //////////////////////////////////////////////////////////////////////////////
  866. void PMemoryCanvas::Construct()
  867. {
  868.   SetHDC(image->CreateImageDC());
  869. }
  870. // End Of File ///////////////////////////////////////////////////////////////