4 * Canvas classes implementation
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
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/
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
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.50 2004/04/04 13:24:24 rjongbloed
31 * Changes to support native C++ Run Time Type Information
33 * Revision 1.49 1999/02/16 08:08:07 robertj
34 * MSVC 6.0 compatibility changes.
36 * Revision 1.48 1998/10/15 11:32:53 robertj
37 * New memory leak detection system.
39 * Revision 1.47 1998/09/24 03:42:31 robertj
40 * Added open software license.
42 * Revision 1.46 1998/09/22 15:09:58 robertj
43 * Added delayed HDC creation in PDrawCanvas.
45 * Revision 1.45 1998/09/18 13:59:31 robertj
46 * Fixed FillRect leaving small gaps in pattern filled rectangles next to each other.
48 * Revision 1.44 1998/09/07 14:03:41 robertj
49 * Fixed printing transforms being reset after each page.
51 * Revision 1.43 1998/09/04 07:00:10 robertj
52 * Fixed double print dialog.
53 * Can now print more than one page.
54 * Fixed uninitialised variable for win95 StartDoc()
56 * Revision 1.42 1998/03/20 03:13:25 robertj
57 * Added function to get physical bounds of canvas. Allows to scale drawing.
59 * Revision 1.41 1996/10/31 12:39:55 robertj
71 _hPen((HPEN
)GetStockObject(BLACK_PEN
)),
72 _hBrush((HBRUSH
)GetStockObject(HOLLOW_BRUSH
)),
75 deviceResX
= deviceResY
= 1;
83 PAssertOS(DeleteDC(_hDC
));
85 PAssertOS(DeleteObject(_hPen
));
87 PAssertOS(DeleteObject(_hBrush
));
89 PAssertOS(DeleteObject(_hFont
));
93 PCanvasState
& PCanvas::operator=(const PCanvasState
& state
)
95 PCanvasState::operator=(state
);
102 PObject::Comparison
PCanvas::Compare(const PObject
& obj
) const
104 PAssert(PIsDescendant(&obj
, PCanvas
), PInvalidCast
);
105 return _hDC
== ((const PCanvas
&)obj
)._hDC
? EqualTo
: GreaterThan
;
109 int PEXPORTED
PEnumFontFamilyProc(const ENUMLOGFONT FAR
* lpelf
,
110 const NEWTEXTMETRIC FAR
*,
114 PFontFamily
* family
= new PFontFamily(lpelf
->elfLogFont
.lfFaceName
);
115 family
->scalable
= (fontType
& RASTER_FONTTYPE
) == 0;
116 ((PFontFamilyList
*)lParam
)->Append(family
);
121 int PEXPORTED
PEnumFontFaceProc(const ENUMLOGFONT FAR
* lpelf
,
122 const NEWTEXTMETRIC FAR
* lpntm
,
126 PFontFamily
* family
= (PFontFamily
*)lParam
;
127 if ((fontType
& TRUETYPE_FONTTYPE
) != 0) {
128 if (family
->sizes
.GetSize() == 0) {
130 8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72
132 family
->sizes
= PWORDArray(sizes
, PARRAYSIZE(sizes
));
134 WORD style
= PFont::Regular
;
135 if ((lpntm
->ntmFlags
&0x20) != 0)
136 style
|= PFont::Bold
;
137 if ((lpntm
->ntmFlags
&1) != 0)
138 style
|= PFont::Italic
;
139 if ((lpntm
->ntmFlags
&2) != 0)
140 style
|= PFont::Underline
;
141 family
->styles
[family
->styles
.GetSize()] = style
;
142 family
->styleNames
[family
->styleNames
.GetSize()] =
143 PString((const char *)lpelf
->elfStyle
);
146 family
->sizes
[family
->sizes
.GetSize()] = (WORD
)lpelf
->elfLogFont
.lfHeight
;
147 if (family
->styles
.GetSize() == 0) {
148 family
->sizes
[0] = 0;
149 if (lpelf
->elfStyle
[0] != '\0')
150 family
->styleNames
[0] = PString((const char *)lpelf
->elfStyle
);
152 family
->styleNames
[0] = "Regular";
159 PFontFamilyList
PCanvas::GetAvailableFonts() const
161 PFontFamilyList list
;
162 EnumFontFamilies(GetHDC(),
163 NULL
, (FONTENUMPROC
)PEnumFontFamilyProc
, (LPARAM
)&list
);
164 for (PINDEX i
= 0; i
< list
.GetSize(); i
++)
165 EnumFontFamilies(GetHDC(), list
[i
].GetFacename(),
166 (FONTENUMPROC
)PEnumFontFaceProc
, (LPARAM
)&list
[i
]);
171 void PCanvas::SetHDC(HDC newDC
)
173 _hDC
= PAssertNULL(newDC
);
174 deviceResX
= GetDeviceCaps(_hDC
, LOGPIXELSX
);
175 deviceResY
= GetDeviceCaps(_hDC
, LOGPIXELSY
);
177 realFont
= PRealFont(*this, font
);
179 SetMapMode(_hDC
, MM_ANISOTROPIC
);
185 SetBrushOrgEx(GetHDC(), patternOrigin
.X(), patternOrigin
.Y(), NULL
);
187 SetBrushOrg(GetHDC(), patternOrigin
.X(), patternOrigin
.Y());
189 PAssertOS(SelectPalette(_hDC
, palette
.GetHPALETTE(), TRUE
) != NULL
);
190 ::SetPolyFillMode(_hDC
, polyFillMode
== Winding
? WINDING
: ALTERNATE
);
191 SetTextAlign(_hDC
, TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
195 BOOL
PCanvas::SetPenStyle(PenStyles style
)
197 if (PCanvasState::SetPenStyle(style
)) {
205 BOOL
PCanvas::SetPenWidth(int width
)
207 if (PCanvasState::SetPenWidth(width
)) {
215 BOOL
PCanvas::SetPenFgColour(const PColour
& colour
)
217 if (PCanvasState::SetPenFgColour(colour
)) {
225 void PCanvas::MakePen()
229 if (penFgColour
.GetAlpha() == 0)
230 _hPen
= (HPEN
)GetStockObject(NULL_PEN
);
232 static int msStyle
[] = { PS_SOLID
, PS_DOT
, PS_DASH
, PS_DASHDOT
};
233 PAssert(penStyle
< sizeof(msStyle
)/sizeof(msStyle
[0]), PInvalidParameter
);
234 _hPen
= CreatePen(msStyle
[penStyle
],
235 penWidth
, penFgColour
.ToCOLORREF());
240 PAssertOS(SelectObject(_hDC
, _hPen
) != NULL
);
243 PAssertOS(DeleteObject(oldPen
));
247 BOOL
PCanvas::SetFillPattern(const PPattern
& pattern
)
249 if (PCanvasState::SetFillPattern(pattern
)) {
257 BOOL
PCanvas::SetPatternOrigin(const PPoint
& pt
)
259 if (PCanvasState::SetPatternOrigin(pt
)) {
261 SetBrushOrgEx(GetHDC(), pt
.X(), pt
.Y(), NULL
);
263 SetBrushOrg(GetHDC(), pt
.X(), pt
.Y());
271 BOOL
PCanvas::SetFillFgColour(const PColour
& colour
)
273 if (PCanvasState::SetFillFgColour(colour
)) {
281 void PCanvas::MakeBrush()
283 HBRUSH oldBrush
= _hBrush
;
285 if (fillFgColour
.GetAlpha() == 0)
286 _hBrush
= (HBRUSH
)GetStockObject(HOLLOW_BRUSH
);
287 else if (fillPattern
.GetHBITMAP() == NULL
)
288 _hBrush
= CreateSolidBrush(fillFgColour
.ToCOLORREF());
290 _hBrush
= CreatePatternBrush(fillPattern
.GetHBITMAP());
291 PAssertNULL(_hBrush
);
294 PAssertOS(SelectObject(_hDC
, _hBrush
) != NULL
);
296 if (oldBrush
!= NULL
)
297 PAssertOS(DeleteObject(oldBrush
));
301 BOOL
PCanvas::SetFont(const PFont
& newFont
)
303 if (!PCanvasState::SetFont(newFont
))
307 realFont
= PRealFont(*this, newFont
);
313 void PCanvas::MakeFont()
315 HFONT oldFont
= _hFont
;
317 _hFont
= CreateFont(FromPointsY(realFont
.GetHeight()),
319 realFont
.IsBold() ? FW_BOLD
: FW_NORMAL
,
320 (BYTE
)realFont
.IsItalic(),
321 (BYTE
)realFont
.IsUnderlined(),
323 realFont
.GetFacename());
327 PAssertOS(SelectObject(_hDC
, _hFont
) != NULL
);
330 PAssertOS(DeleteObject(oldFont
));
334 BOOL
PCanvas::SetPalette(const PPalette
& newPal
)
336 if (PCanvasState::SetPalette(newPal
)) {
338 PAssertOS(SelectPalette(_hDC
, palette
.GetHPALETTE(), TRUE
) != NULL
);
345 BOOL
PCanvas::SetPolyFillMode(PolyFillMode newMode
)
347 if (PCanvasState::SetPolyFillMode(newMode
)) {
349 ::SetPolyFillMode(_hDC
, polyFillMode
== Winding
? WINDING
: ALTERNATE
);
356 BOOL
PCanvas::SetViewportRect(const PRect
& rect
)
358 if (PCanvasState::SetViewportRect(rect
)) {
366 BOOL
PCanvas::SetMappingRect(const PRect
& rect
)
368 if (PCanvasState::SetMappingRect(rect
)) {
376 void PCanvas::SetTransform()
381 SetViewportOrgEx(_hDC
, viewport
.Left(), viewport
.Top(), NULL
);
382 SetViewportExtEx(_hDC
, viewport
.Width(), viewport
.Height(), NULL
);
383 SetWindowOrgEx(_hDC
, map
.Left(), map
.Top(), NULL
);
384 SetWindowExtEx(_hDC
, map
.Width(), map
.Height(), NULL
);
385 if (GetPenWidth() != 0)
391 void PCanvas::MoveCurrentPosition(PORDINATE x
, PORDINATE y
)
394 PAssertOS(GetCurrentPositionEx(GetHDC(), &p
));
395 MoveToEx(_hDC
, p
.x
+x
, p
.y
+y
, NULL
);
399 PPoint
PCanvas::GetCurrentPosition() const
402 PAssertOS(::GetCurrentPositionEx(GetHDC(), p
));
407 void PCanvas::DrawLine(PORDINATE x
, PORDINATE y
)
409 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, -1);
410 LineTo(GetHDC(), x
, y
);
414 void PCanvas::DrawLine(PORDINATE x1
, PORDINATE y1
, PORDINATE x2
, PORDINATE y2
)
416 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, -1);
418 MoveToEx(GetHDC(), x1
, y1
, &p
);
419 LineTo(_hDC
, x2
, y2
);
420 MoveToEx(_hDC
, (int)p
.x
, (int)p
.y
, NULL
);
424 void PCanvas::DrawLineRelative(PORDINATE x
, PORDINATE y
)
426 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, -1);
428 PAssertOS(GetCurrentPositionEx(GetHDC(), &p
));
429 LineTo(_hDC
, p
.x
+x
, p
.y
+y
);
433 void PCanvas::_DrawRect(PORDINATE x
, PORDINATE y
, PDIMENSION dx
, PDIMENSION dy
)
435 if (penMode
== fillMode
) {
436 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
437 Rectangle(_hDC
, x
, y
, x
+dx
, y
+dy
);
441 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, NULL_BRUSH
);
442 Rectangle(_hDC
, x
, y
, x
+dx
, y
+dy
);
444 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, oldBrush
, NULL_PEN
);
445 Rectangle(_hDC
, x
, y
, x
+dx
, y
+dy
);
446 SelectObject(_hDC
, oldPen
);
451 void PCanvas::_FillRect(PORDINATE x
, PORDINATE y
, PDIMENSION dx
, PDIMENSION dy
)
453 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
454 PRect
r(x
, y
, dx
, dy
);
455 ::FillRect(GetHDC(), r
, _hBrush
);
459 void PCanvas::DrawRoundRect(const PRect
& rect
,
460 PDIMENSION cornerWidth
, PDIMENSION cornerHeight
)
462 if (penMode
== fillMode
) {
463 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
464 RoundRect(_hDC
, rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
465 cornerWidth
, cornerHeight
);
469 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, NULL_BRUSH
);
470 RoundRect(_hDC
, rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
471 cornerWidth
, cornerHeight
);
473 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, oldBrush
, NULL_PEN
);
474 RoundRect(_hDC
, rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
475 cornerWidth
, cornerHeight
);
476 SelectObject(_hDC
, oldPen
);
481 void PCanvas::DrawEllipse(const PRect
& rect
)
483 if (penMode
== fillMode
) {
484 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
485 Ellipse(_hDC
, rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom());
489 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, NULL_BRUSH
);
490 Ellipse(_hDC
, rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom());
492 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, oldBrush
, NULL_PEN
);
493 Ellipse(_hDC
, rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom());
494 SelectObject(_hDC
, oldPen
);
499 void PCanvas::DrawArc(const PRect
& rect
,
500 const PPoint
& startPt
, const PPoint
& endPt
)
502 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, -1);
503 Arc(GetHDC(), rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
504 startPt
.X(), startPt
.Y(), endPt
.X(), endPt
.Y());
508 static PPoint
PointFromAngle(int angle
)
510 static int sine
[] = {
511 0, 17, 35, 52, 70, 87, 105, 122, 139, 156, 174, 191, 208,
512 225, 242, 259, 276, 292, 309, 326, 342, 358, 375, 391, 407, 423,
513 438, 454, 469, 485, 500, 515, 530, 545, 559, 574, 588, 602, 616,
514 629, 643, 656, 669, 682, 695, 707, 719, 731, 743, 755, 766, 777,
515 788, 799, 809, 819, 829, 839, 848, 857, 866, 875, 883, 891, 899,
516 906, 914, 921, 927, 934, 940, 946, 951, 956, 961, 966, 970, 974,
517 978, 982, 985, 988, 990, 993, 995, 996, 998, 999, 999, 1000, 1000
527 return PPoint(1000, sine
[angle
]);
530 return PPoint(sine
[90-angle
], 1000);
533 return PPoint(sine
[angle
], -1000);
536 return PPoint(1000, sine
[angle
]);
539 return PPoint(1000, sine
[angle
]);
542 return PPoint(sine
[90-angle
], 1000);
545 return PPoint(sine
[90-angle
], 1000);
548 return PPoint(1000, sine
[angle
]);
553 void PCanvas::DrawArc(const PRect
& rect
, int startAngle
, int endAngle
)
555 DrawArc(rect
, PointFromAngle(startAngle
), PointFromAngle(endAngle
));
559 void PCanvas::DrawPie(const PRect
& rect
,
560 const PPoint
& startPt
, const PPoint
& endPt
)
562 if (penMode
== fillMode
) {
563 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
564 Pie(GetHDC(), rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
565 startPt
.X(), startPt
.Y(), endPt
.X(), endPt
.Y());
569 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, NULL_BRUSH
);
570 Pie(GetHDC(), rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
571 startPt
.X(), startPt
.Y(), endPt
.X(), endPt
.Y());
573 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, oldBrush
, NULL_PEN
);
574 Pie(GetHDC(), rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
575 startPt
.X(), startPt
.Y(), endPt
.X(), endPt
.Y());
576 SelectObject(_hDC
, oldPen
);
581 void PCanvas::DrawPie(const PRect
& rect
, int startAngle
, int endAngle
)
583 DrawPie(rect
, PointFromAngle(startAngle
), PointFromAngle(endAngle
));
587 void PCanvas::DrawChord(const PRect
& rect
,
588 const PPoint
& startPt
, const PPoint
& endPt
)
590 if (penMode
== fillMode
) {
591 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
592 Chord(GetHDC(), rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
593 startPt
.X(), startPt
.Y(), endPt
.X(), endPt
.Y());
597 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, NULL_BRUSH
);
598 Chord(GetHDC(), rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
599 startPt
.X(), startPt
.Y(), endPt
.X(), endPt
.Y());
601 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, oldBrush
, NULL_PEN
);
602 Chord(GetHDC(), rect
.Left(), rect
.Top(), rect
.Right(), rect
.Bottom(),
603 startPt
.X(), startPt
.Y(), endPt
.X(), endPt
.Y());
604 SelectObject(_hDC
, oldPen
);
609 void PCanvas::DrawChord(const PRect
& rect
, int startAngle
, int endAngle
)
611 DrawChord(rect
, PointFromAngle(startAngle
), PointFromAngle(endAngle
));
615 void PCanvas::DrawPolyLine(const PPointArray
& ptArray
)
617 DrawPolyLine(MakePOINTArray(ptArray
), ptArray
.GetSize());
621 void PCanvas::DrawPolyLine(const PPoint
* ptArray
, PINDEX numPts
)
623 DrawPolyLine(MakePOINTArray(ptArray
, numPts
), numPts
);
627 void PCanvas::DrawPolyLine(LPPOINT ptArray
, PINDEX numPts
)
629 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, -1);
630 Polyline(GetHDC(), ptArray
, numPts
);
635 void PCanvas::DrawPolygon(const PPointArray
& ptArray
)
637 DrawPolygon(MakePOINTArray(ptArray
), ptArray
.GetSize());
641 void PCanvas::DrawPolygon(const PPoint
* ptArray
, PINDEX numPts
)
643 DrawPolygon(MakePOINTArray(ptArray
, numPts
), numPts
);
647 void PCanvas::DrawPolygon(LPPOINT ptArray
, PINDEX numPts
)
649 if (penMode
== fillMode
) {
650 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
651 Polygon(GetHDC(), ptArray
, numPts
);
655 SetUpDrawModes(penMode
, penFgColour
, penBkColour
, NULL
, NULL_BRUSH
);
656 Polygon(GetHDC(), ptArray
, numPts
);
658 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, oldBrush
, NULL_PEN
);
659 Polygon(GetHDC(), ptArray
, numPts
);
660 SelectObject(_hDC
, oldPen
);
666 LPPOINT
PCanvas::MakePOINTArray(const PPointArray
& ptArray
)
668 PINDEX size
= ptArray
.GetSize();
669 LPPOINT pa
= new POINT
[size
];
670 for (PINDEX i
= 0; i
< size
; i
++)
671 pa
[i
] = *(LPPOINT
)ptArray
[i
];
676 LPPOINT
PCanvas::MakePOINTArray(const PPoint
* ptArray
, PINDEX numPts
)
678 LPPOINT pa
= new POINT
[numPts
];
679 for (PINDEX i
= 0; i
< numPts
; i
++)
680 pa
[i
] = *(const POINT
*)ptArray
[i
];
685 void PCanvas::DrawImgIcon(PORDINATE x
, PORDINATE y
, const PImgIcon
& icn
)
687 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
688 SetMapMode(_hDC
, MM_TEXT
);
689 SetViewportOrgEx(_hDC
, 0, 0, NULL
);
690 SetWindowOrgEx(_hDC
, 0, 0, NULL
);
691 HDC hSrcDC
= CreateCompatibleDC(_hDC
);
692 HGDIOBJ oldBitmap
= SelectObject(PAssertNULL(hSrcDC
), icn
.GetHBITMAP());
694 GetObject(icn
.GetHBITMAP(), sizeof(bm
), (LPSTR
)&bm
);
695 PAssertOS(BitBlt(_hDC
,
696 ToPixelsX(x
), ToPixelsY(y
),
697 (int)bm
.bmWidth
, (int)bm
.bmHeight
,
698 hSrcDC
, 0, 0, SRCCOPY
));
699 SelectObject(hSrcDC
, oldBitmap
);
701 SetMapMode(_hDC
, MM_ANISOTROPIC
);
706 void PCanvas::DrawIcon(PORDINATE x
, PORDINATE y
, const PIcon
& icn
)
708 ::DrawIcon(GetHDC(), x
, y
, icn
.GetHICON());
712 void PCanvas::DrawPixels(PORDINATE x
, PORDINATE y
, const PPixelImage
& pix
)
714 if (pix
->GetPixelDataPtr() != NULL
) {
715 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
716 RealizePalette(_hDC
);
717 PPixelBase::DIBInfo
dib(*pix
, palette
.GetHPALETTE());
718 SetDIBitsToDevice(_hDC
,
719 x
, y
, dib
.Width(), dib
.Height(),
720 0, 0, 0, dib
.Height(),
721 pix
->GetPixelDataPtr(), dib
, dib
.Usage());
726 void PCanvas::DrawPixels(const PRect
& rect
, const PPixelImage
& pix
)
728 if (pix
->GetPixelDataPtr() != NULL
) {
729 SetUpDrawModes(fillMode
, fillFgColour
, fillBkColour
, NULL
, -1);
730 RealizePalette(_hDC
);
731 PPixelBase::DIBInfo
dib(*pix
, palette
.GetHPALETTE());
733 rect
.X(), rect
.Y(), rect
.Width(), rect
.Height(),
734 0, 0, dib
.Width(), dib
.Height(),
735 pix
->GetPixelDataPtr(), dib
, dib
.Usage(), SRCCOPY
);
740 void PCanvas::DrawPict(PORDINATE x
, PORDINATE y
, const PPictImage
& pic
)
743 SetWindowOrgEx(_hDC
, x
, y
, &org
);
745 PlayEnhMetaFile(GetHDC(), pic
->GetMETAFILE(), NULL
);
747 PlayMetaFile(GetHDC(), pic
->GetMETAFILE());
749 SetWindowOrgEx(_hDC
, (int)org
.x
, (int)org
.y
, NULL
);
753 void PCanvas::DrawPict(const PRect
& rect
, const PPictImage
& pic
)
756 PlayEnhMetaFile(GetHDC(), pic
->GetMETAFILE(), rect
);
760 SetWindowOrgEx(_hDC
, rect
.X(), rect
.Y(), &org
);
761 SetWindowExtEx(_hDC
, rect
.Width(), rect
.Height(), &ext
);
762 PlayMetaFile(GetHDC(), pic
->GetMETAFILE());
763 SetWindowOrgEx(_hDC
, (int)org
.x
, (int)org
.y
, NULL
);
764 SetWindowExtEx(_hDC
, (int)ext
.cx
, (int)ext
.cy
, NULL
);
769 void PCanvas::DrawString(PORDINATE x
, PORDINATE y
,
770 const PString
& str
, int options
)
772 SetUpDrawModes(SrcCopy
, textFgColour
, textBkColour
, NULL
, -1);
775 switch (options
&VerticalAlignmentMask
) {
777 if (dim
.Height() == 0)
778 dim
= MeasureString(str
);
782 case CentreVertical
:
783 if (dim
.Height() == 0)
784 dim
= MeasureString(str
);
789 y
-= FromPointsY(realFont
.GetAscent());
792 switch (options
&HorizontalAlignmentMask
) {
794 if (dim
.Width() == 0)
795 dim
= MeasureString(str
);
800 if (dim
.Width() == 0)
801 dim
= MeasureString(str
);
805 if (str
.FindOneOf("\r\n") == P_MAX_INDEX
)
806 TabbedTextOut(GetHDC(), x
, y
, str
, str
.GetLength(), 0, NULL
, 0);
808 PRect
r(x
, y
, 10000, 10000);
809 DrawText(GetHDC(), str
, -1, r
,
810 DT_LEFT
|DT_TOP
|DT_NOPREFIX
|DT_EXPANDTABS
|DT_EXTERNALLEADING
);
815 PDim
PCanvas::MeasureString(const PString
& str
)
818 if (str
.FindOneOf("\r\n") == P_MAX_INDEX
)
819 dim
= PDim::FromDWORD(GetTabbedTextExtent(GetHDC(),
820 str
, str
.GetLength(), 0, NULL
));
822 PStringArray lines
= str
.Lines();
823 for (PINDEX line
= 0; line
< lines
.GetSize(); line
++) {
824 DWORD lineDim
= GetTabbedTextExtent(GetHDC(),
825 lines
[line
], lines
[line
].GetLength(), 0, NULL
);
826 if (dim
.Width() < (PDIMENSION
)LOWORD(lineDim
))
827 dim
.SetWidth(LOWORD(lineDim
));
828 dim
.SetHeight(dim
.Height() + HIWORD(lineDim
));
835 void PCanvas::DrawTextLine(PORDINATE x
, PORDINATE y
,
836 const char * textChars
,
837 const PDIMENSION
* charWidths
,
840 SetUpDrawModes(SrcCopy
, textFgColour
, textBkColour
, NULL
, -1);
841 PRect
rect(x
, y
, 1, 1);
842 ExtTextOut(_hDC
, x
, y
, 0, rect
, textChars
, len
, (LPINT
)charWidths
);
846 HGDIOBJ
PCanvas::SetUpDrawModes(DrawingModes mode
,
847 const PColour
& fg
, const PColour
& bg
,
848 HGDIOBJ restoreObj
, int saveObj
)
851 SelectObject(GetHDC(), restoreObj
);
853 static int modeTable
[] = {
854 R2_COPYPEN
, R2_NOTCOPYPEN
,
855 R2_MASKPEN
, R2_MASKNOTPEN
, R2_MASKPENNOT
, R2_NOTMASKPEN
,
856 R2_MERGEPEN
, R2_MERGENOTPEN
, R2_MERGEPENNOT
, R2_NOTMERGEPEN
,
857 R2_XORPEN
, R2_NOTXORPEN
,
860 PAssert(mode
< PARRAYSIZE(modeTable
), PInvalidParameter
);
861 SetROP2(GetHDC(), modeTable
[mode
]);
863 SetTextColor(_hDC
, fg
.ToCOLORREF());
864 SetBkColor(_hDC
, bg
.ToCOLORREF());
865 SetBkMode(_hDC
, bg
.GetAlpha() == 0 ? TRANSPARENT
: OPAQUE
);
867 return saveObj
< 0 ? NULL
: SelectObject(_hDC
, GetStockObject(saveObj
));
871 void PCanvas::SetClipRect(const PRect
& rect
)
873 PRegion rgn
= ToPixels(rect
);
874 SelectClipRgn(GetHDC(), rgn
.GetHRGN());
878 PRect
PCanvas::GetClipRect() const
881 GetClipBox(GetHDC(), r
);
886 void PCanvas::SetClipRegion(const PRegion
& rgn
)
888 SelectClipRgn(GetHDC(), rgn
.GetHRGN());
892 PRegion
PCanvas::GetClipRegion() const
896 GetClipRgn(GetHDC(), rgn
.GetHRGN());
900 GetClipBox(GetHDC(), r
);
906 PRect
PCanvas::GetDrawingBounds() const
908 return FromPixels(PRect(0, 0, (PDIMENSION
)GetDeviceCaps(_hDC
,HORZRES
),
909 (PDIMENSION
)GetDeviceCaps(_hDC
,VERTRES
)));
913 PRect
PCanvas::GetPhysicalBounds(BOOL inPixels
) const
916 return PRect(0, 0, (PDIMENSION
)GetDeviceCaps(_hDC
,HORZRES
),
917 (PDIMENSION
)GetDeviceCaps(_hDC
,VERTRES
));
919 return PRect(0, 0, (PDIMENSION
)GetDeviceCaps(_hDC
,HORZSIZE
),
920 (PDIMENSION
)GetDeviceCaps(_hDC
,VERTSIZE
));
924 //////////////////////////////////////////////////////////////////////////////
927 PRect
PInteractorCanvas::GetDrawingBounds() const
929 return FromPixels(interactor
->GetDrawingBounds(PInteractor::PixelCoords
));
933 //////////////////////////////////////////////////////////////////////////////
936 PDrawCanvas::PDrawCanvas(PInteractor
* theInteractor
,
937 BOOL inPixels
, BOOL overDrawChildWindows
)
938 : PInteractorCanvas(theInteractor
, inPixels
)
940 if (overDrawChildWindows
)
941 SetWindowLong(interactor
->GetHWND(), GWL_STYLE
,
942 GetWindowLong(interactor
->GetHWND(), GWL_STYLE
)&~WS_CLIPCHILDREN
);
945 SetHDC(GetDC(interactor
->GetHWND()));
950 PDrawCanvas::PDrawCanvas(PInteractor
* theInteractor
,
951 HDC newDC
, BOOL autoDelete
, BOOL inPixels
)
952 : PInteractorCanvas(theInteractor
, inPixels
)
955 preAllocatedDC
= newDC
;
956 deleteDC
= autoDelete
;
960 PDrawCanvas::~PDrawCanvas()
966 PAssertOS(ReleaseDC(interactor
->GetHWND(), _hDC
));
967 SetWindowLong(interactor
->GetHWND(), GWL_STYLE
,
968 GetWindowLong(interactor
->GetHWND(), GWL_STYLE
)|WS_CLIPCHILDREN
);
971 SelectObject(_hDC
, GetStockObject(BLACK_PEN
));
972 SelectObject(_hDC
, GetStockObject(WHITE_BRUSH
));
973 SelectObject(_hDC
, GetStockObject(SYSTEM_FONT
));
974 SelectPalette(_hDC
, (HPALETTE
)GetStockObject(DEFAULT_PALETTE
), FALSE
);
980 HDC
PDrawCanvas::GetHDC() const
983 ((PDrawCanvas
*)this)->SetHDC(preAllocatedDC
);
988 //////////////////////////////////////////////////////////////////////////////
991 PRedrawCanvas::PRedrawCanvas(PInteractor
* theInteractor
, BOOL inPixels
)
992 : PInteractorCanvas(theInteractor
, inPixels
)
995 SetHDC(GetDC(interactor
->GetHWND()));
996 PAssertOS(ReleaseDC(interactor
->GetHWND(), _hDC
));
997 paint
.hdc
= _hDC
= NULL
;
1001 PRedrawCanvas::~PRedrawCanvas()
1003 if (paint
.hdc
!= NULL
)
1004 EndPaint(interactor
->GetHWND(), &paint
);
1005 else if (_hDC
!= NULL
)
1006 PAssertOS(ReleaseDC(interactor
->GetHWND(), _hDC
));
1011 HDC
PRedrawCanvas::GetHDC() const
1014 ((PRedrawCanvas
*)this)->SetHDC(
1015 BeginPaint(interactor
->GetHWND(), &((PRedrawCanvas
*)this)->paint
));
1020 //////////////////////////////////////////////////////////////////////////////
1023 PPrintCanvas::~PPrintCanvas()
1026 PAssertOS(EndPage(_hDC
) > 0);
1032 void PPrintCanvas::Construct()
1034 HDC newDC
= CreateDC(printInfo
.GetDriver(),
1035 printInfo
.GetPrinter(),
1036 printInfo
.GetDevice(),
1037 printInfo
.GetDEVMODE());
1040 memset(&docInfo
, 0, sizeof(docInfo
));
1041 docInfo
.cbSize
= sizeof(docInfo
);
1042 docInfo
.lpszDocName
= jobName
;
1043 StartDoc(newDC
, &docInfo
);
1045 if (StartPage(newDC
) < 0)
1052 BOOL
PPrintCanvas::NewPage()
1054 if (EndPage(GetHDC()) > 0) {
1055 if (StartPage(_hDC
) > 0) {
1065 //////////////////////////////////////////////////////////////////////////////
1068 void PMemoryCanvas::Construct()
1070 SetHDC(image
->CreateImageDC());
1074 // End Of File ///////////////////////////////////////////////////////////////