1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxDrawnShape
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "drawn.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include <wx/wxprec.h>
28 #include <wx/wxexpr.h>
39 static void IntToHex(unsigned int dec
, char *buf
);
40 static unsigned long HexToInt(char *buf
);
41 extern char *GraphicsBuffer
;
44 #define gyTYPE_BRUSH 41
45 #define gyTYPE_FONT 42
52 IMPLEMENT_DYNAMIC_CLASS(wxDrawnShape
, wxRectangleShape
)
54 wxDrawnShape::wxDrawnShape():wxRectangleShape(100.0, 50.0)
59 wxDrawnShape::~wxDrawnShape()
63 void wxDrawnShape::OnDraw(wxDC
& dc
)
65 // Pass pen and brush in case we have force outline
67 if (m_shadowMode
!= SHADOW_NONE
)
70 m_metafile
.m_fillBrush
= m_shadowBrush
;
71 m_metafile
.m_outlinePen
= transparent_pen
;
72 m_metafile
.Draw(dc
, m_xpos
+ m_shadowOffsetX
, m_ypos
+ m_shadowOffsetY
);
75 m_metafile
.m_outlinePen
= m_pen
;
76 m_metafile
.m_fillBrush
= m_brush
;
77 m_metafile
.Draw(dc
, m_xpos
, m_ypos
);
80 void wxDrawnShape::SetSize(float w
, float h
, bool recursive
)
82 SetAttachmentSize(w
, h
);
86 if (GetWidth() == 0.0)
88 else scaleX
= w
/GetWidth();
89 if (GetHeight() == 0.0)
91 else scaleY
= h
/GetHeight();
93 m_metafile
.Scale(scaleX
, scaleY
);
96 SetDefaultRegionSize();
99 void wxDrawnShape::Scale(float sx
, float sy
)
101 m_metafile
.Scale(sx
, sy
);
102 m_metafile
.CalculateSize(this);
105 void wxDrawnShape::Translate(float x
, float y
)
107 m_metafile
.Translate(x
, y
);
108 m_metafile
.CalculateSize(this);
111 void wxDrawnShape::Rotate(float x
, float y
, float theta
)
113 if (!m_metafile
.GetRotateable())
116 float actualTheta
= theta
-m_metafile
.m_currentRotation
;
119 m_metafile
.Rotate(x
, y
, theta
);
121 // Rotate attachment points
122 float sinTheta
= (float)sin(actualTheta
);
123 float cosTheta
= (float)cos(actualTheta
);
124 wxNode
*node
= m_attachmentPoints
.First();
127 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
128 float x1
= point
->m_x
;
129 float y1
= point
->m_y
;
130 point
->m_x
= x1
*cosTheta
- y1
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
131 point
->m_y
= x1
*sinTheta
+ y1
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
136 m_metafile
.CalculateSize(this);
140 // Prolog database stuff
141 char *wxDrawnShape::GetFunctor()
146 void wxDrawnShape::WritePrologAttributes(wxExpr
*clause
)
148 wxRectangleShape::WritePrologAttributes(clause
);
150 clause
->AddAttributeValue("save_metafile", (long)m_saveToFile
);
152 m_metafile
.WritePrologAttributes(clause
);
155 void wxDrawnShape::ReadPrologAttributes(wxExpr
*clause
)
157 wxRectangleShape::ReadPrologAttributes(clause
);
159 int iVal
= (int) m_saveToFile
;
160 clause
->AssignAttributeValue("save_metafile", &iVal
);
161 m_saveToFile
= (iVal
!= 0);
164 m_metafile
.ReadPrologAttributes(clause
);
168 // Does the copying for this object
169 void wxDrawnShape::Copy(wxShape
& copy
)
171 wxRectangleShape::Copy(copy
);
173 wxASSERT( copy
.IsKindOf(CLASSINFO(wxDrawnShape
)) ) ;
175 wxDrawnShape
& drawnCopy
= (wxDrawnShape
&) copy
;
177 m_metafile
.Copy(drawnCopy
.m_metafile
);
178 drawnCopy
.m_saveToFile
= m_saveToFile
;
181 bool wxDrawnShape::LoadFromMetaFile(char *filename
)
183 return m_metafile
.LoadFromMetaFile(filename
, &m_width
, &m_height
);
186 // Set of functions for drawing into a pseudo metafile.
187 // They use integers, but doubles are used internally for accuracy
190 void wxDrawnShape::DrawLine(const wxPoint
& pt1
, const wxPoint
& pt2
)
192 m_metafile
.DrawLine(pt1
, pt2
);
195 void wxDrawnShape::DrawRectangle(const wxRect
& rect
)
197 m_metafile
.DrawRectangle(rect
);
200 void wxDrawnShape::DrawRoundedRectangle(const wxRect
& rect
, double radius
)
202 m_metafile
.DrawRoundedRectangle(rect
, radius
);
205 void wxDrawnShape::DrawEllipse(const wxRect
& rect
)
207 m_metafile
.DrawEllipse(rect
);
210 void wxDrawnShape::DrawPoint(const wxPoint
& pt
)
212 m_metafile
.DrawPoint(pt
);
215 void wxDrawnShape::DrawText(const wxString
& text
, const wxPoint
& pt
)
217 m_metafile
.DrawText(text
, pt
);
220 void wxDrawnShape::DrawLines(int n
, wxPoint pts
[])
222 m_metafile
.DrawLines(n
, pts
);
225 void wxDrawnShape::DrawPolygon(int n
, wxPoint pts
[])
227 m_metafile
.DrawPolygon(n
, pts
);
230 void wxDrawnShape::DrawSpline(int n
, wxPoint pts
[])
232 m_metafile
.DrawSpline(n
, pts
);
235 void wxDrawnShape::SetClippingRect(const wxRect
& rect
)
237 m_metafile
.SetClippingRect(rect
);
240 void wxDrawnShape::DestroyClippingRect()
242 m_metafile
.DestroyClippingRect();
245 void wxDrawnShape::SetPen(wxPen
* pen
, bool isOutline
)
247 m_metafile
.SetPen(pen
, isOutline
);
250 void wxDrawnShape::SetBrush(wxBrush
* brush
, bool isFill
)
252 m_metafile
.SetBrush(brush
, isFill
);
255 void wxDrawnShape::SetFont(wxFont
* font
)
257 m_metafile
.SetFont(font
);
260 void wxDrawnShape::SetTextColour(const wxColour
& colour
)
262 m_metafile
.SetTextColour(colour
);
265 void wxDrawnShape::SetBackgroundColour(const wxColour
& colour
)
267 m_metafile
.SetBackgroundColour(colour
);
270 void wxDrawnShape::SetBackgroundMode(int mode
)
272 m_metafile
.SetBackgroundMode(mode
);
277 * Individual operations
282 * Set font, brush, text colour
286 wxOpSetGDI::wxOpSetGDI(int theOp
, wxPseudoMetaFile
*theImage
, int theGdiIndex
, int theMode
):
289 m_gdiIndex
= theGdiIndex
;
294 void wxOpSetGDI::Do(wxDC
& dc
, float xoffset
, float yoffset
)
300 // Check for overriding this operation for outline
302 if (m_image
->m_outlineColours
.Member((wxObject
*)m_gdiIndex
))
304 if (m_image
->m_outlinePen
)
305 dc
.SetPen(m_image
->m_outlinePen
);
309 wxNode
*node
= m_image
->m_gdiObjects
.Nth(m_gdiIndex
);
312 wxPen
*pen
= (wxPen
*)node
->Data();
319 case DRAWOP_SET_BRUSH
:
321 // Check for overriding this operation for outline or fill
323 if (m_image
->m_outlineColours
.Member((wxObject
*)m_gdiIndex
))
325 // Need to construct a brush to match the outline pen's colour
326 if (m_image
->m_outlinePen
)
328 wxBrush
*br
= wxTheBrushList
->FindOrCreateBrush(m_image
->m_outlinePen
->GetColour(), wxSOLID
);
333 else if (m_image
->m_fillColours
.Member((wxObject
*)m_gdiIndex
))
335 if (m_image
->m_fillBrush
)
337 dc
.SetBrush(m_image
->m_fillBrush
);
342 wxNode
*node
= m_image
->m_gdiObjects
.Nth(m_gdiIndex
);
345 wxBrush
*brush
= (wxBrush
*)node
->Data();
352 case DRAWOP_SET_FONT
:
354 wxNode
*node
= m_image
->m_gdiObjects
.Nth(m_gdiIndex
);
357 wxFont
*font
= (wxFont
*)node
->Data();
363 case DRAWOP_SET_TEXT_COLOUR
:
365 wxColour
col(m_r
,m_g
,m_b
);
366 dc
.SetTextForeground(col
);
369 case DRAWOP_SET_BK_COLOUR
:
371 wxColour
col(m_r
,m_g
,m_b
);
372 dc
.SetTextBackground(col
);
375 case DRAWOP_SET_BK_MODE
:
377 dc
.SetBackgroundMode(m_mode
);
385 wxDrawOp
*wxOpSetGDI::Copy(wxPseudoMetaFile
*newImage
)
387 wxOpSetGDI
*newOp
= new wxOpSetGDI(m_op
, newImage
, m_gdiIndex
, m_mode
);
394 wxExpr
*wxOpSetGDI::WriteExpr(wxPseudoMetaFile
*image
)
396 wxExpr
*expr
= new wxExpr(PrologList
);
397 expr
->Append(new wxExpr((long)m_op
));
401 case DRAWOP_SET_BRUSH
:
402 case DRAWOP_SET_FONT
:
404 expr
->Append(new wxExpr((long)m_gdiIndex
));
407 case DRAWOP_SET_TEXT_COLOUR
:
408 case DRAWOP_SET_BK_COLOUR
:
410 expr
->Append(new wxExpr((long)m_r
));
411 expr
->Append(new wxExpr((long)m_g
));
412 expr
->Append(new wxExpr((long)m_b
));
415 case DRAWOP_SET_BK_MODE
:
417 expr
->Append(new wxExpr((long)m_mode
));
426 void wxOpSetGDI::ReadExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
431 case DRAWOP_SET_BRUSH
:
432 case DRAWOP_SET_FONT
:
434 m_gdiIndex
= (int)expr
->Nth(1)->IntegerValue();
437 case DRAWOP_SET_TEXT_COLOUR
:
438 case DRAWOP_SET_BK_COLOUR
:
440 m_r
= (unsigned char)expr
->Nth(1)->IntegerValue();
441 m_g
= (unsigned char)expr
->Nth(2)->IntegerValue();
442 m_b
= (unsigned char)expr
->Nth(3)->IntegerValue();
445 case DRAWOP_SET_BK_MODE
:
447 m_mode
= (int)expr
->Nth(1)->IntegerValue();
456 * Set/destroy clipping
460 wxOpSetClipping::wxOpSetClipping(int theOp
, float theX1
, float theY1
,
461 float theX2
, float theY2
):wxDrawOp(theOp
)
469 wxDrawOp
*wxOpSetClipping::Copy(wxPseudoMetaFile
*newImage
)
471 wxOpSetClipping
*newOp
= new wxOpSetClipping(m_op
, m_x1
, m_y1
, m_x2
, m_y2
);
475 void wxOpSetClipping::Do(wxDC
& dc
, float xoffset
, float yoffset
)
479 case DRAWOP_SET_CLIPPING_RECT
:
481 dc
.SetClippingRegion(m_x1
+ xoffset
, m_y1
+ yoffset
, m_x2
+ xoffset
, m_y2
+ yoffset
);
484 case DRAWOP_DESTROY_CLIPPING_RECT
:
486 dc
.DestroyClippingRegion();
494 void wxOpSetClipping::Scale(float xScale
, float yScale
)
502 void wxOpSetClipping::Translate(float x
, float y
)
508 wxExpr
*wxOpSetClipping::WriteExpr(wxPseudoMetaFile
*image
)
510 wxExpr
*expr
= new wxExpr(PrologList
);
511 expr
->Append(new wxExpr((long)m_op
));
514 case DRAWOP_SET_CLIPPING_RECT
:
516 expr
->Append(new wxExpr(m_x1
));
517 expr
->Append(new wxExpr(m_y1
));
518 expr
->Append(new wxExpr(m_x2
));
519 expr
->Append(new wxExpr(m_y2
));
528 void wxOpSetClipping::ReadExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
532 case DRAWOP_SET_CLIPPING_RECT
:
534 m_x1
= expr
->Nth(1)->RealValue();
535 m_y1
= expr
->Nth(2)->RealValue();
536 m_x2
= expr
->Nth(3)->RealValue();
537 m_y2
= expr
->Nth(4)->RealValue();
546 * Draw line, rectangle, rounded rectangle, ellipse, point, arc, text
550 wxOpDraw::wxOpDraw(int theOp
, float theX1
, float theY1
, float theX2
, float theY2
,
551 float theRadius
, char *s
):wxDrawOp(theOp
)
557 m_radius
= theRadius
;
558 if (s
) m_textString
= copystring(s
);
559 else m_textString
= NULL
;
562 wxOpDraw::~wxOpDraw()
564 if (m_textString
) delete[] m_textString
;
567 wxDrawOp
*wxOpDraw::Copy(wxPseudoMetaFile
*newImage
)
569 wxOpDraw
*newOp
= new wxOpDraw(m_op
, m_x1
, m_y1
, m_x2
, m_y2
, m_radius
, m_textString
);
573 void wxOpDraw::Do(wxDC
& dc
, float xoffset
, float yoffset
)
577 case DRAWOP_DRAW_LINE
:
579 dc
.DrawLine(m_x1
+xoffset
, m_y1
+yoffset
, m_x2
+xoffset
, m_y2
+yoffset
);
582 case DRAWOP_DRAW_RECT
:
584 dc
.DrawRectangle(m_x1
+xoffset
, m_y1
+yoffset
, m_x2
, m_y2
);
587 case DRAWOP_DRAW_ROUNDED_RECT
:
589 dc
.DrawRoundedRectangle(m_x1
+xoffset
, m_y1
+yoffset
, m_x2
, m_y2
, m_radius
);
592 case DRAWOP_DRAW_ELLIPSE
:
594 dc
.DrawEllipse(m_x1
+xoffset
, m_y1
+yoffset
, m_x2
, m_y2
);
597 case DRAWOP_DRAW_POINT
:
599 dc
.DrawPoint(m_x1
+xoffset
, m_y1
+yoffset
);
602 case DRAWOP_DRAW_TEXT
:
604 dc
.DrawText(m_textString
, m_x1
+xoffset
, m_y1
+yoffset
);
612 void wxOpDraw::Scale(float scaleX
, float scaleY
)
621 void wxOpDraw::Translate(float x
, float y
)
627 void wxOpDraw::Rotate(float x
, float y
, float sinTheta
, float cosTheta
)
629 m_x1
= m_x1
*cosTheta
- m_y1
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
630 m_y1
= m_x1
*sinTheta
+ m_y1
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
634 case DRAWOP_DRAW_LINE
:
636 m_x2
= m_x2
*cosTheta
- m_y2
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
637 m_y2
= m_x2
*sinTheta
+ m_y2
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
645 wxExpr
*wxOpDraw::WriteExpr(wxPseudoMetaFile
*image
)
647 wxExpr
*expr
= new wxExpr(PrologList
);
648 expr
->Append(new wxExpr((long)m_op
));
651 case DRAWOP_DRAW_LINE
:
652 case DRAWOP_DRAW_RECT
:
653 case DRAWOP_DRAW_ELLIPSE
:
655 expr
->Append(new wxExpr(m_x1
));
656 expr
->Append(new wxExpr(m_y1
));
657 expr
->Append(new wxExpr(m_x2
));
658 expr
->Append(new wxExpr(m_y2
));
661 case DRAWOP_DRAW_ROUNDED_RECT
:
663 expr
->Append(new wxExpr(m_x1
));
664 expr
->Append(new wxExpr(m_y1
));
665 expr
->Append(new wxExpr(m_x2
));
666 expr
->Append(new wxExpr(m_y2
));
667 expr
->Append(new wxExpr(m_radius
));
670 case DRAWOP_DRAW_POINT
:
672 expr
->Append(new wxExpr(m_x1
));
673 expr
->Append(new wxExpr(m_y1
));
676 case DRAWOP_DRAW_TEXT
:
678 expr
->Append(new wxExpr(m_x1
));
679 expr
->Append(new wxExpr(m_y1
));
680 expr
->Append(new wxExpr(PrologString
, m_textString
));
683 case DRAWOP_DRAW_ARC
:
692 void wxOpDraw::ReadExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
696 case DRAWOP_DRAW_LINE
:
697 case DRAWOP_DRAW_RECT
:
698 case DRAWOP_DRAW_ELLIPSE
:
700 m_x1
= expr
->Nth(1)->RealValue();
701 m_y1
= expr
->Nth(2)->RealValue();
702 m_x2
= expr
->Nth(3)->RealValue();
703 m_y2
= expr
->Nth(4)->RealValue();
706 case DRAWOP_DRAW_ROUNDED_RECT
:
708 m_x1
= expr
->Nth(1)->RealValue();
709 m_y1
= expr
->Nth(2)->RealValue();
710 m_x2
= expr
->Nth(3)->RealValue();
711 m_y2
= expr
->Nth(4)->RealValue();
712 m_radius
= expr
->Nth(5)->RealValue();
715 case DRAWOP_DRAW_POINT
:
717 m_x1
= expr
->Nth(1)->RealValue();
718 m_y1
= expr
->Nth(2)->RealValue();
721 case DRAWOP_DRAW_TEXT
:
723 m_x1
= expr
->Nth(1)->RealValue();
724 m_y1
= expr
->Nth(2)->RealValue();
725 m_textString
= copystring(expr
->Nth(3)->StringValue());
728 case DRAWOP_DRAW_ARC
:
737 * Draw polygon, polyline, spline
741 wxOpPolyDraw::wxOpPolyDraw(int theOp
, int n
, wxRealPoint
*thePoints
):wxDrawOp(theOp
)
744 m_points
= thePoints
;
747 wxOpPolyDraw::~wxOpPolyDraw()
752 wxDrawOp
*wxOpPolyDraw::Copy(wxPseudoMetaFile
*newImage
)
754 wxRealPoint
*newPoints
= new wxRealPoint
[m_noPoints
];
755 for (int i
= 0; i
< m_noPoints
; i
++)
757 newPoints
[i
].x
= m_points
[i
].x
;
758 newPoints
[i
].y
= m_points
[i
].y
;
760 wxOpPolyDraw
*newOp
= new wxOpPolyDraw(m_op
, m_noPoints
, newPoints
);
764 void wxOpPolyDraw::Do(wxDC
& dc
, float xoffset
, float yoffset
)
768 case DRAWOP_DRAW_POLYLINE
:
770 wxPoint
*actualPoints
= new wxPoint
[m_noPoints
];
772 for (i
= 0; i
< m_noPoints
; i
++)
774 actualPoints
[i
].x
= (long) m_points
[i
].x
;
775 actualPoints
[i
].y
= (long) m_points
[i
].y
;
778 dc
.DrawLines(m_noPoints
, actualPoints
, xoffset
, yoffset
);
780 delete[] actualPoints
;
783 case DRAWOP_DRAW_POLYGON
:
785 wxPoint
*actualPoints
= new wxPoint
[m_noPoints
];
787 for (i
= 0; i
< m_noPoints
; i
++)
789 actualPoints
[i
].x
= (long) m_points
[i
].x
;
790 actualPoints
[i
].y
= (long) m_points
[i
].y
;
793 dc
.DrawPolygon(m_noPoints
, actualPoints
, xoffset
, yoffset
);
795 delete[] actualPoints
;
798 case DRAWOP_DRAW_SPLINE
:
800 wxPoint
*actualPoints
= new wxPoint
[m_noPoints
];
802 for (i
= 0; i
< m_noPoints
; i
++)
804 actualPoints
[i
].x
= (long) m_points
[i
].x
;
805 actualPoints
[i
].y
= (long) m_points
[i
].y
;
808 dc
.DrawSpline(m_noPoints
, actualPoints
); // no offsets in DrawSpline // , xoffset, yoffset);
810 delete[] actualPoints
;
819 void wxOpPolyDraw::Scale(float scaleX
, float scaleY
)
821 for (int i
= 0; i
< m_noPoints
; i
++)
823 m_points
[i
].x
*= scaleX
;
824 m_points
[i
].y
*= scaleY
;
828 void wxOpPolyDraw::Translate(float x
, float y
)
830 for (int i
= 0; i
< m_noPoints
; i
++)
837 void wxOpPolyDraw::Rotate(float x
, float y
, float sinTheta
, float cosTheta
)
839 for (int i
= 0; i
< m_noPoints
; i
++)
841 float x1
= m_points
[i
].x
;
842 float y1
= m_points
[i
].y
;
843 m_points
[i
].x
= x1
*cosTheta
- y1
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
844 m_points
[i
].y
= x1
*sinTheta
+ y1
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
848 wxExpr
*wxOpPolyDraw::WriteExpr(wxPseudoMetaFile
*image
)
850 wxExpr
*expr
= new wxExpr(PrologList
);
851 expr
->Append(new wxExpr((long)m_op
));
852 expr
->Append(new wxExpr((long)m_noPoints
));
858 GraphicsBuffer
[0] = 0;
861 * Store each coordinate pair in a hex string to save space.
862 * E.g. "1B9080CD". 4 hex digits per coordinate pair.
866 for (int i
= 0; i
< m_noPoints
; i
++)
868 long signedX
= (long)(m_points
[i
].x
*100.0);
869 long signedY
= (long)(m_points
[i
].y
*100.0);
872 long unSignedX
= (long)(signedX
+ 32767.0);
873 long unSignedY
= (long)(signedY
+ 32767.0);
875 // IntToHex((unsigned int)signedX, buf2);
876 // IntToHex((unsigned int)signedY, buf3);
877 IntToHex((int)unSignedX
, buf2
);
878 IntToHex((int)unSignedY
, buf3
);
880 // Don't overrun the buffer
883 strcat(GraphicsBuffer
, buf2
);
884 strcat(GraphicsBuffer
, buf3
);
887 expr
->Append(new wxExpr(PrologString
, GraphicsBuffer
));
891 void wxOpPolyDraw::ReadExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
893 m_noPoints
= (int)expr
->Nth(1)->IntegerValue();
898 m_points
= new wxRealPoint
[m_noPoints
];
901 wxString hexString
= expr
->Nth(2)->StringValue();
902 while (i
< m_noPoints
)
904 buf1
[0] = hexString
[bufPtr
];
905 buf1
[1] = hexString
[bufPtr
+ 1];
906 buf1
[2] = hexString
[bufPtr
+ 2];
907 buf1
[3] = hexString
[bufPtr
+ 3];
910 buf2
[0] = hexString
[bufPtr
+ 4];
911 buf2
[1] = hexString
[bufPtr
+ 5];
912 buf2
[2] = hexString
[bufPtr
+ 6];
913 buf2
[3] = hexString
[bufPtr
+ 7];
918 // int signedX = (signed int)HexToInt(buf1);
919 // int signedY = (signed int)HexToInt(buf2);
920 long unSignedX
= HexToInt(buf1
);
921 long unSignedY
= HexToInt(buf2
);
922 // Scale -32K -> +32K
923 long signedX
= unSignedX
- 32767;
924 long signedY
= unSignedY
- 32767;
926 int testX
= (signed int)unSignedX
;
927 int testY
= (signed int)unSignedY
;
930 m_points
[i
].x
= (float)(signedX
/ 100.0);
931 m_points
[i
].y
= (float)(signedY
/ 100.0);
943 static char hexArray
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
944 'C', 'D', 'E', 'F' };
946 // Convert unsigned 16-bit integer to 4-character hex string
947 static void IntToHex(unsigned int dec
, char *buf
)
949 int digit1
= (int)(dec
/4096);
950 int digit2
= (int)((dec
- (digit1
*4096))/256);
951 int digit3
= (int)((dec
- (digit1
*4096) - (digit2
*256))/16);
952 int digit4
= dec
- (digit1
*4096 + digit2
*256 + digit3
*16);
954 buf
[0] = hexArray
[digit1
];
955 buf
[1] = hexArray
[digit2
];
956 buf
[2] = hexArray
[digit3
];
957 buf
[3] = hexArray
[digit4
];
961 // One hex digit to decimal number
962 static int HexToInt1(char hex
)
1004 // 4-digit hex string to unsigned integer
1005 static unsigned long HexToInt(char *buf
)
1007 long d1
= (long)(HexToInt1(buf
[0])*4096.0) ;
1008 long d2
= (long)(HexToInt1(buf
[1])*256.0) ;
1009 long d3
= (long)(HexToInt1(buf
[2])*16.0) ;
1010 long d4
= (long)(HexToInt1(buf
[3])) ;
1011 unsigned long n
= (long)(d1
+ d2
+ d3
+ d4
) ;
1016 * wxPseudo meta-file
1020 IMPLEMENT_DYNAMIC_CLASS(wxPseudoMetaFile
, wxObject
)
1022 wxPseudoMetaFile::wxPseudoMetaFile()
1024 m_currentRotation
= 0;
1025 m_rotateable
= TRUE
;
1028 m_outlinePen
= NULL
;
1032 wxPseudoMetaFile::wxPseudoMetaFile(wxPseudoMetaFile
& mf
)
1037 wxPseudoMetaFile::~wxPseudoMetaFile()
1042 void wxPseudoMetaFile::Clear()
1044 wxNode
*node
= m_ops
.First();
1047 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1049 node
= node
->Next();
1052 m_gdiObjects
.Clear();
1053 m_outlineColours
.Clear();
1054 m_fillColours
.Clear();
1057 void wxPseudoMetaFile::Draw(wxDC
& dc
, float xoffset
, float yoffset
)
1059 wxNode
*node
= m_ops
.First();
1062 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1063 op
->Do(dc
, xoffset
, yoffset
);
1064 node
= node
->Next();
1068 void wxPseudoMetaFile::Scale(float sx
, float sy
)
1070 wxNode
*node
= m_ops
.First();
1073 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1075 node
= node
->Next();
1081 void wxPseudoMetaFile::Translate(float x
, float y
)
1083 wxNode
*node
= m_ops
.First();
1086 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1087 op
->Translate(x
, y
);
1088 node
= node
->Next();
1092 void wxPseudoMetaFile::Rotate(float x
, float y
, float theta
)
1094 float theta1
= theta
-m_currentRotation
;
1095 if (theta1
== 0.0) return;
1096 float cosTheta
= (float)cos(theta1
);
1097 float sinTheta
= (float)sin(theta1
);
1099 wxNode
*node
= m_ops
.First();
1102 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1103 op
->Rotate(x
, y
, sinTheta
, cosTheta
);
1104 node
= node
->Next();
1106 m_currentRotation
= theta
;
1110 void wxPseudoMetaFile::WritePrologAttributes(wxExpr
*clause
)
1112 // Write width and height
1113 clause
->AddAttributeValue("meta_width", m_width
);
1114 clause
->AddAttributeValue("meta_height", m_height
);
1115 clause
->AddAttributeValue("meta_rotateable", (long)m_rotateable
);
1117 // Write GDI objects
1120 wxNode
*node
= m_gdiObjects
.First();
1123 sprintf(buf
, "gdi%d", i
);
1124 wxObject
*obj
= (wxObject
*)node
->Data();
1125 wxExpr
*expr
= NULL
;
1128 if (obj
->IsKindOf(CLASSINFO(wxPen
)))
1130 wxPen
*thePen
= (wxPen
*)obj
;
1131 expr
= new wxExpr(PrologList
);
1132 expr
->Append(new wxExpr((long)gyTYPE_PEN
));
1133 expr
->Append(new wxExpr((long)thePen
->GetWidth()));
1134 expr
->Append(new wxExpr((long)thePen
->GetStyle()));
1135 expr
->Append(new wxExpr((long)thePen
->GetColour().Red()));
1136 expr
->Append(new wxExpr((long)thePen
->GetColour().Green()));
1137 expr
->Append(new wxExpr((long)thePen
->GetColour().Blue()));
1139 else if (obj
->IsKindOf(CLASSINFO(wxBrush
)))
1141 wxBrush
*theBrush
= (wxBrush
*)obj
;
1142 expr
= new wxExpr(PrologList
);
1143 expr
->Append(new wxExpr((long)gyTYPE_BRUSH
));
1144 expr
->Append(new wxExpr((long)theBrush
->GetStyle()));
1145 expr
->Append(new wxExpr((long)theBrush
->GetColour().Red()));
1146 expr
->Append(new wxExpr((long)theBrush
->GetColour().Green()));
1147 expr
->Append(new wxExpr((long)theBrush
->GetColour().Blue()));
1149 else if (obj
->IsKindOf(CLASSINFO(wxFont
)))
1151 wxFont
*theFont
= (wxFont
*)obj
;
1152 expr
= new wxExpr(PrologList
);
1153 expr
->Append(new wxExpr((long)gyTYPE_FONT
));
1154 expr
->Append(new wxExpr((long)theFont
->GetPointSize()));
1155 expr
->Append(new wxExpr((long)theFont
->GetFamily()));
1156 expr
->Append(new wxExpr((long)theFont
->GetStyle()));
1157 expr
->Append(new wxExpr((long)theFont
->GetWeight()));
1158 expr
->Append(new wxExpr((long)theFont
->GetUnderlined()));
1163 // If no recognised GDI object, append a place holder anyway.
1164 expr
= new wxExpr(PrologList
);
1165 expr
->Append(new wxExpr((long)0));
1170 clause
->AddAttributeValue(buf
, expr
);
1173 node
= node
->Next();
1176 // Write drawing operations
1178 node
= m_ops
.First();
1181 sprintf(buf
, "op%d", i
);
1182 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1183 wxExpr
*expr
= op
->WriteExpr(this);
1186 clause
->AddAttributeValue(buf
, expr
);
1189 node
= node
->Next();
1192 // Write outline and fill GDI op lists (if any)
1193 if (m_outlineColours
.Number() > 0)
1195 wxExpr
*outlineExpr
= new wxExpr(PrologList
);
1196 node
= m_outlineColours
.First();
1199 outlineExpr
->Append(new wxExpr((long)node
->Data()));
1200 node
= node
->Next();
1202 clause
->AddAttributeValue("outline_objects", outlineExpr
);
1204 if (m_fillColours
.Number() > 0)
1206 wxExpr
*fillExpr
= new wxExpr(PrologList
);
1207 node
= m_fillColours
.First();
1210 fillExpr
->Append(new wxExpr((long)node
->Data()));
1211 node
= node
->Next();
1213 clause
->AddAttributeValue("fill_objects", fillExpr
);
1218 void wxPseudoMetaFile::ReadPrologAttributes(wxExpr
*clause
)
1220 clause
->AssignAttributeValue("meta_width", &m_width
);
1221 clause
->AssignAttributeValue("meta_height", &m_height
);
1223 int iVal
= (int) m_rotateable
;
1224 clause
->AssignAttributeValue("meta_rotateable", &iVal
);
1225 m_rotateable
= (iVal
!= 0);
1230 bool keepGoing
= TRUE
;
1233 sprintf(buf
, "gdi%d", i
);
1234 wxExpr
*expr
= NULL
;
1235 clause
->AssignAttributeValue(buf
, &expr
);
1242 wxExpr
*idExpr
= expr
->Nth(0);
1243 switch (idExpr
->IntegerValue())
1247 int penWidth
= (int)expr
->Nth(1)->IntegerValue();
1248 int penStyle
= (int)expr
->Nth(2)->IntegerValue();
1249 int penRed
= (int)expr
->Nth(3)->IntegerValue();
1250 int penGreen
= (int)expr
->Nth(4)->IntegerValue();
1251 int penBlue
= (int)expr
->Nth(5)->IntegerValue();
1252 wxColour
col(penRed
, penGreen
, penBlue
);
1253 wxPen
*p
= wxThePenList
->FindOrCreatePen(col
, penWidth
, penStyle
);
1256 m_gdiObjects
.Append(p
);
1261 int brushStyle
= (int)expr
->Nth(1)->IntegerValue();
1262 int brushRed
= (int)expr
->Nth(2)->IntegerValue();
1263 int brushGreen
= (int)expr
->Nth(3)->IntegerValue();
1264 int brushBlue
= (int)expr
->Nth(4)->IntegerValue();
1265 wxColour
col(brushRed
, brushGreen
, brushBlue
);
1266 wxBrush
*b
= wxTheBrushList
->FindOrCreateBrush(col
, brushStyle
);
1269 m_gdiObjects
.Append(b
);
1274 int fontPointSize
= (int)expr
->Nth(1)->IntegerValue();
1275 int fontFamily
= (int)expr
->Nth(2)->IntegerValue();
1276 int fontStyle
= (int)expr
->Nth(3)->IntegerValue();
1277 int fontWeight
= (int)expr
->Nth(4)->IntegerValue();
1278 int fontUnderlined
= (int)expr
->Nth(5)->IntegerValue();
1279 m_gdiObjects
.Append(wxTheFontList
->FindOrCreateFont(fontPointSize
,
1280 fontFamily
, fontStyle
, fontWeight
, (fontUnderlined
!= 0)));
1286 m_gdiObjects
.Append(NULL
);
1294 // Now read in the operations
1299 sprintf(buf
, "op%d", i
);
1300 wxExpr
*expr
= NULL
;
1301 clause
->AssignAttributeValue(buf
, &expr
);
1308 wxExpr
*idExpr
= expr
->Nth(0);
1309 int opId
= (int)idExpr
->IntegerValue();
1312 case DRAWOP_SET_PEN
:
1313 case DRAWOP_SET_BRUSH
:
1314 case DRAWOP_SET_FONT
:
1315 case DRAWOP_SET_TEXT_COLOUR
:
1316 case DRAWOP_SET_BK_COLOUR
:
1317 case DRAWOP_SET_BK_MODE
:
1319 wxOpSetGDI
*theOp
= new wxOpSetGDI(opId
, this, 0);
1320 theOp
->ReadExpr(this, expr
);
1321 m_ops
.Append(theOp
);
1325 case DRAWOP_SET_CLIPPING_RECT
:
1326 case DRAWOP_DESTROY_CLIPPING_RECT
:
1328 wxOpSetClipping
*theOp
= new wxOpSetClipping(opId
, 0.0, 0.0, 0.0, 0.0);
1329 theOp
->ReadExpr(this, expr
);
1330 m_ops
.Append(theOp
);
1334 case DRAWOP_DRAW_LINE
:
1335 case DRAWOP_DRAW_RECT
:
1336 case DRAWOP_DRAW_ROUNDED_RECT
:
1337 case DRAWOP_DRAW_ELLIPSE
:
1338 case DRAWOP_DRAW_POINT
:
1339 case DRAWOP_DRAW_ARC
:
1340 case DRAWOP_DRAW_TEXT
:
1342 wxOpDraw
*theOp
= new wxOpDraw(opId
, 0.0, 0.0, 0.0, 0.0);
1343 theOp
->ReadExpr(this, expr
);
1344 m_ops
.Append(theOp
);
1347 case DRAWOP_DRAW_SPLINE
:
1348 case DRAWOP_DRAW_POLYLINE
:
1349 case DRAWOP_DRAW_POLYGON
:
1351 wxOpPolyDraw
*theOp
= new wxOpPolyDraw(opId
, 0, NULL
);
1352 theOp
->ReadExpr(this, expr
);
1353 m_ops
.Append(theOp
);
1363 // Now read in the list of outline and fill operations, if any
1364 wxExpr
*expr1
= clause
->AttributeValue("outline_objects");
1367 wxExpr
*eachExpr
= expr1
->GetFirst();
1370 m_outlineColours
.Append((wxObject
*)eachExpr
->IntegerValue());
1371 eachExpr
= eachExpr
->GetNext();
1374 expr1
= clause
->AttributeValue("fill_objects");
1377 wxExpr
*eachExpr
= expr1
->GetFirst();
1380 m_fillColours
.Append((wxObject
*)eachExpr
->IntegerValue());
1381 eachExpr
= eachExpr
->GetNext();
1387 // Does the copying for this object
1388 void wxPseudoMetaFile::Copy(wxPseudoMetaFile
& copy
)
1390 copy
.m_currentRotation
= m_currentRotation
;
1391 copy
.m_width
= m_width
;
1392 copy
.m_height
= m_height
;
1393 copy
.m_rotateable
= m_rotateable
;
1394 copy
.m_fillBrush
= m_fillBrush
;
1395 copy
.m_outlinePen
= m_outlinePen
;
1399 // Copy the GDI objects
1400 wxNode
*node
= m_gdiObjects
.First();
1403 wxObject
*obj
= (wxObject
*)node
->Data();
1404 copy
.m_gdiObjects
.Append(obj
);
1405 node
= node
->Next();
1408 // Copy the operations
1409 node
= m_ops
.First();
1412 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1413 copy
.m_ops
.Append(op
->Copy(©
));
1414 node
= node
->Next();
1417 // Copy the outline/fill operations
1418 node
= m_outlineColours
.First();
1421 copy
.m_outlineColours
.Append((wxObject
*)node
->Data());
1422 node
= node
->Next();
1424 node
= m_fillColours
.First();
1427 copy
.m_fillColours
.Append((wxObject
*)node
->Data());
1428 node
= node
->Next();
1433 * Pass size of existing image; scale height to
1434 * fit width and return new width and height.
1438 bool wxPseudoMetaFile::LoadFromMetaFile(char *filename
, float *rwidth
, float *rheight
)
1440 if (!FileExists(filename
))
1443 wxXMetaFile
*metaFile
= new wxXMetaFile
;
1445 if (!metaFile
->ReadFile(filename
))
1454 // Convert from metafile records to wxDrawnShape records
1455 wxNode
*node
= metaFile
->metaRecords
.First();
1458 wxMetaRecord
*record
= (wxMetaRecord
*)node
->Data();
1459 switch (record
->metaFunction
)
1461 case META_SETBKCOLOR
:
1463 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BK_COLOUR
, this, 0);
1464 op
->m_r
= (unsigned char)record
->param1
;
1465 op
->m_g
= (unsigned char)record
->param2
;
1466 op
->m_b
= (unsigned char)record
->param3
;
1470 case META_SETBKMODE
:
1472 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BK_MODE
, this, 0, (int)record
->param1
);
1476 case META_SETMAPMODE
:
1480 // case META_SETROP2:
1481 // case META_SETRELABS:
1482 // case META_SETPOLYFILLMODE:
1483 // case META_SETSTRETCHBLTMODE:
1484 // case META_SETTEXTCHAREXTRA:
1485 case META_SETTEXTCOLOR
:
1487 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR
, this, 0);
1488 op
->m_r
= (unsigned char)record
->param1
;
1489 op
->m_g
= (unsigned char)record
->param2
;
1490 op
->m_b
= (unsigned char)record
->param3
;
1494 // case META_SETTEXTJUSTIFICATION:
1495 // case META_SETWINDOWORG:
1496 // case META_SETWINDOWEXT:
1497 // case META_SETVIEWPORTORG:
1498 // case META_SETVIEWPORTEXT:
1499 // case META_OFFSETWINDOWORG:
1500 // case META_SCALEWINDOWEXT:
1501 // case META_OFFSETVIEWPORTORG:
1502 // case META_SCALEVIEWPORTEXT:
1505 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_LINE
, (float)lastX
, (float)lastY
,
1506 (float)record
->param1
, (float)record
->param2
);
1512 lastX
= (float)record
->param1
;
1513 lastY
= (float)record
->param2
;
1516 case META_EXCLUDECLIPRECT
:
1519 wxMetaRecord *rec = new wxMetaRecord(META_EXCLUDECLIPRECT);
1520 rec->param4 = getshort(handle); // m_y2
1521 rec->param3 = getshort(handle); // x2
1522 rec->param2 = getshort(handle); // y1
1523 rec->param1 = getshort(handle); // x1
1527 case META_INTERSECTCLIPRECT
:
1530 rec->param4 = getshort(handle); // m_y2
1531 rec->param3 = getshort(handle); // x2
1532 rec->param2 = getshort(handle); // y1
1533 rec->param1 = getshort(handle); // x1
1537 // case META_ARC: // DO!!!
1540 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_ELLIPSE
,
1541 (float)record
->param1
, (float)record
->param2
,
1542 (float)(record
->param3
- record
->param1
),
1543 (float)(record
->param4
- record
->param2
));
1547 // case META_FLOODFILL:
1548 // case META_PIE: // DO!!!
1549 case META_RECTANGLE
:
1551 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_RECT
,
1552 (float)record
->param1
, (float)record
->param2
,
1553 (float)(record
->param3
- record
->param1
),
1554 (float)(record
->param4
- record
->param2
));
1558 case META_ROUNDRECT
:
1560 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT
,
1561 (float)record
->param1
, (float)record
->param2
,
1562 (float)(record
->param3
- record
->param1
),
1563 (float)(record
->param4
- record
->param2
), (float)record
->param5
);
1567 // case META_PATBLT:
1568 // case META_SAVEDC:
1571 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_POINT
,
1572 (float)record
->param1
, (float)record
->param2
,
1575 // SHOULD SET THE COLOUR - SET PEN?
1576 // rec->param3 = getint(handle); // COLORREF
1580 // case META_OFFSETCLIPRGN:
1583 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_TEXT
,
1584 (float)record
->param1
, (float)record
->param2
,
1585 0.0, 0.0, 0.0, record
->stringParam
);
1589 // case META_BITBLT:
1590 // case META_STRETCHBLT:
1593 int n
= (int)record
->param1
;
1594 wxRealPoint
*newPoints
= new wxRealPoint
[n
];
1595 for (int i
= 0; i
< n
; i
++)
1597 newPoints
[i
].x
= record
->points
[i
].x
;
1598 newPoints
[i
].y
= record
->points
[i
].y
;
1601 wxOpPolyDraw
*op
= new wxOpPolyDraw(DRAWOP_DRAW_POLYGON
, n
, newPoints
);
1607 int n
= (int)record
->param1
;
1608 wxRealPoint
*newPoints
= new wxRealPoint
[n
];
1609 for (int i
= 0; i
< n
; i
++)
1611 newPoints
[i
].x
= record
->points
[i
].x
;
1612 newPoints
[i
].y
= record
->points
[i
].y
;
1615 wxOpPolyDraw
*op
= new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE
, n
, newPoints
);
1619 // case META_ESCAPE:
1620 // case META_RESTOREDC:
1621 // case META_FILLREGION:
1622 // case META_FRAMEREGION:
1623 // case META_INVERTREGION:
1624 // case META_PAINTREGION:
1625 // case META_SELECTCLIPREGION: // DO THIS!
1626 case META_SELECTOBJECT
:
1628 // The pen, brush etc. has already been created when the metafile
1629 // was read in, so we don't create it - we set it.
1630 wxNode
*recNode
= metaFile
->gdiObjects
.Nth((int)record
->param2
);
1633 wxMetaRecord
*gdiRec
= (wxMetaRecord
*)recNode
->Data();
1634 if (gdiRec
&& (gdiRec
->param1
!= 0))
1636 wxObject
*obj
= (wxObject
*)gdiRec
->param1
;
1637 if (obj
->IsKindOf(CLASSINFO(wxPen
)))
1639 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_PEN
, this, (int)record
->param2
);
1642 else if (obj
->IsKindOf(CLASSINFO(wxBrush
)))
1644 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BRUSH
, this, (int)record
->param2
);
1647 else if (obj
->IsKindOf(CLASSINFO(wxFont
)))
1649 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_FONT
, this, (int)record
->param2
);
1656 // case META_SETTEXTALIGN:
1657 // case META_DRAWTEXT:
1659 // case META_SETMAPPERFLAGS:
1660 // case META_EXTTEXTOUT:
1661 // case META_SETDIBTODEV:
1662 // case META_SELECTPALETTE:
1663 // case META_REALIZEPALETTE:
1664 // case META_ANIMATEPALETTE:
1665 // case META_SETPALENTRIES:
1666 // case META_POLYPOLYGON:
1667 // case META_RESIZEPALETTE:
1668 // case META_DIBBITBLT:
1669 // case META_DIBSTRETCHBLT:
1670 case META_DIBCREATEPATTERNBRUSH
:
1673 m_gdiObjects
.Append(NULL
);
1676 // case META_STRETCHDIB:
1677 // case META_EXTFLOODFILL:
1678 // case META_RESETDC:
1679 // case META_STARTDOC:
1680 // case META_STARTPAGE:
1681 // case META_ENDPAGE:
1682 // case META_ABORTDOC:
1683 // case META_ENDDOC:
1684 // case META_DELETEOBJECT: // DO!!
1685 case META_CREATEPALETTE
:
1688 m_gdiObjects
.Append(NULL
);
1691 case META_CREATEBRUSH
:
1694 m_gdiObjects
.Append(NULL
);
1697 case META_CREATEPATTERNBRUSH
:
1700 m_gdiObjects
.Append(NULL
);
1703 case META_CREATEPENINDIRECT
:
1705 // The pen is created when the metafile is read in.
1706 // We keep track of all the GDI objects needed for this
1707 // image so when reading the wxDrawnShape from file,
1708 // we can read in all the GDI objects, then refer
1709 // to them by an index starting from zero thereafter.
1710 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1713 case META_CREATEFONTINDIRECT
:
1715 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1718 case META_CREATEBRUSHINDIRECT
:
1720 // Don't have to do anything here: the pen is created
1721 // when the metafile is read in.
1722 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1725 case META_CREATEBITMAPINDIRECT
:
1728 m_gdiObjects
.Append(NULL
);
1731 case META_CREATEBITMAP
:
1734 m_gdiObjects
.Append(NULL
);
1737 case META_CREATEREGION
:
1740 m_gdiObjects
.Append(NULL
);
1748 node
= node
->Next();
1750 float actualWidth
= (float)fabs(metaFile
->right
- metaFile
->left
);
1751 float actualHeight
= (float)fabs(metaFile
->bottom
- metaFile
->top
);
1753 float initialScaleX
= 1.0;
1754 float initialScaleY
= 1.0;
1756 float xoffset
, yoffset
;
1758 // Translate so origin is at centre of rectangle
1759 if (metaFile
->bottom
> metaFile
->top
)
1760 yoffset
= - (float)((metaFile
->bottom
- metaFile
->top
)/2.0);
1762 yoffset
= - (float)((metaFile
->top
- metaFile
->bottom
)/2.0);
1764 if (metaFile
->right
> metaFile
->left
)
1765 xoffset
= - (float)((metaFile
->right
- metaFile
->left
)/2.0);
1767 xoffset
= - (float)((metaFile
->left
- metaFile
->right
)/2.0);
1769 Translate(xoffset
, yoffset
);
1771 // Scale to a reasonable size (take the width of this wxDrawnShape
1773 if (actualWidth
!= 0.0)
1775 initialScaleX
= (float)((*rwidth
) / actualWidth
);
1776 initialScaleY
= initialScaleX
;
1777 (*rheight
) = initialScaleY
*actualHeight
;
1779 Scale(initialScaleX
, initialScaleY
);
1781 m_width
= (actualWidth
*initialScaleX
);
1782 m_height
= *rheight
;
1788 // Scale to fit size
1789 void wxPseudoMetaFile::ScaleTo(float w
, float h
)
1791 float scaleX
= (float)(w
/m_width
);
1792 float scaleY
= (float)(h
/m_height
);
1795 Scale(scaleX
, scaleY
);
1798 void wxPseudoMetaFile::GetBounds(float *boundMinX
, float *boundMinY
, float *boundMaxX
, float *boundMaxY
)
1800 float maxX
= (float) -99999.9;
1801 float maxY
= (float) -99999.9;
1802 float minX
= (float) 99999.9;
1803 float minY
= (float) 99999.9;
1805 wxNode
*node
= m_ops
.First();
1808 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1809 switch (op
->GetOp())
1811 case DRAWOP_DRAW_LINE
:
1812 case DRAWOP_DRAW_RECT
:
1813 case DRAWOP_DRAW_ROUNDED_RECT
:
1814 case DRAWOP_DRAW_ELLIPSE
:
1815 case DRAWOP_DRAW_POINT
:
1816 case DRAWOP_DRAW_ARC
:
1817 case DRAWOP_DRAW_TEXT
:
1819 wxOpDraw
*opDraw
= (wxOpDraw
*)op
;
1820 if (opDraw
->m_x1
< minX
) minX
= opDraw
->m_x1
;
1821 if (opDraw
->m_x1
> maxX
) maxX
= opDraw
->m_x1
;
1822 if (opDraw
->m_y1
< minY
) minY
= opDraw
->m_y1
;
1823 if (opDraw
->m_y1
> maxY
) maxY
= opDraw
->m_y1
;
1824 if (op
->GetOp() == DRAWOP_DRAW_LINE
)
1826 if (opDraw
->m_x2
< minX
) minX
= opDraw
->m_x2
;
1827 if (opDraw
->m_x2
> maxX
) maxX
= opDraw
->m_x2
;
1828 if (opDraw
->m_y2
< minY
) minY
= opDraw
->m_y2
;
1829 if (opDraw
->m_y2
> maxY
) maxY
= opDraw
->m_y2
;
1831 else if (op
->GetOp() == DRAWOP_DRAW_RECT
||
1832 op
->GetOp() == DRAWOP_DRAW_ROUNDED_RECT
||
1833 op
->GetOp() == DRAWOP_DRAW_ELLIPSE
)
1835 if ((opDraw
->m_x1
+ opDraw
->m_x2
) < minX
) minX
= (opDraw
->m_x1
+ opDraw
->m_x2
);
1836 if ((opDraw
->m_x1
+ opDraw
->m_x2
) > maxX
) maxX
= (opDraw
->m_x1
+ opDraw
->m_x2
);
1837 if ((opDraw
->m_y1
+ opDraw
->m_y2
) < minY
) minY
= (opDraw
->m_y1
+ opDraw
->m_y2
);
1838 if ((opDraw
->m_y1
+ opDraw
->m_y2
) > maxY
) maxY
= (opDraw
->m_y1
+ opDraw
->m_y2
);
1842 case DRAWOP_DRAW_POLYLINE
:
1843 case DRAWOP_DRAW_POLYGON
:
1844 case DRAWOP_DRAW_SPLINE
:
1846 wxOpPolyDraw
*poly
= (wxOpPolyDraw
*)op
;
1847 for (int i
= 0; i
< poly
->m_noPoints
; i
++)
1849 if (poly
->m_points
[i
].x
< minX
) minX
= poly
->m_points
[i
].x
;
1850 if (poly
->m_points
[i
].x
> maxX
) maxX
= poly
->m_points
[i
].x
;
1851 if (poly
->m_points
[i
].y
< minY
) minY
= poly
->m_points
[i
].y
;
1852 if (poly
->m_points
[i
].y
> maxY
) maxY
= poly
->m_points
[i
].y
;
1859 node
= node
->Next();
1867 *w = (float)fabs(maxX - minX);
1868 *h = (float)fabs(maxY - minY);
1872 // Calculate size from current operations
1873 void wxPseudoMetaFile::CalculateSize(wxDrawnShape
* shape
)
1875 float boundMinX
, boundMinY
, boundMaxX
, boundMaxY
;
1877 GetBounds(& boundMinX
, & boundMinY
, & boundMaxX
, & boundMaxY
);
1879 SetSize(boundMaxX
- boundMinX
, boundMaxY
- boundMinY
);
1883 shape
->SetWidth(m_width
);
1884 shape
->SetHeight(m_height
);
1888 // Set of functions for drawing into a pseudo metafile.
1889 // They use integers, but doubles are used internally for accuracy
1892 void wxPseudoMetaFile::DrawLine(const wxPoint
& pt1
, const wxPoint
& pt2
)
1894 wxOpDraw
*theOp
= new wxOpDraw(DRAWOP_DRAW_LINE
,
1895 (double) pt1
.x
, (double) pt1
.y
, (double) pt2
.x
, (double) pt2
.y
);
1897 m_ops
.Append(theOp
);
1900 void wxPseudoMetaFile::DrawRectangle(const wxRect
& rect
)
1902 wxOpDraw
*theOp
= new wxOpDraw(DRAWOP_DRAW_RECT
,
1903 (double) rect
.x
, (double) rect
.y
, (double) rect
.width
, (double) rect
.height
);
1905 m_ops
.Append(theOp
);
1908 void wxPseudoMetaFile::DrawRoundedRectangle(const wxRect
& rect
, double radius
)
1910 wxOpDraw
*theOp
= new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT
,
1911 (double) rect
.x
, (double) rect
.y
, (double) rect
.width
, (double) rect
.height
);
1913 theOp
->m_radius
= radius
;
1915 m_ops
.Append(theOp
);
1918 void wxPseudoMetaFile::DrawEllipse(const wxRect
& rect
)
1920 wxOpDraw
*theOp
= new wxOpDraw(DRAWOP_DRAW_ELLIPSE
,
1921 (double) rect
.x
, (double) rect
.y
, (double) rect
.width
, (double) rect
.height
);
1923 m_ops
.Append(theOp
);
1926 void wxPseudoMetaFile::DrawPoint(const wxPoint
& pt
)
1928 wxOpDraw
*theOp
= new wxOpDraw(DRAWOP_DRAW_POINT
,
1929 (double) pt
.x
, (double) pt
.y
, 0.0, 0.0);
1931 m_ops
.Append(theOp
);
1934 void wxPseudoMetaFile::DrawText(const wxString
& text
, const wxPoint
& pt
)
1936 wxOpDraw
*theOp
= new wxOpDraw(DRAWOP_DRAW_TEXT
,
1937 (double) pt
.x
, (double) pt
.y
, 0.0, 0.0);
1939 theOp
->m_textString
= copystring(text
);
1941 m_ops
.Append(theOp
);
1944 void wxPseudoMetaFile::DrawLines(int n
, wxPoint pts
[])
1946 wxRealPoint
* realPoints
= new wxRealPoint
[n
];
1948 for (i
= 0; i
< n
; i
++)
1950 realPoints
[i
].x
= pts
[i
].x
;
1951 realPoints
[i
].y
= pts
[i
].y
;
1953 wxOpPolyDraw
* theOp
= new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE
, n
, realPoints
);
1954 m_ops
.Append(theOp
);
1957 void wxPseudoMetaFile::DrawPolygon(int n
, wxPoint pts
[])
1959 wxRealPoint
* realPoints
= new wxRealPoint
[n
];
1961 for (i
= 0; i
< n
; i
++)
1963 realPoints
[i
].x
= pts
[i
].x
;
1964 realPoints
[i
].y
= pts
[i
].y
;
1966 wxOpPolyDraw
* theOp
= new wxOpPolyDraw(DRAWOP_DRAW_POLYGON
, n
, realPoints
);
1967 m_ops
.Append(theOp
);
1970 void wxPseudoMetaFile::DrawSpline(int n
, wxPoint pts
[])
1972 wxRealPoint
* realPoints
= new wxRealPoint
[n
];
1974 for (i
= 0; i
< n
; i
++)
1976 realPoints
[i
].x
= pts
[i
].x
;
1977 realPoints
[i
].y
= pts
[i
].y
;
1979 wxOpPolyDraw
* theOp
= new wxOpPolyDraw(DRAWOP_DRAW_SPLINE
, n
, realPoints
);
1980 m_ops
.Append(theOp
);
1983 void wxPseudoMetaFile::SetClippingRect(const wxRect
& rect
)
1985 wxOpSetClipping
* theOp
= new wxOpSetClipping(DRAWOP_SET_CLIPPING_RECT
,
1986 (double) rect
.x
, (double) rect
.y
, (double) rect
.width
, (double) rect
.height
);
1989 void wxPseudoMetaFile::DestroyClippingRect()
1991 wxOpSetClipping
* theOp
= new wxOpSetClipping(DRAWOP_DESTROY_CLIPPING_RECT
,
1992 0.0, 0.0, 0.0, 0.0);
1994 m_ops
.Append(theOp
);
1997 void wxPseudoMetaFile::SetPen(wxPen
* pen
, bool isOutline
)
1999 m_gdiObjects
.Append(pen
);
2000 int n
= m_gdiObjects
.Number();
2002 wxOpSetGDI
* theOp
= new wxOpSetGDI(DRAWOP_SET_PEN
, this, n
- 1);
2004 m_ops
.Append(theOp
);
2008 m_outlineColours
.Append((wxObject
*) (n
- 1));
2012 void wxPseudoMetaFile::SetBrush(wxBrush
* brush
, bool isFill
)
2014 m_gdiObjects
.Append(brush
);
2015 int n
= m_gdiObjects
.Number();
2017 wxOpSetGDI
* theOp
= new wxOpSetGDI(DRAWOP_SET_BRUSH
, this, n
- 1);
2019 m_ops
.Append(theOp
);
2023 m_fillColours
.Append((wxObject
*) (n
- 1));
2027 void wxPseudoMetaFile::SetFont(wxFont
* font
)
2029 m_gdiObjects
.Append(font
);
2030 int n
= m_gdiObjects
.Number();
2032 wxOpSetGDI
* theOp
= new wxOpSetGDI(DRAWOP_SET_FONT
, this, n
- 1);
2034 m_ops
.Append(theOp
);
2037 void wxPseudoMetaFile::SetTextColour(const wxColour
& colour
)
2039 wxOpSetGDI
* theOp
= new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR
, this, 0);
2040 theOp
->m_r
= colour
.Red();
2041 theOp
->m_g
= colour
.Green();
2042 theOp
->m_b
= colour
.Blue();
2044 m_ops
.Append(theOp
);
2047 void wxPseudoMetaFile::SetBackgroundColour(const wxColour
& colour
)
2049 wxOpSetGDI
* theOp
= new wxOpSetGDI(DRAWOP_SET_BK_COLOUR
, this, 0);
2050 theOp
->m_r
= colour
.Red();
2051 theOp
->m_g
= colour
.Green();
2052 theOp
->m_b
= colour
.Blue();
2054 m_ops
.Append(theOp
);
2057 void wxPseudoMetaFile::SetBackgroundMode(int mode
)
2059 wxOpSetGDI
* theOp
= new wxOpSetGDI(DRAWOP_SET_BK_MODE
, this, 0, mode
);
2061 m_ops
.Append(theOp
);