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
, wxShape
)
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
);
104 void wxDrawnShape::Translate(float x
, float y
)
106 m_metafile
.Translate(x
, y
);
109 void wxDrawnShape::Rotate(float x
, float y
, float theta
)
111 if (!m_metafile
.GetRotateable())
114 float actualTheta
= theta
-m_metafile
.m_currentRotation
;
117 m_metafile
.Rotate(x
, y
, theta
);
119 // Rotate attachment points
120 float sinTheta
= (float)sin(actualTheta
);
121 float cosTheta
= (float)cos(actualTheta
);
122 wxNode
*node
= m_attachmentPoints
.First();
125 wxAttachmentPoint
*point
= (wxAttachmentPoint
*)node
->Data();
126 float x1
= point
->m_x
;
127 float y1
= point
->m_y
;
128 point
->m_x
= x1
*cosTheta
- y1
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
129 point
->m_y
= x1
*sinTheta
+ y1
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
136 // Prolog database stuff
137 char *wxDrawnShape::GetFunctor()
142 void wxDrawnShape::WritePrologAttributes(wxExpr
*clause
)
144 wxRectangleShape::WritePrologAttributes(clause
);
146 clause
->AddAttributeValue("save_metafile", (long)m_saveToFile
);
148 m_metafile
.WritePrologAttributes(clause
);
151 void wxDrawnShape::ReadPrologAttributes(wxExpr
*clause
)
153 wxRectangleShape::ReadPrologAttributes(clause
);
155 int iVal
= (int) m_saveToFile
;
156 clause
->AssignAttributeValue("save_metafile", &iVal
);
157 m_saveToFile
= (iVal
!= 0);
160 m_metafile
.ReadPrologAttributes(clause
);
164 // Does the copying for this object
165 void wxDrawnShape::Copy(wxShape
& copy
)
167 wxRectangleShape::Copy(copy
);
169 wxASSERT( copy
.IsKindOf(CLASSINFO(wxDrawnShape
)) ) ;
171 wxDrawnShape
& drawnCopy
= (wxDrawnShape
&) copy
;
173 m_metafile
.Copy(drawnCopy
.m_metafile
);
174 drawnCopy
.m_saveToFile
= m_saveToFile
;
177 bool wxDrawnShape::LoadFromMetaFile(char *filename
)
179 return m_metafile
.LoadFromMetaFile(filename
, &m_width
, &m_height
);
183 * Individual operations
188 * Set font, brush, text colour
192 wxOpSetGDI::wxOpSetGDI(int theOp
, wxPseudoMetaFile
*theImage
, int theGdiIndex
, int theMode
):
195 gdiIndex
= theGdiIndex
;
200 void wxOpSetGDI::Do(wxDC
& dc
, float xoffset
, float yoffset
)
206 // Check for overriding this operation for outline
208 if (image
->m_outlineColours
.Member((wxObject
*)gdiIndex
))
210 if (image
->m_outlinePen
)
211 dc
.SetPen(image
->m_outlinePen
);
215 wxNode
*node
= image
->m_gdiObjects
.Nth(gdiIndex
);
218 wxPen
*pen
= (wxPen
*)node
->Data();
225 case DRAWOP_SET_BRUSH
:
227 // Check for overriding this operation for outline or fill
229 if (image
->m_outlineColours
.Member((wxObject
*)gdiIndex
))
231 // Need to construct a brush to match the outline pen's colour
232 if (image
->m_outlinePen
)
234 wxBrush
*br
= wxTheBrushList
->FindOrCreateBrush(image
->m_outlinePen
->GetColour(), wxSOLID
);
239 else if (image
->m_fillColours
.Member((wxObject
*)gdiIndex
))
241 if (image
->m_fillBrush
)
243 dc
.SetBrush(image
->m_fillBrush
);
248 wxNode
*node
= image
->m_gdiObjects
.Nth(gdiIndex
);
251 wxBrush
*brush
= (wxBrush
*)node
->Data();
258 case DRAWOP_SET_FONT
:
260 wxNode
*node
= image
->m_gdiObjects
.Nth(gdiIndex
);
263 wxFont
*font
= (wxFont
*)node
->Data();
269 case DRAWOP_SET_TEXT_COLOUR
:
272 dc
.SetTextForeground(col
);
275 case DRAWOP_SET_BK_COLOUR
:
278 dc
.SetTextBackground(col
);
281 case DRAWOP_SET_BK_MODE
:
283 dc
.SetBackgroundMode(mode
);
291 wxDrawOp
*wxOpSetGDI::Copy(wxPseudoMetaFile
*newImage
)
293 wxOpSetGDI
*newOp
= new wxOpSetGDI(op
, newImage
, gdiIndex
, mode
);
300 wxExpr
*wxOpSetGDI::WritewxExpr(wxPseudoMetaFile
*image
)
302 wxExpr
*expr
= new wxExpr(PrologList
);
303 expr
->Append(new wxExpr((long)op
));
307 case DRAWOP_SET_BRUSH
:
308 case DRAWOP_SET_FONT
:
310 expr
->Append(new wxExpr((long)gdiIndex
));
313 case DRAWOP_SET_TEXT_COLOUR
:
314 case DRAWOP_SET_BK_COLOUR
:
316 expr
->Append(new wxExpr((long)r
));
317 expr
->Append(new wxExpr((long)g
));
318 expr
->Append(new wxExpr((long)b
));
321 case DRAWOP_SET_BK_MODE
:
323 expr
->Append(new wxExpr((long)mode
));
332 void wxOpSetGDI::ReadwxExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
337 case DRAWOP_SET_BRUSH
:
338 case DRAWOP_SET_FONT
:
340 gdiIndex
= (int)expr
->Nth(1)->IntegerValue();
343 case DRAWOP_SET_TEXT_COLOUR
:
344 case DRAWOP_SET_BK_COLOUR
:
346 r
= (unsigned char)expr
->Nth(1)->IntegerValue();
347 g
= (unsigned char)expr
->Nth(2)->IntegerValue();
348 b
= (unsigned char)expr
->Nth(3)->IntegerValue();
351 case DRAWOP_SET_BK_MODE
:
353 mode
= (int)expr
->Nth(1)->IntegerValue();
362 * Set/destroy clipping
366 wxOpSetClipping::wxOpSetClipping(int theOp
, float theX1
, float theY1
,
367 float theX2
, float theY2
):wxDrawOp(theOp
)
375 wxDrawOp
*wxOpSetClipping::Copy(wxPseudoMetaFile
*newImage
)
377 wxOpSetClipping
*newOp
= new wxOpSetClipping(op
, x1
, y1
, x2
, y2
);
381 void wxOpSetClipping::Do(wxDC
& dc
, float xoffset
, float yoffset
)
385 case DRAWOP_SET_CLIPPING_RECT
:
387 dc
.SetClippingRegion(x1
+ xoffset
, y1
+ yoffset
, x2
+ xoffset
, y2
+ yoffset
);
390 case DRAWOP_DESTROY_CLIPPING_RECT
:
392 dc
.DestroyClippingRegion();
400 void wxOpSetClipping::Scale(float xScale
, float yScale
)
408 void wxOpSetClipping::Translate(float x
, float y
)
414 wxExpr
*wxOpSetClipping::WritewxExpr(wxPseudoMetaFile
*image
)
416 wxExpr
*expr
= new wxExpr(PrologList
);
417 expr
->Append(new wxExpr((long)op
));
420 case DRAWOP_SET_CLIPPING_RECT
:
422 expr
->Append(new wxExpr(x1
));
423 expr
->Append(new wxExpr(y1
));
424 expr
->Append(new wxExpr(x2
));
425 expr
->Append(new wxExpr(y2
));
434 void wxOpSetClipping::ReadwxExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
438 case DRAWOP_SET_CLIPPING_RECT
:
440 x1
= expr
->Nth(1)->RealValue();
441 y1
= expr
->Nth(2)->RealValue();
442 x2
= expr
->Nth(3)->RealValue();
443 y2
= expr
->Nth(4)->RealValue();
452 * Draw line, rectangle, rounded rectangle, ellipse, point, arc, text
456 wxOpDraw::wxOpDraw(int theOp
, float theX1
, float theY1
, float theX2
, float theY2
,
457 float theRadius
, char *s
):wxDrawOp(theOp
)
464 if (s
) textString
= copystring(s
);
465 else textString
= NULL
;
468 wxOpDraw::~wxOpDraw()
470 if (textString
) delete[] textString
;
473 wxDrawOp
*wxOpDraw::Copy(wxPseudoMetaFile
*newImage
)
475 wxOpDraw
*newOp
= new wxOpDraw(op
, x1
, y1
, x2
, y2
, radius
, textString
);
479 void wxOpDraw::Do(wxDC
& dc
, float xoffset
, float yoffset
)
483 case DRAWOP_DRAW_LINE
:
485 dc
.DrawLine(x1
+xoffset
, y1
+yoffset
, x2
+xoffset
, y2
+yoffset
);
488 case DRAWOP_DRAW_RECT
:
490 dc
.DrawRectangle(x1
+xoffset
, y1
+yoffset
, x2
+xoffset
, y2
+yoffset
);
493 case DRAWOP_DRAW_ROUNDED_RECT
:
495 dc
.DrawRoundedRectangle(x1
+xoffset
, y1
+yoffset
, x2
+xoffset
, y2
+yoffset
, radius
);
498 case DRAWOP_DRAW_ELLIPSE
:
500 dc
.DrawEllipse(x1
+xoffset
, y1
+yoffset
, x2
+xoffset
, y2
+yoffset
);
503 case DRAWOP_DRAW_POINT
:
505 dc
.DrawPoint(x1
+xoffset
, y1
+yoffset
);
508 case DRAWOP_DRAW_TEXT
:
510 dc
.DrawText(textString
, x1
+xoffset
, y1
+yoffset
);
518 void wxOpDraw::Scale(float scaleX
, float scaleY
)
527 void wxOpDraw::Translate(float x
, float y
)
533 void wxOpDraw::Rotate(float x
, float y
, float sinTheta
, float cosTheta
)
535 x1
= x1
*cosTheta
- y1
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
536 y1
= x1
*sinTheta
+ y1
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
540 case DRAWOP_DRAW_LINE
:
542 x2
= x2
*cosTheta
- y2
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
543 y2
= x2
*sinTheta
+ y2
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
551 wxExpr
*wxOpDraw::WritewxExpr(wxPseudoMetaFile
*image
)
553 wxExpr
*expr
= new wxExpr(PrologList
);
554 expr
->Append(new wxExpr((long)op
));
557 case DRAWOP_DRAW_LINE
:
558 case DRAWOP_DRAW_RECT
:
559 case DRAWOP_DRAW_ELLIPSE
:
561 expr
->Append(new wxExpr(x1
));
562 expr
->Append(new wxExpr(y1
));
563 expr
->Append(new wxExpr(x2
));
564 expr
->Append(new wxExpr(y2
));
567 case DRAWOP_DRAW_ROUNDED_RECT
:
569 expr
->Append(new wxExpr(x1
));
570 expr
->Append(new wxExpr(y1
));
571 expr
->Append(new wxExpr(x2
));
572 expr
->Append(new wxExpr(y2
));
573 expr
->Append(new wxExpr(radius
));
576 case DRAWOP_DRAW_POINT
:
578 expr
->Append(new wxExpr(x1
));
579 expr
->Append(new wxExpr(y1
));
582 case DRAWOP_DRAW_TEXT
:
584 expr
->Append(new wxExpr(x1
));
585 expr
->Append(new wxExpr(y1
));
586 expr
->Append(new wxExpr(PrologString
, textString
));
589 case DRAWOP_DRAW_ARC
:
598 void wxOpDraw::ReadwxExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
602 case DRAWOP_DRAW_LINE
:
603 case DRAWOP_DRAW_RECT
:
604 case DRAWOP_DRAW_ELLIPSE
:
606 x1
= expr
->Nth(1)->RealValue();
607 y1
= expr
->Nth(2)->RealValue();
608 x2
= expr
->Nth(3)->RealValue();
609 y2
= expr
->Nth(4)->RealValue();
612 case DRAWOP_DRAW_ROUNDED_RECT
:
614 x1
= expr
->Nth(1)->RealValue();
615 y1
= expr
->Nth(2)->RealValue();
616 x2
= expr
->Nth(3)->RealValue();
617 y2
= expr
->Nth(4)->RealValue();
618 radius
= expr
->Nth(5)->RealValue();
621 case DRAWOP_DRAW_POINT
:
623 x1
= expr
->Nth(1)->RealValue();
624 y1
= expr
->Nth(2)->RealValue();
627 case DRAWOP_DRAW_TEXT
:
629 x1
= expr
->Nth(1)->RealValue();
630 y1
= expr
->Nth(2)->RealValue();
631 textString
= copystring(expr
->Nth(3)->StringValue());
634 case DRAWOP_DRAW_ARC
:
643 * Draw polygon, polyline, spline
647 wxOpPolyDraw::wxOpPolyDraw(int theOp
, int n
, wxRealPoint
*thePoints
):wxDrawOp(theOp
)
653 wxOpPolyDraw::~wxOpPolyDraw()
658 wxDrawOp
*wxOpPolyDraw::Copy(wxPseudoMetaFile
*newImage
)
660 wxRealPoint
*newPoints
= new wxRealPoint
[noPoints
];
661 for (int i
= 0; i
< noPoints
; i
++)
663 newPoints
[i
].x
= points
[i
].x
;
664 newPoints
[i
].y
= points
[i
].y
;
666 wxOpPolyDraw
*newOp
= new wxOpPolyDraw(op
, noPoints
, newPoints
);
670 void wxOpPolyDraw::Do(wxDC
& dc
, float xoffset
, float yoffset
)
674 case DRAWOP_DRAW_POLYLINE
:
676 wxPoint
*actualPoints
= new wxPoint
[noPoints
];
678 for (i
= 0; i
< noPoints
; i
++)
680 actualPoints
[i
].x
= (long) points
[i
].x
;
681 actualPoints
[i
].y
= (long) points
[i
].y
;
684 dc
.DrawLines(noPoints
, actualPoints
, xoffset
, yoffset
);
686 delete[] actualPoints
;
689 case DRAWOP_DRAW_POLYGON
:
691 wxPoint
*actualPoints
= new wxPoint
[noPoints
];
693 for (i
= 0; i
< noPoints
; i
++)
695 actualPoints
[i
].x
= (long) points
[i
].x
;
696 actualPoints
[i
].y
= (long) points
[i
].y
;
699 dc
.DrawPolygon(noPoints
, actualPoints
, xoffset
, yoffset
);
701 delete[] actualPoints
;
704 case DRAWOP_DRAW_SPLINE
:
706 // dc.DrawSpline(noPoints, points, xoffset, yoffset);
714 void wxOpPolyDraw::Scale(float scaleX
, float scaleY
)
716 for (int i
= 0; i
< noPoints
; i
++)
718 points
[i
].x
*= scaleX
;
719 points
[i
].y
*= scaleY
;
723 void wxOpPolyDraw::Translate(float x
, float y
)
725 for (int i
= 0; i
< noPoints
; i
++)
732 void wxOpPolyDraw::Rotate(float x
, float y
, float sinTheta
, float cosTheta
)
734 for (int i
= 0; i
< noPoints
; i
++)
736 float x1
= points
[i
].x
;
737 float y1
= points
[i
].y
;
738 points
[i
].x
= x1
*cosTheta
- y1
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
739 points
[i
].y
= x1
*sinTheta
+ y1
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
743 wxExpr
*wxOpPolyDraw::WritewxExpr(wxPseudoMetaFile
*image
)
745 wxExpr
*expr
= new wxExpr(PrologList
);
746 expr
->Append(new wxExpr((long)op
));
747 expr
->Append(new wxExpr((long)noPoints
));
753 GraphicsBuffer
[0] = 0;
756 * Store each coordinate pair in a hex string to save space.
757 * E.g. "1B9080CD". 4 hex digits per coordinate pair.
761 for (int i
= 0; i
< noPoints
; i
++)
763 long signedX
= (long)(points
[i
].x
*100.0);
764 long signedY
= (long)(points
[i
].y
*100.0);
767 long unSignedX
= (long)(signedX
+ 32767.0);
768 long unSignedY
= (long)(signedY
+ 32767.0);
770 // IntToHex((unsigned int)signedX, buf2);
771 // IntToHex((unsigned int)signedY, buf3);
772 IntToHex((int)unSignedX
, buf2
);
773 IntToHex((int)unSignedY
, buf3
);
775 // Don't overrun the buffer
778 strcat(GraphicsBuffer
, buf2
);
779 strcat(GraphicsBuffer
, buf3
);
782 expr
->Append(new wxExpr(PrologString
, GraphicsBuffer
));
786 void wxOpPolyDraw::ReadwxExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
788 noPoints
= (int)expr
->Nth(1)->IntegerValue();
793 points
= new wxRealPoint
[noPoints
];
796 wxString hexString
= expr
->Nth(2)->StringValue();
799 buf1
[0] = hexString
[bufPtr
];
800 buf1
[1] = hexString
[bufPtr
+ 1];
801 buf1
[2] = hexString
[bufPtr
+ 2];
802 buf1
[3] = hexString
[bufPtr
+ 3];
805 buf2
[0] = hexString
[bufPtr
+ 4];
806 buf2
[1] = hexString
[bufPtr
+ 5];
807 buf2
[2] = hexString
[bufPtr
+ 6];
808 buf2
[3] = hexString
[bufPtr
+ 7];
813 // int signedX = (signed int)HexToInt(buf1);
814 // int signedY = (signed int)HexToInt(buf2);
815 long unSignedX
= HexToInt(buf1
);
816 long unSignedY
= HexToInt(buf2
);
817 // Scale -32K -> +32K
818 long signedX
= unSignedX
- 32767;
819 long signedY
= unSignedY
- 32767;
821 int testX
= (signed int)unSignedX
;
822 int testY
= (signed int)unSignedY
;
825 points
[i
].x
= (float)(signedX
/ 100.0);
826 points
[i
].y
= (float)(signedY
/ 100.0);
838 static char hexArray
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
839 'C', 'D', 'E', 'F' };
841 // Convert unsigned 16-bit integer to 4-character hex string
842 static void IntToHex(unsigned int dec
, char *buf
)
844 int digit1
= (int)(dec
/4096);
845 int digit2
= (int)((dec
- (digit1
*4096))/256);
846 int digit3
= (int)((dec
- (digit1
*4096) - (digit2
*256))/16);
847 int digit4
= dec
- (digit1
*4096 + digit2
*256 + digit3
*16);
849 buf
[0] = hexArray
[digit1
];
850 buf
[1] = hexArray
[digit2
];
851 buf
[2] = hexArray
[digit3
];
852 buf
[3] = hexArray
[digit4
];
856 // One hex digit to decimal number
857 static int HexToInt1(char hex
)
899 // 4-digit hex string to unsigned integer
900 static unsigned long HexToInt(char *buf
)
902 long d1
= (long)(HexToInt1(buf
[0])*4096.0) ;
903 long d2
= (long)(HexToInt1(buf
[1])*256.0) ;
904 long d3
= (long)(HexToInt1(buf
[2])*16.0) ;
905 long d4
= (long)(HexToInt1(buf
[3])) ;
906 unsigned long n
= (long)(d1
+ d2
+ d3
+ d4
) ;
915 IMPLEMENT_DYNAMIC_CLASS(wxPseudoMetaFile
, wxObject
)
917 wxPseudoMetaFile::wxPseudoMetaFile()
919 m_currentRotation
= 0;
925 wxPseudoMetaFile::wxPseudoMetaFile(wxPseudoMetaFile
& mf
)
930 wxPseudoMetaFile::~wxPseudoMetaFile()
935 void wxPseudoMetaFile::Clear()
937 wxNode
*node
= m_ops
.First();
940 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
945 m_gdiObjects
.Clear();
948 void wxPseudoMetaFile::Draw(wxDC
& dc
, float xoffset
, float yoffset
)
950 wxNode
*node
= m_ops
.First();
953 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
954 op
->Do(dc
, xoffset
, yoffset
);
959 void wxPseudoMetaFile::Scale(float sx
, float sy
)
961 wxNode
*node
= m_ops
.First();
964 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
972 void wxPseudoMetaFile::Translate(float x
, float y
)
974 wxNode
*node
= m_ops
.First();
977 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
983 void wxPseudoMetaFile::Rotate(float x
, float y
, float theta
)
985 float theta1
= theta
-m_currentRotation
;
986 if (theta1
== 0.0) return;
987 float cosTheta
= (float)cos(theta1
);
988 float sinTheta
= (float)sin(theta1
);
990 wxNode
*node
= m_ops
.First();
993 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
994 op
->Rotate(x
, y
, sinTheta
, cosTheta
);
997 m_currentRotation
= theta
;
1001 void wxPseudoMetaFile::WritePrologAttributes(wxExpr
*clause
)
1003 // Write width and height
1004 clause
->AddAttributeValue("meta_width", m_width
);
1005 clause
->AddAttributeValue("meta_height", m_height
);
1006 clause
->AddAttributeValue("meta_rotateable", (long)m_rotateable
);
1008 // Write GDI objects
1011 wxNode
*node
= m_gdiObjects
.First();
1014 sprintf(buf
, "gdi%d", i
);
1015 wxObject
*obj
= (wxObject
*)node
->Data();
1016 wxExpr
*expr
= NULL
;
1019 if (obj
->IsKindOf(CLASSINFO(wxPen
)))
1021 wxPen
*thePen
= (wxPen
*)obj
;
1022 expr
= new wxExpr(PrologList
);
1023 expr
->Append(new wxExpr((long)gyTYPE_PEN
));
1024 expr
->Append(new wxExpr((long)thePen
->GetWidth()));
1025 expr
->Append(new wxExpr((long)thePen
->GetStyle()));
1026 expr
->Append(new wxExpr((long)thePen
->GetColour().Red()));
1027 expr
->Append(new wxExpr((long)thePen
->GetColour().Green()));
1028 expr
->Append(new wxExpr((long)thePen
->GetColour().Blue()));
1030 else if (obj
->IsKindOf(CLASSINFO(wxBrush
)))
1032 wxBrush
*theBrush
= (wxBrush
*)obj
;
1033 expr
= new wxExpr(PrologList
);
1034 expr
->Append(new wxExpr((long)gyTYPE_BRUSH
));
1035 expr
->Append(new wxExpr((long)theBrush
->GetStyle()));
1036 expr
->Append(new wxExpr((long)theBrush
->GetColour().Red()));
1037 expr
->Append(new wxExpr((long)theBrush
->GetColour().Green()));
1038 expr
->Append(new wxExpr((long)theBrush
->GetColour().Blue()));
1040 else if (obj
->IsKindOf(CLASSINFO(wxFont
)))
1042 wxFont
*theFont
= (wxFont
*)obj
;
1043 expr
= new wxExpr(PrologList
);
1044 expr
->Append(new wxExpr((long)gyTYPE_FONT
));
1045 expr
->Append(new wxExpr((long)theFont
->GetPointSize()));
1046 expr
->Append(new wxExpr((long)theFont
->GetFamily()));
1047 expr
->Append(new wxExpr((long)theFont
->GetStyle()));
1048 expr
->Append(new wxExpr((long)theFont
->GetWeight()));
1049 expr
->Append(new wxExpr((long)theFont
->GetUnderlined()));
1054 // If no recognised GDI object, append a place holder anyway.
1055 expr
= new wxExpr(PrologList
);
1056 expr
->Append(new wxExpr((long)0));
1061 clause
->AddAttributeValue(buf
, expr
);
1064 node
= node
->Next();
1067 // Write drawing operations
1069 node
= m_ops
.First();
1072 sprintf(buf
, "op%d", i
);
1073 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1074 wxExpr
*expr
= op
->WritewxExpr(this);
1077 clause
->AddAttributeValue(buf
, expr
);
1080 node
= node
->Next();
1083 // Write outline and fill GDI op lists (if any)
1084 if (m_outlineColours
.Number() > 0)
1086 wxExpr
*outlineExpr
= new wxExpr(PrologList
);
1087 node
= m_outlineColours
.First();
1090 outlineExpr
->Append(new wxExpr((long)node
->Data()));
1091 node
= node
->Next();
1093 clause
->AddAttributeValue("outline_objects", outlineExpr
);
1095 if (m_fillColours
.Number() > 0)
1097 wxExpr
*fillExpr
= new wxExpr(PrologList
);
1098 node
= m_fillColours
.First();
1101 fillExpr
->Append(new wxExpr((long)node
->Data()));
1102 node
= node
->Next();
1104 clause
->AddAttributeValue("fill_objects", fillExpr
);
1109 void wxPseudoMetaFile::ReadPrologAttributes(wxExpr
*clause
)
1111 clause
->AssignAttributeValue("meta_width", &m_width
);
1112 clause
->AssignAttributeValue("meta_height", &m_height
);
1114 int iVal
= (int) m_rotateable
;
1115 clause
->AssignAttributeValue("meta_rotateable", &iVal
);
1116 m_rotateable
= (iVal
!= 0);
1121 bool keepGoing
= TRUE
;
1124 sprintf(buf
, "gdi%d", i
);
1125 wxExpr
*expr
= NULL
;
1126 clause
->AssignAttributeValue(buf
, &expr
);
1133 wxExpr
*idExpr
= expr
->Nth(0);
1134 switch (idExpr
->IntegerValue())
1138 int penWidth
= (int)expr
->Nth(1)->IntegerValue();
1139 int penStyle
= (int)expr
->Nth(2)->IntegerValue();
1140 int penRed
= (int)expr
->Nth(3)->IntegerValue();
1141 int penGreen
= (int)expr
->Nth(4)->IntegerValue();
1142 int penBlue
= (int)expr
->Nth(5)->IntegerValue();
1143 wxColour
col(penRed
, penGreen
, penBlue
);
1144 wxPen
*p
= wxThePenList
->FindOrCreatePen(col
, penWidth
, penStyle
);
1147 m_gdiObjects
.Append(p
);
1152 int brushStyle
= (int)expr
->Nth(1)->IntegerValue();
1153 int brushRed
= (int)expr
->Nth(2)->IntegerValue();
1154 int brushGreen
= (int)expr
->Nth(3)->IntegerValue();
1155 int brushBlue
= (int)expr
->Nth(4)->IntegerValue();
1156 wxColour
col(brushRed
, brushGreen
, brushBlue
);
1157 wxBrush
*b
= wxTheBrushList
->FindOrCreateBrush(col
, brushStyle
);
1160 m_gdiObjects
.Append(b
);
1165 int fontPointSize
= (int)expr
->Nth(1)->IntegerValue();
1166 int fontFamily
= (int)expr
->Nth(2)->IntegerValue();
1167 int fontStyle
= (int)expr
->Nth(3)->IntegerValue();
1168 int fontWeight
= (int)expr
->Nth(4)->IntegerValue();
1169 int fontUnderlined
= (int)expr
->Nth(5)->IntegerValue();
1170 m_gdiObjects
.Append(wxTheFontList
->FindOrCreateFont(fontPointSize
,
1171 fontFamily
, fontStyle
, fontWeight
, (fontUnderlined
!= 0)));
1177 m_gdiObjects
.Append(NULL
);
1185 // Now read in the operations
1190 sprintf(buf
, "op%d", i
);
1191 wxExpr
*expr
= NULL
;
1192 clause
->AssignAttributeValue(buf
, &expr
);
1199 wxExpr
*idExpr
= expr
->Nth(0);
1200 int opId
= (int)idExpr
->IntegerValue();
1203 case DRAWOP_SET_PEN
:
1204 case DRAWOP_SET_BRUSH
:
1205 case DRAWOP_SET_FONT
:
1206 case DRAWOP_SET_TEXT_COLOUR
:
1207 case DRAWOP_SET_BK_COLOUR
:
1208 case DRAWOP_SET_BK_MODE
:
1210 wxOpSetGDI
*theOp
= new wxOpSetGDI(opId
, this, 0);
1211 theOp
->ReadwxExpr(this, expr
);
1212 m_ops
.Append(theOp
);
1216 case DRAWOP_SET_CLIPPING_RECT
:
1217 case DRAWOP_DESTROY_CLIPPING_RECT
:
1219 wxOpSetClipping
*theOp
= new wxOpSetClipping(opId
, 0.0, 0.0, 0.0, 0.0);
1220 theOp
->ReadwxExpr(this, expr
);
1221 m_ops
.Append(theOp
);
1225 case DRAWOP_DRAW_LINE
:
1226 case DRAWOP_DRAW_RECT
:
1227 case DRAWOP_DRAW_ROUNDED_RECT
:
1228 case DRAWOP_DRAW_ELLIPSE
:
1229 case DRAWOP_DRAW_POINT
:
1230 case DRAWOP_DRAW_ARC
:
1231 case DRAWOP_DRAW_TEXT
:
1233 wxOpDraw
*theOp
= new wxOpDraw(opId
, 0.0, 0.0, 0.0, 0.0);
1234 theOp
->ReadwxExpr(this, expr
);
1235 m_ops
.Append(theOp
);
1238 case DRAWOP_DRAW_SPLINE
:
1239 case DRAWOP_DRAW_POLYLINE
:
1240 case DRAWOP_DRAW_POLYGON
:
1242 wxOpPolyDraw
*theOp
= new wxOpPolyDraw(opId
, 0, NULL
);
1243 theOp
->ReadwxExpr(this, expr
);
1244 m_ops
.Append(theOp
);
1254 // Now read in the list of outline and fill operations, if any
1255 wxExpr
*expr1
= clause
->AttributeValue("outline_objects");
1258 wxExpr
*eachExpr
= expr1
->GetFirst();
1261 m_outlineColours
.Append((wxObject
*)eachExpr
->IntegerValue());
1262 eachExpr
= eachExpr
->GetNext();
1265 expr1
= clause
->AttributeValue("fill_objects");
1268 wxExpr
*eachExpr
= expr1
->GetFirst();
1271 m_fillColours
.Append((wxObject
*)eachExpr
->IntegerValue());
1272 eachExpr
= eachExpr
->GetNext();
1278 // Does the copying for this object
1279 void wxPseudoMetaFile::Copy(wxPseudoMetaFile
& copy
)
1281 copy
.m_currentRotation
= m_currentRotation
;
1282 copy
.m_width
= m_width
;
1283 copy
.m_height
= m_height
;
1284 copy
.m_rotateable
= m_rotateable
;
1286 // Copy the GDI objects
1287 wxNode
*node
= m_gdiObjects
.First();
1290 wxObject
*obj
= (wxObject
*)node
->Data();
1291 copy
.m_gdiObjects
.Append(obj
);
1292 node
= node
->Next();
1295 // Copy the operations
1296 node
= m_ops
.First();
1299 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1300 copy
.m_ops
.Append(op
->Copy(©
));
1301 node
= node
->Next();
1304 // Copy the outline/fill operations
1305 copy
.m_outlineColours
.Clear();
1306 node
= m_outlineColours
.First();
1309 copy
.m_outlineColours
.Append((wxObject
*)node
->Data());
1310 node
= node
->Next();
1312 copy
.m_fillColours
.Clear();
1313 node
= m_fillColours
.First();
1316 copy
.m_fillColours
.Append((wxObject
*)node
->Data());
1317 node
= node
->Next();
1322 * Pass size of existing image; scale height to
1323 * fit width and return new width and height.
1327 bool wxPseudoMetaFile::LoadFromMetaFile(char *filename
, float *rwidth
, float *rheight
)
1329 if (!FileExists(filename
))
1332 wxXMetaFile
*metaFile
= new wxXMetaFile
;
1334 if (!metaFile
->ReadFile(filename
))
1343 // Convert from metafile records to wxDrawnShape records
1344 wxNode
*node
= metaFile
->metaRecords
.First();
1347 wxMetaRecord
*record
= (wxMetaRecord
*)node
->Data();
1348 switch (record
->metaFunction
)
1350 case META_SETBKCOLOR
:
1352 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BK_COLOUR
, this, 0);
1353 op
->r
= (unsigned char)record
->param1
;
1354 op
->g
= (unsigned char)record
->param2
;
1355 op
->b
= (unsigned char)record
->param3
;
1359 case META_SETBKMODE
:
1361 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BK_MODE
, this, 0, (int)record
->param1
);
1365 case META_SETMAPMODE
:
1369 // case META_SETROP2:
1370 // case META_SETRELABS:
1371 // case META_SETPOLYFILLMODE:
1372 // case META_SETSTRETCHBLTMODE:
1373 // case META_SETTEXTCHAREXTRA:
1374 case META_SETTEXTCOLOR
:
1376 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR
, this, 0);
1377 op
->r
= (unsigned char)record
->param1
;
1378 op
->g
= (unsigned char)record
->param2
;
1379 op
->b
= (unsigned char)record
->param3
;
1383 // case META_SETTEXTJUSTIFICATION:
1384 // case META_SETWINDOWORG:
1385 // case META_SETWINDOWEXT:
1386 // case META_SETVIEWPORTORG:
1387 // case META_SETVIEWPORTEXT:
1388 // case META_OFFSETWINDOWORG:
1389 // case META_SCALEWINDOWEXT:
1390 // case META_OFFSETVIEWPORTORG:
1391 // case META_SCALEVIEWPORTEXT:
1394 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_LINE
, (float)lastX
, (float)lastY
,
1395 (float)record
->param1
, (float)record
->param2
);
1401 lastX
= (float)record
->param1
;
1402 lastY
= (float)record
->param2
;
1405 case META_EXCLUDECLIPRECT
:
1408 wxMetaRecord *rec = new wxMetaRecord(META_EXCLUDECLIPRECT);
1409 rec->param4 = getshort(handle); // y2
1410 rec->param3 = getshort(handle); // x2
1411 rec->param2 = getshort(handle); // y1
1412 rec->param1 = getshort(handle); // x1
1416 case META_INTERSECTCLIPRECT
:
1419 rec->param4 = getshort(handle); // y2
1420 rec->param3 = getshort(handle); // x2
1421 rec->param2 = getshort(handle); // y1
1422 rec->param1 = getshort(handle); // x1
1426 // case META_ARC: // DO!!!
1429 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_ELLIPSE
,
1430 (float)record
->param1
, (float)record
->param2
,
1431 (float)(record
->param3
- record
->param1
),
1432 (float)(record
->param4
- record
->param2
));
1436 // case META_FLOODFILL:
1437 // case META_PIE: // DO!!!
1438 case META_RECTANGLE
:
1440 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_RECT
,
1441 (float)record
->param1
, (float)record
->param2
,
1442 (float)(record
->param3
- record
->param1
),
1443 (float)(record
->param4
- record
->param2
));
1447 case META_ROUNDRECT
:
1449 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT
,
1450 (float)record
->param1
, (float)record
->param2
,
1451 (float)(record
->param3
- record
->param1
),
1452 (float)(record
->param4
- record
->param2
), (float)record
->param5
);
1456 // case META_PATBLT:
1457 // case META_SAVEDC:
1460 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_POINT
,
1461 (float)record
->param1
, (float)record
->param2
,
1464 // SHOULD SET THE COLOUR - SET PEN?
1465 // rec->param3 = getint(handle); // COLORREF
1469 // case META_OFFSETCLIPRGN:
1472 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_TEXT
,
1473 (float)record
->param1
, (float)record
->param2
,
1474 0.0, 0.0, 0.0, record
->stringParam
);
1478 // case META_BITBLT:
1479 // case META_STRETCHBLT:
1482 int n
= (int)record
->param1
;
1483 wxRealPoint
*newPoints
= new wxRealPoint
[n
];
1484 for (int i
= 0; i
< n
; i
++)
1486 newPoints
[i
].x
= record
->points
[i
].x
;
1487 newPoints
[i
].y
= record
->points
[i
].y
;
1490 wxOpPolyDraw
*op
= new wxOpPolyDraw(DRAWOP_DRAW_POLYGON
, n
, newPoints
);
1496 int n
= (int)record
->param1
;
1497 wxRealPoint
*newPoints
= new wxRealPoint
[n
];
1498 for (int i
= 0; i
< n
; i
++)
1500 newPoints
[i
].x
= record
->points
[i
].x
;
1501 newPoints
[i
].y
= record
->points
[i
].y
;
1504 wxOpPolyDraw
*op
= new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE
, n
, newPoints
);
1508 // case META_ESCAPE:
1509 // case META_RESTOREDC:
1510 // case META_FILLREGION:
1511 // case META_FRAMEREGION:
1512 // case META_INVERTREGION:
1513 // case META_PAINTREGION:
1514 // case META_SELECTCLIPREGION: // DO THIS!
1515 case META_SELECTOBJECT
:
1517 // The pen, brush etc. has already been created when the metafile
1518 // was read in, so we don't create it - we set it.
1519 wxNode
*recNode
= metaFile
->gdiObjects
.Nth((int)record
->param2
);
1522 wxMetaRecord
*gdiRec
= (wxMetaRecord
*)recNode
->Data();
1523 if (gdiRec
&& (gdiRec
->param1
!= 0))
1525 wxObject
*obj
= (wxObject
*)gdiRec
->param1
;
1526 if (obj
->IsKindOf(CLASSINFO(wxPen
)))
1528 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_PEN
, this, (int)record
->param2
);
1531 else if (obj
->IsKindOf(CLASSINFO(wxBrush
)))
1533 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BRUSH
, this, (int)record
->param2
);
1536 else if (obj
->IsKindOf(CLASSINFO(wxFont
)))
1538 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_FONT
, this, (int)record
->param2
);
1545 // case META_SETTEXTALIGN:
1546 // case META_DRAWTEXT:
1548 // case META_SETMAPPERFLAGS:
1549 // case META_EXTTEXTOUT:
1550 // case META_SETDIBTODEV:
1551 // case META_SELECTPALETTE:
1552 // case META_REALIZEPALETTE:
1553 // case META_ANIMATEPALETTE:
1554 // case META_SETPALENTRIES:
1555 // case META_POLYPOLYGON:
1556 // case META_RESIZEPALETTE:
1557 // case META_DIBBITBLT:
1558 // case META_DIBSTRETCHBLT:
1559 case META_DIBCREATEPATTERNBRUSH
:
1562 m_gdiObjects
.Append(NULL
);
1565 // case META_STRETCHDIB:
1566 // case META_EXTFLOODFILL:
1567 // case META_RESETDC:
1568 // case META_STARTDOC:
1569 // case META_STARTPAGE:
1570 // case META_ENDPAGE:
1571 // case META_ABORTDOC:
1572 // case META_ENDDOC:
1573 // case META_DELETEOBJECT: // DO!!
1574 case META_CREATEPALETTE
:
1577 m_gdiObjects
.Append(NULL
);
1580 case META_CREATEBRUSH
:
1583 m_gdiObjects
.Append(NULL
);
1586 case META_CREATEPATTERNBRUSH
:
1589 m_gdiObjects
.Append(NULL
);
1592 case META_CREATEPENINDIRECT
:
1594 // The pen is created when the metafile is read in.
1595 // We keep track of all the GDI objects needed for this
1596 // image so when reading the wxDrawnShape from file,
1597 // we can read in all the GDI objects, then refer
1598 // to them by an index starting from zero thereafter.
1599 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1602 case META_CREATEFONTINDIRECT
:
1604 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1607 case META_CREATEBRUSHINDIRECT
:
1609 // Don't have to do anything here: the pen is created
1610 // when the metafile is read in.
1611 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1614 case META_CREATEBITMAPINDIRECT
:
1617 m_gdiObjects
.Append(NULL
);
1620 case META_CREATEBITMAP
:
1623 m_gdiObjects
.Append(NULL
);
1626 case META_CREATEREGION
:
1629 m_gdiObjects
.Append(NULL
);
1637 node
= node
->Next();
1639 float actualWidth
= (float)fabs(metaFile
->right
- metaFile
->left
);
1640 float actualHeight
= (float)fabs(metaFile
->bottom
- metaFile
->top
);
1642 float initialScaleX
= 1.0;
1643 float initialScaleY
= 1.0;
1645 float xoffset
, yoffset
;
1647 // Translate so origin is at centre of rectangle
1648 if (metaFile
->bottom
> metaFile
->top
)
1649 yoffset
= - (float)((metaFile
->bottom
- metaFile
->top
)/2.0);
1651 yoffset
= - (float)((metaFile
->top
- metaFile
->bottom
)/2.0);
1653 if (metaFile
->right
> metaFile
->left
)
1654 xoffset
= - (float)((metaFile
->right
- metaFile
->left
)/2.0);
1656 xoffset
= - (float)((metaFile
->left
- metaFile
->right
)/2.0);
1658 Translate(xoffset
, yoffset
);
1660 // Scale to a reasonable size (take the width of this wxDrawnShape
1662 if (actualWidth
!= 0.0)
1664 initialScaleX
= (float)((*rwidth
) / actualWidth
);
1665 initialScaleY
= initialScaleX
;
1666 (*rheight
) = initialScaleY
*actualHeight
;
1668 Scale(initialScaleX
, initialScaleY
);
1670 m_width
= (actualWidth
*initialScaleX
);
1671 m_height
= *rheight
;
1677 // Scale to fit size
1678 void wxPseudoMetaFile::ScaleTo(float w
, float h
)
1680 float scaleX
= (float)(w
/m_width
);
1681 float scaleY
= (float)(h
/m_height
);
1684 Scale(scaleX
, scaleY
);
1687 void wxPseudoMetaFile::GetBounds(float *boundMinX
, float *boundMinY
, float *boundMaxX
, float *boundMaxY
)
1689 float maxX
= (float) -99999.9;
1690 float maxY
= (float) -99999.9;
1691 float minX
= (float) 99999.9;
1692 float minY
= (float) 99999.9;
1694 wxNode
*node
= m_ops
.First();
1697 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1700 case DRAWOP_DRAW_LINE
:
1701 case DRAWOP_DRAW_RECT
:
1702 case DRAWOP_DRAW_ROUNDED_RECT
:
1703 case DRAWOP_DRAW_ELLIPSE
:
1704 case DRAWOP_DRAW_POINT
:
1705 case DRAWOP_DRAW_ARC
:
1706 case DRAWOP_DRAW_TEXT
:
1708 wxOpDraw
*opDraw
= (wxOpDraw
*)op
;
1709 if (opDraw
->x1
< minX
) minX
= opDraw
->x1
;
1710 if (opDraw
->x1
> maxX
) maxX
= opDraw
->x1
;
1711 if (opDraw
->y1
< minY
) minY
= opDraw
->y1
;
1712 if (opDraw
->y1
> maxY
) maxY
= opDraw
->y1
;
1713 if (op
->op
== DRAWOP_DRAW_LINE
)
1715 if (opDraw
->x2
< minX
) minX
= opDraw
->x2
;
1716 if (opDraw
->x2
> maxX
) maxX
= opDraw
->x2
;
1717 if (opDraw
->y2
< minY
) minY
= opDraw
->y2
;
1718 if (opDraw
->y2
> maxY
) maxY
= opDraw
->y2
;
1720 else if (op
->op
== DRAWOP_DRAW_RECT
||
1721 op
->op
== DRAWOP_DRAW_ROUNDED_RECT
||
1722 op
->op
== DRAWOP_DRAW_ELLIPSE
)
1724 if ((opDraw
->x1
+ opDraw
->x2
) < minX
) minX
= (opDraw
->x1
+ opDraw
->x2
);
1725 if ((opDraw
->x1
+ opDraw
->x2
) > maxX
) maxX
= (opDraw
->x1
+ opDraw
->x2
);
1726 if ((opDraw
->y1
+ opDraw
->y2
) < minY
) minY
= (opDraw
->y1
+ opDraw
->y2
);
1727 if ((opDraw
->y1
+ opDraw
->y2
) > maxY
) maxY
= (opDraw
->y1
+ opDraw
->y2
);
1731 case DRAWOP_DRAW_POLYLINE
:
1732 case DRAWOP_DRAW_POLYGON
:
1733 case DRAWOP_DRAW_SPLINE
:
1735 wxOpPolyDraw
*poly
= (wxOpPolyDraw
*)op
;
1736 for (int i
= 0; i
< poly
->noPoints
; i
++)
1738 if (poly
->points
[i
].x
< minX
) minX
= poly
->points
[i
].x
;
1739 if (poly
->points
[i
].x
> maxX
) maxX
= poly
->points
[i
].x
;
1740 if (poly
->points
[i
].y
< minY
) minY
= poly
->points
[i
].y
;
1741 if (poly
->points
[i
].y
> maxY
) maxY
= poly
->points
[i
].y
;
1748 node
= node
->Next();
1756 *w = (float)fabs(maxX - minX);
1757 *h = (float)fabs(maxY - minY);