00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "a2dprec.h"
00012
00013 #ifndef WX_PRECOMP
00014 #include "wx/wx.h"
00015 #endif
00016
00017 #include <wx/dir.h>
00018 #include <wx/file.h>
00019 #include <wx/filename.h>
00020 #include <wx/fontenum.h>
00021 #include <wx/module.h>
00022
00023 #include "wx/general/genmod.h"
00024
00025
00026
00027 #include "wx/artbase/stylebase.h"
00028 #include "wx/artbase/bbox.h"
00029 #include "wx/artbase/drawer2d.h"
00030 #include "wx/artbase/polyver.h"
00031
00032 #if defined(__USE_WINAPI__)
00033 #include "wx/msw/dc.h"
00034 #include "wx/artbase/mswfont.h"
00035 #endif
00036
00037 #if defined(__WXMSW__) && defined(__MEMDEBUG__)
00038 #include <wx/msw/msvcrt.h>
00039 #endif
00040
00041 #define newline wxString("\n")
00042
00043 #if wxART2D_USE_FREETYPE
00044 FT_Library g_freetypeLibrary;
00045 #endif
00046
00047 #define wxART2D_USE_DC2FREETYPE 1
00048
00049
00050 IMPLEMENT_DYNAMIC_CLASS( a2dStroke, wxObject )
00051 IMPLEMENT_DYNAMIC_CLASS( a2dFill, wxObject )
00052
00053 IMPLEMENT_DYNAMIC_CLASS( a2dFillProperty, a2dNamedProperty )
00054 IMPLEMENT_DYNAMIC_CLASS( a2dStrokeProperty, a2dNamedProperty )
00055 IMPLEMENT_DYNAMIC_CLASS( a2dFontProperty, a2dNamedProperty )
00056
00057
00058
00059
00060
00061 a2dFontProperty::a2dFontProperty(): a2dNamedProperty()
00062 {
00063 }
00064
00065 a2dFontProperty::a2dFontProperty( const a2dPropertyIdFont* id, const a2dFont& value )
00066 :a2dNamedProperty( id )
00067 {
00068 m_value = value;
00069 }
00070
00071 a2dFontProperty::a2dFontProperty( const a2dFontProperty* ori )
00072 : a2dNamedProperty( *ori )
00073 {
00074 m_value = ori->m_value;
00075 }
00076
00077 a2dFontProperty::~a2dFontProperty()
00078 {
00079 }
00080
00081 a2dFontProperty::a2dFontProperty( const a2dFontProperty &other )
00082 : a2dNamedProperty( other )
00083 {
00084 m_value = other.m_value;
00085 }
00086
00087 a2dNamedProperty *a2dFontProperty::Clone( a2dObject::CloneOptions WXUNUSED(options) ) const
00088 {
00089 return new a2dFontProperty(*this );
00090 };
00091
00092 void a2dFontProperty::Assign( const a2dNamedProperty &other )
00093 {
00094 a2dFontProperty *propcast = wxStaticCast( &other, a2dFontProperty);
00095 m_value = propcast->m_value;
00096 }
00097
00098 a2dFontProperty *a2dFontProperty::CreatePropertyFromString( const a2dPropertyIdFont* id, const wxString& WXUNUSED(value) )
00099 {
00100 return 0;
00101 }
00102
00103 #if wxART2D_USE_CVGIO
00104 void a2dFontProperty::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
00105 {
00106 a2dNamedProperty::DoSave( parent, out, xmlparts, towrite );
00107 if ( xmlparts == a2dXmlSer_attrib )
00108 {
00109 }
00110 else
00111 {
00112
00113 }
00114 }
00115
00116 void a2dFontProperty::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
00117 {
00118 a2dNamedProperty::DoLoad( parent, parser, xmlparts );
00119 if ( xmlparts == a2dXmlSer_attrib )
00120 {
00121 }
00122 else
00123 {
00124
00125 }
00126 }
00127 #endif //wxART2D_USE_CVGIO
00128
00129 void a2dFontProperty::SetValue( const a2dFont& value )
00130 {
00131 m_value = value;
00132 }
00133
00134 wxString a2dFontProperty::StringRepresentation() const
00135 {
00136 return wxT("VOID");
00137 }
00138
00139 wxString a2dFontProperty::StringValueRepresentation() const
00140 {
00141 return wxT("VOID");
00142 }
00143
00144
00145
00146
00147
00148 #include <wx/listimpl.cpp>
00149 WX_DEFINE_LIST( a2dFontInfoList );
00150
00151
00152
00153
00154
00155 a2dFontInfo::a2dFontInfo( const wxString& type, const wxString& name,
00156 const wxString& style, double size, const wxString& extra )
00157 {
00158 m_type = type;
00159 m_name = name;
00160 m_style = style;
00161 m_size = size;
00162 m_extra = extra;
00163 }
00164
00165 a2dFontInfo::a2dFontInfo( const wxString& type, const wxString& name,
00166 const wxString& style, const wxString& extra )
00167 {
00168 m_type = type;
00169 m_name = name;
00170 m_style = style;
00171 m_size = 1.0;
00172 m_extra = extra;
00173 }
00174
00175 a2dFontInfo::a2dFontInfo( const wxString& info )
00176 {
00177 ParseString( info );
00178 }
00179
00180 a2dFontInfo& a2dFontInfo::operator=( const a2dFontInfo& other )
00181 {
00182 m_type = other.m_type;
00183 m_name = other.m_name;
00184 m_style = other.m_style;
00185 m_size = other.m_size;
00186 m_extra = other.m_extra;
00187 return *this;
00188 }
00189
00190 bool a2dFontInfo::operator == ( const a2dFontInfo& other ) const
00191 {
00192 return m_type == other.m_type
00193 && m_name == other.m_name
00194 && m_style == other.m_style
00195 && m_size == other.m_size
00196 && m_extra == other.m_extra;
00197 }
00198
00199 wxString a2dFontInfo::CreateString() const
00200 {
00201 wxString size;
00202 size.Printf( wxT( "%f" ), m_size );
00203 wxString description = m_type + wxT( "-" ) + m_name + wxT( "-" ) + m_style
00204 + wxT( "-" ) + size + wxT( "-" );
00205 if ( !m_extra.IsEmpty() )
00206 description += wxT( "-" ) + m_extra;
00207
00208 return description;
00209 }
00210
00211 void a2dFontInfo::ParseString( wxString string )
00212 {
00213 size_t stringlength = string.Length();
00214 size_t idx, last;
00215 idx = last = 0;
00216 while ( idx < stringlength && string[idx] != wxChar( '-' ) )
00217 idx++;
00218 m_type = string.Mid( last, idx - last );
00219 if ( idx < stringlength )
00220 idx++;
00221 last = idx;
00222 while ( idx < stringlength && string[idx] != wxChar( '-' ) )
00223 idx++;
00224 m_name = string.Mid( last, idx - last );
00225 if ( idx < stringlength )
00226 idx++;
00227 last = idx;
00228 while ( idx < stringlength && string[idx] != wxChar( '-' ) )
00229 idx++;
00230 m_style = string.Mid( last, idx - last );
00231 if ( idx < stringlength )
00232 idx++;
00233 last = idx;
00234 while ( idx < stringlength && string[idx] != wxChar( '-' ) )
00235 idx++;
00236 string.Mid( last, idx - last ).ToDouble( &m_size );
00237 if ( idx < stringlength )
00238 idx++;
00239 last = idx;
00240 while ( idx < stringlength && string[idx] != wxChar( '-' ) )
00241 idx++;
00242 if ( idx < stringlength )
00243 idx++;
00244 last = idx;
00245 m_extra = string.Mid( last );
00246 }
00247
00248 a2dFont a2dFontInfo::CreateFont( double size )
00249 {
00250 m_size = size;
00251 return a2dFont::CreateFont( *this );
00252 }
00253
00254
00255
00256
00257
00258 class A2DARTBASEDLLEXP a2dFontRefData : public wxObjectRefData
00259 {
00260 friend class a2dFont;
00261 public:
00262
00263 virtual a2dFontType GetType( void ) const { return a2dFONT_NULL; }
00264
00265 a2dFontRefData( double size )
00266 {
00267 m_fontinfo.SetSize( size );
00268 m_height = 1;
00269 m_desc = 0;
00270 m_lead = 0;
00271 m_ok = false;
00272 }
00273
00274
00275 a2dFontRefData()
00276 {
00277 }
00278
00279 a2dFontRefData( const a2dFontRefData& other )
00280 : wxObjectRefData()
00281 {
00282 m_fontinfo = other.m_fontinfo;
00283 m_height = other.m_height;
00284 m_desc = other.m_desc;
00285 m_lead = other.m_lead;
00286 m_ok = other.m_ok;
00287 }
00288
00289 bool Ok() { return m_ok; }
00290 inline void SetSize( double size ) { m_fontinfo.SetSize( size ); }
00291 inline double GetSize() const { return m_fontinfo.GetSize(); }
00292
00293 double GetDescent() const
00294 {
00295 if ( m_ok )
00296 return m_fontinfo.GetSize() * m_desc;
00297 else
00298 return 0.0;
00299 }
00300
00301 double GetLineHeight() const
00302 {
00303 if ( m_ok )
00304 return m_fontinfo.GetSize() * m_height;
00305 else
00306 return 0.0;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315 virtual double GetKerning( wxChar WXUNUSED( c1 ), wxChar WXUNUSED( c2 ) ) const { return 0.0; }
00316
00317
00318 virtual double GetWidth( wxChar c ) const = 0;
00319
00320 virtual bool GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine = a2dIDENTITY_MATRIX ) { return false; }
00321
00322 void GetTextExtent( const wxString& string, double& w, double& h, double& descent, double& externalLeading ) const;
00323
00324
00325 protected:
00326
00327
00328 a2dFontInfo m_fontinfo;
00329
00330
00331 double m_height;
00332
00333
00334 double m_desc;
00335
00336
00337 double m_lead;
00338
00339
00340 bool m_ok;
00341
00342 #if wxART2D_USE_CVGIO
00343
00344 //virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList* towrite ) = 0;
00345
00346 //virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts ) = 0;
00347 #endif //wxART2D_USE_CVGIO
00348
00349 };
00350
00351 void a2dFontRefData::GetTextExtent( const wxString& string, double& w,
00352 double& h, double& descent, double& externalLeading ) const
00353 {
00354 if ( m_ok )
00355 {
00356 double x = 0.0;
00357 for ( size_t n = 0; n < string.Length(); n++ )
00358 {
00359 if ( n > 0 )
00360 x += GetKerning( string[n-1], string[n] );
00361 x += GetWidth( string[n] );
00362 }
00363 w = x;
00364 h = GetSize() * m_height;
00365 descent = GetSize() * m_desc;
00366 externalLeading = GetSize() * m_lead;
00367 }
00368 else
00369 w = h = descent = externalLeading = 0.0;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 class A2DARTBASEDLLEXP a2dFontDcData
00389 : public a2dFontRefData
00390 {
00391 friend class a2dFont;
00392 public:
00393
00394 virtual a2dFontType GetType( void ) const { return a2dFONT_WXDC; }
00395
00396
00397
00398
00399
00400 a2dFontDcData( const wxFont& font = wxNullFont, double size = 0.0 );
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 a2dFontDcData( double size, int family, int style = wxNORMAL, int weight = wxNORMAL,
00434 const bool underline = false, const wxString& faceName = wxT( "" ),
00435 wxFontEncoding encoding = wxFONTENCODING_DEFAULT );
00436
00437
00438 a2dFontDcData( const a2dFontDcData& other );
00439
00440 virtual ~a2dFontDcData();
00441
00442
00443
00444
00445 void SetFont( const wxFont& font );
00446
00447
00448
00449
00450
00451 wxFont& GetFont( void ) { return m_font; }
00452
00453
00454
00455
00456
00457 wxString FindFileName() const;
00458
00459
00460 double GetWidth( wxChar c ) const;
00461
00462
00463 double GetKerning( wxChar c1, wxChar c2 ) const;
00464
00465
00466 static void GetInfoList( a2dFontInfoList& list );
00467
00468
00469 static a2dFontDcData* CreateFont( const a2dFontInfo& info, bool force = false );
00470
00471 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
00472
00473 virtual void SetSize( double size );
00474
00475
00476 a2dFont GetFreetypeFont();
00477 #endif
00478
00479
00480 protected:
00481
00482 wxFont m_font;
00483
00484
00485 mutable double* m_widthcache;
00486
00487 mutable DcWidthHash m_extwidthcache;
00488
00489 #if defined(__USE_WINAPI__)
00490
00491 mutable KERNINGPAIR* m_kerningcache;
00492
00493 mutable int m_nkerningpairs;
00494 #else
00495
00496 mutable DcKerningHash m_kerningcache;
00497 #endif
00498
00499 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
00500
00501 a2dFont m_freetypefont;
00502 #endif
00503 };
00504
00505
00506 #define CHAR_CACHE_START wxChar(' ')
00507 #define CHAR_CACHE_END wxChar('~')
00508
00509 a2dFontDcData::a2dFontDcData( const wxFont& font, double size )
00510 : a2dFontRefData( size )
00511 {
00512 m_fontinfo.SetType( wxT( "Device font" ) );
00513 m_widthcache = NULL;
00514 #if defined(__USE_WINAPI__)
00515 m_kerningcache = NULL;
00516 #endif
00517 SetFont( font );
00518 }
00519
00520 a2dFontDcData::a2dFontDcData( double size, int family, int style, int weight,
00521 const bool underline, const wxString& faceName, wxFontEncoding encoding )
00522 : a2dFontRefData( size )
00523 {
00524 m_fontinfo.SetType( wxT( "Device font" ) );
00525 m_widthcache = NULL;
00526 #if defined(__USE_WINAPI__)
00527 m_kerningcache = NULL;
00528 #endif
00529 SetFont( wxFont( 1, family, style, weight, underline, faceName, encoding ) );
00530 }
00531
00532 a2dFontDcData::a2dFontDcData( const a2dFontDcData& other )
00533 : a2dFontRefData( other )
00534 {
00535 m_widthcache = NULL;
00536 #if defined(__USE_WINAPI__)
00537 m_kerningcache = NULL;
00538 #endif
00539 SetFont( other.m_font );
00540 }
00541
00542 a2dFontDcData::~a2dFontDcData()
00543 {
00544 if ( m_widthcache )
00545 delete[] m_widthcache;
00546 #if defined(__USE_WINAPI__)
00547 if ( m_kerningcache )
00548 delete[] m_kerningcache;
00549 #endif
00550 }
00551
00552 void a2dFontDcData::SetFont( const wxFont& font )
00553 {
00554 m_font = font;
00555 m_ok = m_font.Ok();
00556
00557
00558 while ( !m_extwidthcache.empty() )
00559 {
00560 DcWidthHash::iterator it = m_extwidthcache.begin();
00561 m_extwidthcache.erase( it );
00562 }
00563
00564
00565 if ( !m_widthcache )
00566 m_widthcache = new double[CHAR_CACHE_END - CHAR_CACHE_START + 1];
00567
00568 wxMemoryDC dc;
00569 wxFont fnt = m_font;
00570 fnt.SetPointSize( NORMFONT );
00571 dc.SetFont( fnt );
00572 wxChar c;
00573 wxString string;
00574 wxCoord width, height, desc, lead;
00575 width = height = desc = lead = 0;
00576 for ( c = CHAR_CACHE_START; c <= CHAR_CACHE_END; c++ )
00577 {
00578 string = c;
00579 dc.GetTextExtent( string, &width, &height, &desc, &lead );
00580 m_widthcache[c - CHAR_CACHE_START] = ( double ) width / NORMFONT;
00581 }
00582 m_height = ( double ) height / NORMFONT;
00583 m_desc = ( double ) desc / NORMFONT;
00584 m_lead = ( double ) lead / NORMFONT;
00585
00586 if ( m_font.GetFaceName().IsEmpty() )
00587 m_fontinfo.SetName( wxT("Arial") );
00588 else
00589 m_fontinfo.SetName( m_font.GetFaceName() );
00590 wxString style = wxEmptyString;
00591 switch ( m_font.GetWeight() )
00592 {
00593 case wxNORMAL:
00594 if ( m_font.GetStyle() == wxNORMAL )
00595 style = wxT( "Regular" );
00596 break;
00597 case wxBOLD:
00598 style = wxT( "Bold " );
00599 break;
00600 case wxLIGHT:
00601 style = wxT( "Light " );
00602 break;
00603 }
00604 switch ( m_font.GetStyle() )
00605 {
00606 case wxNORMAL:
00607 break;
00608 case wxITALIC:
00609 case wxSLANT:
00610 style += wxT( "Italic" );
00611 break;
00612 }
00613 m_fontinfo.SetStyle( style.Trim() );
00614
00615 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
00616 #if wxART2D_USE_DC2FREETYPE
00617 wxString filename = FindFileName();
00618 if ( !filename.IsEmpty() )
00619 {
00620 m_freetypefont = a2dFont( filename, GetSize() );
00621 }
00622 #endif
00623 #endif
00624
00625 #if defined(__USE_WINAPI__)
00626
00627
00628 if ( m_kerningcache )
00629 {
00630 delete[] m_kerningcache;
00631 m_nkerningpairs = 0;
00632 }
00633 #if wxCHECK_VERSION(2,9,0)
00634 wxMSWDCImpl* dcimpl = wxStaticCast( dc.GetImpl(), wxMSWDCImpl );
00635 WXHDC hdc = dcimpl->GetHDC();
00636 #else
00637 WXHDC hdc = dc.GetHDC();
00638 #endif
00639
00640 m_nkerningpairs = ::GetKerningPairs( ( HDC ) hdc, 0, NULL );
00641 m_kerningcache = new KERNINGPAIR[ m_nkerningpairs ];
00642 m_nkerningpairs = ::GetKerningPairs( ( HDC ) hdc, m_nkerningpairs, m_kerningcache );
00643 #endif //defined(__USE_WINAPI__)
00644 dc.SetFont( wxNullFont );
00645 }
00646
00647 wxString a2dFontDcData::FindFileName() const
00648 {
00649 wxString filename;
00650 #if defined(__USE_WINAPI__)
00651 wxString facename = m_font.GetFaceName();
00652 if ( m_font.GetWeight() == wxBOLD )
00653 facename += wxT( " Bold" );
00654 if ( m_font.GetStyle() == wxITALIC )
00655 facename += wxT( " Italic" );
00656
00657 TCHAR displayname[_MAX_PATH];
00658 TCHAR fontfilename[_MAX_PATH];
00659 if( GetFontFile( facename.c_str(), displayname, _MAX_PATH - 1,
00660 fontfilename, _MAX_PATH - 1 ) )
00661 {
00662 filename = fontfilename;
00663 }
00664 #endif // defined( __USE_WINAPI__ )
00665
00666 return filename;
00667 }
00668
00669 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
00670 void a2dFontDcData::SetSize( double size )
00671 {
00672 SetSize( size );
00673 m_freetypefont.SetSize( size );
00674 }
00675 #endif
00676
00677 double a2dFontDcData::GetWidth( wxChar c ) const
00678 {
00679 if ( !m_ok )
00680 return 0.0;
00681
00682
00683 if ( c >= CHAR_CACHE_START && c <= CHAR_CACHE_END )
00684 return GetSize() * m_widthcache[c - CHAR_CACHE_START];
00685 else
00686 {
00687 DcWidthHash::iterator it = m_extwidthcache.find( c );
00688 if ( it == m_extwidthcache.end() )
00689 {
00690 wxMemoryDC dc;
00691 wxFont font = m_font;
00692 font.SetPointSize( NORMFONT );
00693 dc.SetFont( font );
00694 wxCoord width, height, desc, lead;
00695 wxString string = c;
00696 dc.GetTextExtent( string, &width, &height, &desc, &lead );
00697 dc.SetFont( wxNullFont );
00698 m_extwidthcache[c] = ( double ) width / NORMFONT;
00699 return GetSize() * width / NORMFONT;
00700 }
00701 else
00702 return GetSize() * it->second;
00703 }
00704 }
00705
00706 double a2dFontDcData::GetKerning( wxChar c1, wxChar c2 ) const
00707 {
00708 #if defined( __USE_WINAPI__ )
00709 WORD a = c1;
00710 WORD b = c2;
00711 KERNINGPAIR* ptr = m_kerningcache;
00712 int i = m_nkerningpairs;
00713 while ( i-- )
00714 {
00715 if ( ptr->wFirst == a && ptr->wSecond == b )
00716 return GetSize() * ptr->iKernAmount / NORMFONT;
00717 ptr++;
00718 }
00719 return 0.0;
00720 #else // defined( __USE_WINAPI__ )
00721 wxString ab = c1;
00722 ab += c2;
00723 DcKerningHash::iterator it = m_kerningcache.find( ab );
00724 if ( it == m_kerningcache.end() )
00725 {
00726 wxMemoryDC dc;
00727 wxFont font = m_font;
00728 font.SetPointSize( NORMFONT );
00729 dc.SetFont( font );
00730 wxCoord width, height, desc, lead;
00731 dc.GetTextExtent( ab, &width, &height, &desc, &lead );
00732 dc.SetFont( wxNullFont );
00733 double kerning = ( double ) width / NORMFONT - ( GetWidth( c1 ) + GetWidth( c2 ) ) / GetSize();
00734 m_kerningcache[ab] = kerning;
00735 return GetSize() * kerning;
00736 }
00737 else
00738 return GetSize() * it->second;
00739 #endif // defined( __USE_WINAPI__ )
00740 }
00741
00742
00743 class DcFontEnumerator : public wxFontEnumerator
00744 {
00745 public:
00746 virtual bool OnFacename( const wxString& facename )
00747 {
00748 m_facenames.Add( facename );
00749 return true;
00750 }
00751 wxArrayString m_facenames;
00752 };
00753
00754 void a2dFontDcData::GetInfoList( a2dFontInfoList& list )
00755 {
00756 DcFontEnumerator enumerator;
00757 enumerator.EnumerateFacenames();
00758 for ( unsigned int i = 0; i < enumerator.m_facenames.GetCount(); i++ )
00759 {
00760 wxString fontname = enumerator.m_facenames.Item( i );
00761 list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Regular" ), 1.0 ) );
00762 list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Italic" ), 1.0 ) );
00763 list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Bold" ), 1.0 ) );
00764 list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Bold Italic" ), 1.0 ) );
00765 list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Light" ), 1.0 ) );
00766 list.Append( new a2dFontInfo( wxT( "Device font" ), fontname, wxT( "Light Italic" ), 1.0 ) );
00767 }
00768 }
00769
00770 a2dFontDcData* a2dFontDcData::CreateFont( const a2dFontInfo& info, bool force )
00771 {
00772 int slant = wxNORMAL;
00773 int weight = wxNORMAL;
00774 if ( force || info.GetType().Upper() == wxT( "DEVICE FONT" ) )
00775 {
00776 if ( info.GetStyle().Upper().Find( wxT( "ITALIC" ) ) != -1 )
00777 slant = wxITALIC;
00778 if ( info.GetStyle().Upper().Find( wxT( "BOLD" ) ) != -1 )
00779 weight = wxBOLD;
00780 if ( info.GetStyle().Upper().Find( wxT( "LIGHT" ) ) != -1 )
00781 weight = wxLIGHT;
00782
00783 a2dFontDcData *font = new a2dFontDcData( info.GetSize(), wxSWISS, slant, weight, false, info.GetName() );
00784 if ( font->Ok() )
00785 return font;
00786 else
00787 delete font;
00788 }
00789 return NULL;
00790 }
00791
00792 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
00793 a2dFont a2dFontDcData::GetFreetypeFont()
00794 {
00795 return m_freetypefont;
00796 }
00797 #endif
00798
00799
00800
00801
00802
00803 class a2dFreetypeFace;
00804
00805
00806 IMPLEMENT_DYNAMIC_CLASS( a2dFreetypeModule, wxModule )
00807
00808 a2dFreetypeModule::a2dFreetypeModule()
00809 {
00810 AddDependency( CLASSINFO( a2dGeneralModule ) );
00811 }
00812
00813 bool a2dFreetypeModule::OnInit()
00814 {
00815 #if wxART2D_USE_FREETYPE
00816 int error = FT_Init_FreeType( &g_freetypeLibrary );
00817 if ( error ) return false;
00818 #endif
00819 return true;
00820 }
00821
00822 void a2dFreetypeModule::OnExit()
00823 {
00824 a2dFont::ClearFontCache();
00825
00826 #if wxART2D_USE_FREETYPE
00827 FT_Done_FreeType( g_freetypeLibrary );
00828
00829
00830 g_freetypeLibrary = NULL;
00831 #endif
00832 }
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 class A2DARTBASEDLLEXP a2dFontFreetypeData
00847 : public a2dFontRefData
00848 {
00849 friend class a2dFont;
00850 public:
00851
00852 virtual a2dFontType GetType( void ) const { return a2dFONT_FREETYPE; }
00853
00854
00855
00856
00857
00858
00859 a2dFontFreetypeData( const wxString& filename = wxT( "" ), double size = 0.0, wxFontEncoding encoding = wxFONTENCODING_DEFAULT, int weight = wxNORMAL );
00860 #if defined(__USE_WINAPI__)
00861
00862
00863
00864
00865
00866
00867
00868 a2dFontFreetypeData( const wxFont& font, double size = 0.0, wxFontEncoding encoding = wxFONTENCODING_DEFAULT );
00869 #endif // defined( __USE_WINAPI__ )
00870
00871
00872 a2dFontFreetypeData( const a2dFontFreetypeData& other );
00873
00874
00875 virtual ~a2dFontFreetypeData();
00876
00877
00878
00879
00880
00881
00882 void SetFilename( const wxString& filename );
00883
00884
00885
00886
00887 wxString GetFilename( bool filenameonly = false ) const;
00888
00889 void SetEncodingConverter( wxEncodingConverter* converter );
00890
00891
00892
00893
00894 const a2dGlyph* GetGlyph( wxChar c ) const;
00895
00896
00897 double GetWidth( wxChar c ) const;
00898
00899
00900 double GetKerning( wxChar c1, wxChar c2 ) const;
00901
00902
00903 bool GetVpath( wxChar c, a2dVpath& glyph, const a2dAffineMatrix& affine = a2dIDENTITY_MATRIX );
00904
00905
00906 static void GetInfoList( a2dFontInfoList& list );
00907
00908
00909 static a2dFontFreetypeData* CreateFont( const a2dFontInfo& info, bool force = false );
00910
00911 protected:
00912
00913 wxString m_filename;
00914
00915
00916 mutable a2dGlyph* m_glyphcache;
00917
00918 mutable a2dGlyphHash m_extglyphcache;
00919
00920 #if wxART2D_USE_FREETYPE
00921
00922 mutable wxChar m_lastChar;
00923
00924 mutable a2dGlyph* m_a2dLastGlyph;
00925 #endif // wxART2D_USE_FREETYPE
00926
00927
00928 FT_Face m_face;
00929
00930
00931 wxFontEncoding m_encoding;
00932
00933
00934 wxEncodingConverter *m_converter;
00935
00936 void ClearCacheLinkes( void );
00937 };
00938
00939 a2dFontFreetypeData::a2dFontFreetypeData( const wxString& filename, double size, wxFontEncoding encoding, int weight )
00940 : a2dFontRefData( size )
00941 {
00942 m_fontinfo.SetType( wxT( "Freetype font" ) );
00943 m_face = NULL;
00944 m_glyphcache = NULL;
00945 m_converter = NULL;
00946 m_encoding = encoding;
00947 #if wxART2D_USE_FREETYPE
00948 m_lastChar = ( wxChar ) - 1;
00949 m_a2dLastGlyph = NULL;
00950 #endif
00951
00952 if( m_encoding != wxFONTENCODING_DEFAULT )
00953 {
00954 m_converter = new wxEncodingConverter();
00955 wxASSERT( m_converter != NULL );
00956 if( !m_converter->Init( m_encoding, wxFONTENCODING_UNICODE ) )
00957 {
00958 delete m_converter;
00959 m_converter = NULL;
00960
00961 }
00962 }
00963
00964 SetFilename( filename );
00965 }
00966
00967 #if defined(__USE_WINAPI__)
00968 a2dFontFreetypeData::a2dFontFreetypeData( const wxFont& font, double size, wxFontEncoding encoding )
00969 : a2dFontRefData( size )
00970 {
00971 m_fontinfo.SetType( wxT( "Freetype font" ) );
00972 m_face = NULL;
00973 m_glyphcache = NULL;
00974 m_converter = NULL;
00975 m_encoding = encoding;
00976 #if wxART2D_USE_FREETYPE
00977 m_lastChar = ( wxChar ) - 1;
00978 m_a2dLastGlyph = NULL;
00979 #endif
00980
00981 if( m_encoding != wxFONTENCODING_DEFAULT )
00982 {
00983 m_converter = new wxEncodingConverter();
00984 wxASSERT( m_converter != NULL );
00985 if( !m_converter->Init( m_encoding, wxFONTENCODING_UNICODE ) )
00986 {
00987 delete m_converter;
00988 m_converter = NULL;
00989
00990 }
00991 }
00992
00993 wxString filename;
00994 wxString facename = font.GetFaceName();
00995 if ( font.GetWeight() == wxBOLD )
00996 facename += wxT( " Bold" );
00997 if ( font.GetStyle() == wxITALIC )
00998 facename += wxT( " Italic" );
00999
01000 TCHAR displayname[10];
01001 TCHAR fontfilename[_MAX_PATH];
01002
01003 if( GetFontFile( facename.c_str(), displayname, sizeof( displayname ),
01004 fontfilename, sizeof( fontfilename ) ) )
01005 {
01006 SetFilename( fontfilename );
01007 }
01008 }
01009 #endif // defined( __USE_WINAPI__ )
01010
01011 a2dFontFreetypeData::a2dFontFreetypeData( const a2dFontFreetypeData& other )
01012 : a2dFontRefData( other )
01013 {
01014 m_face = NULL;
01015 m_glyphcache = NULL;
01016 m_converter = NULL;
01017 m_encoding = other.m_encoding;
01018 #if wxART2D_USE_FREETYPE
01019 m_lastChar = ( wxChar ) - 1;
01020 m_a2dLastGlyph = NULL;
01021 #endif
01022
01023 if( m_encoding != wxFONTENCODING_DEFAULT )
01024 {
01025 m_converter = new wxEncodingConverter();
01026 wxASSERT( m_converter != NULL );
01027 if( !m_converter->Init( m_encoding, wxFONTENCODING_UNICODE ) )
01028 {
01029 delete m_converter;
01030 m_converter = NULL;
01031
01032 }
01033 }
01034 SetFilename( other.m_filename );
01035 }
01036
01037 a2dFontFreetypeData::~a2dFontFreetypeData()
01038 {
01039 #if wxART2D_USE_FREETYPE
01040
01041 if ( m_glyphcache )
01042 {
01043 ClearCacheLinkes();
01044 delete[] m_glyphcache;
01045 }
01046 m_extglyphcache.clear();
01047
01048 if ( m_face && g_freetypeLibrary )
01049 FT_Done_Face( m_face );
01050
01051 #endif // wxART2D_USE_FREETYPE
01052 if( m_converter )
01053 delete m_converter;
01054 }
01055
01056 wxString a2dFontFreetypeData::GetFilename( bool filenameonly ) const
01057 {
01058 if ( filenameonly )
01059 {
01060 wxFileName filename( m_filename );
01061 return filename.GetFullName();
01062 }
01063 else
01064 return m_filename;
01065 }
01066
01067 void a2dFontFreetypeData::ClearCacheLinkes( void )
01068 {
01069 #if wxART2D_USE_FREETYPE
01070 m_lastChar = ( wxChar ) - 1;
01071 m_a2dLastGlyph = NULL;
01072 #endif
01073 int qpos = wxChar( '?' ) - CHAR_CACHE_START;
01074 if( m_glyphcache[qpos].m_glyph != NULL && m_glyphcache[qpos].m_glyph != ( FT_Glyph ) - 1 )
01075 {
01076 size_t index = m_glyphcache[qpos].m_index;
01077 for ( size_t i = CHAR_CACHE_START; i <= CHAR_CACHE_END; i++ )
01078 if( m_glyphcache[i - CHAR_CACHE_START].m_index == index )
01079 m_glyphcache[i - CHAR_CACHE_START].m_glyph = NULL;
01080
01081 a2dGlyphHash::iterator it = m_extglyphcache.begin();
01082 for( ;it != m_extglyphcache.end(); it++ )
01083 {
01084 if( it->second.m_index == index )
01085 it->second.m_glyph = NULL;
01086 }
01087 }
01088 }
01089
01090 void a2dFontFreetypeData::SetFilename( const wxString& filename )
01091 {
01092 m_filename = filename;
01093
01094 #if wxART2D_USE_FREETYPE
01095 if ( m_face )
01096 {
01097 FT_Done_Face( m_face );
01098 m_face = NULL;
01099 }
01100 m_ok = false;
01101
01102
01103 if ( !m_glyphcache )
01104 m_glyphcache = new a2dGlyph[ CHAR_CACHE_END - CHAR_CACHE_START + 1 ];
01105 else
01106 {
01107 ClearCacheLinkes();
01108
01109 for ( size_t i = CHAR_CACHE_START; i <= CHAR_CACHE_END; i++ )
01110 if( m_glyphcache[i - CHAR_CACHE_START].m_glyph != NULL )
01111 FT_Done_Glyph( m_glyphcache[i - CHAR_CACHE_START].m_glyph );
01112
01113 for ( size_t j = CHAR_CACHE_START; j <= CHAR_CACHE_END; j++ )
01114 m_glyphcache[j - CHAR_CACHE_START].m_glyph = NULL;
01115 }
01116 m_extglyphcache.clear();
01117
01118 if ( filename.IsEmpty() )
01119 return;
01120
01121 wxString fname = a2dGlobals->GetFontPathList().FindValidPath( m_filename );
01122 if ( !::wxFileExists( fname ) )
01123 {
01124 a2dGeneralGlobals->ReportErrorF( a2dError_FileCouldNotOpen, _( "Sorry, could not open file %s for loading font" ), m_filename.c_str() );
01125 return;
01126 }
01127
01128 FT_Error error;
01129 error = FT_New_Face( g_freetypeLibrary, fname.mb_str(), 0, &m_face );
01130 if ( error )
01131 {
01132 a2dGeneralGlobals->ReportErrorF( a2dError_FileCouldNotOpen, _( "file %s contains wrong font" ), m_filename.c_str() );
01133 m_face = NULL;
01134 return;
01135 }
01136 else if ( !( m_face->face_flags & FT_FACE_FLAG_SCALABLE ) )
01137 {
01138 a2dGeneralGlobals->ReportErrorF( a2dError_FileCouldNotOpen, _( "file %s contains non scalable font" ), m_filename.c_str() );
01139 m_face = NULL;
01140 return;
01141 }
01142
01143 error = FT_Set_Char_Size( m_face, 0, ( long )( FTNORMFONT * 64 ), 96, 96 );
01144 wxASSERT_MSG( error == 0 , _( "a2dText problem setting character size" ) );
01145 if ( error )
01146 {
01147 m_face = NULL;
01148 return;
01149 }
01150
01151 const FT_Size_Metrics& size = m_face->size->metrics;
01152 m_height = ( size.ascender - size.descender ) / ( FTNORMFONT * 64.0 );
01153 m_desc = -size.descender / ( FTNORMFONT * 64.0 );
01154 m_lead = ( size.height - ( size.ascender - size.descender ) ) / ( FTNORMFONT * 64.0 );
01155
01156 m_fontinfo.SetName( wxString::FromAscii( m_face->family_name ) );
01157 m_fontinfo.SetStyle( wxString::FromAscii( m_face->style_name ) );
01158 m_fontinfo.SetExtra( GetFilename( true ) );
01159 #else //wxART2D_USE_FREETYPE
01160
01161 m_height = 1.6;
01162 m_desc = 0.3;
01163 m_lead = 0.0;
01164 #endif // wxART2D_USE_FREETYPE
01165 m_ok = true;
01166 }
01167
01168 const a2dGlyph* a2dFontFreetypeData::GetGlyph( wxChar cinput ) const
01169 {
01170 #if wxART2D_USE_FREETYPE
01171 if( cinput == m_lastChar )
01172 return m_a2dLastGlyph;
01173
01174 if ( !m_face )
01175 return NULL;
01176
01177
01178 if ( cinput >= CHAR_CACHE_START && cinput <= CHAR_CACHE_END )
01179 {
01180 a2dGlyph * a2dglyph = m_glyphcache + ( cinput - CHAR_CACHE_START );
01181 FT_Glyph glyph = a2dglyph->m_glyph;
01182 if ( !glyph )
01183 {
01184 wchar_t wc = ( wchar_t )cinput;
01185
01186 if( m_converter )
01187 {
01188 #if wxUSE_WCHAR_T
01189 wxChar cinputstr[2];
01190 wchar_t wcstr[2];
01191 cinputstr[0] = cinput;
01192 cinputstr[1] = 0;
01193 m_converter->Convert( cinputstr, wcstr );
01194 wc = wcstr[0];
01195 #else
01196 wc = m_converter->Convert( wxString( cinput ) ).Last();
01197 #endif
01198 }
01199
01200 FT_ULong c = ( FT_ULong ) wc;
01201
01202 FT_UInt index = FT_Get_Char_Index( m_face, ( FT_ULong ) c );
01203
01204 int error = FT_Load_Glyph( m_face, index, FT_LOAD_DEFAULT );
01205 wxASSERT_MSG( error == 0 , _( "Glyph could not be loaded" ) );
01206 if ( !error )
01207 {
01208 error = FT_Get_Glyph( m_face->glyph, &glyph );
01209 wxASSERT_MSG( error == 0 , _( "Glyph could not be get" ) );
01210 if ( error )
01211 glyph = NULL;
01212 }
01213 if ( glyph )
01214 glyph->advance = m_face->glyph->advance;
01215 if ( !glyph )
01216 {
01217 glyph = ( FT_Glyph ) - 1;
01218 if ( c != wxChar( '?' ) )
01219 {
01220 const a2dGlyph * glyphErr = GetGlyph( wxChar( '?' ) );
01221 if( glyphErr )
01222 {
01223 index = a2dglyph->m_index;
01224 glyph = glyphErr->m_glyph;
01225 }
01226 }
01227 }
01228 a2dglyph->m_index = index;
01229 a2dglyph->m_glyph = glyph;
01230 }
01231 if ( glyph == ( FT_Glyph ) - 1 )
01232 a2dglyph = NULL;
01233
01234 m_lastChar = cinput;
01235 m_a2dLastGlyph = a2dglyph;
01236
01237 return a2dglyph;
01238 }
01239 else
01240 {
01241 a2dGlyph* a2dglyph = &m_extglyphcache[cinput];
01242 FT_Glyph glyph = a2dglyph->m_glyph;
01243 if ( !glyph )
01244 {
01245 wchar_t wc = ( wchar_t )cinput;
01246
01247 if( m_converter )
01248 {
01249 #if wxUSE_WCHAR_T
01250 wxChar cinputstr[2];
01251 wchar_t wcstr[2];
01252 cinputstr[0] = cinput;
01253 cinputstr[1] = 0;
01254 m_converter->Convert( cinputstr, wcstr );
01255 wc = wcstr[0];
01256 #else
01257 wc = m_converter->Convert( wxString( cinput ) ).Last();
01258 #endif
01259 }
01260 FT_ULong c = ( FT_ULong ) wc;
01261
01262 FT_UInt index = FT_Get_Char_Index( m_face, ( FT_ULong ) c );
01263
01264 int error = FT_Load_Glyph( m_face, index, FT_LOAD_DEFAULT );
01265 wxASSERT_MSG( error == 0 , _( "Glyph could not be loaded" ) );
01266 if ( !error )
01267 {
01268 error = FT_Get_Glyph( m_face->glyph, &glyph );
01269 wxASSERT_MSG( error == 0 , _( "Glyph could not be get" ) );
01270 if ( error )
01271 glyph = NULL;
01272 }
01273 if ( glyph )
01274 glyph->advance = m_face->glyph->advance;
01275
01276 if ( !glyph )
01277 {
01278 glyph = ( FT_Glyph ) - 1;
01279 if ( c != wxChar( '?' ) )
01280 {
01281 const a2dGlyph * glyphErr = GetGlyph( wxChar( '?' ) );
01282 if( glyphErr )
01283 {
01284 index = glyphErr->m_index;
01285 glyph = glyphErr->m_glyph;
01286 }
01287 }
01288 }
01289 a2dglyph->m_index = index;
01290 a2dglyph->m_glyph = glyph;
01291 }
01292 if ( glyph == ( FT_Glyph ) - 1 )
01293 a2dglyph = NULL;
01294
01295 m_lastChar = cinput;
01296 m_a2dLastGlyph = a2dglyph;
01297
01298 return a2dglyph;
01299 }
01300 #else // wxART2D_USE_FREETYPE
01301 return NULL;
01302 #endif // wxART2D_USE_FREETYPE
01303 }
01304
01305 double a2dFontFreetypeData::GetWidth( wxChar c ) const
01306 {
01307 #if wxART2D_USE_FREETYPE
01308 if ( m_face )
01309 {
01310 const a2dGlyph * a2dglyph = GetGlyph( c );
01311 if( a2dglyph )
01312 {
01313 FT_Glyph glyphimage = a2dglyph->m_glyph;
01314 return glyphimage->advance.x * m_fontinfo.GetSize() / ( 64.0 * FTNORMFONT );
01315 }
01316 }
01317 return 0.0;
01318 #else //wxART2D_USE_FREETYPE
01319
01320 return m_fontinfo.GetSize() * 0.25;
01321 #endif //wxART2D_USE_FREETYPE
01322 }
01323
01324 double a2dFontFreetypeData::GetKerning( wxChar cinput1, wxChar cinput2 ) const
01325 {
01326 #if wxART2D_USE_FREETYPE
01327 FT_Vector kern;
01328 if ( !m_face )
01329 return 0.0;
01330
01331 const a2dGlyph *a2dglyph1 = GetGlyph( cinput1 );
01332 if( !a2dglyph1 )
01333 return 0.0;
01334 const a2dGlyph *a2dglyph2 = GetGlyph( cinput2 );
01335 if( !a2dglyph2 )
01336 return 0.0;
01337
01338 if ( FT_Get_Kerning( m_face, a2dglyph1->m_index, a2dglyph2->m_index, FT_KERNING_UNFITTED, &kern ) )
01339 return 0.0;
01340 else
01341 return kern.x * m_fontinfo.GetSize() / ( 64.0 * FTNORMFONT );
01342 #else //wxART2D_USE_FREETYPE
01343 return 0.0;
01344 #endif //wxART2D_USE_FREETYPE
01345 }
01346
01347 bool a2dFontFreetypeData::GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine )
01348 {
01349 #if wxART2D_USE_FREETYPE
01350 double x = affine.GetValue( 2, 0 );
01351 double y = affine.GetValue( 2, 1 );
01352 y += GetDescent();
01353
01354 double scale = GetSize() / ( 64 * FTNORMFONT );
01355
01356 const a2dGlyph* a2dglyph = GetGlyph( c );
01357 if( !a2dglyph )
01358 return false;
01359 FT_Glyph glyph = a2dglyph->m_glyph;
01360 if ( glyph->format != FT_GLYPH_FORMAT_OUTLINE )
01361 return false;
01362 FT_Outline& outline = ( ( FT_OutlineGlyph ) glyph )->outline;
01363
01364 FT_Vector v_last;
01365 FT_Vector v_control;
01366 FT_Vector v_start;
01367
01368 FT_Vector* point;
01369 FT_Vector* limit;
01370 char* tags;
01371
01372 int n;
01373 int first;
01374 char tag;
01375
01376 first = 0;
01377
01378 for( n = 0; n < outline.n_contours; n++ )
01379 {
01380 int last;
01381
01382 last = outline.contours[n];
01383 limit = outline.points + last;
01384
01385 v_start = outline.points[first];
01386 v_last = outline.points[last];
01387
01388 v_control = v_start;
01389
01390 point = outline.points + first;
01391 tags = outline.tags + first;
01392 tag = FT_CURVE_TAG( tags[0] );
01393
01394
01395 if( tag == FT_CURVE_TAG_CUBIC ) return false;
01396
01397
01398 if( tag == FT_CURVE_TAG_CONIC )
01399 {
01400
01401 if( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
01402 {
01403
01404 v_start = v_last;
01405 limit--;
01406 }
01407 else
01408 {
01409
01410
01411
01412 v_start.x = ( v_start.x + v_last.x ) / 2;
01413 v_start.y = ( v_start.y + v_last.y ) / 2;
01414
01415 v_last = v_start;
01416 }
01417 point--;
01418 tags--;
01419 }
01420
01421 vpath.Add( new a2dVpathSegment( x + scale * v_start.x, y + scale * v_start.y, a2dPATHSEG_MOVETO ) );
01422
01423 while( point < limit )
01424 {
01425 point++;
01426 tags++;
01427
01428 tag = FT_CURVE_TAG( tags[0] );
01429 switch( tag )
01430 {
01431 case FT_CURVE_TAG_ON:
01432 {
01433 vpath.Add( new a2dVpathSegment( x + scale * point->x, y + scale * point->y ) );
01434 continue;
01435 }
01436
01437 case FT_CURVE_TAG_CONIC:
01438 {
01439 v_control.x = point->x;
01440 v_control.y = point->y;
01441
01442 Do_Conic:
01443 if( point < limit )
01444 {
01445 FT_Vector vec;
01446 FT_Vector v_middle;
01447
01448 point++;
01449 tags++;
01450 tag = FT_CURVE_TAG( tags[0] );
01451
01452 vec.x = point->x;
01453 vec.y = point->y;
01454
01455 if( tag == FT_CURVE_TAG_ON )
01456 {
01457 vpath.Add( new a2dVpathQBCurveSegment( x + scale * v_control.x, y + scale * v_control.y,
01458 x + scale * vec.x, y + scale * vec.y ) );
01459 continue;
01460 }
01461
01462 if( tag != FT_CURVE_TAG_CONIC ) return false;
01463
01464 v_middle.x = ( v_control.x + vec.x ) / 2;
01465 v_middle.y = ( v_control.y + vec.y ) / 2;
01466
01467 vpath.Add( new a2dVpathQBCurveSegment( x + scale * v_control.x, y + scale * v_control.y,
01468 x + scale * v_middle.x, y + scale * v_middle.y ) );
01469
01470 v_control = vec;
01471 goto Do_Conic;
01472 }
01473 vpath.Add( new a2dVpathQBCurveSegment( x + scale * v_control.x, y + scale * v_control.y, x + scale * v_start.x, y + scale * v_start.y, a2dPATHSEG_QBCURVETO, a2dPATHSEG_END_CLOSED ) );
01474 goto Close;
01475 }
01476
01477 default:
01478 {
01479 FT_Vector vec1, vec2;
01480
01481 if( point + 1 > limit || FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
01482 {
01483 return false;
01484 }
01485
01486 vec1.x = point[0].x;
01487 vec1.y = point[0].y;
01488 vec2.x = point[1].x;
01489 vec2.y = point[1].y;
01490
01491 point += 2;
01492 tags += 2;
01493
01494 if( point <= limit )
01495 {
01496 FT_Vector vec;
01497
01498 vec.x = point->x;
01499 vec.y = point->y;
01500
01501 vpath.Add( new a2dVpathCBCurveSegment( x + scale * vec1.x, y + scale * vec1.y,
01502 x + scale * vec2.x, y + scale * vec2.y, x + scale * vec.x, y + scale * vec.y ) );
01503 continue;
01504 }
01505
01506 vpath.Add( new a2dVpathCBCurveSegment( x + scale * vec1.x, y + scale * vec1.y,
01507 x + scale * vec2.x, y + scale * vec2.y, x + scale * v_start.x, y + scale * v_start.y, a2dPATHSEG_CBCURVETO, a2dPATHSEG_END_CLOSED ) );
01508 goto Close;
01509 }
01510 }
01511 }
01512 Close:
01513 first = last + 1;
01514 }
01515 return true;
01516 #else //wxART2D_USE_FREETYPE
01517 return false;
01518 #endif //wxART2D_USE_FREETYPE
01519 }
01520
01521 void a2dFontFreetypeData::GetInfoList( a2dFontInfoList& list )
01522 {
01523 #if wxART2D_USE_FREETYPE
01524 wxPathList & pathlist = a2dGlobals->GetFontPathList();
01525 #if wxCHECK_VERSION(2,7,0)
01526 for ( wxPathList::iterator node = pathlist.begin(); node != pathlist.end(); node++ )
01527 #else
01528 for ( wxPathList::compatibility_iterator node = pathlist.GetFirst(); node; node = node->GetNext() )
01529 #endif
01530 {
01531 wxString path( node->GetData() );
01532 if ( !wxDir::Exists( path ) )
01533 continue;
01534 wxArrayString files;
01535 wxDir::GetAllFiles( path, &files, wxT( "*.ttf" ), wxDIR_FILES );
01536 for ( unsigned int i = 0; i < files.GetCount(); i++ )
01537 {
01538 FT_Error error;
01539 FT_Face face;
01540 error = FT_New_Face( g_freetypeLibrary, files.Item( i ).mb_str(), 0, &face );
01541 if ( error )
01542 continue;
01543 list.Append( new a2dFontInfo( wxT( "Freetype font" ),
01544 wxString::FromAscii( face->family_name ),
01545 wxString::FromAscii( face->style_name ),
01546 1.0, files.Item( i ) ) );
01547 FT_Done_Face( face );
01548 }
01549 }
01550 #else
01551 wxUnusedVar( list );
01552 #endif
01553 }
01554
01555 a2dFontFreetypeData* a2dFontFreetypeData::CreateFont( const a2dFontInfo& info, bool force )
01556 {
01557 #if wxART2D_USE_FREETYPE
01558 if ( force || info.GetType().Upper() == wxT( "FREETYPE FONT" ) )
01559 {
01560 a2dFontFreetypeData * font = NULL;
01561 if ( !force && !info.GetExtra().IsEmpty() )
01562 {
01563
01564 font = new a2dFontFreetypeData( info.GetExtra(), info.GetSize() );
01565 if ( font )
01566 {
01567 if ( font->Ok() )
01568 return font;
01569 else
01570 delete font;
01571 }
01572 }
01573 a2dFontInfoList list;
01574 list.DeleteContents( true );
01575 GetInfoList( list );
01576 unsigned int i;
01577
01578 for ( i = 0; i < list.GetCount(); i++ )
01579 {
01580 a2dFontInfo* fi = list.Item( i )->GetData();
01581 if ( fi->GetName() == info.GetName() && fi->GetStyle() == info.GetStyle() )
01582 {
01583 font = new a2dFontFreetypeData( fi->GetExtra(), info.GetSize() );
01584 if ( font )
01585 {
01586 if ( font->Ok() )
01587 return font;
01588 else
01589 delete font;
01590 }
01591 }
01592 }
01593
01594 int maxval = 0;
01595
01596 for ( i = 0; i < list.GetCount(); i++ )
01597 {
01598 a2dFontInfo* fi = list.Item( i )->GetData();
01599 int val = 0;
01600
01601 if ( fi->GetName() == info.GetName() )
01602 val = 4;
01603 else if ( fi->GetName().Upper() == info.GetName().Upper() )
01604 val = 3;
01605 else if ( ( fi->GetName().Upper().Find( info.GetName().Upper() ) != -1 )
01606 || ( info.GetName().Upper().Find( fi->GetName().Upper() ) != -1 ) )
01607 val = 1;
01608
01609 if ( val )
01610 {
01611 if ( ( info.GetStyle().Upper() == wxT( "BOLD" ) )
01612 || ( info.GetStyle().Upper().Find( wxT( "BOLD" ) ) != -1 ) )
01613 val++;
01614 if ( ( info.GetStyle().Upper() == wxT( "ITALIC" ) )
01615 || ( info.GetStyle().Upper().Find( wxT( "ITALIC" ) ) != -1 ) )
01616 val++;
01617 if ( ( info.GetStyle().Upper() == wxT( "REGULAR" ) )
01618 || ( info.GetStyle().Upper().Find( wxT( "REGULAR" ) ) != -1 ) )
01619 val++;
01620
01621 if ( val > maxval )
01622 {
01623 a2dFontFreetypeData * oldfont = font;
01624 font = new a2dFontFreetypeData( fi->GetExtra(), info.GetSize() );
01625 if ( font )
01626 {
01627 if ( font->Ok() )
01628 {
01629 maxval = val;
01630 delete oldfont;
01631 }
01632 else
01633 {
01634 delete font;
01635 font = oldfont;
01636 }
01637 }
01638 }
01639 }
01640 }
01641 if ( font )
01642 return font;
01643 }
01644 #endif
01645 return NULL;
01646 }
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662 class A2DARTBASEDLLEXP a2dFontStrokeData
01663 : public a2dFontRefData
01664 {
01665 friend class a2dFont;
01666 public:
01667
01668 virtual a2dFontType GetType( void ) const { return a2dFONT_STROKED; }
01669
01670
01671
01672
01673
01674
01675 a2dFontStrokeData( const wxString& filename = wxT( "" ), double size = 0.0, bool monoSpaced = false, double weight = 0.0 );
01676
01677
01678 a2dFontStrokeData( const a2dFontStrokeData& other );
01679
01680 virtual ~a2dFontStrokeData();
01681
01682
01683
01684
01685
01686
01687 void SetFilename( const wxString& filename );
01688
01689
01690
01691
01692 wxString GetFilename( bool filenameonly = false ) const;
01693
01694
01695
01696
01697
01698 inline double GetWeight() const { return m_weight; }
01699
01700
01701
01702
01703 void SetWeight( double weight );
01704
01705
01706
01707
01708 void SetWeight( const wxString& weight );
01709
01710
01711 double GetWidth( wxChar c ) const;
01712
01713
01714 double GetKerning( wxChar c1, wxChar c2 ) const;
01715
01716
01717
01718
01719
01720
01721 double GetStrokeWidth() const;
01722
01723
01724
01725
01726 a2dStrokeGlyph GetGlyph( wxChar c ) const;
01727
01728
01729 virtual bool GetVpath( wxChar c, a2dVpath& glyph, const a2dAffineMatrix& affine = a2dIDENTITY_MATRIX );
01730
01731
01732 static void GetInfoList( a2dFontInfoList& list );
01733
01734
01735 static a2dFontStrokeData* CreateFont( const a2dFontInfo& info, bool force = false );
01736
01737 protected:
01738
01739 wxString m_filename;
01740
01741
01742 wxUint16* m_width;
01743
01744 a2dStrokeGlyph* m_characters;
01745
01746
01747 wxUint16 m_beginchar;
01748
01749 wxUint16 m_count;
01750
01751 wxUint16 m_intsize;
01752
01753 double m_weight;
01754
01755 bool m_monoSpaced;
01756 };
01757
01758 #define BGI_FONT_MAGIC "PK\b\bBGI "
01759
01760 #pragma pack(1)
01761
01762
01763
01764 typedef struct
01765 {
01766 char magic[8];
01767 char descr[108];
01768 char stringend;
01769 unsigned short headersize;
01770 char fname[5];
01771 unsigned short datasize;
01772 unsigned char majorversion, minorversion;
01773 unsigned char minmajorversion, minminorversion;
01774 }
01775 BGI_FONT_HEADER;
01776
01777
01778 typedef struct
01779 {
01780 char signature;
01781 unsigned short nchar;
01782 char undefined;
01783 unsigned char firstchar;
01784 unsigned short stroke_offset;
01785 char scan_flag;
01786 signed char org_top;
01787 signed char org_base;
01788 signed char org_desc;
01789 char unused[5];
01790 }
01791 BGI_FONT_DATA;
01792 #pragma pack()
01793
01794
01795 a2dFontStrokeData::a2dFontStrokeData( const wxString& filename, double size, bool monoSpaced, double weight )
01796 : a2dFontRefData( size )
01797 {
01798 m_monoSpaced = monoSpaced;
01799 m_fontinfo.SetType( wxT( "Stroke font" ) );
01800 m_width = NULL;
01801 m_characters = NULL;
01802 SetWeight( weight );
01803 SetFilename( filename );
01804 }
01805
01806 a2dFontStrokeData::a2dFontStrokeData( const a2dFontStrokeData& other )
01807 : a2dFontRefData( other )
01808 {
01809 m_fontinfo.SetType( wxT( "Stroke font" ) );
01810 m_width = NULL;
01811 m_weight = other.m_weight;
01812 m_characters = NULL;
01813 m_monoSpaced = other.m_monoSpaced;
01814 SetFilename( other.m_filename );
01815 }
01816
01817 a2dFontStrokeData::~a2dFontStrokeData()
01818 {
01819 if ( m_width )
01820 delete[] m_width;
01821 if ( m_characters )
01822 {
01823 for ( unsigned char i = 0; i < m_count; i++ )
01824 {
01825 a2dStrokeGlyph glyph = m_characters[i];
01826 while ( *glyph )
01827 {
01828 delete * glyph;
01829 glyph++;
01830 }
01831 free( m_characters[i] );
01832 }
01833 free( m_characters );
01834 }
01835 }
01836
01837 wxString a2dFontStrokeData::GetFilename( bool filenameonly ) const
01838 {
01839 if ( filenameonly )
01840 {
01841 wxFileName filename( m_filename );
01842 return filename.GetFullName();
01843 }
01844 else
01845 return m_filename;
01846 }
01847
01848 void a2dFontStrokeData::SetFilename( const wxString& filename )
01849 {
01850 m_ok = false;
01851
01852
01853 if ( m_width )
01854 {
01855 delete[] m_width;
01856 m_width = NULL;
01857 }
01858 if ( m_characters )
01859 {
01860 for ( unsigned char i = 0; i < m_count; i++ )
01861 {
01862 a2dStrokeGlyph glyph = m_characters[i];
01863 while ( *glyph )
01864 {
01865 delete * glyph;
01866 glyph++;
01867 }
01868 free( m_characters[i] );
01869 }
01870 free( m_characters );
01871 m_characters = NULL;
01872 }
01873
01874 m_filename = filename;
01875 if ( m_filename.IsEmpty() )
01876 return;
01877
01878 wxString fname = a2dGlobals->GetFontPathList().FindValidPath( m_filename );
01879
01880 if ( fname.IsEmpty() )
01881 fname = m_filename;
01882
01883 wxFile file( fname );
01884 if ( !file.IsOpened() )
01885 return;
01886
01887 BGI_FONT_HEADER bgifontheader;
01888 file.Read( &bgifontheader.magic, sizeof( bgifontheader.magic ) );
01889 size_t idx = 0;
01890 char c;
01891 file.Read( &c, 1 );
01892 while( !file.Eof() && idx < sizeof( bgifontheader.descr ) - 1 && c != 0x1a )
01893 {
01894 bgifontheader.descr[idx++] = c;
01895 file.Read( &c, 1 );
01896 }
01897 while( !file.Eof() && c != 0x1a )
01898 file.Read( &c, 1 );
01899 bgifontheader.descr[idx] = '\0';
01900 file.Read( &bgifontheader.headersize, sizeof( bgifontheader.headersize ) );
01901
01902 bgifontheader.headersize = wxINT16_SWAP_ON_BE( bgifontheader.headersize );
01903 file.Read( &bgifontheader.fname, 4 );
01904 bgifontheader.fname[4] = '\0';
01905 file.Read( &bgifontheader.datasize, sizeof( bgifontheader.datasize ) );
01906
01907 bgifontheader.datasize = wxINT16_SWAP_ON_BE( bgifontheader.datasize );
01908 file.Read( &bgifontheader.majorversion, 4 * sizeof( bgifontheader.majorversion ) );
01909
01910 if ( memcmp( bgifontheader.magic, BGI_FONT_MAGIC, sizeof( bgifontheader.magic ) ) )
01911 {
01912 file.Close();
01913 return;
01914 }
01915 file.Seek( bgifontheader.headersize, wxFromStart );
01916
01917 BGI_FONT_DATA bgifontdata;
01918 file.Read( &bgifontdata, sizeof( BGI_FONT_DATA ) );
01919
01920 bgifontdata.nchar = wxUINT16_SWAP_ON_BE( bgifontdata.nchar );
01921 bgifontdata.stroke_offset = wxUINT16_SWAP_ON_BE( bgifontdata.stroke_offset );
01922
01923 if ( bgifontdata.signature != '+' )
01924 {
01925 file.Close();
01926 return;
01927 }
01928
01929 m_count = bgifontdata.nchar;
01930 m_beginchar = bgifontdata.firstchar;
01931
01932 m_intsize = bgifontdata.org_top - bgifontdata.org_base;
01933 double size = m_intsize;
01934 m_height = ( m_intsize - 2 * ( bgifontdata.org_desc - bgifontdata.org_base ) + 3 ) / size;
01935 m_desc = ( bgifontdata.org_base - bgifontdata.org_desc + 1.5 ) / size;
01936 m_lead = 0.0;
01937
01938
01939
01940 m_width = new wxUint16[m_count];
01941 file.Seek( bgifontheader.headersize + sizeof( BGI_FONT_DATA ) + sizeof( unsigned short ) * ( bgifontdata.nchar ), wxFromStart );
01942 unsigned int i;
01943 unsigned char w;
01944 for ( i = 0; i < m_count; i++ )
01945 {
01946 file.Read( &w, sizeof( unsigned char ) );
01947 m_width[i] = w;
01948 }
01949
01950
01951 m_characters = ( a2dStrokeGlyph* ) malloc( sizeof( a2dStrokeGlyph ) * m_count );
01952 for ( i = 0; i < m_count; i++ )
01953 {
01954
01955 file.Seek( bgifontheader.headersize + sizeof( BGI_FONT_DATA ) + sizeof( unsigned short ) * i, wxFromStart );
01956 unsigned short char_offset;
01957 file.Read( &char_offset, sizeof( char_offset ) );
01958
01959 char_offset = wxUINT16_SWAP_ON_BE( char_offset );
01960
01961 file.Seek( bgifontheader.headersize + bgifontdata.stroke_offset + char_offset, wxFromStart );
01962
01963 bool penup = true;
01964 unsigned char opcode = 1;
01965 a2dVertexList *list = new a2dVertexList;
01966 int nlists = 0;
01967 m_characters[i] = ( a2dStrokeGlyph ) malloc( sizeof( a2dVertexList* ) );
01968 m_characters[i][0] = NULL;
01969 signed char penupx = 0;
01970 signed char penupy = 0;
01971 while ( opcode != 0 )
01972 {
01973 signed char x, y;
01974 file.Read( &x, sizeof( x ) );
01975 file.Read( &y, sizeof( y ) );
01976 if ( x & 0x80 ) opcode |= 0x2; else opcode &= ~0x2;
01977 if ( y & 0x80 ) opcode |= 0x1; else opcode &= ~0x1;
01978 if ( x & 0x40 ) x |= 0x80; else x &= ~0x80;
01979 if ( y & 0x40 ) y |= 0x80; else y &= ~0x80;
01980
01981 switch( opcode )
01982 {
01983 case 3:
01984 if ( penup )
01985 list->push_back( new a2dLineSegment( penupx / size, ( penupy - bgifontdata.org_base ) / size + m_desc ) );
01986
01987 penup = false;
01988 list->push_back( new a2dLineSegment( x / size, ( y - bgifontdata.org_base ) / size + m_desc ) );
01989 break;
01990 case 2:
01991 if ( !penup )
01992 {
01993 m_characters[i] = ( a2dStrokeGlyph ) realloc( m_characters[i], sizeof( a2dVertexList* ) * ( nlists + 2 ) );
01994 m_characters[i][nlists + 1] = NULL;
01995 m_characters[i][nlists] = list;
01996 nlists++;
01997 list = new a2dVertexList;
01998 }
01999 penup = true; penupx = x; penupy = y;
02000 break;
02001 case 1:
02002 break;
02003 default:
02004 m_characters[i] = ( a2dStrokeGlyph ) realloc( m_characters[i], sizeof( a2dVertexList* ) * ( nlists + 2 ) );
02005 m_characters[i][nlists + 1] = NULL;
02006 m_characters[i][nlists] = list;
02007 nlists++;
02008 }
02009 }
02010 }
02011 file.Close();
02012 m_ok = true;
02013
02014
02015 wxString fontname = wxString::FromAscii( bgifontheader.fname );
02016 if ( fontname == wxT( "EURO" ) )
02017 fontname = wxT( "EuroStyle" );
02018 else if ( fontname == wxT( "GOTH" ) )
02019 fontname = wxT( "Gothic" );
02020 else if ( fontname == wxT( "LCOM" ) )
02021 fontname = wxT( "Complex" );
02022 else if ( fontname == wxT( "LITT" ) )
02023 fontname = wxT( "Small" );
02024 else if ( fontname == wxT( "SANS" ) )
02025 fontname = wxT( "Sans serif" );
02026 else if ( fontname == wxT( "SCRI" ) )
02027 fontname = wxT( "Script" );
02028 else if ( fontname == wxT( "SIMP" ) )
02029 fontname = wxT( "Simple" );
02030 else if ( fontname == wxT( "TRIP" ) )
02031 fontname = wxT( "Triplex" );
02032 else if ( fontname == wxT( "TSCR" ) )
02033 fontname = wxT( "Triplex Script" );
02034 else if ( fontname == wxT( "NEN " ) )
02035 fontname = wxT( "NEN 3094" );
02036 m_fontinfo.SetName( fontname );
02037
02038 m_fontinfo.SetExtra( GetFilename( true ) );
02039 }
02040
02041 void a2dFontStrokeData::SetWeight( double weight )
02042 {
02043 m_weight = weight;
02044
02045 if ( m_weight == 0.0 )
02046 m_fontinfo.SetStyle( wxT( "Pixel Pen" ) );
02047 if ( m_weight == -1.0 )
02048 m_fontinfo.SetStyle( wxT( "Normalized Pen" ) );
02049 else
02050 {
02051 wxString style;
02052 style.Printf( wxT( "%.1f\x25 of height" ), m_weight );
02053 m_fontinfo.SetStyle( style );
02054 }
02055 }
02056
02057 void a2dFontStrokeData::SetWeight( const wxString& weight )
02058 {
02059 m_fontinfo.SetStyle( weight );
02060 if ( weight.Upper() == wxT( "PIXEL PEN" ) )
02061 {
02062 m_weight = 0.0;
02063 }
02064 else if ( weight.Upper() == wxT( "NORMALIZED PEN" ) )
02065 {
02066 m_weight = -1.0;
02067 }
02068 else
02069 {
02070 int idxend = weight.Find( wxChar( '%' ) );
02071 if ( idxend <= 0 )
02072 m_weight = -1;
02073 else
02074 {
02075 size_t idxstart = idxend;
02076 while ( idxstart > 0 && weight[idxstart - 1] == wxChar( ' ' ) )
02077 idxstart--;
02078 while ( idxstart > 0 && weight[idxstart - 1] != wxChar( ' ' ) )
02079 idxstart--;
02080 weight.Mid( idxstart, idxend - idxstart ).ToDouble( &m_weight );
02081 }
02082 }
02083 }
02084
02085 double a2dFontStrokeData::GetWidth( wxChar c ) const
02086 {
02087 if ( !m_ok || !m_width )
02088 return 0.0;
02089
02090 unsigned char c2 = c;
02091 if ( m_monoSpaced )
02092 c2 = 'm';
02093
02094 if ( c2 < m_beginchar && c2 >= m_beginchar + m_count )
02095 c2 = '?';
02096
02097 if ( c2 >= m_beginchar && c2 < m_beginchar + m_count )
02098 { double width = m_fontinfo.GetSize() * m_width[c2 - m_beginchar] / m_intsize;
02099 if ( m_monoSpaced )
02100 return width * 0.83;
02101 }
02102 return 0.0;
02103 }
02104
02105 double a2dFontStrokeData::GetStrokeWidth() const
02106 {
02107 if ( !m_ok )
02108 return 0.0;
02109
02110 if ( m_weight == -1.0 )
02111 return m_fontinfo.GetSize() * 1.25 / m_intsize;
02112 else if ( m_weight == 0.0 )
02113 return 0.0;
02114 else
02115 return m_fontinfo.GetSize() * m_weight * 0.01;
02116 }
02117
02118 double a2dFontStrokeData::GetKerning( wxChar WXUNUSED( c1 ), wxChar WXUNUSED( c2 ) ) const
02119 {
02120
02121 return 0.0;
02122 }
02123
02124 a2dStrokeGlyph a2dFontStrokeData::GetGlyph( wxChar c ) const
02125 {
02126 if ( !m_ok || !m_characters )
02127 return NULL;
02128
02129 unsigned char c2 = c;
02130
02131 if ( c2 >= m_beginchar && c2 < m_beginchar + m_count )
02132 return m_characters[c2 - m_beginchar];
02133 else
02134 {
02135 c2 = '?';
02136 if ( c2 >= m_beginchar && c2 < m_beginchar + m_count )
02137 return m_characters[c2 - m_beginchar];
02138 else
02139 return NULL;
02140 }
02141 }
02142
02143
02144 bool a2dFontStrokeData::GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine )
02145 {
02146 a2dVertexList** ptr = GetGlyph( c );
02147
02148
02149 a2dAffineMatrix affine2;
02150
02151 affine2.Scale( GetSize() );
02152
02153 a2dAffineMatrix affine3 = affine;
02154 affine3 *= affine2;
02155
02156 if ( ptr )
02157 {
02158 while ( *ptr )
02159 {
02160 a2dVertexList trans = a2dVertexList( **ptr );
02161 trans.Transform( affine3 );
02162 vpath.Add( trans, true, false );
02163 ptr++;
02164 }
02165 }
02166 return true;
02167 }
02168
02169 void a2dFontStrokeData::GetInfoList( a2dFontInfoList& list )
02170 {
02171 wxPathList & pathlist = a2dGlobals->GetFontPathList();
02172 #if wxCHECK_VERSION(2,7,0)
02173 for ( wxPathList::iterator node = pathlist.begin(); node != pathlist.end(); node++ )
02174 #else
02175 for ( wxPathList::compatibility_iterator node = pathlist.GetFirst(); node; node = node->GetNext() )
02176 #endif
02177 {
02178 wxString path( node->GetData() );
02179 if ( !wxDir::Exists( path ) )
02180 continue;
02181
02182 wxArrayString files;
02183 wxDir::GetAllFiles( path, &files, wxT( "*.chr" ), wxDIR_FILES );
02184 for ( unsigned int i = 0; i < files.GetCount(); i++ )
02185 {
02186
02187 wxFile file( files.Item( i ) );
02188 if ( !file.IsOpened() )
02189 continue;
02190
02191 BGI_FONT_HEADER bgifontheader;
02192 file.Read( &bgifontheader.magic, sizeof( bgifontheader.magic ) );
02193 size_t idx = 0;
02194 char c;
02195 file.Read( &c, 1 );
02196 while( !file.Eof() && idx < sizeof( bgifontheader.descr ) - 1 && c != 0x1a )
02197 {
02198 bgifontheader.descr[idx++] = c;
02199 file.Read( &c, 1 );
02200 }
02201 while( !file.Eof() && c != 0x1a )
02202 file.Read( &c, 1 );
02203 bgifontheader.descr[idx] = '\0';
02204 file.Read( &bgifontheader.headersize, sizeof( bgifontheader.headersize ) );
02205
02206 bgifontheader.headersize = wxINT16_SWAP_ON_BE( bgifontheader.headersize );
02207 file.Read( &bgifontheader.fname, 4 );
02208 bgifontheader.fname[4] = '\0';
02209 file.Read( &bgifontheader.datasize, sizeof( bgifontheader.datasize ) );
02210
02211 bgifontheader.datasize = wxINT16_SWAP_ON_BE( bgifontheader.datasize );
02212 file.Read( &bgifontheader.majorversion, 4 * sizeof( bgifontheader.majorversion ) );
02213
02214 if ( memcmp( bgifontheader.magic, BGI_FONT_MAGIC, sizeof( bgifontheader.magic ) ) )
02215 {
02216 file.Close();
02217 continue;
02218 }
02219 file.Seek( bgifontheader.headersize, wxFromStart );
02220
02221 BGI_FONT_DATA bgifontdata;
02222 file.Read( &bgifontdata, sizeof( BGI_FONT_DATA ) );
02223
02224 bgifontdata.nchar = wxUINT16_SWAP_ON_BE( bgifontdata.nchar );
02225 bgifontdata.stroke_offset = wxUINT16_SWAP_ON_BE( bgifontdata.stroke_offset );
02226
02227 if ( bgifontdata.signature != '+' )
02228 {
02229 file.Close();
02230 continue;
02231 }
02232
02233
02234 wxString fontname = wxString::FromAscii( bgifontheader.fname );
02235 if ( fontname == wxT( "EURO" ) )
02236 fontname = wxT( "EuroStyle" );
02237 else if ( fontname == wxT( "GOTH" ) )
02238 fontname = wxT( "Gothic" );
02239 else if ( fontname == wxT( "LCOM" ) )
02240 fontname = wxT( "Complex" );
02241 else if ( fontname == wxT( "LITT" ) )
02242 fontname = wxT( "Small" );
02243 else if ( fontname == wxT( "SANS" ) )
02244 fontname = wxT( "Sans serif" );
02245 else if ( fontname == wxT( "SCRI" ) )
02246 fontname = wxT( "Script" );
02247 else if ( fontname == wxT( "SIMP" ) )
02248 fontname = wxT( "Simple" );
02249 else if ( fontname == wxT( "TRIP" ) )
02250 fontname = wxT( "Triplex" );
02251 else if ( fontname == wxT( "TSCR" ) )
02252 fontname = wxT( "Triplex Script" );
02253 else if ( fontname == wxT( "NEN " ) )
02254 fontname = wxT( "NEN 3094" );
02255
02256 wxFileName filename( files.Item( i ) );
02257 wxString weightstring;
02258 list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "Pixel Pen" ), 1.0, filename.GetFullName() ) );
02259 list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "Normalized Pen" ), 1.0, filename.GetFullName() ) );
02260 list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( " 2% of height" ), 1.0, filename.GetFullName() ) );
02261 list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( " 5% of height" ), 1.0, filename.GetFullName() ) );
02262 list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( " 7% of height" ), 1.0, filename.GetFullName() ) );
02263 list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "10% of height" ), 1.0, filename.GetFullName() ) );
02264 list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "15% of height" ), 1.0, filename.GetFullName() ) );
02265 list.Append( new a2dFontInfo( wxT( "Stroke font" ), fontname, wxT( "20% of height" ), 1.0, filename.GetFullName() ) );
02266 }
02267 }
02268 }
02269
02270 a2dFontStrokeData* a2dFontStrokeData::CreateFont( const a2dFontInfo& info, bool force )
02271 {
02272 if ( force || info.GetType().Upper() == wxT( "STROKE FONT" ) )
02273 {
02274 a2dFontStrokeData * font = NULL;
02275 if ( !force && !info.GetExtra().IsEmpty() )
02276 {
02277
02278 font = new a2dFontStrokeData( info.GetExtra(), info.GetSize() );
02279 if ( font )
02280 {
02281 font->SetWeight( info.GetStyle() );
02282 if ( font->Ok() )
02283 return font;
02284 else
02285 delete font;
02286 }
02287 }
02288 a2dFontInfoList list;
02289 list.DeleteContents( true );
02290 GetInfoList( list );
02291 unsigned int i;
02292
02293 for ( i = 0; i < list.GetCount(); i++ )
02294 {
02295 a2dFontInfo* fi = list.Item( i )->GetData();
02296
02297 if ( fi->GetName() == info.GetName() )
02298 {
02299 font = new a2dFontStrokeData( fi->GetExtra(), info.GetSize() );
02300 if ( font )
02301 {
02302 font->SetWeight( info.GetStyle() );
02303 if ( font->Ok() )
02304 return font;
02305 else
02306 delete font;
02307 }
02308 }
02309 }
02310
02311 for ( i = 0; i < list.GetCount(); i++ )
02312 {
02313 a2dFontInfo* fi = list.Item( i )->GetData();
02314
02315 if ( ( fi->GetName().Upper().Find( info.GetName().Upper() ) != -1 )
02316 || ( info.GetName().Upper().Find( fi->GetName().Upper() ) != -1 ) )
02317 {
02318 font = new a2dFontStrokeData( fi->GetExtra(), info.GetSize() );
02319 if ( font )
02320 {
02321 font->SetWeight( info.GetStyle() );
02322 if ( font->Ok() )
02323 return font;
02324 else
02325 delete font;
02326 }
02327 }
02328 }
02329 }
02330 return NULL;
02331 }
02332
02333
02334
02335
02336
02337 map< wxString, a2dFont > a2dFont::ms_fontCache;
02338
02339 IMPLEMENT_ABSTRACT_CLASS( a2dFont, wxObject )
02340
02341 a2dFont::a2dFont()
02342 {
02343 }
02344
02345 a2dFont::a2dFont( const a2dFont& other )
02346 :wxObject( other )
02347 {
02348 }
02349
02350 wxString a2dFont::CreateString( const wxString& filename, double size, wxFontEncoding encoding, int weight )
02351 {
02352 wxString typestr = wxT( "Freetype font" );
02353 wxString sizestr;
02354 sizestr.Printf( wxT( "%f" ), size );
02355 wxString weightstr;
02356 weightstr.Printf( wxT( "%d" ), weight );
02357 wxString description = typestr + wxT( "-" ) + filename + wxT( "-" ) + weightstr
02358 + wxT( "-" ) + sizestr;
02359 return description;
02360 }
02361
02362 wxString a2dFont::CreateString( const wxString& filename, double size, bool monoSpaced, double weight )
02363 {
02364 wxString typestr = wxT( "Stroke font" );
02365 wxString weightstr;
02366
02367 if ( weight == 0.0 )
02368 weightstr = wxT( "Pixel Pen" );
02369 if ( weight == -1.0 )
02370 weightstr = wxT( "Normalized Pen" );
02371 else
02372 weightstr.Printf( wxT( "%.1f\x25 of height" ), weight );
02373
02374 wxString monostr;
02375 if ( monoSpaced ) monostr = wxT( "monoSpaced" );
02376 wxString sizestr;
02377 sizestr.Printf( wxT( "%f" ), size );
02378 wxString description = typestr + wxT( "-" ) + filename + wxT( "-" ) + weightstr
02379 + wxT( "-" ) + sizestr + wxT( "-" ) + monostr ;
02380 return description;
02381 }
02382
02383 wxString a2dFont::CreateString( a2dFontType type, const wxFont& font, double size, wxFontEncoding encoding )
02384 {
02385 wxString name = font.GetFaceName();
02386 wxString style = wxEmptyString;
02387
02388 wxString typestr;
02389 switch ( type )
02390 {
02391 case a2dFONT_WXDC:
02392 typestr = wxT( "Device font" );
02393 break;
02394 case a2dFONT_FREETYPE:
02395 typestr = wxT( "Freetype font" );
02396 break;
02397 default:
02398 wxFAIL_MSG( _( "wrong font to set a wxFont to" ) );
02399 break;
02400 }
02401
02402 switch ( font.GetWeight() )
02403 {
02404 case wxNORMAL:
02405 if ( font.GetStyle() == wxNORMAL )
02406 style = wxT( "Regular" );
02407 break;
02408 case wxBOLD:
02409 style = wxT( "Bold " );
02410 break;
02411 case wxLIGHT:
02412 style = wxT( "Light " );
02413 break;
02414 }
02415 switch ( font.GetStyle() )
02416 {
02417 case wxNORMAL:
02418 break;
02419 case wxITALIC:
02420 case wxSLANT:
02421 style += wxT( "Italic" );
02422 break;
02423 }
02424 style.Trim();
02425
02426 wxString sizestr;
02427 sizestr.Printf( wxT( "%f" ), size );
02428 wxString description = typestr + wxT( "-" ) + name + wxT( "-" ) + style.Trim()
02429 + wxT( "-" ) + sizestr;
02430
02431 return description;
02432 }
02433
02434 a2dFont::a2dFont( const wxFont& font, double size, a2dFontType type, wxFontEncoding encoding )
02435 {
02436 wxString fontstr = CreateString( type, font, size, encoding );
02437 if ( ms_fontCache.find( fontstr ) == ms_fontCache.end())
02438 {
02439 switch ( type )
02440 {
02441 case a2dFONT_WXDC:
02442 m_refData = new a2dFontDcData( font, size );
02443 break;
02444 case a2dFONT_FREETYPE:
02445 #if defined(__USE_WINAPI__)
02446 m_refData = new a2dFontFreetypeData( font, size, encoding );
02447 #else
02448 wxFAIL_MSG( _( "freetype based on wxFont not enabled" ) );
02449 #endif // defined( __USE_WINAPI__ )
02450 break;
02451 default:
02452 wxFAIL_MSG( _( "wrong font to set a wxFont to" ) );
02453 break;
02454 }
02455 ms_fontCache[fontstr] = *this;
02456 }
02457 else
02458
02459 Ref( ms_fontCache[fontstr] );
02460 }
02461
02462 a2dFont::a2dFont( double size, int family, int style, int weight,
02463 const bool underline, const wxString& faceName,
02464 wxFontEncoding encoding )
02465 {
02466 wxString fontstr = CreateString( a2dFONT_WXDC, wxFont( 1, family, style, weight, underline, faceName, encoding ), size, encoding );
02467 if ( ms_fontCache.find( fontstr ) == ms_fontCache.end())
02468 {
02469 m_refData = new a2dFontDcData( size, family, style, weight, underline, faceName, encoding );
02470 ms_fontCache[fontstr] = *this;
02471 }
02472 else
02473
02474 Ref( ms_fontCache[fontstr] );
02475 }
02476
02477
02478 a2dFont::a2dFont( const wxString& filename, double size, wxFontEncoding encoding, int weight )
02479 {
02480 m_refData = new a2dFontFreetypeData( filename, size, encoding, weight );
02481 }
02482
02483 a2dFont::a2dFont( const wxString& filename, double size, bool monoSpaced, double weight )
02484 {
02485 wxString fontstr = CreateString( filename, size, monoSpaced, weight );
02486 if ( ms_fontCache.find( fontstr ) == ms_fontCache.end())
02487 {
02488 m_refData = new a2dFontStrokeData( filename, size, monoSpaced, weight );
02489 ms_fontCache[fontstr] = *this;
02490 }
02491 else
02492 {
02493 a2dFont cached = ms_fontCache[fontstr];
02494
02495 Ref( cached );
02496 }
02497 }
02498
02499 a2dFont::~a2dFont()
02500 {
02501 }
02502
02503 wxString a2dFont::CreateString()
02504 {
02505 if ( m_refData )
02506 return ((a2dFontRefData*)GetRefData())->m_fontinfo.CreateString();
02507 return wxEmptyString;
02508 }
02509
02510 bool a2dFont::Ok() const
02511 {
02512 if ( m_refData )
02513 return ((a2dFontRefData*)GetRefData())->Ok();
02514 return false;
02515 }
02516
02517 const a2dFontInfo& a2dFont::GetFontInfo() const
02518 {
02519 if ( m_refData )
02520 return ((a2dFontRefData*)GetRefData())->m_fontinfo;
02521 static a2dFontInfo dummy = a2dFontInfo();
02522 return dummy;
02523 }
02524
02525 void a2dFont::SetSize( double size )
02526 {
02527 AllocExclusive();
02528
02529 if ( m_refData )
02530 ((a2dFontRefData*)GetRefData())->SetSize( size );
02531 }
02532
02533 double a2dFont::GetSize() const
02534 {
02535 if ( m_refData )
02536 return ((a2dFontRefData*)GetRefData())->GetSize();
02537 return 0.0;
02538 }
02539
02540 double a2dFont::GetKerning( wxChar c1, wxChar c2 ) const
02541 {
02542 if ( m_refData )
02543 return ((a2dFontRefData*)GetRefData())->GetKerning( c1, c2 );
02544 return 0.0;
02545 }
02546
02547 double a2dFont::GetStrokeWidth() const
02548 {
02549 switch ( GetType() )
02550 {
02551 case a2dFONT_STROKED:
02552 return ((const a2dFontStrokeData*)m_refData)->GetStrokeWidth();
02553 default:
02554 return 0.0;
02555 break;
02556 }
02557 return 0.0;
02558 }
02559
02560 a2dStrokeGlyph a2dFont::GetGlyphStroke( wxChar c ) const
02561 {
02562 switch ( GetType() )
02563 {
02564 case a2dFONT_STROKED:
02565 return ((a2dFontStrokeData*)GetRefData())->GetGlyph( c );
02566 default:
02567 wxFAIL_MSG( _( "need stroked font a2dFontStrokeData" ) );
02568 break;
02569 }
02570 return NULL;
02571 }
02572
02573 const a2dGlyph* a2dFont::GetGlyphFreetype( wxChar c ) const
02574 {
02575 switch ( GetType() )
02576 {
02577 case a2dFONT_FREETYPE:
02578 return ((a2dFontFreetypeData*)GetRefData())->GetGlyph( c );
02579 default:
02580 wxFAIL_MSG( _( "need stroked font a2dFontFreetypeData" ) );
02581 break;
02582 }
02583 return NULL;
02584 }
02585
02586 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
02587 a2dFont a2dFont::GetFreetypeFont()
02588 {
02589 switch ( GetType() )
02590 {
02591 case a2dFONT_WXDC:
02592 return ((a2dFontDcData*)GetRefData())->GetFreetypeFont();
02593 break;
02594 default:
02595 wxFAIL_MSG( _( "need wxDc font a2dFontDcData" ) );
02596 break;
02597 }
02598 return *a2dNullFONT;
02599 }
02600 #endif
02601
02602 wxFont& a2dFont::GetFont( void )
02603 {
02604 switch ( GetType() )
02605 {
02606 case a2dFONT_WXDC:
02607
02608 return ((a2dFontDcData*)GetRefData())->m_font;
02609 default:
02610 wxFAIL_MSG( _( "need wxDc font a2dFontDcData" ) );
02611 break;
02612 }
02613 return wxNullFont;
02614 }
02615
02616 a2dBoundingBox a2dFont::GetTextExtent( const wxString& string,
02617 int yaxisdirection, int alignment, double* w, double* h,
02618 double* descent, double* externalLeading ) const
02619 {
02620 double gte_x, gte_y, gte_w, gte_h, gte_desc, gte_lead;
02621 GetTextExtent( string, gte_w, gte_h, gte_desc, gte_lead );
02622
02623
02624 if ( alignment & wxBBOX )
02625 {
02626
02627 gte_y = -gte_h / 2.0;
02628 if ( alignment & wxMINY )
02629 gte_y += gte_h / 2.0;
02630 if ( alignment & wxMAXY )
02631 gte_y -= gte_h / 2.0;
02632 }
02633 else
02634 {
02635 double fontsize = GetSize();
02636 gte_y = -fontsize / 2.0;
02637 if ( yaxisdirection == 1 )
02638 gte_y -= gte_desc;
02639 else if ( yaxisdirection == 0 )
02640 gte_y += ( fontsize - gte_h ) + gte_desc;
02641 else
02642 {
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662 double above = gte_h - fontsize - gte_desc;
02663 if ( above < gte_desc )
02664 above = gte_desc;
02665 double lh = fontsize + 2.0 * above;
02666 gte_y += fontsize + above - lh;
02667 }
02668
02669 if ( alignment & wxMINY )
02670 gte_y += fontsize / 2.0;
02671 if ( alignment & wxMAXY )
02672 gte_y -= fontsize / 2.0;
02673 }
02674
02675
02676 gte_x = -gte_w / 2.0;
02677 if ( alignment & wxLEFT )
02678 gte_x += gte_w / 2.0;
02679 if ( alignment & wxRIGHT )
02680 gte_x -= gte_w / 2.0;
02681
02682
02683 if ( w ) * w = gte_w;
02684 if ( h ) * h = gte_h;
02685 if ( descent ) * descent = gte_desc;
02686 if ( externalLeading ) * externalLeading = gte_lead;
02687
02688 return a2dBoundingBox( gte_x, gte_y, gte_x + gte_w, gte_y + gte_h );
02689 }
02690
02691 void a2dFont::GetTextExtent( const wxString& string, double& w,
02692 double& h, double& descent, double& externalLeading ) const
02693 {
02694 return ((a2dFontRefData*)GetRefData())->GetTextExtent( string, w, h, descent, externalLeading );
02695 }
02696
02697 void a2dFont::GetTextExtentWH( const wxString& string, double& w, double& h ) const
02698 {
02699 double descent, externalLeading;
02700 return ((a2dFontRefData*)GetRefData())->GetTextExtent( string, w, h, descent, externalLeading );
02701 }
02702
02703 bool a2dFont::GetPartialTextExtents ( const wxString & text, wxArrayInt & widths ) const
02704 {
02705 return true;
02706 }
02707
02708 double a2dFont::GetLineHeight() const
02709 {
02710 return ((a2dFontRefData*)GetRefData())->GetLineHeight();
02711 }
02712
02713 double a2dFont::GetDescent() const
02714 {
02715 return ((a2dFontRefData*)GetRefData())->GetDescent();
02716 }
02717
02718 double a2dFont::GetWidth( wxChar c )
02719 {
02720 return ((a2dFontRefData*)GetRefData())->GetWidth(c);
02721 }
02722
02723 bool a2dFont::GetVpath( wxChar c, a2dVpath& vpath, const a2dAffineMatrix& affine )
02724 {
02725 return ((a2dFontRefData*)GetRefData())->GetVpath( c, vpath, affine );
02726 }
02727
02728 void a2dFont::GetVpath( const wxString& text, a2dVpath& vpath, double x, double y, int alignment, bool yaxis, const a2dAffineMatrix& affine )
02729 {
02730
02731 a2dBoundingBox bbox = GetTextExtent( text, yaxis, alignment );
02732 bbox.Translate( x, y );
02733
02734
02735
02736 x = bbox.GetMinX();
02737 y = bbox.GetMinY();
02738
02739
02740 const double h = GetLineHeight();
02741 a2dAffineMatrix affine2;
02742 if ( !yaxis )
02743 {
02744 affine2.Translate( 0.0, -h );
02745 affine2.Mirror( true, false );
02746 }
02747
02748 affine2.Translate( x, y );
02749
02750 a2dAffineMatrix affine3 = affine;
02751 affine3 *= affine2;
02752
02753 wxChar c = 0;
02754 double w = 0.0;
02755 const size_t n = text.Length();
02756 for ( size_t i = 0; i < n; i++ )
02757 {
02758 const wxChar oldc = c;
02759 c = text[i];
02760 if ( i > 0 )
02761 affine3 *= a2dAffineMatrix( w + GetKerning( oldc, c ), 0.0 );
02762 w = GetWidth( c );
02763
02764 GetVpath( c, vpath, affine3 );
02765 }
02766 }
02767
02768 void a2dFont::GetInfoList( a2dFontInfoList& list )
02769 {
02770 a2dFontFreetypeData::GetInfoList( list );
02771 a2dFontStrokeData::GetInfoList( list );
02772 a2dFontDcData::GetInfoList( list );
02773 }
02774
02775 a2dFont a2dFont::CreateFont( const a2dFontInfo& info, bool force )
02776 {
02777 a2dFontRefData* fontdata;
02778 a2dFont font;
02779
02780
02781 fontdata = (a2dFontRefData*) a2dFontFreetypeData::CreateFont( info );
02782 if ( !fontdata )
02783 fontdata = (a2dFontRefData*) a2dFontStrokeData::CreateFont( info );
02784 if ( !fontdata )
02785 fontdata = (a2dFontRefData*) a2dFontDcData::CreateFont( info );
02786
02787
02788 if ( !fontdata )
02789 fontdata = (a2dFontRefData*) a2dFontFreetypeData::CreateFont( info, force );
02790 if ( !fontdata )
02791 fontdata = (a2dFontRefData*) a2dFontStrokeData::CreateFont( info, force );
02792 if ( !fontdata )
02793 fontdata = (a2dFontRefData*) a2dFontDcData::CreateFont( info, force );
02794
02795 if ( !fontdata )
02796 {
02797
02798 font = *a2dDEFAULT_CANVASFONT;
02799 font.SetSize( info.GetSize() );
02800 }
02801 else
02802 {
02803 font = a2dFont();
02804 font.m_refData = fontdata;
02805 }
02806 return font;
02807 }
02808
02809 a2dFontType a2dFont::GetType( void ) const
02810 {
02811 if ( !m_refData )
02812 return a2dFONT_NULL;
02813 return ( (a2dFontRefData*) m_refData )->GetType();
02814 }
02815
02816 wxObjectRefData* a2dFont::CreateRefData() const
02817 {
02818 switch ( GetType() )
02819 {
02820 case a2dFONT_NULL:
02821 return new a2dFontDcData();
02822 case a2dFONT_WXDC:
02823 return new a2dFontDcData();
02824 case a2dFONT_FREETYPE:
02825 return new a2dFontFreetypeData();
02826 case a2dFONT_STROKED:
02827 return new a2dFontStrokeData();
02828 default:
02829 break;
02830 }
02831 return NULL;
02832 }
02833
02834 wxObjectRefData* a2dFont::CloneRefData(const wxObjectRefData * data) const
02835 {
02836 switch ( ( (a2dFontRefData*) data )->GetType() )
02837 {
02838 case a2dFONT_NULL:
02839 return NULL;
02840 case a2dFONT_WXDC:
02841 return new a2dFontDcData( *((const a2dFontDcData*)data) );
02842 case a2dFONT_FREETYPE:
02843 return new a2dFontFreetypeData( *((const a2dFontFreetypeData*)data) );
02844 case a2dFONT_STROKED:
02845 return new a2dFontStrokeData( *((const a2dFontStrokeData*)data) );
02846 default:
02847 break;
02848 }
02849 return NULL;
02850 }
02851
02852 void a2dFont::SetFilename( const wxString& filename )
02853 {
02854 switch ( ( (a2dFontRefData*) m_refData )->GetType() )
02855 {
02856 case a2dFONT_FREETYPE:
02857 ((a2dFontFreetypeData*)m_refData)->SetFilename( filename );
02858 break;
02859 case a2dFONT_STROKED:
02860 ((a2dFontStrokeData*)m_refData)->SetFilename( filename );
02861 break;
02862 default:
02863 wxFAIL_MSG( _( "wrong font to set a filename" ) );
02864 break;
02865 }
02866 }
02867
02868 wxString a2dFont::GetFilename( bool filenameonly ) const
02869 {
02870 switch ( ( (a2dFontRefData*) m_refData )->GetType() )
02871 {
02872 case a2dFONT_FREETYPE:
02873 return ((const a2dFontFreetypeData*)m_refData)->GetFilename(filenameonly);
02874 case a2dFONT_STROKED:
02875 return ((const a2dFontStrokeData*)m_refData)->GetFilename(filenameonly);
02876 default:
02877 break;
02878 }
02879 return wxT("");
02880 }
02881
02882 double a2dFont::GetWeight() const
02883 {
02884 switch ( ( (a2dFontRefData*) m_refData )->GetType() )
02885 {
02886 case a2dFONT_STROKED:
02887 return ((const a2dFontStrokeData*)m_refData)->GetWeight();
02888 default:
02889 break;
02890 }
02891 return 0.0;
02892 }
02893
02894 void a2dFont::SetWeight( double weight )
02895 {
02896 if ( GetWeight() == weight )
02897 return;
02898
02899 AllocExclusive();
02900
02901 switch ( ( (a2dFontRefData*) m_refData )->GetType() )
02902 {
02903 case a2dFONT_STROKED:
02904 ((a2dFontStrokeData*)m_refData)->SetWeight( weight );
02905 default:
02906 break;
02907 }
02908 }
02909
02910 void a2dFont::SetWeight( const wxString& weight )
02911 {
02912 AllocExclusive();
02913
02914 switch ( ( (a2dFontRefData*) m_refData )->GetType() )
02915 {
02916 case a2dFONT_STROKED:
02917 ((a2dFontStrokeData*)m_refData)->SetWeight( weight );
02918 default:
02919 break;
02920 }
02921 }
02922
02923
02924 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dBLACK_FILL );
02925 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dWHITE_FILL );
02926 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dTRANSPARENT_FILL );
02927
02928
02929 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dNullFILL);
02930
02931 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dINHERIT_FILL );
02932 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFill*, a2dSELECT_FILL );
02933
02934 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dBLACK_STROKE );
02935 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dWHITE_STROKE );
02936 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dTRANSPARENT_STROKE );
02937
02938
02939 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dNullSTROKE);
02940
02941 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dINHERIT_STROKE );
02942
02943
02944 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dStroke*, a2dLAYER_SELECT_STROKE );
02945
02946
02947 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFont*, a2dNullFONT );
02948
02949 A2DARTBASEDLLEXP a2dDECLARE_GLOBAL_VAR( const a2dFont*, a2dDEFAULT_CANVASFONT );
02950
02951 A2DARTBASEDLLEXP void a2dCanvasInitializeStockObjects ()
02952 {
02953 a2dBLACK_FILL = new a2dFill( wxColour(0,0,0) );
02954
02955 a2dWHITE_FILL = new a2dFill( wxColour(255,255,255) );
02956
02957 a2dTRANSPARENT_FILL = new a2dFill( wxColour(255,255,255), a2dFILL_TRANSPARENT );
02958
02959 a2dNullFILL = new a2dFill();
02960
02961 a2dINHERIT_FILL = new a2dFill( wxColour(0,0,0) );
02962
02963 a2dBLACK_STROKE = new a2dStroke( wxColour(0,0,0),0.0 );
02964
02965 a2dWHITE_STROKE = new a2dStroke( wxColour(255,255,255),0.0 );
02966
02967 a2dTRANSPARENT_STROKE = new a2dStroke( wxColour(255,255,255), 0.0, a2dSTROKE_TRANSPARENT );
02968
02969 a2dNullSTROKE = new a2dStroke();
02970
02971 a2dINHERIT_STROKE = new a2dStroke( wxColour(0,0,0), 0 );
02972
02973 a2dSELECT_FILL = new a2dFill(wxColour(0,0,0), a2dFILL_TRANSPARENT );
02974
02975 a2dLAYER_SELECT_STROKE = new a2dStroke( wxColour( wxT("YELLOW") ),2,a2dSTROKE_SOLID );
02976
02977 a2dNullFONT = new a2dFont();
02978
02979 a2dDEFAULT_CANVASFONT = new a2dFont( 100.0, wxSWISS );
02980 }
02981
02982 A2DARTBASEDLLEXP void a2dCanvasDeleteStockObjects ()
02983 {
02984 delete a2dBLACK_FILL;
02985
02986 delete a2dWHITE_FILL;
02987
02988 delete a2dTRANSPARENT_FILL;
02989
02990 delete a2dNullFILL;
02991
02992 delete a2dINHERIT_FILL;
02993
02994 delete a2dBLACK_STROKE;
02995
02996 delete a2dWHITE_STROKE;
02997
02998 delete a2dTRANSPARENT_STROKE;
02999
03000 delete a2dNullSTROKE;
03001
03002 delete a2dINHERIT_STROKE;
03003
03004 delete a2dSELECT_FILL;
03005
03006 delete a2dLAYER_SELECT_STROKE;
03007
03008 delete a2dNullFONT;
03009
03010 delete a2dDEFAULT_CANVASFONT;
03011
03012 }
03013
03014
03015
03016
03017
03018
03019 wxString FillStyle2String( a2dFillStyle style )
03020 {
03021 switch ( style )
03022 {
03023 case a2dFILL_SOLID: return wxT("a2dFILL_SOLID");
03024 case a2dFILL_TRANSPARENT: return wxT("a2dFILL_TRANSPARENT");
03025 case a2dFILL_BDIAGONAL_HATCH: return wxT("a2dFILL_BDIAGONAL_HATCH");
03026 case a2dFILL_CROSSDIAG_HATCH: return wxT("a2dFILL_CROSSDIAG_HATCH");
03027 case a2dFILL_FDIAGONAL_HATCH: return wxT("a2dFILL_FDIAGONAL_HATCH");
03028 case a2dFILL_CROSS_HATCH: return wxT("a2dFILL_CROSS_HATCH");
03029 case a2dFILL_HORIZONTAL_HATCH: return wxT("a2dFILL_HORIZONTAL_HATCH");
03030 case a2dFILL_VERTICAL_HATCH: return wxT("a2dFILL_VERTICAL_HATCH");
03031 case a2dFILL_STIPPLE: return wxT("a2dFILL_STIPPLE");
03032 case a2dFILL_STIPPLE_MASK_OPAQUE: return wxT("a2dFILL_STIPPLE_MASK_OPAQUE");
03033 case a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT: return wxT("a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT");
03034 case a2dFILL_GRADIENT_FILL_XY_LINEAR: return wxT("a2dFILL_GRADIENT_FILL_XY_LINEAR");
03035 case a2dFILL_GRADIENT_FILL_XY_RADIAL: return wxT("a2dFILL_GRADIENT_FILL_XY_RADIAL");
03036 case a2dFILL_GRADIENT_FILL_XY_DROP: return wxT("a2dFILL_GRADIENT_FILL_XY_DROP");
03037 case a2dFILL_INHERIT: return wxT("a2dFILL_INHERIT");
03038 case a2dFILL_LAYER: return wxT("a2dFILL_LAYER");
03039 case a2dFILL_NULLFILL: return wxT("a2dFILL_NULLFILL");
03040 case a2dFILL_TWOCOL_BDIAGONAL_HATCH: return wxT("a2dFILL_TWOCOL_BDIAGONAL_HATCH");
03041 case a2dFILL_TWOCOL_CROSSDIAG_HATCH: return wxT("a2dFILL_TWOCOL_CROSSDIAG_HATCH");
03042 case a2dFILL_TWOCOL_FDIAGONAL_HATCH: return wxT("a2dFILL_TWOCOL_FDIAGONAL_HATCH");
03043 case a2dFILL_TWOCOL_CROSS_HATCH: return wxT("a2dFILL_TWOCOL_CROSS_HATCH");
03044 case a2dFILL_TWOCOL_HORIZONTAL_HATCH: return wxT("a2dFILL_TWOCOL_HORIZONTAL_HATCH");
03045 case a2dFILL_TWOCOL_VERTICAL_HATCH: return wxT("a2dFILL_TWOCOL_VERTICAL_HATCH");
03046
03047 default:
03048 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("CVG : invalid style") );
03049 }
03050 return wxT("a2dFILL_NULLFILL");
03051 }
03052
03053
03054 a2dFillStyle FillString2Style( const wxString& stylestr )
03055 {
03056 if ( stylestr == wxT("a2dFILL_SOLID") )
03057 return a2dFILL_SOLID;
03058 if ( stylestr == wxT("a2dFILL_TRANSPARENT") )
03059 return a2dFILL_TRANSPARENT;
03060 if ( stylestr == wxT("a2dFILL_BDIAGONAL_HATCH") )
03061 return a2dFILL_BDIAGONAL_HATCH;
03062 if ( stylestr == wxT("a2dFILL_CROSSDIAG_HATCH") )
03063 return a2dFILL_CROSSDIAG_HATCH;
03064 if ( stylestr == wxT("a2dFILL_FDIAGONAL_HATCH") )
03065 return a2dFILL_FDIAGONAL_HATCH;
03066 if ( stylestr == wxT("a2dFILL_CROSS_HATCH") )
03067 return a2dFILL_CROSS_HATCH;
03068 if ( stylestr == wxT("a2dFILL_HORIZONTAL_HATCH") )
03069 return a2dFILL_HORIZONTAL_HATCH;
03070 if ( stylestr == wxT("a2dFILL_VERTICAL_HATCH") )
03071 return a2dFILL_VERTICAL_HATCH;
03072 if ( stylestr == wxT("a2dFILL_STIPPLE") )
03073 return a2dFILL_STIPPLE;
03074 if ( stylestr == wxT("a2dFILL_STIPPLE_MASK_OPAQUE") )
03075 return a2dFILL_STIPPLE_MASK_OPAQUE;
03076 if ( stylestr == wxT("a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT") )
03077 return a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT;
03078 if ( stylestr == wxT("a2dFILL_GRADIENT_FILL_XY_LINEAR") )
03079 return a2dFILL_GRADIENT_FILL_XY_LINEAR;
03080 if ( stylestr == wxT("a2dFILL_GRADIENT_FILL_XY_RADIAL") )
03081 return a2dFILL_GRADIENT_FILL_XY_RADIAL;
03082 if ( stylestr == wxT("a2dFILL_GRADIENT_FILL_XY_DROP") )
03083 return a2dFILL_GRADIENT_FILL_XY_DROP;
03084 if ( stylestr == wxT("a2dFILL_INHERIT") )
03085 return a2dFILL_INHERIT;
03086 if ( stylestr == wxT("a2dFILL_LAYER") )
03087 return a2dFILL_LAYER;
03088 if ( stylestr == wxT("a2dFILL_NULLFILL") )
03089 return a2dFILL_NULLFILL;
03090
03091 if ( stylestr == wxT("a2dFILL_TWOCOL_BDIAGONAL_HATCH") )
03092 return a2dFILL_TWOCOL_BDIAGONAL_HATCH;
03093 if ( stylestr == wxT("a2dFILL_TWOCOL_CROSSDIAG_HATCH") )
03094 return a2dFILL_TWOCOL_CROSSDIAG_HATCH;
03095 if ( stylestr == wxT("a2dFILL_TWOCOL_FDIAGONAL_HATCH") )
03096 return a2dFILL_TWOCOL_FDIAGONAL_HATCH;
03097 if ( stylestr == wxT("a2dFILL_TWOCOL_CROSS_HATCH") )
03098 return a2dFILL_TWOCOL_CROSS_HATCH;
03099 if ( stylestr == wxT("a2dFILL_TWOCOL_HORIZONTAL_HATCH") )
03100 return a2dFILL_TWOCOL_HORIZONTAL_HATCH;
03101 if ( stylestr == wxT("a2dFILL_TWOCOL_VERTICAL_HATCH") )
03102 return a2dFILL_TWOCOL_VERTICAL_HATCH;
03103
03104 if ( !stylestr.IsEmpty() )
03105 {
03106 long num;
03107 stylestr.ToLong( &num );
03108 return ( a2dFillStyle ) num;
03109 }
03110
03111 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("CVG : invalid style %s"), stylestr.c_str() );
03112
03113 return a2dFILL_NULLFILL;
03114 }
03115
03116
03117
03118
03119
03120 a2dFillProperty::a2dFillProperty(): a2dNamedProperty()
03121 {
03122 }
03123
03124 a2dFillProperty::a2dFillProperty( const a2dPropertyIdFill* id, const a2dFill& value )
03125 :a2dNamedProperty( id )
03126 {
03127 m_value = value;
03128 }
03129
03130 a2dFillProperty::~a2dFillProperty()
03131 {
03132 }
03133
03134 a2dFillProperty::a2dFillProperty( const a2dFillProperty* ori )
03135 : a2dNamedProperty( *ori )
03136 {
03137 m_value = ori->m_value;
03138 }
03139
03140 a2dFillProperty::a2dFillProperty( const a2dFillProperty &other )
03141 : a2dNamedProperty( other )
03142 {
03143 m_value = other.m_value;
03144 }
03145
03146 a2dNamedProperty *a2dFillProperty::Clone( a2dObject::CloneOptions WXUNUSED(options) ) const
03147 {
03148 return new a2dFillProperty(*this );
03149 };
03150
03151 void a2dFillProperty::Assign( const a2dNamedProperty &other )
03152 {
03153 a2dFillProperty *propcast = wxStaticCast( &other, a2dFillProperty);
03154 m_value = propcast->m_value;
03155 }
03156
03157 a2dFillProperty *a2dFillProperty::CreatePropertyFromString( const a2dPropertyIdFill* id, const wxString& WXUNUSED(value) )
03158 {
03159 return 0;
03160 }
03161
03162 #if wxART2D_USE_CVGIO
03163 void a2dFillProperty::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
03164 {
03165 a2dNamedProperty::DoSave( parent, out, xmlparts, towrite );
03166 if ( xmlparts == a2dXmlSer_attrib )
03167 {
03168 }
03169 else
03170 {
03171 m_value.Save( parent, out, towrite );
03172 }
03173 }
03174
03175 void a2dFillProperty::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
03176 {
03177 a2dNamedProperty::DoLoad( parent, parser, xmlparts );
03178 if ( xmlparts == a2dXmlSer_attrib )
03179 {
03180 }
03181 else
03182 {
03183 m_value.Load( parent, parser );
03184 }
03185 }
03186 #endif //wxART2D_USE_CVGIO
03187
03188 void a2dFillProperty::SetValue( const a2dFill& value )
03189 {
03190 m_value = value;
03191 }
03192
03193 wxString a2dFillProperty::StringRepresentation() const
03194 {
03195 return wxT("VOID");
03196 }
03197
03198 wxString a2dFillProperty::StringValueRepresentation() const
03199 {
03200 return wxT("VOID");
03201 }
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211 class A2DARTBASEDLLEXP a2dFillRefData : public wxObjectRefData
03212 {
03213 public:
03214
03215 virtual a2dFillType GetType( void ) const { return a2dFILL_NULL; }
03216
03217
03218 a2dFillRefData()
03219 {
03220 m_fillOn = true;
03221 }
03222
03223 a2dFillRefData( const a2dFillRefData& other )
03224 : wxObjectRefData()
03225 {
03226 m_fillOn = other.m_fillOn;
03227 }
03228
03229 #if wxART2D_USE_CVGIO
03230
03231 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList* towrite ) = 0;
03232
03233 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts ) = 0;
03234 #endif //wxART2D_USE_CVGIO
03235
03236
03237 bool m_fillOn;
03238 };
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250 class A2DARTBASEDLLEXP a2dOneColourFillData : public a2dFillRefData
03251 {
03252 private:
03253
03254 friend class a2dFill;
03255
03256 public:
03257
03258 virtual a2dFillType GetType( void ) const { return a2dFILL_ONE_COLOUR; }
03259
03260
03261 a2dOneColourFillData( void );
03262
03263 a2dOneColourFillData( const a2dOneColourFillData& fill );
03264
03265
03266 a2dOneColourFillData( const wxColour& col, a2dFillStyle style = a2dFILL_SOLID );
03267
03268 a2dOneColourFillData( const wxBrush& brush );
03269
03270
03271 ~a2dOneColourFillData( void ){}
03272
03273 static a2dOneColourFillData* Create( const wxColour& col, a2dFillStyle style = a2dFILL_SOLID );
03274
03275 void SetColour( const wxColour& col ) { m_colour1 = col; }
03276
03277
03278 wxColour GetColour() const { return m_colour1; }
03279
03280 a2dFillStyle GetStyle( void ) const { return m_style; }
03281
03282 void SetStyle( a2dFillStyle style ) { m_style = style; }
03283
03284 protected:
03285
03286 #if wxART2D_USE_CVGIO
03287 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
03288 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
03289 #endif //wxART2D_USE_CVGIO
03290
03291
03292 a2dFillStyle m_style;
03293
03294 wxColour m_colour1;
03295 };
03296
03297 a2dOneColourFillData* a2dOneColourFillData::Create( const wxColour& col, a2dFillStyle style )
03298 {
03299 return new a2dOneColourFillData( col, style );
03300 }
03301
03302 a2dOneColourFillData::a2dOneColourFillData( void )
03303 : a2dFillRefData()
03304 {
03305 m_style = a2dFILL_SOLID;
03306 m_colour1 = *wxBLACK;
03307 }
03308
03309 a2dOneColourFillData::a2dOneColourFillData( const wxColour& col, a2dFillStyle style )
03310 : a2dFillRefData()
03311 {
03312 m_colour1 = col;
03313 if ( style == a2dFILL_SOLID ||
03314 style == a2dFILL_TRANSPARENT ||
03315 style == a2dFILL_BDIAGONAL_HATCH ||
03316 style == a2dFILL_CROSSDIAG_HATCH ||
03317 style == a2dFILL_FDIAGONAL_HATCH ||
03318 style == a2dFILL_CROSS_HATCH ||
03319 style == a2dFILL_HORIZONTAL_HATCH ||
03320 style == a2dFILL_VERTICAL_HATCH ||
03321 style == a2dFILL_NULLFILL
03322 )
03323 m_style = style;
03324 else
03325 wxFAIL_MSG( _( "invalid style for a2dOneColourFillData" ) );
03326 }
03327
03328 a2dOneColourFillData::a2dOneColourFillData( const wxBrush& brush )
03329 : a2dFillRefData()
03330 {
03331 if ( brush.GetStyle() == wxSOLID)
03332 {
03333 m_colour1 = wxColour( brush.GetColour() );
03334 m_style = a2dFILL_SOLID;
03335 }
03336 else if ( brush.IsHatch() )
03337 {
03338 m_colour1 = wxColour( brush.GetColour() );
03339
03340 switch( brush.GetStyle() )
03341 {
03342 case wxBDIAGONAL_HATCH :
03343 m_style = a2dFILL_BDIAGONAL_HATCH;
03344 break ;
03345 case wxCROSSDIAG_HATCH :
03346 m_style = a2dFILL_CROSSDIAG_HATCH;
03347 break ;
03348 case wxFDIAGONAL_HATCH :
03349 m_style = a2dFILL_FDIAGONAL_HATCH;
03350 break ;
03351 case wxCROSS_HATCH :
03352 m_style = a2dFILL_CROSS_HATCH;
03353 break ;
03354 case wxHORIZONTAL_HATCH :
03355 m_style = a2dFILL_HORIZONTAL_HATCH;
03356 break ;
03357 case wxVERTICAL_HATCH :
03358 m_style = a2dFILL_VERTICAL_HATCH;
03359 break ;
03360 }
03361 }
03362 else if ( brush.GetStyle() == wxTRANSPARENT )
03363 m_style = a2dFILL_TRANSPARENT;
03364 }
03365
03366 a2dOneColourFillData::a2dOneColourFillData( const a2dOneColourFillData& other )
03367 : a2dFillRefData( other )
03368 {
03369 m_style = other.m_style;
03370 m_colour1 = other.m_colour1;
03371 }
03372
03373 #if wxART2D_USE_CVGIO
03374 void a2dOneColourFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
03375 {
03376 if ( xmlparts == a2dXmlSer_attrib )
03377 {
03378 m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT("a2dFILL_SOLID") ) );
03379 SetStyle( m_style );
03380
03381 wxString fillColour = parser.GetAttributeValue( wxT( "colour" ) );
03382 if ( !fillColour.IsEmpty() )
03383 {
03384 if ( fillColour.GetChar( 0 ) == wxT( '#' ) )
03385 m_colour1 = HexToColour( fillColour.After( wxT( '#' ) ) );
03386 else
03387 {
03388 m_colour1 = wxTheColourDatabase->Find( fillColour );
03389 if ( !m_colour1.Ok() )
03390 m_colour1 = *wxBLACK;
03391 }
03392 }
03393 else
03394 m_colour1 = *wxBLACK;
03395 }
03396 else
03397 {}
03398 }
03399
03400 void a2dOneColourFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
03401 {
03402 if ( xmlparts == a2dXmlSer_attrib )
03403 {
03404 if ( m_style != a2dFILL_SOLID )
03405 out.WriteAttribute( wxT( "style" ), FillStyle2String( GetStyle() ) );
03406 if ( m_style != a2dFILL_TRANSPARENT )
03407 {
03408 wxString brushColour = wxTheColourDatabase->FindName( GetColour() );
03409
03410 if ( brushColour.IsEmpty() )
03411 out.WriteAttribute( wxT( "colour" ), wxT( "#" ) + ColourToHex( GetColour() ) );
03412 else
03413 out.WriteAttribute( wxT( "colour" ), brushColour );
03414 }
03415 }
03416 else
03417 {}
03418 }
03419 #endif //wxART2D_USE_CVGIO
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432 class A2DARTBASEDLLEXP a2dTwoColourFillData : public a2dFillRefData
03433 {
03434
03435 private:
03436
03437 friend class a2dFill;
03438
03439 protected:
03440
03441
03442 a2dTwoColourFillData( void );
03443
03444 a2dTwoColourFillData( const a2dTwoColourFillData& fill );
03445
03446
03447 a2dTwoColourFillData( const wxColour& col, const wxColour& col2, a2dFillStyle style );
03448
03449
03450 ~a2dTwoColourFillData( void ){}
03451
03452 a2dFillStyle GetStyle( void ) const { return m_style; }
03453
03454 void SetStyle( a2dFillStyle style ) { m_style = style; }
03455
03456
03457 void SetColour2( const wxColour& col ) { m_colour2 = col; }
03458
03459
03460 wxColour GetColour2() const { return m_colour2; }
03461
03462
03463 void SetColour( const wxColour& col ) { m_colour1 = col; }
03464
03465
03466 wxColour GetColour() const { return m_colour1; }
03467
03468 #if wxART2D_USE_CVGIO
03469 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
03470 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
03471 #endif //wxART2D_USE_CVGIO
03472
03473
03474 wxColour m_colour1;
03475
03476
03477 wxColour m_colour2;
03478
03479
03480 a2dFillStyle m_style;
03481 };
03482
03483 a2dTwoColourFillData::a2dTwoColourFillData( void )
03484 : a2dFillRefData()
03485 {
03486 m_colour1 = *wxBLACK;
03487 m_colour2 = *wxBLACK;
03488 }
03489
03490 a2dTwoColourFillData::a2dTwoColourFillData( const wxColour& col, const wxColour& col2, a2dFillStyle style )
03491 : a2dFillRefData( )
03492 {
03493 m_colour1 = col;
03494 m_colour2 = col2;
03495 m_style = style;
03496 }
03497
03498 a2dTwoColourFillData::a2dTwoColourFillData( const a2dTwoColourFillData& other )
03499 : a2dFillRefData( other )
03500 {
03501 m_style = other.m_style;
03502 m_colour1 = other.m_colour1;
03503 m_colour2 = other.m_colour2;
03504 }
03505
03506 #if wxART2D_USE_CVGIO
03507 void a2dTwoColourFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
03508 {
03509 if ( xmlparts == a2dXmlSer_attrib )
03510 {
03511 wxString fillColour = parser.GetAttributeValue( wxT( "colour" ) );
03512 if ( fillColour.GetChar( 0 ) == wxT( '#' ) )
03513 m_colour1 = HexToColour( fillColour.After( wxT( '#' ) ) );
03514 else
03515 {
03516 m_colour1 = wxTheColourDatabase->Find( fillColour );
03517 if ( !m_colour1.Ok() )
03518 m_colour1 = *wxBLACK;
03519 }
03520 fillColour = parser.GetAttributeValue( wxT( "colour2" ) );
03521 if ( !fillColour.IsEmpty() )
03522 {
03523 if ( fillColour.GetChar( 0 ) == wxT( '#' ) )
03524 m_colour2 = HexToColour( fillColour.After( wxT( '#' ) ) );
03525 else
03526 {
03527 m_colour2 = wxTheColourDatabase->Find( fillColour );
03528 if ( !m_colour2.Ok() )
03529 m_colour2 = *wxBLACK;
03530 }
03531 }
03532 }
03533 else
03534 {}
03535 }
03536
03537 void a2dTwoColourFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
03538 {
03539 if ( xmlparts == a2dXmlSer_attrib )
03540 {
03541 if ( m_style != a2dFILL_TRANSPARENT )
03542 {
03543 wxString brushColour = wxTheColourDatabase->FindName( GetColour() );
03544
03545 if ( brushColour.IsEmpty() )
03546 out.WriteAttribute( wxT( "colour" ), wxT( "#" ) + ColourToHex( GetColour() ) );
03547 else
03548 out.WriteAttribute( wxT( "colour" ), brushColour );
03549
03550 brushColour = wxTheColourDatabase->FindName( GetColour2() );
03551 if ( brushColour.IsEmpty() )
03552 out.WriteAttribute( wxT( "colour2" ), wxT( "#" ) + ColourToHex( GetColour2() ) );
03553 else
03554 out.WriteAttribute( wxT( "colour2" ), brushColour );
03555 }
03556 }
03557 else
03558 {}
03559 }
03560 #endif //wxART2D_USE_CVGIO
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572 class A2DARTBASEDLLEXP a2dHatchFillData: public a2dTwoColourFillData
03573 {
03574
03575 private:
03576
03577 friend class a2dFill;
03578
03579 public:
03580
03581 virtual a2dFillType GetType( void ) const { return a2dFILL_HATCH_TWO_COLOUR; }
03582
03583 protected:
03584
03585
03586 a2dHatchFillData( void );
03587
03588
03589 a2dHatchFillData( const a2dHatchFillData& other );
03590
03591
03592
03593
03594
03595
03596 a2dHatchFillData( const wxColour& col, const wxColour& col2, a2dFillStyle style );
03597
03598
03599 ~a2dHatchFillData( void ){}
03600
03601 void SetStyle( a2dFillStyle style );
03602
03603 #if wxART2D_USE_CVGIO
03604 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
03605 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
03606 #endif //wxART2D_USE_CVGIO
03607
03608 };
03609
03610 a2dHatchFillData::a2dHatchFillData( void ): a2dTwoColourFillData()
03611 {
03612 m_style = a2dFILL_TWOCOL_BDIAGONAL_HATCH;
03613 }
03614
03615 a2dHatchFillData::a2dHatchFillData( const wxColour& col, const wxColour& col2, a2dFillStyle style )
03616 :a2dTwoColourFillData( col, col2, style )
03617 {
03618 SetStyle( style );
03619 }
03620
03621 a2dHatchFillData::a2dHatchFillData( const a2dHatchFillData& other )
03622 : a2dTwoColourFillData( other )
03623 {
03624 }
03625
03626 void a2dHatchFillData::SetStyle( a2dFillStyle style )
03627 {
03628 if (
03629 style == a2dFILL_TRANSPARENT ||
03630 style == a2dFILL_TWOCOL_BDIAGONAL_HATCH ||
03631 style == a2dFILL_TWOCOL_CROSSDIAG_HATCH ||
03632 style == a2dFILL_TWOCOL_FDIAGONAL_HATCH ||
03633 style == a2dFILL_TWOCOL_CROSS_HATCH ||
03634 style == a2dFILL_TWOCOL_HORIZONTAL_HATCH ||
03635 style == a2dFILL_TWOCOL_VERTICAL_HATCH
03636 )
03637 m_style = style;
03638 else
03639 wxFAIL_MSG( _( "invalid style for a2dHatchFillData" ) );
03640 }
03641
03642 #if wxART2D_USE_CVGIO
03643 void a2dHatchFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
03644 {
03645 a2dTwoColourFillData::DoSave( parent, out, xmlparts, towrite );
03646 if ( xmlparts == a2dXmlSer_attrib )
03647 {
03648 if ( m_style != a2dFILL_TWOCOL_BDIAGONAL_HATCH )
03649 out.WriteAttribute( wxT( "style" ), FillStyle2String( m_style ) );
03650 }
03651 else
03652 {}
03653 }
03654
03655 void a2dHatchFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
03656 {
03657 a2dTwoColourFillData::DoLoad( parent, parser, xmlparts );
03658 if ( xmlparts == a2dXmlSer_attrib )
03659 {
03660 m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT("a2dFILL_TWOCOL_BDIAGONAL_HATCH") ) );
03661 }
03662 else
03663 {}
03664 }
03665 #endif //wxART2D_USE_CVGIO
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679 class A2DARTBASEDLLEXP a2dLinearGradientFillData: public a2dTwoColourFillData
03680 {
03681
03682 private:
03683
03684 friend class a2dFill;
03685
03686 public:
03687
03688 virtual a2dFillType GetType( void ) const { return a2dFILL_GRADIENT_FILL_LINEAR; }
03689
03690 protected:
03691
03692
03693 a2dLinearGradientFillData( void );
03694
03695
03696 a2dLinearGradientFillData( const a2dLinearGradientFillData& other );
03697
03698
03699
03700
03701
03702
03703 a2dLinearGradientFillData(
03704 const wxColour& col, const wxColour& col2,
03705 double x1, double y1, double x2, double y2 );
03706
03707
03708 ~a2dLinearGradientFillData( void ){}
03709
03710
03711 void SetStart( double x, double y );
03712
03713
03714 void SetStop( double x, double y );
03715
03716
03717 a2dPoint2D GetStart() { return a2dPoint2D( m_x1, m_y1 ); }
03718
03719
03720 a2dPoint2D GetStop() { return a2dPoint2D( m_x2, m_y2 ); }
03721
03722 void Init( a2dAffineMatrix* cworld, double minx, double miny, double maxx, double maxy, double centroidx, double centroidy );
03723
03724 void ColourXY( a2dDrawer2D* drawer, int x1, int x2, int y );
03725
03726 wxUint32 GetStamp() { return m_gradientstamp; }
03727
03728 #if wxART2D_USE_CVGIO
03729 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
03730 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
03731 #endif //wxART2D_USE_CVGIO
03732
03733 double m_x1, m_y1, m_x2, m_y2;
03734
03735 wxUint32 m_gradientstamp;
03736 };
03737
03738 a2dLinearGradientFillData::a2dLinearGradientFillData( void ): a2dTwoColourFillData()
03739 {
03740 m_style = a2dFILL_GRADIENT_FILL_XY_LINEAR;
03741 m_x1 = 0;
03742 m_y1 = 0;
03743 m_x2 = 0;
03744 m_y2 = 0;
03745 }
03746
03747 a2dLinearGradientFillData::a2dLinearGradientFillData(
03748 const wxColour& col, const wxColour& col2,
03749 double x1, double y1, double x2, double y2 )
03750 :a2dTwoColourFillData( col, col2, a2dFILL_GRADIENT_FILL_XY_LINEAR )
03751 {
03752 m_x1 = x1;
03753 m_y1 = y1;
03754 m_x2 = x2;
03755 m_y2 = y2;
03756 }
03757
03758 a2dLinearGradientFillData::a2dLinearGradientFillData( const a2dLinearGradientFillData& other )
03759 : a2dTwoColourFillData( other )
03760 {
03761 m_x1 = other.m_x1;
03762 m_y1 = other.m_y1;
03763 m_x2 = other.m_x2;
03764 m_y2 = other.m_y2;
03765 }
03766
03767 void a2dLinearGradientFillData::SetStart( double x, double y )
03768 {
03769 m_x1 = x;
03770 m_y1 = y;
03771 }
03772
03773 void a2dLinearGradientFillData::SetStop( double x, double y )
03774 {
03775 m_x2 = x;
03776 m_y2 = y;
03777 }
03778
03779 #if wxART2D_USE_CVGIO
03780 void a2dLinearGradientFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
03781 {
03782 a2dTwoColourFillData::DoSave( parent, out, xmlparts, towrite );
03783 if ( xmlparts == a2dXmlSer_attrib )
03784 {
03785 if ( m_style != a2dFILL_GRADIENT_FILL_XY_LINEAR )
03786 out.WriteAttribute( wxT( "style" ), FillStyle2String( m_style ) );
03787 out.WriteAttribute( wxT( "x1" ), m_x1 );
03788 out.WriteAttribute( wxT( "y1" ), m_y1 );
03789 out.WriteAttribute( wxT( "x2" ), m_x2 );
03790 out.WriteAttribute( wxT( "y2" ), m_y2 );
03791 }
03792 else
03793 {}
03794 }
03795
03796 void a2dLinearGradientFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
03797 {
03798 a2dTwoColourFillData::DoLoad( parent, parser, xmlparts );
03799 if ( xmlparts == a2dXmlSer_attrib )
03800 {
03801 m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT("a2dFILL_GRADIENT_FILL_XY_LINEAR") ) );
03802
03803 m_x1 = parser.GetAttributeValueDouble( wxT( "x1" ) ) ;
03804 m_y1 = parser.GetAttributeValueDouble( wxT( "y1" ) ) ;
03805 m_x2 = parser.GetAttributeValueDouble( wxT( "x2" ) ) ;
03806 m_y2 = parser.GetAttributeValueDouble( wxT( "y2" ) ) ;
03807 }
03808 else
03809 {}
03810 }
03811
03812 #endif //wxART2D_USE_CVGIO
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825 class A2DARTBASEDLLEXP a2dRadialGradientFillData: public a2dTwoColourFillData
03826 {
03827
03828 private:
03829
03830 friend class a2dFill;
03831
03832 public:
03833
03834 virtual a2dFillType GetType( void ) const { return a2dFILL_GRADIENT_FILL_RADIAL; }
03835
03836 protected:
03837
03838
03839 a2dRadialGradientFillData( void );
03840
03841
03842 a2dRadialGradientFillData( const a2dRadialGradientFillData& other );
03843
03844
03845
03846
03847
03848
03849 a2dRadialGradientFillData(
03850 const wxColour& col, const wxColour& col2,
03851 double xfc, double yfc, double xe, double ye, double radius );
03852
03853
03854 ~a2dRadialGradientFillData( void ){}
03855
03856
03857 void SetCenter( double x, double y );
03858
03859
03860 void SetRadius( double radius );
03861
03862
03863 void SetFocal( double x, double y );
03864
03865
03866 a2dPoint2D GetCenter() { return a2dPoint2D( m_xe, m_ye ); }
03867
03868
03869 a2dPoint2D GetFocal() { return a2dPoint2D( m_xe, m_ye ); }
03870
03871
03872 double GetRadius() { return m_radius; }
03873
03874 void Init( a2dAffineMatrix* cworld, double minx, double miny, double maxx, double maxy, double centroidx, double centroidy );
03875
03876 void ColourXY( a2dDrawer2D* drawer, int x1, int x2, int y );
03877
03878 wxUint32 GetStamp() { return m_gradientstamp; }
03879
03880 #if wxART2D_USE_CVGIO
03881 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
03882 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
03883 #endif //wxART2D_USE_CVGIO
03884
03885
03886
03887 double m_radius;
03888
03889
03890 double m_xe;
03891
03892
03893 double m_ye;
03894
03895
03896 double m_xfc;
03897
03898
03899 double m_yfc;
03900
03901 wxUint32 m_gradientstamp;
03902 };
03903
03904 a2dRadialGradientFillData::a2dRadialGradientFillData( void ): a2dTwoColourFillData()
03905 {
03906 m_style = a2dFILL_GRADIENT_FILL_XY_RADIAL;
03907 m_xe = 0;
03908 m_ye = 0;
03909 m_xfc = 0;
03910 m_yfc = 0;
03911 m_radius = 0;
03912 }
03913
03914 a2dRadialGradientFillData::a2dRadialGradientFillData(
03915 const wxColour& col, const wxColour& col2,
03916 double xfc, double yfc, double xe, double ye, double radius )
03917 : a2dTwoColourFillData( col, col2, a2dFILL_GRADIENT_FILL_XY_RADIAL )
03918 {
03919 m_xe = xe;
03920 m_ye = ye;
03921 m_xfc = xfc;
03922 m_yfc = yfc;
03923 m_radius = radius;
03924 }
03925
03926 a2dRadialGradientFillData::a2dRadialGradientFillData( const a2dRadialGradientFillData& other )
03927 : a2dTwoColourFillData( other )
03928 {
03929 m_xe = other.m_xe;
03930 m_ye = other.m_ye;
03931 m_xfc = other.m_xfc;
03932 m_yfc = other.m_yfc;
03933 m_radius = other.m_radius;
03934 }
03935
03936 void a2dRadialGradientFillData::SetCenter( double x, double y )
03937 {
03938 m_xe = x;
03939 m_ye = y;
03940 }
03941
03942 void a2dRadialGradientFillData::SetRadius( double radius )
03943 {
03944 m_radius = radius;
03945 }
03946
03947
03948 void a2dRadialGradientFillData::SetFocal( double x, double y )
03949 {
03950 m_xfc = x;
03951 m_yfc = y;
03952 }
03953
03954 #if wxART2D_USE_CVGIO
03955 void a2dRadialGradientFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
03956 {
03957 a2dTwoColourFillData::DoSave( parent, out, xmlparts, towrite );
03958 if ( xmlparts == a2dXmlSer_attrib )
03959 {
03960 if ( m_style != a2dFILL_GRADIENT_FILL_XY_RADIAL )
03961 out.WriteAttribute( wxT( "style" ), FillStyle2String( m_style ) );
03962 out.WriteAttribute( wxT( "cx" ), m_xe );
03963 out.WriteAttribute( wxT( "cy" ), m_ye );
03964 out.WriteAttribute( wxT( "r" ), m_radius );
03965 out.WriteAttribute( wxT( "fx" ), m_xfc );
03966 out.WriteAttribute( wxT( "fy" ), m_yfc );
03967 }
03968 else
03969 {}
03970 }
03971
03972 void a2dRadialGradientFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
03973 {
03974 a2dTwoColourFillData::DoLoad( parent, parser, xmlparts );
03975 if ( xmlparts == a2dXmlSer_attrib )
03976 {
03977 m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT("a2dFILL_GRADIENT_FILL_XY_RADIAL") ) );
03978
03979 m_xe = parser.GetAttributeValueDouble( wxT( "cx" ) ) ;
03980 m_ye = parser.GetAttributeValueDouble( wxT( "cy" ) ) ;
03981 m_radius = parser.GetAttributeValueDouble( wxT( "r" ) ) ;
03982 m_xfc = parser.GetAttributeValueDouble( wxT( "fx" ) ) ;
03983 m_yfc = parser.GetAttributeValueDouble( wxT( "fy" ) ) ;
03984 }
03985 else
03986 {}
03987
03988 }
03989 #endif //wxART2D_USE_CVGIO
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006 class A2DARTBASEDLLEXP a2dPatternFillData: public a2dTwoColourFillData
04007 {
04008 private:
04009
04010 friend class a2dFill;
04011
04012 public:
04013
04014 virtual a2dFillType GetType( void ) const { return a2dFILL_BITMAP; }
04015
04016 protected:
04017
04018
04019 a2dPatternFillData();
04020
04021
04022 a2dPatternFillData( const a2dPatternFillData& other );
04023
04024
04025
04026
04027
04028
04029
04030 a2dPatternFillData( const wxBitmap& stipple, a2dFillStyle style = a2dFILL_STIPPLE );
04031
04032 a2dPatternFillData( const wxFileName& filename, a2dFillStyle style = a2dFILL_STIPPLE );
04033
04034
04035 ~a2dPatternFillData( void ){}
04036
04037
04038 void SetStipple( const wxBitmap& stipple );
04039
04040 const wxBitmap& GetStipple() const { return m_stipple; }
04041
04042
04043
04044
04045
04046 wxString GetFileName() { return m_filename; }
04047
04048 a2dFillStyle GetStyle() const;
04049
04050 void SetStyle( a2dFillStyle style );
04051
04052 #if wxART2D_USE_CVGIO
04053 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
04054 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
04055 #endif //wxART2D_USE_CVGIO
04056
04057 wxBitmap m_stipple;
04058
04059
04060
04061 wxString m_filename;
04062
04063 };
04064
04065 a2dPatternFillData::a2dPatternFillData()
04066 {
04067 m_stipple = wxNullBitmap;
04068 m_style = a2dFILL_STIPPLE;
04069 SetStyle( m_style );
04070 }
04071
04072 a2dPatternFillData::a2dPatternFillData( const wxBitmap& stipple, a2dFillStyle style )
04073 {
04074 m_stipple = stipple;
04075
04076 if ( style == a2dFILL_STIPPLE_MASK_OPAQUE || style == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
04077 {
04078 wxASSERT_MSG( m_stipple.GetMask(), wxT( "require a mask for a2dFILL_STIPPLE_MASK_OPAQUE or a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT" ) );
04079 }
04080 SetStyle( style );
04081 }
04082
04083 a2dPatternFillData::a2dPatternFillData( const wxFileName& filename, a2dFillStyle style )
04084 {
04085 m_filename = filename.GetFullPath();
04086
04087 wxImage image;
04088 if ( m_filename.IsEmpty() )
04089 {
04090 wxLogError( _("CVG : bitmap file for a2dPatternFill not specified or empty") );
04091 image = wxImage( 32, 32 );
04092 }
04093 else
04094 {
04095 wxString filename = a2dGlobals->GetImagePathList().FindValidPath( m_filename );
04096 if ( filename.IsEmpty() )
04097 {
04098 wxLogError( _("CVG : Could not load bitmap \"%s\" for a2dPatternFill from path \"%s\" "), m_filename.c_str(), a2dGlobals->GetImagePathList().GetAsString().c_str() );
04099 image = wxImage( 32, 32 );
04100 }
04101 else if ( ! image.LoadFile(filename,wxBITMAP_TYPE_BMP) )
04102 {
04103 wxLogError( _("CVG : Could not load bitmap %s for a2dPatternFill"), filename.c_str() );
04104 image = wxImage( 32, 32 );
04105 }
04106 }
04107 m_stipple = wxBitmap( image );
04108
04109 if ( style == a2dFILL_STIPPLE_MASK_OPAQUE || style == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
04110 {
04111 wxColour white(wxT("WHITE"));
04112 wxColour black(wxT("BLACK"));
04113
04114 wxMask* monochrome_mask = new wxMask( m_stipple, black );
04115 m_stipple.SetMask(monochrome_mask);
04116 }
04117 SetStyle( style );
04118 }
04119
04120 void a2dPatternFillData::SetStipple( const wxBitmap& stipple )
04121 {
04122 m_stipple = stipple;
04123 }
04124
04125 a2dPatternFillData::a2dPatternFillData( const a2dPatternFillData& other ): a2dTwoColourFillData( other )
04126 {
04127 m_stipple = other.m_stipple;
04128 }
04129
04130 a2dFillStyle a2dPatternFillData::GetStyle() const
04131 {
04132 return m_style;
04133 }
04134
04135 void a2dPatternFillData::SetStyle( a2dFillStyle style )
04136 {
04137 if ( style == a2dFILL_TRANSPARENT )
04138 m_style = a2dFILL_TRANSPARENT;
04139 else if ( style == a2dFILL_STIPPLE_MASK_OPAQUE ||
04140 style == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT
04141 )
04142 {
04143 if ( !m_stipple.GetMask() )
04144 {
04145 wxMask * mask = new wxMask( m_stipple, GetColour() );
04146 m_stipple.SetMask( mask );
04147 }
04148 m_style = style;
04149 }
04150 else if ( style == a2dFILL_STIPPLE )
04151 m_style = style;
04152 else
04153 wxFAIL_MSG( _( "invalid style for a2dPatternFillData" ) );
04154 }
04155
04156 #if wxART2D_USE_CVGIO
04157 void a2dPatternFillData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
04158 {
04159 a2dTwoColourFillData::DoLoad( parent, parser, xmlparts );
04160 if ( xmlparts == a2dXmlSer_attrib )
04161 {
04162 wxString filename = parser.GetAttributeValue( wxT( "filename" ), wxT( "" ) );
04163 wxImage image;
04164 if ( filename.IsEmpty() )
04165 {
04166 wxLogError( _( "CVG : bitmap file for a2dPatternFillData not specified or empty" ) );
04167 image = wxImage( 32, 32 );
04168 }
04169 else
04170 {
04171 m_filename = a2dGlobals->GetImagePathList().FindValidPath( filename );
04172 if ( m_filename.IsEmpty() )
04173 {
04174 wxLogError( _( "CVG : Could not load bitmap \"%s\" for a2dPatternFillData from path \"%s\" " ), filename.c_str(), a2dGlobals->GetImagePathList().GetAsString().c_str() );
04175 image = wxImage( 32, 32 );
04176 }
04177 else if ( ! image.LoadFile( m_filename, wxBITMAP_TYPE_BMP ) )
04178 {
04179 wxLogError( _( "CVG : Could not load bitmap %s for a2dPatternFillData" ), m_filename.c_str() );
04180 image = wxImage( 32, 32 );
04181 }
04182 }
04183 m_stipple = wxBitmap( image );
04184
04185 m_style = ( a2dFillStyle ) FillString2Style( parser.GetAttributeValue( wxT( "style" ), wxT("a2dFILL_STIPPLE") ) );
04186 SetStyle( m_style );
04187
04188 if ( m_style == a2dFILL_STIPPLE_MASK_OPAQUE || m_style == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
04189 {
04190 wxColour white( wxT( "WHITE" ) );
04191 wxColour black( wxT( "BLACK" ) );
04192
04193 wxMask* monochrome_mask = new wxMask( m_stipple, black );
04194 m_stipple.SetMask( monochrome_mask );
04195 }
04196 }
04197 else
04198 {}
04199 }
04200
04201 void a2dPatternFillData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
04202 {
04203 a2dTwoColourFillData::DoSave( parent, out, xmlparts, towrite );
04204 if ( xmlparts == a2dXmlSer_attrib )
04205 {
04206 if ( m_style != a2dFILL_STIPPLE )
04207 out.WriteAttribute( wxT( "style" ), FillStyle2String( GetStyle() ) );
04208
04209 wxString filename = a2dGlobals->GetImagePathList().FindValidPath( m_filename );
04210 if ( filename.IsEmpty() )
04211 {
04212
04213
04214 wxString fileTosave;
04215
04216 wxString* layerfile = a2dGeneralGlobals->GetVariablesHash().GetVariableString( wxT( "wxart2dlayers" ) );
04217 wxString* layerfiledir = a2dGeneralGlobals->GetVariablesHash().GetVariableString( wxT( "layerFileSavePath" ) );
04218
04219 if ( layerfile && !layerfile->IsEmpty() )
04220 {
04221 if ( !wxDirExists( *layerfiledir ) )
04222 wxMkdir( *layerfiledir );
04223 wxString mess = *layerfiledir + *layerfile + wxT( " directory does not exist, and could not be created" );
04224 wxASSERT_MSG( wxDirExists( *layerfiledir ) , mess );
04225
04226 fileTosave = *layerfiledir + wxFILE_SEP_PATH;
04227 }
04228
04229 if ( m_filename.IsEmpty() )
04230 {
04231 m_filename.Printf( _T( "canpat_%ld.bmp" ), wxGenNewId() );
04232 fileTosave += m_filename;
04233 }
04234 else
04235 fileTosave += wxFileNameFromPath( m_filename );
04236 bool isOke = m_stipple.SaveFile( fileTosave, wxBITMAP_TYPE_BMP );
04237 if ( !isOke )
04238 wxLogError( _( "Could not save bitmap %s for a2dPatternFillData" ), fileTosave.c_str() );
04239 out.WriteAttribute( wxT( "filename" ), wxFileNameFromPath( m_filename ) );
04240 }
04241 else
04242 out.WriteAttribute( wxT( "filename" ), wxFileNameFromPath(m_filename) );
04243 }
04244 else
04245 {}
04246
04247 }
04248 #endif //wxART2D_USE_CVGIO
04249
04250
04251
04252
04253
04254 a2dFill::a2dFill( void )
04255 {
04256 }
04257
04258 a2dFill::a2dFill( const wxColour& col, a2dFillStyle style )
04259 {
04260 m_refData = new a2dOneColourFillData( col, style );
04261 }
04262
04263 a2dFill::a2dFill( const wxColour& col, const wxColour& col2, a2dFillStyle style )
04264 {
04265 if ( style == a2dFILL_GRADIENT_FILL_XY_LINEAR )
04266 {
04267 m_refData = new a2dLinearGradientFillData( col, col2, 0,0,0,0 );
04268 }
04269 else if ( style == a2dFILL_GRADIENT_FILL_XY_RADIAL )
04270 {
04271 m_refData = new a2dRadialGradientFillData( col, col2, 0,0,0,0,0 );
04272 }
04273 else if ( style >= a2dFIRST_TWOCOL_HATCH && style <= a2dLAST_TWOCOL_HATCH )
04274 {
04275 m_refData = new a2dHatchFillData( col, col2, style );
04276 }
04277 else if ( style == a2dFILL_STIPPLE ||
04278 style == a2dFILL_STIPPLE_MASK_OPAQUE ||
04279 style == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT
04280 )
04281 {
04282 m_refData = new a2dPatternFillData( wxNullBitmap, style );
04283 }
04284 else
04285 {
04286 wxFAIL_MSG( _( "invalid style for in a2dFill for two colours" ) );
04287 }
04288 }
04289
04290 a2dFill::a2dFill( const wxColour& col, const wxColour& col2,
04291 double x1, double y1, double x2, double y2 )
04292 {
04293 m_refData = new a2dLinearGradientFillData( col, col2, x1, y1, x2, y2 );
04294 }
04295
04296 a2dFill::a2dFill( const wxColour& col, const wxColour& col2,
04297 double xfc, double yfc, double xe, double ye, double radius )
04298 {
04299 m_refData = new a2dRadialGradientFillData( col, col2, xfc, yfc, xe, ye, radius );
04300 }
04301
04302 a2dFill::a2dFill( const a2dFill& fill )
04303 :wxObject( fill )
04304 {
04305 }
04306
04307 a2dFill::a2dFill( const wxBitmap& stipple, a2dFillStyle style )
04308 {
04309 m_refData = new a2dPatternFillData( stipple, style );
04310 }
04311
04312 a2dFill::a2dFill( const wxBitmap& stipple, const wxColour& col, const wxColour& col2, a2dFillStyle style )
04313 {
04314 m_refData = new a2dPatternFillData( stipple, style );
04315 SetColour( col );
04316 SetColour2( col2 );
04317 }
04318
04319 a2dFill::a2dFill( const wxFileName& filename, a2dFillStyle style )
04320 {
04321 m_refData = new a2dPatternFillData( filename, style );
04322 }
04323
04324 a2dFill::a2dFill( const wxFileName& filename, const wxColour& col, const wxColour& col2, a2dFillStyle style )
04325 {
04326 m_refData = new a2dPatternFillData( filename, style );
04327 SetColour( col );
04328 SetColour2( col2 );
04329 }
04330
04331 a2dFill::a2dFill( const wxBrush& brush )
04332 {
04333 if ( brush == wxNullBrush )
04334 {
04335 }
04336 else if ( brush.GetStyle() == wxTRANSPARENT || brush.GetStyle() == wxSOLID || brush.IsHatch() )
04337 m_refData = new a2dOneColourFillData( brush );
04338 else if ( brush.GetStyle() == wxSTIPPLE )
04339 {
04340 m_refData = new a2dPatternFillData( *brush.GetStipple(), a2dFILL_STIPPLE );
04341 ((a2dPatternFillData*)m_refData)->SetColour( brush.GetColour() );
04342 }
04343 else if ( brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
04344 {
04345 m_refData = new a2dPatternFillData( *brush.GetStipple(), a2dFILL_STIPPLE_MASK_OPAQUE );
04346 ((a2dPatternFillData*)m_refData)->SetColour( brush.GetColour() );
04347 }
04348 }
04349
04350 a2dFill::~a2dFill( void )
04351 {
04352 }
04353
04354 a2dFillType a2dFill::GetType( void ) const
04355 {
04356 if ( !m_refData )
04357 return a2dFILL_NULL;
04358 return ( (a2dFillRefData*) m_refData )->GetType();
04359 }
04360
04361
04362 a2dFill& a2dFill::UnShare()
04363 {
04364 wxObject::UnShare();
04365 return *this;
04366 }
04367
04368 wxObjectRefData* a2dFill::CreateRefData() const
04369 {
04370 switch ( GetType() )
04371 {
04372 case a2dFILL_NULL:
04373 return new a2dOneColourFillData();
04374 case a2dFILL_ONE_COLOUR:
04375 return new a2dOneColourFillData();
04376 case a2dFILL_HATCH_TWO_COLOUR:
04377 return new a2dHatchFillData();
04378 case a2dFILL_GRADIENT_FILL_LINEAR:
04379 return new a2dLinearGradientFillData();
04380 case a2dFILL_GRADIENT_FILL_RADIAL:
04381 return new a2dRadialGradientFillData();
04382 case a2dFILL_BITMAP:
04383 return new a2dPatternFillData();
04384 default:
04385 break;
04386 }
04387 return NULL;
04388 }
04389
04390 wxObjectRefData* a2dFill::CloneRefData(const wxObjectRefData* data) const
04391 {
04392 switch ( ( (a2dFillRefData*) data )->GetType() )
04393 {
04394 case a2dFILL_NULL:
04395 return NULL;
04396 case a2dFILL_ONE_COLOUR:
04397 return new a2dOneColourFillData( *((const a2dOneColourFillData*)data ));
04398 case a2dFILL_HATCH_TWO_COLOUR:
04399 return new a2dHatchFillData( *((const a2dHatchFillData*)data ));
04400 case a2dFILL_GRADIENT_FILL_LINEAR:
04401 return new a2dLinearGradientFillData( *((const a2dLinearGradientFillData*)data ));
04402 case a2dFILL_GRADIENT_FILL_RADIAL:
04403 return new a2dRadialGradientFillData( *((const a2dRadialGradientFillData*)data ));
04404 case a2dFILL_BITMAP:
04405 return new a2dPatternFillData( *((const a2dPatternFillData*)data ));
04406 default:
04407 break;
04408 }
04409 return NULL;
04410 }
04411
04412 a2dPoint2D a2dFill::GetStart() const
04413 {
04414 wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_LINEAR, _T("No ref data") );
04415 return ((a2dLinearGradientFillData*)GetRefData())->GetStart();
04416 }
04417
04418 a2dPoint2D a2dFill::GetStop() const
04419 {
04420 wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_LINEAR, _T("No ref data") );
04421 return ((a2dLinearGradientFillData*)GetRefData())->GetStop();
04422 }
04423
04424 wxUint32 a2dFill::GetStamp() const
04425 {
04426 switch ( GetType() )
04427 {
04428 case a2dFILL_GRADIENT_FILL_LINEAR:
04429 return ((a2dLinearGradientFillData*)GetRefData())->GetStamp();
04430 case a2dFILL_GRADIENT_FILL_RADIAL:
04431 return ((a2dRadialGradientFillData*)GetRefData())->GetStamp();
04432 default:
04433 wxFAIL_MSG( _T("Not a gradient fill") );
04434 }
04435 return 0;
04436 }
04437
04438 a2dPoint2D a2dFill::GetCenter() const
04439 {
04440 wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_RADIAL, _T("No ref data") );
04441 return ((a2dRadialGradientFillData*)GetRefData())->GetCenter();
04442 }
04443
04444 a2dPoint2D a2dFill::GetFocal() const
04445 {
04446 wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_RADIAL, _T("No ref data") );
04447 return ((a2dRadialGradientFillData*)GetRefData())->GetFocal();
04448 }
04449
04450 double a2dFill::GetRadius() const
04451 {
04452 wxASSERT_MSG( GetType() == a2dFILL_GRADIENT_FILL_RADIAL, _T("No ref data") );
04453 return ((a2dRadialGradientFillData*)GetRefData())->GetRadius();
04454 }
04455
04456 void a2dFill::SetAlpha( wxUint8 val )
04457 {
04458 AllocExclusive();
04459
04460 switch ( GetType() )
04461 {
04462 case a2dFILL_NULL:
04463 UnRef();
04464 break;
04465 case a2dFILL_ONE_COLOUR:
04466 {
04467 wxASSERT_MSG( m_refData, _T("No ref data") );
04468 wxColour newcol = ((a2dOneColourFillData*)GetRefData())->GetColour();
04469 newcol.Set( newcol.Red(), newcol.Green(), newcol.Blue(), val );
04470 ((a2dOneColourFillData*)GetRefData())->SetColour( newcol );
04471 break;
04472 }
04473 case a2dFILL_HATCH_TWO_COLOUR:
04474 case a2dFILL_GRADIENT_FILL_LINEAR:
04475 case a2dFILL_GRADIENT_FILL_RADIAL:
04476 case a2dFILL_BITMAP:
04477 {
04478 wxASSERT_MSG( m_refData, _T("No ref data") );
04479 wxColour newcol = ((a2dTwoColourFillData*)GetRefData())->GetColour();
04480 newcol.Set( newcol.Red(), newcol.Green(), newcol.Blue(), val );
04481 ((a2dTwoColourFillData*)GetRefData())->SetColour( newcol );
04482 break;
04483 }
04484 default:
04485 break;
04486 }
04487 }
04488
04489 wxUint8 a2dFill::GetAlpha() const
04490 {
04491 switch ( GetType() )
04492 {
04493 case a2dFILL_NULL:
04494 return a2dFILL_NULLFILL;
04495 case a2dFILL_ONE_COLOUR:
04496 wxASSERT_MSG( m_refData, _T("No ref data") );
04497 return ((a2dOneColourFillData*)GetRefData())->GetColour().Alpha();
04498 break;
04499 case a2dFILL_HATCH_TWO_COLOUR:
04500 case a2dFILL_GRADIENT_FILL_LINEAR:
04501 case a2dFILL_GRADIENT_FILL_RADIAL:
04502 case a2dFILL_BITMAP:
04503 wxASSERT_MSG( m_refData, _T("No ref data") );
04504 return ((a2dTwoColourFillData*)GetRefData())->GetColour().Alpha();
04505 break;
04506 default:
04507 break;
04508 }
04509 return 255;
04510 }
04511
04512
04513 a2dFillStyle a2dFill::GetStyle() const
04514 {
04515 switch ( GetType() )
04516 {
04517 case a2dFILL_NULL:
04518 return a2dFILL_NULLFILL;
04519 case a2dFILL_ONE_COLOUR:
04520 wxASSERT_MSG( m_refData, _T("No ref data") );
04521 return ((a2dOneColourFillData*)GetRefData())->GetStyle();
04522 break;
04523 case a2dFILL_HATCH_TWO_COLOUR:
04524 case a2dFILL_GRADIENT_FILL_LINEAR:
04525 case a2dFILL_GRADIENT_FILL_RADIAL:
04526 case a2dFILL_BITMAP:
04527 wxASSERT_MSG( m_refData, _T("No ref data") );
04528 return ((a2dTwoColourFillData*)GetRefData())->GetStyle();
04529 break;
04530 default:
04531 break;
04532 }
04533 return a2dFILL_NULLFILL;
04534 }
04535
04536 void a2dFill::SetStyle( a2dFillStyle style )
04537 {
04538 a2dFillStyle cur_style = GetStyle();
04539 if ( cur_style == style )
04540 return;
04541
04542 AllocExclusive();
04543
04544 a2dFillType type = GetTypeForStyle( style );
04545
04546 if ( type == GetType() )
04547 {
04548 switch ( GetType() )
04549 {
04550 case a2dFILL_NULL:
04551 UnRef();
04552 break;
04553 case a2dFILL_ONE_COLOUR:
04554 wxASSERT_MSG( m_refData, _T("No ref data") );
04555 ((a2dOneColourFillData*)GetRefData())->SetStyle( style );
04556 break;
04557 case a2dFILL_HATCH_TWO_COLOUR:
04558 wxASSERT_MSG( m_refData, _T("No ref data") );
04559 ((a2dHatchFillData*)GetRefData())->SetStyle( style );
04560 break;
04561 case a2dFILL_GRADIENT_FILL_LINEAR:
04562 wxASSERT_MSG( m_refData, _T("No ref data") );
04563 ((a2dLinearGradientFillData*)GetRefData())->SetStyle( style );
04564 break;
04565 case a2dFILL_GRADIENT_FILL_RADIAL:
04566 wxASSERT_MSG( m_refData, _T("No ref data") );
04567 ((a2dRadialGradientFillData*)GetRefData())->SetStyle( style );
04568 break;
04569 case a2dFILL_BITMAP:
04570 wxASSERT_MSG( m_refData, _T("No ref data") );
04571 ((a2dPatternFillData*)GetRefData())->SetStyle( style );
04572 break;
04573 default:
04574 break;
04575 }
04576 }
04577 else
04578 {
04579 a2dFillRefData* newrefdata = NULL;
04580 switch ( type )
04581 {
04582 case a2dFILL_NULL:
04583 break;
04584 case a2dFILL_ONE_COLOUR:
04585 newrefdata = new a2dOneColourFillData( GetColour(), style );
04586 break;
04587 case a2dFILL_HATCH_TWO_COLOUR:
04588 newrefdata = new a2dHatchFillData( GetColour(), GetColour2(), style );
04589 break;
04590 case a2dFILL_GRADIENT_FILL_LINEAR:
04591 newrefdata = new a2dLinearGradientFillData( GetColour(), GetColour2(), 0, 0, 0, 0 );
04592 break;
04593 case a2dFILL_GRADIENT_FILL_RADIAL:
04594 newrefdata = new a2dRadialGradientFillData( GetColour(), GetColour2(), 0, 0, 0, 0, 0 );
04595 break;
04596 case a2dFILL_BITMAP:
04597 newrefdata = new a2dPatternFillData( wxNullBitmap, style );
04598 break;
04599 default:
04600 break;
04601 }
04602 UnRef();
04603 m_refData = newrefdata;
04604 }
04605 }
04606
04607 a2dFillType a2dFill::GetTypeForStyle( a2dFillStyle style ) const
04608 {
04609 if ( style == a2dFILL_NULLFILL || style == a2dFILL_LAYER || style == a2dFILL_INHERIT )
04610 return a2dFILL_NULL;
04611 else if ( style == a2dFILL_TRANSPARENT && GetType() != a2dFILL_NULL )
04612 return GetType();
04613 else if ( style == a2dFILL_SOLID || style == a2dFILL_TRANSPARENT || style == a2dFILL_NULLFILL )
04614 return a2dFILL_ONE_COLOUR;
04615 else if ( style >= a2dFIRST_TWOCOL_HATCH && style <= a2dLAST_TWOCOL_HATCH )
04616 return a2dFILL_HATCH_TWO_COLOUR;
04617 else if ( style >= a2dFIRST_HATCH && style <= a2dLAST_HATCH )
04618 return a2dFILL_ONE_COLOUR;
04619 else if ( style == a2dFILL_GRADIENT_FILL_XY_LINEAR )
04620 return a2dFILL_GRADIENT_FILL_LINEAR;
04621 else if ( style == a2dFILL_GRADIENT_FILL_XY_RADIAL )
04622 return a2dFILL_GRADIENT_FILL_RADIAL;
04623 else if ( style == a2dFILL_STIPPLE ||
04624 style == a2dFILL_STIPPLE_MASK_OPAQUE ||
04625 style == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT
04626 )
04627 return a2dFILL_BITMAP;
04628 else
04629 wxFAIL_MSG( _( "invalid style for in a2dFill" ) );
04630
04631 return a2dFILL_NULL;
04632 }
04633
04634 void a2dFill::SetColour2( const wxColour& col )
04635 {
04636 AllocExclusive();
04637 switch ( GetType() )
04638 {
04639 case a2dFILL_NULL:
04640 UnRef();
04641 break;
04642 case a2dFILL_HATCH_TWO_COLOUR:
04643 case a2dFILL_GRADIENT_FILL_LINEAR:
04644 case a2dFILL_GRADIENT_FILL_RADIAL:
04645 case a2dFILL_BITMAP:
04646 wxASSERT_MSG( m_refData, _T("No ref data") );
04647 ((a2dTwoColourFillData*)GetRefData())->SetColour2( col );
04648 break;
04649 default:
04650 break;
04651 }
04652 }
04653
04654 wxColour a2dFill::GetColour2() const
04655 {
04656 switch ( GetType() )
04657 {
04658 case a2dFILL_NULL:
04659 break;
04660 case a2dFILL_HATCH_TWO_COLOUR:
04661 case a2dFILL_GRADIENT_FILL_LINEAR:
04662 case a2dFILL_GRADIENT_FILL_RADIAL:
04663 case a2dFILL_BITMAP:
04664 wxASSERT_MSG( m_refData, _T("No ref data") );
04665 return ((a2dTwoColourFillData*)GetRefData())->GetColour2();
04666 break;
04667 default:
04668 break;
04669 }
04670 return wxColour( 0,0,0,0);
04671 }
04672
04673 void a2dFill::SetColour( const wxColour& col )
04674 {
04675 AllocExclusive();
04676 switch ( GetType() )
04677 {
04678 case a2dFILL_NULL:
04679 UnRef();
04680 break;
04681 case a2dFILL_ONE_COLOUR:
04682 wxASSERT_MSG( m_refData, _T("No ref data") );
04683 ((a2dOneColourFillData*)GetRefData())->SetColour( col );
04684 break;
04685 case a2dFILL_HATCH_TWO_COLOUR:
04686 case a2dFILL_GRADIENT_FILL_LINEAR:
04687 case a2dFILL_GRADIENT_FILL_RADIAL:
04688 case a2dFILL_BITMAP:
04689 wxASSERT_MSG( m_refData, _T("No ref data") );
04690 ((a2dTwoColourFillData*)GetRefData())->SetColour( col );
04691 break;
04692 default:
04693 break;
04694 }
04695 }
04696
04697 wxColour a2dFill::GetColour() const
04698 {
04699 switch ( GetType() )
04700 {
04701 case a2dFILL_NULL:
04702 break;
04703 case a2dFILL_ONE_COLOUR:
04704 wxASSERT_MSG( m_refData, _T("No ref data") );
04705 return ((a2dOneColourFillData*)GetRefData())->GetColour();
04706 break;
04707 case a2dFILL_HATCH_TWO_COLOUR:
04708 case a2dFILL_GRADIENT_FILL_LINEAR:
04709 case a2dFILL_GRADIENT_FILL_RADIAL:
04710 case a2dFILL_BITMAP:
04711 wxASSERT_MSG( m_refData, _T("No ref data") );
04712 return ((a2dTwoColourFillData*)GetRefData())->GetColour();
04713 break;
04714 default:
04715 break;
04716 }
04717 return *wxBLACK;
04718 }
04719
04720 void a2dFill::SetStipple( const wxBitmap& stipple )
04721 {
04722 AllocExclusive();
04723 if ( GetType() == a2dFILL_BITMAP )
04724 ((a2dPatternFillData*)m_refData)->SetStipple( stipple );
04725 else
04726 {
04727 UnRef();
04728 m_refData = new a2dPatternFillData( stipple, a2dFILL_STIPPLE );
04729 }
04730 }
04731
04732 const wxBitmap& a2dFill::GetStipple() const
04733 {
04734 if ( GetType() == a2dFILL_BITMAP )
04735 {
04736 wxASSERT_MSG( m_refData, _T("No ref data") );
04737 return ((const a2dPatternFillData*)m_refData)->GetStipple();
04738 }
04739 else
04740 {
04741 return wxNullBitmap;
04742 }
04743 }
04744
04745 void a2dFill::SetFilling( bool OnOff )
04746 {
04747 if ( ((a2dFillRefData*)GetRefData())->m_fillOn == OnOff)
04748 return;
04749
04750 AllocExclusive();
04751 ((a2dFillRefData*)GetRefData())->m_fillOn = OnOff;
04752 }
04753
04754 bool a2dFill::GetFilling() const
04755 {
04756 switch ( GetType() )
04757 {
04758 case a2dFILL_NULL:
04759 return false;
04760 }
04761 return ((a2dFillRefData*)GetRefData())->m_fillOn;
04762 }
04763
04764 #if wxART2D_USE_CVGIO
04765 void a2dFill::Load( wxObject* parent, a2dIOHandlerXmlSerIn& parser )
04766 {
04767 a2dFillType type;
04768
04769 parser.Require( START_TAG, wxT("o") );
04770
04771 wxString classname = parser.GetAttributeValue( wxT("classname") );
04772 if ( classname == wxT("a2dOneColourFill") )
04773 type = a2dFILL_ONE_COLOUR;
04774 else if ( classname == wxT("a2dLinearGradientFill") )
04775 type = a2dFILL_GRADIENT_FILL_LINEAR;
04776 else if ( classname == wxT("a2dRadialGradientFill") )
04777 type = a2dFILL_GRADIENT_FILL_RADIAL;
04778 else if ( classname == wxT("a2dPatternFill") )
04779 type = a2dFILL_BITMAP;
04780 else
04781 {
04782 wxString stype = parser.GetAttributeValue( wxT( "type" ), wxT( "a2dFILL_NULL" ) );
04783 if ( stype == wxT("a2dFILL_NULL") )
04784 type = a2dFILL_NULL;
04785 else if ( stype == wxT("a2dFILL_ONE_COLOUR") )
04786 type = a2dFILL_ONE_COLOUR;
04787 else if ( stype == wxT("a2dFILL_HATCH_TWO_COLOUR") )
04788 type = a2dFILL_HATCH_TWO_COLOUR;
04789 else if ( stype == wxT("a2dFILL_GRADIENT_FILL_LINEAR") )
04790 type = a2dFILL_GRADIENT_FILL_LINEAR;
04791 else if ( stype == wxT("a2dFILL_GRADIENT_FILL_RADIAL") )
04792 type = a2dFILL_GRADIENT_FILL_RADIAL;
04793 else if ( stype == wxT("a2dFILL_BITMAP") )
04794 type = a2dFILL_BITMAP;
04795 }
04796
04797 switch ( type )
04798 {
04799 case a2dFILL_NULL:
04800 break;
04801 case a2dFILL_ONE_COLOUR:
04802 m_refData = new a2dOneColourFillData( *wxBLACK );
04803 break;
04804 case a2dFILL_HATCH_TWO_COLOUR:
04805 m_refData = new a2dHatchFillData( *wxBLACK, *wxBLACK, a2dFILL_TWOCOL_BDIAGONAL_HATCH );
04806 break;
04807 case a2dFILL_GRADIENT_FILL_LINEAR:
04808 m_refData = new a2dLinearGradientFillData( *wxBLACK, *wxBLACK, 0, 0, 0, 0 );
04809 break;
04810 case a2dFILL_GRADIENT_FILL_RADIAL:
04811 m_refData = new a2dRadialGradientFillData( *wxBLACK, *wxBLACK, 0, 0, 0, 0, 0 );
04812 break;
04813 case a2dFILL_BITMAP:
04814 m_refData = new a2dPatternFillData( wxNullBitmap );
04815 break;
04816 default:
04817 break;
04818 }
04819
04820 if ( GetRefData() )
04821 {
04822 ((a2dFillRefData*)GetRefData())->DoLoad( parent, parser, a2dXmlSer_attrib );
04823 parser.Next();
04824
04825 ((a2dFillRefData*)GetRefData())->DoLoad( parent, parser, a2dXmlSer_Content );
04826 }
04827 else
04828 parser.Next();
04829
04830 parser.Require( END_TAG, wxT("o") );
04831 parser.Next();
04832 }
04833
04834 void a2dFill::Save( wxObject* parent, a2dIOHandlerXmlSerOut &out , a2dObjectList* towrite )
04835 {
04836 out.WriteStartElementAttributes( wxT("o") );
04837 out.WriteAttribute( wxT("classname"), GetClassInfo()->GetClassName() );
04838
04839 switch ( GetType() )
04840 {
04841 case a2dFILL_NULL:
04842 break;
04843 case a2dFILL_ONE_COLOUR:
04844 out.WriteAttribute( wxT("type"), wxT("a2dFILL_ONE_COLOUR") );
04845 break;
04846 case a2dFILL_HATCH_TWO_COLOUR:
04847 out.WriteAttribute( wxT("type"), wxT("a2dFILL_HATCH_TWO_COLOUR") );
04848 break;
04849 case a2dFILL_GRADIENT_FILL_LINEAR:
04850 out.WriteAttribute( wxT("type"), wxT("a2dFILL_GRADIENT_FILL_LINEAR") );
04851 break;
04852 case a2dFILL_GRADIENT_FILL_RADIAL:
04853 out.WriteAttribute( wxT("type"), wxT("a2dFILL_GRADIENT_FILL_RADIAL") );
04854 break;
04855 case a2dFILL_BITMAP:
04856 out.WriteAttribute( wxT("type"), wxT("a2dFILL_BITMAP") );
04857 break;
04858 default:
04859 break;
04860 }
04861
04862 if ( GetRefData() )
04863 ((a2dFillRefData*)GetRefData())->DoSave( parent, out, a2dXmlSer_attrib, towrite );
04864 out.WriteEndAttributes();
04865 if ( GetRefData() )
04866 ((a2dFillRefData*)GetRefData())->DoSave( parent, out, a2dXmlSer_Content, towrite );
04867 out.WriteEndElement();
04868 }
04869 #endif //wxART2D_USE_CVGIO
04870
04871
04872
04873
04874
04875
04876 a2dStrokeProperty::a2dStrokeProperty(): a2dNamedProperty()
04877 {
04878 }
04879
04880 a2dStrokeProperty::a2dStrokeProperty( const a2dPropertyIdStroke* id, const a2dStroke& value )
04881 :a2dNamedProperty( id )
04882 {
04883 m_value = value;
04884 }
04885
04886 a2dStrokeProperty::~a2dStrokeProperty()
04887 {
04888 }
04889
04890 a2dStrokeProperty::a2dStrokeProperty( const a2dStrokeProperty *ori )
04891 : a2dNamedProperty( *ori )
04892 {
04893 m_value = ori->m_value;
04894 }
04895
04896 a2dStrokeProperty::a2dStrokeProperty( const a2dStrokeProperty &other )
04897 : a2dNamedProperty( other )
04898 {
04899 m_value = other.m_value;
04900 }
04901
04902 a2dNamedProperty *a2dStrokeProperty::Clone( a2dObject::CloneOptions WXUNUSED(options) ) const
04903 {
04904 return new a2dStrokeProperty(*this );
04905 };
04906
04907 void a2dStrokeProperty::Assign( const a2dNamedProperty &other )
04908 {
04909 a2dStrokeProperty *propcast = wxStaticCast( &other, a2dStrokeProperty);
04910 m_value = propcast->m_value;
04911 }
04912
04913 a2dStrokeProperty *a2dStrokeProperty::CreatePropertyFromString( const a2dPropertyIdStroke* id, const wxString& WXUNUSED(value) )
04914 {
04915 return 0;
04916 }
04917
04918 #if wxART2D_USE_CVGIO
04919 void a2dStrokeProperty::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
04920 {
04921 a2dNamedProperty::DoSave( parent, out, xmlparts, towrite );
04922 if ( xmlparts == a2dXmlSer_attrib )
04923 {
04924 }
04925 else
04926 {
04927 m_value.Save( parent, out, towrite );
04928 }
04929 }
04930
04931 void a2dStrokeProperty::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
04932 {
04933 a2dNamedProperty::DoLoad( parent, parser, xmlparts );
04934 if ( xmlparts == a2dXmlSer_attrib )
04935 {
04936 }
04937 else
04938 {
04939 m_value.Load( parent, parser );
04940 }
04941 }
04942 #endif //wxART2D_USE_CVGIO
04943
04944 void a2dStrokeProperty::SetValue( const a2dStroke& value )
04945 {
04946 m_value = value;
04947 }
04948
04949 wxString a2dStrokeProperty::StringRepresentation() const
04950 {
04951 return wxT("VOID");
04952 }
04953
04954 wxString a2dStrokeProperty::StringValueRepresentation() const
04955 {
04956 return wxT("VOID");
04957 }
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967 class A2DARTBASEDLLEXP a2dStrokeRefData : public wxObjectRefData
04968 {
04969 public:
04970
04971 virtual a2dStrokeType GetType( void ) const { return a2dSTROKE_NULL; }
04972
04973
04974 a2dStrokeRefData()
04975 {
04976 }
04977
04978 a2dStrokeRefData( const a2dStrokeRefData& other )
04979 : wxObjectRefData()
04980 {
04981 }
04982
04983 #if wxART2D_USE_CVGIO
04984
04985 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList* towrite ) = 0;
04986
04987 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts ) = 0;
04988 #endif //wxART2D_USE_CVGIO
04989
04990 };
04991
04992
04993
04994
04995
04996
04997 wxString StrokeStyle2String( a2dStrokeStyle style )
04998 {
04999 switch ( style )
05000 {
05001 case a2dSTROKE_SOLID: return wxT("a2dSTROKE_SOLID");
05002 case a2dSTROKE_TRANSPARENT: return wxT("a2dSTROKE_TRANSPARENT");
05003 case a2dSTROKE_DOT: return wxT("a2dSTROKE_DOT");
05004 case a2dSTROKE_LONG_DASH: return wxT("a2dSTROKE_LONG_DASH");
05005 case a2dSTROKE_SHORT_DASH: return wxT("a2dSTROKE_SHORT_DASH");
05006 case a2dSTROKE_DOT_DASH: return wxT("a2dSTROKE_DOT_DASH");
05007 case a2dSTROKE_USER_DASH: return wxT("a2dSTROKE_USER_DASH");
05008 case a2dSTROKE_BDIAGONAL_HATCH: return wxT("a2dSTROKE_BDIAGONAL_HATCH");
05009 case a2dSTROKE_CROSSDIAG_HATCH: return wxT("a2dSTROKE_CROSSDIAG_HATCH");
05010 case a2dSTROKE_FDIAGONAL_HATCH: return wxT("a2dSTROKE_FDIAGONAL_HATCH");
05011 case a2dSTROKE_CROSS_HATCH: return wxT("a2dSTROKE_CROSS_HATCH");
05012 case a2dSTROKE_HORIZONTAL_HATCH: return wxT("a2dSTROKE_HORIZONTAL_HATCH");
05013 case a2dSTROKE_VERTICAL_HATCH: return wxT("a2dSTROKE_VERTICAL_HATCH");
05014 case a2dSTROKE_STIPPLE: return wxT("a2dSTROKE_STIPPLE");
05015 case a2dSTROKE_STIPPLE_MASK_OPAQUE: return wxT("a2dSTROKE_STIPPLE_MASK_OPAQUE");
05016 case a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT: return wxT("a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT");
05017
05018
05019
05020 case a2dSTROKE_INHERIT: return wxT("a2dSTROKE_INHERIT");
05021 case a2dSTROKE_LAYER: return wxT("a2dSTROKE_LAYER");
05022 case a2dSTROKE_NULLSTROKE: return wxT("a2dSTROKE_NULLSTROKE");
05023
05024 default:
05025 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("CVG : invalid style") );
05026 }
05027 return wxT("a2dSTROKE_NULLFILL");
05028 }
05029
05030
05031 a2dStrokeStyle StrokeString2Style( const wxString& stylestr )
05032 {
05033 if ( stylestr == wxT("a2dSTROKE_SOLID") )
05034 return a2dSTROKE_SOLID;
05035 if ( stylestr == wxT("a2dSTROKE_TRANSPARENT") )
05036 return a2dSTROKE_TRANSPARENT;
05037 if ( stylestr == wxT("a2dSTROKE_DOT") )
05038 return a2dSTROKE_DOT;
05039 if ( stylestr == wxT("a2dSTROKE_LONG_DASH") )
05040 return a2dSTROKE_LONG_DASH;
05041 if ( stylestr == wxT("a2dSTROKE_SHORT_DASH") )
05042 return a2dSTROKE_SHORT_DASH;
05043 if ( stylestr == wxT("a2dSTROKE_DOT_DASH") )
05044 return a2dSTROKE_DOT_DASH;
05045 if ( stylestr == wxT("a2dSTROKE_USER_DASH") )
05046 return a2dSTROKE_USER_DASH;
05047 if ( stylestr == wxT("a2dSTROKE_BDIAGONAL_HATCH") )
05048 return a2dSTROKE_BDIAGONAL_HATCH;
05049 if ( stylestr == wxT("a2dSTROKE_CROSSDIAG_HATCH") )
05050 return a2dSTROKE_CROSSDIAG_HATCH;
05051 if ( stylestr == wxT("a2dSTROKE_FDIAGONAL_HATCH") )
05052 return a2dSTROKE_FDIAGONAL_HATCH;
05053 if ( stylestr == wxT("a2dSTROKE_CROSS_HATCH") )
05054 return a2dSTROKE_CROSS_HATCH;
05055 if ( stylestr == wxT("a2dSTROKE_HORIZONTAL_HATCH") )
05056 return a2dSTROKE_HORIZONTAL_HATCH;
05057 if ( stylestr == wxT("a2dSTROKE_VERTICAL_HATCH") )
05058 return a2dSTROKE_VERTICAL_HATCH;
05059 if ( stylestr == wxT("a2dSTROKE_STIPPLE") )
05060 return a2dSTROKE_STIPPLE;
05061 if ( stylestr == wxT("a2dSTROKE_STIPPLE_MASK_OPAQUE") )
05062 return a2dSTROKE_STIPPLE_MASK_OPAQUE;
05063 if ( stylestr == wxT("a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT") )
05064 return a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT;
05065
05066
05067
05068
05069
05070
05071
05072
05073 if ( stylestr == wxT("a2dSTROKE_INHERIT") )
05074 return a2dSTROKE_INHERIT;
05075 if ( stylestr == wxT("a2dSTROKE_LAYER") )
05076 return a2dSTROKE_LAYER;
05077 if ( stylestr == wxT("a2dSTROKE_NULLSTROKE") )
05078 return a2dSTROKE_NULLSTROKE;
05079
05080 if ( !stylestr.IsEmpty() )
05081 {
05082 long num;
05083 stylestr.ToLong( &num );
05084 return ( a2dStrokeStyle ) num;
05085 }
05086
05087 a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _("CVG : invalid style %s"), stylestr.c_str() );
05088
05089 return a2dSTROKE_NULLSTROKE;
05090 }
05091
05092
05093
05094
05095
05096
05097
05098
05099 class A2DARTBASEDLLEXP a2dOneColourStrokeData : public a2dStrokeRefData
05100 {
05101
05102 private:
05103
05104 friend class a2dStroke;
05105
05106 public:
05107
05108 virtual a2dStrokeType GetType( void ) const { return a2dSTROKE_ONE_COLOUR; }
05109
05110 protected:
05111
05112
05113 a2dOneColourStrokeData( void );
05114
05115 a2dOneColourStrokeData( const a2dOneColourStrokeData& fill );
05116
05117
05118 a2dOneColourStrokeData( const wxColour& col, a2dStrokeStyle style = a2dSTROKE_SOLID );
05119
05120 a2dOneColourStrokeData( const wxPen& stroke );
05121
05122
05123 ~a2dOneColourStrokeData( void ){}
05124
05125 static a2dOneColourStrokeData* Create( const wxColour& col, a2dStrokeStyle style = a2dSTROKE_SOLID );
05126
05127 void SetColour( const wxColour& col ) { m_colour1 = col; }
05128
05129
05130 wxColour GetColour() const { return m_colour1; }
05131
05132 void SetJoin( wxPenJoin join_style ) { m_join = join_style; }
05133
05134 void SetCap( wxPenCap cap_style ) { m_cap = cap_style; }
05135
05136 wxPenCap GetCap() { return m_cap; }
05137
05138 wxPenJoin GetJoin() { return m_join; }
05139
05140
05141 void SetWidth( float width ) { m_width = width; }
05142
05143
05144
05145 virtual float GetWidth() const { return m_width; }
05146
05147 virtual float GetExtend() const { return m_width; }
05148
05149
05150 void SetPixelStroke( bool pixelstroke ) { m_pixelstroke = pixelstroke; }
05151
05152
05153 inline bool GetPixelStroke() const { return m_pixelstroke; }
05154
05155 a2dStrokeStyle GetStyle( void ) const;
05156
05157 void SetStyle( a2dStrokeStyle style );
05158
05159 #if wxART2D_USE_CVGIO
05160 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
05161 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
05162 #endif //wxART2D_USE_CVGIO
05163
05164 wxColour m_colour1;
05165
05166
05167 float m_width;
05168
05169
05170 bool m_pixelstroke;
05171
05172
05173 wxPenJoin m_join;
05174
05175
05176 wxPenCap m_cap;
05177
05178 a2dDash *m_dash;
05179
05180 a2dStrokeStyle m_style;
05181
05182 };
05183
05184 a2dOneColourStrokeData* a2dOneColourStrokeData::Create( const wxColour& col, a2dStrokeStyle style )
05185 {
05186 return new a2dOneColourStrokeData( col, style );
05187 }
05188
05189 a2dOneColourStrokeData::a2dOneColourStrokeData( void )
05190 : a2dStrokeRefData()
05191 {
05192 m_style = a2dSTROKE_SOLID;
05193 m_colour1 = *wxBLACK;
05194 m_join = wxJOIN_ROUND;
05195 m_cap = wxCAP_ROUND;
05196
05197 m_pixelstroke = false;
05198 m_width = 0.0;
05199
05200 }
05201
05202 a2dOneColourStrokeData::a2dOneColourStrokeData( const wxColour& col, a2dStrokeStyle style )
05203 : a2dStrokeRefData()
05204 {
05205 m_colour1 = col;
05206 m_join = wxJOIN_ROUND;
05207 m_cap = wxCAP_ROUND;
05208
05209 m_pixelstroke = false;
05210 m_width = 0.0;
05211
05212 switch( style )
05213 {
05214 case a2dSTROKE_SOLID:
05215 case a2dSTROKE_TRANSPARENT:
05216 case a2dSTROKE_DOT:
05217 case a2dSTROKE_DOT_DASH:
05218 case a2dSTROKE_LONG_DASH:
05219 case a2dSTROKE_SHORT_DASH:
05220 case a2dSTROKE_USER_DASH:
05221 case a2dSTROKE_BDIAGONAL_HATCH:
05222 case a2dSTROKE_CROSSDIAG_HATCH:
05223 case a2dSTROKE_FDIAGONAL_HATCH:
05224 case a2dSTROKE_CROSS_HATCH:
05225 case a2dSTROKE_HORIZONTAL_HATCH:
05226 case a2dSTROKE_VERTICAL_HATCH:
05227 case a2dSTROKE_NULLSTROKE:
05228 m_style = style;
05229 break;
05230
05231 case a2dSTROKE_STIPPLE:
05232 case a2dSTROKE_STIPPLE_MASK_OPAQUE:
05233 case a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT:
05234 m_style = style;
05235 break;
05236
05237 default:
05238 wxFAIL_MSG( _( "invalid style for a2dStroke" ) );
05239 }
05240 }
05241
05242 a2dOneColourStrokeData::a2dOneColourStrokeData( const wxPen& stroke )
05243 : a2dStrokeRefData()
05244 {
05245 m_join = stroke.GetJoin();
05246 m_cap = stroke.GetCap();
05247
05248 m_colour1 = stroke.GetColour();
05249
05250 m_pixelstroke = true;
05251 if ( stroke != wxNullPen )
05252 {
05253 m_width = ( float ) stroke.GetWidth();
05254 switch( stroke.GetStyle() )
05255 {
05256 case wxSOLID: m_style = a2dSTROKE_SOLID;
05257 break;
05258 case wxTRANSPARENT: m_style = a2dSTROKE_TRANSPARENT;
05259 break;
05260 case wxDOT: m_style = a2dSTROKE_DOT;
05261 break;
05262 case wxLONG_DASH: m_style = a2dSTROKE_LONG_DASH;
05263 break;
05264 case wxSHORT_DASH: m_style = a2dSTROKE_SHORT_DASH;
05265 break;
05266 case wxDOT_DASH: m_style = a2dSTROKE_DOT_DASH;
05267 break;
05268 case wxBDIAGONAL_HATCH: m_style = a2dSTROKE_BDIAGONAL_HATCH;
05269 break;
05270 case wxCROSSDIAG_HATCH: m_style = a2dSTROKE_CROSSDIAG_HATCH;
05271 break;
05272 case wxFDIAGONAL_HATCH: m_style = a2dSTROKE_FDIAGONAL_HATCH;
05273 break;
05274 case wxCROSS_HATCH: m_style = a2dSTROKE_CROSS_HATCH;
05275 break;
05276 case wxHORIZONTAL_HATCH: m_style = a2dSTROKE_HORIZONTAL_HATCH;
05277 break;
05278 case wxVERTICAL_HATCH: m_style = a2dSTROKE_VERTICAL_HATCH;
05279 break;
05280 default:
05281 wxFAIL_MSG( _( "invalid style for a2dOneColourStroke" ) );
05282 }
05283 }
05284 else
05285 {
05286 m_width = 0;
05287 }
05288 }
05289
05290 a2dOneColourStrokeData::a2dOneColourStrokeData( const a2dOneColourStrokeData& other )
05291 : a2dStrokeRefData( other )
05292 {
05293 m_colour1 = other.m_colour1;
05294 m_style = other.m_style;
05295 m_join = other.m_join;
05296 m_cap = other.m_cap;
05297 m_pixelstroke = other.m_pixelstroke;
05298 m_width = other.m_width;
05299 m_dash = other.m_dash;
05300 }
05301
05302 a2dStrokeStyle a2dOneColourStrokeData::GetStyle() const
05303 {
05304 return m_style;
05305 }
05306
05307 void a2dOneColourStrokeData::SetStyle( a2dStrokeStyle style )
05308 {
05309 switch( style )
05310 {
05311 case a2dSTROKE_SOLID:
05312 case a2dSTROKE_TRANSPARENT:
05313 case a2dSTROKE_DOT:
05314 case a2dSTROKE_DOT_DASH:
05315 case a2dSTROKE_LONG_DASH:
05316 case a2dSTROKE_SHORT_DASH:
05317 case a2dSTROKE_USER_DASH:
05318 case a2dSTROKE_BDIAGONAL_HATCH:
05319 case a2dSTROKE_CROSSDIAG_HATCH:
05320 case a2dSTROKE_FDIAGONAL_HATCH:
05321 case a2dSTROKE_CROSS_HATCH:
05322 case a2dSTROKE_HORIZONTAL_HATCH:
05323 case a2dSTROKE_VERTICAL_HATCH:
05324 case a2dSTROKE_NULLSTROKE:
05325 m_style = style;
05326 break;
05327
05328 case a2dSTROKE_STIPPLE:
05329 case a2dSTROKE_STIPPLE_MASK_OPAQUE:
05330 case a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT:
05331 m_style = style;
05332 break;
05333
05334 default:
05335 wxFAIL_MSG( _( "invalid style for a2dStroke" ) );
05336 }
05337 }
05338
05339
05340 #if wxART2D_USE_CVGIO
05341 void a2dOneColourStrokeData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
05342 {
05343 if ( xmlparts == a2dXmlSer_attrib )
05344 {
05345 if ( m_style != a2dSTROKE_SOLID )
05346 out.WriteAttribute( wxT( "style" ), StrokeStyle2String( GetStyle() ) );
05347
05348 if ( m_style != a2dSTROKE_TRANSPARENT )
05349 {
05350 wxString strokeColour = wxTheColourDatabase->FindName( m_colour1 );
05351 if ( strokeColour.IsEmpty() )
05352 {
05353 out.WriteAttribute( wxT( "colour" ), wxT( "#" ) + ColourToHex( m_colour1 ) );
05354 }
05355 else
05356 {
05357 out.WriteAttribute( wxT( "colour" ), strokeColour );
05358 }
05359
05360 if ( GetPixelStroke() )
05361 {
05362 out.WriteAttribute( wxT( "pixelwidth" ), GetPixelStroke() );
05363 }
05364
05365 if ( m_width != 0 )
05366 {
05367 out.WriteAttribute( wxT( "width" ), m_width );
05368 }
05369 }
05370 }
05371 else
05372 {}
05373 }
05374
05375 void a2dOneColourStrokeData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
05376 {
05377 if ( xmlparts == a2dXmlSer_attrib )
05378 {
05379 m_style = ( a2dStrokeStyle ) StrokeString2Style( parser.GetAttributeValue( wxT( "style" ), wxT("a2dSTROKE_SOLID") ) );
05380 SetStyle( m_style );
05381
05382 wxString strokeColour = parser.GetAttributeValue( wxT( "colour" ) );
05383 if ( !strokeColour.IsEmpty() )
05384 {
05385 if ( strokeColour.GetChar( 0 ) == wxT( '#' ) )
05386 {
05387 m_colour1 = HexToColour( strokeColour.After( wxT( '#' ) ) );
05388 }
05389 else
05390 {
05391 m_colour1 = wxTheColourDatabase->Find( strokeColour );
05392 if ( !m_colour1.Ok() )
05393 m_colour1 = *wxBLACK;
05394 }
05395 }
05396 else
05397 m_colour1 = *wxBLACK;
05398
05399 m_pixelstroke = parser.GetAttributeValueBool( wxT( "pixelwidth" ), false );
05400
05401 m_width = ( float ) parser.GetAttributeValueDouble( wxT( "width" ) );
05402 }
05403 else
05404 {}
05405 }
05406 #endif //wxART2D_USE_CVGIO
05407
05408
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418
05419
05420
05421
05422
05423 class A2DARTBASEDLLEXP a2dPatternStrokeData: public a2dOneColourStrokeData
05424 {
05425
05426 private:
05427
05428 friend class a2dStroke;
05429
05430 public:
05431
05432 virtual a2dStrokeType GetType( void ) const { return a2dSTROKE_BITMAP; }
05433
05434 protected:
05435
05436
05437 a2dPatternStrokeData();
05438
05439
05440 a2dPatternStrokeData( const a2dPatternStrokeData& other );
05441
05442
05443
05444
05445
05446
05447
05448 a2dPatternStrokeData( const wxBitmap& stipple, a2dStrokeStyle style = a2dSTROKE_STIPPLE );
05449
05450 a2dPatternStrokeData( const wxFileName& filename, a2dStrokeStyle style = a2dSTROKE_STIPPLE );
05451
05452
05453 ~a2dPatternStrokeData( void ){}
05454
05455
05456 void SetStipple( const wxBitmap& stipple ) { m_stipple = stipple; }
05457
05458 const wxBitmap& GetStipple() const { return m_stipple; }
05459
05460
05461
05462
05463
05464 wxString GetFileName() { return m_filename; }
05465
05466 a2dStrokeStyle GetStyle( void ) const;
05467
05468 void SetStyle( a2dStrokeStyle style );
05469
05470 #if wxART2D_USE_CVGIO
05471 virtual void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts );
05472 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite );
05473 #endif //wxART2D_USE_CVGIO
05474
05475 wxBitmap m_stipple;
05476
05477
05478
05479 wxString m_filename;
05480 };
05481
05482 a2dPatternStrokeData::a2dPatternStrokeData()
05483 {
05484 m_stipple = wxNullBitmap;
05485 m_style = a2dSTROKE_STIPPLE;
05486 SetStyle( m_style );
05487 }
05488
05489 a2dPatternStrokeData::a2dPatternStrokeData( const wxBitmap& stipple, a2dStrokeStyle style )
05490 {
05491 m_stipple = stipple;
05492
05493 wxASSERT_MSG( m_stipple.Ok(), wxT( "Stipple Bitmap not oke" ));
05494 if ( style == a2dSTROKE_STIPPLE_MASK_OPAQUE || style == a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT )
05495 {
05496 wxASSERT_MSG( m_stipple.GetMask(), wxT( "require a mask for a2dSTROKE_STIPPLE_MASK_OPAQUE or a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT" ) );
05497 }
05498 SetStyle( style );
05499 }
05500
05501 a2dPatternStrokeData::a2dPatternStrokeData( const wxFileName& filename, a2dStrokeStyle style )
05502 {
05503 m_filename = filename.GetFullPath();
05504
05505 wxImage image;
05506 if ( m_filename.IsEmpty() )
05507 {
05508 wxLogError( _("CVG : bitmap file for a2dPatternFill not specified or empty") );
05509 image = wxImage( 32, 32 );
05510 }
05511 else
05512 {
05513 wxString filename = a2dGlobals->GetImagePathList().FindValidPath( m_filename );
05514 if ( filename.IsEmpty() )
05515 {
05516 wxLogError( _("CVG : Could not load bitmap \"%s\" for a2dPatternStroke from path \"%s\" "), m_filename.c_str(), a2dGlobals->GetImagePathList().GetAsString().c_str() );
05517 image = wxImage( 32, 32 );
05518 }
05519 else if ( ! image.LoadFile(filename,wxBITMAP_TYPE_BMP) )
05520 {
05521 wxLogError( _("CVG : Could not load bitmap %s for a2dPatternStroke"), filename.c_str() );
05522 image = wxImage( 32, 32 );
05523 }
05524 }
05525 m_stipple = wxBitmap( image );
05526
05527 if ( m_style == a2dSTROKE_STIPPLE_MASK_OPAQUE || m_style == a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT )
05528 {
05529 wxColour white(wxT("WHITE"));
05530 wxColour black(wxT("BLACK"));
05531
05532 wxMask* monochrome_mask = new wxMask( m_stipple, black );
05533 m_stipple.SetMask(monochrome_mask);
05534 }
05535 SetStyle( style );
05536 }
05537
05538 a2dPatternStrokeData::a2dPatternStrokeData( const a2dPatternStrokeData& other ): a2dOneColourStrokeData( other )
05539 {
05540 m_stipple = other.m_stipple;
05541 }
05542
05543 a2dStrokeStyle a2dPatternStrokeData::GetStyle() const
05544 {
05545 return m_style;
05546 }
05547
05548 void a2dPatternStrokeData::SetStyle( a2dStrokeStyle style )
05549 {
05550 if ( style == a2dSTROKE_TRANSPARENT )
05551 m_style = a2dSTROKE_TRANSPARENT;
05552 if ( style == a2dSTROKE_STIPPLE_MASK_OPAQUE ||
05553 style == a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT
05554 )
05555 {
05556 if ( !m_stipple.GetMask() )
05557 {
05558 wxMask * mask = new wxMask( m_stipple, GetColour() );
05559 m_stipple.SetMask( mask );
05560 }
05561 m_style = style;
05562 }
05563 else if ( style == a2dSTROKE_STIPPLE )
05564 m_style = style;
05565 else
05566 wxFAIL_MSG( _( "invalid style for a2dPatternStrokeData" ) );
05567 }
05568
05569 #if wxART2D_USE_CVGIO
05570 void a2dPatternStrokeData::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
05571 {
05572 a2dOneColourStrokeData::DoLoad( parent, parser, xmlparts );
05573 if ( xmlparts == a2dXmlSer_attrib )
05574 {
05575 wxString filename = parser.GetAttributeValue( wxT( "filename" ), wxT( "" ) );
05576 wxImage image;
05577 if ( filename.IsEmpty() )
05578 {
05579 wxLogError( _( "CVG : bitmap file for a2dPatternStrokeData not specified or empty" ) );
05580 image = wxImage( 32, 32 );
05581 }
05582 else
05583 {
05584 m_filename = a2dGlobals->GetImagePathList().FindValidPath( filename );
05585 if ( m_filename.IsEmpty() )
05586 {
05587 wxLogError( _( "CVG : Could not load bitmap \"%s\" for a2dPatternStrokeData from path \"%s\" " ), filename.c_str(), a2dGlobals->GetImagePathList().GetAsString().c_str() );
05588 image = wxImage( 32, 32 );
05589 }
05590 else if ( ! image.LoadFile( m_filename, wxBITMAP_TYPE_BMP ) )
05591 {
05592 wxLogError( _( "CVG : Could not load bitmap %s for a2dPatternStrokeData" ), m_filename.c_str() );
05593 image = wxImage( 32, 32 );
05594 }
05595 }
05596 m_stipple = wxBitmap( image );
05597
05598 m_style = ( a2dStrokeStyle ) StrokeString2Style( parser.GetAttributeValue( wxT( "style" ), wxT("a2dSTROKE_STIPPLE") ) );
05599 SetStyle( m_style );
05600
05601 if ( m_style == a2dSTROKE_STIPPLE_MASK_OPAQUE || m_style == a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT )
05602 {
05603 wxColour white( wxT( "WHITE" ) );
05604 wxColour black( wxT( "BLACK" ) );
05605
05606 wxMask* monochrome_mask = new wxMask( m_stipple, black );
05607 m_stipple.SetMask( monochrome_mask );
05608 }
05609 }
05610 else
05611 {}
05612 }
05613
05614 void a2dPatternStrokeData::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
05615 {
05616 a2dOneColourStrokeData::DoSave( parent, out, xmlparts, towrite );
05617
05618 if ( xmlparts == a2dXmlSer_attrib )
05619 {
05620 if ( m_style != a2dSTROKE_STIPPLE )
05621 out.WriteAttribute( wxT( "style" ), StrokeStyle2String( GetStyle() ) );
05622
05623 wxString filename = a2dGlobals->GetImagePathList().FindValidPath( m_filename );
05624 if ( filename.IsEmpty() )
05625 {
05626
05627
05628 wxString fileTosave;
05629
05630 wxString* layerfile = a2dGeneralGlobals->GetVariablesHash().GetVariableString( wxT( "wxart2dlayers" ) );
05631 wxString* layerfiledir = a2dGeneralGlobals->GetVariablesHash().GetVariableString( wxT( "layerFileSavePath" ) );
05632
05633 if ( layerfile && !layerfile->IsEmpty() )
05634 {
05635 if ( !wxDirExists( *layerfiledir ) )
05636 wxMkdir( *layerfiledir );
05637 wxString mess = *layerfiledir + *layerfile + wxT( " directory does not exist, and could not be created" );
05638 wxASSERT_MSG( wxDirExists( *layerfiledir ) , mess );
05639
05640 fileTosave = *layerfiledir + wxFILE_SEP_PATH;
05641 }
05642
05643 if ( m_filename.IsEmpty() )
05644 {
05645 m_filename.Printf( _T( "canpat_%ld.bmp" ), wxGenNewId() );
05646 fileTosave += m_filename;
05647 }
05648 else
05649 fileTosave += wxFileNameFromPath( m_filename );
05650 bool isOke = m_stipple.SaveFile( fileTosave, wxBITMAP_TYPE_BMP );
05651 if ( !isOke )
05652 wxLogError( _( "Could not save bitmap %s for a2dPatternStrokeData" ), fileTosave.c_str() );
05653 out.WriteAttribute( wxT( "filename" ), wxFileNameFromPath( m_filename ) );
05654 }
05655 else
05656 out.WriteAttribute( wxT( "filename" ), wxFileNameFromPath(m_filename) );
05657 }
05658 else
05659 {}
05660 }
05661 #endif //wxART2D_USE_CVGIO
05662
05663
05664
05665
05666
05667 a2dStroke::a2dStroke( void )
05668 {
05669 }
05670
05671 a2dStroke::a2dStroke( const wxColour& col, a2dStrokeStyle style )
05672 {
05673 m_refData = new a2dOneColourStrokeData( col, style );
05674 }
05675
05676 a2dStroke::a2dStroke( const wxColour& col, double width, a2dStrokeStyle style )
05677 {
05678 m_refData = new a2dOneColourStrokeData( col, style );
05679 ((a2dOneColourStrokeData*)GetRefData())->SetWidth( width );
05680 }
05681
05682 a2dStroke::a2dStroke( const wxColour& col, int width, a2dStrokeStyle style )
05683 {
05684 m_refData = new a2dOneColourStrokeData( col, style );
05685 ((a2dOneColourStrokeData*)GetRefData())->SetWidth( width );
05686 ((a2dOneColourStrokeData*)GetRefData())->SetPixelStroke( true );
05687 }
05688
05689 a2dStroke::a2dStroke( const wxBitmap& stipple, a2dStrokeStyle style )
05690 {
05691 m_refData = new a2dPatternStrokeData( stipple, style );
05692 }
05693
05694 a2dStroke::a2dStroke( const wxBitmap& stipple, const wxColour& col, const wxColour& col2, a2dStrokeStyle style )
05695 {
05696 m_refData = new a2dPatternStrokeData( stipple, style );
05697 SetColour( col );
05698
05699 }
05700
05701 a2dStroke::a2dStroke( const wxFileName& filename, a2dStrokeStyle style )
05702 {
05703 m_refData = new a2dPatternStrokeData( filename, style );
05704 }
05705
05706 a2dStroke::a2dStroke( const wxFileName& filename, const wxColour& col, const wxColour& col2, a2dStrokeStyle style )
05707 {
05708 m_refData = new a2dPatternStrokeData( filename, style );
05709 SetColour( col );
05710
05711 }
05712
05713 a2dStroke::a2dStroke( const wxPen& stroke )
05714 {
05715 m_refData = new a2dOneColourStrokeData( stroke );
05716 }
05717
05718 a2dStroke::a2dStroke( const a2dStroke& Stroke )
05719 :wxObject( Stroke )
05720 {
05721 }
05722
05723
05724 a2dStroke::~a2dStroke( void )
05725 {
05726 }
05727
05728 a2dStroke& a2dStroke::UnShare()
05729 {
05730 wxObject::UnShare();
05731 return *this;
05732 }
05733
05734 a2dStrokeType a2dStroke::GetType( void ) const
05735 {
05736 if ( !m_refData )
05737 return a2dSTROKE_NULL;
05738 return ( (a2dStrokeRefData*) m_refData )->GetType();
05739 }
05740
05741 wxObjectRefData* a2dStroke::CreateRefData() const
05742 {
05743 return new a2dOneColourStrokeData();
05744 }
05745
05746 wxObjectRefData* a2dStroke::CloneRefData(const wxObjectRefData* data) const
05747 {
05748 switch ( ( (a2dStrokeRefData*) data )->GetType() )
05749 {
05750 case a2dSTROKE_NULL:
05751 break;
05752 case a2dSTROKE_ONE_COLOUR:
05753 return new a2dOneColourStrokeData( *((const a2dOneColourStrokeData*)data ));
05754 break;
05755 case a2dSTROKE_BITMAP:
05756 return new a2dPatternStrokeData( *((const a2dPatternStrokeData*)data ));
05757 break;
05758 default:
05759 break;
05760 }
05761 return NULL;
05762 }
05763
05764 void a2dStroke::SetStipple( const wxBitmap& stipple )
05765 {
05766 AllocExclusive();
05767 if ( GetType() == a2dSTROKE_BITMAP )
05768 ((a2dPatternStrokeData*)m_refData)->SetStipple( stipple );
05769 else
05770 {
05771 UnRef();
05772 m_refData = new a2dPatternStrokeData( stipple, a2dSTROKE_STIPPLE );
05773 }
05774 }
05775
05776 const wxBitmap& a2dStroke::GetStipple() const
05777 {
05778 if ( GetType() == a2dSTROKE_BITMAP )
05779 {
05780 wxASSERT_MSG( m_refData, _T("No ref data") );
05781 return ((const a2dPatternStrokeData*)m_refData)->GetStipple();
05782 }
05783 else
05784 {
05785 return wxNullBitmap;
05786 }
05787 }
05788
05789 void a2dStroke::SetAlpha( wxUint8 val )
05790 {
05791 AllocExclusive();
05792
05793 switch ( GetType() )
05794 {
05795 case a2dSTROKE_NULL:
05796 UnRef();
05797 break;
05798 case a2dSTROKE_ONE_COLOUR:
05799 {
05800 wxASSERT_MSG( m_refData, _T("No ref data") );
05801 wxColour newcol = ((a2dOneColourStrokeData*)GetRefData())->GetColour();
05802 newcol.Set( newcol.Red(), newcol.Green(), newcol.Blue(), val );
05803 ((a2dOneColourStrokeData*)GetRefData())->SetColour( newcol );
05804 break;
05805 }
05806 case a2dSTROKE_BITMAP:
05807 {
05808 wxASSERT_MSG( m_refData, _T("No ref data") );
05809 wxColour newcol = ((a2dOneColourStrokeData*)GetRefData())->GetColour();
05810 newcol.Set( newcol.Red(), newcol.Green(), newcol.Blue(), val );
05811 ((a2dPatternStrokeData*)GetRefData())->SetColour( newcol );
05812 break;
05813 }
05814 default:
05815 break;
05816 }
05817 }
05818
05819 wxUint8 a2dStroke::GetAlpha() const
05820 {
05821 switch ( GetType() )
05822 {
05823 case a2dSTROKE_NULL:
05824 return a2dSTROKE_NULLSTROKE;
05825 case a2dSTROKE_ONE_COLOUR:
05826 wxASSERT_MSG( m_refData, _T("No ref data") );
05827 return ((a2dOneColourStrokeData*)GetRefData())->GetColour().Alpha();
05828 break;
05829 case a2dSTROKE_BITMAP:
05830 wxASSERT_MSG( m_refData, _T("No ref data") );
05831 return ((a2dPatternStrokeData*)GetRefData())->GetColour().Alpha();
05832 break;
05833 default:
05834 break;
05835 }
05836 return 255;
05837 }
05838
05839
05840 void a2dStroke::SetColour( const wxColour& col )
05841 {
05842 AllocExclusive();
05843 switch ( GetType() )
05844 {
05845 case a2dSTROKE_NULL:
05846 UnRef();
05847 break;
05848 case a2dSTROKE_ONE_COLOUR:
05849 ((a2dOneColourStrokeData*)GetRefData())->SetColour( col );
05850 break;
05851 case a2dSTROKE_BITMAP:
05852 ((a2dPatternStrokeData*)GetRefData())->SetColour( col );
05853 break;
05854 default:
05855 break;
05856 }
05857 }
05858
05859 wxColour a2dStroke::GetColour() const
05860 {
05861 switch ( GetType() )
05862 {
05863 case a2dSTROKE_NULL:
05864 break;
05865 case a2dSTROKE_ONE_COLOUR:
05866 return ((a2dOneColourStrokeData*)GetRefData())->GetColour();
05867 break;
05868 case a2dSTROKE_BITMAP:
05869 return ((a2dPatternStrokeData*)GetRefData())->GetColour();
05870 break;
05871 default:
05872 break;
05873 }
05874 return *wxBLACK;
05875 }
05876
05877 void a2dStroke::SetColour2( const wxColour& col )
05878 {
05879 AllocExclusive();
05880 switch ( GetType() )
05881 {
05882 case a2dSTROKE_NULL:
05883 UnRef();
05884 break;
05885 case a2dSTROKE_ONE_COLOUR:
05886 wxASSERT_MSG( m_refData, _T("No ref data") );
05887 break;
05888 case a2dSTROKE_BITMAP:
05889 wxASSERT_MSG( m_refData, _T("No ref data") );
05890
05891 ((a2dPatternStrokeData*)GetRefData())->SetColour( col );
05892 break;
05893 default:
05894 break;
05895 }
05896 }
05897
05898 wxColour a2dStroke::GetColour2() const
05899 {
05900 switch ( GetType() )
05901 {
05902 case a2dSTROKE_NULL:
05903 break;
05904 case a2dSTROKE_ONE_COLOUR:
05905 break;
05906 case a2dSTROKE_BITMAP:
05907
05908 return ((a2dPatternStrokeData*)GetRefData())->GetColour();
05909 break;
05910 default:
05911 break;
05912 }
05913 return *wxBLACK;
05914 }
05915
05916 void a2dStroke::SetJoin( wxPenJoin join_style )
05917 {
05918 AllocExclusive();
05919 switch ( GetType() )
05920 {
05921 case a2dSTROKE_NULL:
05922 UnRef();
05923 break;
05924 case a2dSTROKE_ONE_COLOUR:
05925 ((a2dOneColourStrokeData*)GetRefData())->SetJoin( join_style );
05926 break;
05927 case a2dSTROKE_BITMAP:
05928 ((a2dPatternStrokeData*)GetRefData())->SetJoin( join_style );
05929 break;
05930 default:
05931 break;
05932 }
05933 }
05934
05935 void a2dStroke::SetCap( wxPenCap cap_style )
05936 {
05937 AllocExclusive();
05938 switch ( GetType() )
05939 {
05940 case a2dSTROKE_NULL:
05941 UnRef();
05942 break;
05943 case a2dSTROKE_ONE_COLOUR:
05944 ((a2dOneColourStrokeData*)GetRefData())->SetCap( cap_style );
05945 break;
05946 case a2dSTROKE_BITMAP:
05947 ((a2dPatternStrokeData*)GetRefData())->SetCap( cap_style );
05948 break;
05949 default:
05950 break;
05951 }
05952 }
05953
05954 wxPenCap a2dStroke::GetCap() const
05955 {
05956 switch ( GetType() )
05957 {
05958 case a2dSTROKE_NULL:
05959 break;
05960 case a2dSTROKE_ONE_COLOUR:
05961 return ((a2dOneColourStrokeData*)GetRefData())->GetCap();
05962 break;
05963 case a2dSTROKE_BITMAP:
05964 return ((a2dPatternStrokeData*)GetRefData())->GetCap();
05965 break;
05966 default:
05967 break;
05968 }
05969 return wxCAP_ROUND;
05970 }
05971
05972 wxPenJoin a2dStroke::GetJoin() const
05973 {
05974 switch ( GetType() )
05975 {
05976 case a2dSTROKE_NULL:
05977 break;
05978 case a2dSTROKE_ONE_COLOUR:
05979 return ((a2dOneColourStrokeData*)GetRefData())->GetJoin();
05980 break;
05981 case a2dSTROKE_BITMAP:
05982 return ((a2dPatternStrokeData*)GetRefData())->GetJoin();
05983 break;
05984 default:
05985 break;
05986 }
05987 return wxJOIN_ROUND;
05988 }
05989
05990 void a2dStroke::SetWidth( float width )
05991 {
05992 AllocExclusive();
05993 switch ( GetType() )
05994 {
05995 case a2dSTROKE_NULL:
05996 UnRef();
05997 break;
05998 case a2dSTROKE_ONE_COLOUR:
05999 ((a2dOneColourStrokeData*)GetRefData())->SetWidth( width );
06000 break;
06001 case a2dSTROKE_BITMAP:
06002 ((a2dPatternStrokeData*)GetRefData())->SetWidth( width );
06003 break;
06004 default:
06005 break;
06006 }
06007 }
06008
06009 float a2dStroke::GetWidth() const
06010 {
06011 switch ( GetType() )
06012 {
06013 case a2dSTROKE_NULL:
06014 break;
06015 case a2dSTROKE_ONE_COLOUR:
06016 return ((a2dOneColourStrokeData*)GetRefData())->GetWidth();
06017 break;
06018 case a2dSTROKE_BITMAP:
06019 return ((a2dPatternStrokeData*)GetRefData())->GetWidth();
06020 break;
06021 default:
06022 break;
06023 }
06024 return 0;
06025 }
06026 float a2dStroke::GetExtend() const
06027 {
06028 switch ( GetType() )
06029 {
06030 case a2dSTROKE_NULL:
06031 break;
06032 case a2dSTROKE_ONE_COLOUR:
06033 return ((a2dOneColourStrokeData*)GetRefData())->GetExtend();
06034 break;
06035 case a2dSTROKE_BITMAP:
06036 return ((a2dPatternStrokeData*)GetRefData())->GetExtend();
06037 break;
06038 default:
06039 break;
06040 }
06041 return 0;
06042 }
06043
06044 void a2dStroke::SetPixelStroke( bool pixelstroke )
06045 {
06046 AllocExclusive();
06047 switch ( GetType() )
06048 {
06049 case a2dSTROKE_NULL:
06050 UnRef();
06051 break;
06052 case a2dSTROKE_ONE_COLOUR:
06053 ((a2dOneColourStrokeData*)GetRefData())->SetPixelStroke( pixelstroke );
06054 break;
06055 case a2dSTROKE_BITMAP:
06056 ((a2dPatternStrokeData*)GetRefData())->SetPixelStroke( pixelstroke );
06057 break;
06058 default:
06059 break;
06060 }
06061 }
06062
06063 bool a2dStroke::GetPixelStroke() const
06064 {
06065 switch ( GetType() )
06066 {
06067 case a2dSTROKE_NULL:
06068 break;
06069 case a2dSTROKE_ONE_COLOUR:
06070 return ((a2dOneColourStrokeData*)GetRefData())->GetPixelStroke();
06071 break;
06072 case a2dSTROKE_BITMAP:
06073 return ((a2dPatternStrokeData*)GetRefData())->GetPixelStroke();
06074 break;
06075 default:
06076 break;
06077 }
06078 return false;
06079 }
06080
06081 a2dStrokeStyle a2dStroke::GetStyle( void ) const
06082 {
06083 switch ( GetType() )
06084 {
06085 case a2dSTROKE_NULL:
06086 return a2dSTROKE_NULLSTROKE;
06087 break;
06088 case a2dSTROKE_ONE_COLOUR:
06089 return ((a2dOneColourStrokeData*)GetRefData())->GetStyle();
06090 break;
06091 case a2dSTROKE_BITMAP:
06092 return ((a2dPatternStrokeData*)GetRefData())->GetStyle();
06093 break;
06094 default:
06095 break;
06096 }
06097 return a2dSTROKE_NULLSTROKE;
06098 }
06099
06100 void a2dStroke::SetStyle( a2dStrokeStyle style )
06101 {
06102 a2dStrokeStyle cur_style = GetStyle();
06103 if ( cur_style == style )
06104 return;
06105 AllocExclusive();
06106
06107 a2dStrokeType type = GetTypeForStyle( style );
06108
06109 if ( type == GetType() )
06110 {
06111 switch ( type )
06112 {
06113 case a2dSTROKE_NULL:
06114 UnRef();
06115 break;
06116 case a2dSTROKE_ONE_COLOUR:
06117 wxASSERT_MSG( m_refData, _T("No ref data") );
06118 ((a2dOneColourStrokeData*)GetRefData())->SetStyle( style );
06119 break;
06120
06121
06122
06123
06124
06125
06126
06127
06128
06129
06130 case a2dSTROKE_BITMAP:
06131 wxASSERT_MSG( m_refData, _T("No ref data") );
06132 ((a2dPatternStrokeData*)GetRefData())->SetStyle( style );
06133 break;
06134 default:
06135 break;
06136 }
06137 }
06138 else
06139 {
06140 a2dStrokeRefData* newrefdata = NULL;
06141 switch ( type )
06142 {
06143 case a2dSTROKE_NULL:
06144 break;
06145 case a2dSTROKE_ONE_COLOUR:
06146 {
06147 a2dOneColourStrokeData* onenewrefdata = new a2dOneColourStrokeData( GetColour(), style );
06148 newrefdata = onenewrefdata;
06149 onenewrefdata->SetColour( GetColour() );
06150 onenewrefdata->SetWidth( GetWidth() );
06151 onenewrefdata->SetJoin( GetJoin() );
06152 onenewrefdata->SetCap( GetCap() );
06153 onenewrefdata->SetPixelStroke( GetPixelStroke() );
06154 break;
06155 }
06156
06157
06158
06159
06160
06161
06162
06163
06164 case a2dSTROKE_BITMAP:
06165 {
06166 a2dPatternStrokeData* patnewrefdata = new a2dPatternStrokeData( wxNullBitmap, style );
06167 newrefdata = patnewrefdata;
06168 patnewrefdata->SetColour( GetColour() );
06169 patnewrefdata->SetWidth( GetWidth() );
06170 patnewrefdata->SetJoin( GetJoin() );
06171 patnewrefdata->SetCap( GetCap() );
06172 patnewrefdata->SetPixelStroke( GetPixelStroke() );
06173
06174 break;
06175 }
06176 default:
06177 break;
06178 }
06179 UnRef();
06180 m_refData = newrefdata;
06181 }
06182 }
06183
06184 a2dStrokeType a2dStroke::GetTypeForStyle( a2dStrokeStyle style ) const
06185 {
06186 if ( style == a2dSTROKE_NULLSTROKE || style == a2dSTROKE_LAYER || style == a2dSTROKE_INHERIT )
06187 return a2dSTROKE_NULL;
06188 if ( style == a2dSTROKE_TRANSPARENT && GetType() != a2dSTROKE_NULL )
06189 return GetType();
06190 else if ( style == a2dSTROKE_SOLID ||
06191 style == a2dSTROKE_TRANSPARENT ||
06192 style == a2dSTROKE_DOT ||
06193 style == a2dSTROKE_DOT_DASH ||
06194 style == a2dSTROKE_LONG_DASH ||
06195 style == a2dSTROKE_SHORT_DASH ||
06196 style == a2dSTROKE_USER_DASH ||
06197 style == a2dSTROKE_BDIAGONAL_HATCH ||
06198 style == a2dSTROKE_CROSSDIAG_HATCH ||
06199 style == a2dSTROKE_FDIAGONAL_HATCH ||
06200 style == a2dSTROKE_CROSS_HATCH ||
06201 style == a2dSTROKE_HORIZONTAL_HATCH ||
06202 style == a2dSTROKE_VERTICAL_HATCH ||
06203 style == a2dSTROKE_NULLSTROKE
06204 )
06205 return a2dSTROKE_ONE_COLOUR;
06206
06207
06208
06209
06210
06211
06212 else if ( style == a2dSTROKE_STIPPLE ||
06213 style == a2dSTROKE_STIPPLE_MASK_OPAQUE ||
06214 style == a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT
06215 )
06216 return a2dSTROKE_BITMAP;
06217 else
06218 wxFAIL_MSG( _( "invalid style for in a2dStroke" ) );
06219
06220 return a2dSTROKE_NULL;
06221 }
06222
06223
06224 #if wxART2D_USE_CVGIO
06225 void a2dStroke::Load( wxObject* parent, a2dIOHandlerXmlSerIn& parser )
06226 {
06227 a2dStrokeType type;
06228
06229 parser.Require( START_TAG, wxT("o") );
06230
06231 wxString classname = parser.GetAttributeValue( wxT("classname") );
06232 if ( classname == wxT("a2dOneColourStroke") )
06233 type = a2dSTROKE_ONE_COLOUR;
06234 else if ( classname == wxT("a2dPatternFill") )
06235 type = a2dSTROKE_BITMAP;
06236 else
06237 {
06238 wxString stype = parser.GetAttributeValue( wxT( "type" ), wxT( "a2dSTROKE_NULL" ) );
06239 if ( stype == wxT("a2dSTROKE_NULL") )
06240 type = a2dSTROKE_NULL;
06241 if ( stype == wxT("a2dSTROKE_ONE_COLOUR") )
06242 type = a2dSTROKE_ONE_COLOUR;
06243 else if ( stype == wxT("a2dSTROKE_BITMAP") )
06244 type = a2dSTROKE_BITMAP;
06245 }
06246
06247 switch ( type )
06248 {
06249 case a2dSTROKE_NULL:
06250 break;
06251 case a2dSTROKE_ONE_COLOUR:
06252 m_refData = new a2dOneColourStrokeData( *wxBLACK );
06253 break;
06254 case a2dSTROKE_BITMAP:
06255 m_refData = new a2dPatternStrokeData( wxNullBitmap );
06256 break;
06257 default:
06258 break;
06259 }
06260
06261 if ( GetRefData() )
06262 {
06263 ((a2dStrokeRefData*)GetRefData())->DoLoad( parent, parser, a2dXmlSer_attrib );
06264 parser.Next();
06265 ((a2dStrokeRefData*)GetRefData())->DoLoad( parent, parser, a2dXmlSer_Content );
06266 }
06267 else
06268 parser.Next();
06269
06270 parser.Require( END_TAG, wxT("o") );
06271 parser.Next();
06272 }
06273
06274 void a2dStroke::Save( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dObjectList* towrite )
06275 {
06276 out.WriteStartElementAttributes( wxT("o") );
06277 out.WriteAttribute( wxT("classname"), GetClassInfo()->GetClassName() );
06278
06279 switch ( GetType() )
06280 {
06281 case a2dSTROKE_NULL:
06282 break;
06283 case a2dSTROKE_ONE_COLOUR:
06284 out.WriteAttribute( wxT("type"), wxT("a2dSTROKE_ONE_COLOUR") );
06285 break;
06286 case a2dSTROKE_BITMAP:
06287 out.WriteAttribute( wxT("type"), wxT("a2dSTROKE_BITMAP") );
06288 break;
06289 default:
06290 break;
06291 }
06292 if ( GetRefData() )
06293 ((a2dStrokeRefData*)GetRefData())->DoSave( parent, out, a2dXmlSer_attrib, towrite );;
06294
06295 out.WriteEndAttributes();
06296 if ( GetRefData() )
06297 ((a2dStrokeRefData*)GetRefData())->DoSave( parent, out, a2dXmlSer_Content, towrite );;
06298
06299 out.WriteEndElement();
06300 }
06301 #endif //wxART2D_USE_CVGIO