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(wxDrawnShape
& copy
)
167 wxRectangleShape::Copy(copy
);
168 m_metafile
.Copy(copy
.m_metafile
);
169 copy
.m_saveToFile
= m_saveToFile
;
172 // Returns a new instance, and does the copy for this class. Define for each class.
173 wxShape
*wxDrawnShape::PrivateCopy()
175 wxDrawnShape
*obj
= new wxDrawnShape
;
180 bool wxDrawnShape::LoadFromMetaFile(char *filename
)
182 return m_metafile
.LoadFromMetaFile(filename
, &m_width
, &m_height
);
186 * Individual operations
191 * Set font, brush, text colour
195 wxOpSetGDI::wxOpSetGDI(int theOp
, wxPseudoMetaFile
*theImage
, int theGdiIndex
, int theMode
):
198 gdiIndex
= theGdiIndex
;
203 void wxOpSetGDI::Do(wxDC
& dc
, float xoffset
, float yoffset
)
209 // Check for overriding this operation for outline
211 if (image
->m_outlineColours
.Member((wxObject
*)gdiIndex
))
213 if (image
->m_outlinePen
)
214 dc
.SetPen(image
->m_outlinePen
);
218 wxNode
*node
= image
->m_gdiObjects
.Nth(gdiIndex
);
221 wxPen
*pen
= (wxPen
*)node
->Data();
228 case DRAWOP_SET_BRUSH
:
230 // Check for overriding this operation for outline or fill
232 if (image
->m_outlineColours
.Member((wxObject
*)gdiIndex
))
234 // Need to construct a brush to match the outline pen's colour
235 if (image
->m_outlinePen
)
237 wxBrush
*br
= wxTheBrushList
->FindOrCreateBrush(image
->m_outlinePen
->GetColour(), wxSOLID
);
242 else if (image
->m_fillColours
.Member((wxObject
*)gdiIndex
))
244 if (image
->m_fillBrush
)
246 dc
.SetBrush(image
->m_fillBrush
);
251 wxNode
*node
= image
->m_gdiObjects
.Nth(gdiIndex
);
254 wxBrush
*brush
= (wxBrush
*)node
->Data();
261 case DRAWOP_SET_FONT
:
263 wxNode
*node
= image
->m_gdiObjects
.Nth(gdiIndex
);
266 wxFont
*font
= (wxFont
*)node
->Data();
272 case DRAWOP_SET_TEXT_COLOUR
:
275 dc
.SetTextForeground(col
);
278 case DRAWOP_SET_BK_COLOUR
:
281 dc
.SetTextBackground(col
);
284 case DRAWOP_SET_BK_MODE
:
286 dc
.SetBackgroundMode(mode
);
294 wxDrawOp
*wxOpSetGDI::Copy(wxPseudoMetaFile
*newImage
)
296 wxOpSetGDI
*newOp
= new wxOpSetGDI(op
, newImage
, gdiIndex
, mode
);
303 wxExpr
*wxOpSetGDI::WritewxExpr(wxPseudoMetaFile
*image
)
305 wxExpr
*expr
= new wxExpr(PrologList
);
306 expr
->Append(new wxExpr((long)op
));
310 case DRAWOP_SET_BRUSH
:
311 case DRAWOP_SET_FONT
:
313 expr
->Append(new wxExpr((long)gdiIndex
));
316 case DRAWOP_SET_TEXT_COLOUR
:
317 case DRAWOP_SET_BK_COLOUR
:
319 expr
->Append(new wxExpr((long)r
));
320 expr
->Append(new wxExpr((long)g
));
321 expr
->Append(new wxExpr((long)b
));
324 case DRAWOP_SET_BK_MODE
:
326 expr
->Append(new wxExpr((long)mode
));
335 void wxOpSetGDI::ReadwxExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
340 case DRAWOP_SET_BRUSH
:
341 case DRAWOP_SET_FONT
:
343 gdiIndex
= (int)expr
->Nth(1)->IntegerValue();
346 case DRAWOP_SET_TEXT_COLOUR
:
347 case DRAWOP_SET_BK_COLOUR
:
349 r
= (unsigned char)expr
->Nth(1)->IntegerValue();
350 g
= (unsigned char)expr
->Nth(2)->IntegerValue();
351 b
= (unsigned char)expr
->Nth(3)->IntegerValue();
354 case DRAWOP_SET_BK_MODE
:
356 mode
= (int)expr
->Nth(1)->IntegerValue();
365 * Set/destroy clipping
369 wxOpSetClipping::wxOpSetClipping(int theOp
, float theX1
, float theY1
,
370 float theX2
, float theY2
):wxDrawOp(theOp
)
378 wxDrawOp
*wxOpSetClipping::Copy(wxPseudoMetaFile
*newImage
)
380 wxOpSetClipping
*newOp
= new wxOpSetClipping(op
, x1
, y1
, x2
, y2
);
384 void wxOpSetClipping::Do(wxDC
& dc
, float xoffset
, float yoffset
)
388 case DRAWOP_SET_CLIPPING_RECT
:
390 dc
.SetClippingRegion(x1
+ xoffset
, y1
+ yoffset
, x2
+ xoffset
, y2
+ yoffset
);
393 case DRAWOP_DESTROY_CLIPPING_RECT
:
395 dc
.DestroyClippingRegion();
403 void wxOpSetClipping::Scale(float xScale
, float yScale
)
411 void wxOpSetClipping::Translate(float x
, float y
)
417 wxExpr
*wxOpSetClipping::WritewxExpr(wxPseudoMetaFile
*image
)
419 wxExpr
*expr
= new wxExpr(PrologList
);
420 expr
->Append(new wxExpr((long)op
));
423 case DRAWOP_SET_CLIPPING_RECT
:
425 expr
->Append(new wxExpr(x1
));
426 expr
->Append(new wxExpr(y1
));
427 expr
->Append(new wxExpr(x2
));
428 expr
->Append(new wxExpr(y2
));
437 void wxOpSetClipping::ReadwxExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
441 case DRAWOP_SET_CLIPPING_RECT
:
443 x1
= expr
->Nth(1)->RealValue();
444 y1
= expr
->Nth(2)->RealValue();
445 x2
= expr
->Nth(3)->RealValue();
446 y2
= expr
->Nth(4)->RealValue();
455 * Draw line, rectangle, rounded rectangle, ellipse, point, arc, text
459 wxOpDraw::wxOpDraw(int theOp
, float theX1
, float theY1
, float theX2
, float theY2
,
460 float theRadius
, char *s
):wxDrawOp(theOp
)
467 if (s
) textString
= copystring(s
);
468 else textString
= NULL
;
471 wxOpDraw::~wxOpDraw()
473 if (textString
) delete[] textString
;
476 wxDrawOp
*wxOpDraw::Copy(wxPseudoMetaFile
*newImage
)
478 wxOpDraw
*newOp
= new wxOpDraw(op
, x1
, y1
, x2
, y2
, radius
, textString
);
482 void wxOpDraw::Do(wxDC
& dc
, float xoffset
, float yoffset
)
486 case DRAWOP_DRAW_LINE
:
488 dc
.DrawLine(x1
+xoffset
, y1
+yoffset
, x2
+xoffset
, y2
+yoffset
);
491 case DRAWOP_DRAW_RECT
:
493 dc
.DrawRectangle(x1
+xoffset
, y1
+yoffset
, x2
+xoffset
, y2
+yoffset
);
496 case DRAWOP_DRAW_ROUNDED_RECT
:
498 dc
.DrawRoundedRectangle(x1
+xoffset
, y1
+yoffset
, x2
+xoffset
, y2
+yoffset
, radius
);
501 case DRAWOP_DRAW_ELLIPSE
:
503 dc
.DrawEllipse(x1
+xoffset
, y1
+yoffset
, x2
+xoffset
, y2
+yoffset
);
506 case DRAWOP_DRAW_POINT
:
508 dc
.DrawPoint(x1
+xoffset
, y1
+yoffset
);
511 case DRAWOP_DRAW_TEXT
:
513 dc
.DrawText(textString
, x1
+xoffset
, y1
+yoffset
);
521 void wxOpDraw::Scale(float scaleX
, float scaleY
)
530 void wxOpDraw::Translate(float x
, float y
)
536 void wxOpDraw::Rotate(float x
, float y
, float sinTheta
, float cosTheta
)
538 x1
= x1
*cosTheta
- y1
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
539 y1
= x1
*sinTheta
+ y1
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
543 case DRAWOP_DRAW_LINE
:
545 x2
= x2
*cosTheta
- y2
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
546 y2
= x2
*sinTheta
+ y2
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
554 wxExpr
*wxOpDraw::WritewxExpr(wxPseudoMetaFile
*image
)
556 wxExpr
*expr
= new wxExpr(PrologList
);
557 expr
->Append(new wxExpr((long)op
));
560 case DRAWOP_DRAW_LINE
:
561 case DRAWOP_DRAW_RECT
:
562 case DRAWOP_DRAW_ELLIPSE
:
564 expr
->Append(new wxExpr(x1
));
565 expr
->Append(new wxExpr(y1
));
566 expr
->Append(new wxExpr(x2
));
567 expr
->Append(new wxExpr(y2
));
570 case DRAWOP_DRAW_ROUNDED_RECT
:
572 expr
->Append(new wxExpr(x1
));
573 expr
->Append(new wxExpr(y1
));
574 expr
->Append(new wxExpr(x2
));
575 expr
->Append(new wxExpr(y2
));
576 expr
->Append(new wxExpr(radius
));
579 case DRAWOP_DRAW_POINT
:
581 expr
->Append(new wxExpr(x1
));
582 expr
->Append(new wxExpr(y1
));
585 case DRAWOP_DRAW_TEXT
:
587 expr
->Append(new wxExpr(x1
));
588 expr
->Append(new wxExpr(y1
));
589 expr
->Append(new wxExpr(PrologString
, textString
));
592 case DRAWOP_DRAW_ARC
:
601 void wxOpDraw::ReadwxExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
605 case DRAWOP_DRAW_LINE
:
606 case DRAWOP_DRAW_RECT
:
607 case DRAWOP_DRAW_ELLIPSE
:
609 x1
= expr
->Nth(1)->RealValue();
610 y1
= expr
->Nth(2)->RealValue();
611 x2
= expr
->Nth(3)->RealValue();
612 y2
= expr
->Nth(4)->RealValue();
615 case DRAWOP_DRAW_ROUNDED_RECT
:
617 x1
= expr
->Nth(1)->RealValue();
618 y1
= expr
->Nth(2)->RealValue();
619 x2
= expr
->Nth(3)->RealValue();
620 y2
= expr
->Nth(4)->RealValue();
621 radius
= expr
->Nth(5)->RealValue();
624 case DRAWOP_DRAW_POINT
:
626 x1
= expr
->Nth(1)->RealValue();
627 y1
= expr
->Nth(2)->RealValue();
630 case DRAWOP_DRAW_TEXT
:
632 x1
= expr
->Nth(1)->RealValue();
633 y1
= expr
->Nth(2)->RealValue();
634 textString
= copystring(expr
->Nth(3)->StringValue());
637 case DRAWOP_DRAW_ARC
:
646 * Draw polygon, polyline, spline
650 wxOpPolyDraw::wxOpPolyDraw(int theOp
, int n
, wxRealPoint
*thePoints
):wxDrawOp(theOp
)
656 wxOpPolyDraw::~wxOpPolyDraw()
661 wxDrawOp
*wxOpPolyDraw::Copy(wxPseudoMetaFile
*newImage
)
663 wxRealPoint
*newPoints
= new wxRealPoint
[noPoints
];
664 for (int i
= 0; i
< noPoints
; i
++)
666 newPoints
[i
].x
= points
[i
].x
;
667 newPoints
[i
].y
= points
[i
].y
;
669 wxOpPolyDraw
*newOp
= new wxOpPolyDraw(op
, noPoints
, newPoints
);
673 void wxOpPolyDraw::Do(wxDC
& dc
, float xoffset
, float yoffset
)
677 case DRAWOP_DRAW_POLYLINE
:
679 wxPoint
*actualPoints
= new wxPoint
[noPoints
];
681 for (i
= 0; i
< noPoints
; i
++)
683 actualPoints
[i
].x
= (long) points
[i
].x
;
684 actualPoints
[i
].y
= (long) points
[i
].y
;
687 dc
.DrawLines(noPoints
, actualPoints
, xoffset
, yoffset
);
689 delete[] actualPoints
;
692 case DRAWOP_DRAW_POLYGON
:
694 wxPoint
*actualPoints
= new wxPoint
[noPoints
];
696 for (i
= 0; i
< noPoints
; i
++)
698 actualPoints
[i
].x
= (long) points
[i
].x
;
699 actualPoints
[i
].y
= (long) points
[i
].y
;
702 dc
.DrawPolygon(noPoints
, actualPoints
, xoffset
, yoffset
);
704 delete[] actualPoints
;
707 case DRAWOP_DRAW_SPLINE
:
709 // dc.DrawSpline(noPoints, points, xoffset, yoffset);
717 void wxOpPolyDraw::Scale(float scaleX
, float scaleY
)
719 for (int i
= 0; i
< noPoints
; i
++)
721 points
[i
].x
*= scaleX
;
722 points
[i
].y
*= scaleY
;
726 void wxOpPolyDraw::Translate(float x
, float y
)
728 for (int i
= 0; i
< noPoints
; i
++)
735 void wxOpPolyDraw::Rotate(float x
, float y
, float sinTheta
, float cosTheta
)
737 for (int i
= 0; i
< noPoints
; i
++)
739 float x1
= points
[i
].x
;
740 float y1
= points
[i
].y
;
741 points
[i
].x
= x1
*cosTheta
- y1
*sinTheta
+ x
*(1 - cosTheta
) + y
*sinTheta
;
742 points
[i
].y
= x1
*sinTheta
+ y1
*cosTheta
+ y
*(1 - cosTheta
) + x
*sinTheta
;
746 wxExpr
*wxOpPolyDraw::WritewxExpr(wxPseudoMetaFile
*image
)
748 wxExpr
*expr
= new wxExpr(PrologList
);
749 expr
->Append(new wxExpr((long)op
));
750 expr
->Append(new wxExpr((long)noPoints
));
756 GraphicsBuffer
[0] = 0;
759 * Store each coordinate pair in a hex string to save space.
760 * E.g. "1B9080CD". 4 hex digits per coordinate pair.
764 for (int i
= 0; i
< noPoints
; i
++)
766 long signedX
= (long)(points
[i
].x
*100.0);
767 long signedY
= (long)(points
[i
].y
*100.0);
770 long unSignedX
= (long)(signedX
+ 32767.0);
771 long unSignedY
= (long)(signedY
+ 32767.0);
773 // IntToHex((unsigned int)signedX, buf2);
774 // IntToHex((unsigned int)signedY, buf3);
775 IntToHex((int)unSignedX
, buf2
);
776 IntToHex((int)unSignedY
, buf3
);
778 // Don't overrun the buffer
781 strcat(GraphicsBuffer
, buf2
);
782 strcat(GraphicsBuffer
, buf3
);
785 expr
->Append(new wxExpr(PrologString
, GraphicsBuffer
));
789 void wxOpPolyDraw::ReadwxExpr(wxPseudoMetaFile
*image
, wxExpr
*expr
)
791 noPoints
= (int)expr
->Nth(1)->IntegerValue();
796 points
= new wxRealPoint
[noPoints
];
799 wxString hexString
= expr
->Nth(2)->StringValue();
802 buf1
[0] = hexString
[bufPtr
];
803 buf1
[1] = hexString
[bufPtr
+ 1];
804 buf1
[2] = hexString
[bufPtr
+ 2];
805 buf1
[3] = hexString
[bufPtr
+ 3];
808 buf2
[0] = hexString
[bufPtr
+ 4];
809 buf2
[1] = hexString
[bufPtr
+ 5];
810 buf2
[2] = hexString
[bufPtr
+ 6];
811 buf2
[3] = hexString
[bufPtr
+ 7];
816 // int signedX = (signed int)HexToInt(buf1);
817 // int signedY = (signed int)HexToInt(buf2);
818 long unSignedX
= HexToInt(buf1
);
819 long unSignedY
= HexToInt(buf2
);
820 // Scale -32K -> +32K
821 long signedX
= unSignedX
- 32767;
822 long signedY
= unSignedY
- 32767;
824 int testX
= (signed int)unSignedX
;
825 int testY
= (signed int)unSignedY
;
828 points
[i
].x
= (float)(signedX
/ 100.0);
829 points
[i
].y
= (float)(signedY
/ 100.0);
841 static char hexArray
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
842 'C', 'D', 'E', 'F' };
844 // Convert unsigned 16-bit integer to 4-character hex string
845 static void IntToHex(unsigned int dec
, char *buf
)
847 int digit1
= (int)(dec
/4096);
848 int digit2
= (int)((dec
- (digit1
*4096))/256);
849 int digit3
= (int)((dec
- (digit1
*4096) - (digit2
*256))/16);
850 int digit4
= dec
- (digit1
*4096 + digit2
*256 + digit3
*16);
852 buf
[0] = hexArray
[digit1
];
853 buf
[1] = hexArray
[digit2
];
854 buf
[2] = hexArray
[digit3
];
855 buf
[3] = hexArray
[digit4
];
859 // One hex digit to decimal number
860 static int HexToInt1(char hex
)
902 // 4-digit hex string to unsigned integer
903 static unsigned long HexToInt(char *buf
)
905 long d1
= (long)(HexToInt1(buf
[0])*4096.0) ;
906 long d2
= (long)(HexToInt1(buf
[1])*256.0) ;
907 long d3
= (long)(HexToInt1(buf
[2])*16.0) ;
908 long d4
= (long)(HexToInt1(buf
[3])) ;
909 unsigned long n
= (long)(d1
+ d2
+ d3
+ d4
) ;
918 IMPLEMENT_DYNAMIC_CLASS(wxPseudoMetaFile
, wxObject
)
920 wxPseudoMetaFile::wxPseudoMetaFile()
922 m_currentRotation
= 0;
928 wxPseudoMetaFile::wxPseudoMetaFile(wxPseudoMetaFile
& mf
)
933 wxPseudoMetaFile::~wxPseudoMetaFile()
938 void wxPseudoMetaFile::Clear()
940 wxNode
*node
= m_ops
.First();
943 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
948 m_gdiObjects
.Clear();
951 void wxPseudoMetaFile::Draw(wxDC
& dc
, float xoffset
, float yoffset
)
953 wxNode
*node
= m_ops
.First();
956 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
957 op
->Do(dc
, xoffset
, yoffset
);
962 void wxPseudoMetaFile::Scale(float sx
, float sy
)
964 wxNode
*node
= m_ops
.First();
967 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
975 void wxPseudoMetaFile::Translate(float x
, float y
)
977 wxNode
*node
= m_ops
.First();
980 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
986 void wxPseudoMetaFile::Rotate(float x
, float y
, float theta
)
988 float theta1
= theta
-m_currentRotation
;
989 if (theta1
== 0.0) return;
990 float cosTheta
= (float)cos(theta1
);
991 float sinTheta
= (float)sin(theta1
);
993 wxNode
*node
= m_ops
.First();
996 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
997 op
->Rotate(x
, y
, sinTheta
, cosTheta
);
1000 m_currentRotation
= theta
;
1004 void wxPseudoMetaFile::WritePrologAttributes(wxExpr
*clause
)
1006 // Write width and height
1007 clause
->AddAttributeValue("meta_width", m_width
);
1008 clause
->AddAttributeValue("meta_height", m_height
);
1009 clause
->AddAttributeValue("meta_rotateable", (long)m_rotateable
);
1011 // Write GDI objects
1014 wxNode
*node
= m_gdiObjects
.First();
1017 sprintf(buf
, "gdi%d", i
);
1018 wxObject
*obj
= (wxObject
*)node
->Data();
1019 wxExpr
*expr
= NULL
;
1022 if (obj
->IsKindOf(CLASSINFO(wxPen
)))
1024 wxPen
*thePen
= (wxPen
*)obj
;
1025 expr
= new wxExpr(PrologList
);
1026 expr
->Append(new wxExpr((long)gyTYPE_PEN
));
1027 expr
->Append(new wxExpr((long)thePen
->GetWidth()));
1028 expr
->Append(new wxExpr((long)thePen
->GetStyle()));
1029 expr
->Append(new wxExpr((long)thePen
->GetColour().Red()));
1030 expr
->Append(new wxExpr((long)thePen
->GetColour().Green()));
1031 expr
->Append(new wxExpr((long)thePen
->GetColour().Blue()));
1033 else if (obj
->IsKindOf(CLASSINFO(wxBrush
)))
1035 wxBrush
*theBrush
= (wxBrush
*)obj
;
1036 expr
= new wxExpr(PrologList
);
1037 expr
->Append(new wxExpr((long)gyTYPE_BRUSH
));
1038 expr
->Append(new wxExpr((long)theBrush
->GetStyle()));
1039 expr
->Append(new wxExpr((long)theBrush
->GetColour().Red()));
1040 expr
->Append(new wxExpr((long)theBrush
->GetColour().Green()));
1041 expr
->Append(new wxExpr((long)theBrush
->GetColour().Blue()));
1043 else if (obj
->IsKindOf(CLASSINFO(wxFont
)))
1045 wxFont
*theFont
= (wxFont
*)obj
;
1046 expr
= new wxExpr(PrologList
);
1047 expr
->Append(new wxExpr((long)gyTYPE_FONT
));
1048 expr
->Append(new wxExpr((long)theFont
->GetPointSize()));
1049 expr
->Append(new wxExpr((long)theFont
->GetFamily()));
1050 expr
->Append(new wxExpr((long)theFont
->GetStyle()));
1051 expr
->Append(new wxExpr((long)theFont
->GetWeight()));
1052 expr
->Append(new wxExpr((long)theFont
->GetUnderlined()));
1057 // If no recognised GDI object, append a place holder anyway.
1058 expr
= new wxExpr(PrologList
);
1059 expr
->Append(new wxExpr((long)0));
1064 clause
->AddAttributeValue(buf
, expr
);
1067 node
= node
->Next();
1070 // Write drawing operations
1072 node
= m_ops
.First();
1075 sprintf(buf
, "op%d", i
);
1076 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1077 wxExpr
*expr
= op
->WritewxExpr(this);
1080 clause
->AddAttributeValue(buf
, expr
);
1083 node
= node
->Next();
1086 // Write outline and fill GDI op lists (if any)
1087 if (m_outlineColours
.Number() > 0)
1089 wxExpr
*outlineExpr
= new wxExpr(PrologList
);
1090 node
= m_outlineColours
.First();
1093 outlineExpr
->Append(new wxExpr((long)node
->Data()));
1094 node
= node
->Next();
1096 clause
->AddAttributeValue("outline_objects", outlineExpr
);
1098 if (m_fillColours
.Number() > 0)
1100 wxExpr
*fillExpr
= new wxExpr(PrologList
);
1101 node
= m_fillColours
.First();
1104 fillExpr
->Append(new wxExpr((long)node
->Data()));
1105 node
= node
->Next();
1107 clause
->AddAttributeValue("fill_objects", fillExpr
);
1112 void wxPseudoMetaFile::ReadPrologAttributes(wxExpr
*clause
)
1114 clause
->AssignAttributeValue("meta_width", &m_width
);
1115 clause
->AssignAttributeValue("meta_height", &m_height
);
1117 int iVal
= (int) m_rotateable
;
1118 clause
->AssignAttributeValue("meta_rotateable", &iVal
);
1119 m_rotateable
= (iVal
!= 0);
1124 bool keepGoing
= TRUE
;
1127 sprintf(buf
, "gdi%d", i
);
1128 wxExpr
*expr
= NULL
;
1129 clause
->AssignAttributeValue(buf
, &expr
);
1136 wxExpr
*idExpr
= expr
->Nth(0);
1137 switch (idExpr
->IntegerValue())
1141 int penWidth
= (int)expr
->Nth(1)->IntegerValue();
1142 int penStyle
= (int)expr
->Nth(2)->IntegerValue();
1143 int penRed
= (int)expr
->Nth(3)->IntegerValue();
1144 int penGreen
= (int)expr
->Nth(4)->IntegerValue();
1145 int penBlue
= (int)expr
->Nth(5)->IntegerValue();
1146 wxColour
col(penRed
, penGreen
, penBlue
);
1147 wxPen
*p
= wxThePenList
->FindOrCreatePen(col
, penWidth
, penStyle
);
1150 m_gdiObjects
.Append(p
);
1155 int brushStyle
= (int)expr
->Nth(1)->IntegerValue();
1156 int brushRed
= (int)expr
->Nth(2)->IntegerValue();
1157 int brushGreen
= (int)expr
->Nth(3)->IntegerValue();
1158 int brushBlue
= (int)expr
->Nth(4)->IntegerValue();
1159 wxColour
col(brushRed
, brushGreen
, brushBlue
);
1160 wxBrush
*b
= wxTheBrushList
->FindOrCreateBrush(col
, brushStyle
);
1163 m_gdiObjects
.Append(b
);
1168 int fontPointSize
= (int)expr
->Nth(1)->IntegerValue();
1169 int fontFamily
= (int)expr
->Nth(2)->IntegerValue();
1170 int fontStyle
= (int)expr
->Nth(3)->IntegerValue();
1171 int fontWeight
= (int)expr
->Nth(4)->IntegerValue();
1172 int fontUnderlined
= (int)expr
->Nth(5)->IntegerValue();
1173 m_gdiObjects
.Append(wxTheFontList
->FindOrCreateFont(fontPointSize
,
1174 fontFamily
, fontStyle
, fontWeight
, (fontUnderlined
!= 0)));
1180 m_gdiObjects
.Append(NULL
);
1188 // Now read in the operations
1193 sprintf(buf
, "op%d", i
);
1194 wxExpr
*expr
= NULL
;
1195 clause
->AssignAttributeValue(buf
, &expr
);
1202 wxExpr
*idExpr
= expr
->Nth(0);
1203 int opId
= (int)idExpr
->IntegerValue();
1206 case DRAWOP_SET_PEN
:
1207 case DRAWOP_SET_BRUSH
:
1208 case DRAWOP_SET_FONT
:
1209 case DRAWOP_SET_TEXT_COLOUR
:
1210 case DRAWOP_SET_BK_COLOUR
:
1211 case DRAWOP_SET_BK_MODE
:
1213 wxOpSetGDI
*theOp
= new wxOpSetGDI(opId
, this, 0);
1214 theOp
->ReadwxExpr(this, expr
);
1215 m_ops
.Append(theOp
);
1219 case DRAWOP_SET_CLIPPING_RECT
:
1220 case DRAWOP_DESTROY_CLIPPING_RECT
:
1222 wxOpSetClipping
*theOp
= new wxOpSetClipping(opId
, 0.0, 0.0, 0.0, 0.0);
1223 theOp
->ReadwxExpr(this, expr
);
1224 m_ops
.Append(theOp
);
1228 case DRAWOP_DRAW_LINE
:
1229 case DRAWOP_DRAW_RECT
:
1230 case DRAWOP_DRAW_ROUNDED_RECT
:
1231 case DRAWOP_DRAW_ELLIPSE
:
1232 case DRAWOP_DRAW_POINT
:
1233 case DRAWOP_DRAW_ARC
:
1234 case DRAWOP_DRAW_TEXT
:
1236 wxOpDraw
*theOp
= new wxOpDraw(opId
, 0.0, 0.0, 0.0, 0.0);
1237 theOp
->ReadwxExpr(this, expr
);
1238 m_ops
.Append(theOp
);
1241 case DRAWOP_DRAW_SPLINE
:
1242 case DRAWOP_DRAW_POLYLINE
:
1243 case DRAWOP_DRAW_POLYGON
:
1245 wxOpPolyDraw
*theOp
= new wxOpPolyDraw(opId
, 0, NULL
);
1246 theOp
->ReadwxExpr(this, expr
);
1247 m_ops
.Append(theOp
);
1257 // Now read in the list of outline and fill operations, if any
1258 wxExpr
*expr1
= clause
->AttributeValue("outline_objects");
1261 wxExpr
*eachExpr
= expr1
->GetFirst();
1264 m_outlineColours
.Append((wxObject
*)eachExpr
->IntegerValue());
1265 eachExpr
= eachExpr
->GetNext();
1268 expr1
= clause
->AttributeValue("fill_objects");
1271 wxExpr
*eachExpr
= expr1
->GetFirst();
1274 m_fillColours
.Append((wxObject
*)eachExpr
->IntegerValue());
1275 eachExpr
= eachExpr
->GetNext();
1281 // Does the copying for this object
1282 void wxPseudoMetaFile::Copy(wxPseudoMetaFile
& copy
)
1284 copy
.m_currentRotation
= m_currentRotation
;
1285 copy
.m_width
= m_width
;
1286 copy
.m_height
= m_height
;
1287 copy
.m_rotateable
= m_rotateable
;
1289 // Copy the GDI objects
1290 wxNode
*node
= m_gdiObjects
.First();
1293 wxObject
*obj
= (wxObject
*)node
->Data();
1294 copy
.m_gdiObjects
.Append(obj
);
1295 node
= node
->Next();
1298 // Copy the operations
1299 node
= m_ops
.First();
1302 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1303 copy
.m_ops
.Append(op
->Copy(©
));
1304 node
= node
->Next();
1307 // Copy the outline/fill operations
1308 copy
.m_outlineColours
.Clear();
1309 node
= m_outlineColours
.First();
1312 copy
.m_outlineColours
.Append((wxObject
*)node
->Data());
1313 node
= node
->Next();
1315 copy
.m_fillColours
.Clear();
1316 node
= m_fillColours
.First();
1319 copy
.m_fillColours
.Append((wxObject
*)node
->Data());
1320 node
= node
->Next();
1325 * Pass size of existing image; scale height to
1326 * fit width and return new width and height.
1330 bool wxPseudoMetaFile::LoadFromMetaFile(char *filename
, float *rwidth
, float *rheight
)
1332 if (!FileExists(filename
))
1335 wxXMetaFile
*metaFile
= new wxXMetaFile
;
1337 if (!metaFile
->ReadFile(filename
))
1346 // Convert from metafile records to wxDrawnShape records
1347 wxNode
*node
= metaFile
->metaRecords
.First();
1350 wxMetaRecord
*record
= (wxMetaRecord
*)node
->Data();
1351 switch (record
->metaFunction
)
1353 case META_SETBKCOLOR
:
1355 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BK_COLOUR
, this, 0);
1356 op
->r
= (unsigned char)record
->param1
;
1357 op
->g
= (unsigned char)record
->param2
;
1358 op
->b
= (unsigned char)record
->param3
;
1362 case META_SETBKMODE
:
1364 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BK_MODE
, this, 0, (int)record
->param1
);
1368 case META_SETMAPMODE
:
1372 // case META_SETROP2:
1373 // case META_SETRELABS:
1374 // case META_SETPOLYFILLMODE:
1375 // case META_SETSTRETCHBLTMODE:
1376 // case META_SETTEXTCHAREXTRA:
1377 case META_SETTEXTCOLOR
:
1379 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR
, this, 0);
1380 op
->r
= (unsigned char)record
->param1
;
1381 op
->g
= (unsigned char)record
->param2
;
1382 op
->b
= (unsigned char)record
->param3
;
1386 // case META_SETTEXTJUSTIFICATION:
1387 // case META_SETWINDOWORG:
1388 // case META_SETWINDOWEXT:
1389 // case META_SETVIEWPORTORG:
1390 // case META_SETVIEWPORTEXT:
1391 // case META_OFFSETWINDOWORG:
1392 // case META_SCALEWINDOWEXT:
1393 // case META_OFFSETVIEWPORTORG:
1394 // case META_SCALEVIEWPORTEXT:
1397 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_LINE
, (float)lastX
, (float)lastY
,
1398 (float)record
->param1
, (float)record
->param2
);
1404 lastX
= (float)record
->param1
;
1405 lastY
= (float)record
->param2
;
1408 case META_EXCLUDECLIPRECT
:
1411 wxMetaRecord *rec = new wxMetaRecord(META_EXCLUDECLIPRECT);
1412 rec->param4 = getshort(handle); // y2
1413 rec->param3 = getshort(handle); // x2
1414 rec->param2 = getshort(handle); // y1
1415 rec->param1 = getshort(handle); // x1
1419 case META_INTERSECTCLIPRECT
:
1422 rec->param4 = getshort(handle); // y2
1423 rec->param3 = getshort(handle); // x2
1424 rec->param2 = getshort(handle); // y1
1425 rec->param1 = getshort(handle); // x1
1429 // case META_ARC: // DO!!!
1432 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_ELLIPSE
,
1433 (float)record
->param1
, (float)record
->param2
,
1434 (float)(record
->param3
- record
->param1
),
1435 (float)(record
->param4
- record
->param2
));
1439 // case META_FLOODFILL:
1440 // case META_PIE: // DO!!!
1441 case META_RECTANGLE
:
1443 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_RECT
,
1444 (float)record
->param1
, (float)record
->param2
,
1445 (float)(record
->param3
- record
->param1
),
1446 (float)(record
->param4
- record
->param2
));
1450 case META_ROUNDRECT
:
1452 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT
,
1453 (float)record
->param1
, (float)record
->param2
,
1454 (float)(record
->param3
- record
->param1
),
1455 (float)(record
->param4
- record
->param2
), (float)record
->param5
);
1459 // case META_PATBLT:
1460 // case META_SAVEDC:
1463 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_POINT
,
1464 (float)record
->param1
, (float)record
->param2
,
1467 // SHOULD SET THE COLOUR - SET PEN?
1468 // rec->param3 = getint(handle); // COLORREF
1472 // case META_OFFSETCLIPRGN:
1475 wxOpDraw
*op
= new wxOpDraw(DRAWOP_DRAW_TEXT
,
1476 (float)record
->param1
, (float)record
->param2
,
1477 0.0, 0.0, 0.0, record
->stringParam
);
1481 // case META_BITBLT:
1482 // case META_STRETCHBLT:
1485 int n
= (int)record
->param1
;
1486 wxRealPoint
*newPoints
= new wxRealPoint
[n
];
1487 for (int i
= 0; i
< n
; i
++)
1489 newPoints
[i
].x
= record
->points
[i
].x
;
1490 newPoints
[i
].y
= record
->points
[i
].y
;
1493 wxOpPolyDraw
*op
= new wxOpPolyDraw(DRAWOP_DRAW_POLYGON
, n
, newPoints
);
1499 int n
= (int)record
->param1
;
1500 wxRealPoint
*newPoints
= new wxRealPoint
[n
];
1501 for (int i
= 0; i
< n
; i
++)
1503 newPoints
[i
].x
= record
->points
[i
].x
;
1504 newPoints
[i
].y
= record
->points
[i
].y
;
1507 wxOpPolyDraw
*op
= new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE
, n
, newPoints
);
1511 // case META_ESCAPE:
1512 // case META_RESTOREDC:
1513 // case META_FILLREGION:
1514 // case META_FRAMEREGION:
1515 // case META_INVERTREGION:
1516 // case META_PAINTREGION:
1517 // case META_SELECTCLIPREGION: // DO THIS!
1518 case META_SELECTOBJECT
:
1520 // The pen, brush etc. has already been created when the metafile
1521 // was read in, so we don't create it - we set it.
1522 wxNode
*recNode
= metaFile
->gdiObjects
.Nth((int)record
->param2
);
1525 wxMetaRecord
*gdiRec
= (wxMetaRecord
*)recNode
->Data();
1526 if (gdiRec
&& (gdiRec
->param1
!= 0))
1528 wxObject
*obj
= (wxObject
*)gdiRec
->param1
;
1529 if (obj
->IsKindOf(CLASSINFO(wxPen
)))
1531 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_PEN
, this, (int)record
->param2
);
1534 else if (obj
->IsKindOf(CLASSINFO(wxBrush
)))
1536 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_BRUSH
, this, (int)record
->param2
);
1539 else if (obj
->IsKindOf(CLASSINFO(wxFont
)))
1541 wxOpSetGDI
*op
= new wxOpSetGDI(DRAWOP_SET_FONT
, this, (int)record
->param2
);
1548 // case META_SETTEXTALIGN:
1549 // case META_DRAWTEXT:
1551 // case META_SETMAPPERFLAGS:
1552 // case META_EXTTEXTOUT:
1553 // case META_SETDIBTODEV:
1554 // case META_SELECTPALETTE:
1555 // case META_REALIZEPALETTE:
1556 // case META_ANIMATEPALETTE:
1557 // case META_SETPALENTRIES:
1558 // case META_POLYPOLYGON:
1559 // case META_RESIZEPALETTE:
1560 // case META_DIBBITBLT:
1561 // case META_DIBSTRETCHBLT:
1562 case META_DIBCREATEPATTERNBRUSH
:
1565 m_gdiObjects
.Append(NULL
);
1568 // case META_STRETCHDIB:
1569 // case META_EXTFLOODFILL:
1570 // case META_RESETDC:
1571 // case META_STARTDOC:
1572 // case META_STARTPAGE:
1573 // case META_ENDPAGE:
1574 // case META_ABORTDOC:
1575 // case META_ENDDOC:
1576 // case META_DELETEOBJECT: // DO!!
1577 case META_CREATEPALETTE
:
1580 m_gdiObjects
.Append(NULL
);
1583 case META_CREATEBRUSH
:
1586 m_gdiObjects
.Append(NULL
);
1589 case META_CREATEPATTERNBRUSH
:
1592 m_gdiObjects
.Append(NULL
);
1595 case META_CREATEPENINDIRECT
:
1597 // The pen is created when the metafile is read in.
1598 // We keep track of all the GDI objects needed for this
1599 // image so when reading the wxDrawnShape from file,
1600 // we can read in all the GDI objects, then refer
1601 // to them by an index starting from zero thereafter.
1602 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1605 case META_CREATEFONTINDIRECT
:
1607 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1610 case META_CREATEBRUSHINDIRECT
:
1612 // Don't have to do anything here: the pen is created
1613 // when the metafile is read in.
1614 m_gdiObjects
.Append((wxObject
*)record
->param1
);
1617 case META_CREATEBITMAPINDIRECT
:
1620 m_gdiObjects
.Append(NULL
);
1623 case META_CREATEBITMAP
:
1626 m_gdiObjects
.Append(NULL
);
1629 case META_CREATEREGION
:
1632 m_gdiObjects
.Append(NULL
);
1640 node
= node
->Next();
1642 float actualWidth
= (float)fabs(metaFile
->right
- metaFile
->left
);
1643 float actualHeight
= (float)fabs(metaFile
->bottom
- metaFile
->top
);
1645 float initialScaleX
= 1.0;
1646 float initialScaleY
= 1.0;
1648 float xoffset
, yoffset
;
1650 // Translate so origin is at centre of rectangle
1651 if (metaFile
->bottom
> metaFile
->top
)
1652 yoffset
= - (float)((metaFile
->bottom
- metaFile
->top
)/2.0);
1654 yoffset
= - (float)((metaFile
->top
- metaFile
->bottom
)/2.0);
1656 if (metaFile
->right
> metaFile
->left
)
1657 xoffset
= - (float)((metaFile
->right
- metaFile
->left
)/2.0);
1659 xoffset
= - (float)((metaFile
->left
- metaFile
->right
)/2.0);
1661 Translate(xoffset
, yoffset
);
1663 // Scale to a reasonable size (take the width of this wxDrawnShape
1665 if (actualWidth
!= 0.0)
1667 initialScaleX
= (float)((*rwidth
) / actualWidth
);
1668 initialScaleY
= initialScaleX
;
1669 (*rheight
) = initialScaleY
*actualHeight
;
1671 Scale(initialScaleX
, initialScaleY
);
1673 m_width
= (actualWidth
*initialScaleX
);
1674 m_height
= *rheight
;
1680 // Scale to fit size
1681 void wxPseudoMetaFile::ScaleTo(float w
, float h
)
1683 float scaleX
= (float)(w
/m_width
);
1684 float scaleY
= (float)(h
/m_height
);
1687 Scale(scaleX
, scaleY
);
1690 void wxPseudoMetaFile::GetBounds(float *boundMinX
, float *boundMinY
, float *boundMaxX
, float *boundMaxY
)
1692 float maxX
= (float) -99999.9;
1693 float maxY
= (float) -99999.9;
1694 float minX
= (float) 99999.9;
1695 float minY
= (float) 99999.9;
1697 wxNode
*node
= m_ops
.First();
1700 wxDrawOp
*op
= (wxDrawOp
*)node
->Data();
1703 case DRAWOP_DRAW_LINE
:
1704 case DRAWOP_DRAW_RECT
:
1705 case DRAWOP_DRAW_ROUNDED_RECT
:
1706 case DRAWOP_DRAW_ELLIPSE
:
1707 case DRAWOP_DRAW_POINT
:
1708 case DRAWOP_DRAW_ARC
:
1709 case DRAWOP_DRAW_TEXT
:
1711 wxOpDraw
*opDraw
= (wxOpDraw
*)op
;
1712 if (opDraw
->x1
< minX
) minX
= opDraw
->x1
;
1713 if (opDraw
->x1
> maxX
) maxX
= opDraw
->x1
;
1714 if (opDraw
->y1
< minY
) minY
= opDraw
->y1
;
1715 if (opDraw
->y1
> maxY
) maxY
= opDraw
->y1
;
1716 if (op
->op
== DRAWOP_DRAW_LINE
)
1718 if (opDraw
->x2
< minX
) minX
= opDraw
->x2
;
1719 if (opDraw
->x2
> maxX
) maxX
= opDraw
->x2
;
1720 if (opDraw
->y2
< minY
) minY
= opDraw
->y2
;
1721 if (opDraw
->y2
> maxY
) maxY
= opDraw
->y2
;
1723 else if (op
->op
== DRAWOP_DRAW_RECT
||
1724 op
->op
== DRAWOP_DRAW_ROUNDED_RECT
||
1725 op
->op
== DRAWOP_DRAW_ELLIPSE
)
1727 if ((opDraw
->x1
+ opDraw
->x2
) < minX
) minX
= (opDraw
->x1
+ opDraw
->x2
);
1728 if ((opDraw
->x1
+ opDraw
->x2
) > maxX
) maxX
= (opDraw
->x1
+ opDraw
->x2
);
1729 if ((opDraw
->y1
+ opDraw
->y2
) < minY
) minY
= (opDraw
->y1
+ opDraw
->y2
);
1730 if ((opDraw
->y1
+ opDraw
->y2
) > maxY
) maxY
= (opDraw
->y1
+ opDraw
->y2
);
1734 case DRAWOP_DRAW_POLYLINE
:
1735 case DRAWOP_DRAW_POLYGON
:
1736 case DRAWOP_DRAW_SPLINE
:
1738 wxOpPolyDraw
*poly
= (wxOpPolyDraw
*)op
;
1739 for (int i
= 0; i
< poly
->noPoints
; i
++)
1741 if (poly
->points
[i
].x
< minX
) minX
= poly
->points
[i
].x
;
1742 if (poly
->points
[i
].x
> maxX
) maxX
= poly
->points
[i
].x
;
1743 if (poly
->points
[i
].y
< minY
) minY
= poly
->points
[i
].y
;
1744 if (poly
->points
[i
].y
> maxY
) maxY
= poly
->points
[i
].y
;
1751 node
= node
->Next();
1759 *w = (float)fabs(maxX - minX);
1760 *h = (float)fabs(maxY - minY);