wxArt2D
stylebase.cpp
Go to the documentation of this file.
1 /*! \file artbase/src/stylebase.cpp
2  \author Klaas Holwerda
3 
4  Copyright: 2000-2004 (c) Klaas Holwerda
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: stylebase.cpp,v 1.142 2009/08/20 18:59:14 titato Exp $
9 */
10 
11 #include "a2dprec.h"
12 
13 #ifndef WX_PRECOMP
14 #include "wx/wx.h"
15 #endif
16 
17 #include <wx/dir.h>
18 #include <wx/file.h>
19 #include <wx/filename.h>
20 #include <wx/fontenum.h>
21 #include <wx/module.h>
22 
23 #include "wx/general/genmod.h"
24 
25 //#include "wx/general/id.inl"
26 
27 #include "wx/artbase/stylebase.h"
28 #include "wx/artbase/bbox.h"
29 #include "wx/artbase/drawer2d.h"
30 #include "wx/artbase/polyver.h"
31 
32 #if defined(__USE_WINAPI__)
33 #include "wx/msw/dc.h"
34 #include "wx/artbase/mswfont.h"
35 #endif
36 
37 #if defined(__WXMSW__) && defined(__MEMDEBUG__)
38 #include <wx/msw/msvcrt.h>
39 #endif
40 
41 #define newline wxString("\n")
42 
43 #if wxART2D_USE_FREETYPE
44 FT_Library g_freetypeLibrary;
45 #endif
46 
47 #define wxART2D_USE_DC2FREETYPE 1
48 
49 
50 IMPLEMENT_DYNAMIC_CLASS( a2dStroke, wxObject )
51 IMPLEMENT_DYNAMIC_CLASS( a2dFill, wxObject )
52 
53 //----------------------------------------------------------------------------
54 // a2dFontInfoList
55 //----------------------------------------------------------------------------
56 
57 #include <wx/listimpl.cpp>
58 WX_DEFINE_LIST( a2dFontInfoList );
59 
60 //----------------------------------------------------------------------------
61 // a2dFontInfo
62 //----------------------------------------------------------------------------
63 
64 a2dFontInfo::a2dFontInfo( const wxString& type, const wxString& name,
65  const wxString& style, double size, const wxString& extra )
66 {
67  m_type = type;
68  m_name = name;
69  m_style = style;
70  m_size = size;
71  m_extra = extra;
72 }
73 
74 a2dFontInfo::a2dFontInfo( const wxString& type, const wxString& name,
75  const wxString& style, const wxString& extra )
76 {
77  m_type = type;
78  m_name = name;
79  m_style = style;
80  m_size = 1.0;
81  m_extra = extra;
82 }
83 
84 a2dFontInfo::a2dFontInfo( const wxString& info )
85 {
86  ParseString( info );
87 }
88 
90 {
91  m_type = other.m_type;
92  m_name = other.m_name;
93  m_style = other.m_style;
94  m_size = other.m_size;
95  m_extra = other.m_extra;
96  return *this;
97 }
98 
99 bool a2dFontInfo::operator == ( const a2dFontInfo& other ) const
100 {
101  return m_type == other.m_type
102  && m_name == other.m_name
103  && m_style == other.m_style
104  && m_size == other.m_size
105  && m_extra == other.m_extra;
106 }
107 
109 {
110  wxString size;
111  size.Printf( wxT( "%f" ), m_size );
112  wxString description = m_type + wxT( "-" ) + m_name + wxT( "-" ) + m_style
113  + wxT( "-" ) + size + wxT( "-" );
114  if ( !m_extra.IsEmpty() )
115  description += wxT( "-" ) + m_extra;
116 
117  return description;
118 }
119 
120 void a2dFontInfo::ParseString( wxString string )
121 {
122  size_t stringlength = string.Length();
123  size_t idx, last;
124  idx = last = 0;
125  while ( idx < stringlength && string[idx] != wxChar( '-' ) )
126  idx++;
127  m_type = string.Mid( last, idx - last );
128  if ( idx < stringlength )
129  idx++;
130  last = idx;
131  while ( idx < stringlength && string[idx] != wxChar( '-' ) )
132  idx++;
133  m_name = string.Mid( last, idx - last );
134  if ( idx < stringlength )
135  idx++;
136  last = idx;
137  while ( idx < stringlength && string[idx] != wxChar( '-' ) )
138  idx++;
139  m_style = string.Mid( last, idx - last );
140  if ( idx < stringlength )
141  idx++;
142  last = idx;
143  while ( idx < stringlength && string[idx] != wxChar( '-' ) )
144  idx++;
145  string.Mid( last, idx - last ).ToDouble( &m_size );
146  if ( idx < stringlength )
147  idx++;
148  last = idx;
149  while ( idx < stringlength && string[idx] != wxChar( '-' ) )
150  idx++;
151  if ( idx < stringlength )
152  idx++;
153  last = idx;
154  m_extra = string.Mid( last );
155 }
156 
158 {
159  m_size = size;
160  return a2dFont::CreateFont( *this );
161 }
162 
163 //----------------------------------------------------------------------------
164 // a2dFontRefData
165 //----------------------------------------------------------------------------
166 
167 class A2DARTBASEDLLEXP a2dFontRefData : public wxObjectRefData
168 {
169  friend class a2dFont;
170 public:
171 
172  virtual a2dFontType GetType( void ) const { return a2dFONT_NULL; }
173 
174  a2dFontRefData( double size )
175  {
176  m_fontinfo.SetSize( size );
177  m_height = 1;
178  m_desc = 0;
179  m_lead = 0;
180  m_ok = false;
181  }
182 
183  //!constructor
185  {
186  }
187 
188  a2dFontRefData( const a2dFontRefData& other )
189  : wxObjectRefData()
190  {
191  m_fontinfo = other.m_fontinfo;
192  m_height = other.m_height;
193  m_desc = other.m_desc;
194  m_lead = other.m_lead;
195  m_ok = other.m_ok;
196  }
197 
198  bool Ok() { return m_ok; }
199  virtual void SetSize( double size ) { m_fontinfo.SetSize( size ); }
200  inline double GetSize() const { return m_fontinfo.GetSize(); }
201 
202  double GetDescent() const
203  {
204  if ( m_ok )
205  return m_fontinfo.GetSize() * m_desc;
206  else
207  return 0.0;
208  }
209 
210  double GetLineHeight() const
211  {
212  if ( m_ok )
213  return m_fontinfo.GetSize() * m_height;
214  else
215  return 0.0;
216  }
217 
218  //! Get kerning space between two characters.
219  /*! Kerning is a method, which moves characters closer together/further apart, to
220  improve the look of the font. Eg. the letter combination LT will be moved closer together.
221  The return value is negative or positive, to respectively move characters closer together, or further
222  apart.
223  */
224  virtual double GetKerning( wxChar WXUNUSED( c1 ), wxChar WXUNUSED( c2 ) ) const { return 0.0; }
225 
226  //! Get width of a single character
227  virtual double GetWidth( wxChar c ) const = 0;
228 
229  virtual bool GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine = a2dIDENTITY_MATRIX ) { return false; }
230 
231  virtual void GetTextExtent( const wxString& string, double& w, double& h, double& descent, double& externalLeading ) const;
232 
233 
234 protected:
235 
236  //! Font info
238 
239  //! Font height cache normalized to a font height of 1.
240  double m_height;
241 
242  //! Font descender cache normalized to a font height of 1.
243  double m_desc;
244 
245  //! Font external leading normalized to a font height of 1.
246  double m_lead;
247 
248  //! True if a valid font is set.
249  bool m_ok;
250 
251 #if wxART2D_USE_CVGIO
252  //! Save settings.
253  //virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList* towrite ) = 0;
254  //! Load settings.
255  //virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts ) = 0;
256 #endif //wxART2D_USE_CVGIO
257 
258 };
259 
260 void a2dFontRefData::GetTextExtent( const wxString& string, double& w,
261  double& h, double& descent, double& externalLeading ) const
262 {
263  if ( m_ok )
264  {
265  double x(0.0);
266  int len(string.Length());
267  if (len)
268  {
269  wxChar ch_n_1, ch_n(string[(size_t)0]);
270  x = GetWidth( ch_n );
271  for ( size_t n = 1; n < len; n++ )
272  {
273  ch_n_1 = ch_n;
274  ch_n = string[n];
275  x += GetKerning( ch_n_1, ch_n);
276  x += GetWidth( ch_n );
277  }
278  }
279  w = x;
280  h = GetSize() * m_height;
281  descent = GetSize() * m_desc;
282  externalLeading = GetSize() * m_lead;
283  }
284  else
285  w = h = descent = externalLeading = 0.0;
286 }
287 
288 //----------------------------------------------------------------------------
289 // a2dFontDcData
290 //----------------------------------------------------------------------------
291 
292 //! DC font class.
293 /*! \class a2dFontDc stylebase.h artbase/stylebase.h
294  Font class, based on the DC (device context) fonts. While being relatively fast, it has a
295  disadvantage, that they can neither be stretched, nor slanted. Scaling is not a problem.
296 
297  \todo EW: To overcome the non-proportional font scaling on windows, I draw every character myself.
298  This pretty much disables the pango (font) renderer for gtk2. Therefore some non-western languages
299  might not work properly (if they ever did?).
300 
301  \ingroup property style
302  \ingroup textrelated
303 */
304 class A2DARTBASEDLLEXP a2dFontDcData
305  : public a2dFontRefData
306 {
307  friend class a2dFont;
308 public:
309 
310  virtual a2dFontType GetType( void ) const { return a2dFONT_WXDC; }
311 
312  //! Constructor.
313  /*! \param font Font format. The size of the font is not used and should be set using the next parameter.
314  \param size Size in world coordinates.
315  */
316  a2dFontDcData( const wxFont& font = wxNullFont, double size = 0.0 );
317 
318  //! Constructor
319  /*!
320  Creates a font object (see font encoding overview, in the wxWidgets documentation, for the meaning of the last parameter).
321  \param size Size in world coordinates.
322  \param family Font family, a generic way of referring to fonts without specifying actual facename. One of:
323  - wxDEFAULT Chooses a default font.
324  - wxDECORATIVE A decorative font.
325  - wxROMAN A formal, serif font.
326  - wxSCRIPT A handwriting font.
327  - wxSWISS A sans-serif font.
328  - wxMODERN A fixed pitch font.
329  \param style One of wxNORMAL, wxSLANT and wxITALIC.
330  \param weight One of wxNORMAL, wxLIGHT and wxBOLD.
331  \param underline The value can be true or false. At present this has an effect on Windows and Motif 2.x only.
332  \param faceName An optional string specifying the actual typeface to be used. If the empty string, a default typeface will chosen based on the family.
333  \param encoding An encoding which may be one of
334  - wxFONTENCODING_SYSTEM Default system encoding.
335  - wxFONTENCODING_DEFAULT Default application encoding.
336  - wxFONTENCODING_ISO8859_1...15 ISO8859 encodings.
337  - wxFONTENCODING_KOI8 The standard Russian encoding for Internet.
338  - wxFONTENCODING_CP1250...1252 Windows encodings similar to ISO8859 (but not identical).
339 
340  If the specified encoding isn't available, no font is created.
341 
342  wxFONTENCODING_DEFAULT is the encoding set by calls to SetDefaultEncoding and which
343  may be set to, say, KOI8 to create all fonts by default with KOI8 encoding. Initially,
344  the default application encoding is the same as default system encoding.
345  \remark
346  - If the desired font does not exist, the closest match will be chosen.
347  - Under Windows, only scalable TrueType fonts are used.
348  */
349  a2dFontDcData( double size, int family, int style = wxNORMAL, int weight = wxNORMAL,
350  const bool underline = false, const wxString& faceName = wxT( "" ),
351  wxFontEncoding encoding = wxFONTENCODING_DEFAULT );
352 
353  //! Copy constructor.
354  a2dFontDcData( const a2dFontDcData& other );
355  //! Destructor.
356  virtual ~a2dFontDcData();
357 
358  //! Set font format.
359  /*! \param font The font information. The size of the font is not used.
360  */
361  void SetFont( const wxFont& font );
362 
363  //! Get the font format.
364  /*! \return The font information. The size of the font should be disregarded, since
365  it is internally for storage.
366  */
367  wxFont& GetFont( void ) { return m_font; }
368 
369  //! Find the filename of the current font.
370  /*! Currently only implemented for Windows.
371  \return The absolute filename. In case of error an empty string is returned
372  */
373  wxString FindFileName() const;
374 
375  // Documented in base class
376  double GetWidth( wxChar c ) const;
377 
378  // Documented in base class
379  double GetKerning( wxChar c1, wxChar c2 ) const;
380 
381  //! to set for load glyph from face, to do proper hinting
382  void SetDeviceHeight( double sizeInPixels );
383 
384  double GetDeviceHeight() { return m_sizeInPixels; }
385 
386  void GetTextExtent( const wxString& string, double& w, double& h, double& descent, double& externalLeading ) const;
387 
388  bool GetVpath( wxChar c, a2dVpath& glyph, const a2dAffineMatrix& affine = a2dIDENTITY_MATRIX );
389 
390  // Documented in base class
391  static void GetInfoList( a2dFontInfoList& list );
392 
393  // Documented in base class
394  static a2dFontDcData* CreateFont( const a2dFontInfo& info, bool force = false );
395 
396 #if wxART2D_USE_FREETYPE
397  // Documented in base class
398  void SetSize( double size );
399 
400  //! Get the freetype equivalent of the font
401  a2dFont GetFreetypeFont();
402 #endif
403 
404 
405 protected:
406 
407  //! current text drawn its size in pixels to do proper hinting.
409 
410  //! Font
411  wxFont m_font;
412 
413  //! Width cache normalized to a font height of 1. This stores the 'normal' part of the alphabet.
414  mutable double* m_widthcache;
415  //! Width cache normalized to a font height of 1. This stores the extended characters.
417 
418 #if defined(__USE_WINAPI__)
419  //! Kerning cache normalized to a font height of 1.
420  mutable KERNINGPAIR* m_kerningcache;
421  mutable map<int, int> m_kerningmap; //! faster access than linear search in m_kerningcache
422  //! Number of kerning pairs.
423  mutable int m_nkerningpairs;
424 #else
425  //! Kerning cache normalized to a font height of 1.
427 #endif
428 
429 #if wxART2D_USE_FREETYPE
430  //! freetype equivalent of the font, used in AggDrawer.
432 #endif
433 };
434 
435 
436 #define CHAR_CACHE_START wxChar(' ')
437 #define CHAR_CACHE_END wxChar('~')
438 
439 a2dFontDcData::a2dFontDcData( const wxFont& font, double size )
440  : a2dFontRefData( size )
441 {
443  m_fontinfo.SetType( wxT( "Device font" ) );
444  m_widthcache = NULL;
445 #if defined(__USE_WINAPI__)
446  m_kerningcache = NULL;
447 #endif
448  SetFont( font );
449 }
450 
451 a2dFontDcData::a2dFontDcData( double size, int family, int style, int weight,
452  const bool underline, const wxString& faceName, wxFontEncoding encoding )
453  : a2dFontRefData( size )
454 {
456  m_fontinfo.SetType( wxT( "Device font" ) );
457  m_widthcache = NULL;
458 #if defined(__USE_WINAPI__)
459  m_kerningcache = NULL;
460 #endif
461  SetFont( wxFont( 1, family, style, weight, underline, faceName, encoding ) );
462 }
463 
465  : a2dFontRefData( other )
466 {
468  m_widthcache = NULL;
469 #if defined(__USE_WINAPI__)
470  m_kerningcache = NULL;
471 #endif
472  SetFont( other.m_font );
473 }
474 
476 {
477  if ( m_widthcache )
478  delete[] m_widthcache;
479 #if defined(__USE_WINAPI__)
480  if ( m_kerningcache )
481  delete[] m_kerningcache;
482 #endif
483 }
484 
485 void a2dFontDcData::SetDeviceHeight( double sizeInPixels )
486 {
487  if ( m_sizeInPixels != sizeInPixels )
488  {
489  m_sizeInPixels = sizeInPixels;
490  if ( m_sizeInPixels < 1 )
491  m_sizeInPixels = 1;
492 
493  m_font.SetPointSize( ( int ) m_sizeInPixels );
494  SetFont( m_font );
495 
496 #if wxART2D_USE_FREETYPE
497  if ( m_freetypefont != *a2dNullFONT )
498  m_freetypefont.SetDeviceHeight( m_sizeInPixels );
499 #endif
500  }
501 }
502 
503 
504 void a2dFontDcData::SetFont( const wxFont& font )
505 {
506  m_font = font;
507  m_ok = m_font.Ok();
508 
509  //delete old cache
510  while ( !m_extwidthcache.empty() )
511  {
512  DcWidthHash::iterator it = m_extwidthcache.begin();
513  m_extwidthcache.erase( it );
514  }
515 
516  //prefill cache;
517  if ( !m_widthcache )
518  m_widthcache = new double[CHAR_CACHE_END - CHAR_CACHE_START + 1];
519 
520  wxMemoryDC dc;
521  wxFont fnt = m_font;
522  fnt.SetPointSize( ( int ) m_sizeInPixels );
523  dc.SetFont( fnt );
524  wxChar c;
525  wxString string;
526  wxCoord width, height, desc, lead;
527  width = height = desc = lead = 0;
528 
529 #if defined(__USE_WINAPI__)
530 #if wxCHECK_VERSION(2,9,0)
531  wxMSWDCImpl* dcimpl = wxStaticCast( dc.GetImpl(), wxMSWDCImpl );
532  WXHDC hdc = dcimpl->GetHDC();
533 #else
534  WXHDC hdc = dc.GetHDC();
535 #endif
536 #endif
537 
538  wxCoord descmax = 0;
539 #if defined(__USE_WINAPI__)
540  string = CHAR_CACHE_START;
541  dc.GetTextExtent( string, &width, &height, &descmax, &lead );
542 
543  ABCFLOAT* ABCarray = new ABCFLOAT[CHAR_CACHE_END - CHAR_CACHE_START + 1];
544  GetCharABCWidthsFloat( ( HDC ) hdc, CHAR_CACHE_START, CHAR_CACHE_END, ( LPABCFLOAT ) ABCarray );
545 
546  for ( c = CHAR_CACHE_START; c <= CHAR_CACHE_END; c++ )
547  {
548  ABCFLOAT a = ABCarray[c - CHAR_CACHE_START];
549  float widthf = a.abcfA + a.abcfB + a.abcfC;
550  widthf = widthf / m_sizeInPixels;
551  m_widthcache[c - CHAR_CACHE_START] = widthf ;
552  }
553  delete ABCarray;
554 #else
555  for ( c = CHAR_CACHE_START; c <= CHAR_CACHE_END; c++ )
556  {
557  string = c;
558  dc.GetTextExtent( string, &width, &height, &desc, &lead );
559  descmax = wxMax( descmax, desc );
560  float widthf = ( float ) width / m_sizeInPixels;
561  m_widthcache[c - CHAR_CACHE_START] = widthf;
562  }
563 #endif
564 
565  m_height = ( double ) height / m_sizeInPixels;
566  m_desc = ( double ) descmax / m_sizeInPixels;
567  m_lead = ( double ) lead / m_sizeInPixels;
568 
569  if ( m_font.GetFaceName().IsEmpty() )
570  m_fontinfo.SetName( wxT( "LiberationSans" ) );
571  else
572  m_fontinfo.SetName( m_font.GetFaceName() );
573  wxString style = wxEmptyString;
574  switch ( m_font.GetWeight() )
575  {
576  case wxNORMAL:
577  if ( m_font.GetStyle() == wxNORMAL )
578  style = wxT( "Regular" );
579  break;
580  case wxBOLD:
581  style = wxT( "Bold " );
582  break;
583  case wxLIGHT:
584  style = wxT( "Light " );
585  break;
586  }
587  switch ( m_font.GetStyle() )
588  {
589  case wxNORMAL:
590  break;
591  case wxITALIC:
592  case wxSLANT:
593  style += wxT( "Italic" );
594  break;
595  }
596  m_fontinfo.SetStyle( style.Trim() );
597 
598 #if wxART2D_USE_FREETYPE
600 
601 #if wxART2D_USE_DC2FREETYPE
602  wxString filename = FindFileName();
603  if ( !filename.IsEmpty() )
604  {
605  m_freetypefont = a2dFont( filename, GetSize() );
606  }
607 #endif
608 
609 #endif
610 
611 #if defined(__USE_WINAPI__)
612  // Standard drawing method on Windows using DrawText does not use kerning, therefore
613  // we have to get the values ourselves.
614  if ( m_kerningcache )
615  {
616  delete[] m_kerningcache;
617  m_nkerningpairs = 0;
618  }
619  m_nkerningpairs = ::GetKerningPairs( ( HDC ) hdc, 0, NULL );
620  m_kerningcache = new KERNINGPAIR[ m_nkerningpairs ];
621  m_nkerningpairs = ::GetKerningPairs( ( HDC ) hdc, m_nkerningpairs, m_kerningcache );
622 
623  // init map
624  KERNINGPAIR* ptr = m_kerningcache;
625  int i = m_nkerningpairs;
626  while ( i-- )
627  {
628  m_kerningmap[(ptr->wFirst << 16) + ptr->wSecond] = ptr->iKernAmount;
629  ptr++;
630  }
631 
632 
633 #endif //defined(__USE_WINAPI__)
634  dc.SetFont( wxNullFont );
635 }
636 
637 
638 void a2dFontDcData::GetTextExtent( const wxString& string, double& w,
639  double& h, double& descent, double& externalLeading ) const
640 {
641  a2dFontRefData::GetTextExtent( string, w, h, descent, externalLeading );
642  return;
643 
644  if ( !m_ok )
645  {
646  w = h = descent = externalLeading = 0.0;
647  return;
648  }
649 
650  wxMemoryDC dc;
651  dc.SetFont( m_font );
652  wxCoord width, height, desc, lead;
653  width = height = desc = lead = 0;
654 
655  dc.GetTextExtent( string, &width, &height, &desc, &lead );
656  w = GetSize() * width / m_sizeInPixels;
657  h = GetSize() * height / m_sizeInPixels;
658  descent = GetSize() * desc / m_sizeInPixels;
659  externalLeading = GetSize() * lead / m_sizeInPixels;
660 }
661 
663 {
664  wxString filename;
665 #if defined(__USE_WINAPI__)
666  wxString facename = m_font.GetFaceName();
667  if ( m_font.GetWeight() == wxBOLD )
668  facename += wxT( " Bold" );
669  if ( m_font.GetStyle() == wxITALIC )
670  facename += wxT( " Italic" );
671 
672  TCHAR displayname[_MAX_PATH];
673  TCHAR fontfilename[_MAX_PATH];
674  if( GetFontFile( facename.c_str(), displayname, _MAX_PATH - 1,
675  fontfilename, _MAX_PATH - 1 ) )
676  {
677  filename = fontfilename;
678  }
679 #endif // defined( __USE_WINAPI__ )
680 
681  return filename;
682 }
683 
684 #if wxART2D_USE_FREETYPE
685 void a2dFontDcData::SetSize( double size )
686 {
687  a2dFontRefData::SetSize( size );
688  if ( m_freetypefont != *a2dNullFONT )
689  m_freetypefont.SetSize( size );
690 }
691 #endif
692 
693 double a2dFontDcData::GetWidth( wxChar c ) const
694 {
695  if ( !m_ok )
696  return 0.0;
697 
698  // if character is a 'normal' ascii character, use lookup-table.
699  if ( c >= CHAR_CACHE_START && c <= CHAR_CACHE_END )
700  return GetSize() * m_widthcache[c - CHAR_CACHE_START];
701  else
702  {
703  DcWidthHash::iterator it = m_extwidthcache.find( c );
704  if ( it == m_extwidthcache.end() )
705  {
706  wxMemoryDC dc;
707  wxFont font = m_font;
708  font.SetPointSize( ( int ) m_sizeInPixels );
709  dc.SetFont( font );
710  wxCoord width, height, desc, lead;
711  wxString string = c;
712  dc.GetTextExtent( string, &width, &height, &desc, &lead );
713  dc.SetFont( wxNullFont );
714  m_extwidthcache[c] = ( double ) width / m_sizeInPixels;
715  return GetSize() * width / m_sizeInPixels;
716  }
717  else
718  return GetSize() * it->second;
719  }
720 }
721 
722 double a2dFontDcData::GetKerning( wxChar c1, wxChar c2 ) const
723 {
724 #if defined( __USE_WINAPI__ )
725  map<int,int>::iterator it(m_kerningmap.find((c1 << 16) + c2));
726  if (it != m_kerningmap.end())
727  return GetSize() * (*it).second / m_sizeInPixels;
728  else
729  return 0.0;
730 #else // defined( __USE_WINAPI__ )
731  wxString ab = c1;
732  ab += c2;
733  DcKerningHash::iterator it = m_kerningcache.find( ab );
734  if ( it == m_kerningcache.end() )
735  {
736  wxMemoryDC dc;
737  wxFont font = m_font;
738  font.SetPointSize( ( int ) m_sizeInPixels );
739  dc.SetFont( font );
740  wxCoord width, height, desc, lead;
741  dc.GetTextExtent( ab, &width, &height, &desc, &lead );
742  dc.SetFont( wxNullFont );
743  double kerning = ( double ) width / m_sizeInPixels - ( GetWidth( c1 ) + GetWidth( c2 ) ) / GetSize();
744  m_kerningcache[ab] = kerning;
745  return GetSize() * kerning;
746  }
747  else
748  return GetSize() * it->second;
749 #endif // defined( __USE_WINAPI__ )
750 }
751 
752 bool a2dFontDcData::GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine )
753 {
754 #if wxART2D_USE_FREETYPE
755 #if defined( __USE_WINAPI__ )
756  /*
757  bool flip_y = false;
758  const char* cur_glyph = c;
759  double x, y;
760 
761  const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
762 
763  const char* end_poly = cur_glyph + th->cb;
764  const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
765 
766  x = fx_to_dbl(th->pfxStart.x);
767  y = fx_to_dbl(th->pfxStart.y);
768  if(flip_y) y = -y;
769  affine.Translate(&x, &y);
770  vpath.MoveTo(value_type(dbl_to_int26p6(x)),
771  value_type(dbl_to_int26p6(y)));
772 
773  while(cur_poly < end_poly)
774  {
775  const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
776 
777  if (pc->wType == TT_PRIM_LINE)
778  {
779  int i;
780  for (i = 0; i < pc->cpfx; i++)
781  {
782  x = fx_to_dbl(pc->apfx[i].x);
783  y = fx_to_dbl(pc->apfx[i].y);
784  if(flip_y) y = -y;
785  affine.Translate(&x, &y);
786  path.line_to(value_type(dbl_to_int26p6(x)),
787  value_type(dbl_to_int26p6(y)));
788  }
789  }
790 
791  if (pc->wType == TT_PRIM_QSPLINE)
792  {
793  int u;
794  for (u = 0; u < pc->cpfx - 1; u++) // Walk through points in spline
795  {
796  POINTFX pnt_b = pc->apfx[u]; // B is always the current point
797  POINTFX pnt_c = pc->apfx[u+1];
798 
799  if (u < pc->cpfx - 2) // If not on last spline, compute C
800  {
801  // midpoint (x,y)
802  *(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2;
803  *(int*)&pnt_c.y = (*(int*)&pnt_b.y + *(int*)&pnt_c.y) / 2;
804  }
805 
806  double x2, y2;
807  x = fx_to_dbl(pnt_b.x);
808  y = fx_to_dbl(pnt_b.y);
809  x2 = fx_to_dbl(pnt_c.x);
810  y2 = fx_to_dbl(pnt_c.y);
811  if(flip_y) { y = -y; y2 = -y2; }
812  affine.Translate(&x, &y);
813  affine.Translate(&x2, &y2);
814  path.curve3(value_type(dbl_to_int26p6(x)),
815  value_type(dbl_to_int26p6(y)),
816  value_type(dbl_to_int26p6(x2)),
817  value_type(dbl_to_int26p6(y2)));
818  }
819  }
820  cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
821  }
822  */
823  if ( m_freetypefont != *a2dNullFONT )
824  return m_freetypefont.GetVpath( c, vpath, affine );
825 #else // defined( __USE_WINAPI__ )
826  if ( m_freetypefont != *a2dNullFONT )
827  return m_freetypefont.GetVpath( c, vpath, affine );
828 #endif // defined( __USE_WINAPI__ )
829  return false;
830 #else
831  return false;
832 #endif
833 }
834 
835 //! a2dFontDcData auxiliry class to aid in enumerating fonts.
836 class DcFontEnumerator : public wxFontEnumerator
837 {
838 public:
839  virtual bool OnFacename( const wxString& facename )
840  {
841  m_facenames.Add( facename );
842  return true;
843  }
844  wxArrayString m_facenames;
845 };
846 
847 void a2dFontDcData::GetInfoList( a2dFontInfoList& list )
848 {
849  DcFontEnumerator enumerator;
850  enumerator.EnumerateFacenames();
851  for ( unsigned int i = 0; i < enumerator.m_facenames.GetCount(); i++ )
852  {
853  wxString fontname = enumerator.m_facenames.Item( i );
854  list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Regular" ), 1.0 ) );
855  list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Italic" ), 1.0 ) );
856  list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Bold" ), 1.0 ) );
857  list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Bold Italic" ), 1.0 ) );
858  list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Light" ), 1.0 ) );
859  list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Light Italic" ), 1.0 ) );
860  }
861 }
862 
863 a2dFontDcData* a2dFontDcData::CreateFont( const a2dFontInfo& info, bool force )
864 {
865  int slant = wxNORMAL;
866  int weight = wxNORMAL;
867  if ( force || info.GetType().Upper() == wxT( "DEVICE FONT" ) )
868  {
869  if ( info.GetStyle().Upper().Find( wxT( "ITALIC" ) ) != -1 )
870  slant = wxITALIC;
871  if ( info.GetStyle().Upper().Find( wxT( "BOLD" ) ) != -1 )
872  weight = wxBOLD;
873  if ( info.GetStyle().Upper().Find( wxT( "LIGHT" ) ) != -1 )
874  weight = wxLIGHT;
875 
876  a2dFontDcData* font = new a2dFontDcData( info.GetSize(), wxSWISS, slant, weight, false, info.GetName() );
877  if ( font->Ok() )
878  return font;
879  else
880  delete font;
881  }
882  return NULL;
883 }
884 
885 #if wxART2D_USE_FREETYPE
887 {
888  return m_freetypefont;
889 }
890 #endif
891 
892 //--------------------------------------------------------------------
893 // a2dFreetypeModule
894 //--------------------------------------------------------------------
895 
896 class a2dFreetypeFace;
897 
898 
899 IMPLEMENT_DYNAMIC_CLASS( a2dFreetypeModule, wxModule )
900 
902 {
903  AddDependency( CLASSINFO( a2dGeneralModule ) );
904 }
905 
906 bool a2dFreetypeModule::OnInit()
907 {
908 #if wxART2D_USE_FREETYPE
909  int error = FT_Init_FreeType( &g_freetypeLibrary );
910  if ( error ) return false;
911 #endif
912  return true;
913 }
914 
915 void a2dFreetypeModule::OnExit()
916 {
917  a2dFont::ClearFontCache();
918 
919 #if wxART2D_USE_FREETYPE
920  FT_Done_FreeType( g_freetypeLibrary );
921  // Sometimes library is deleted before other fonts are deleted, therefore
922  // set g_freetypeLibrary to NULL. Memory leakage to be solved.
923  g_freetypeLibrary = NULL;
924 #endif
925 }
926 
927 #if wxART2D_USE_FREETYPE
928 //----------------------------------------------------------------------------
929 // a2dFontFreetypeData
930 //----------------------------------------------------------------------------
931 //----------------------------------------------------------------------------
932 // a2dFontFreetypeData
933 //----------------------------------------------------------------------------
934 
935 //! Freetype font class.
936 /*! \class a2dFontFreetypeData stylebase.h artbase/stylebase.h
937  \ingroup property style
938  \ingroup textrelated
939 */
940 class A2DARTBASEDLLEXP a2dFontFreetypeData
941  : public a2dFontRefData
942 {
943  friend class a2dFont;
944 public:
945 
946  virtual a2dFontType GetType( void ) const { return a2dFONT_FREETYPE; }
947 
948  //! Constructor.
949  /*! \param filename Filename of the vector font.
950  \param size Size in world coordinates.
951  \param encoding endocing of font
952  */
953  a2dFontFreetypeData( const wxString& filename = wxT( "" ), double size = 0.0, wxFontEncoding encoding = wxFONTENCODING_DEFAULT, int faceindex = 0 );
954 #if defined(__USE_WINAPI__)
955  //! Constructor.
956  /*! This constructor tries to locate the font file, belonging to the wxFont class, which
957  is then used for drawing. At present only a Windows version is implemented.
958  \param font wxFont class, to be used as the vector font.
959  \param size Size in world coordinates.
960  \param encoding endocing of font
961  */
962  a2dFontFreetypeData( const wxFont& font, double size = 0.0, wxFontEncoding encoding = wxFONTENCODING_DEFAULT );
963 #endif // defined( __USE_WINAPI__ )
964 
965  //! Copy constructor.
967 
968  //! Destructor.
969  virtual ~a2dFontFreetypeData();
970 
971  //! Set the font filename and load the font.
972  /*! \param filename The filename of the font. This may either be a full path, or just the
973  fontname. In the latter case, the fontpath of a2dGlobals will be used to search the font.
974  \sa a2dGlobal
975  */
976  void SetFilename( const wxString& filename );
977  //! Get the font filename.
978  /*! \param filenameonly The returned filename will be stripped of drive-letters and directories.
979  \return The filename of the font.
980  */
981  wxString GetFilename( bool filenameonly = false ) const;
982 
983  void SetEncodingConverter( wxEncodingConverter* converter );
984 
985  //! Get the glyph of a single character.
986  /*! \return The glyph of the character, in a coordinate space, normalized to a font size m_sizeInPixels.
987  */
988  const a2dGlyph* GetGlyph( wxChar c ) const;
989 
990  //! to set for load glyph from face, to do proper hinting
991  void SetDeviceHeight( double sizeInPixels );
992 
993  double GetDeviceHeight() { return m_sizeInPixels; }
994 
995  void GetTextExtent( const wxString& string, double& w, double& h, double& descent, double& externalLeading ) const;
996 
997  // Documented in base class
998  double GetWidth( wxChar c ) const;
999 
1000  double GetGlyphHeight( wxChar c ) const;
1001 
1002  // Documented in base class
1003  double GetKerning( wxChar c1, wxChar c2 ) const;
1004 
1005  // Documented in base class
1006  bool GetVpath( wxChar c, a2dVpath& glyph, const a2dAffineMatrix& affine = a2dIDENTITY_MATRIX );
1007 
1008  // Documented in base class
1009  static void GetInfoList( a2dFontInfoList& list );
1010 
1011  // Documented in base class
1012  static a2dFontFreetypeData* CreateFont( const a2dFontInfo& info, bool force = false );
1013 
1014  //! Set the way glyphs are loaded by freetype. Important for small fonts.
1015  //! a2d_LOAD_DEFAULT;
1016  //! a2d_LOAD_DEFAULT | a2d_LOAD_NO_HINTING;
1017  //! a2d_LOAD_DEFAULT | a2d_LOAD_FORCE_AUTOHINT;
1018  static void SetLoadFlags( wxInt32 loadMethodMask ) { m_loadMethodMask = loadMethodMask; }
1019 
1020 protected:
1021 
1022  static wxInt32 m_loadMethodMask;
1023 
1024  //! Filename of the vector font.
1025  wxString m_filename;
1026 
1027  //! Glyph Cache. This stores the 'normal' part of the alphabet.
1028  typedef vector< a2dGlyph > a2dGlyphCache;
1029  mutable a2dGlyphCache m_glyphcache;
1030  //! Glyph cache. This stores the extended characters.
1031  mutable a2dGlyphHash m_extglyphcache;
1032 
1033  //mutable map< int, a2dGlyphCacheHash > m_glyphcacheOnDevHeight;
1034 
1035 #if wxART2D_USE_FREETYPE
1036  //! last character for glyph cache one character
1037  mutable wxChar m_lastChar;
1038  //! Glyph cache one last character
1040 #endif // wxART2D_USE_FREETYPE
1041 
1042  //! freetypelib face struct.
1043  FT_Face m_face;
1044 
1045  //! encoding setting
1046  wxFontEncoding m_encoding;
1047 
1048  //! current text drawn its size in pixels to do proper hinting.
1050 
1051  //! what font with index to load from file
1053 
1054  //! encoding converter
1055  wxEncodingConverter* m_converter;
1056 
1057  void ClearCacheLinkes( void );
1058 };
1059 
1060 wxInt32 a2dFontFreetypeData::m_loadMethodMask = a2dFont::a2d_LOAD_DEFAULT;
1061 
1062 a2dFontFreetypeData::a2dFontFreetypeData( const wxString& filename, double size, wxFontEncoding encoding, int faceindex )
1063  : a2dFontRefData( size )
1064 {
1066  m_fontinfo.SetType( wxT( "Freetype font" ) );
1067  m_face = NULL;
1068  m_converter = NULL;
1069  m_encoding = encoding;
1070 #if wxART2D_USE_FREETYPE
1071  m_lastChar = ( wxChar ) - 1;
1072  m_a2dLastGlyph = NULL;
1073 #endif
1074 
1075  if( m_encoding != wxFONTENCODING_DEFAULT )
1076  {
1077  m_converter = new wxEncodingConverter();
1078  wxASSERT( m_converter != NULL );
1079  if( !m_converter->Init( m_encoding, wxFONTENCODING_UNICODE ) )
1080  {
1081  delete m_converter;
1082  m_converter = NULL;
1083 // m_encoding = wxFONTENCODING_DEFAULT;
1084  }
1085  }
1086  m_faceindex = faceindex;
1087  SetFilename( filename );
1088 }
1089 
1090 #if defined(__USE_WINAPI__)
1091 a2dFontFreetypeData::a2dFontFreetypeData( const wxFont& font, double size, wxFontEncoding encoding )
1092  : a2dFontRefData( size )
1093 {
1095  m_fontinfo.SetType( wxT( "Freetype font" ) );
1096  m_face = NULL;
1097  m_converter = NULL;
1098  m_encoding = encoding;
1099 #if wxART2D_USE_FREETYPE
1100  m_lastChar = ( wxChar ) - 1;
1101  m_a2dLastGlyph = NULL;
1102 #endif
1103 
1104  if( m_encoding != wxFONTENCODING_DEFAULT )
1105  {
1106  m_converter = new wxEncodingConverter();
1107  wxASSERT( m_converter != NULL );
1108  if( !m_converter->Init( m_encoding, wxFONTENCODING_UNICODE ) )
1109  {
1110  delete m_converter;
1111  m_converter = NULL;
1112  // m_encoding = wxFONTENCODING_DEFAULT;
1113  }
1114  }
1115 
1116  wxString filename;
1117  wxString facename = font.GetFaceName();
1118  if ( font.GetWeight() == wxBOLD )
1119  facename += wxT( " Bold" );
1120  if ( font.GetStyle() == wxITALIC )
1121  facename += wxT( " Italic" );
1122 
1123  m_faceindex = 0;
1124 
1125  TCHAR displayname[10];
1126  TCHAR fontfilename[_MAX_PATH];
1127 
1128  if( GetFontFile( facename.c_str(), displayname, sizeof( displayname ),
1129  fontfilename, sizeof( fontfilename ) ) )
1130  {
1131  SetFilename( fontfilename );
1132  }
1133 }
1134 #endif // defined( __USE_WINAPI__ )
1135 
1137  : a2dFontRefData( other )
1138 {
1140  m_face = NULL;
1141  m_converter = NULL;
1142  m_encoding = other.m_encoding;
1143  m_faceindex = other.m_faceindex;
1144 #if wxART2D_USE_FREETYPE
1145  m_lastChar = ( wxChar ) - 1;
1146  m_a2dLastGlyph = NULL;
1147 #endif
1148 
1149  if( m_encoding != wxFONTENCODING_DEFAULT )
1150  {
1151  m_converter = new wxEncodingConverter();
1152  wxASSERT( m_converter != NULL );
1153  if( !m_converter->Init( m_encoding, wxFONTENCODING_UNICODE ) )
1154  {
1155  delete m_converter;
1156  m_converter = NULL;
1157  // m_encoding = wxFONTENCODING_DEFAULT;
1158  }
1159  }
1160  SetFilename( other.m_filename );
1161 }
1162 
1164 {
1165 #if wxART2D_USE_FREETYPE
1166  // free cache.
1167  ClearCacheLinkes();
1168  m_extglyphcache.clear();
1169  // release face.
1170  if ( m_face && g_freetypeLibrary )
1171  FT_Done_Face( m_face );
1172 
1173 #endif // wxART2D_USE_FREETYPE
1174  if( m_converter )
1175  delete m_converter;
1176 }
1177 
1178 void a2dFontFreetypeData::SetDeviceHeight( double sizeInPixels )
1179 {
1180  if ( fabs(m_sizeInPixels - sizeInPixels) > 0.0001 )
1181  {
1182  m_sizeInPixels = sizeInPixels;
1183  if ( m_sizeInPixels < 1 )
1184  m_sizeInPixels = 1;
1185 
1186  //SetFilename( m_filename );
1187 
1188 #if wxART2D_USE_FREETYPE
1189  int error;
1190  //The character widths and heights are specified in 1/64th of points.
1191  //A point is a physical distance, equaling 1/72th of an inch. Normally, it is not equivalent to a pixel.
1192  error = FT_Set_Pixel_Sizes( m_face, 0, ( int ) m_sizeInPixels );
1193  //error = FT_Set_Char_Size( m_face, 0, m_sizeInPixels * 64, 96, 96 );// screen dpi
1194 
1195  wxASSERT_MSG( error == 0 , _( "a2dText problem setting character size" ) );
1196  if ( error )
1197  {
1198  m_face = NULL;
1199  return;
1200  }
1201  const FT_Size_Metrics& size = m_face->size->metrics;
1202  m_height = ( size.ascender - size.descender ) / ( m_sizeInPixels * 64.0 );
1203  m_desc = -size.descender / ( m_sizeInPixels * 64.0 );
1204  m_lead = ( size.height - ( size.ascender - size.descender ) ) / ( m_sizeInPixels * 64.0 );
1205 
1206 #else //wxART2D_USE_FREETYPE
1207  // reasonable estimate
1208  m_height = 1.6;
1209  m_desc = 0.3;
1210  m_lead = 0.0;
1211 #endif // wxART2D_USE_FREETYPE
1212 
1213  // If cache did not exist, create it.
1214  if ( m_glyphcache.empty() )
1215  {
1216  m_glyphcache.reserve( CHAR_CACHE_END - CHAR_CACHE_START + 1 );
1217  for ( size_t i = CHAR_CACHE_START; i <= CHAR_CACHE_END; i++ )
1218  m_glyphcache.push_back( a2dGlyph() );
1219  }
1220  ClearCacheLinkes();
1221  //clear previous cache
1222  for ( size_t i = CHAR_CACHE_START; i <= CHAR_CACHE_END; i++ )
1223  if( m_glyphcache[i - CHAR_CACHE_START].m_glyph != NULL )
1224  FT_Done_Glyph( m_glyphcache[i - CHAR_CACHE_START].m_glyph );
1225  // Clear cache.
1226  for ( size_t j = CHAR_CACHE_START; j <= CHAR_CACHE_END; j++ )
1227  m_glyphcache[j - CHAR_CACHE_START].m_glyph = NULL;
1228 
1229  m_extglyphcache.clear();
1230  }
1231 }
1232 
1233 wxString a2dFontFreetypeData::GetFilename( bool filenameonly ) const
1234 {
1235  if ( filenameonly )
1236  {
1237  wxFileName filename( m_filename );
1238  return filename.GetFullName();
1239  }
1240  else
1241  return m_filename;
1242 }
1243 
1244 void a2dFontFreetypeData::ClearCacheLinkes( void )
1245 {
1246 #if wxART2D_USE_FREETYPE
1247  m_lastChar = ( wxChar ) - 1;
1248  m_a2dLastGlyph = NULL;
1249 #endif
1250  int qpos = wxChar( '?' ) - CHAR_CACHE_START;
1251  if( m_glyphcache[qpos].m_glyph != NULL && m_glyphcache[qpos].m_glyph != ( FT_Glyph ) - 1 )
1252  {
1253  size_t index = m_glyphcache[qpos].m_index;
1254  for ( size_t i = CHAR_CACHE_START; i <= CHAR_CACHE_END; i++ )
1255  if( m_glyphcache[i - CHAR_CACHE_START].m_index == index )
1256  m_glyphcache[i - CHAR_CACHE_START].m_glyph = NULL;
1257 
1258  a2dGlyphHash::iterator it = m_extglyphcache.begin();
1259  for( ; it != m_extglyphcache.end(); it++ )
1260  {
1261  if( it->second.m_index == index )
1262  it->second.m_glyph = NULL;
1263  }
1264  }
1265 }
1266 
1267 void a2dFontFreetypeData::SetFilename( const wxString& filename )
1268 {
1269  if (m_filename == filename)
1270  {
1271  m_ok = true;
1272  return;
1273  }
1274  m_filename = filename;
1275 
1276 #if wxART2D_USE_FREETYPE
1277  if ( m_face )
1278  {
1279  FT_Done_Face( m_face );
1280  m_face = NULL;
1281  }
1282  m_ok = false;
1283 
1284  // If cache did not exist, create it.
1285  if ( m_glyphcache.empty() )
1286  {
1287  m_glyphcache.reserve( CHAR_CACHE_END - CHAR_CACHE_START + 1 );
1288  for ( size_t i = CHAR_CACHE_START; i <= CHAR_CACHE_END; i++ )
1289  m_glyphcache.push_back( a2dGlyph() );
1290  }
1291  ClearCacheLinkes();
1292  //clear previous cache
1293  for ( size_t i = CHAR_CACHE_START; i <= CHAR_CACHE_END; i++ )
1294  if( m_glyphcache[i - CHAR_CACHE_START].m_glyph != NULL )
1295  FT_Done_Glyph( m_glyphcache[i - CHAR_CACHE_START].m_glyph );
1296  // Clear cache.
1297  for ( size_t j = CHAR_CACHE_START; j <= CHAR_CACHE_END; j++ )
1298  m_glyphcache[j - CHAR_CACHE_START].m_glyph = NULL;
1299 
1300  m_extglyphcache.clear();
1301 
1302  if ( filename.IsEmpty() )
1303  {
1304  a2dGeneralGlobals->ReportErrorF( a2dError_FileCouldNotOpen, _( "Font file path is empty" ) );
1305  return;
1306  }
1307 
1308  wxString fname = a2dGlobals->GetFontPathList().FindValidPath( m_filename );
1309  if ( !::wxFileExists( fname ) )
1310  {
1311  a2dGeneralGlobals->ReportErrorF( a2dError_FileCouldNotOpen, _( "Sorry, could not open file %s for loading font" ), m_filename.c_str() );
1312  return;
1313  }
1314 
1315  FT_Error error;
1316  error = FT_New_Face( g_freetypeLibrary, fname.mb_str(), m_faceindex, &m_face );
1317  if ( error )
1318  {
1319  a2dGeneralGlobals->ReportErrorF( a2dError_FileCouldNotOpen, _( "file %s contains wrong font" ), m_filename.c_str() );
1320  m_face = NULL;
1321  return;
1322  }
1323  else if ( !( m_face->face_flags & FT_FACE_FLAG_SCALABLE ) )
1324  {
1325  a2dGeneralGlobals->ReportErrorF( a2dError_FileCouldNotOpen, _( "file %s contains non scalable font" ), m_filename.c_str() );
1326  m_face = NULL;
1327  return;
1328  }
1329 
1330  //The character widths and heights are specified in 1/64th of points.
1331  //A point is a physical distance, equaling 1/72th of an inch. Normally, it is not equivalent to a pixel.
1332  error = FT_Set_Pixel_Sizes( m_face, 0, ( int ) m_sizeInPixels );
1333  //error = FT_Set_Char_Size( m_face, 0, (int) m_sizeInPixels * 64, 96, 96 );// screen dpi
1334 
1335  wxASSERT_MSG( error == 0 , _( "a2dText problem setting character size" ) );
1336  if ( error )
1337  {
1338  m_face = NULL;
1339  return;
1340  }
1341 
1342  const FT_Size_Metrics& size = m_face->size->metrics;
1343  m_height = ( size.ascender - size.descender ) / ( m_sizeInPixels * 64.0 );
1344  m_desc = -size.descender / ( m_sizeInPixels * 64.0 );
1345  m_lead = ( size.height - ( size.ascender - size.descender ) ) / ( m_sizeInPixels * 64.0 );
1346 
1347  m_fontinfo.SetName( wxString::FromAscii( m_face->family_name ) );
1348  m_fontinfo.SetStyle( wxString::FromAscii( m_face->style_name ) );
1349  m_fontinfo.SetExtra( GetFilename( true ) );
1350 #else //wxART2D_USE_FREETYPE
1351  // reasonable estimate
1352  m_height = 1.6;
1353  m_desc = 0.3;
1354  m_lead = 0.0;
1355 #endif // wxART2D_USE_FREETYPE
1356  m_ok = true;
1357 }
1358 
1359 const a2dGlyph* a2dFontFreetypeData::GetGlyph( wxChar cinput ) const
1360 {
1361 #if wxART2D_USE_FREETYPE
1362  if( cinput == m_lastChar )
1363  return m_a2dLastGlyph;
1364 
1365  if ( !m_face )
1366  return NULL;
1367 
1368  // if character is a 'normal' ascii character, use lookup-table.
1369  if ( cinput >= CHAR_CACHE_START && cinput <= CHAR_CACHE_END )
1370  {
1371  a2dGlyph* a2dglyph = &m_glyphcache[cinput - CHAR_CACHE_START];
1372  FT_Glyph glyph = a2dglyph->m_glyph;
1373  if ( !glyph )
1374  {
1375  wchar_t wc = ( wchar_t )cinput;
1376 
1377  if( m_converter )
1378  {
1379 #if wxUSE_WCHAR_T
1380  wxChar cinputstr[2];
1381  wchar_t wcstr[2];
1382  cinputstr[0] = cinput;
1383  cinputstr[1] = 0;
1384  m_converter->Convert( cinputstr, wcstr );
1385  wc = wcstr[0];
1386 #else
1387  wc = m_converter->Convert( wxString( cinput ) ).Last();
1388 #endif
1389  }
1390 
1391  FT_ULong c = ( FT_ULong ) wc;
1392 
1393  FT_UInt index = FT_Get_Char_Index( m_face, ( FT_ULong ) c );
1394  /* load the glyph image (in its native format) */
1395  int error;
1396  error = FT_Load_Glyph( m_face, index, m_loadMethodMask );
1397  wxASSERT_MSG( error == 0 , _( "Glyph could not be loaded" ) );
1398  if ( !error )
1399  {
1400  error = FT_Get_Glyph( m_face->glyph, &glyph );
1401  wxASSERT_MSG( error == 0 , _( "Glyph could not be get" ) );
1402  if ( error )
1403  glyph = NULL;
1404  }
1405  if ( glyph )
1406  glyph->advance = m_face->glyph->advance;
1407  if ( !glyph )
1408  {
1409  glyph = ( FT_Glyph ) - 1;
1410  if ( c != wxChar( '?' ) )
1411  {
1412  const a2dGlyph* glyphErr = GetGlyph( wxChar( '?' ) );
1413  if( glyphErr )
1414  {
1415  index = a2dglyph->m_index;
1416  glyph = glyphErr->m_glyph;
1417  }
1418  }
1419  }
1420  a2dglyph->m_index = index;
1421  a2dglyph->m_glyph = glyph;
1422  a2dglyph->m_lsb = m_face->glyph->lsb_delta;
1423  a2dglyph->m_rsb = m_face->glyph->rsb_delta;
1424  a2dglyph->m_face = m_face;
1425  }
1426  if ( glyph == ( FT_Glyph ) - 1 )
1427  a2dglyph = NULL;
1428 
1429  m_lastChar = cinput;
1430  m_a2dLastGlyph = a2dglyph;
1431 
1432  return a2dglyph;
1433  }
1434  else
1435  {
1436  a2dGlyph* a2dglyph = &m_extglyphcache[cinput];
1437  FT_Glyph glyph = a2dglyph->m_glyph;
1438  if ( !glyph )
1439  {
1440  wchar_t wc = ( wchar_t )cinput;
1441 
1442  if( m_converter )
1443  {
1444 #if wxUSE_WCHAR_T
1445  wxChar cinputstr[2];
1446  wchar_t wcstr[2];
1447  cinputstr[0] = cinput;
1448  cinputstr[1] = 0;
1449  m_converter->Convert( cinputstr, wcstr );
1450  wc = wcstr[0];
1451 #else
1452  wc = m_converter->Convert( wxString( cinput ) ).Last();
1453 #endif
1454  }
1455  FT_ULong c = ( FT_ULong ) wc;
1456  int error;
1457  FT_UInt index = FT_Get_Char_Index( m_face, ( FT_ULong ) c );
1458  /* load the glyph image (in its native format) */
1459  error = FT_Load_Glyph( m_face, index, m_loadMethodMask );
1460  wxASSERT_MSG( error == 0 , _( "Glyph could not be loaded" ) );
1461  if ( !error )
1462  {
1463  error = FT_Get_Glyph( m_face->glyph, &glyph );
1464  wxASSERT_MSG( error == 0 , _( "Glyph could not be get" ) );
1465  if ( error )
1466  glyph = NULL;
1467  }
1468  if ( glyph )
1469  glyph->advance = m_face->glyph->advance;
1470 
1471  if ( !glyph )
1472  {
1473  glyph = ( FT_Glyph ) - 1;
1474  if ( c != wxChar( '?' ) )
1475  {
1476  const a2dGlyph* glyphErr = GetGlyph( wxChar( '?' ) );
1477  if( glyphErr )
1478  {
1479  index = glyphErr->m_index;
1480  glyph = glyphErr->m_glyph;
1481  }
1482  }
1483  }
1484  a2dglyph->m_index = index;
1485  a2dglyph->m_glyph = glyph;
1486  a2dglyph->m_lsb = m_face->glyph->lsb_delta;
1487  a2dglyph->m_rsb = m_face->glyph->rsb_delta;
1488  a2dglyph->m_face = m_face;
1489  }
1490  if ( glyph == ( FT_Glyph ) - 1 )
1491  a2dglyph = NULL;
1492 
1493  m_lastChar = cinput;
1494  m_a2dLastGlyph = a2dglyph;
1495 
1496  return a2dglyph;
1497  }
1498 #else // wxART2D_USE_FREETYPE
1499  return NULL;
1500 #endif // wxART2D_USE_FREETYPE
1501 }
1502 
1503 void a2dFontFreetypeData::GetTextExtent( const wxString& string, double& w,
1504  double& h, double& descent, double& externalLeading ) const
1505 {
1506  if ( m_ok )
1507  {
1508  const a2dGlyph* a2dglyphprev = NULL;
1509  double x = 0.0;
1510 #if wxUSE_UNICODE
1511  const wxStringCharType *cp(string.wx_str());
1512 #else
1513  const wxChar* cp(string.c_str());
1514 #endif // wxUSE_UNICODE
1515  for ( size_t n = 0; n < string.Length(); n++ )
1516  {
1517  wxChar c = *cp++;
1518  const a2dGlyph* a2dglyph = GetGlyph( c );
1519  // The glyph is now grid fitted and hinted.
1520  if( !a2dglyph )
1521  return;
1522 
1523  if ( n > 0 )
1524  {
1525  FT_Face face = a2dglyph->m_face;
1526  FT_Vector kern;
1527  FT_Get_Kerning( a2dglyph->m_face, a2dglyphprev->m_index, a2dglyph->m_index, FT_KERNING_DEFAULT, &kern );
1528  x += kern.x / 64.0;
1529 
1530  if ( a2dglyphprev->m_rsb - a2dglyph->m_lsb >= 32 )
1531  x -= 1;
1532  else if ( a2dglyphprev->m_rsb - a2dglyph->m_lsb < -32 )
1533  x += 1;
1534 
1535  }
1536  a2dglyphprev = a2dglyph;
1537  FT_Glyph glyphimage = a2dglyph->m_glyph;
1538  x += glyphimage->advance.x / 64.0;
1539  }
1540  if ( m_sizeInPixels == NORMFONT )
1541  x += 10; //bbox is a bit to small after hinting at device level, we add a view normalized pixel here.
1542  else
1543  x += 1; //bbox is a bit to small after hinting at device level, we add a X pixels here.
1544  // scale = GetSize() / m_sizeInPixels;
1545  w = GetSize() * x / m_sizeInPixels;
1546  h = GetSize() * m_height;
1547  descent = GetSize() * m_desc;
1548  externalLeading = GetSize() * m_lead;
1549  }
1550  else
1551  w = h = descent = externalLeading = 0.0;
1552 
1553  /* less accurate because fo rounding
1554  if ( m_ok )
1555  {
1556  double x = 0.0;
1557  //double y = 0.0;
1558  for ( size_t n = 0; n < string.Length(); n++ )
1559  {
1560  if ( n > 0 )
1561  x += GetKerning( string[n-1], string[n] );
1562  x += GetWidth( string[n] );
1563  //y = max( GetGlyphHeight( string[n] ), y );
1564  }
1565  w = x;
1566  //h = y;
1567  h = GetSize() * m_height;
1568  descent = GetSize() * m_desc;
1569  externalLeading = GetSize() * m_lead;
1570  }
1571  else
1572  w = h = descent = externalLeading = 0.0;
1573  */
1574 }
1575 
1576 double a2dFontFreetypeData::GetWidth( wxChar c ) const
1577 {
1578 #if wxART2D_USE_FREETYPE
1579  if ( m_face )
1580  {
1581  const a2dGlyph* a2dglyph = GetGlyph( c );
1582  if( a2dglyph )
1583  {
1584  FT_Glyph glyphimage = a2dglyph->m_glyph;
1585  return glyphimage->advance.x * m_fontinfo.GetSize() / ( 64.0 * m_sizeInPixels );
1586  }
1587  }
1588  return 0.0;
1589 #else //wxART2D_USE_FREETYPE
1590  // reasonable estimate
1591  return m_fontinfo.GetSize() * 0.25;
1592 #endif //wxART2D_USE_FREETYPE
1593 }
1594 
1595 double a2dFontFreetypeData::GetGlyphHeight( wxChar c ) const
1596 {
1597 #if wxART2D_USE_FREETYPE
1598  if ( m_face )
1599  {
1600  const a2dGlyph* a2dglyph = GetGlyph( c );
1601  if( a2dglyph )
1602  {
1603  FT_Glyph glyphimage = a2dglyph->m_glyph;
1604  return m_face->glyph->metrics.height * m_fontinfo.GetSize() / ( 64.0 * m_sizeInPixels );
1605  }
1606  }
1607  return 0.0;
1608 #else //wxART2D_USE_FREETYPE
1609  // reasonable estimate
1610  return m_fontinfo.GetSize() * 0.25;
1611 #endif //wxART2D_USE_FREETYPE
1612 }
1613 
1614 double a2dFontFreetypeData::GetKerning( wxChar cinput1, wxChar cinput2 ) const
1615 {
1616 #if wxART2D_USE_FREETYPE
1617  FT_Vector kern;
1618  if ( !m_face )
1619  return 0.0;
1620 
1621  const a2dGlyph* a2dglyph1 = GetGlyph( cinput1 );
1622  if( !a2dglyph1 )
1623  return 0.0;
1624  const a2dGlyph* a2dglyph2 = GetGlyph( cinput2 );
1625  if( !a2dglyph2 )
1626  return 0.0;
1627 
1628  //if ( FT_Get_Kerning( m_face, a2dglyph1->m_index, a2dglyph2->m_index, FT_KERNING_UNFITTED, &kern ) )
1629  if ( FT_Get_Kerning( m_face, a2dglyph1->m_index, a2dglyph2->m_index, FT_KERNING_DEFAULT, &kern ) )
1630  return 0.0;
1631  else
1632  {
1633  double rsblsbshift = 0;
1634 
1635  if ( a2dglyph1->m_rsb - a2dglyph2->m_lsb >= 32 )
1636  rsblsbshift -= 64;
1637  else if ( a2dglyph1->m_rsb - a2dglyph2->m_lsb < -32 )
1638  rsblsbshift += 64;
1639 
1640  return ( ( rsblsbshift + kern.x ) * m_fontinfo.GetSize() ) / ( 64.0 * m_sizeInPixels );
1641  }
1642 #else //wxART2D_USE_FREETYPE
1643  return 0.0;
1644 #endif //wxART2D_USE_FREETYPE
1645 }
1646 
1647 static double fscale = 0;
1648 static double fx = 0;
1649 static double fy = 0;
1650 
1651 int MoveToFunc( const FT_Vector* to, void* user )
1652 {
1653  a2dVpath* vpath = ( a2dVpath* ) user;
1654  if ( vpath->size() )
1655  vpath->back()->SetClose( a2dPATHSEG_END_CLOSED );
1656  vpath->MoveTo( fx + fscale * to->x , fy + fscale * to->y );
1657  return 0;
1658 }
1659 
1660 int LineToFunc( const FT_Vector* to, void* user )
1661 {
1662  a2dVpath* vpath = ( a2dVpath* ) user;
1663  vpath->LineTo( fx + fscale * to->x , fy + fscale * to->y );
1664 
1665  return 0;
1666 }
1667 
1668 int ConicToFunc( const FT_Vector* control,
1669  const FT_Vector* to,
1670  void* user )
1671 {
1672  a2dVpath* vpath = ( a2dVpath* ) user;
1673  vpath->QBCurveTo( fx + fscale * to->x, fy + fscale * to->y, fx + fscale * control->x, fy + fscale * control->y );
1674 
1675  return 0;
1676 }
1677 
1678 int CubicToFunc( const FT_Vector* control1,
1679  const FT_Vector* control2,
1680  const FT_Vector* to,
1681  void* user )
1682 {
1683  a2dVpath* vpath = ( a2dVpath* ) user;
1684  //vpath->LineTo( fx + fscale*to->x , fy + fscale*to->y );
1685  vpath->CBCurveTo( fx + fscale * to->x, fy + fscale * to->y, fx + fscale * control2->x, fy + fscale * control2->y,
1686  fx + fscale * control2->x, fy + fscale * control2->y );
1687 
1688  return 0;
1689 }
1690 
1691 
1692 bool a2dFontFreetypeData::GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine )
1693 {
1694 #if wxART2D_USE_FREETYPE
1695  double x = affine.GetValue( 2, 0 );
1696  double y = affine.GetValue( 2, 1 );
1697  y += GetDescent();
1698 
1699  double scale = GetSize() / ( 64.0 * m_sizeInPixels );
1700 
1701  const a2dGlyph* a2dglyph = GetGlyph( c );
1702  if( !a2dglyph )
1703  return false;
1704  FT_Glyph glyph = a2dglyph->m_glyph;
1705  if ( glyph->format != FT_GLYPH_FORMAT_OUTLINE )
1706  return false;
1707  FT_Outline& outline = ( ( FT_OutlineGlyph ) glyph )->outline;
1708 
1709  FT_Vector v_last;
1710  FT_Vector v_control;
1711  FT_Vector v_start;
1712 
1713  FT_Vector* point;
1714  FT_Vector* limit;
1715  char* tags;
1716 
1717  int n; // index of contour in outline
1718  int first; // index of first point in contour
1719  char tag; // current point's state
1720 
1721  first = 0;
1722 
1723  /*
1724  FT_Outline_Funcs segmentCallBack;
1725  segmentCallBack.move_to = &::MoveToFunc;
1726  segmentCallBack.line_to = &::LineToFunc;
1727  segmentCallBack.conic_to = &::ConicToFunc;
1728  segmentCallBack.cubic_to = &::CubicToFunc;
1729  segmentCallBack.shift = 0;
1730  segmentCallBack.delta = 0;
1731  fscale = scale;
1732  fx = x;
1733  fy = y;
1734 
1735  FT_Outline_Decompose( &outline, &segmentCallBack, &vpath );
1736  a2dAffineMatrix affinesize;
1737  affinesize.Scale( scale, scale, 0, 0 );
1738 
1739  */
1740  //as in FT_Outline_Decompose, but for wxArt2D
1741  for( n = 0; n < outline.n_contours; n++ )
1742  {
1743  int last; // index of last point in contour
1744 
1745  last = outline.contours[n];
1746  limit = outline.points + last;
1747 
1748  v_start = outline.points[first];
1749  v_last = outline.points[last];
1750 
1751  v_control = v_start;
1752 
1753  point = outline.points + first;
1754  tags = outline.tags + first;
1755  tag = FT_CURVE_TAG( tags[0] );
1756 
1757  // A contour cannot start with a cubic control point!
1758  if( tag == FT_CURVE_TAG_CUBIC ) return false;
1759 
1760  // check first point to determine origin
1761  if( tag == FT_CURVE_TAG_CONIC )
1762  {
1763  // first point is conic control. Yes, this happens.
1764  if( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
1765  {
1766  // start at last point if it is on the curve
1767  v_start = v_last;
1768  limit--;
1769  }
1770  else
1771  {
1772  // if both first and last points are conic,
1773  // start at their middle and record its position
1774  // for closure
1775  v_start.x = ( v_start.x + v_last.x ) / 2;
1776  v_start.y = ( v_start.y + v_last.y ) / 2;
1777 
1778  v_last = v_start;
1779  }
1780  point--;
1781  tags--;
1782  }
1783 
1784  vpath.MoveTo( x + scale * v_start.x, y + scale * v_start.y );
1785 
1786  while( point < limit )
1787  {
1788  point++;
1789  tags++;
1790 
1791  tag = FT_CURVE_TAG( tags[0] );
1792  switch( tag )
1793  {
1794  case FT_CURVE_TAG_ON: // emit a single line_to
1795  {
1796  vpath.LineTo( x + scale * point->x, y + scale * point->y );
1797  continue;
1798  }
1799 
1800  case FT_CURVE_TAG_CONIC: // consume conic arcs
1801  {
1802  v_control.x = point->x;
1803  v_control.y = point->y;
1804 
1805 Do_Conic:
1806  if( point < limit )
1807  {
1808  FT_Vector vec;
1809  FT_Vector v_middle;
1810 
1811  point++;
1812  tags++;
1813  tag = FT_CURVE_TAG( tags[0] );
1814 
1815  vec.x = point->x;
1816  vec.y = point->y;
1817 
1818  if( tag == FT_CURVE_TAG_ON )
1819  {
1820  //vpath.LineTo( x + scale * vec.x, y + scale * vec.y );
1821  vpath.QBCurveTo( x + scale * vec.x, y + scale * vec.y, x + scale * v_control.x, y + scale * v_control.y );
1822  continue;
1823  }
1824 
1825  if( tag != FT_CURVE_TAG_CONIC ) return false;
1826 
1827  v_middle.x = ( v_control.x + vec.x ) / 2;
1828  v_middle.y = ( v_control.y + vec.y ) / 2;
1829 
1830  vpath.QBCurveTo( x + scale * v_middle.x, y + scale * v_middle.y, x + scale * v_control.x, y + scale * v_control.y );
1831 
1832  v_control = vec;
1833  goto Do_Conic;
1834  }
1835  vpath.QBCurveTo( x + scale * v_start.x, y + scale * v_start.y, x + scale * v_control.x, y + scale * v_control.y );
1836  vpath.Close();
1837  goto Close;
1838  }
1839 
1840  default: // FT_CURVE_TAG_CUBIC
1841  {
1842  FT_Vector vec1, vec2;
1843 
1844  if( point + 1 > limit || FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1845  {
1846  return false;
1847  }
1848 
1849  vec1.x = point[0].x;
1850  vec1.y = point[0].y;
1851  vec2.x = point[1].x;
1852  vec2.y = point[1].y;
1853 
1854  point += 2;
1855  tags += 2;
1856 
1857  if( point <= limit )
1858  {
1859  FT_Vector vec;
1860 
1861  vec.x = point->x;
1862  vec.y = point->y;
1863 
1864  vpath.CBCurveTo( x + scale * vec1.x, y + scale * vec1.y,
1865  x + scale * vec2.x, y + scale * vec2.y,
1866  x + scale * vec.x, y + scale * vec.y );
1867  continue;
1868  }
1869 
1870  vpath.CBCurveTo( x + scale * vec1.x, y + scale * vec1.y,
1871  x + scale * vec2.x, y + scale * vec2.y,
1872  x + scale * v_start.x, y + scale * v_start.y );
1873  vpath.Close();
1874  goto Close;
1875  }
1876  }
1877  }
1878 
1879  vpath.LineTo( x + scale * v_start.x, y + scale * v_start.y, true );
1880  vpath.Close();
1881 
1882 Close:
1883  first = last + 1;
1884  }
1885  return true;
1886 #else //wxART2D_USE_FREETYPE
1887  return false;
1888 #endif //wxART2D_USE_FREETYPE
1889 }
1890 
1891 void a2dFontFreetypeData::GetInfoList( a2dFontInfoList& list )
1892 {
1893 #if wxART2D_USE_FREETYPE
1894  wxPathList& pathlist = a2dGlobals->GetFontPathList();
1895 #if wxCHECK_VERSION(2,7,0)
1896  for ( wxPathList::iterator node = pathlist.begin(); node != pathlist.end(); node++ )
1897 #else
1898  for ( wxPathList::compatibility_iterator node = pathlist.GetFirst(); node; node = node->GetNext() )
1899 #endif
1900  {
1901  wxString path( node->GetData() );
1902  if ( !wxDir::Exists( path ) )
1903  continue;
1904  wxArrayString files;
1905  wxDir::GetAllFiles( path, &files, wxT( "*.ttf" ), wxDIR_FILES );
1906  for ( unsigned int i = 0; i < files.GetCount(); i++ )
1907  {
1908  FT_Error error;
1909  FT_Face face;
1910  error = FT_New_Face( g_freetypeLibrary, files.Item( i ).mb_str(), 0, &face );
1911  if ( error )
1912  continue;
1913  list.Append( new a2dFontInfo( wxT( "Freetype font" ),
1914  wxString::FromAscii( face->family_name ),
1915  wxString::FromAscii( face->style_name ),
1916  1.0, files.Item( i ) ) );
1917  FT_Done_Face( face );
1918  }
1919  }
1920 #else
1921  wxUnusedVar( list );
1922 #endif
1923 }
1924 
1925 a2dFontFreetypeData* a2dFontFreetypeData::CreateFont( const a2dFontInfo& info, bool force )
1926 {
1927 #if wxART2D_USE_FREETYPE
1928  if ( force || info.GetType().Upper() == wxT( "FREETYPE FONT" ) )
1929  {
1930  a2dFontFreetypeData* font = NULL;
1931  if ( !force && !info.GetExtra().IsEmpty() )
1932  {
1933  // try to open supplied filename
1934  font = new a2dFontFreetypeData( info.GetExtra(), info.GetSize() );
1935  if ( font )
1936  {
1937  if ( font->Ok() )
1938  return font;
1939  else
1940  {
1941  delete font;
1942  return NULL;
1943  }
1944  }
1945  }
1946  a2dFontInfoList list;
1947  list.DeleteContents( true );
1948  GetInfoList( list );
1949  unsigned int i;
1950  // try to find exact fontname
1951  for ( i = 0; i < list.GetCount(); i++ )
1952  {
1953  a2dFontInfo* fi = list.Item( i )->GetData();
1954  if ( fi->GetName() == info.GetName() && fi->GetStyle() == info.GetStyle() )
1955  {
1956  font = new a2dFontFreetypeData( fi->GetExtra(), info.GetSize() );
1957  if ( font )
1958  {
1959  if ( font->Ok() )
1960  return font;
1961  else
1962  delete font;
1963  }
1964  }
1965  }
1966  font = NULL;
1967 
1968  int maxval = 0;
1969  // try to find similar font
1970  for ( i = 0; i < list.GetCount(); i++ )
1971  {
1972  a2dFontInfo* fi = list.Item( i )->GetData();
1973  int val = 0;
1974  // if fontname is part of fi.name ore fi.name = part of fontname.
1975  if ( fi->GetName() == info.GetName() )
1976  val = 4;
1977  else if ( fi->GetName().Upper() == info.GetName().Upper() )
1978  val = 3;
1979  else if ( ( fi->GetName().Upper().Find( info.GetName().Upper() ) != -1 )
1980  || ( info.GetName().Upper().Find( fi->GetName().Upper() ) != -1 ) )
1981  val = 1;
1982 
1983  if ( val )
1984  {
1985  if ( ( info.GetStyle().Upper() == wxT( "BOLD" ) )
1986  || ( info.GetStyle().Upper().Find( wxT( "BOLD" ) ) != -1 ) )
1987  val++;
1988  if ( ( info.GetStyle().Upper() == wxT( "ITALIC" ) )
1989  || ( info.GetStyle().Upper().Find( wxT( "ITALIC" ) ) != -1 ) )
1990  val++;
1991  if ( ( info.GetStyle().Upper() == wxT( "REGULAR" ) )
1992  || ( info.GetStyle().Upper().Find( wxT( "REGULAR" ) ) != -1 ) )
1993  val++;
1994 
1995  if ( val > maxval )
1996  {
1997  a2dFontFreetypeData* oldfont = font;
1998  font = new a2dFontFreetypeData( fi->GetExtra(), info.GetSize() );
1999  if ( font )
2000  {
2001  if ( font->Ok() )
2002  {
2003  maxval = val;
2004  delete oldfont;
2005  }
2006  else
2007  {
2008  delete font;
2009  font = oldfont;
2010  }
2011  }
2012  }
2013  }
2014  }
2015  if ( font )
2016  return font;
2017  }
2018 #endif
2019  return NULL;
2020 }
2021 
2022 #endif
2023 
2024 //----------------------------------------------------------------------------
2025 // a2dFontStrokeData
2026 //----------------------------------------------------------------------------
2027 
2028 //! Stroke font class.
2029 /*! \class a2dFontStroke stylebase.h artbase/stylebase.h
2030  Font class based on BGI fonts (*.CHR). These font once were part of the Borland
2031  BGI Toolkit. They can be found at several places on the internet. Look for bgifonts.zip
2032  and bgifont.zip. The latter also contains an editor for these fonts.
2033 
2034  \todo EW: Translate the native text encoding / unicode to codepage 850 for a2dFontStroke, since these are 'old' DOS fonts.
2035  \ingroup property style
2036  \ingroup text
2037 */
2038 class A2DARTBASEDLLEXP a2dFontStrokeData
2039  : public a2dFontRefData
2040 {
2041  friend class a2dFont;
2042 public:
2043 
2044  virtual a2dFontType GetType( void ) const { return a2dFONT_STROKED; }
2045 
2046  //! Constructor.
2047  /*! \param filename Filename of the vector font.
2048  \param size Size in world coordinates.
2049  \param monoSpaced if true, all character will have eqaul distance
2050  */
2051  a2dFontStrokeData( const wxString& filename = wxT( "" ), double size = 0.0, bool monoSpaced = false, double weight = 0.0 );
2052 
2053  //! Copy constructor.
2054  a2dFontStrokeData( const a2dFontStrokeData& other );
2055  //! Destructor.
2056  virtual ~a2dFontStrokeData();
2057 
2058  //! Set the font filename and load the font.
2059  /*! \param filename The filename of the font. This may either be a full path, or just the
2060  fontname. In the latter case, the fontpath of a2dGlobals will be used to search the font.
2061  \sa a2dGlobal
2062  */
2063  void SetFilename( const wxString& filename );
2064  //! Get the font filename.
2065  /*! \param filenameonly The returned filename will be stripped of drive-letters and directories.
2066  \return The filename of the font.
2067  */
2068  wxString GetFilename( bool filenameonly = false ) const;
2069 
2070  //! Get the weight of the font.
2071  /*! \return The weight (in this case stroke width) in percentages of the font size. There are two exceptions.
2072  0: Draws the font with a pen of 1 pixel wide. -1: Draws the font with a normalized pen, as the font-designer intended it.
2073  */
2074  inline double GetWeight() const { return m_weight; }
2075  //! Set the weight of the font.
2076  /*! \param weight The weight (in this case stroke width) in percentages of the font size. There are two exceptions.
2077  0: Draws the font with a pen of 1 pixel wide. -1: Draws the font with a normalized pen, as the font-designer intended it.
2078  */
2079  void SetWeight( double weight );
2080 
2081  //! Set the weight of the font, from a string.
2082  /*! \param weight One of: "Normalized Pen", "Pixel pen" or a string starting with the width in percentages, ending with %.
2083  */
2084  void SetWeight( const wxString& weight );
2085 
2086  // Documented in base class
2087  double GetWidth( wxChar c ) const;
2088 
2089  // Documented in base class
2090  double GetKerning( wxChar c1, wxChar c2 ) const;
2091 
2092  //! Get stroke width.
2093  /*!
2094  \return The stroke width in world coordinates. In case of a pixel font, 0.0 is returned.
2095  \sa GetWeight()
2096  */
2097  double GetStrokeWidth() const;
2098 
2099  //! Get the glyph of a single character.
2100  /*! \return The glyph of the character, in a coordinate space, normalized to the font size.
2101  */
2102  a2dStrokeGlyph GetGlyph( wxChar c ) const;
2103 
2104  // Documented in base class
2105  virtual bool GetVpath( wxChar c, a2dVpath& glyph, const a2dAffineMatrix& affine = a2dIDENTITY_MATRIX );
2106 
2107  // Documented in base class
2108  static void GetInfoList( a2dFontInfoList& list );
2109 
2110  // Documented in base class
2111  static a2dFontStrokeData* CreateFont( const a2dFontInfo& info, bool force = false );
2112 
2113 protected:
2114  //! Filename of the font.
2115  wxString m_filename;
2116 
2117  //! Width storage.
2118  wxUint16* m_width;
2119  //! Glyph storage.
2121 
2122  //! First character in font.
2123  wxUint16 m_beginchar;
2124  //! Number of characters in font.
2125  wxUint16 m_count;
2126  //! Font size in internal coordinates
2127  wxUint16 m_intsize;
2128  //! Font weight
2129  double m_weight;
2130 
2131  bool m_monoSpaced;
2132 };
2133 
2134 #define BGI_FONT_MAGIC "PK\b\bBGI "
2135 
2136 #pragma pack(1)
2137 //! \cond
2138 
2139 // begin of a BGI font ( used in a2dFontStrokeData )
2140 typedef struct
2141 {
2142  char magic[8];
2143  char descr[108];
2144  char stringend;
2145  unsigned short headersize;
2146  char fname[5];
2147  unsigned short datasize;
2148  unsigned char majorversion, minorversion;
2149  unsigned char minmajorversion, minminorversion;
2150 }
2151 BGI_FONT_HEADER;
2152 
2153 //! \cond
2154 typedef struct
2155 {
2156  char signature;
2157  unsigned short nchar;
2158  char undefined;
2159  unsigned char firstchar;
2160  unsigned short stroke_offset;
2161  char scan_flag;
2162  signed char org_top;
2163  signed char org_base;
2164  signed char org_desc;
2165  char unused[5];
2166 }
2167 BGI_FONT_DATA;
2168 #pragma pack()
2169 //! \endcond
2170 
2171 a2dFontStrokeData::a2dFontStrokeData( const wxString& filename, double size, bool monoSpaced, double weight )
2172  : a2dFontRefData( size )
2173 {
2174  m_monoSpaced = monoSpaced;
2175  m_fontinfo.SetType( wxT( "Stroke font" ) );
2176  m_width = NULL;
2177  m_characters = NULL;
2178  SetWeight( weight );
2179  SetFilename( filename );
2180 }
2181 
2183  : a2dFontRefData( other )
2184 {
2185  m_fontinfo.SetType( wxT( "Stroke font" ) );
2186  m_width = NULL;
2187  m_weight = other.m_weight;
2188  m_characters = NULL;
2189  m_monoSpaced = other.m_monoSpaced;
2190  SetFilename( other.m_filename );
2191 }
2192 
2194 {
2195  if ( m_width )
2196  delete[] m_width;
2197  if ( m_characters )
2198  {
2199  for ( unsigned char i = 0; i < m_count; i++ )
2200  {
2201  a2dStrokeGlyph glyph = m_characters[i];
2202  while ( *glyph )
2203  {
2204  delete * glyph;
2205  glyph++;
2206  }
2207  free( m_characters[i] );
2208  }
2209  free( m_characters );
2210  }
2211 }
2212 
2213 wxString a2dFontStrokeData::GetFilename( bool filenameonly ) const
2214 {
2215  if ( filenameonly )
2216  {
2217  wxFileName filename( m_filename );
2218  return filename.GetFullName();
2219  }
2220  else
2221  return m_filename;
2222 }
2223 
2224 void a2dFontStrokeData::SetFilename( const wxString& filename )
2225 {
2226  m_ok = false;
2227 
2228  // delete previous font storage
2229  if ( m_width )
2230  {
2231  delete[] m_width;
2232  m_width = NULL;
2233  }
2234  if ( m_characters )
2235  {
2236  for ( unsigned char i = 0; i < m_count; i++ )
2237  {
2238  a2dStrokeGlyph glyph = m_characters[i];
2239  while ( *glyph )
2240  {
2241  delete * glyph;
2242  glyph++;
2243  }
2244  free( m_characters[i] );
2245  }
2246  free( m_characters );
2247  m_characters = NULL;
2248  }
2249 
2250  m_filename = filename;
2251  if ( m_filename.IsEmpty() )
2252  return;
2253 
2254  wxString fname = a2dGlobals->GetFontPathList().FindValidPath( m_filename );
2255 
2256  if ( fname.IsEmpty() )
2257  fname = m_filename; //make sure we get a name to at least say that this filename could not be found.
2258 
2259  wxFile file( fname );
2260  if ( !file.IsOpened() )
2261  return;
2262 
2263  BGI_FONT_HEADER bgifontheader;
2264  file.Read( &bgifontheader.magic, sizeof( bgifontheader.magic ) );
2265  size_t idx = 0;
2266  char c;
2267  file.Read( &c, 1 );
2268  while( !file.Eof() && idx < sizeof( bgifontheader.descr ) - 1 && c != 0x1a )
2269  {
2270  bgifontheader.descr[idx++] = c;
2271  file.Read( &c, 1 );
2272  }
2273  while( !file.Eof() && c != 0x1a )
2274  file.Read( &c, 1 );
2275  bgifontheader.descr[idx] = '\0';
2276  file.Read( &bgifontheader.headersize, sizeof( bgifontheader.headersize ) );
2277  // swapping for big-endian systems.
2278  bgifontheader.headersize = wxINT16_SWAP_ON_BE( bgifontheader.headersize );
2279  file.Read( &bgifontheader.fname, 4 );
2280  bgifontheader.fname[4] = '\0';
2281  file.Read( &bgifontheader.datasize, sizeof( bgifontheader.datasize ) );
2282  // swapping for big-endian systems.
2283  bgifontheader.datasize = wxINT16_SWAP_ON_BE( bgifontheader.datasize );
2284  file.Read( &bgifontheader.majorversion, 4 * sizeof( bgifontheader.majorversion ) );
2285 
2286  if ( memcmp( bgifontheader.magic, BGI_FONT_MAGIC, sizeof( bgifontheader.magic ) ) )
2287  {
2288  file.Close();
2289  return;
2290  }
2291  file.Seek( bgifontheader.headersize, wxFromStart );
2292 
2293  BGI_FONT_DATA bgifontdata;
2294  file.Read( &bgifontdata, sizeof( BGI_FONT_DATA ) );
2295  // swapping for big-endian systems.
2296  bgifontdata.nchar = wxUINT16_SWAP_ON_BE( bgifontdata.nchar );
2297  bgifontdata.stroke_offset = wxUINT16_SWAP_ON_BE( bgifontdata.stroke_offset );
2298 
2299  if ( bgifontdata.signature != '+' )
2300  {
2301  file.Close();
2302  return;
2303  }
2304 
2305  m_count = bgifontdata.nchar;
2306  m_beginchar = bgifontdata.firstchar;
2307 
2308  m_intsize = bgifontdata.org_top - bgifontdata.org_base;
2309  double size = m_intsize;
2310  m_height = 1.11;
2311  //was
2312  //m_height = ( m_intsize - 2 * ( bgifontdata.org_desc - bgifontdata.org_base ) + 3 ) / size;
2313  m_desc = ( bgifontdata.org_base - bgifontdata.org_desc + 1.5 ) / size;
2314  m_lead = 0.0;
2315 
2316  // read width table.
2317  //m_width = new (unsigned char)[m_count];
2318  m_width = new wxUint16[m_count];
2319  file.Seek( bgifontheader.headersize + sizeof( BGI_FONT_DATA ) + sizeof( unsigned short ) * ( bgifontdata.nchar ), wxFromStart );
2320  unsigned int i;
2321  unsigned char w;
2322  for ( i = 0; i < m_count; i++ )
2323  {
2324  file.Read( &w, sizeof( unsigned char ) );
2325  m_width[i] = w;
2326  }
2327 
2328  // create character table
2329  m_characters = ( a2dStrokeGlyph* ) malloc( sizeof( a2dStrokeGlyph ) * m_count );
2330  for ( i = 0; i < m_count; i++ )
2331  {
2332  // read offset for character definition
2333  file.Seek( bgifontheader.headersize + sizeof( BGI_FONT_DATA ) + sizeof( unsigned short ) * i, wxFromStart );
2334  unsigned short char_offset;
2335  file.Read( &char_offset, sizeof( char_offset ) );
2336  // swapping for big-endian systems.
2337  char_offset = wxUINT16_SWAP_ON_BE( char_offset );
2338  // goto offset for character definition
2339  file.Seek( bgifontheader.headersize + bgifontdata.stroke_offset + char_offset, wxFromStart );
2340 
2341  bool penup = true;
2342  unsigned char opcode = 1;
2343  a2dVertexList* list = new a2dVertexList;
2344  int nlists = 0;
2345  m_characters[i] = ( a2dStrokeGlyph ) malloc( sizeof( a2dVertexList* ) );
2346  m_characters[i][0] = NULL;
2347  signed char penupx = 0;
2348  signed char penupy = 0;
2349  while ( opcode != 0 )
2350  {
2351  signed char x, y;
2352  file.Read( &x, sizeof( x ) );
2353  file.Read( &y, sizeof( y ) );
2354  if ( x & 0x80 ) opcode |= 0x2; else opcode &= ~0x2;
2355  if ( y & 0x80 ) opcode |= 0x1; else opcode &= ~0x1;
2356  if ( x & 0x40 ) x |= 0x80; else x &= ~0x80;
2357  if ( y & 0x40 ) y |= 0x80; else y &= ~0x80;
2358 
2359  switch( opcode )
2360  {
2361  case 3:
2362  if ( penup )
2363  list->push_back( new a2dLineSegment( penupx / size, ( penupy - bgifontdata.org_base ) / size + m_desc ) );
2364 
2365  penup = false;
2366  list->push_back( new a2dLineSegment( x / size, ( y - bgifontdata.org_base ) / size + m_desc ) );
2367  break;
2368  case 2:
2369  if ( !penup )
2370  {
2371  m_characters[i] = ( a2dStrokeGlyph ) realloc( m_characters[i], sizeof( a2dVertexList* ) * ( nlists + 2 ) );
2372  m_characters[i][nlists + 1] = NULL;
2373  m_characters[i][nlists] = list;
2374  nlists++;
2375  list = new a2dVertexList;
2376  }
2377  penup = true; penupx = x; penupy = y;
2378  break;
2379  case 1:
2380  break;
2381  default:
2382  m_characters[i] = ( a2dStrokeGlyph ) realloc( m_characters[i], sizeof( a2dVertexList* ) * ( nlists + 2 ) );
2383  m_characters[i][nlists + 1] = NULL;
2384  m_characters[i][nlists] = list;
2385  nlists++;
2386  }
2387  }
2388  }
2389  file.Close();
2390  m_ok = true;
2391 
2392  // rename known fonts.
2393  wxString fontname = wxString::FromAscii( bgifontheader.fname );
2394  if ( fontname == wxT( "EURO" ) )
2395  fontname = wxT( "EuroStyle" );
2396  else if ( fontname == wxT( "GOTH" ) )
2397  fontname = wxT( "Gothic" );
2398  else if ( fontname == wxT( "LCOM" ) )
2399  fontname = wxT( "Complex" );
2400  else if ( fontname == wxT( "LITT" ) )
2401  fontname = wxT( "Small" );
2402  else if ( fontname == wxT( "SANS" ) )
2403  fontname = wxT( "Sans serif" );
2404  else if ( fontname == wxT( "SCRI" ) )
2405  fontname = wxT( "Script" );
2406  else if ( fontname == wxT( "SIMP" ) )
2407  fontname = wxT( "Simple" );
2408  else if ( fontname == wxT( "TRIP" ) )
2409  fontname = wxT( "Triplex" );
2410  else if ( fontname == wxT( "TSCR" ) )
2411  fontname = wxT( "Triplex Script" );
2412  else if ( fontname == wxT( "NEN " ) )
2413  fontname = wxT( "NEN 3094" );
2414  m_fontinfo.SetName( fontname );
2415 
2416  m_fontinfo.SetExtra( GetFilename( true ) );
2417 }
2418 
2419 void a2dFontStrokeData::SetWeight( double weight )
2420 {
2421  m_weight = weight;
2422 
2423  if ( m_weight == 0.0 )
2424  m_fontinfo.SetStyle( wxT( "Pixel Pen" ) );
2425  if ( m_weight == -1.0 )
2426  m_fontinfo.SetStyle( wxT( "Normalized Pen" ) );
2427  else
2428  {
2429  wxString style;
2430  style.Printf( wxT( "%.1f\x25 of height" ), m_weight );
2431  m_fontinfo.SetStyle( style );
2432  }
2433 }
2434 
2435 void a2dFontStrokeData::SetWeight( const wxString& weight )
2436 {
2437  m_fontinfo.SetStyle( weight );
2438  if ( weight.Upper() == wxT( "PIXEL PEN" ) )
2439  {
2440  m_weight = 0.0;
2441  }
2442  else if ( weight.Upper() == wxT( "NORMALIZED PEN" ) )
2443  {
2444  m_weight = -1.0;
2445  }
2446  else
2447  {
2448  int idxend = weight.Find( wxChar( '%' ) );
2449  if ( idxend <= 0 )
2450  m_weight = -1;
2451  else
2452  {
2453  size_t idxstart = idxend;
2454  while ( idxstart > 0 && weight[idxstart - 1] == wxChar( ' ' ) )
2455  idxstart--;
2456  while ( idxstart > 0 && weight[idxstart - 1] != wxChar( ' ' ) )
2457  idxstart--;
2458  weight.Mid( idxstart, idxend - idxstart ).ToDouble( &m_weight );
2459  }
2460  }
2461 }
2462 
2463 double a2dFontStrokeData::GetWidth( wxChar c ) const
2464 {
2465  if ( !m_ok || !m_width )
2466  return 0.0;
2467 
2468  unsigned char c2 = c;
2469  if ( m_monoSpaced )
2470  c2 = 'm'; // this character seems to represent best a monospaced width that fits all other.
2471 
2472  if ( c2 < m_beginchar && c2 >= m_beginchar + m_count )
2473  c2 = '?';
2474 
2475  if ( c2 >= m_beginchar && c2 < m_beginchar + m_count )
2476  {
2477  double width = m_fontinfo.GetSize() * m_width[c2 - m_beginchar] / m_intsize;
2478  if ( m_monoSpaced )
2479  return width * 0.83;
2480  return width;
2481  }
2482  return 0.0;
2483 }
2484 
2486 {
2487  if ( !m_ok )
2488  return 0.0;
2489 
2490  if ( m_weight == -1.0 )
2491  return m_fontinfo.GetSize() * 1.25 / m_intsize;
2492  else if ( m_weight == 0.0 )
2493  return 0.0;
2494  else
2495  return m_fontinfo.GetSize() * m_weight * 0.01;
2496 }
2497 
2498 double a2dFontStrokeData::GetKerning( wxChar WXUNUSED( c1 ), wxChar WXUNUSED( c2 ) ) const
2499 {
2500  // no kerning.
2501  return 0.0;
2502 }
2503 
2505 {
2506  if ( !m_ok || !m_characters )
2507  return NULL;
2508 
2509  unsigned char c2 = c;
2510 
2511  if ( c2 >= m_beginchar && c2 < m_beginchar + m_count )
2512  return m_characters[c2 - m_beginchar];
2513  else
2514  {
2515  c2 = '?';
2516  if ( c2 >= m_beginchar && c2 < m_beginchar + m_count )
2517  return m_characters[c2 - m_beginchar];
2518  else
2519  return NULL;
2520  }
2521 }
2522 
2523 
2524 bool a2dFontStrokeData::GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine )
2525 {
2526  a2dVertexList** ptr = GetGlyph( c );
2527 
2528  // mirror text, depending on y-axis orientation
2529  a2dAffineMatrix affine2;
2530  // position glyph
2531  affine2.Scale( GetSize() );
2532 
2533  a2dAffineMatrix affine3 = affine;
2534  affine3 *= affine2;
2535 
2536  if ( ptr )
2537  {
2538  while ( *ptr )
2539  {
2540  a2dVertexList trans = a2dVertexList( **ptr );
2541  trans.Transform( affine3 );
2542  vpath.Add( trans, true, false );
2543  ptr++;
2544  }
2545  }
2546  return true;
2547 }
2548 
2549 void a2dFontStrokeData::GetInfoList( a2dFontInfoList& list )
2550 {
2551  wxPathList& pathlist = a2dGlobals->GetFontPathList();
2552 #if wxCHECK_VERSION(2,7,0)
2553  for ( wxPathList::iterator node = pathlist.begin(); node != pathlist.end(); node++ )
2554 #else
2555  for ( wxPathList::compatibility_iterator node = pathlist.GetFirst(); node; node = node->GetNext() )
2556 #endif
2557  {
2558  wxString path( node->GetData() );
2559  if ( !wxDir::Exists( path ) )
2560  continue;
2561 
2562  wxArrayString files;
2563  wxDir::GetAllFiles( path, &files, wxT( "*.chr" ), wxDIR_FILES );
2564  for ( unsigned int i = 0; i < files.GetCount(); i++ )
2565  {
2566  // check if file actually is a stroke font
2567  wxFile file( files.Item( i ) );
2568  if ( !file.IsOpened() )
2569  continue;
2570 
2571  BGI_FONT_HEADER bgifontheader;
2572  file.Read( &bgifontheader.magic, sizeof( bgifontheader.magic ) );
2573  size_t idx = 0;
2574  char c;
2575  file.Read( &c, 1 );
2576  while( !file.Eof() && idx < sizeof( bgifontheader.descr ) - 1 && c != 0x1a )
2577  {
2578  bgifontheader.descr[idx++] = c;
2579  file.Read( &c, 1 );
2580  }
2581  while( !file.Eof() && c != 0x1a )
2582  file.Read( &c, 1 );
2583  bgifontheader.descr[idx] = '\0';
2584  file.Read( &bgifontheader.headersize, sizeof( bgifontheader.headersize ) );
2585  // swapping for big-endian systems.
2586  bgifontheader.headersize = wxINT16_SWAP_ON_BE( bgifontheader.headersize );
2587  file.Read( &bgifontheader.fname, 4 );
2588  bgifontheader.fname[4] = '\0';
2589  file.Read( &bgifontheader.datasize, sizeof( bgifontheader.datasize ) );
2590  // swapping for big-endian systems.
2591  bgifontheader.datasize = wxINT16_SWAP_ON_BE( bgifontheader.datasize );
2592  file.Read( &bgifontheader.majorversion, 4 * sizeof( bgifontheader.majorversion ) );
2593 
2594  if ( memcmp( bgifontheader.magic, BGI_FONT_MAGIC, sizeof( bgifontheader.magic ) ) )
2595  {
2596  file.Close();
2597  continue;
2598  }
2599  file.Seek( bgifontheader.headersize, wxFromStart );
2600 
2601  BGI_FONT_DATA bgifontdata;
2602  file.Read( &bgifontdata, sizeof( BGI_FONT_DATA ) );
2603  // swapping for big-endian systems.
2604  bgifontdata.nchar = wxUINT16_SWAP_ON_BE( bgifontdata.nchar );
2605  bgifontdata.stroke_offset = wxUINT16_SWAP_ON_BE( bgifontdata.stroke_offset );
2606 
2607  if ( bgifontdata.signature != '+' )
2608  {
2609  file.Close();
2610  continue;
2611  }
2612 
2613  // rename known fonts.
2614  wxString fontname = wxString::FromAscii( bgifontheader.fname );
2615  if ( fontname == wxT( "EURO" ) )
2616  fontname = wxT( "EuroStyle" );
2617  else if ( fontname == wxT( "GOTH" ) )
2618  fontname = wxT( "Gothic" );
2619  else if ( fontname == wxT( "LCOM" ) )
2620  fontname = wxT( "Complex" );
2621  else if ( fontname == wxT( "LITT" ) )
2622  fontname = wxT( "Small" );
2623  else if ( fontname == wxT( "SANS" ) )
2624  fontname = wxT( "Sans serif" );
2625  else if ( fontname == wxT( "SCRI" ) )
2626  fontname = wxT( "Script" );
2627  else if ( fontname == wxT( "SIMP" ) )
2628  fontname = wxT( "Simple" );
2629  else if ( fontname == wxT( "TRIP" ) )
2630  fontname = wxT( "Triplex" );
2631  else if ( fontname == wxT( "TSCR" ) )
2632  fontname = wxT( "Triplex Script" );
2633  else if ( fontname == wxT( "NEN " ) )
2634  fontname = wxT( "NEN 3094" );
2635 
2636  wxFileName filename( files.Item( i ) );
2637  wxString weightstring;
2638  list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "Pixel Pen" ), 1.0, filename.GetFullName() ) );
2639  list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "Normalized Pen" ), 1.0, filename.GetFullName() ) );
2640  list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( " 2% of height" ), 1.0, filename.GetFullName() ) );
2641  list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( " 5% of height" ), 1.0, filename.GetFullName() ) );
2642  list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( " 7% of height" ), 1.0, filename.GetFullName() ) );
2643  list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "10% of height" ), 1.0, filename.GetFullName() ) );
2644  list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "15% of height" ), 1.0, filename.GetFullName() ) );
2645  list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "20% of height" ), 1.0, filename.GetFullName() ) );
2646  }
2647  }
2648 }
2649 
2650 a2dFontStrokeData* a2dFontStrokeData::CreateFont( const a2dFontInfo& info, bool force )
2651 {
2652  if ( force || info.GetType().Upper() == wxT( "STROKE FONT" ) )
2653  {
2654  a2dFontStrokeData* font = NULL;
2655  if ( !force && !info.GetExtra().IsEmpty() )
2656  {
2657  // try to open supplied filename
2658  font = new a2dFontStrokeData( info.GetExtra(), info.GetSize() );
2659  if ( font )
2660  {
2661  font->SetWeight( info.GetStyle() );
2662  if ( font->Ok() )
2663  return font;
2664  else
2665  delete font;
2666  }
2667  }
2668  a2dFontInfoList list;
2669  list.DeleteContents( true );
2670  GetInfoList( list );
2671  unsigned int i;
2672  // try to find exact fontname
2673  for ( i = 0; i < list.GetCount(); i++ )
2674  {
2675  a2dFontInfo* fi = list.Item( i )->GetData();
2676  // if fontname is part of fi.name or fi.name = part of fontname.
2677  if ( fi->GetName() == info.GetName() )
2678  {
2679  font = new a2dFontStrokeData( fi->GetExtra(), info.GetSize() );
2680  if ( font )
2681  {
2682  font->SetWeight( info.GetStyle() );
2683  if ( font->Ok() )
2684  return font;
2685  else
2686  delete font;
2687  }
2688  }
2689  }
2690  // try to find similar fontname
2691  for ( i = 0; i < list.GetCount(); i++ )
2692  {
2693  a2dFontInfo* fi = list.Item( i )->GetData();
2694  // if fontname is part of fi.name ore fi.name = part of fontname.
2695  if ( ( fi->GetName().Upper().Find( info.GetName().Upper() ) != -1 )
2696  || ( info.GetName().Upper().Find( fi->GetName().Upper() ) != -1 ) )
2697  {
2698  font = new a2dFontStrokeData( fi->GetExtra(), info.GetSize() );
2699  if ( font )
2700  {
2701  font->SetWeight( info.GetStyle() );
2702  if ( font->Ok() )
2703  return font;
2704  else
2705  delete font;
2706  }
2707  }
2708  }
2709  }
2710  return NULL;
2711 }
2712 
2713 //----------------------------------------------------------------------------
2714 // a2dFont
2715 //----------------------------------------------------------------------------
2716 
2717 map< wxString, a2dFont > a2dFont::ms_fontCache;
2718 
2719 IMPLEMENT_ABSTRACT_CLASS( a2dFont, wxObject )
2720 
2722 {
2723 }
2724 
2725 a2dFont::a2dFont( const a2dFont& other )
2726  : wxObject( other )
2727 {
2728 }
2729 
2730 wxString a2dFont::CreateString( const wxString& filename, double size, wxFontEncoding encoding, int weight )
2731 {
2732  wxString typestr = wxT( "Freetype font" );
2733  wxString sizestr;
2734  sizestr.Printf( wxT( "%f" ), size );
2735  wxString weightstr;
2736  weightstr.Printf( wxT( "%d" ), weight );
2737  wxString description = typestr + wxT( "-" ) + filename + wxT( "-" ) + weightstr
2738  + wxT( "-" ) + sizestr;
2739  return description;
2740 }
2741 
2742 wxString a2dFont::CreateString( const wxString& filename, double size, bool monoSpaced, double weight )
2743 {
2744  wxString typestr = wxT( "Stroke font" );
2745  wxString weightstr;
2746 
2747  if ( weight == 0.0 )
2748  weightstr = wxT( "Pixel Pen" );
2749  if ( weight == -1.0 )
2750  weightstr = wxT( "Normalized Pen" );
2751  else
2752  weightstr.Printf( wxT( "%.1f\x25 of height" ), weight );
2753 
2754  wxString monostr;
2755  if ( monoSpaced ) monostr = wxT( "monoSpaced" );
2756  wxString sizestr;
2757  sizestr.Printf( wxT( "%f" ), size );
2758  wxString description = typestr + wxT( "-" ) + filename + wxT( "-" ) + weightstr
2759  + wxT( "-" ) + sizestr + wxT( "-" ) + monostr ;
2760  return description;
2761 }
2762 
2763 wxString a2dFont::CreateString( a2dFontType type, const wxFont& font, double size, wxFontEncoding encoding )
2764 {
2765  wxString name = font.GetFaceName();
2766  wxString style = wxEmptyString;
2767 
2768  wxString typestr;
2769  switch ( type )
2770  {
2771  case a2dFONT_WXDC:
2772  typestr = wxT( "Device font" );
2773  break;
2774  case a2dFONT_FREETYPE:
2775  typestr = wxT( "Freetype font" );
2776  break;
2777  default:
2778  wxFAIL_MSG( _( "wrong font to set a wxFont to" ) );
2779  break;
2780  }
2781 
2782  switch ( font.GetWeight() )
2783  {
2784  case wxNORMAL:
2785  if ( font.GetStyle() == wxNORMAL )
2786  style = wxT( "Regular" );
2787  break;
2788  case wxBOLD:
2789  style = wxT( "Bold " );
2790  break;
2791  case wxLIGHT:
2792  style = wxT( "Light " );
2793  break;
2794  }
2795  switch ( font.GetStyle() )
2796  {
2797  case wxNORMAL:
2798  break;
2799  case wxITALIC:
2800  case wxSLANT:
2801  style += wxT( "Italic" );
2802  break;
2803  }
2804  style.Trim();
2805 
2806  wxString sizestr;
2807  sizestr.Printf( wxT( "%f" ), size );
2808  wxString description = typestr + wxT( "-" ) + name + wxT( "-" ) + style.Trim()
2809  + wxT( "-" ) + sizestr;
2810 
2811  return description;
2812 }
2813 
2814 a2dFont::a2dFont( const wxFont& font, double size, a2dFontType type, wxFontEncoding encoding )
2815 {
2816  wxString fontstr = CreateString( type, font, size, encoding );
2817  if ( ms_fontCache.find( fontstr ) == ms_fontCache.end() )
2818  {
2819  switch ( type )
2820  {
2821  case a2dFONT_WXDC:
2822  m_refData = new a2dFontDcData( font, size );
2823  break;
2824 #if wxART2D_USE_FREETYPE
2825  case a2dFONT_FREETYPE:
2826 #if defined(__USE_WINAPI__)
2827  m_refData = new a2dFontFreetypeData( font, size, encoding );
2828 #else
2829  wxFAIL_MSG( _( "freetype based on wxFont not enabled" ) );
2830 #endif // defined( __USE_WINAPI__ )
2831  break;
2832 #endif
2833  default:
2834  wxFAIL_MSG( _( "wrong font to set a wxFont to" ) );
2835  break;
2836  }
2837  ms_fontCache[fontstr] = *this;
2838  }
2839  else
2840  // re-use that cached font
2841  Ref( ms_fontCache[fontstr] );
2842 }
2843 
2844 a2dFont::a2dFont( double size, int family, int style, int weight,
2845  const bool underline, const wxString& faceName,
2846  wxFontEncoding encoding )
2847 {
2848  wxString fontstr = CreateString( a2dFONT_WXDC, wxFont( 1, family, style, weight, underline, faceName, encoding ), size, encoding );
2849  if ( ms_fontCache.find( fontstr ) == ms_fontCache.end() )
2850  {
2851  m_refData = new a2dFontDcData( size, family, style, weight, underline, faceName, encoding );
2852  ms_fontCache[fontstr] = *this;
2853  }
2854  else
2855  // re-use that cached font
2856  Ref( ms_fontCache[fontstr] );
2857 }
2858 
2859 
2860 #if wxART2D_USE_FREETYPE
2861 a2dFont::a2dFont( const wxString& filename, double size, wxFontEncoding encoding, int faceindex )
2862 {
2863  m_refData = new a2dFontFreetypeData( filename, size, encoding, faceindex );
2864 }
2865 #endif
2866 
2867 a2dFont::a2dFont( const wxString& filename, double size, bool monoSpaced, double weight )
2868 {
2869  wxString fontstr = CreateString( filename, size, monoSpaced, weight );
2870  if ( ms_fontCache.find( fontstr ) == ms_fontCache.end() )
2871  {
2872  m_refData = new a2dFontStrokeData( filename, size, monoSpaced, weight );
2873  ms_fontCache[fontstr] = *this;
2874  }
2875  else
2876  {
2877  a2dFont cached = ms_fontCache[fontstr];
2878  // re-use that cached font
2879  Ref( cached );
2880  }
2881 }
2882 
2884 {
2885 }
2886 
2888 {
2889  if ( m_refData )
2890  return ( ( a2dFontRefData* )GetRefData() )->m_fontinfo.CreateString();
2891  return wxEmptyString;
2892 }
2893 
2894 bool a2dFont::Ok() const
2895 {
2896  if ( m_refData )
2897  return ( ( a2dFontRefData* )GetRefData() )->Ok();
2898  return false;
2899 }
2900 
2902 {
2903  if ( m_refData )
2904  return ( ( a2dFontRefData* )GetRefData() )->m_fontinfo;
2905  static a2dFontInfo dummy = a2dFontInfo();
2906  return dummy;
2907 }
2908 
2909 void a2dFont::SetSize( double size )
2910 {
2911  AllocExclusive();
2912 
2913  if ( m_refData )
2914  ( ( a2dFontRefData* )GetRefData() )->SetSize( size );
2915 }
2916 
2917 double a2dFont::GetSize() const
2918 {
2919  if ( m_refData )
2920  return ( ( a2dFontRefData* )GetRefData() )->GetSize();
2921  return 0.0;
2922 }
2923 
2924 double a2dFont::GetKerning( wxChar c1, wxChar c2 ) const
2925 {
2926  if ( m_refData )
2927  return ( ( a2dFontRefData* )GetRefData() )->GetKerning( c1, c2 );
2928  return 0.0;
2929 }
2930 
2932 {
2933  switch ( GetType() )
2934  {
2935  case a2dFONT_STROKED:
2936  return ( ( const a2dFontStrokeData* )m_refData )->GetStrokeWidth();
2937  default:
2938  return 0.0;
2939  break;
2940  }
2941  return 0.0;
2942 }
2943 
2945 {
2946  switch ( GetType() )
2947  {
2948  case a2dFONT_STROKED:
2949  return ( ( a2dFontStrokeData* )GetRefData() )->GetGlyph( c );
2950  default:
2951  wxFAIL_MSG( _( "need stroked font a2dFontStrokeData" ) );
2952  break;
2953  }
2954  return NULL;
2955 }
2956 
2957 const a2dGlyph* a2dFont::GetGlyphFreetype( wxChar c ) const
2958 {
2959  switch ( GetType() )
2960  {
2961 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
2962  case a2dFONT_WXDC:
2963  {
2964  a2dFont ft = ( ( a2dFontDcData* )GetRefData() )->GetFreetypeFont();
2965  return ( ( a2dFontFreetypeData* )ft.GetRefData() )->GetGlyph( c );
2966  break;
2967  }
2968 #endif
2969  case a2dFONT_FREETYPE:
2970  return ( ( a2dFontFreetypeData* )GetRefData() )->GetGlyph( c );
2971  default:
2972  wxFAIL_MSG( _( "need stroked font a2dFontFreetypeData" ) );
2973  break;
2974  }
2975  return NULL;
2976 }
2977 
2978 void a2dFont::SetDeviceHeight( double sizeInPixels )
2979 {
2980  switch ( GetType() )
2981  {
2982  case a2dFONT_WXDC:
2983  {
2984  ( ( a2dFontDcData* )GetRefData() )->SetDeviceHeight( sizeInPixels );
2985  break;
2986  }
2987  case a2dFONT_FREETYPE:
2988  ( ( a2dFontFreetypeData* )GetRefData() )->SetDeviceHeight( sizeInPixels );
2989  break;
2990  default:
2991  break;
2992  }
2993 }
2994 
2995 double a2dFont::GetDeviceHeight()
2996 {
2997  switch ( GetType() )
2998  {
2999 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
3000  case a2dFONT_WXDC:
3001  {
3002  return ( ( a2dFontDcData* )GetRefData() )->GetDeviceHeight();
3003  break;
3004  }
3005 #endif
3006  case a2dFONT_FREETYPE:
3007  return ( ( a2dFontFreetypeData* )GetRefData() )->GetDeviceHeight();
3008  default:
3009  return 0;
3010  break;
3011  }
3012 }
3013 
3014 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
3015 a2dFont a2dFont::GetFreetypeFont()
3016 {
3017  switch ( GetType() )
3018  {
3019  case a2dFONT_WXDC:
3020  return ( ( a2dFontDcData* )GetRefData() )->GetFreetypeFont();
3021  break;
3022  default:
3023  wxFAIL_MSG( _( "need wxDc font a2dFontDcData" ) );
3024  break;
3025  }
3026  return *a2dNullFONT;
3027 }
3028 #endif
3029 
3030 wxFont& a2dFont::GetFont( void )
3031 {
3032  switch ( GetType() )
3033  {
3034  case a2dFONT_WXDC:
3035 
3036  return ( ( a2dFontDcData* )GetRefData() )->m_font;
3037  default:
3038  wxFAIL_MSG( _( "need wxDc font a2dFontDcData" ) );
3039  break;
3040  }
3041  return wxNullFont;
3042 }
3043 
3044 a2dBoundingBox a2dFont::GetTextExtent( const wxString& string,
3045  int alignment, double* w, double* h,
3046  double* descent, double* externalLeading ) const
3047 {
3048  double gte_x, gte_y, gte_w, gte_h, gte_desc, gte_lead;
3049  GetTextExtent( string, gte_w, gte_h, gte_desc, gte_lead );
3050 
3051  // Determine Y-Offset
3052  if ( alignment & wxMINY )
3053  gte_y = 0;
3054  else if ( alignment & wxMAXY )
3055  gte_y = -gte_h;
3056  else if ( alignment & wxBASELINE )
3057  gte_y = -gte_desc;
3058  else if ( alignment & wxBASELINE_CONTRA )
3059  gte_y = gte_desc - gte_h;
3060  else
3061  gte_y = -gte_h / 2.0; //centre
3062 
3063  // Determine X-offset
3064  gte_x = -gte_w / 2.0; //centre
3065  if ( alignment & wxMINX )
3066  gte_x += gte_w / 2.0;
3067  if ( alignment & wxMAXX )
3068  gte_x -= gte_w / 2.0;
3069 
3070  // set return variables.
3071  if ( w ) * w = gte_w;
3072  if ( h ) * h = gte_h;
3073  if ( descent ) * descent = gte_desc;
3074  if ( externalLeading ) * externalLeading = gte_lead;
3075 
3076  return a2dBoundingBox( gte_x, gte_y, gte_x + gte_w, gte_y + gte_h );
3077 }
3078 
3079 void a2dFont::GetTextExtent( const wxString& string, double& w,
3080  double& h, double& descent, double& externalLeading ) const
3081 {
3082  return ( ( a2dFontRefData* )GetRefData() )->GetTextExtent( string, w, h, descent, externalLeading );
3083 }
3084 
3085 void a2dFont::GetTextExtentWH( const wxString& string, double& w, double& h ) const
3086 {
3087  double descent, externalLeading;
3088  return ( ( a2dFontRefData* )GetRefData() )->GetTextExtent( string, w, h, descent, externalLeading );
3089 }
3090 
3091 bool a2dFont::GetPartialTextExtents ( const wxString& text, wxArrayInt& widths ) const
3092 {
3093  return true;
3094 }
3095 
3097 {
3098  return ( ( a2dFontRefData* )GetRefData() )->GetLineHeight();
3099 }
3100 
3101 double a2dFont::GetDescent() const
3102 {
3103  return ( ( a2dFontRefData* )GetRefData() )->GetDescent();
3104 }
3105 
3106 double a2dFont::GetWidth( wxChar c )
3107 {
3108  return ( ( a2dFontRefData* )GetRefData() )->GetWidth( c );
3109 }
3110 
3111 bool a2dFont::GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine )
3112 {
3113  return ( ( a2dFontRefData* )GetRefData() )->GetVpath( c, vpath, affine );
3114 }
3115 
3116 void a2dFont::GetVpath( const wxString& text, a2dVpath& vpath, double x, double y, int alignment, bool yaxis, const a2dAffineMatrix& affine )
3117 {
3118  // Get the bounding box, including alignment displacement.
3119  a2dBoundingBox bbox = GetTextExtent( text, alignment );
3120  bbox.Translate( x, y );
3121 
3122  // Get unaligned coordinates. By default these functions
3123  // use the lowerleft corner of the boundingbox, hence GetMinX() and GetMinY().
3124  x = bbox.GetMinX();
3125  y = bbox.GetMinY();
3126 
3127  // mirror text, depending on y-axis orientation
3128  const double h = GetLineHeight();
3129  a2dAffineMatrix affine2;
3130  if ( !yaxis )
3131  {
3132  affine2.Translate( 0.0, -h );
3133  affine2.Mirror( true, false );
3134  }
3135  // position text
3136  affine2.Translate( x, y );
3137 
3138  a2dAffineMatrix affine3 = affine;
3139  affine3 *= affine2;
3140 
3141  wxChar c = 0;
3142  double w = 0.0;
3143  const size_t n = text.Length();
3144  for ( size_t i = 0; i < n; i++ )
3145  {
3146  const wxChar oldc = c;
3147  c = text[i];
3148  if ( i > 0 )
3149  affine3 *= a2dAffineMatrix( w + GetKerning( oldc, c ), 0.0 );
3150  w = GetWidth( c );
3151 
3152  GetVpath( c, vpath, affine3 );
3153  }
3154 }
3155 
3157 {
3158  a2dFontFreetypeData::GetInfoList( list );
3159  a2dFontStrokeData::GetInfoList( list );
3160  a2dFontDcData::GetInfoList( list );
3161 }
3162 
3163 a2dFont a2dFont::CreateFont( const a2dFontInfo& info, bool force )
3164 {
3165  a2dFontRefData* fontdata;
3166  a2dFont font;
3167 
3168  // try to find exact font
3169  fontdata = ( a2dFontRefData* ) a2dFontFreetypeData::CreateFont( info );
3170  if ( !fontdata )
3171  fontdata = ( a2dFontRefData* ) a2dFontStrokeData::CreateFont( info );
3172  if ( !fontdata )
3173  fontdata = ( a2dFontRefData* ) a2dFontDcData::CreateFont( info );
3174 
3175  if ( !fontdata && !force )
3176  {
3177  font = a2dFont();
3178  font.m_refData = fontdata;
3179  return font;
3180  }
3181 
3182  // try to find similar font, whatever type
3183  if ( !fontdata )
3184  fontdata = ( a2dFontRefData* ) a2dFontFreetypeData::CreateFont( info, force );
3185  if ( !fontdata )
3186  fontdata = ( a2dFontRefData* ) a2dFontStrokeData::CreateFont( info, force );
3187  if ( !fontdata )
3188  fontdata = ( a2dFontRefData* ) a2dFontDcData::CreateFont( info, force );
3189 
3190  if ( !fontdata )
3191  {
3192  // just use default font
3193  font = *a2dDEFAULT_CANVASFONT;
3194  font.SetSize( info.GetSize() );
3195  }
3196  else
3197  {
3198  font = a2dFont();
3199  font.m_refData = fontdata;
3200  }
3201  return font;
3202 }
3203 
3204 a2dFontType a2dFont::GetType( void ) const
3205 {
3206  if ( !m_refData )
3207  return a2dFONT_NULL;
3208  return ( ( a2dFontRefData* ) m_refData )->GetType();
3209 }
3210 
3211 wxObjectRefData* a2dFont::CreateRefData() const
3212 {
3213  switch ( GetType() )
3214  {
3215  case a2dFONT_NULL:
3216  return new a2dFontDcData(); //dummy to be removed soon
3217  case a2dFONT_WXDC:
3218  return new a2dFontDcData();
3219  case a2dFONT_FREETYPE:
3220  return new a2dFontFreetypeData();
3221  case a2dFONT_STROKED:
3222  return new a2dFontStrokeData();
3223  default:
3224  break;
3225  }
3226  return NULL;
3227 }
3228 
3229 wxObjectRefData* a2dFont::CloneRefData( const wxObjectRefData* data ) const
3230 {
3231  switch ( ( ( a2dFontRefData* ) data )->GetType() )
3232  {
3233  case a2dFONT_NULL:
3234  return NULL;
3235  case a2dFONT_WXDC:
3236  return new a2dFontDcData( *( ( const a2dFontDcData* )data ) );
3237  case a2dFONT_FREETYPE:
3238  return new a2dFontFreetypeData( *( ( const a2dFontFreetypeData* )data ) );
3239  case a2dFONT_STROKED:
3240  return new a2dFontStrokeData( *( ( const a2dFontStrokeData* )data ) );
3241  default:
3242  break;
3243  }
3244  return NULL;
3245 }
3246 
3247 void a2dFont::SetLoadFlags( wxInt32 loadMethodMask )
3248 {
3249  a2dFontFreetypeData::SetLoadFlags( loadMethodMask );
3250 }
3251 
3252 
3253 void a2dFont::SetFilename( const wxString& filename )
3254 {
3255  switch ( ( ( a2dFontRefData* ) m_refData )->GetType() )
3256  {
3257  case a2dFONT_FREETYPE:
3258  ( ( a2dFontFreetypeData* )m_refData )->SetFilename( filename );
3259  break;
3260  case a2dFONT_STROKED:
3261  ( ( a2dFontStrokeData* )m_refData )->SetFilename( filename );
3262  break;
3263  default:
3264  wxFAIL_MSG( _( "wrong font to set a filename" ) );
3265  break;
3266  }
3267 }
3268 
3269 wxString a2dFont::GetFilename( bool filenameonly ) const
3270 {
3271  switch ( ( ( a2dFontRefData* ) m_refData )->GetType() )
3272  {
3273  case a2dFONT_FREETYPE:
3274  return ( ( const a2dFontFreetypeData* )m_refData )->GetFilename( filenameonly );
3275  case a2dFONT_STROKED:
3276  return ( ( const a2dFontStrokeData* )m_refData )->GetFilename( filenameonly );
3277  default:
3278  break;
3279  }
3280  return wxT( "" );
3281 }
3282 
3283 double a2dFont::GetWeight() const
3284 {
3285  switch ( ( ( a2dFontRefData* ) m_refData )->GetType() )
3286  {
3287  case a2dFONT_STROKED:
3288  return ( ( const a2dFontStrokeData* )m_refData )->GetWeight();
3289  default:
3290  break;
3291  }
3292  return 0.0;
3293 }
3294 
3295 void a2dFont::SetWeight( double weight )
3296 {
3297  if ( GetWeight() == weight )
3298  return;
3299 
3300  AllocExclusive();
3301 
3302  switch ( ( ( a2dFontRefData* ) m_refData )->GetType() )
3303  {
3304  case a2dFONT_STROKED:
3305  ( ( a2dFontStrokeData* )m_refData )->SetWeight( weight );
3306  default:
3307  break;
3308  }
3309 }
3310 
3311 void a2dFont::SetWeight( const wxString& weight )
3312 {
3313  AllocExclusive();
3314 
3315  switch ( ( ( a2dFontRefData* ) m_refData )->GetType() )
3316  {
3317  case a2dFONT_STROKED:
3318  ( ( a2dFontStrokeData* )m_refData )->SetWeight( weight );
3319  default:
3320  break;
3321  }
3322 }
3323 
3324 
3325 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dBLACK_FILL );
3326 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dWHITE_FILL );
3327 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dTRANSPARENT_FILL );
3328 
3329 //! used to remove fill style in objects
3330 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dNullFILL );
3331 
3332 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dINHERIT_FILL );
3333 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dSELECT_FILL );
3334 
3335 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dBLACK_STROKE );
3336 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dWHITE_STROKE );
3337 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dTRANSPARENT_STROKE );
3338 
3339 //! used to remove stroke style in objects
3340 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dNullSTROKE );
3341 
3342 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dINHERIT_STROKE );
3343 
3344 //! used layer wxLAYER_SELECTED in to show selected object (and nested objects)
3345 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dLAYER_SELECT_STROKE );
3346 
3347 //! used to remove font style in objects
3348 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFont*, a2dNullFONT );
3349 
3350 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFont*, a2dDEFAULT_CANVASFONT );
3351 
3352 A2DARTBASEDLLEXP void a2dCanvasInitializeStockObjects ()
3353 {
3354  a2dBLACK_FILL = new a2dFill( wxColour( 0, 0, 0 ) );
3355 
3356  a2dWHITE_FILL = new a2dFill( wxColour( 255, 255, 255 ) );
3357 
3358  a2dTRANSPARENT_FILL = new a2dFill( wxColour( 255, 255, 255 ), a2dFILL_TRANSPARENT );
3359 
3360  a2dNullFILL = new a2dFill();
3361 
3362  a2dINHERIT_FILL = new a2dFill( wxColour( 0, 0, 0 ) );
3363 
3364  a2dBLACK_STROKE = new a2dStroke( wxColour( 0, 0, 0 ), 0.0 );
3365 
3366  a2dWHITE_STROKE = new a2dStroke( wxColour( 255, 255, 255 ), 0.0 );
3367 
3368  a2dTRANSPARENT_STROKE = new a2dStroke( wxColour( 255, 255, 255 ), 0.0, a2dSTROKE_TRANSPARENT );
3369 
3370  a2dNullSTROKE = new a2dStroke();
3371 
3372  a2dINHERIT_STROKE = new a2dStroke( wxColour( 0, 0, 0 ), 0 );
3373 
3374  a2dSELECT_FILL = new a2dFill( wxColour( 0, 0, 0 ), a2dFILL_TRANSPARENT );
3375 
3376  a2dLAYER_SELECT_STROKE = new a2dStroke( wxColour( wxT( "YELLOW" ) ), 2, a2dSTROKE_SOLID );
3377 
3378  a2dNullFONT = new a2dFont();
3379 
3380  a2dDEFAULT_CANVASFONT = new a2dFont( 100.0, wxSWISS );
3381 }
3382 
3383 A2DARTBASEDLLEXP void a2dCanvasDeleteStockObjects ()
3384 {
3385  delete a2dBLACK_FILL;
3386 
3387  delete a2dWHITE_FILL;
3388 
3389  delete a2dTRANSPARENT_FILL;
3390 
3391  delete a2dNullFILL;
3392 
3393  delete a2dINHERIT_FILL;
3394 
3395  delete a2dBLACK_STROKE;
3396 
3397  delete a2dWHITE_STROKE;
3398 
3399  delete a2dTRANSPARENT_STROKE;
3400 
3401  delete a2dNullSTROKE;
3402 
3403  delete a2dINHERIT_STROKE;
3404 
3405  delete a2dSELECT_FILL;
3406 
3407  delete a2dLAYER_SELECT_STROKE;
3408 
3409  delete a2dNullFONT;
3410 
3411  delete a2dDEFAULT_CANVASFONT;
3412 
3413 }
3414 
3415 //----------------------------------------------------------------------------
3416 // a2dFill stuff
3417 //----------------------------------------------------------------------------
3418 
3419 //! convert a style enum to a string
3421 {
3422  switch ( style )
3423  {
3424  case a2dFILL_SOLID: return wxT( "a2dFILL_SOLID" );
3425  case a2dFILL_TRANSPARENT: return wxT( "a2dFILL_TRANSPARENT" );
3426  case a2dFILL_BDIAGONAL_HATCH: return wxT( "a2dFILL_BDIAGONAL_HATCH" );
3427  case a2dFILL_CROSSDIAG_HATCH: return wxT( "a2dFILL_CROSSDIAG_HATCH" );
3428  case a2dFILL_FDIAGONAL_HATCH: return wxT( "a2dFILL_FDIAGONAL_HATCH" );
3429  case a2dFILL_CROSS_HATCH: return wxT( "a2dFILL_CROSS_HATCH" );
3430  case a2dFILL_HORIZONTAL_HATCH: return wxT( "a2dFILL_HORIZONTAL_HATCH" );
3431  case a2dFILL_VERTICAL_HATCH: return wxT( "a2dFILL_VERTICAL_HATCH" );
3432  case a2dFILL_STIPPLE: return wxT( "a2dFILL_STIPPLE" );
3433  case a2dFILL_STIPPLE_MASK_OPAQUE: return wxT( "a2dFILL_STIPPLE_MASK_OPAQUE" );
3434  case a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT: return wxT( "a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT" );
3435  case a2dFILL_GRADIENT_FILL_XY_LINEAR: return wxT( "a2dFILL_GRADIENT_FILL_XY_LINEAR" );
3436  case a2dFILL_GRADIENT_FILL_XY_RADIAL: return wxT( "a2dFILL_GRADIENT_FILL_XY_RADIAL" );
3437  case a2dFILL_GRADIENT_FILL_XY_DROP: return wxT( "a2dFILL_GRADIENT_FILL_XY_DROP" );
3438  case a2dFILL_INHERIT: return wxT( "a2dFILL_INHERIT" );
3439  case a2dFILL_LAYER: return wxT( "a2dFILL_LAYER" );
3440  case a2dFILL_NULLFILL: return wxT( "a2dFILL_NULLFILL" );
3441  case a2dFILL_TWOCOL_BDIAGONAL_HATCH: return wxT( "a2dFILL_TWOCOL_BDIAGONAL_HATCH" );
3442  case a2dFILL_TWOCOL_CROSSDIAG_HATCH: return wxT( "a2dFILL_TWOCOL_CROSSDIAG_HATCH" );
3443  case a2dFILL_TWOCOL_FDIAGONAL_HATCH: return wxT( "a2dFILL_TWOCOL_FDIAGONAL_HATCH" );
3444  case a2dFILL_TWOCOL_CROSS_HATCH: return wxT( "a2dFILL_TWOCOL_CROSS_HATCH" );
3445  case a2dFILL_TWOCOL_HORIZONTAL_HATCH: return wxT( "a2dFILL_TWOCOL_HORIZONTAL_HATCH" );
3446  case a2dFILL_TWOCOL_VERTICAL_HATCH: return wxT( "a2dFILL_TWOCOL_VERTICAL_HATCH" );
3447 
3448  default:
3449  a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "CVG : invalid style" ) );
3450  }
3451  return wxT( "a2dFILL_NULLFILL" );
3452 }
3453 
3454 //! convert a string to a style enum
3455 a2dFillStyle FillString2Style( const wxString& stylestr )
3456 {
3457  if ( stylestr == wxT( "a2dFILL_SOLID" ) )
3458  return a2dFILL_SOLID;
3459  if ( stylestr == wxT( "a2dFILL_TRANSPARENT" ) )
3460  return a2dFILL_TRANSPARENT;
3461  if ( stylestr == wxT( "a2dFILL_BDIAGONAL_HATCH" ) )
3462  return a2dFILL_BDIAGONAL_HATCH;
3463  if ( stylestr == wxT( "a2dFILL_CROSSDIAG_HATCH" ) )
3464  return a2dFILL_CROSSDIAG_HATCH;
3465  if ( stylestr == wxT( "a2dFILL_FDIAGONAL_HATCH" ) )
3466  return a2dFILL_FDIAGONAL_HATCH;
3467  if ( stylestr == wxT( "a2dFILL_CROSS_HATCH" ) )
3468  return a2dFILL_CROSS_HATCH;
3469  if ( stylestr == wxT( "a2dFILL_HORIZONTAL_HATCH" ) )
3470  return a2dFILL_HORIZONTAL_HATCH;
3471  if ( stylestr == wxT( "a2dFILL_VERTICAL_HATCH" ) )
3472  return a2dFILL_VERTICAL_HATCH;
3473  if ( stylestr == wxT( "a2dFILL_STIPPLE" ) )
3474  return a2dFILL_STIPPLE;
3475  if ( stylestr == wxT( "a2dFILL_STIPPLE_MASK_OPAQUE" ) )
3477  if ( stylestr == wxT( "a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT" ) )
3479  if ( stylestr == wxT( "a2dFILL_GRADIENT_FILL_XY_LINEAR" ) )
3481  if ( stylestr == wxT( "a2dFILL_GRADIENT_FILL_XY_RADIAL" ) )
3483  if ( stylestr == wxT( "a2dFILL_GRADIENT_FILL_XY_DROP" ) )
3485  if ( stylestr == wxT( "a2dFILL_INHERIT" ) )
3486  return a2dFILL_INHERIT;
3487  if ( stylestr == wxT( "a2dFILL_LAYER" ) )
3488  return a2dFILL_LAYER;
3489  if ( stylestr == wxT( "a2dFILL_NULLFILL" ) )
3490  return a2dFILL_NULLFILL;
3491 
3492  if ( stylestr == wxT( "a2dFILL_TWOCOL_BDIAGONAL_HATCH" ) )
3494  if ( stylestr == wxT( "a2dFILL_TWOCOL_CROSSDIAG_HATCH" ) )
3496  if ( stylestr == wxT( "a2dFILL_TWOCOL_FDIAGONAL_HATCH" ) )
3498  if ( stylestr == wxT( "a2dFILL_TWOCOL_CROSS_HATCH" ) )
3500  if ( stylestr == wxT( "a2dFILL_TWOCOL_HORIZONTAL_HATCH" ) )
3502  if ( stylestr == wxT( "a2dFILL_TWOCOL_VERTICAL_HATCH" ) )
3504 
3505  if ( !stylestr.IsEmpty() ) //old style settings
3506  {
3507  long num;
3508  stylestr.ToLong( &num );
3509  return ( a2dFillStyle ) num;
3510  }
3511 
3512  a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "CVG : invalid style %s" ), stylestr.c_str() );
3513 
3514  return a2dFILL_NULLFILL;
3515 }
3516 
3517 
3518 //----------------------------------------------------------------------------
3519 // a2dFillRefData
3520 //----------------------------------------------------------------------------
3521 
3522 //! Internal to a2dFill for refcounting in wxObject style
3523 /*!
3524  \ingroup style
3525 */
3526 class A2DARTBASEDLLEXP a2dFillRefData : public wxObjectRefData
3527 {
3528 public:
3529 
3530  virtual a2dFillType GetType( void ) const { return a2dFILL_NULL; }
3531 
3532  //!constructor
3534  {
3535  m_fillOn = true;
3536  }
3537 
3538  a2dFillRefData( const a2dFillRefData& other )
3539  : wxObjectRefData()
3540  {
3541  m_fillOn = other.m_fillOn;
3542  }
3543 
3544 #if wxART2D_USE_CVGIO
3545  //! Save settings.
3546  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts, a2dObjectList* towrite ) = 0;
3547  //! Load settings.
3548  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts ) = 0;
3549 #endif //wxART2D_USE_CVGIO
3550 
3551  //! if true filling is done, else transparent fill
3552  bool m_fillOn;
3553 };
3554 
3555 //----------------------------------------------------------------------------
3556 // a2dOneColourFillData
3557 //----------------------------------------------------------------------------
3558 
3559 //! One Colour Fill
3560 /*!
3561 A second colour is not saved, but when asked for it return wxBLACK
3562 
3563  \ingroup property style
3564 */
3565 class A2DARTBASEDLLEXP a2dOneColourFillData : public a2dFillRefData
3566 {
3567 private:
3568 
3569  friend class a2dFill;
3570 
3571 public:
3572 
3573  virtual a2dFillType GetType( void ) const { return a2dFILL_ONE_COLOUR; }
3574 
3575  //!constructor
3576  a2dOneColourFillData( void );
3577 
3579 
3580  //!constructor
3581  a2dOneColourFillData( const wxColour& col, a2dFillStyle style = a2dFILL_SOLID );
3582 
3583  a2dOneColourFillData( const wxBrush& brush );
3584 
3585  //!destructor
3587 
3588  static a2dOneColourFillData* Create( const wxColour& col, a2dFillStyle style = a2dFILL_SOLID );
3589 
3590  void SetColour( const wxColour& col ) { m_colour1 = col; }
3591 
3592  //! return colour
3593  wxColour GetColour() const { return m_colour1; }
3594 
3595  a2dFillStyle GetStyle( void ) const { return m_style; }
3596 
3597  void SetStyle( a2dFillStyle style ) { m_style = style; }
3598 
3599 protected:
3600 
3601 #if wxART2D_USE_CVGIO
3602  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
3603  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
3604 #endif //wxART2D_USE_CVGIO
3605 
3606  //! style of Fill
3608 
3609  wxColour m_colour1;
3610 };
3611 
3612 a2dOneColourFillData* a2dOneColourFillData::Create( const wxColour& col, a2dFillStyle style )
3613 {
3614  return new a2dOneColourFillData( col, style );
3615 }
3616 
3618  : a2dFillRefData()
3619 {
3621  m_colour1 = *wxBLACK;
3622 }
3623 
3625  : a2dFillRefData()
3626 {
3627  m_colour1 = col;
3628  if ( style == a2dFILL_SOLID ||
3629  style == a2dFILL_TRANSPARENT ||
3630  style == a2dFILL_BDIAGONAL_HATCH ||
3631  style == a2dFILL_CROSSDIAG_HATCH ||
3632  style == a2dFILL_FDIAGONAL_HATCH ||
3633  style == a2dFILL_CROSS_HATCH ||
3634  style == a2dFILL_HORIZONTAL_HATCH ||
3635  style == a2dFILL_VERTICAL_HATCH ||
3636  style == a2dFILL_NULLFILL
3637  )
3638  m_style = style;
3639  else
3640  wxFAIL_MSG( _( "invalid style for a2dOneColourFillData" ) );
3641 }
3642 
3643 a2dOneColourFillData::a2dOneColourFillData( const wxBrush& brush )
3644  : a2dFillRefData()
3645 {
3646  if ( brush.GetStyle() == wxSOLID )
3647  {
3648  m_colour1 = wxColour( brush.GetColour() );
3650  }
3651  else if ( brush.IsHatch() )
3652  {
3653  m_colour1 = wxColour( brush.GetColour() );
3654 
3655  switch( brush.GetStyle() )
3656  {
3657  case wxBDIAGONAL_HATCH :
3659  break ;
3660  case wxCROSSDIAG_HATCH :
3662  break ;
3663  case wxFDIAGONAL_HATCH :
3665  break ;
3666  case wxCROSS_HATCH :
3668  break ;
3669  case wxHORIZONTAL_HATCH :
3671  break ;
3672  case wxVERTICAL_HATCH :
3674  break ;
3675  }
3676  }
3677  else if ( brush.GetStyle() == wxTRANSPARENT )
3679 }
3680 
3682  : a2dFillRefData( other )
3683 {
3684  m_style = other.m_style;
3685  m_colour1 = other.m_colour1;
3686 }
3687 
3688 #if wxART2D_USE_CVGIO
3689 void a2dOneColourFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
3690 {
3691  if ( xmlparts == a2dXmlSer_attrib )
3692  {
3693  m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT( "a2dFILL_SOLID" ) ) );
3694  SetStyle( m_style );
3695 
3696  wxString fillColour = parser.GetAttributeValue( wxT( "colour" ) );
3697  if ( !fillColour.IsEmpty() )
3698  {
3699  if ( fillColour.GetChar( 0 ) == wxT( '#' ) )
3700  m_colour1 = HexToColour( fillColour.After( wxT( '#' ) ) );
3701  else
3702  {
3703  m_colour1 = wxTheColourDatabase->Find( fillColour );
3704  if ( !m_colour1.Ok() )
3705  m_colour1 = *wxBLACK;
3706  }
3707  }
3708  else
3709  m_colour1 = *wxBLACK;
3710  }
3711  else
3712  {}
3713 }
3714 
3715 void a2dOneColourFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
3716 {
3717  if ( xmlparts == a2dXmlSer_attrib )
3718  {
3719  if ( m_style != a2dFILL_SOLID )
3720  out.WriteAttribute( wxT( "style" ), FillStyle2String( GetStyle() ) );
3721  if ( m_style != a2dFILL_TRANSPARENT )
3722  {
3723  wxString brushColour = wxTheColourDatabase->FindName( GetColour() );
3724 
3725  if ( brushColour.IsEmpty() )
3726  out.WriteAttribute( wxT( "colour" ), wxT( "#" ) + ColourToHex( GetColour() ) );
3727  else
3728  out.WriteAttribute( wxT( "colour" ), brushColour );
3729  }
3730  }
3731  else
3732  {}
3733 }
3734 #endif //wxART2D_USE_CVGIO
3735 
3736 //----------------------------------------------------------------------------
3737 // a2dTwoColourFillData
3738 //----------------------------------------------------------------------------
3739 
3740 //!To set a two colour fill.
3741 /*!
3742 It defines a second colour for a fill used for the background of
3743 text.
3744 
3745  \ingroup property style
3746 */
3747 class A2DARTBASEDLLEXP a2dTwoColourFillData : public a2dFillRefData
3748 {
3749 
3750 private:
3751 
3752  friend class a2dFill;
3753 
3754 protected:
3755 
3756  //!constructor
3757  a2dTwoColourFillData( void );
3758 
3760 
3761  //!constructor
3762  a2dTwoColourFillData( const wxColour& col, const wxColour& col2, a2dFillStyle style );
3763 
3764  //!destructor
3766 
3767  a2dFillStyle GetStyle( void ) const { return m_style; }
3768 
3769  void SetStyle( a2dFillStyle style ) { m_style = style; }
3770 
3771  //! set colour 2 used for gradient and wxSTIPPLE_MASK_OPAQUE filling.
3772  void SetColour2( const wxColour& col ) { m_colour2 = col; }
3773 
3774  //! return colour 2
3775  wxColour GetColour2() const { return m_colour2; }
3776 
3777  //! set colour used for gradient and wxSTIPPLE_MASK_OPAQUE filling.
3778  void SetColour( const wxColour& col ) { m_colour1 = col; }
3779 
3780  //! return colour
3781  wxColour GetColour() const { return m_colour1; }
3782 
3783 #if wxART2D_USE_CVGIO
3784  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
3785  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
3786 #endif //wxART2D_USE_CVGIO
3787 
3788  //! used for gradient fill or text background or opaque filling
3789  wxColour m_colour1;
3790 
3791  //! used for gradient fill or text background or opaque filling
3792  wxColour m_colour2;
3793 
3794  //! style of Fill
3796 };
3797 
3799  : a2dFillRefData()
3800 {
3801  m_colour1 = *wxBLACK;
3802  m_colour2 = *wxBLACK;
3803 }
3804 
3805 a2dTwoColourFillData::a2dTwoColourFillData( const wxColour& col, const wxColour& col2, a2dFillStyle style )
3806  : a2dFillRefData( )
3807 {
3808  m_colour1 = col;
3809  m_colour2 = col2;
3810  m_style = style;
3811 }
3812 
3814  : a2dFillRefData( other )
3815 {
3816  m_style = other.m_style;
3817  m_colour1 = other.m_colour1;
3818  m_colour2 = other.m_colour2;
3819 }
3820 
3821 #if wxART2D_USE_CVGIO
3822 void a2dTwoColourFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
3823 {
3824  if ( xmlparts == a2dXmlSer_attrib )
3825  {
3826  wxString fillColour = parser.GetAttributeValue( wxT( "colour" ) );
3827  if ( fillColour.GetChar( 0 ) == wxT( '#' ) )
3828  m_colour1 = HexToColour( fillColour.After( wxT( '#' ) ) );
3829  else
3830  {
3831  m_colour1 = wxTheColourDatabase->Find( fillColour );
3832  if ( !m_colour1.Ok() )
3833  m_colour1 = *wxBLACK;
3834  }
3835  fillColour = parser.GetAttributeValue( wxT( "colour2" ) );
3836  if ( !fillColour.IsEmpty() )
3837  {
3838  if ( fillColour.GetChar( 0 ) == wxT( '#' ) )
3839  m_colour2 = HexToColour( fillColour.After( wxT( '#' ) ) );
3840  else
3841  {
3842  m_colour2 = wxTheColourDatabase->Find( fillColour );
3843  if ( !m_colour2.Ok() )
3844  m_colour2 = *wxBLACK;
3845  }
3846  }
3847  }
3848  else
3849  {}
3850 }
3851 
3852 void a2dTwoColourFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
3853 {
3854  if ( xmlparts == a2dXmlSer_attrib )
3855  {
3856  if ( m_style != a2dFILL_TRANSPARENT )
3857  {
3858  wxString brushColour = wxTheColourDatabase->FindName( GetColour() );
3859 
3860  if ( brushColour.IsEmpty() )
3861  out.WriteAttribute( wxT( "colour" ), wxT( "#" ) + ColourToHex( GetColour() ) );
3862  else
3863  out.WriteAttribute( wxT( "colour" ), brushColour );
3864 
3865  brushColour = wxTheColourDatabase->FindName( GetColour2() );
3866  if ( brushColour.IsEmpty() )
3867  out.WriteAttribute( wxT( "colour2" ), wxT( "#" ) + ColourToHex( GetColour2() ) );
3868  else
3869  out.WriteAttribute( wxT( "colour2" ), brushColour );
3870  }
3871  }
3872  else
3873  {}
3874 }
3875 #endif //wxART2D_USE_CVGIO
3876 
3877 //----------------------------------------------------------------------------
3878 // a2dHatchFillData
3879 //----------------------------------------------------------------------------
3880 
3881 //! Two colour Hatch Fill
3882 /*!
3883  The hatch if drawn in the foreground colour and, colour2 is used for the background.
3884 
3885  \ingroup property style
3886 */
3887 class A2DARTBASEDLLEXP a2dHatchFillData: public a2dTwoColourFillData
3888 {
3889 
3890 private:
3891 
3892  friend class a2dFill;
3893 
3894 public:
3895 
3896  virtual a2dFillType GetType( void ) const { return a2dFILL_HATCH_TWO_COLOUR; }
3897 
3898 protected:
3899 
3900  //!constructor
3901  a2dHatchFillData( void );
3902 
3903  //!constructor
3904  a2dHatchFillData( const a2dHatchFillData& other );
3905 
3906  //!constructor
3907  /*!
3908  \param col foreground color
3909  \param col2 background color
3910  */
3911  a2dHatchFillData( const wxColour& col, const wxColour& col2, a2dFillStyle style );
3912 
3913  //!destructor
3915 
3916  void SetStyle( a2dFillStyle style );
3917 
3918 #if wxART2D_USE_CVGIO
3919  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
3920  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
3921 #endif //wxART2D_USE_CVGIO
3922 
3923 };
3924 
3926 {
3928 }
3929 
3930 a2dHatchFillData::a2dHatchFillData( const wxColour& col, const wxColour& col2, a2dFillStyle style )
3931  : a2dTwoColourFillData( col, col2, style )
3932 {
3933  SetStyle( style );
3934 }
3935 
3937  : a2dTwoColourFillData( other )
3938 {
3939 }
3940 
3941 void a2dHatchFillData::SetStyle( a2dFillStyle style )
3942 {
3943  if (
3944  style == a2dFILL_TRANSPARENT ||
3945  style == a2dFILL_TWOCOL_BDIAGONAL_HATCH ||
3946  style == a2dFILL_TWOCOL_CROSSDIAG_HATCH ||
3947  style == a2dFILL_TWOCOL_FDIAGONAL_HATCH ||
3948  style == a2dFILL_TWOCOL_CROSS_HATCH ||
3951  )
3952  m_style = style;
3953  else
3954  wxFAIL_MSG( _( "invalid style for a2dHatchFillData" ) );
3955 }
3956 
3957 #if wxART2D_USE_CVGIO
3958 void a2dHatchFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
3959 {
3960  a2dTwoColourFillData::DoSave( parent, out, xmlparts, towrite );
3961  if ( xmlparts == a2dXmlSer_attrib )
3962  {
3964  out.WriteAttribute( wxT( "style" ), FillStyle2String( m_style ) );
3965  }
3966  else
3967  {}
3968 }
3969 
3970 void a2dHatchFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
3971 {
3972  a2dTwoColourFillData::DoLoad( parent, parser, xmlparts );
3973  if ( xmlparts == a2dXmlSer_attrib )
3974  {
3975  m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT( "a2dFILL_TWOCOL_BDIAGONAL_HATCH" ) ) );
3976  }
3977  else
3978  {}
3979 }
3980 #endif //wxART2D_USE_CVGIO
3981 
3982 //----------------------------------------------------------------------------
3983 // a2dLinearGradientFillData
3984 //----------------------------------------------------------------------------
3985 
3986 //!Linear gradient Fill
3987 /*!
3988 gradient filling using lines changing in colour from brush colour to colour2
3989 There is a start and end point for the gradient fill, those points are relative to the parent
3990 of the object containing the fill, and defined in world coordinates.
3991 
3992  \ingroup property style
3993 */
3994 class A2DARTBASEDLLEXP a2dLinearGradientFillData: public a2dTwoColourFillData
3995 {
3996 
3997 private:
3998 
3999  friend class a2dFill;
4000 
4001 public:
4002 
4003  virtual a2dFillType GetType( void ) const { return a2dFILL_GRADIENT_FILL_LINEAR; }
4004 
4005 protected:
4006 
4007  //!constructor
4008  a2dLinearGradientFillData( void );
4009 
4010  //!constructor
4012 
4013  //!constructor
4014  /*!
4015  \param col first color
4016  \param col2 second color
4017  */
4019  const wxColour& col, const wxColour& col2,
4020  double x1, double y1, double x2, double y2 );
4021 
4022  //!destructor
4024 
4025  //!start for gradient fill colour change
4026  void SetStart( double x, double y );
4027 
4028  //!stop for gradient fill colour change
4029  void SetStop( double x, double y );
4030 
4031  //!Get start for gradient fill colour change
4032  a2dPoint2D GetStart() { return a2dPoint2D( m_x1, m_y1 ); }
4033 
4034  //!Get stop for gradient fill colour change
4035  a2dPoint2D GetStop() { return a2dPoint2D( m_x2, m_y2 ); }
4036 
4037  void Init( a2dAffineMatrix* cworld, double minx, double miny, double maxx, double maxy, double centroidx, double centroidy );
4038 
4039  void ColourXY( a2dDrawer2D* drawer, int x1, int x2, int y );
4040 
4041  wxUint32 GetStamp() { return m_gradientstamp; }
4042 
4043 #if wxART2D_USE_CVGIO
4044  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
4045  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
4046 #endif //wxART2D_USE_CVGIO
4047 
4048  double m_x1, m_y1, m_x2, m_y2;
4049 
4050  wxUint32 m_gradientstamp;
4051 };
4052 
4054 {
4056  m_x1 = 0;
4057  m_y1 = 0;
4058  m_x2 = 0;
4059  m_y2 = 0;
4060 }
4061 
4063  const wxColour& col, const wxColour& col2,
4064  double x1, double y1, double x2, double y2 )
4066 {
4067  m_x1 = x1;
4068  m_y1 = y1;
4069  m_x2 = x2;
4070  m_y2 = y2;
4071 }
4072 
4074  : a2dTwoColourFillData( other )
4075 {
4076  m_x1 = other.m_x1;
4077  m_y1 = other.m_y1;
4078  m_x2 = other.m_x2;
4079  m_y2 = other.m_y2;
4080 }
4081 
4082 void a2dLinearGradientFillData::SetStart( double x, double y )
4083 {
4084  m_x1 = x;
4085  m_y1 = y;
4086 }
4087 
4088 void a2dLinearGradientFillData::SetStop( double x, double y )
4089 {
4090  m_x2 = x;
4091  m_y2 = y;
4092 }
4093 
4094 #if wxART2D_USE_CVGIO
4095 void a2dLinearGradientFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
4096 {
4097  a2dTwoColourFillData::DoSave( parent, out, xmlparts, towrite );
4098  if ( xmlparts == a2dXmlSer_attrib )
4099  {
4101  out.WriteAttribute( wxT( "style" ), FillStyle2String( m_style ) );
4102  out.WriteAttribute( wxT( "x1" ), m_x1 );
4103  out.WriteAttribute( wxT( "y1" ), m_y1 );
4104  out.WriteAttribute( wxT( "x2" ), m_x2 );
4105  out.WriteAttribute( wxT( "y2" ), m_y2 );
4106  }
4107  else
4108  {}
4109 }
4110 
4111 void a2dLinearGradientFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
4112 {
4113  a2dTwoColourFillData::DoLoad( parent, parser, xmlparts );
4114  if ( xmlparts == a2dXmlSer_attrib )
4115  {
4116  m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT( "a2dFILL_GRADIENT_FILL_XY_LINEAR" ) ) );
4117 
4118  m_x1 = parser.GetAttributeValueDouble( wxT( "x1" ) ) ;
4119  m_y1 = parser.GetAttributeValueDouble( wxT( "y1" ) ) ;
4120  m_x2 = parser.GetAttributeValueDouble( wxT( "x2" ) ) ;
4121  m_y2 = parser.GetAttributeValueDouble( wxT( "y2" ) ) ;
4122  }
4123  else
4124  {}
4125 }
4126 
4127 #endif //wxART2D_USE_CVGIO
4128 
4129 //----------------------------------------------------------------------------
4130 // a2dRadialGradientFillData
4131 //----------------------------------------------------------------------------
4132 //!radial gradient Fill
4133 /*!
4134 gradient filling using circles changing in colour from colour1 to colour2
4135 There is a start and end point for the gradient fill, those points are relative to the parent
4136 of the object containing the fill, and defined in world coordinates.
4137 
4138  \ingroup property style
4139 */
4140 class A2DARTBASEDLLEXP a2dRadialGradientFillData: public a2dTwoColourFillData
4141 {
4142 
4143 private:
4144 
4145  friend class a2dFill;
4146 
4147 public:
4148 
4149  virtual a2dFillType GetType( void ) const { return a2dFILL_GRADIENT_FILL_RADIAL; }
4150 
4151 protected:
4152 
4153  //!constructor
4154  a2dRadialGradientFillData( void );
4155 
4156  //!constructor
4158 
4159  //!constructor
4160  /*!
4161  \param col first color
4162  \param col2 second color
4163  */
4165  const wxColour& col, const wxColour& col2,
4166  double xfc, double yfc, double xe, double ye, double radius );
4167 
4168  //!destructor
4170 
4171  //!center end for gradient fill colour change
4172  void SetCenter( double x, double y );
4173 
4174  //!radius for gradient fill colour change
4175  void SetRadius( double radius );
4176 
4177  //!focal point, startpoint for gradient fill
4178  void SetFocal( double x, double y );
4179 
4180  //!Get start for gradient fill colour change
4181  a2dPoint2D GetCenter() { return a2dPoint2D( m_xe, m_ye ); }
4182 
4183  //!Get start for gradient fill colour change
4184  a2dPoint2D GetFocal() { return a2dPoint2D( m_xe, m_ye ); }
4185 
4186  //!Get stop for gradient fill colour change
4187  double GetRadius() { return m_radius; }
4188 
4189  void Init( a2dAffineMatrix* cworld, double minx, double miny, double maxx, double maxy, double centroidx, double centroidy );
4190 
4191  void ColourXY( a2dDrawer2D* drawer, int x1, int x2, int y );
4192 
4193  wxUint32 GetStamp() { return m_gradientstamp; }
4194 
4195 #if wxART2D_USE_CVGIO
4196  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
4197  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
4198 #endif //wxART2D_USE_CVGIO
4199 
4200  //a2dAffineMatrix* m_usertodevice;
4201 
4202  double m_radius;
4203 
4204  //!relative x as end for gradient fill
4205  double m_xe;
4206 
4207  //!relative y as end for gradient fill
4208  double m_ye;
4209 
4210  //!relative start and focal point x
4211  double m_xfc;
4212 
4213  //!relative start and focal point y
4214  double m_yfc;
4215 
4216  wxUint32 m_gradientstamp;
4217 };
4218 
4220 {
4222  m_xe = 0;
4223  m_ye = 0;
4224  m_xfc = 0;
4225  m_yfc = 0;
4226  m_radius = 0;
4227 }
4228 
4230  const wxColour& col, const wxColour& col2,
4231  double xfc, double yfc, double xe, double ye, double radius )
4233 {
4234  m_xe = xe;
4235  m_ye = ye;
4236  m_xfc = xfc;
4237  m_yfc = yfc;
4238  m_radius = radius;
4239 }
4240 
4242  : a2dTwoColourFillData( other )
4243 {
4244  m_xe = other.m_xe;
4245  m_ye = other.m_ye;
4246  m_xfc = other.m_xfc;
4247  m_yfc = other.m_yfc;
4248  m_radius = other.m_radius;
4249 }
4250 
4251 void a2dRadialGradientFillData::SetCenter( double x, double y )
4252 {
4253  m_xe = x;
4254  m_ye = y;
4255 }
4256 
4258 {
4259  m_radius = radius;
4260 }
4261 
4262 //!focal point, startpoint for gradient fill
4263 void a2dRadialGradientFillData::SetFocal( double x, double y )
4264 {
4265  m_xfc = x;
4266  m_yfc = y;
4267 }
4268 
4269 #if wxART2D_USE_CVGIO
4270 void a2dRadialGradientFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
4271 {
4272  a2dTwoColourFillData::DoSave( parent, out, xmlparts, towrite );
4273  if ( xmlparts == a2dXmlSer_attrib )
4274  {
4276  out.WriteAttribute( wxT( "style" ), FillStyle2String( m_style ) );
4277  out.WriteAttribute( wxT( "cx" ), m_xe );
4278  out.WriteAttribute( wxT( "cy" ), m_ye );
4279  out.WriteAttribute( wxT( "r" ), m_radius );
4280  out.WriteAttribute( wxT( "fx" ), m_xfc );
4281  out.WriteAttribute( wxT( "fy" ), m_yfc );
4282  }
4283  else
4284  {}
4285 }
4286 
4287 void a2dRadialGradientFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
4288 {
4289  a2dTwoColourFillData::DoLoad( parent, parser, xmlparts );
4290  if ( xmlparts == a2dXmlSer_attrib )
4291  {
4292  m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT( "a2dFILL_GRADIENT_FILL_XY_RADIAL" ) ) );
4293 
4294  m_xe = parser.GetAttributeValueDouble( wxT( "cx" ) ) ;
4295  m_ye = parser.GetAttributeValueDouble( wxT( "cy" ) ) ;
4296  m_radius = parser.GetAttributeValueDouble( wxT( "r" ) ) ;
4297  m_xfc = parser.GetAttributeValueDouble( wxT( "fx" ) ) ;
4298  m_yfc = parser.GetAttributeValueDouble( wxT( "fy" ) ) ;
4299  }
4300  else
4301  {}
4302 
4303 }
4304 #endif //wxART2D_USE_CVGIO
4305 
4306 //----------------------------------------------------------------------------
4307 // a2dPatternFillData
4308 //----------------------------------------------------------------------------
4309 
4310 //!Filling using a wxbitmap
4311 /*!
4312 To Fill shapes with a bitmap. a2dFILL_STIPPLE
4313 In case a wxMask is set, to do transparent stipple drawing use style a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT.
4314 The fill colour1 will be used for non Transparent parts in the brush bitmap,
4315 while other parts will be transparent.
4316 In case a wxMask is set, use style wxSTIPPLE_MASK_OPAQUE to use colour1 and colour2 to fill with
4317 the wxMask in those colours.
4318 
4319  \ingroup property style
4320 */
4321 class A2DARTBASEDLLEXP a2dPatternFillData: public a2dTwoColourFillData
4322 {
4323 private:
4324 
4325  friend class a2dFill;
4326 
4327 public:
4328 
4329  virtual a2dFillType GetType( void ) const { return a2dFILL_BITMAP; }
4330 
4331 protected:
4332 
4333  //!constructor
4335 
4336  //!constructor
4337  a2dPatternFillData( const a2dPatternFillData& other );
4338 
4339  //!constructor
4340  /*!
4341  \param stipple bitmap for stippling the primitive drawn.
4342  \param style can be a2dFILL_STIPPLE a2dFILL_STIPPLE_MASK_OPAQUE, a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT
4343 
4344  */
4345  a2dPatternFillData( const wxBitmap& stipple, a2dFillStyle style = a2dFILL_STIPPLE );
4346 
4347  a2dPatternFillData( const wxFileName& filename, a2dFillStyle style = a2dFILL_STIPPLE );
4348 
4349  //!destructor
4351 
4352  //! set stipple style
4353  void SetStipple( const wxBitmap& stipple );
4354 
4355  const wxBitmap& GetStipple() const { return m_stipple; }
4356 
4357  //! can contain the filename if pattern was read froma file
4358  /*!
4359  Certain input formats ( Like CVG ) can hold the path to the pattern.
4360  */
4361  wxString GetFileName() { return m_filename; }
4362 
4363  a2dFillStyle GetStyle() const;
4364 
4365  void SetStyle( a2dFillStyle style );
4366 
4367 #if wxART2D_USE_CVGIO
4368  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
4369  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
4370 #endif //wxART2D_USE_CVGIO
4371 
4372  wxBitmap m_stipple;
4373 
4374  //! if the pattern was loaded from a file, this contains the path to this file.
4375  //! a2dGlobals->GetImagePathList() contains the search path for the file.
4376  wxString m_filename;
4377 
4378 };
4379 
4381 {
4382  m_stipple = wxNullBitmap;
4384  SetStyle( m_style );
4385 }
4386 
4387 a2dPatternFillData::a2dPatternFillData( const wxBitmap& stipple, a2dFillStyle style )
4388 {
4389  m_stipple = stipple;
4390 
4392  {
4393  wxASSERT_MSG( m_stipple.GetMask(), wxT( "require a mask for a2dFILL_STIPPLE_MASK_OPAQUE or a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT" ) );
4394  }
4395  SetStyle( style );
4396 }
4397 
4398 a2dPatternFillData::a2dPatternFillData( const wxFileName& filename, a2dFillStyle style )
4399 {
4400  m_filename = filename.GetFullPath();
4401 
4402  wxImage image;
4403  if ( m_filename.IsEmpty() )
4404  {
4405  wxLogError( _( "CVG : bitmap file for a2dPatternFill not specified or empty" ) );
4406  image = wxImage( 32, 32 );
4407  }
4408  else
4409  {
4410  wxString filename = a2dGlobals->GetImagePathList().FindValidPath( m_filename );
4411  if ( filename.IsEmpty() )
4412  {
4413  wxLogError( _( "CVG : Could not load bitmap \"%s\" for a2dPatternFill from path \"%s\" " ), m_filename.c_str(), a2dGlobals->GetImagePathList().GetAsString().c_str() );
4414  image = wxImage( 32, 32 );
4415  }
4416  else if ( ! image.LoadFile( filename, wxBITMAP_TYPE_BMP ) )
4417  {
4418  wxLogError( _( "CVG : Could not load bitmap %s for a2dPatternFill" ), filename.c_str() );
4419  image = wxImage( 32, 32 );
4420  }
4421  }
4422  m_stipple = wxBitmap( image );
4423 
4425  {
4426  wxColour white( wxT( "WHITE" ) );
4427  wxColour black( wxT( "BLACK" ) );
4428 
4429  wxMask* monochrome_mask = new wxMask( m_stipple, black );
4430  m_stipple.SetMask( monochrome_mask );
4431  }
4432  SetStyle( style );
4433 }
4434 
4435 void a2dPatternFillData::SetStipple( const wxBitmap& stipple )
4436 {
4437  m_stipple = stipple;
4438 }
4439 
4441 {
4442  m_stipple = other.m_stipple;
4443 }
4444 
4445 a2dFillStyle a2dPatternFillData::GetStyle() const
4446 {
4447  return m_style;
4448 }
4449 
4450 void a2dPatternFillData::SetStyle( a2dFillStyle style )
4451 {
4452  if ( style == a2dFILL_TRANSPARENT )
4454  else if ( style == a2dFILL_STIPPLE_MASK_OPAQUE ||
4456  )
4457  {
4458  if ( !m_stipple.GetMask() )
4459  {
4460  wxMask* mask = new wxMask( m_stipple, GetColour() );
4461  m_stipple.SetMask( mask );
4462  }
4463  m_style = style;
4464  }
4465  else if ( style == a2dFILL_STIPPLE )
4466  m_style = style;
4467  else
4468  wxFAIL_MSG( _( "invalid style for a2dPatternFillData" ) );
4469 }
4470 
4471 #if wxART2D_USE_CVGIO
4472 void a2dPatternFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
4473 {
4474  a2dTwoColourFillData::DoLoad( parent, parser, xmlparts );
4475  if ( xmlparts == a2dXmlSer_attrib )
4476  {
4477  wxString filename = parser.GetAttributeValue( wxT( "filename" ), wxT( "" ) );
4478  wxImage image;
4479  if ( filename.IsEmpty() )
4480  {
4481  wxLogError( _( "CVG : bitmap file for a2dPatternFillData not specified or empty" ) );
4482  image = wxImage( 32, 32 );
4483  }
4484  else
4485  {
4487  if ( m_filename.IsEmpty() )
4488  {
4489  wxLogError( _( "CVG : Could not load bitmap \"%s\" for a2dPatternFillData from path \"%s\" " ), filename.c_str(), a2dGlobals->GetImagePathList().GetAsString().c_str() );
4490  image = wxImage( 32, 32 );
4491  }
4492  else if ( ! image.LoadFile( m_filename, wxBITMAP_TYPE_BMP ) )
4493  {
4494  wxLogError( _( "CVG : Could not load bitmap %s for a2dPatternFillData" ), m_filename.c_str() );
4495  image = wxImage( 32, 32 );
4496  }
4497  }
4498  m_stipple = wxBitmap( image );
4499 
4500  m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT( "a2dFILL_STIPPLE" ) ) );
4501  SetStyle( m_style );
4502 
4504  {
4505  wxColour white( wxT( "WHITE" ) );
4506  wxColour black( wxT( "BLACK" ) );
4507 
4508  wxMask* monochrome_mask = new wxMask( m_stipple, black );
4509  m_stipple.SetMask( monochrome_mask );
4510  }
4511  }
4512  else
4513  {}
4514 }
4515 
4516 void a2dPatternFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
4517 {
4518  a2dTwoColourFillData::DoSave( parent, out, xmlparts, towrite );
4519  if ( xmlparts == a2dXmlSer_attrib )
4520  {
4521  if ( m_style != a2dFILL_STIPPLE )
4522  out.WriteAttribute( wxT( "style" ), FillStyle2String( GetStyle() ) );
4523 
4524  wxString filename = a2dGlobals->GetImagePathList().FindValidPath( m_filename );
4525  if ( filename.IsEmpty() )
4526  {
4527  // We can/may not save/use the original files, because the pattern may have changed inside the appl.
4528  // If available use the name of the orginal file.
4529  wxString fileTosave;
4530 
4531  wxString* layerfile = a2dGeneralGlobals->GetVariablesHash().GetVariableString( wxT( "wxart2dlayers" ) );
4532  wxString* layerfiledir = a2dGeneralGlobals->GetVariablesHash().GetVariableString( wxT( "layerFileSavePath" ) );
4533 
4534  if ( layerfile && !layerfile->IsEmpty() )
4535  {
4536  if ( !wxDirExists( *layerfiledir ) )
4537  wxMkdir( *layerfiledir );
4538  wxString mess = *layerfiledir + *layerfile + wxT( " directory does not exist, and could not be created" );
4539  wxASSERT_MSG( wxDirExists( *layerfiledir ) , mess );
4540 
4541  fileTosave = *layerfiledir + wxFILE_SEP_PATH;
4542  }
4543 
4544  if ( m_filename.IsEmpty() )
4545  {
4546  m_filename.Printf( _T( "canpat_%ld.bmp" ), wxGenNewId() );
4547  fileTosave += m_filename;
4548  }
4549  else
4550  fileTosave += wxFileNameFromPath( m_filename );
4551  bool isOke = m_stipple.SaveFile( fileTosave, wxBITMAP_TYPE_BMP );
4552  if ( !isOke )
4553  wxLogError( _( "Could not save bitmap %s for a2dPatternFillData" ), fileTosave.c_str() );
4554  out.WriteAttribute( wxT( "filename" ), wxFileNameFromPath( m_filename ) );
4555  }
4556  else
4557  out.WriteAttribute( wxT( "filename" ), wxFileNameFromPath( m_filename ) );
4558  }
4559  else
4560  {}
4561 
4562 }
4563 #endif //wxART2D_USE_CVGIO
4564 
4565 //----------------------------------------------------------------------------
4566 // a2dFill
4567 //----------------------------------------------------------------------------
4568 
4570 {
4571 }
4572 
4573 a2dFill::a2dFill( const wxColour& col, a2dFillStyle style )
4574 {
4575  m_refData = new a2dOneColourFillData( col, style );
4576 }
4577 
4578 a2dFill::a2dFill( const wxColour& col, const wxColour& col2, a2dFillStyle style )
4579 {
4580  if ( style == a2dFILL_GRADIENT_FILL_XY_LINEAR )
4581  {
4582  m_refData = new a2dLinearGradientFillData( col, col2, 0, 0, 0, 0 );
4583  }
4584  else if ( style == a2dFILL_GRADIENT_FILL_XY_RADIAL )
4585  {
4586  m_refData = new a2dRadialGradientFillData( col, col2, 0, 0, 0, 0, 0 );
4587  }
4588  else if ( style >= a2dFIRST_TWOCOL_HATCH && style <= a2dLAST_TWOCOL_HATCH )
4589  {
4590  m_refData = new a2dHatchFillData( col, col2, style );
4591  }
4592  else if ( style == a2dFILL_STIPPLE ||
4593  style == a2dFILL_STIPPLE_MASK_OPAQUE ||
4595  )
4596  {
4597  m_refData = new a2dPatternFillData( wxNullBitmap, style );
4598  }
4599  else
4600  {
4601  wxFAIL_MSG( _( "invalid style for in a2dFill for two colours" ) );
4602  }
4603 }
4604 
4605 a2dFill::a2dFill( const wxColour& col, const wxColour& col2,
4606  double x1, double y1, double x2, double y2 )
4607 {
4608  m_refData = new a2dLinearGradientFillData( col, col2, x1, y1, x2, y2 );
4609 }
4610 
4611 a2dFill::a2dFill( const wxColour& col, const wxColour& col2,
4612  double xfc, double yfc, double xe, double ye, double radius )
4613 {
4614  m_refData = new a2dRadialGradientFillData( col, col2, xfc, yfc, xe, ye, radius );
4615 }
4616 
4617 a2dFill::a2dFill( const a2dFill& fill )
4618  : wxObject( fill )
4619 {
4620 }
4621 
4622 a2dFill::a2dFill( const wxBitmap& stipple, a2dFillStyle style )
4623 {
4624  m_refData = new a2dPatternFillData( stipple, style );
4625 }
4626 
4627 a2dFill::a2dFill( const wxBitmap& stipple, const wxColour& col, const wxColour& col2, a2dFillStyle style )
4628 {
4629  m_refData = new a2dPatternFillData( stipple, style );
4630  SetColour( col );
4631  SetColour2( col2 );
4632 }
4633 
4634 a2dFill::a2dFill( const wxFileName& filename, a2dFillStyle style )
4635 {
4636  m_refData = new a2dPatternFillData( filename, style );
4637 }
4638 
4639 a2dFill::a2dFill( const wxFileName& filename, const wxColour& col, const wxColour& col2, a2dFillStyle style )
4640 {
4641  m_refData = new a2dPatternFillData( filename, style );
4642  SetColour( col );
4643  SetColour2( col2 );
4644 }
4645 
4646 a2dFill::a2dFill( const wxBrush& brush )
4647 {
4648  if ( brush == wxNullBrush )
4649  {
4650  }
4651  else if ( brush.GetStyle() == wxTRANSPARENT || brush.GetStyle() == wxSOLID || brush.IsHatch() )
4652  m_refData = new a2dOneColourFillData( brush );
4653  else if ( brush.GetStyle() == wxSTIPPLE )
4654  {
4655  m_refData = new a2dPatternFillData( *brush.GetStipple(), a2dFILL_STIPPLE );
4656  ( ( a2dPatternFillData* )m_refData )->SetColour( brush.GetColour() );
4657  }
4658  else if ( brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
4659  {
4660  m_refData = new a2dPatternFillData( *brush.GetStipple(), a2dFILL_STIPPLE_MASK_OPAQUE );
4661  ( ( a2dPatternFillData* )m_refData )->SetColour( brush.GetColour() );
4662  }
4663 }
4664 
4666 {
4667 }
4668 
4669 a2dFillType a2dFill::GetType( void ) const
4670 {
4671  if ( !m_refData )
4672  return a2dFILL_NULL;
4673  return ( ( a2dFillRefData* ) m_refData )->GetType();
4674 }
4675 
4676 
4677 a2dFill& a2dFill::UnShare()
4678 {
4679  wxObject::UnShare();
4680  return *this;
4681 }
4682 
4683 wxObjectRefData* a2dFill::CreateRefData() const
4684 {
4685  switch ( GetType() )
4686  {
4687  case a2dFILL_NULL:
4688  return new a2dOneColourFillData(); //dummy to be removed soon
4689  case a2dFILL_ONE_COLOUR:
4690  return new a2dOneColourFillData();
4692  return new a2dHatchFillData();
4694  return new a2dLinearGradientFillData();
4696  return new a2dRadialGradientFillData();
4697  case a2dFILL_BITMAP:
4698  return new a2dPatternFillData();
4699  default:
4700  break;
4701  }
4702  return NULL;
4703 }
4704 
4705 wxObjectRefData* a2dFill::CloneRefData( const wxObjectRefData* data ) const
4706 {
4707  switch ( ( ( a2dFillRefData* ) data )->GetType() )
4708  {
4709  case a2dFILL_NULL:
4710  return NULL;
4711  case a2dFILL_ONE_COLOUR:
4712  return new a2dOneColourFillData( *( ( const a2dOneColourFillData* )data ) );
4714  return new a2dHatchFillData( *( ( const a2dHatchFillData* )data ) );
4716  return new a2dLinearGradientFillData( *( ( const a2dLinearGradientFillData* )data ) );
4718  return new a2dRadialGradientFillData( *( ( const a2dRadialGradientFillData* )data ) );
4719  case a2dFILL_BITMAP:
4720  return new a2dPatternFillData( *( ( const a2dPatternFillData* )data ) );
4721  default:
4722  break;
4723  }
4724  return NULL;
4725 }
4726 
4728 {
4729  wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_LINEAR, _T( "No ref data" ) );
4730  return ( ( a2dLinearGradientFillData* )GetRefData() )->GetStart();
4731 }
4732 
4734 {
4735  wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_LINEAR, _T( "No ref data" ) );
4736  return ( ( a2dLinearGradientFillData* )GetRefData() )->GetStop();
4737 }
4738 
4739 wxUint32 a2dFill::GetStamp() const
4740 {
4741  switch ( GetType() )
4742  {
4744  return ( ( a2dLinearGradientFillData* )GetRefData() )->GetStamp();
4746  return ( ( a2dRadialGradientFillData* )GetRefData() )->GetStamp();
4747  default:
4748  wxFAIL_MSG( _T( "Not a gradient fill" ) );
4749  }
4750  return 0;
4751 }
4752 
4754 {
4755  wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_RADIAL, _T( "No ref data" ) );
4756  return ( ( a2dRadialGradientFillData* )GetRefData() )->GetCenter();
4757 }
4758 
4760 {
4761  wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_RADIAL, _T( "No ref data" ) );
4762  return ( ( a2dRadialGradientFillData* )GetRefData() )->GetFocal();
4763 }
4764 
4765 double a2dFill::GetRadius() const
4766 {
4767  wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_RADIAL, _T( "No ref data" ) );
4768  return ( ( a2dRadialGradientFillData* )GetRefData() )->GetRadius();
4769 }
4770 
4771 void a2dFill::SetAlpha( wxUint8 val )
4772 {
4773  AllocExclusive();
4774 
4775  switch ( GetType() )
4776  {
4777  case a2dFILL_NULL:
4778  UnRef();
4779  break;
4780  case a2dFILL_ONE_COLOUR:
4781  {
4782  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4783  wxColour newcol = ( ( a2dOneColourFillData* )GetRefData() )->GetColour();
4784  newcol.Set( newcol.Red(), newcol.Green(), newcol.Blue(), val );
4785  ( ( a2dOneColourFillData* )GetRefData() )->SetColour( newcol );
4786  break;
4787  }
4791  case a2dFILL_BITMAP:
4792  {
4793  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4794  wxColour newcol = ( ( a2dTwoColourFillData* )GetRefData() )->GetColour();
4795  newcol.Set( newcol.Red(), newcol.Green(), newcol.Blue(), val );
4796  ( ( a2dTwoColourFillData* )GetRefData() )->SetColour( newcol );
4797  break;
4798  }
4799  default:
4800  break;
4801  }
4802 }
4803 
4804 wxUint8 a2dFill::GetAlpha() const
4805 {
4806  switch ( GetType() )
4807  {
4808  case a2dFILL_NULL:
4809  return a2dFILL_NULLFILL;
4810  case a2dFILL_ONE_COLOUR:
4811  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4812  return ( ( a2dOneColourFillData* )GetRefData() )->GetColour().Alpha();
4813  break;
4817  case a2dFILL_BITMAP:
4818  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4819  return ( ( a2dTwoColourFillData* )GetRefData() )->GetColour().Alpha();
4820  break;
4821  default:
4822  break;
4823  }
4824  return 255;
4825 }
4826 
4827 
4828 a2dFillStyle a2dFill::GetStyle() const
4829 {
4830  switch ( GetType() )
4831  {
4832  case a2dFILL_NULL:
4833  return a2dFILL_NULLFILL;
4834  case a2dFILL_ONE_COLOUR:
4835  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4836  return ( ( a2dOneColourFillData* )GetRefData() )->GetStyle();
4837  break;
4841  case a2dFILL_BITMAP:
4842  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4843  return ( ( a2dTwoColourFillData* )GetRefData() )->GetStyle();
4844  break;
4845  default:
4846  break;
4847  }
4848  return a2dFILL_NULLFILL;
4849 }
4850 
4851 void a2dFill::SetStyle( a2dFillStyle style )
4852 {
4853  a2dFillStyle cur_style = GetStyle();
4854  if ( cur_style == style )
4855  return;
4856 
4857  AllocExclusive();
4858 
4859  a2dFillType type = GetTypeForStyle( style );
4860 
4861  if ( type == GetType() )
4862  {
4863  switch ( GetType() )
4864  {
4865  case a2dFILL_NULL:
4866  UnRef();
4867  break;
4868  case a2dFILL_ONE_COLOUR:
4869  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4870  ( ( a2dOneColourFillData* )GetRefData() )->SetStyle( style );
4871  break;
4873  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4874  ( ( a2dHatchFillData* )GetRefData() )->SetStyle( style );
4875  break;
4877  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4878  ( ( a2dLinearGradientFillData* )GetRefData() )->SetStyle( style );
4879  break;
4881  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4882  ( ( a2dRadialGradientFillData* )GetRefData() )->SetStyle( style );
4883  break;
4884  case a2dFILL_BITMAP:
4885  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4886  ( ( a2dPatternFillData* )GetRefData() )->SetStyle( style );
4887  break;
4888  default:
4889  break;
4890  }
4891  }
4892  else
4893  {
4894  a2dFillRefData* newrefdata = NULL;
4895  switch ( type )
4896  {
4897  case a2dFILL_NULL:
4898  break;
4899  case a2dFILL_ONE_COLOUR:
4900  newrefdata = new a2dOneColourFillData( GetColour(), style );
4901  break;
4903  newrefdata = new a2dHatchFillData( GetColour(), GetColour2(), style );
4904  break;
4906  newrefdata = new a2dLinearGradientFillData( GetColour(), GetColour2(), 0, 0, 0, 0 );
4907  break;
4909  newrefdata = new a2dRadialGradientFillData( GetColour(), GetColour2(), 0, 0, 0, 0, 0 );
4910  break;
4911  case a2dFILL_BITMAP:
4912  newrefdata = new a2dPatternFillData( wxNullBitmap, style );
4913  break;
4914  default:
4915  break;
4916  }
4917  UnRef();
4918  m_refData = newrefdata;
4919  }
4920 }
4921 
4922 a2dFillType a2dFill::GetTypeForStyle( a2dFillStyle style ) const
4923 {
4924  if ( style == a2dFILL_NULLFILL || style == a2dFILL_LAYER || style == a2dFILL_INHERIT )
4925  return a2dFILL_NULL;
4926  else if ( style == a2dFILL_TRANSPARENT && GetType() != a2dFILL_NULL )
4927  return GetType();
4928  else if ( style == a2dFILL_SOLID || style == a2dFILL_TRANSPARENT || style == a2dFILL_NULLFILL )
4929  return a2dFILL_ONE_COLOUR;
4930  else if ( style >= a2dFIRST_TWOCOL_HATCH && style <= a2dLAST_TWOCOL_HATCH )
4931  return a2dFILL_HATCH_TWO_COLOUR;
4932  else if ( style >= a2dFIRST_HATCH && style <= a2dLAST_HATCH )
4933  return a2dFILL_ONE_COLOUR;
4934  else if ( style == a2dFILL_GRADIENT_FILL_XY_LINEAR )
4936  else if ( style == a2dFILL_GRADIENT_FILL_XY_RADIAL )
4938  else if ( style == a2dFILL_STIPPLE ||
4939  style == a2dFILL_STIPPLE_MASK_OPAQUE ||
4941  )
4942  return a2dFILL_BITMAP;
4943  else
4944  wxFAIL_MSG( _( "invalid style for in a2dFill" ) );
4945 
4946  return a2dFILL_NULL;
4947 }
4948 
4949 void a2dFill::SetColour2( const wxColour& col )
4950 {
4951  AllocExclusive();
4952  switch ( GetType() )
4953  {
4954  case a2dFILL_NULL:
4955  UnRef();
4956  break;
4960  case a2dFILL_BITMAP:
4961  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4962  ( ( a2dTwoColourFillData* )GetRefData() )->SetColour2( col );
4963  break;
4964  default:
4965  break;
4966  }
4967 }
4968 
4969 wxColour a2dFill::GetColour2() const
4970 {
4971  switch ( GetType() )
4972  {
4973  case a2dFILL_NULL:
4974  break;
4978  case a2dFILL_BITMAP:
4979  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4980  return ( ( a2dTwoColourFillData* )GetRefData() )->GetColour2();
4981  break;
4982  default:
4983  break;
4984  }
4985  return wxColour( 0, 0, 0, 0 ); //*wxBLACK;
4986 }
4987 
4988 void a2dFill::SetColour( const wxColour& col )
4989 {
4990  AllocExclusive();
4991  switch ( GetType() )
4992  {
4993  case a2dFILL_NULL:
4994  UnRef();
4995  break;
4996  case a2dFILL_ONE_COLOUR:
4997  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
4998  ( ( a2dOneColourFillData* )GetRefData() )->SetColour( col );
4999  break;
5003  case a2dFILL_BITMAP:
5004  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
5005  ( ( a2dTwoColourFillData* )GetRefData() )->SetColour( col );
5006  break;
5007  default:
5008  break;
5009  }
5010 }
5011 
5012 wxColour a2dFill::GetColour() const
5013 {
5014  switch ( GetType() )
5015  {
5016  case a2dFILL_NULL:
5017  break;
5018  case a2dFILL_ONE_COLOUR:
5019  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
5020  return ( ( a2dOneColourFillData* )GetRefData() )->GetColour();
5021  break;
5025  case a2dFILL_BITMAP:
5026  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
5027  return ( ( a2dTwoColourFillData* )GetRefData() )->GetColour();
5028  break;
5029  default:
5030  break;
5031  }
5032  return *wxBLACK;
5033 }
5034 
5035 void a2dFill::SetStipple( const wxBitmap& stipple )
5036 {
5037  AllocExclusive();
5038  if ( GetType() == a2dFILL_BITMAP )
5039  ( ( a2dPatternFillData* )m_refData )->SetStipple( stipple );
5040  else
5041  {
5042  UnRef();
5043  m_refData = new a2dPatternFillData( stipple, a2dFILL_STIPPLE );
5044  }
5045 }
5046 
5047 const wxBitmap& a2dFill::GetStipple() const
5048 {
5049  if ( GetType() == a2dFILL_BITMAP )
5050  {
5051  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
5052  return ( ( const a2dPatternFillData* )m_refData )->GetStipple();
5053  }
5054  else
5055  {
5056  return wxNullBitmap;
5057  }
5058 }
5059 
5060 void a2dFill::SetFilling( bool OnOff )
5061 {
5062  if ( ( ( a2dFillRefData* )GetRefData() )->m_fillOn == OnOff )
5063  return;
5064 
5065  AllocExclusive();
5066  ( ( a2dFillRefData* )GetRefData() )->m_fillOn = OnOff;
5067 }
5068 
5070 {
5071  switch ( GetType() )
5072  {
5073  case a2dFILL_NULL:
5074  return false;
5075  }
5076  return ( ( a2dFillRefData* )GetRefData() )->m_fillOn;
5077 }
5078 
5079 #if wxART2D_USE_CVGIO
5080 void a2dFill::Load( wxObject* parent, a2dIOHandlerXmlSerIn& parser )
5081 {
5082  a2dFillType type;
5083 
5084  parser.Require( START_TAG, wxT( "o" ) );
5085 
5086  wxString classname = parser.GetAttributeValue( wxT( "classname" ) );
5087  if ( classname == wxT( "a2dOneColourFill" ) )
5088  type = a2dFILL_ONE_COLOUR;
5089  else if ( classname == wxT( "a2dLinearGradientFill" ) )
5091  else if ( classname == wxT( "a2dRadialGradientFill" ) )
5093  else if ( classname == wxT( "a2dPatternFill" ) )
5094  type = a2dFILL_BITMAP;
5095  else
5096  {
5097  wxString stype = parser.GetAttributeValue( wxT( "type" ), wxT( "a2dFILL_NULL" ) );
5098  if ( stype == wxT( "a2dFILL_NULL" ) )
5099  type = a2dFILL_NULL;
5100  else if ( stype == wxT( "a2dFILL_ONE_COLOUR" ) )
5101  type = a2dFILL_ONE_COLOUR;
5102  else if ( stype == wxT( "a2dFILL_HATCH_TWO_COLOUR" ) )
5103  type = a2dFILL_HATCH_TWO_COLOUR;
5104  else if ( stype == wxT( "a2dFILL_GRADIENT_FILL_LINEAR" ) )
5106  else if ( stype == wxT( "a2dFILL_GRADIENT_FILL_RADIAL" ) )
5108  else if ( stype == wxT( "a2dFILL_BITMAP" ) )
5109  type = a2dFILL_BITMAP;
5110  }
5111 
5112  switch ( type )
5113  {
5114  case a2dFILL_NULL:
5115  break;
5116  case a2dFILL_ONE_COLOUR:
5117  m_refData = new a2dOneColourFillData( *wxBLACK );
5118  break;
5120  m_refData = new a2dHatchFillData( *wxBLACK, *wxBLACK, a2dFILL_TWOCOL_BDIAGONAL_HATCH );
5121  break;
5123  m_refData = new a2dLinearGradientFillData( *wxBLACK, *wxBLACK, 0, 0, 0, 0 );
5124  break;
5126  m_refData = new a2dRadialGradientFillData( *wxBLACK, *wxBLACK, 0, 0, 0, 0, 0 );
5127  break;
5128  case a2dFILL_BITMAP:
5129  m_refData = new a2dPatternFillData( wxNullBitmap );
5130  break;
5131  default:
5132  break;
5133  }
5134 
5135  if ( GetRefData() )
5136  {
5137  ( ( a2dFillRefData* )GetRefData() )->DoLoad( parent, parser, a2dXmlSer_attrib );
5138  parser.Next();
5139 
5140  ( ( a2dFillRefData* )GetRefData() )->DoLoad( parent, parser, a2dXmlSer_Content );
5141  }
5142  else
5143  parser.Next();
5144 
5145  parser.Require( END_TAG, wxT( "o" ) );
5146  parser.Next();
5147 }
5148 
5149 void a2dFill::Save( wxObject* parent, a2dIOHandlerXmlSerOut& out , a2dObjectList* towrite )
5150 {
5151  out.WriteStartElementAttributes( wxT( "o" ) );
5152  out.WriteAttribute( wxT( "classname" ), GetClassInfo()->GetClassName() );
5153 
5154  switch ( GetType() )
5155  {
5156  case a2dFILL_NULL:
5157  break;
5158  case a2dFILL_ONE_COLOUR:
5159  out.WriteAttribute( wxT( "type" ), wxT( "a2dFILL_ONE_COLOUR" ) );
5160  break;
5162  out.WriteAttribute( wxT( "type" ), wxT( "a2dFILL_HATCH_TWO_COLOUR" ) );
5163  break;
5165  out.WriteAttribute( wxT( "type" ), wxT( "a2dFILL_GRADIENT_FILL_LINEAR" ) );
5166  break;
5168  out.WriteAttribute( wxT( "type" ), wxT( "a2dFILL_GRADIENT_FILL_RADIAL" ) );
5169  break;
5170  case a2dFILL_BITMAP:
5171  out.WriteAttribute( wxT( "type" ), wxT( "a2dFILL_BITMAP" ) );
5172  break;
5173  default:
5174  break;
5175  }
5176 
5177  if ( GetRefData() )
5178  ( ( a2dFillRefData* )GetRefData() )->DoSave( parent, out, a2dXmlSer_attrib, towrite );
5179  out.WriteEndAttributes();
5180  if ( GetRefData() )
5181  ( ( a2dFillRefData* )GetRefData() )->DoSave( parent, out, a2dXmlSer_Content, towrite );
5182  out.WriteEndElement();
5183 }
5184 #endif //wxART2D_USE_CVGIO
5185 
5186 //----------------------------------------------------------------------------
5187 // a2dStrokeRefData
5188 //----------------------------------------------------------------------------
5189 
5190 //! Internal to a2dStroke for refcounting in wxObject style
5191 /*!
5192  \ingroup style
5193 */
5194 class A2DARTBASEDLLEXP a2dStrokeRefData : public wxObjectRefData
5195 {
5196 public:
5197 
5198  virtual a2dStrokeType GetType( void ) const { return a2dSTROKE_NULL; }
5199 
5200  //!constructor
5202  {
5203  }
5204 
5205  a2dStrokeRefData( const a2dStrokeRefData& other )
5206  : wxObjectRefData()
5207  {
5208  }
5209 
5210 #if wxART2D_USE_CVGIO
5211  //! Save settings.
5212  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts, a2dObjectList* towrite ) = 0;
5213  //! Load settings.
5214  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts ) = 0;
5215 #endif //wxART2D_USE_CVGIO
5216 
5217 };
5218 
5219 //----------------------------------------------------------------------------
5220 // a2dOneColourStrokeData
5221 //----------------------------------------------------------------------------
5222 
5223 //! convert a style enum to a string
5225 {
5226  switch ( style )
5227  {
5228  case a2dSTROKE_SOLID: return wxT( "a2dSTROKE_SOLID" );
5229  case a2dSTROKE_TRANSPARENT: return wxT( "a2dSTROKE_TRANSPARENT" );
5230  case a2dSTROKE_DOT: return wxT( "a2dSTROKE_DOT" );
5231  case a2dSTROKE_LONG_DASH: return wxT( "a2dSTROKE_LONG_DASH" );
5232  case a2dSTROKE_SHORT_DASH: return wxT( "a2dSTROKE_SHORT_DASH" );
5233  case a2dSTROKE_DOT_DASH: return wxT( "a2dSTROKE_DOT_DASH" );
5234  case a2dSTROKE_USER_DASH: return wxT( "a2dSTROKE_USER_DASH" );
5235  case a2dSTROKE_BDIAGONAL_HATCH: return wxT( "a2dSTROKE_BDIAGONAL_HATCH" );
5236  case a2dSTROKE_CROSSDIAG_HATCH: return wxT( "a2dSTROKE_CROSSDIAG_HATCH" );
5237  case a2dSTROKE_FDIAGONAL_HATCH: return wxT( "a2dSTROKE_FDIAGONAL_HATCH" );
5238  case a2dSTROKE_CROSS_HATCH: return wxT( "a2dSTROKE_CROSS_HATCH" );
5239  case a2dSTROKE_HORIZONTAL_HATCH: return wxT( "a2dSTROKE_HORIZONTAL_HATCH" );
5240  case a2dSTROKE_VERTICAL_HATCH: return wxT( "a2dSTROKE_VERTICAL_HATCH" );
5241  case a2dSTROKE_STIPPLE: return wxT( "a2dSTROKE_STIPPLE" );
5242  case a2dSTROKE_STIPPLE_MASK_OPAQUE: return wxT( "a2dSTROKE_STIPPLE_MASK_OPAQUE" );
5243  case a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT: return wxT( "a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT" );
5244  //case a2dSTROKE_GRADIENT_STROKE_XY_LINEAR: return wxT("a2dSTROKE_GRADIENT_FILL_XY_LINEAR");
5245  //case a2dSTROKE_GRADIENT_STROKE_XY_RADIAL: return wxT("a2dSTROKE_GRADIENT_FILL_XY_RADIAL");
5246  //case a2dSTROKE_GRADIENT_STROKE_XY_DROP: return wxT("a2dSTROKE_GRADIENT_FILL_XY_DROP");
5247  case a2dSTROKE_INHERIT: return wxT( "a2dSTROKE_INHERIT" );
5248  case a2dSTROKE_LAYER: return wxT( "a2dSTROKE_LAYER" );
5249  case a2dSTROKE_NULLSTROKE: return wxT( "a2dSTROKE_NULLSTROKE" );
5250 
5251  default:
5252  a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "CVG : invalid style" ) );
5253  }
5254  return wxT( "a2dSTROKE_NULLFILL" );
5255 }
5256 
5257 //! convert a string to a style enum
5258 a2dStrokeStyle StrokeString2Style( const wxString& stylestr )
5259 {
5260  if ( stylestr == wxT( "a2dSTROKE_SOLID" ) )
5261  return a2dSTROKE_SOLID;
5262  if ( stylestr == wxT( "a2dSTROKE_TRANSPARENT" ) )
5263  return a2dSTROKE_TRANSPARENT;
5264  if ( stylestr == wxT( "a2dSTROKE_DOT" ) )
5265  return a2dSTROKE_DOT;
5266  if ( stylestr == wxT( "a2dSTROKE_LONG_DASH" ) )
5267  return a2dSTROKE_LONG_DASH;
5268  if ( stylestr == wxT( "a2dSTROKE_SHORT_DASH" ) )
5269  return a2dSTROKE_SHORT_DASH;
5270  if ( stylestr == wxT( "a2dSTROKE_DOT_DASH" ) )
5271  return a2dSTROKE_DOT_DASH;
5272  if ( stylestr == wxT( "a2dSTROKE_USER_DASH" ) )
5273  return a2dSTROKE_USER_DASH;
5274  if ( stylestr == wxT( "a2dSTROKE_BDIAGONAL_HATCH" ) )
5276  if ( stylestr == wxT( "a2dSTROKE_CROSSDIAG_HATCH" ) )
5278  if ( stylestr == wxT( "a2dSTROKE_FDIAGONAL_HATCH" ) )
5280  if ( stylestr == wxT( "a2dSTROKE_CROSS_HATCH" ) )
5281  return a2dSTROKE_CROSS_HATCH;
5282  if ( stylestr == wxT( "a2dSTROKE_HORIZONTAL_HATCH" ) )
5284  if ( stylestr == wxT( "a2dSTROKE_VERTICAL_HATCH" ) )
5285  return a2dSTROKE_VERTICAL_HATCH;
5286  if ( stylestr == wxT( "a2dSTROKE_STIPPLE" ) )
5287  return a2dSTROKE_STIPPLE;
5288  if ( stylestr == wxT( "a2dSTROKE_STIPPLE_MASK_OPAQUE" ) )
5290  if ( stylestr == wxT( "a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT" ) )
5292  /*
5293  if ( stylestr == wxT("a2dSTROKE_GRADIENT_STROKE_XY_LINEAR") )
5294  return a2dSTROKE_GRADIENT_FILL_XY_LINEAR;
5295  if ( stylestr == wxT("a2dSTROKE_GRADIENT_STROKE_XY_RADIAL") )
5296  return a2dSTROKE_GRADIENT_FILL_XY_RADIAL;
5297  if ( stylestr == wxT("a2dSTROKE_GRADIENT_STROKE_XY_DROP") )
5298  return a2dSTROKE_GRADIENT_FILL_XY_DROP;
5299  */
5300  if ( stylestr == wxT( "a2dSTROKE_INHERIT" ) )
5301  return a2dSTROKE_INHERIT;
5302  if ( stylestr == wxT( "a2dSTROKE_LAYER" ) )
5303  return a2dSTROKE_LAYER;
5304  if ( stylestr == wxT( "a2dSTROKE_NULLSTROKE" ) )
5305  return a2dSTROKE_NULLSTROKE;
5306 
5307  if ( !stylestr.IsEmpty() ) //old style settings
5308  {
5309  long num;
5310  stylestr.ToLong( &num );
5311  return ( a2dStrokeStyle ) num;
5312  }
5313 
5314  a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "CVG : invalid style %s" ), stylestr.c_str() );
5315 
5316  return a2dSTROKE_NULLSTROKE;
5317 }
5318 
5319 
5320 //! One Colour Fill
5321 /*!
5322 A second colour is not saved, but when asked for it return wxBLACK
5323 
5324  \ingroup property style
5325 */
5326 class A2DARTBASEDLLEXP a2dOneColourStrokeData : public a2dStrokeRefData
5327 {
5328 
5329 private:
5330 
5331  friend class a2dStroke;
5332 
5333 public:
5334 
5335  virtual a2dStrokeType GetType( void ) const { return a2dSTROKE_ONE_COLOUR; }
5336 
5337 protected:
5338 
5339  //!constructor
5340  a2dOneColourStrokeData( void );
5341 
5343 
5344  //!constructor
5345  a2dOneColourStrokeData( const wxColour& col, a2dStrokeStyle style = a2dSTROKE_SOLID );
5346 
5347  a2dOneColourStrokeData( const wxPen& stroke );
5348 
5349  //!destructor
5351 
5352  static a2dOneColourStrokeData* Create( const wxColour& col, a2dStrokeStyle style = a2dSTROKE_SOLID );
5353 
5354  void SetColour( const wxColour& col ) { m_colour1 = col; }
5355 
5356  //! return colour
5357  wxColour GetColour() const { return m_colour1; }
5358 
5359  void SetJoin( wxPenJoin join_style ) { m_join = join_style; }
5360 
5361  void SetCap( wxPenCap cap_style ) { m_cap = cap_style; }
5362 
5363  wxPenCap GetCap() { return m_cap; }
5364 
5365  wxPenJoin GetJoin() { return m_join; }
5366 
5367  //!Set width of stroke in world coordinates.
5368  void SetWidth( float width ) { m_width = width; }
5369 
5370  //!Get width of stroke in world or device coordinates.
5371  //!(depending on pixel or non pixel stroke).
5372  virtual float GetWidth() const { return m_width; }
5373 
5374  virtual float GetExtend() const { return m_width; }
5375 
5376  //!set pixelstoke flag, stroke width is defined in pixels else in worldcoordinates
5377  void SetPixelStroke( bool pixelstroke ) { m_pixelstroke = pixelstroke; }
5378 
5379  //!if the width is pixels or not.
5380  inline bool GetPixelStroke() const { return m_pixelstroke; }
5381 
5382  a2dStrokeStyle GetStyle( void ) const;
5383 
5384  void SetStyle( a2dStrokeStyle style );
5385 
5386 #if wxART2D_USE_CVGIO
5387  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
5388  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
5389 #endif //wxART2D_USE_CVGIO
5390 
5391  wxColour m_colour1;
5392 
5393  //!width of stroke in world coordinates
5394  float m_width;
5395 
5396  //!set if stroke is in pixels
5398 
5399  //!Sets the pen join style, which may be one of wxJOIN_BEVEL, wxJOIN_ROUND (default) and wxJOIN_MITER.
5400  wxPenJoin m_join;
5401 
5402  //!Sets the pen cap style, which may be one of wxCAP_ROUND (default), wxCAP_PROJECTING and wxCAP_BUTT.
5403  wxPenCap m_cap;
5404 
5405  a2dDash* m_dash;
5406 
5407  a2dStrokeStyle m_style;
5408 
5409 };
5410 
5411 a2dOneColourStrokeData* a2dOneColourStrokeData::Create( const wxColour& col, a2dStrokeStyle style )
5412 {
5413  return new a2dOneColourStrokeData( col, style );
5414 }
5415 
5417  : a2dStrokeRefData()
5418 {
5419  m_style = a2dSTROKE_SOLID;
5420  m_colour1 = *wxBLACK;
5421  m_join = wxJOIN_ROUND;
5422  m_cap = wxCAP_ROUND;
5423 
5424  m_pixelstroke = false;
5425  m_width = 0.0;
5426 
5427 }
5428 
5430  : a2dStrokeRefData()
5431 {
5432  m_colour1 = col;
5433  m_join = wxJOIN_ROUND;
5434  m_cap = wxCAP_ROUND;
5435 
5436  m_pixelstroke = false;
5437  m_width = 0.0;
5438 
5439  switch( style )
5440  {
5441  case a2dSTROKE_SOLID:
5442  case a2dSTROKE_TRANSPARENT:
5443  case a2dSTROKE_DOT:
5444  case a2dSTROKE_DOT_DASH:
5445  case a2dSTROKE_LONG_DASH:
5446  case a2dSTROKE_SHORT_DASH:
5447  case a2dSTROKE_USER_DASH:
5451  case a2dSTROKE_CROSS_HATCH:
5454  case a2dSTROKE_NULLSTROKE:
5455  m_style = style;
5456  break;
5457 
5458  case a2dSTROKE_STIPPLE: // Use the stipple bitmap.
5461  m_style = style;
5462  break;
5463 
5464  default:
5465  wxFAIL_MSG( _( "invalid style for a2dStroke" ) );
5466  }
5467 }
5468 
5470  : a2dStrokeRefData()
5471 {
5472  m_join = stroke.GetJoin();
5473  m_cap = stroke.GetCap();
5474 
5475  m_colour1 = stroke.GetColour();
5476 
5477  m_pixelstroke = true;
5478  if ( stroke != wxNullPen )
5479  {
5480  m_width = ( float ) stroke.GetWidth();
5481  switch( stroke.GetStyle() )
5482  {
5483  case wxSOLID: m_style = a2dSTROKE_SOLID;
5484  break;
5485  case wxTRANSPARENT: m_style = a2dSTROKE_TRANSPARENT;
5486  break;
5487  case wxDOT: m_style = a2dSTROKE_DOT;
5488  break;
5489  case wxLONG_DASH: m_style = a2dSTROKE_LONG_DASH;
5490  break;
5491  case wxSHORT_DASH: m_style = a2dSTROKE_SHORT_DASH;
5492  break;
5493  case wxDOT_DASH: m_style = a2dSTROKE_DOT_DASH;
5494  break;
5495  case wxBDIAGONAL_HATCH: m_style = a2dSTROKE_BDIAGONAL_HATCH;
5496  break;
5497  case wxCROSSDIAG_HATCH: m_style = a2dSTROKE_CROSSDIAG_HATCH;
5498  break;
5499  case wxFDIAGONAL_HATCH: m_style = a2dSTROKE_FDIAGONAL_HATCH;
5500  break;
5501  case wxCROSS_HATCH: m_style = a2dSTROKE_CROSS_HATCH;
5502  break;
5503  case wxHORIZONTAL_HATCH: m_style = a2dSTROKE_HORIZONTAL_HATCH;
5504  break;
5505  case wxVERTICAL_HATCH: m_style = a2dSTROKE_VERTICAL_HATCH;
5506  break;
5507  default:
5508  wxFAIL_MSG( _( "invalid style for a2dOneColourStroke" ) );
5509  }
5510  }
5511  else
5512  {
5513  m_width = 0;
5514  }
5515 }
5516 
5518  : a2dStrokeRefData( other )
5519 {
5520  m_colour1 = other.m_colour1;
5521  m_style = other.m_style;
5522  m_join = other.m_join;
5523  m_cap = other.m_cap;
5524  m_pixelstroke = other.m_pixelstroke;
5525  m_width = other.m_width;
5526  m_dash = other.m_dash;
5527 }
5528 
5529 a2dStrokeStyle a2dOneColourStrokeData::GetStyle() const
5530 {
5531  return m_style;
5532 }
5533 
5534 void a2dOneColourStrokeData::SetStyle( a2dStrokeStyle style )
5535 {
5536  switch( style )
5537  {
5538  case a2dSTROKE_SOLID:
5539  case a2dSTROKE_TRANSPARENT:
5540  case a2dSTROKE_DOT:
5541  case a2dSTROKE_DOT_DASH:
5542  case a2dSTROKE_LONG_DASH:
5543  case a2dSTROKE_SHORT_DASH:
5544  case a2dSTROKE_USER_DASH:
5548  case a2dSTROKE_CROSS_HATCH:
5551  case a2dSTROKE_NULLSTROKE:
5552  m_style = style;
5553  break;
5554 
5555  case a2dSTROKE_STIPPLE: // Use the stipple bitmap.
5558  m_style = style;
5559  break;
5560 
5561  default:
5562  wxFAIL_MSG( _( "invalid style for a2dStroke" ) );
5563  }
5564 }
5565 
5566 
5567 #if wxART2D_USE_CVGIO
5568 void a2dOneColourStrokeData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
5569 {
5570  if ( xmlparts == a2dXmlSer_attrib )
5571  {
5572  if ( m_style != a2dSTROKE_SOLID )
5573  out.WriteAttribute( wxT( "style" ), StrokeStyle2String( GetStyle() ) );
5574 
5575  if ( m_style != a2dSTROKE_TRANSPARENT )
5576  {
5577  switch ( m_cap )
5578  {
5579  case wxCAP_ROUND:
5580  //default
5581  //out.WriteAttribute( wxT( "cap" ), "round" );
5582  break;
5583  case wxCAP_PROJECTING:
5584  out.WriteAttribute( wxT( "cap" ), "projecting" );
5585  break;
5586  case wxCAP_BUTT:
5587  out.WriteAttribute( wxT( "cap" ), "butt" );
5588  break;
5589  default:
5590  break;
5591  }
5592  switch ( m_join )
5593  {
5594  case wxJOIN_BEVEL:
5595  out.WriteAttribute( wxT( "join" ), "bevel" );
5596  break;
5597  case wxJOIN_MITER:
5598  out.WriteAttribute( wxT( "join" ), "miter" );
5599  break;
5600  case wxJOIN_ROUND:
5601  //default
5602  //out.WriteAttribute( wxT( "join" ), "round" );
5603  break;
5604  default:
5605  break;
5606  }
5607  wxString strokeColour = wxTheColourDatabase->FindName( m_colour1 );
5608  if ( strokeColour.IsEmpty() )
5609  {
5610  out.WriteAttribute( wxT( "colour" ), wxT( "#" ) + ColourToHex( m_colour1 ) );
5611  }
5612  else
5613  {
5614  out.WriteAttribute( wxT( "colour" ), strokeColour );
5615  }
5616 
5617  if ( GetPixelStroke() )
5618  {
5619  out.WriteAttribute( wxT( "pixelwidth" ), GetPixelStroke() );
5620  }
5621 
5622  if ( m_width != 0 )
5623  {
5624  out.WriteAttribute( wxT( "width" ), m_width );
5625  }
5626  }
5627  }
5628  else
5629  {}
5630 }
5631 
5632 void a2dOneColourStrokeData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
5633 {
5634  if ( xmlparts == a2dXmlSer_attrib )
5635  {
5636  m_style = ( a2dStrokeStyle ) StrokeString2Style( parser.GetAttributeValue( wxT( "style" ), wxT( "a2dSTROKE_SOLID" ) ) );
5637  SetStyle( m_style );
5638  wxString cap = parser.GetAttributeValue( wxT( "cap" ) );
5639  if ( cap == "round")
5640  m_cap = wxCAP_ROUND;
5641  else if ( cap == "projecting")
5642  m_cap = wxCAP_PROJECTING;
5643  else if ( cap == "butt")
5644  m_cap = wxCAP_BUTT;
5645 
5646  wxString join = parser.GetAttributeValue( wxT( "join" ) );
5647  if ( join == "bevel")
5648  m_join = wxJOIN_BEVEL;
5649  else if ( join == "miter")
5650  m_join = wxJOIN_MITER;
5651  else if ( join == "round")
5652  m_join = wxJOIN_ROUND;
5653 
5654  wxString strokeColour = parser.GetAttributeValue( wxT( "colour" ) );
5655  if ( !strokeColour.IsEmpty() )
5656  {
5657  if ( strokeColour.GetChar( 0 ) == wxT( '#' ) )
5658  {
5659  m_colour1 = HexToColour( strokeColour.After( wxT( '#' ) ) );
5660  }
5661  else
5662  {
5663  m_colour1 = wxTheColourDatabase->Find( strokeColour );
5664  if ( !m_colour1.Ok() )
5665  m_colour1 = *wxBLACK;
5666  }
5667  }
5668  else
5669  m_colour1 = *wxBLACK;
5670 
5671  m_pixelstroke = parser.GetAttributeValueBool( wxT( "pixelwidth" ), false );
5672 
5673  m_width = ( float ) parser.GetAttributeValueDouble( wxT( "width" ) );
5674  }
5675  else
5676  {}
5677 }
5678 #endif //wxART2D_USE_CVGIO
5679 
5680 //----------------------------------------------------------------------------
5681 // a2dPatternStrokeData
5682 //----------------------------------------------------------------------------
5683 
5684 //!Filling using a wxbitmap
5685 /*!
5686 To Fill shapes with a bitmap. a2dSTROKE_STIPPLE
5687 In case a wxMask is set, to do transparent stipple drawing use style a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT.
5688 The fill colour1 will be used for non Transparent parts in the brush bitmap,
5689 while other parts will be transparent.
5690 In case a wxMask is set, use style wxSTIPPLE_MASK_OPAQUE to use colour1 and colour2 to fill with
5691 the wxMask in those colours.
5692 
5693  \ingroup property style
5694 */
5695 class A2DARTBASEDLLEXP a2dPatternStrokeData: public a2dOneColourStrokeData
5696 {
5697 
5698 private:
5699 
5700  friend class a2dStroke;
5701 
5702 public:
5703 
5704  virtual a2dStrokeType GetType( void ) const { return a2dSTROKE_BITMAP; }
5705 
5706 protected:
5707 
5708  //!constructor
5710 
5711  //!constructor
5713 
5714  //!constructor
5715  /*!
5716  \param stipple bitmap for stippling the primitive drawn.
5717  \param style can be a2dSTROKE_STIPPLE a2dSTROKE_STIPPLE_MASK_OPAQUE, a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT
5718 
5719  */
5720  a2dPatternStrokeData( const wxBitmap& stipple, a2dStrokeStyle style = a2dSTROKE_STIPPLE );
5721 
5722  a2dPatternStrokeData( const wxFileName& filename, a2dStrokeStyle style = a2dSTROKE_STIPPLE );
5723 
5724  //!destructor
5726 
5727  //! set stipple style
5728  void SetStipple( const wxBitmap& stipple ) { m_stipple = stipple; }
5729 
5730  const wxBitmap& GetStipple() const { return m_stipple; }
5731 
5732  //! can contain the filename if pattern was read froma file
5733  /*!
5734  Certain input formats ( Like CVG ) can hold the path to the pattern.
5735  */
5736  wxString GetFileName() { return m_filename; }
5737 
5738  a2dStrokeStyle GetStyle( void ) const;
5739 
5740  void SetStyle( a2dStrokeStyle style );
5741 
5742 #if wxART2D_USE_CVGIO
5743  virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
5744  virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
5745 #endif //wxART2D_USE_CVGIO
5746 
5747  wxBitmap m_stipple;
5748 
5749  //! if the pattern was loaded from a file, this contains the path to this file.
5750  //! a2dGlobals->GetImagePathList() contains the search path for the file.
5751  wxString m_filename;
5752 };
5753 
5755 {
5756  m_stipple = wxNullBitmap;
5757  m_style = a2dSTROKE_STIPPLE;
5758  SetStyle( m_style );
5759 }
5760 
5762 {
5763  m_stipple = stipple;
5764 
5765  wxASSERT_MSG( m_stipple.Ok(), wxT( "Stipple Bitmap not oke" ) );
5767  {
5768  wxASSERT_MSG( m_stipple.GetMask(), wxT( "require a mask for a2dSTROKE_STIPPLE_MASK_OPAQUE or a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT" ) );
5769  }
5770  SetStyle( style );
5771 }
5772 
5773 a2dPatternStrokeData::a2dPatternStrokeData( const wxFileName& filename, a2dStrokeStyle style )
5774 {
5775  m_filename = filename.GetFullPath();
5776 
5777  wxImage image;
5778  if ( m_filename.IsEmpty() )
5779  {
5780  wxLogError( _( "CVG : bitmap file for a2dPatternFill not specified or empty" ) );
5781  image = wxImage( 32, 32 );
5782  }
5783  else
5784  {
5785  wxString filename = a2dGlobals->GetImagePathList().FindValidPath( m_filename );
5786  if ( filename.IsEmpty() )
5787  {
5788  wxLogError( _( "CVG : Could not load bitmap \"%s\" for a2dPatternStroke from path \"%s\" " ), m_filename.c_str(), a2dGlobals->GetImagePathList().GetAsString().c_str() );
5789  image = wxImage( 32, 32 );
5790  }
5791  else if ( ! image.LoadFile( filename, wxBITMAP_TYPE_BMP ) )
5792  {
5793  wxLogError( _( "CVG : Could not load bitmap %s for a2dPatternStroke" ), filename.c_str() );
5794  image = wxImage( 32, 32 );
5795  }
5796  }
5797  m_stipple = wxBitmap( image );
5798 
5800  {
5801  wxColour white( wxT( "WHITE" ) );
5802  wxColour black( wxT( "BLACK" ) );
5803 
5804  wxMask* monochrome_mask = new wxMask( m_stipple, black );
5805  m_stipple.SetMask( monochrome_mask );
5806  }
5807  SetStyle( style );
5808 }
5809 
5811 {
5812  m_stipple = other.m_stipple;
5813 }
5814 
5815 a2dStrokeStyle a2dPatternStrokeData::GetStyle() const
5816 {
5817  return m_style;
5818 }
5819 
5820 void a2dPatternStrokeData::SetStyle( a2dStrokeStyle style )
5821 {
5822  if ( style == a2dSTROKE_TRANSPARENT )
5823  m_style = a2dSTROKE_TRANSPARENT;
5824  if ( style == a2dSTROKE_STIPPLE_MASK_OPAQUE ||
5826  )
5827  {
5828  if ( !m_stipple.GetMask() )
5829  {
5830  wxMask* mask = new wxMask( m_stipple, GetColour() );
5831  m_stipple.SetMask( mask );
5832  }
5833  m_style = style;
5834  }
5835  else if ( style == a2dSTROKE_STIPPLE )
5836  m_style = style;
5837  else
5838  wxFAIL_MSG( _( "invalid style for a2dPatternStrokeData" ) );
5839 }
5840 
5841 #if wxART2D_USE_CVGIO
5842 void a2dPatternStrokeData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
5843 {
5844  a2dOneColourStrokeData::DoLoad( parent, parser, xmlparts );
5845  if ( xmlparts == a2dXmlSer_attrib )
5846  {
5847  wxString filename = parser.GetAttributeValue( wxT( "filename" ), wxT( "" ) );
5848  wxImage image;
5849  if ( filename.IsEmpty() )
5850  {
5851  wxLogError( _( "CVG : bitmap file for a2dPatternStrokeData not specified or empty" ) );
5852  image = wxImage( 32, 32 );
5853  }
5854  else
5855  {
5857  if ( m_filename.IsEmpty() )
5858  {
5859  wxLogError( _( "CVG : Could not load bitmap \"%s\" for a2dPatternStrokeData from path \"%s\" " ), filename.c_str(), a2dGlobals->GetImagePathList().GetAsString().c_str() );
5860  image = wxImage( 32, 32 );
5861  }
5862  else if ( ! image.LoadFile( m_filename, wxBITMAP_TYPE_BMP ) )
5863  {
5864  wxLogError( _( "CVG : Could not load bitmap %s for a2dPatternStrokeData" ), m_filename.c_str() );
5865  image = wxImage( 32, 32 );
5866  }
5867  }
5868  m_stipple = wxBitmap( image );
5869 
5870  m_style = ( a2dStrokeStyle ) StrokeString2Style( parser.GetAttributeValue( wxT( "style" ), wxT( "a2dSTROKE_STIPPLE" ) ) );
5871  SetStyle( m_style );
5872 
5874  {
5875  wxColour white( wxT( "WHITE" ) );
5876  wxColour black( wxT( "BLACK" ) );
5877 
5878  wxMask* monochrome_mask = new wxMask( m_stipple, black );
5879  m_stipple.SetMask( monochrome_mask );
5880  }
5881  }
5882  else
5883  {}
5884 }
5885 
5886 void a2dPatternStrokeData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
5887 {
5888  a2dOneColourStrokeData::DoSave( parent, out, xmlparts, towrite );
5889 
5890  if ( xmlparts == a2dXmlSer_attrib )
5891  {
5892  if ( m_style != a2dSTROKE_STIPPLE )
5893  out.WriteAttribute( wxT( "style" ), StrokeStyle2String( GetStyle() ) );
5894 
5895  wxString filename = a2dGlobals->GetImagePathList().FindValidPath( m_filename );
5896  if ( filename.IsEmpty() )
5897  {
5898  // We can/may not save/use the original files, because the pattern may have changed inside the appl.
5899  // If available use the name of the orginal file.
5900  wxString fileTosave;
5901 
5902  wxString* layerfile = a2dGeneralGlobals->GetVariablesHash().GetVariableString( wxT( "wxart2dlayers" ) );
5903  wxString* layerfiledir = a2dGeneralGlobals->GetVariablesHash().GetVariableString( wxT( "layerFileSavePath" ) );
5904 
5905  if ( layerfile && !layerfile->IsEmpty() )
5906  {
5907  if ( !wxDirExists( *layerfiledir ) )
5908  wxMkdir( *layerfiledir );
5909  wxString mess = *layerfiledir + *layerfile + wxT( " directory does not exist, and could not be created" );
5910  wxASSERT_MSG( wxDirExists( *layerfiledir ) , mess );
5911 
5912  fileTosave = *layerfiledir + wxFILE_SEP_PATH;
5913  }
5914 
5915  if ( m_filename.IsEmpty() )
5916  {
5917  m_filename.Printf( _T( "canpat_%ld.bmp" ), wxGenNewId() );
5918  fileTosave += m_filename;
5919  }
5920  else
5921  fileTosave += wxFileNameFromPath( m_filename );
5922  bool isOke = m_stipple.SaveFile( fileTosave, wxBITMAP_TYPE_BMP );
5923  if ( !isOke )
5924  wxLogError( _( "Could not save bitmap %s for a2dPatternStrokeData" ), fileTosave.c_str() );
5925  out.WriteAttribute( wxT( "filename" ), wxFileNameFromPath( m_filename ) );
5926  }
5927  else
5928  out.WriteAttribute( wxT( "filename" ), wxFileNameFromPath( m_filename ) );
5929  }
5930  else
5931  {}
5932 }
5933 #endif //wxART2D_USE_CVGIO
5934 
5935 //----------------------------------------------------------------------------
5936 // a2dStroke
5937 //----------------------------------------------------------------------------
5938 
5940 {
5941 }
5942 
5943 a2dStroke::a2dStroke( const wxColour& col, a2dStrokeStyle style )
5944 {
5945  m_refData = new a2dOneColourStrokeData( col, style );
5946 }
5947 
5948 a2dStroke::a2dStroke( const wxColour& col, double width, a2dStrokeStyle style )
5949 {
5950  m_refData = new a2dOneColourStrokeData( col, style );
5951  ( ( a2dOneColourStrokeData* )GetRefData() )->SetWidth( width );
5952 }
5953 
5954 a2dStroke::a2dStroke( const wxColour& col, int width, a2dStrokeStyle style )
5955 {
5956  m_refData = new a2dOneColourStrokeData( col, style );
5957  ( ( a2dOneColourStrokeData* )GetRefData() )->SetWidth( width );
5958  ( ( a2dOneColourStrokeData* )GetRefData() )->SetPixelStroke( true );
5959 }
5960 
5961 a2dStroke::a2dStroke( const wxBitmap& stipple, a2dStrokeStyle style )
5962 {
5963  m_refData = new a2dPatternStrokeData( stipple, style );
5964 }
5965 
5966 a2dStroke::a2dStroke( const wxBitmap& stipple, const wxColour& col, const wxColour& col2, a2dStrokeStyle style )
5967 {
5968  m_refData = new a2dPatternStrokeData( stipple, style );
5969  SetColour( col );
5970  //SetColour2( col2 );
5971 }
5972 
5973 a2dStroke::a2dStroke( const wxFileName& filename, a2dStrokeStyle style )
5974 {
5975  m_refData = new a2dPatternStrokeData( filename, style );
5976 }
5977 
5978 a2dStroke::a2dStroke( const wxFileName& filename, const wxColour& col, const wxColour& col2, a2dStrokeStyle style )
5979 {
5980  m_refData = new a2dPatternStrokeData( filename, style );
5981  SetColour( col );
5982  //SetColour2( col2 );
5983 }
5984 
5985 a2dStroke::a2dStroke( const wxPen& stroke )
5986 {
5987  m_refData = new a2dOneColourStrokeData( stroke );
5988 }
5989 
5991  : wxObject( Stroke )
5992 {
5993 }
5994 
5995 
5997 {
5998 }
5999 
6000 a2dStroke& a2dStroke::UnShare()
6001 {
6002  wxObject::UnShare();
6003  return *this;
6004 }
6005 
6006 a2dStrokeType a2dStroke::GetType( void ) const
6007 {
6008  if ( !m_refData )
6009  return a2dSTROKE_NULL;
6010  return ( ( a2dStrokeRefData* ) m_refData )->GetType();
6011 }
6012 
6013 wxObjectRefData* a2dStroke::CreateRefData() const
6014 {
6015  return new a2dOneColourStrokeData(); //dummy will be removed soon if not needed.
6016 }
6017 
6018 wxObjectRefData* a2dStroke::CloneRefData( const wxObjectRefData* data ) const
6019 {
6020  switch ( ( ( a2dStrokeRefData* ) data )->GetType() )
6021  {
6022  case a2dSTROKE_NULL:
6023  break;
6024  case a2dSTROKE_ONE_COLOUR:
6025  return new a2dOneColourStrokeData( *( ( const a2dOneColourStrokeData* )data ) );
6026  break;
6027  case a2dSTROKE_BITMAP:
6028  return new a2dPatternStrokeData( *( ( const a2dPatternStrokeData* )data ) );
6029  break;
6030  default:
6031  break;
6032  }
6033  return NULL;
6034 }
6035 
6036 void a2dStroke::SetStipple( const wxBitmap& stipple )
6037 {
6038  AllocExclusive();
6039  if ( GetType() == a2dSTROKE_BITMAP )
6040  ( ( a2dPatternStrokeData* )m_refData )->SetStipple( stipple );
6041  else
6042  {
6043  UnRef();
6044  m_refData = new a2dPatternStrokeData( stipple, a2dSTROKE_STIPPLE );
6045  }
6046 }
6047 
6048 const wxBitmap& a2dStroke::GetStipple() const
6049 {
6050  if ( GetType() == a2dSTROKE_BITMAP )
6051  {
6052  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6053  return ( ( const a2dPatternStrokeData* )m_refData )->GetStipple();
6054  }
6055  else
6056  {
6057  return wxNullBitmap;
6058  }
6059 }
6060 
6061 void a2dStroke::SetAlpha( wxUint8 val )
6062 {
6063  AllocExclusive();
6064 
6065  switch ( GetType() )
6066  {
6067  case a2dSTROKE_NULL:
6068  UnRef();
6069  break;
6070  case a2dSTROKE_ONE_COLOUR:
6071  {
6072  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6073  wxColour newcol = ( ( a2dOneColourStrokeData* )GetRefData() )->GetColour();
6074  newcol.Set( newcol.Red(), newcol.Green(), newcol.Blue(), val );
6075  ( ( a2dOneColourStrokeData* )GetRefData() )->SetColour( newcol );
6076  break;
6077  }
6078  case a2dSTROKE_BITMAP:
6079  {
6080  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6081  wxColour newcol = ( ( a2dOneColourStrokeData* )GetRefData() )->GetColour();
6082  newcol.Set( newcol.Red(), newcol.Green(), newcol.Blue(), val );
6083  ( ( a2dPatternStrokeData* )GetRefData() )->SetColour( newcol );
6084  break;
6085  }
6086  default:
6087  break;
6088  }
6089 }
6090 
6091 wxUint8 a2dStroke::GetAlpha() const
6092 {
6093  switch ( GetType() )
6094  {
6095  case a2dSTROKE_NULL:
6096  return a2dSTROKE_NULLSTROKE;
6097  case a2dSTROKE_ONE_COLOUR:
6098  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6099  return ( ( a2dOneColourStrokeData* )GetRefData() )->GetColour().Alpha();
6100  break;
6101  case a2dSTROKE_BITMAP:
6102  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6103  return ( ( a2dPatternStrokeData* )GetRefData() )->GetColour().Alpha();
6104  break;
6105  default:
6106  break;
6107  }
6108  return 255;
6109 }
6110 
6111 
6112 void a2dStroke::SetColour( const wxColour& col )
6113 {
6114  AllocExclusive();
6115  switch ( GetType() )
6116  {
6117  case a2dSTROKE_NULL:
6118  UnRef();
6119  break;
6120  case a2dSTROKE_ONE_COLOUR:
6121  ( ( a2dOneColourStrokeData* )GetRefData() )->SetColour( col );
6122  break;
6123  case a2dSTROKE_BITMAP:
6124  ( ( a2dPatternStrokeData* )GetRefData() )->SetColour( col );
6125  break;
6126  default:
6127  break;
6128  }
6129 }
6130 
6131 wxColour a2dStroke::GetColour() const
6132 {
6133  switch ( GetType() )
6134  {
6135  case a2dSTROKE_NULL:
6136  break;
6137  case a2dSTROKE_ONE_COLOUR:
6138  return ( ( a2dOneColourStrokeData* )GetRefData() )->GetColour();
6139  break;
6140  case a2dSTROKE_BITMAP:
6141  return ( ( a2dPatternStrokeData* )GetRefData() )->GetColour();
6142  break;
6143  default:
6144  break;
6145  }
6146  return *wxBLACK;
6147 }
6148 
6149 void a2dStroke::SetColour2( const wxColour& col )
6150 {
6151  AllocExclusive();
6152  switch ( GetType() )
6153  {
6154  case a2dSTROKE_NULL:
6155  UnRef();
6156  break;
6157  case a2dSTROKE_ONE_COLOUR:
6158  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6159  break;
6160  case a2dSTROKE_BITMAP:
6161  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6162  //((a2dPatternStrokeData*)GetRefData())->SetColour2( col );
6163  ( ( a2dPatternStrokeData* )GetRefData() )->SetColour( col );
6164  break;
6165  default:
6166  break;
6167  }
6168 }
6169 
6170 wxColour a2dStroke::GetColour2() const
6171 {
6172  switch ( GetType() )
6173  {
6174  case a2dSTROKE_NULL:
6175  break;
6176  case a2dSTROKE_ONE_COLOUR:
6177  break;
6178  case a2dSTROKE_BITMAP:
6179  //return ((a2dPatternStrokeData*)GetRefData())->GetColour2();
6180  return ( ( a2dPatternStrokeData* )GetRefData() )->GetColour();
6181  break;
6182  default:
6183  break;
6184  }
6185  return *wxBLACK;
6186 }
6187 
6188 void a2dStroke::SetJoin( wxPenJoin join_style )
6189 {
6190  AllocExclusive();
6191  switch ( GetType() )
6192  {
6193  case a2dSTROKE_NULL:
6194  UnRef();
6195  break;
6196  case a2dSTROKE_ONE_COLOUR:
6197  ( ( a2dOneColourStrokeData* )GetRefData() )->SetJoin( join_style );
6198  break;
6199  case a2dSTROKE_BITMAP:
6200  ( ( a2dPatternStrokeData* )GetRefData() )->SetJoin( join_style );
6201  break;
6202  default:
6203  break;
6204  }
6205 }
6206 
6207 void a2dStroke::SetCap( wxPenCap cap_style )
6208 {
6209  AllocExclusive();
6210  switch ( GetType() )
6211  {
6212  case a2dSTROKE_NULL:
6213  UnRef();
6214  break;
6215  case a2dSTROKE_ONE_COLOUR:
6216  ( ( a2dOneColourStrokeData* )GetRefData() )->SetCap( cap_style );
6217  break;
6218  case a2dSTROKE_BITMAP:
6219  ( ( a2dPatternStrokeData* )GetRefData() )->SetCap( cap_style );
6220  break;
6221  default:
6222  break;
6223  }
6224 }
6225 
6226 wxPenCap a2dStroke::GetCap() const
6227 {
6228  switch ( GetType() )
6229  {
6230  case a2dSTROKE_NULL:
6231  break;
6232  case a2dSTROKE_ONE_COLOUR:
6233  return ( ( a2dOneColourStrokeData* )GetRefData() )->GetCap();
6234  break;
6235  case a2dSTROKE_BITMAP:
6236  return ( ( a2dPatternStrokeData* )GetRefData() )->GetCap();
6237  break;
6238  default:
6239  break;
6240  }
6241  return wxCAP_ROUND;
6242 }
6243 
6244 wxPenJoin a2dStroke::GetJoin() const
6245 {
6246  switch ( GetType() )
6247  {
6248  case a2dSTROKE_NULL:
6249  break;
6250  case a2dSTROKE_ONE_COLOUR:
6251  return ( ( a2dOneColourStrokeData* )GetRefData() )->GetJoin();
6252  break;
6253  case a2dSTROKE_BITMAP:
6254  return ( ( a2dPatternStrokeData* )GetRefData() )->GetJoin();
6255  break;
6256  default:
6257  break;
6258  }
6259  return wxJOIN_ROUND;
6260 }
6261 
6262 void a2dStroke::SetWidth( float width )
6263 {
6264  AllocExclusive();
6265  switch ( GetType() )
6266  {
6267  case a2dSTROKE_NULL:
6268  UnRef();
6269  break;
6270  case a2dSTROKE_ONE_COLOUR:
6271  ( ( a2dOneColourStrokeData* )GetRefData() )->SetWidth( width );
6272  break;
6273  case a2dSTROKE_BITMAP:
6274  ( ( a2dPatternStrokeData* )GetRefData() )->SetWidth( width );
6275  break;
6276  default:
6277  break;
6278  }
6279 }
6280 
6281 float a2dStroke::GetWidth() const
6282 {
6283  switch ( GetType() )
6284  {
6285  case a2dSTROKE_NULL:
6286  break;
6287  case a2dSTROKE_ONE_COLOUR:
6288  return ( ( a2dOneColourStrokeData* )GetRefData() )->GetWidth();
6289  break;
6290  case a2dSTROKE_BITMAP:
6291  return ( ( a2dPatternStrokeData* )GetRefData() )->GetWidth();
6292  break;
6293  default:
6294  break;
6295  }
6296  return 0;
6297 }
6298 float a2dStroke::GetExtend() const
6299 {
6300  switch ( GetType() )
6301  {
6302  case a2dSTROKE_NULL:
6303  break;
6304  case a2dSTROKE_ONE_COLOUR:
6305  return ( ( a2dOneColourStrokeData* )GetRefData() )->GetExtend();
6306  break;
6307  case a2dSTROKE_BITMAP:
6308  return ( ( a2dPatternStrokeData* )GetRefData() )->GetExtend();
6309  break;
6310  default:
6311  break;
6312  }
6313  return 0;
6314 }
6315 
6316 void a2dStroke::SetPixelStroke( bool pixelstroke )
6317 {
6318  AllocExclusive();
6319  switch ( GetType() )
6320  {
6321  case a2dSTROKE_NULL:
6322  UnRef();
6323  break;
6324  case a2dSTROKE_ONE_COLOUR:
6325  ( ( a2dOneColourStrokeData* )GetRefData() )->SetPixelStroke( pixelstroke );
6326  break;
6327  case a2dSTROKE_BITMAP:
6328  ( ( a2dPatternStrokeData* )GetRefData() )->SetPixelStroke( pixelstroke );
6329  break;
6330  default:
6331  break;
6332  }
6333 }
6334 
6336 {
6337  switch ( GetType() )
6338  {
6339  case a2dSTROKE_NULL:
6340  break;
6341  case a2dSTROKE_ONE_COLOUR:
6342  return ( ( a2dOneColourStrokeData* )GetRefData() )->GetPixelStroke();
6343  break;
6344  case a2dSTROKE_BITMAP:
6345  return ( ( a2dPatternStrokeData* )GetRefData() )->GetPixelStroke();
6346  break;
6347  default:
6348  break;
6349  }
6350  return false;
6351 }
6352 
6353 a2dStrokeStyle a2dStroke::GetStyle( void ) const
6354 {
6355  switch ( GetType() )
6356  {
6357  case a2dSTROKE_NULL:
6358  return a2dSTROKE_NULLSTROKE;
6359  break;
6360  case a2dSTROKE_ONE_COLOUR:
6361  return ( ( a2dOneColourStrokeData* )GetRefData() )->GetStyle();
6362  break;
6363  case a2dSTROKE_BITMAP:
6364  return ( ( a2dPatternStrokeData* )GetRefData() )->GetStyle();
6365  break;
6366  default:
6367  break;
6368  }
6369  return a2dSTROKE_NULLSTROKE;
6370 }
6371 
6372 void a2dStroke::SetStyle( a2dStrokeStyle style )
6373 {
6374  a2dStrokeStyle cur_style = GetStyle();
6375  if ( cur_style == style )
6376  return;
6377  AllocExclusive();
6378 
6379  a2dStrokeType type = GetTypeForStyle( style );
6380 
6381  if ( type == GetType() )
6382  {
6383  switch ( type )
6384  {
6385  case a2dSTROKE_NULL:
6386  UnRef();
6387  break;
6388  case a2dSTROKE_ONE_COLOUR:
6389  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6390  ( ( a2dOneColourStrokeData* )GetRefData() )->SetStyle( style );
6391  break;
6392  /*
6393  case a2dSTROKE_GRADIENT_FILL_LINEAR:
6394  wxASSERT_MSG( m_refData, _T("No ref data") );
6395  ((a2dLinearGradientFillData*)GetRefData())->SetStyle( style );
6396  break;
6397  case a2dSTROKE_GRADIENT_FILL_RADIAL:
6398  wxASSERT_MSG( m_refData, _T("No ref data") );
6399  ((a2dRadialGradientFillData*)GetRefData())->SetStyle( style );
6400  break;
6401  */
6402  case a2dSTROKE_BITMAP:
6403  wxASSERT_MSG( m_refData, _T( "No ref data" ) );
6404  ( ( a2dPatternStrokeData* )GetRefData() )->SetStyle( style );
6405  break;
6406  default:
6407  break;
6408  }
6409  }
6410  else
6411  {
6412  a2dStrokeRefData* newrefdata = NULL;
6413  switch ( type )
6414  {
6415  case a2dSTROKE_NULL:
6416  break;
6417  case a2dSTROKE_ONE_COLOUR:
6418  {
6419  a2dOneColourStrokeData* onenewrefdata = new a2dOneColourStrokeData( GetColour(), style );
6420  newrefdata = onenewrefdata;
6421  onenewrefdata->SetColour( GetColour() );
6422  onenewrefdata->SetWidth( GetWidth() );
6423  onenewrefdata->SetJoin( GetJoin() );
6424  onenewrefdata->SetCap( GetCap() );
6425  onenewrefdata->SetPixelStroke( GetPixelStroke() );
6426  break;
6427  }
6428  /*
6429  case a2dSTROKE_GRADIENT_FILL_LINEAR:
6430  newrefdata = new a2dLinearGradientStrokeData( GetColour(), GetColour2(), 0, 0, 0, 0 );
6431  break;
6432  case a2dSTROKE_GRADIENT_FILL_RADIAL:
6433  newrefdata = new a2dRadialGradientStrokeData( GetColour(), GetColour2(), 0, 0, 0, 0, 0 );
6434  break;
6435  */
6436  case a2dSTROKE_BITMAP:
6437  {
6438  a2dPatternStrokeData* patnewrefdata = new a2dPatternStrokeData( wxNullBitmap, style );
6439  newrefdata = patnewrefdata;
6440  patnewrefdata->SetColour( GetColour() );
6441  patnewrefdata->SetWidth( GetWidth() );
6442  patnewrefdata->SetJoin( GetJoin() );
6443  patnewrefdata->SetCap( GetCap() );
6444  patnewrefdata->SetPixelStroke( GetPixelStroke() );
6445  //patnewrefdata->SetColour2( GetColour2() );
6446  break;
6447  }
6448  default:
6449  break;
6450  }
6451  UnRef();
6452  m_refData = newrefdata;
6453  }
6454 }
6455 
6456 a2dStrokeType a2dStroke::GetTypeForStyle( a2dStrokeStyle style ) const
6457 {
6458  if ( style == a2dSTROKE_NULLSTROKE || style == a2dSTROKE_LAYER || style == a2dSTROKE_INHERIT )
6459  return a2dSTROKE_NULL;
6460  if ( style == a2dSTROKE_TRANSPARENT && GetType() != a2dSTROKE_NULL )
6461  return GetType();
6462  else if ( style == a2dSTROKE_SOLID ||
6463  style == a2dSTROKE_TRANSPARENT ||
6464  style == a2dSTROKE_DOT ||
6465  style == a2dSTROKE_DOT_DASH ||
6466  style == a2dSTROKE_LONG_DASH ||
6467  style == a2dSTROKE_SHORT_DASH ||
6468  style == a2dSTROKE_USER_DASH ||
6469  style == a2dSTROKE_BDIAGONAL_HATCH ||
6470  style == a2dSTROKE_CROSSDIAG_HATCH ||
6471  style == a2dSTROKE_FDIAGONAL_HATCH ||
6472  style == a2dSTROKE_CROSS_HATCH ||
6473  style == a2dSTROKE_HORIZONTAL_HATCH ||
6474  style == a2dSTROKE_VERTICAL_HATCH ||
6475  style == a2dSTROKE_NULLSTROKE
6476  )
6477  return a2dSTROKE_ONE_COLOUR;
6478  /*
6479  else if ( style == a2dSTROKE_GRADIENT_FILL_XY_LINEAR )
6480  return a2dSTROKE_GRADIENT_FILL_LINEAR;
6481  else if ( style == a2dSTROKE_GRADIENT_FILL_XY_RADIAL )
6482  return a2dSTROKE_GRADIENT_FILL_RADIAL;
6483  */
6484  else if ( style == a2dSTROKE_STIPPLE ||
6485  style == a2dSTROKE_STIPPLE_MASK_OPAQUE ||
6487  )
6488  return a2dSTROKE_BITMAP;
6489  else
6490  wxFAIL_MSG( _( "invalid style for in a2dStroke" ) );
6491 
6492  return a2dSTROKE_NULL;
6493 }
6494 
6495 
6496 #if wxART2D_USE_CVGIO
6497 void a2dStroke::Load( wxObject* parent, a2dIOHandlerXmlSerIn& parser )
6498 {
6499  a2dStrokeType type;
6500 
6501  parser.Require( START_TAG, wxT( "o" ) );
6502 
6503  wxString classname = parser.GetAttributeValue( wxT( "classname" ) );
6504  if ( classname == wxT( "a2dOneColourStroke" ) )
6505  type = a2dSTROKE_ONE_COLOUR;
6506  else if ( classname == wxT( "a2dPatternFill" ) )
6507  type = a2dSTROKE_BITMAP;
6508  else
6509  {
6510  wxString stype = parser.GetAttributeValue( wxT( "type" ), wxT( "a2dSTROKE_NULL" ) );
6511  if ( stype == wxT( "a2dSTROKE_NULL" ) )
6512  type = a2dSTROKE_NULL;
6513  if ( stype == wxT( "a2dSTROKE_ONE_COLOUR" ) )
6514  type = a2dSTROKE_ONE_COLOUR;
6515  else if ( stype == wxT( "a2dSTROKE_BITMAP" ) )
6516  type = a2dSTROKE_BITMAP;
6517  }
6518 
6519  switch ( type )
6520  {
6521  case a2dSTROKE_NULL:
6522  break;
6523  case a2dSTROKE_ONE_COLOUR:
6524  m_refData = new a2dOneColourStrokeData( *wxBLACK );
6525  break;
6526  case a2dSTROKE_BITMAP:
6527  m_refData = new a2dPatternStrokeData( wxNullBitmap );
6528  break;
6529  default:
6530  break;
6531  }
6532 
6533  if ( GetRefData() )
6534  {
6535  ( ( a2dStrokeRefData* )GetRefData() )->DoLoad( parent, parser, a2dXmlSer_attrib );
6536  parser.Next();
6537  ( ( a2dStrokeRefData* )GetRefData() )->DoLoad( parent, parser, a2dXmlSer_Content );
6538  }
6539  else
6540  parser.Next();
6541 
6542  parser.Require( END_TAG, wxT( "o" ) );
6543  parser.Next();
6544 }
6545 
6546 void a2dStroke::Save( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dObjectList* towrite )
6547 {
6548  out.WriteStartElementAttributes( wxT( "o" ) );
6549  out.WriteAttribute( wxT( "classname" ), GetClassInfo()->GetClassName() );
6550 
6551  switch ( GetType() )
6552  {
6553  case a2dSTROKE_NULL:
6554  break;
6555  case a2dSTROKE_ONE_COLOUR:
6556  out.WriteAttribute( wxT( "type" ), wxT( "a2dSTROKE_ONE_COLOUR" ) );
6557  break;
6558  case a2dSTROKE_BITMAP:
6559  out.WriteAttribute( wxT( "type" ), wxT( "a2dSTROKE_BITMAP" ) );
6560  break;
6561  default:
6562  break;
6563  }
6564  if ( GetRefData() )
6565  ( ( a2dStrokeRefData* )GetRefData() )->DoSave( parent, out, a2dXmlSer_attrib, towrite );
6566 
6567  out.WriteEndAttributes();
6568  if ( GetRefData() )
6569  ( ( a2dStrokeRefData* )GetRefData() )->DoSave( parent, out, a2dXmlSer_Content, towrite );
6570 
6571  out.WriteEndElement();
6572 }
6573 #endif //wxART2D_USE_CVGIO
6574 
6575 
6576 
6577 //===========================================================================
6578 // a2dExtStroke
6579 //===========================================================================
6580 
6581 bool a2dExtStroke::HasIndividualAttributes(a2dStrokeStyle style)
6582 {
6583  if( (style == a2dSTROKE_TRANSPARENT) || (style == a2dSTROKE_LAYER) ||
6584  (style == a2dSTROKE_NULLSTROKE) || (style == a2dSTROKE_INHERIT) )
6585  {
6586  return false;
6587  }
6588  return true;
6589 }
6590 
6591 a2dExtStroke::a2dExtStroke()
6592  : m_Default(), m_Style(), m_Color(), m_Width(), m_Cap(), m_Join(), m_bStyle(false), m_bInitialised(false),
6593  m_bEditable(false), m_bColor(false), m_bWidth(false), m_bCap(false), m_bJoin(false)
6594 {
6595 }
6596 
6597 a2dExtStroke::a2dExtStroke(const a2dStroke& stroke)
6598  : m_Default(), m_Style(), m_Color(), m_Width(), m_Cap(), m_Join(), m_bStyle(false), m_bInitialised(false),
6599  m_bEditable(false), m_bColor(false), m_bWidth(false), m_bCap(false), m_bJoin(false)
6600 {
6601  Set(stroke);
6602 }
6603 
6604 // Initialises all attributes with <stroke>.
6605 void a2dExtStroke::Set(const a2dStroke& stroke)
6606 {
6607  m_Style = stroke.GetStyle();
6608  m_bStyle = true;
6609 
6610  if(HasIndividualAttributes(stroke.GetStyle()))
6611  SetAttributes(stroke);
6612 }
6613 
6614 void a2dExtStroke::SetAttributes(const a2dStroke& stroke)
6615 {
6616  m_Color = stroke.GetColour();
6617  m_Width = stroke.GetWidth();
6618  m_Cap = stroke.GetCap();
6619  m_Join = stroke.GetJoin();
6620 
6621  m_bInitialised = true;
6622  m_bEditable = true;
6623  m_bColor = true;
6624  m_bWidth = true;
6625  m_bCap = true;
6626  m_bJoin = true;
6627 }
6628 
6629 // Compares with <stroke> and sets all unequal attributes to invalid.
6630 // Attributes that are still invalid will not compared again.
6631 void a2dExtStroke::Mix(const a2dStroke& stroke)
6632 {
6633  if( m_bStyle && (stroke.GetStyle() != m_Style) ) m_bStyle = false;
6634 
6635  if(!HasIndividualAttributes(stroke.GetStyle()))
6636  return;
6637 
6638  if(!m_bInitialised)
6639  {
6640  SetAttributes(stroke);
6641  return;
6642  }
6643 
6644  if( m_bColor && (stroke.GetColour() != m_Color) ) m_bColor = false;
6645  if( m_bWidth && (stroke.GetWidth() != m_Width) ) m_bWidth = false;
6646  if( m_bCap && (stroke.GetCap() != m_Cap) ) m_bCap = false;
6647  if( m_bJoin && (stroke.GetJoin() != m_Join) ) m_bJoin = false;
6648 }
6649 
6650 // Returns the result of setting all valid attributes to <stroke>.
6651 a2dStroke a2dExtStroke::Get(const a2dStroke& stroke) const
6652 {
6653  if(m_bStyle)
6654  {
6655  switch(m_Style)
6656  {
6657  case a2dSTROKE_LAYER:
6658  case a2dSTROKE_NULLSTROKE:
6659  return *a2dNullSTROKE;
6660 
6661  case a2dSTROKE_TRANSPARENT:
6662  return *a2dTRANSPARENT_STROKE;
6663  }
6664  }
6665 
6666  a2dStroke mixed = stroke;
6667  if(!HasIndividualAttributes(stroke.GetStyle()))
6668  {
6669  if(!m_bStyle)
6670  return stroke;
6671 
6672  mixed = m_Default;
6673  }
6674 
6675  if( m_bColor && (mixed.GetColour() != m_Color) )
6676  mixed.SetColour(m_Color);
6677  if( m_bWidth && (mixed.GetWidth() != m_Width) )
6678  mixed.SetWidth(m_Width);
6679  if( m_bCap && (mixed.GetCap() != m_Cap) )
6680  mixed.SetCap(m_Cap);
6681  if( m_bJoin && (mixed.GetJoin() != m_Join) )
6682  mixed.SetJoin(m_Join);
6683  if( m_bStyle && (mixed.GetStyle() != m_Style) )
6684  mixed.SetStyle(m_Style);
6685  return mixed;
6686 }
6687 
6688 void a2dExtStroke::SetStyle(a2dStrokeStyle style)
6689 {
6690  m_Style = style;
6691  m_bStyle = true;
6692  m_bEditable = HasIndividualAttributes(m_Style);
6693 }
6694 
6695 void a2dExtStroke::SetColor(const wxColour& color)
6696 {
6697  m_Color = color;
6698  m_bColor = true;
6699 }
6700 
6701 void a2dExtStroke::SetWidth(const float& width)
6702 {
6703  m_Width = width;
6704  m_bWidth = true;
6705 }
6706 
6707 void a2dExtStroke::SetCap(wxPenCap cap)
6708 {
6709  m_Cap = cap;
6710  m_bCap = true;
6711 }
6712 
6713 void a2dExtStroke::SetJoin(wxPenJoin join)
6714 {
6715  m_Join = join;
6716  m_bJoin = true;
6717 }
6718 
6719 
6720 //===========================================================================
6721 // a2dExtFill
6722 //===========================================================================
6723 
6724 a2dExtFill::a2dExtFill()
6725  : m_Fill(), m_bFill(false)
6726 {
6727 }
6728 
6729 a2dExtFill::a2dExtFill(const a2dFill& fill)
6730  : m_Fill(), m_bFill(false)
6731 {
6732  Set(fill);
6733 }
6734 
6735 // Initialises with <fill>.
6736 void a2dExtFill::Set(const a2dFill& fill)
6737 {
6738  if( fill.GetStyle() == a2dFILL_SOLID || fill.GetStyle() == a2dFILL_TRANSPARENT ||
6739  fill.GetStyle() == a2dFILL_LAYER || fill.GetStyle() == a2dFILL_NULLFILL )
6740  {
6741  m_Fill = fill;
6742  m_bFill = true;
6743  }
6744  else m_bFill = false;
6745 }
6746 
6747 // Compares with <fill> and sets to invalid if unequal.
6748 void a2dExtFill::Mix(const a2dFill& fill)
6749 {
6750  if(!m_bFill) return; // already invalid, don't compare
6751  switch(m_Fill.GetStyle())
6752  {
6753  case a2dFILL_TRANSPARENT:
6754  if(fill.GetStyle() != a2dFILL_TRANSPARENT) m_bFill = false;
6755  break;
6756 
6757  case a2dFILL_SOLID:
6758  if(fill.GetStyle() != a2dFILL_SOLID) m_bFill = false;
6759  else if(fill.GetColour() != m_Fill.GetColour()) m_bFill = false;
6760  break;
6761 
6762  default:
6763  m_bFill = false;
6764  }
6765 }
6766 
6767 // Returns the a2dFill member object if valid, or <fill> instead.
6768 a2dFill a2dExtFill::Get(const a2dFill& fill) const
6769 {
6770  if(m_bFill) return m_Fill;
6771  return fill;
6772 /*
6773  // Returns the result of setting all valid attributes to <fill>.
6774  if(!m_bFill) return fill;
6775 
6776  a2dFill mixed = fill;
6777  switch(m_Fill.GetStyle())
6778  {
6779  case a2dFILL_TRANSPARENT:
6780  mixed.SetStyle(a2dFILL_TRANSPARENT);
6781  break;
6782 
6783  case a2dFILL_SOLID:
6784  mixed.SetStyle(a2dFILL_SOLID);
6785  mixed.SetColour(m_Fill.GetColour());
6786  break;
6787  }
6788  return mixed;
6789 */
6790 }
6791 
6792 
wxString GetFilename(bool filenameonly=false) const
Get the font filename.
Definition: stylebase.cpp:3269
bool GetAttributeValueBool(const wxString &attrib, bool defaultv=false)
Returns the boolean value of an attribute.
Definition: genxmlpars.cpp:537
wxEncodingConverter * m_converter
encoding converter
Definition: stylebase.cpp:1055
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
a2dStrokeGlyph * m_characters
Glyph storage.
Definition: stylebase.cpp:2120
a2dAffineMatrix & Mirror(bool y=true, bool x=false)
mirror a matrix in x, y
Definition: afmatrix.cpp:396
a2dFillStyle FillString2Style(const wxString &stylestr)
convert a string to a style enum
Definition: stylebase.cpp:3455
a2dOneColourStrokeData(void)
constructor
Definition: stylebase.cpp:5416
wxUint16 * m_width
Width storage.
Definition: stylebase.cpp:2118
a2dTwoColourFillData(void)
constructor
Definition: stylebase.cpp:3798
double GetSize() const
Get the font size.
Definition: stylebase.cpp:2917
A2DGENERALDLLEXP long wxGenNewId()
This function is like wxNewId, but it has its own ID set.
Definition: gen.cpp:92
const a2dFill * a2dSELECT_FILL
global a2dFill stock object for drawing fill of selected objects
double GetStrokeWidth() const
Get stroke width.
Definition: stylebase.cpp:2931
Base class for all types of strokes, understood by a2dDrawer2D classes.
Definition: stylebase.h:378
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)=0
Load settings.
a2dPatternFillData()
constructor
Definition: stylebase.cpp:4380
void SetFont(const wxFont &font)
Set font format.
Definition: stylebase.cpp:504
void SetDeviceHeight(double sizeInPixels)
to set for load glyph from face, to do proper hinting
Definition: stylebase.cpp:485
const wxString & GetName() const
Get name of font, e.g. Arial.
Definition: stylebase.h:717
a2dGlyph * m_a2dLastGlyph
Glyph cache one last character.
Definition: stylebase.cpp:1039
wxColour A2DGENERALDLLEXP HexToColour(const wxString &hex)
3-digit hex to wxColour
Definition: gen.cpp:5279
To set a two colour fill.
Definition: stylebase.cpp:3747
bool m_fillOn
if true filling is done, else transparent fill
Definition: stylebase.cpp:3552
a2dFont CreateFont(double size)
Create this enumerated font.
Definition: stylebase.cpp:157
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: stylebase.cpp:5568
wxColour GetColour() const
return colour
Definition: stylebase.cpp:5357
void SetWeight(double weight)
Set the weight of the font.
Definition: stylebase.cpp:2419
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: stylebase.cpp:3852
Stroke and fill base classes.
Font info class, used as a single element for enumerating fonts.
Definition: stylebase.h:686
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: stylebase.cpp:4472
wxString FindValidPath(const wxString &filename, bool reportError=true)
Find the first full path for which the file exists.
Definition: gen.cpp:4486
XMLeventType Next()
Walks to next element and returns event type.
Definition: genxmlpars.cpp:422
bool GetPixelStroke() const
if the width is pixels or not.
Definition: stylebase.cpp:5380
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: stylebase.cpp:3715
void SetColour(const wxColour &col)
set colour used for gradient and wxSTIPPLE_MASK_OPAQUE filling.
Definition: stylebase.cpp:3778
a2dPoint2D GetStop() const
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4733
const a2dFill * a2dINHERIT_FILL
global a2dFill stock object for INHERTED from parent object filling
void ParseString(wxString string)
Fill this class from a string.
Definition: stylebase.cpp:120
a2dVertexList ** a2dStrokeGlyph
A list of pointers to vertexlists. Ends with NULL.
Definition: stylebase.h:542
wxColour GetColour2() const
return colour 2
Definition: stylebase.cpp:4969
double m_height
Font height cache normalized to a font height of 1.
Definition: stylebase.cpp:240
a2dFontDcData auxiliry class to aid in enumerating fonts.
Definition: stylebase.cpp:836
void SetWidth(float width)
Set width of stroke in world coordinates.
Definition: stylebase.cpp:5368
a2dRadialGradientFillData(void)
constructor
Definition: stylebase.cpp:4219
const wxString & GetExtra() const
Get the extra information ( e.g. the filename of the font )
Definition: stylebase.h:744
a2dPoint2D GetCenter()
Get start for gradient fill colour change.
Definition: stylebase.cpp:4181
void SetFilename(const wxString &filename)
Set the font filename and load the font.
Definition: stylebase.cpp:3253
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)=0
Save settings.
void SetColour2(const wxColour &col)
set colour 2 used for gradient and wxSTIPPLE_MASK_OPAQUE filling.
Definition: stylebase.cpp:3772
void SetPixelStroke(bool pixelstroke)
set pixelstoke flag, stroke width is defined in pixels else in worldcoordinates
Definition: stylebase.cpp:6316
const a2dFill * a2dBLACK_FILL
global a2dFill stock object for BLACK filling
void WriteStartElementAttributes(const wxString &name, bool newLine=true)
Writes start tag which has attributes.
Definition: genxmlpars.cpp:757
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: stylebase.cpp:4270
wxFont & GetFont(void)
wxFont in case of a2dFONT_WXDC
Definition: stylebase.cpp:3030
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: stylebase.cpp:3689
double GetSize() const
Get size of the font.
Definition: stylebase.h:727
void CBCurveTo(double x1, double y1, double x2, double y2, double x3, double y3, bool withStroke=true)
add a quadratic bezier segment to the path
Definition: polyver.cpp:3934
wxString m_type
Font type.
Definition: stylebase.h:751
a2dOneColourFillData(void)
constructor
Definition: stylebase.cpp:3617
Two colour Hatch Fill.
Definition: stylebase.cpp:3887
wxString CreateString()
Create a string description of the font.
Definition: stylebase.cpp:2887
DcKerningHash m_kerningcache
Kerning cache normalized to a font height of 1.
Definition: stylebase.cpp:426
~a2dPatternStrokeData(void)
destructor
Definition: stylebase.cpp:5725
wxChar m_lastChar
last character for glyph cache one character
Definition: stylebase.cpp:1037
double GetDescent() const
Get descent.
Definition: stylebase.cpp:3101
const a2dError a2dError_FileCouldNotOpen
bool operator==(const a2dFontInfo &other) const
Comparison operator.
Definition: stylebase.cpp:99
Defines a font to be set to a2dDrawer2D or stored in a2dCanvsObject etc.
Definition: stylebase.h:779
double GetRadius() const
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4765
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:819
bool GetPixelStroke() const
if the width is pixels or not.
Definition: stylebase.cpp:6335
wxString A2DGENERALDLLEXP ColourToHex(const wxColour &colour)
RGB to 3-digit hex.
Definition: gen.cpp:5295
double GetValue(int col, int row) const
get the value in the matrix at col,row
Definition: afmatrix.cpp:106
double GetKerning(wxChar c1, wxChar c2) const
Get kerning space between two characters.
Definition: stylebase.cpp:722
wxUint32 GetStamp() const
time stamp gradient fill
Definition: stylebase.cpp:4739
a2dFont m_freetypefont
freetype equivalent of the font, used in AggDrawer.
Definition: stylebase.cpp:431
const a2dFill * a2dWHITE_FILL
global a2dFill stock object for WHITE filling
a2dGlobal * a2dGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: artglob.cpp:34
const a2dGlyph * GetGlyph(wxChar c) const
Get the glyph of a single character.
Definition: stylebase.cpp:1359
void Close(bool withStroke=true)
Closing the path as a filled area.
Definition: polyver.cpp:3974
void a2dCanvasInitializeStockObjects()
to initialize stock style ( a2dStroke a2dFill ) objects.
Definition: stylebase.cpp:3352
void SetCenter(double x, double y)
center end for gradient fill colour change
Definition: stylebase.cpp:4251
double m_sizeInPixels
current text drawn its size in pixels to do proper hinting.
Definition: stylebase.cpp:1049
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: stylebase.cpp:5886
double GetKerning(wxChar c1, wxChar c2) const
Get kerning space between two characters.
Definition: stylebase.cpp:1614
wxFont & GetFont(void)
Get the font format.
Definition: stylebase.cpp:367
wxColour GetColour() const
return colour 1
Definition: stylebase.cpp:6131
void SetSize(double size)
Set the font size.
Definition: stylebase.cpp:2909
a2dAffineMatrix a2dIDENTITY_MATRIX
global a2dAffineMatrix to set/pass the identity matrix.
Definition: afmatrix.cpp:51
a2dFontFreetypeData(const wxString &filename=wxT(""), double size=0.0, wxFontEncoding encoding=wxFONTENCODING_DEFAULT, int faceindex=0)
Constructor.
Definition: stylebase.cpp:1062
bool GetVpath(wxChar c, a2dVpath &glyph, const a2dAffineMatrix &affine=a2dIDENTITY_MATRIX)
Get the glyph of a single character as a vpath.
Definition: stylebase.cpp:3111
vector< a2dGlyph > a2dGlyphCache
Glyph Cache. This stores the &#39;normal&#39; part of the alphabet.
Definition: stylebase.cpp:1028
vertex list of line and arc segments.
Definition: polyver.h:600
wxString FillStyle2String(a2dFillStyle style)
convert a style enum to a string
Definition: stylebase.cpp:3420
~a2dOneColourStrokeData(void)
destructor
Definition: stylebase.cpp:5350
a2dStrokeGlyph GetGlyphStroke(wxChar c) const
Get the glyph of a single character.
Definition: stylebase.cpp:2944
virtual ~a2dFontStrokeData()
Destructor.
Definition: stylebase.cpp:2193
wxColour GetColour2() const
return colour 2
Definition: stylebase.cpp:3775
#define NORMFONT
Normalization font size used for bigger size drawing of text.
Definition: stylebase.h:68
a2dBoundingBox GetTextExtent(const wxString &string, int alignment=wxMINX|wxMINY, double *w=NULL, double *h=NULL, double *descent=NULL, double *externalLeading=NULL) const
Get the dimensions in world coordinates of the string.
Definition: stylebase.cpp:3044
FT_Face m_face
freetypelib face struct.
Definition: stylebase.cpp:1043
void WriteEndElement(bool newLine=true)
Writes correspondending end tag for the current start tag.
Definition: genxmlpars.cpp:862
virtual ~a2dFill(void)
destructor
Definition: stylebase.cpp:4665
wxString GetFileName()
can contain the filename if pattern was read froma file
Definition: stylebase.cpp:4361
general vertexlist and array and vector path functions and classes.
double GetWeight() const
Get the weight of the font.
Definition: stylebase.cpp:2074
void SetStipple(const wxBitmap &stipple)
set stipple style
Definition: stylebase.cpp:4435
wxString GetFileName()
can contain the filename if pattern was read froma file
Definition: stylebase.cpp:5736
void Transform(const a2dAffineMatrix &world)
transform all segments with given matrix
Definition: polyver.cpp:1928
double GetKerning(wxChar c1, wxChar c2) const
Get kerning space between two characters.
Definition: stylebase.cpp:2498
void SetStyle(const wxString &style)
Set style of font, e.g. Bold.
Definition: stylebase.h:724
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: stylebase.cpp:4095
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)=0
Save settings.
a2dFillRefData()
constructor
Definition: stylebase.cpp:3533
bool Ok() const
Check font validity.
Definition: stylebase.cpp:2894
Filling using a wxbitmap.
Definition: stylebase.cpp:5695
a2dFillStyle
Filling styles for a2dFill.
Definition: stylebase.h:91
a2dFill(void)
constructor
Definition: stylebase.cpp:4569
wxUint16 m_beginchar
First character in font.
Definition: stylebase.cpp:2123
void SetWidth(float width)
Set width of stroke in world coordinates.
Definition: stylebase.cpp:6262
a2dStrokeStyle StrokeString2Style(const wxString &stylestr)
convert a string to a style enum
Definition: stylebase.cpp:5258
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: stylebase.cpp:5632
double GetWidth(wxChar c)
Get width of a single character.
Definition: stylebase.cpp:3106
void GetTextExtentWH(const wxString &string, double &w, double &h) const
Get the dimensions in world coordinates of the string.
Definition: stylebase.cpp:3085
const wxString & GetType() const
Get type of font, e.g. Freetype or Stroke.
Definition: stylebase.h:712
const a2dBoundingBox & Translate(a2dPoint2D &)
translate with given vector
Definition: bbox.cpp:370
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
a2dPathList & GetFontPathList()
Path for Fonts.
Definition: artglob.h:149
void SetStart(double x, double y)
start for gradient fill colour change
Definition: stylebase.cpp:4082
a2dFont GetFreetypeFont()
Get the freetype equivalent of the font.
Definition: stylebase.cpp:886
double GetLineHeight() const
Get the line height.
Definition: stylebase.cpp:3096
a2dStrokeGlyph GetGlyph(wxChar c) const
Get the glyph of a single character.
Definition: stylebase.cpp:2504
void SetColour(const wxColour &col)
set colour used for gradient and wxSTROKE_MASK_OPAQUE filling.
Definition: stylebase.cpp:6112
a2dStrokeType
Definition: stylebase.h:325
wxColour m_colour1
used for gradient fill or text background or opaque filling
Definition: stylebase.cpp:3789
A hash map, used for storage of kerning between characters of a font.
static void GetInfoList(a2dFontInfoList &list)
Append fonts of this type to the list.
Definition: stylebase.cpp:3156
static void SetLoadFlags(wxInt32 loadMethodMask)
Definition: stylebase.cpp:3247
const a2dFont * a2dNullFONT
global a2dFont stock object for NO font
virtual ~a2dFont()
Destructor.
Definition: stylebase.cpp:2883
static void SetLoadFlags(wxInt32 loadMethodMask)
Definition: stylebase.cpp:1018
a2dFontStrokeData(const wxString &filename=wxT(""), double size=0.0, bool monoSpaced=false, double weight=0.0)
Constructor.
Definition: stylebase.cpp:2171
Linear gradient Fill.
Definition: stylebase.cpp:3994
void SetWeight(double weight)
Set the weight of the font.
Definition: stylebase.cpp:3295
wxPenCap m_cap
Sets the pen cap style, which may be one of wxCAP_ROUND (default), wxCAP_PROJECTING and wxCAP_BUTT...
Definition: stylebase.cpp:5403
a2dPoint2D GetStart()
Get start for gradient fill colour change.
Definition: stylebase.cpp:4032
wxString m_extra
Extra information (e.g. the filename of the font).
Definition: stylebase.h:759
Filling using a wxbitmap.
Definition: stylebase.cpp:4321
const a2dError a2dError_XMLparse
a2dPoint2D GetStart() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4727
bounding class for optimizing drawing speed.
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
a2dPoint2D GetCenter() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4753
Drawing context abstraction.
Definition: drawer2d.h:177
a2dFillStyle m_style
style of Fill
Definition: stylebase.cpp:3607
a2dFontDcData(const wxFont &font=wxNullFont, double size=0.0)
Constructor.
Definition: stylebase.cpp:439
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
static a2dFont CreateFont(const a2dFontInfo &info, bool force=false)
Create the font from a fontinfo description.
Definition: stylebase.cpp:3163
A2DGENERALDLLEXP a2dSmrtPtr< a2dGeneralGlobal > a2dGeneralGlobals
a global pointer to get to global instance of important classes.
Definition: comevt.cpp:1148
a2dFontInfo m_fontinfo
Font info.
Definition: stylebase.cpp:237
bool m_ok
True if a valid font is set.
Definition: stylebase.cpp:249
void SetRadius(double radius)
radius for gradient fill colour change
Definition: stylebase.cpp:4257
void Add(a2dVpathSegment *seg)
add a segment
Definition: polyver.h:1240
wxString GetFilename(bool filenameonly=false) const
Get the font filename.
Definition: stylebase.cpp:1233
virtual ~a2dFontDcData()
Destructor.
Definition: stylebase.cpp:475
void SetColour(const wxColour &col)
set colour used for gradient and wxSTIPPLE_MASK_OPAQUE filling.
Definition: stylebase.cpp:4988
wxColour GetColour() const
return colour
Definition: stylebase.cpp:3593
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: stylebase.cpp:5842
double GetStrokeWidth() const
Get stroke width.
Definition: stylebase.cpp:2485
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: stylebase.cpp:4287
const a2dStroke * a2dINHERIT_STROKE
global a2dStroke stock object for INHERTED from parent object stroking
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:862
~a2dLinearGradientFillData(void)
destructor
Definition: stylebase.cpp:4023
Internal to a2dStroke for refcounting in wxObject style.
Definition: stylebase.cpp:5194
a2dPoint2D GetFocal() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4759
void QBCurveTo(double x1, double y1, double x2, double y2, bool withStroke=true)
add a quadratic bezier segment to the path
Definition: polyver.cpp:3918
const a2dFill * a2dNullFILL
global a2dFill stock object for defining NO filling
wxString GetFilename(bool filenameonly=false) const
Get the font filename.
Definition: stylebase.cpp:2213
double m_lead
Font external leading normalized to a font height of 1.
Definition: stylebase.cpp:246
A hash map, used for storage of character widths of a font.
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: stylebase.cpp:3970
void WriteEndAttributes(bool close=false)
&quot;Closes&quot; the start tag after writing all attributes (writes the &quot;&gt;&quot; or &quot;/&gt;&quot; bracket).
Definition: genxmlpars.cpp:837
a2dPathList & GetImagePathList()
Path for Images.
Definition: artglob.h:152
a2dFontInfo & operator=(const a2dFontInfo &other)
Assignment operator.
Definition: stylebase.cpp:89
double m_xfc
relative start and focal point x
Definition: stylebase.cpp:4211
~a2dPatternFillData(void)
destructor
Definition: stylebase.cpp:4350
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: stylebase.cpp:4516
double GetRadius()
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4187
a2dStrokeRefData()
constructor
Definition: stylebase.cpp:5201
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
wxString m_name
Font name.
Definition: stylebase.h:753
double GetAttributeValueDouble(const wxString &attrib, double defaultv=0)
Returns the double value of an attribute.
Definition: genxmlpars.cpp:474
wxPenJoin m_join
Sets the pen join style, which may be one of wxJOIN_BEVEL, wxJOIN_ROUND (default) and wxJOIN_MITER...
Definition: stylebase.cpp:5400
const a2dStroke * a2dNullSTROKE
global a2dStroke stock object for NO stroking
radial gradient Fill
Definition: stylebase.cpp:4140
virtual ~a2dFontFreetypeData()
Destructor.
Definition: stylebase.cpp:1163
bool GetFilling() const
if true, filling is on else filling is transparent.
Definition: stylebase.cpp:5069
void SetName(const wxString &name)
Set name of font, e.g. Arial.
Definition: stylebase.h:719
void SetStipple(const wxBitmap &stipple)
set stipple style
Definition: stylebase.cpp:5728
const a2dStroke * a2dWHITE_STROKE
global a2dStroke stock object for WHITE stroking
void SetFilename(const wxString &filename)
Set the font filename and load the font.
Definition: stylebase.cpp:2224
Contains graphical drawing context specific classes. a2dDrawer2D and derived classes are used for dra...
holes one glyph from a freetype font.
Definition: stylebase.h:581
void SetExtra(const wxString &extra)
Set the extra information ( e.g. the filename of the font )
Definition: stylebase.h:747
void SetColour2(const wxColour &col)
set colour 2 used for gradient and wxSTROKE_MASK_OPAQUE filling.
Definition: stylebase.cpp:6149
long m_faceindex
what font with index to load from file
Definition: stylebase.cpp:1052
virtual ~a2dStroke(void)
destructor
Definition: stylebase.cpp:5996
double * m_widthcache
Width cache normalized to a font height of 1. This stores the &#39;normal&#39; part of the alphabet...
Definition: stylebase.cpp:414
double GetWidth(wxChar c) const
Get width of a single character.
Definition: stylebase.cpp:2463
const a2dFont * a2dDEFAULT_CANVASFONT
global a2dFont stock object for default font
general modules header files all together.
wxUint16 m_intsize
Font size in internal coordinates.
Definition: stylebase.cpp:2127
a2dPoint2D GetStop()
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4035
void SetDeviceHeight(double sizeInPixels)
to set for load glyph from face, to do proper hinting
Definition: stylebase.cpp:1178
double GetWidth(wxChar c) const
Get width of a single character.
Definition: stylebase.cpp:693
wxString GetAttributeValue(const wxString &attrib, const wxString &defaultv=wxT(""))
Returns the value of an attribute.
Definition: genxmlpars.cpp:450
wxString FindFileName() const
Find the filename of the current font.
Definition: stylebase.cpp:662
virtual double GetKerning(wxChar c1, wxChar c2) const
Get kerning space between two characters.
Definition: stylebase.cpp:224
a2dFontInfo()
Constructor.
Definition: stylebase.h:690
double m_desc
Font descender cache normalized to a font height of 1.
Definition: stylebase.cpp:243
wxString StrokeStyle2String(a2dStrokeStyle style)
convert a style enum to a string
Definition: stylebase.cpp:5224
a2dFillType
for a2dFill to define the type of filling.
Definition: stylebase.h:126
wxString m_style
Font style.
Definition: stylebase.h:755
const wxString & GetStyle() const
Get style of font, e.g. Bold.
Definition: stylebase.h:722
void Require(const XMLeventType &type, wxString name)
Forces a special tag.
Definition: genxmlpars.cpp:390
~a2dTwoColourFillData(void)
destructor
Definition: stylebase.cpp:3765
void MoveTo(double x, double y)
add a MoveTo command to the path
Definition: polyver.cpp:3905
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: stylebase.cpp:3822
double GetWidth(wxChar c) const
Get width of a single character.
Definition: stylebase.cpp:1576
double m_weight
Font weight.
Definition: stylebase.cpp:2129
a2dFont()
Constructor.
Definition: stylebase.cpp:2721
a2dStroke(void)
constructor
Definition: stylebase.cpp:5939
double m_yfc
relative start and focal point y
Definition: stylebase.cpp:4214
wxColour GetColour() const
return colour
Definition: stylebase.cpp:5012
a2dLinearGradientFillData(void)
constructor
Definition: stylebase.cpp:4053
bool Scale(double scale)
Scale by scale (isotropic scaling i.e. the same in x and y):
Definition: afmatrix.cpp:270
bool Translate(double x, double y)
Translate by dx, dy:
Definition: afmatrix.cpp:420
double GetKerning(wxChar c1, wxChar c2) const
Get kerning space between two characters.
Definition: stylebase.cpp:2924
void LineTo(double x, double y, bool withStroke=true)
add a LineTo command to the path
Definition: polyver.cpp:3911
const a2dStroke * a2dTRANSPARENT_STROKE
global a2dStroke stock object for TRANSPARENT stroking
a2dPatternStrokeData()
constructor
Definition: stylebase.cpp:5754
a2dPoint2D GetFocal()
Get start for gradient fill colour change.
Definition: stylebase.cpp:4184
~a2dRadialGradientFillData(void)
destructor
Definition: stylebase.cpp:4169
a2dHatchFillData(void)
constructor
Definition: stylebase.cpp:3925
wxString CreateString() const
Assemble a string containing this class in a readable format.
Definition: stylebase.cpp:108
One Colour Fill.
Definition: stylebase.cpp:3565
double m_ye
relative y as end for gradient fill
Definition: stylebase.cpp:4208
wxFont m_font
Font.
Definition: stylebase.cpp:411
wxString m_filename
Filename of the font.
Definition: stylebase.cpp:2115
A list used for enumerating fonts.
initiates Freetype library
Definition: stylebase.h:1197
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: stylebase.cpp:3958
void SetFilename(const wxString &filename)
Set the font filename and load the font.
Definition: stylebase.cpp:1267
double m_size
Font Size.
Definition: stylebase.h:757
void SetType(const wxString &type)
Set type of font, e.g. Freetype or Stroke.
Definition: stylebase.h:714
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
DcWidthHash m_extwidthcache
Width cache normalized to a font height of 1. This stores the extended characters.
Definition: stylebase.cpp:416
BOOL GetFontFile(LPCTSTR lpszFontName, LPTSTR lpszDisplayName, int nDisplayNameSize, LPTSTR lpszFontFile, int nFontFileSize)
find a font that is close to a wxDC font.
wxString GetAsString()
Get all search paths as one string.
Definition: gen.cpp:4470
float GetWidth() const
Definition: stylebase.cpp:6281
void SetFilling(bool OnOff)
Definition: stylebase.cpp:5060
wxColour m_colour2
used for gradient fill or text background or opaque filling
Definition: stylebase.cpp:3792
wxUint16 m_count
Number of characters in font.
Definition: stylebase.cpp:2125
One Colour Fill.
Definition: stylebase.cpp:5326
Freetype font class.
Definition: stylebase.cpp:940
void SetFocal(double x, double y)
focal point, startpoint for gradient fill
Definition: stylebase.cpp:4263
initializes the general module
Definition: comevt.h:1238
Vector Path.
Definition: polyver.h:1211
const a2dFontInfo & GetFontInfo() const
Get fontinfo of the font.
Definition: stylebase.cpp:2901
bool m_pixelstroke
set if stroke is in pixels
Definition: stylebase.cpp:5397
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: stylebase.cpp:4111
~a2dOneColourFillData(void)
destructor
Definition: stylebase.cpp:3586
float m_width
width of stroke in world coordinates
Definition: stylebase.cpp:5394
a2dFillStyle m_style
style of Fill
Definition: stylebase.cpp:3795
a2dStrokeStyle
stroke styles for a2dStroke
Definition: stylebase.h:298
virtual float GetWidth() const
Definition: stylebase.cpp:5372
double m_xe
relative x as end for gradient fill
Definition: stylebase.cpp:4205
Internal to a2dFill for refcounting in wxObject style.
Definition: stylebase.cpp:3526
wxString m_filename
Filename of the vector font.
Definition: stylebase.cpp:1025
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)=0
Load settings.
list of a2dObject&#39;s
Definition: gen.h:3157
void a2dCanvasDeleteStockObjects()
to delete stock style ( a2dStroke a2dFill ) objects.
Definition: stylebase.cpp:3383
wxColour GetColour() const
return colour
Definition: stylebase.cpp:3781
void SetColour2(const wxColour &col)
set colour 2 used for gradient and wxSTIPPLE_MASK_OPAQUE filling.
Definition: stylebase.cpp:4949
double m_sizeInPixels
current text drawn its size in pixels to do proper hinting.
Definition: stylebase.cpp:408
wxColour GetColour2() const
return colour 2
Definition: stylebase.cpp:6170
a2dGlyphHash m_extglyphcache
Glyph cache. This stores the extended characters.
Definition: stylebase.cpp:1031
virtual double GetWidth(wxChar c) const =0
Get width of a single character.
const a2dStroke * a2dLAYER_SELECT_STROKE
global a2dStroke stock object for SELECTED object stroking
void SetPixelStroke(bool pixelstroke)
set pixelstoke flag, stroke width is defined in pixels else in worldcoordinates
Definition: stylebase.cpp:5377
void SetStop(double x, double y)
stop for gradient fill colour change
Definition: stylebase.cpp:4088
a2dFontRefData()
constructor
Definition: stylebase.cpp:184
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
~a2dHatchFillData(void)
destructor
Definition: stylebase.cpp:3914
wxFontEncoding m_encoding
encoding setting
Definition: stylebase.cpp:1046
double GetWeight() const
Get the weight of the font.
Definition: stylebase.cpp:3283
stylebase.cpp Source File -- Sun Oct 12 2014 17:04:26 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation