1 /***************************************************************************
2  *
3  * Project:  OpenCPN
4  * Purpose:  Chart Symbols
5  * Author:   Jesper Weissglas
6  *
7  ***************************************************************************
8  *   Copyright (C) 2010 by David S. Register                               *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful,       *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  *   GNU General Public License for more details.                          *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, Inc.,                                       *
23  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
24  **************************************************************************/
25 #include "config.h"
26 
27 #include "wx/wxprec.h"
28 
29 #ifndef  WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32 
33 #include <wx/filename.h>
34 #include <wx/dir.h>
35 #include <stdlib.h>
36 #include "OCPNPlatform.h"
37 
38 #include "styles.h"
39 #include "chart1.h"
40 #include "wx28compat.h"
41 
42 #ifdef ocpnUSE_SVG
43 #include "wxSVG/svg.h"
44 #endif // ocpnUSE_SVG
45 
46 #ifdef __OCPN__ANDROID__
47 #include "androidUTIL.h"
48 #include "qdebug.h"
49 #endif
50 
51 extern OCPNPlatform     *g_Platform;
52 
53 using namespace ocpnStyle;
54 
bmdump(wxBitmap bm,wxString name)55 void bmdump(wxBitmap bm, wxString name)
56 {
57     wxImage img = bm.ConvertToImage();
58     img.SaveFile( name << _T(".png"), wxBITMAP_TYPE_PNG );
59 }
60 
LoadSVG(const wxString filename,unsigned int width,unsigned int height)61 static wxBitmap LoadSVG( const wxString filename, unsigned int width, unsigned int height )
62 {
63 #ifdef ocpnUSE_SVG
64 #ifdef __OCPN__ANDROID__
65     return loadAndroidSVG( filename, width, height );
66 #else
67     wxSVGDocument svgDoc;
68     if( svgDoc.Load(filename) )
69         return wxBitmap( svgDoc.Render( width, height, NULL, true, true ) );
70     else
71         return wxBitmap(width, height);
72 #endif
73 #else
74     return wxBitmap(width, height);
75 #endif // ocpnUSE_SVG
76 }
77 
78 // This function can be used to create custom bitmap blending for all platforms
79 // where 32 bit bitmap ops are broken. Can hopefully be removed for wxWidgets 3.0...
80 
MergeBitmaps(wxBitmap back,wxBitmap front,wxSize offset)81 wxBitmap MergeBitmaps( wxBitmap back, wxBitmap front, wxSize offset )
82 {
83     //  If the front bitmap has no alpha channel, then merging will accomplish nothing
84     //  So, simply return the bitmap intact
85     //  However, if the bitmaps are different sizes, do the render anyway.
86     wxImage im_front = front.ConvertToImage();
87     if(!im_front.HasAlpha() && (front.GetWidth() == back.GetWidth()) )
88         return front;
89 
90 #ifdef __WXMSW__
91     //  WxWidgets still has some trouble overlaying bitmaps with transparency.
92     //  This is true on wx2.8 as well as wx3.0
93     //  In the specific case where the back bitmap has alpha, but the front does not,
94     //  we obviously mean for the front to be drawn over the back, with 100% opacity.
95     //  To do this, we need to convert the back bitmap to simple no-alpha model.
96     if(!im_front.HasAlpha()){
97         wxImage im_back = back.ConvertToImage();
98         back = wxBitmap(im_back);
99     }
100 #endif
101 
102     wxBitmap merged( back.GetWidth(), back.GetHeight(), back.GetDepth() );
103 
104     // Manual alpha blending for broken wxWidgets alpha bitmap support, pervasive in wx2.8.
105     // And also in wx3, at least on Windows...
106 #if 1 //!wxCHECK_VERSION(2,9,4)
107 
108 #if !wxCHECK_VERSION(2,9,4)
109     merged.UseAlpha();
110     back.UseAlpha();
111     front.UseAlpha();
112 #endif
113 
114     wxImage im_back = back.ConvertToImage();
115     wxImage im_result = back.ConvertToImage();// Only way to make result have alpha channel in wxW 2.8.
116 
117     unsigned char *presult = im_result.GetData();
118     unsigned char *pback = im_back.GetData();
119     unsigned char *pfront = im_front.GetData();
120 
121     unsigned char *afront = NULL;
122     if( im_front.HasAlpha() )
123         afront = im_front.GetAlpha();
124 
125     unsigned char *aback = NULL;
126     if( im_back.HasAlpha() )
127         aback = im_back.GetAlpha();
128 
129     unsigned char *aresult = NULL;
130     if( im_result.HasAlpha() )
131         aresult = im_result.GetAlpha();
132 
133     // Do alpha blending, associative version of "over" operator.
134     if(presult && pback && pfront){
135         for( int i = 0; i < back.GetHeight(); i++ ) {
136             for( int j = 0; j < back.GetWidth(); j++ ) {
137 
138                 int fX = j - offset.x;
139                 int fY = i - offset.y;
140 
141                 bool inFront = true;
142                 if( fX < 0 || fY < 0 ) inFront = false;
143                 if( fX >= front.GetWidth() ) inFront = false;
144                 if( fY >= front.GetHeight() ) inFront = false;
145 
146                 if( inFront ) {
147                     double alphaF = 1.0;
148                     if (afront) alphaF = (double) ( *afront++ ) / 255.0;
149                     double alphaB = 1.0;
150                     if (aback) alphaB = (double) ( *aback++ ) / 255.0;
151                     double alphaRes = alphaF + alphaB * ( 1.0 - alphaF );
152                     if (aresult) {
153                         unsigned char a = alphaRes * 255;
154                         *aresult++ = a;
155                     }
156                     unsigned char r = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes;
157                     *presult++ = r;
158                     unsigned char g = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes;
159                     *presult++ = g;
160                     unsigned char b = (*pfront++ * alphaF + *pback++ * alphaB * ( 1.0 - alphaF )) / alphaRes;
161                     *presult++ = b;
162                 } else {
163                     if (aresult && aback) *aresult++ = *aback++;
164                     *presult++ = *pback++;
165                     *presult++ = *pback++;
166                     *presult++ = *pback++;
167                 }
168             }
169         }
170     }
171     merged = wxBitmap( im_result );
172 #else
173     wxMemoryDC mdc( merged );
174     mdc.Clear();
175     mdc.DrawBitmap( back, 0, 0, true );
176     mdc.DrawBitmap( front, offset.x, offset.y, true );
177     mdc.SelectObject( wxNullBitmap );
178 #endif
179 
180     return merged;
181 }
182 
183 // The purpouse of ConvertTo24Bit is to take an icon with 32 bit depth and alpha
184 // channel and put it in a 24 bit deep bitmap with no alpha, that can be safely
185 // drawn in the crappy wxWindows implementations.
186 
ConvertTo24Bit(wxColor bgColor,wxBitmap front)187 wxBitmap ConvertTo24Bit( wxColor bgColor, wxBitmap front ) {
188     if( front.GetDepth() == 24 ) return front;
189 
190 #if !wxCHECK_VERSION(2,9,4)
191     front.UseAlpha();
192 #endif
193 
194     wxImage im_front = front.ConvertToImage();
195     unsigned char *pfront = im_front.GetData();
196     if(!pfront)
197         return wxNullBitmap;
198 
199     unsigned char *presult = (unsigned char *)malloc(front.GetWidth() * front.GetHeight() * 3);
200     if(!presult)
201         return wxNullBitmap;
202 
203     unsigned char *po_result = presult;
204 
205 
206     unsigned char *afront = NULL;
207     if( im_front.HasAlpha() )
208     afront = im_front.GetAlpha();
209 
210     for( int i = 0; i < front.GetWidth(); i++ ) {
211         for( int j = 0; j < front.GetHeight(); j++ ) {
212 
213             double alphaF = 1.0;
214             if(afront)
215                 alphaF = (double) ( *afront++ ) / 256.0;
216              unsigned char r = *pfront++ * alphaF + bgColor.Red() * ( 1.0 - alphaF );
217              *presult++ = r;
218              unsigned char g = *pfront++ * alphaF + bgColor.Green() * ( 1.0 - alphaF );
219              *presult++ = g;
220              unsigned char b = *pfront++ * alphaF + bgColor.Blue() * ( 1.0 - alphaF );
221              *presult++ = b;
222         }
223     }
224 
225     wxImage im_result(front.GetWidth(), front.GetHeight(), po_result);
226 
227     wxBitmap result = wxBitmap( im_result );
228     return result;
229 }
230 
231 
NativeToolIconExists(const wxString & name)232 bool Style::NativeToolIconExists(const wxString & name)
233 {
234     if( toolIndex.find( name ) == toolIndex.end() )
235         return false;
236     else
237         return true;
238 }
239 
240 
241 // Tools and Icons perform on-demand loading and dimming of bitmaps.
242 // Changing color scheme invalidatres all loaded bitmaps.
243 
GetIcon(const wxString & name,int width,int height,bool bforceReload)244 wxBitmap Style::GetIcon(const wxString & name, int width, int height, bool bforceReload)
245 {
246     if( iconIndex.find( name ) == iconIndex.end() ) {
247         wxString msg( _T("The requested icon was not found in the style: ") );
248         msg += name;
249         wxLogMessage( msg );
250         return wxBitmap( GetToolSize().x, GetToolSize().y ); // Prevents crashing.
251     }
252 
253     int index = iconIndex[name]; // FIXME: this operation is not const but should be, use 'find'
254 
255     Icon* icon = (Icon*) icons[index];
256 
257     if( icon->loaded && !bforceReload)
258         return icon->icon;
259     if( icon->size.x == 0 )
260         icon->size = toolSize[currentOrientation];
261 
262     wxSize retSize = icon->size;
263     if((width > 0) && (height > 0))
264         retSize = wxSize(width, height);
265 
266     wxBitmap bm;
267 #ifdef ocpnUSE_SVG
268     wxString fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + name + _T(".svg");
269     if( wxFileExists( fullFilePath ) )
270         bm = LoadSVG( fullFilePath, retSize.x, retSize.y);
271     else
272     {
273 ///        wxLogMessage( _T("Can't find SVG icon: ") + fullFilePath );
274 #endif // ocpnUSE_SVG
275         wxRect location( icon->iconLoc, icon->size );
276         bm = graphics->GetSubBitmap( location );
277         if(retSize != icon->size){
278             wxImage scaled_image = bm.ConvertToImage();
279             bm = wxBitmap(scaled_image.Scale(retSize.x, retSize.y, wxIMAGE_QUALITY_HIGH));
280         }
281 
282 #ifdef ocpnUSE_SVG
283     }
284 #endif // ocpnUSE_SVG
285     icon->icon = SetBitmapBrightness( bm, colorscheme );
286     icon->loaded = true;
287     return icon->icon;
288 }
289 
GetToolIcon(const wxString & toolname,int iconType,bool rollover,int width,int height)290 wxBitmap Style::GetToolIcon(const wxString & toolname, int iconType, bool rollover, int width, int height )
291 {
292 
293     if( toolIndex.find( toolname ) == toolIndex.end() ) {
294 //  This will produce a flood of log messages for some PlugIns, notably WMM_PI, and GRADAR_PI
295 //        wxString msg( _T("The requested tool was not found in the style: ") );
296 //        msg += toolname;
297 //        wxLogMessage( msg );
298         return wxBitmap( GetToolSize().x, GetToolSize().y, 1 );
299     }
300 
301     int index = toolIndex[toolname];
302 
303     Tool* tool = (Tool*) tools[index];
304 
305     wxSize size = tool->customSize;
306     if( size.x == 0 )
307         size = toolSize[currentOrientation];
308 
309     wxSize retSize = size;
310     if((width > 0) && (height > 0))
311         retSize = wxSize(width, height);
312 
313     switch( iconType ){
314         case TOOLICON_NORMAL: {
315             if( tool->iconLoaded && !rollover ){
316                 return tool->icon;
317             }
318             if( tool->rolloverLoaded && rollover ) return tool->rollover;
319 
320             wxRect location( tool->iconLoc, size );
321 
322             //  If rollover icon does not exist, use the defult icon
323             if( rollover ) {
324                 if( (tool->rolloverLoc.x != 0) || (tool->rolloverLoc.y != 0) )
325                     location = wxRect( tool->rolloverLoc, size );
326             }
327 
328             if( currentOrientation ) {
329                 location.x -= verticalIconOffset.x;
330                 location.y -= verticalIconOffset.y;
331             }
332 
333             wxBitmap bm;
334 #ifdef ocpnUSE_SVG
335             wxString fullFilePath;
336             if( rollover ){
337                 fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + toolname + _T("_rollover.svg");
338                 if( !wxFileExists( fullFilePath ) )
339                     fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + toolname + _T(".svg");
340             }
341             else
342                 fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + toolname + _T(".svg");
343             if( wxFileExists( fullFilePath ) )
344                 bm = LoadSVG( fullFilePath, retSize.x, retSize.y );
345             else
346             {
347                 ///wxLogMessage( _T("Can't find SVG: ") + fullFilePath );
348 #endif // ocpnUSE_SVG
349                 bm = graphics->GetSubBitmap( location );
350 
351                 if( hasBackground ) {
352                     bm = MergeBitmaps( GetNormalBG(), bm, wxSize( 0, 0 ) );
353                 } else {
354                     wxBitmap bg( GetToolSize().x, GetToolSize().y );
355                     wxMemoryDC mdc( bg );
356                     mdc.SetBackground( wxBrush( GetGlobalColor( _T("GREY2") ), wxBRUSHSTYLE_SOLID ) );
357                     mdc.Clear();
358                     mdc.SelectObject( wxNullBitmap );
359                     bm = MergeBitmaps( bg, bm, wxSize( 0, 0 ) );
360                 }
361 
362                 if(retSize != size){
363                     wxImage scaled_image = bm.ConvertToImage();
364                     bm = wxBitmap(scaled_image.Scale(retSize.x, retSize.y, wxIMAGE_QUALITY_HIGH));
365                 }
366 
367 #ifdef ocpnUSE_SVG
368             }
369 #endif // ocpnUSE_SVG
370 
371             if( rollover ) {
372                 tool->rollover = SetBitmapBrightness( bm, colorscheme );
373                 tool->rolloverLoaded = true;
374                 return tool->rollover;
375             } else {
376                 if( toolname == _T("mob_btn") ) {
377                     double dimLevel = 1.0;
378                     if(colorscheme ==  GLOBAL_COLOR_SCHEME_DUSK)
379                         dimLevel = 0.5;
380                     else if(colorscheme ==  GLOBAL_COLOR_SCHEME_NIGHT)
381                         dimLevel = 0.5;
382                     tool->icon = SetBitmapBrightnessAbs( bm, dimLevel );
383                 }
384                 else {
385                     tool->icon = SetBitmapBrightness( bm, colorscheme );
386                 }
387 
388                 tool->iconLoaded = true;
389                 return tool->icon;
390             }
391         }
392         case TOOLICON_TOGGLED: {
393             if( tool->toggledLoaded && !rollover ) return tool->toggled;
394             if( tool->rolloverToggledLoaded && rollover ) return tool->rolloverToggled;
395 
396             wxRect location( tool->iconLoc, size );
397             if( rollover ) location = wxRect( tool->rolloverLoc, size );
398             wxSize offset( 0, 0 );
399             if( GetToolSize() != GetToggledToolSize() ) {
400                 offset = GetToggledToolSize() - GetToolSize();
401                 offset /= 2;
402             }
403             if( currentOrientation ) {
404                 location.x -= verticalIconOffset.x;
405                 location.y -= verticalIconOffset.y;
406             }
407             wxBitmap bm;
408 #ifdef ocpnUSE_SVG
409             wxString fullFilePath;
410             if( rollover )
411                 fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + toolname + _T("_rollover_toggled.svg");
412             else
413                 fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + toolname + _T("_toggled.svg");
414             if( wxFileExists( fullFilePath ) )
415                 bm = LoadSVG( fullFilePath, retSize.x, retSize.y );
416             else
417             {
418                 // Could not find a toggled SVG, so try to make one
419                 if( rollover )
420                     fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + toolname + _T("_rollover.svg");
421                 else
422                     fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + toolname + _T(".svg");
423 
424                 if( wxFileExists( fullFilePath ) ){
425                     bm = LoadSVG( fullFilePath, retSize.x, retSize.y );
426 
427                     wxBitmap bmBack = GetToggledBG();
428                     if( (bmBack.GetWidth() != retSize.x) || (bmBack.GetHeight() != retSize.y) ){
429                         wxImage scaled_back = bmBack.ConvertToImage();
430                         bmBack = wxBitmap(scaled_back.Scale(retSize.x, retSize.y, wxIMAGE_QUALITY_HIGH));
431                     }
432                     bm = MergeBitmaps( bmBack, bm, wxSize(0,0) );
433                 }
434             }
435 
436 #endif // ocpnUSE_SVG
437             if(!bm.Ok()){
438                 bm = graphics->GetSubBitmap( location );
439                 bm = MergeBitmaps( GetToggledBG(), bm, offset );
440 
441                 if(retSize != size){
442                     wxImage scaled_image = bm.ConvertToImage();
443                     bm = wxBitmap(scaled_image.Scale(retSize.x, retSize.y, wxIMAGE_QUALITY_HIGH));
444                 }
445             }
446 
447             if( rollover ) {
448                 tool->rolloverToggled = SetBitmapBrightness( bm, colorscheme );
449                 tool->rolloverToggledLoaded = true;
450                 return tool->rolloverToggled;
451             } else {
452                 tool->toggled = SetBitmapBrightness( bm, colorscheme );
453                 tool->toggledLoaded = true;
454                 return tool->toggled;
455             }
456         }
457         case TOOLICON_DISABLED: {
458             if( tool->disabledLoaded ) return tool->disabled;
459             wxRect location( tool->disabledLoc, size );
460 
461             wxBitmap bm;
462 #ifdef ocpnUSE_SVG
463             wxString fullFilePath = myConfigFileDir + this->sysname + wxFileName::GetPathSeparator() + toolname + _T("_disabled.svg");
464             if( wxFileExists( fullFilePath ) )
465                 bm = LoadSVG( fullFilePath, retSize.x, retSize.y );
466             else
467             {
468                 ///wxLogMessage( _T("Can't find SVG: ") + fullFilePath );
469 #endif // ocpnUSE_SVG
470                 bm = graphics->GetSubBitmap( location );
471 
472                 if( hasBackground ) {
473                     bm = MergeBitmaps( GetNormalBG(), bm, wxSize( 0, 0 ) );
474                 }
475 
476                 if(retSize != size){
477                     wxImage scaled_image = bm.ConvertToImage();
478                     bm = wxBitmap(scaled_image.Scale(retSize.x, retSize.y, wxIMAGE_QUALITY_HIGH));
479                 }
480 #ifdef ocpnUSE_SVG
481             }
482 #endif // ocpnUSE_SVG
483             if( currentOrientation ) {
484                 location.x -= verticalIconOffset.x;
485                 location.y -= verticalIconOffset.y;
486             }
487             tool->disabled = SetBitmapBrightness( bm, colorscheme );
488             tool->disabledLoaded = true;
489             return tool->disabled;
490         }
491     }
492     wxString msg( _T("A requested icon type for this tool was not found in the style: ") );
493     msg += toolname;
494     wxLogMessage( msg );
495     return wxBitmap( GetToolSize().x, GetToolSize().y ); // Prevents crashing.
496 }
497 
BuildPluginIcon(wxBitmap & bm,int iconType,double factor)498 wxBitmap Style::BuildPluginIcon( wxBitmap &bm, int iconType, double factor )
499 {
500     if(  !bm.IsOk() ) return wxNullBitmap;
501 
502     wxBitmap iconbm;
503 
504     switch( iconType ){
505         case TOOLICON_NORMAL:
506         case TOOLICON_TOGGLED:
507             {
508             if( hasBackground ) {
509                 wxBitmap bg;
510                 if(iconType == TOOLICON_NORMAL)
511                     bg = GetNormalBG();
512                 else
513                     bg = GetToggledBG();
514 
515                 if((bg.GetWidth() >= bm.GetWidth()) && (bg.GetHeight() >= bm.GetHeight())){
516                     int w = bg.GetWidth() * factor;
517                     int h = bg.GetHeight() * factor;
518                     wxImage scaled_image = bg.ConvertToImage();
519                     bg = wxBitmap(scaled_image.Scale(w, h, wxIMAGE_QUALITY_HIGH));
520 
521                     wxSize offset = wxSize( bg.GetWidth() - bm.GetWidth(), bg.GetHeight() - bm.GetHeight() );
522                     offset /= 2;
523                     iconbm = MergeBitmaps( bg, bm, offset );
524                 }
525                 else{
526                     // A bit of contorted logic for non-square backgrounds...
527                     double factor = ((double)bm.GetHeight()) / bg.GetHeight();
528                     int nw = bg.GetWidth() * factor;
529                     int nh = bm.GetHeight();
530                     if(bg.GetWidth() == bg.GetHeight())
531                         nw = nh;
532                     wxImage scaled_image = bg.ConvertToImage();
533                     bg = wxBitmap(scaled_image.Scale(nw, nh, wxIMAGE_QUALITY_HIGH));
534 
535                     wxSize offset = wxSize( bg.GetWidth() - bm.GetWidth(), bg.GetHeight() - bm.GetHeight() );
536                     offset /= 2;
537                     iconbm = MergeBitmaps( bg, bm, offset );
538                 }
539 
540             } else {
541                 wxBitmap bg( GetToolSize().x, GetToolSize().y );
542                 wxMemoryDC mdc( bg );
543                 wxSize offset = GetToolSize() - wxSize( bm.GetWidth(), bm.GetHeight() );
544                 offset /= 2;
545                 mdc.SetBackground( wxBrush( GetGlobalColor( _T("GREY2") ), wxBRUSHSTYLE_SOLID ) );
546                 mdc.Clear();
547                 mdc.SelectObject( wxNullBitmap );
548                 iconbm = MergeBitmaps( bg, bm, offset );
549             }
550             break;
551         }
552         default:
553             return wxNullBitmap;
554             break;
555     }
556     return SetBitmapBrightness( iconbm, colorscheme );
557 }
558 
SetBitmapBrightness(wxBitmap & bitmap,ColorScheme cs)559 wxBitmap Style::SetBitmapBrightness( wxBitmap& bitmap, ColorScheme cs )
560 {
561     double dimLevel;
562     switch( cs ){
563         case GLOBAL_COLOR_SCHEME_DUSK: {
564             dimLevel = 0.8;
565             break;
566         }
567         case GLOBAL_COLOR_SCHEME_NIGHT: {
568             dimLevel = 0.5;
569             break;
570         }
571         default: {
572             return bitmap;
573         }
574     }
575 
576     return SetBitmapBrightnessAbs(bitmap, dimLevel);
577 }
578 
SetBitmapBrightnessAbs(wxBitmap & bitmap,double level)579 wxBitmap Style::SetBitmapBrightnessAbs( wxBitmap& bitmap, double level )
580 {
581     wxImage image = bitmap.ConvertToImage();
582 
583     int gimg_width = image.GetWidth();
584     int gimg_height = image.GetHeight();
585 
586     for( int iy = 0; iy < gimg_height; iy++ ) {
587         for( int ix = 0; ix < gimg_width; ix++ ) {
588             if( !image.IsTransparent( ix, iy, 30 ) ) {
589                 wxImage::RGBValue rgb( image.GetRed( ix, iy ), image.GetGreen( ix, iy ),
590                         image.GetBlue( ix, iy ) );
591                 wxImage::HSVValue hsv = wxImage::RGBtoHSV( rgb );
592                 hsv.value = hsv.value * level;
593                 wxImage::RGBValue nrgb = wxImage::HSVtoRGB( hsv );
594                 image.SetRGB( ix, iy, nrgb.red, nrgb.green, nrgb.blue );
595             }
596         }
597     }
598     return wxBitmap( image );
599 }
600 
GetNormalBG()601 wxBitmap Style::GetNormalBG()
602 {
603     wxSize size = toolSize[currentOrientation];
604     return graphics->GetSubBitmap(
605             wxRect( normalBGlocation[currentOrientation].x, normalBGlocation[currentOrientation].y,
606                     size.x, size.y ) );
607 }
608 
GetActiveBG()609 wxBitmap Style::GetActiveBG()
610 {
611     return graphics->GetSubBitmap(
612             wxRect( activeBGlocation[currentOrientation].x, activeBGlocation[currentOrientation].y,
613                     toolSize[currentOrientation].x, toolSize[currentOrientation].y ) );
614 }
615 
GetToggledBG()616 wxBitmap Style::GetToggledBG()
617 {
618     wxSize size = toolSize[currentOrientation];
619     if( toggledBGSize[currentOrientation].x ) {
620         size = toggledBGSize[currentOrientation];
621     }
622     return graphics->GetSubBitmap( wxRect( toggledBGlocation[currentOrientation], size ) );
623 }
624 
GetToolbarStart()625 wxBitmap Style::GetToolbarStart()
626 {
627     wxSize size = toolbarStartSize[currentOrientation];
628     if( toolbarStartSize[currentOrientation].x == 0 ) {
629         size = toolbarStartSize[currentOrientation];
630     }
631     return graphics->GetSubBitmap( wxRect( toolbarStartLoc[currentOrientation], size ) );
632 }
633 
GetToolbarEnd()634 wxBitmap Style::GetToolbarEnd()
635 {
636     wxSize size = toolbarEndSize[currentOrientation];
637     if( toolbarEndSize[currentOrientation].x == 0 ) {
638         size = toolbarEndSize[currentOrientation];
639     }
640     return graphics->GetSubBitmap( wxRect( toolbarEndLoc[currentOrientation], size ) );
641 }
642 
GetToolbarCornerRadius()643 int Style::GetToolbarCornerRadius()
644 {
645     return cornerRadius[currentOrientation];
646 }
647 
DrawToolbarLineStart(wxBitmap & bmp,double scale)648 void Style::DrawToolbarLineStart( wxBitmap& bmp, double scale )
649 {
650     if( !HasToolbarStart() ) return;
651     wxMemoryDC dc( bmp );
652     wxBitmap sbmp = GetToolbarStart();
653     if( fabs(scale - 1.0) > 0.01){
654         int h = sbmp.GetHeight() * scale;
655         int w = sbmp.GetWidth() * scale;
656         if( (h > 0) && (w > 0)){
657             wxImage scaled_image = sbmp.ConvertToImage();
658             sbmp = wxBitmap(scaled_image.Scale(w, h, wxIMAGE_QUALITY_HIGH));
659         }
660     }
661     dc.DrawBitmap( sbmp, 0, 0, true );
662     dc.SelectObject( wxNullBitmap );
663 }
664 
DrawToolbarLineEnd(wxBitmap & bmp,double scale)665 void Style::DrawToolbarLineEnd( wxBitmap& bmp, double scale )
666 {
667     if( !HasToolbarStart() ) return;
668     wxMemoryDC dc( bmp );
669     wxBitmap sbmp = GetToolbarEnd();
670     if( fabs(scale - 1.0) > 0.01){
671         int h = sbmp.GetHeight() * scale;
672         int w = sbmp.GetWidth() * scale;
673         if( (h > 0) && (w > 0)){
674             wxImage scaled_image = sbmp.ConvertToImage();
675             sbmp = wxBitmap(scaled_image.Scale(w, h, wxIMAGE_QUALITY_HIGH));
676         }
677     }
678 
679     if( currentOrientation ) {
680         dc.DrawBitmap( sbmp, 0, bmp.GetHeight() - sbmp.GetHeight(), true );
681     } else {
682         dc.DrawBitmap( sbmp, bmp.GetWidth() - sbmp.GetWidth(), 0, true );
683     }
684     dc.SelectObject( wxNullBitmap );
685 }
686 
SetOrientation(long orient)687 void Style::SetOrientation( long orient )
688 {
689     int newOrient = 0;
690     if( orient == wxTB_VERTICAL ) newOrient = 1;
691     if( newOrient == currentOrientation ) return;
692     currentOrientation = newOrient;
693     Unload();
694 }
695 
GetOrientation()696 int Style::GetOrientation()
697 {
698     return currentOrientation;
699 }
700 
SetColorScheme(ColorScheme cs)701 void Style::SetColorScheme( ColorScheme cs )
702 {
703     colorscheme = cs;
704     Unload();
705 
706     if( (consoleTextBackgroundSize.x) && (consoleTextBackgroundSize.y)) {
707         wxBitmap bm = graphics->GetSubBitmap(
708             wxRect( consoleTextBackgroundLoc, consoleTextBackgroundSize ) );
709 
710     // The background bitmap in the icons file may be too small, so will grow it arbitrailly
711         wxImage image = bm.ConvertToImage();
712         image.Rescale( consoleTextBackgroundSize.GetX() * 2, consoleTextBackgroundSize.GetY() * 2 , wxIMAGE_QUALITY_NORMAL );
713         wxBitmap bn( image );
714         consoleTextBackground = SetBitmapBrightness( bn, cs );
715     }
716 }
717 
Unload()718 void Style::Unload()
719 {
720     for( unsigned int i = 0; i < tools.Count(); i++ ) {
721         Tool* tool = (Tool*) tools[i];
722         tool->Unload();
723     }
724 
725     for( unsigned int i = 0; i < icons.Count(); i++ ) {
726         Icon* icon = (Icon*) icons[i];
727         icon->Unload();
728     }
729 }
730 
Style(void)731 Style::Style( void )
732 {
733     graphics = NULL;
734     currentOrientation = 0;
735     colorscheme = GLOBAL_COLOR_SCHEME_DAY;
736     marginsInvisible = false;
737     hasBackground = false;
738     chartStatusIconWidth = 0;
739     chartStatusWindowTransparent = false;
740     embossHeight = 40;
741     embossFont = wxEmptyString;
742 
743     //  Set compass window style defauilts
744     compassMarginTop = 4;
745     compassMarginRight = 0;
746     compassMarginBottom = 4;
747     compassMarginLeft = 4;
748     compasscornerRadius = 3;
749     compassXoffset = 0;
750     compassYoffset = 0;
751 
752     for( int i = 0; i < 2; i++ ) {
753         toolbarStartLoc[i] = wxPoint( 0, 0 );
754         toolbarEndLoc[i] = wxPoint( 0, 0 );
755         cornerRadius[i] = 0;
756     }
757 }
758 
~Style(void)759 Style::~Style( void )
760 {
761     for( unsigned int i = 0; i < tools.Count(); i++ ) {
762         delete (Tool*) ( tools[i] );
763     }
764     tools.Clear();
765 
766     for( unsigned int i = 0; i < icons.Count(); i++ ) {
767         delete (Icon*) ( icons[i] );
768     }
769     icons.Clear();
770 
771     if( graphics ) delete graphics;
772 
773     toolIndex.clear();
774     iconIndex.clear();
775 }
776 
StyleManager(void)777 StyleManager::StyleManager(void)
778 {
779     isOK = false;
780     currentStyle = NULL;
781     Init( g_Platform->GetSharedDataDir() + _T("uidata") + wxFileName::GetPathSeparator() );
782     Init( g_Platform->GetHomeDir() );
783     Init( g_Platform->GetHomeDir() + _T(".opencpn") + wxFileName::GetPathSeparator() );
784     SetStyle( _T("") );
785 #ifdef ocpnUSE_SVG
786     wxLogMessage(_T("Using SVG Icons"));
787 #else
788     wxLogMessage(_T("Using PNG Icons"));
789 #endif
790 }
791 
StyleManager(const wxString & configDir)792 StyleManager::StyleManager(const wxString & configDir)
793 {
794     isOK = false;
795     currentStyle = NULL;
796     Init( configDir );
797     SetStyle( _T("") );
798 }
799 
~StyleManager(void)800 StyleManager::~StyleManager(void)
801 {
802     for( unsigned int i = 0; i < styles.Count(); i++ ) {
803         delete (Style*) ( styles[i] );
804     }
805     styles.Clear();
806 }
807 
Init(const wxString & fromPath)808 void StyleManager::Init(const wxString & fromPath)
809 {
810     TiXmlDocument doc;
811 
812     if( !wxDir::Exists( fromPath ) ) {
813         wxString msg = _T("No styles found at: ");
814         msg << fromPath;
815         wxLogMessage( msg );
816         return;
817     }
818 
819     wxDir dir( fromPath );
820     if( !dir.IsOpened() ) return;
821 
822     wxString filename;
823 
824     // We allow any number of styles to load from files called style<something>.xml
825 
826     bool more = dir.GetFirst( &filename, _T("style*.xml"), wxDIR_FILES );
827 
828     if( !more ) {
829         wxString msg = _T("No styles found at: ");
830         msg << fromPath;
831         wxLogMessage( msg );
832         return;
833     }
834 
835     bool firstFile = true;
836     while( more ) {
837         wxString name, extension;
838 
839         if( !firstFile ) more = dir.GetNext( &filename );
840         if( !more ) break;
841         firstFile = false;
842 
843         wxString fullFilePath = fromPath + filename;
844 
845         if( !doc.LoadFile( (const char*) fullFilePath.mb_str() ) ) {
846             wxString msg( _T("Attempt to load styles from this file failed: ") );
847             msg += fullFilePath;
848             wxLogMessage( msg );
849             continue;
850         }
851 
852         wxString msg( _T("Styles loading from ") );
853         msg += fullFilePath;
854         wxLogMessage( msg );
855 
856         TiXmlHandle hRoot( doc.RootElement() );
857 
858         wxString root = wxString( doc.RootElement()->Value(), wxConvUTF8 );
859         if( root != _T("styles" ) ) {
860             wxLogMessage( _T("    StyleManager: Expected XML Root <styles> not found.") );
861             continue;
862         }
863 
864         TiXmlElement* styleElem = hRoot.FirstChild().Element();
865 
866         for( ; styleElem; styleElem = styleElem->NextSiblingElement() ) {
867 
868             if( wxString( styleElem->Value(), wxConvUTF8 ) == _T("style") ) {
869 
870                 Style* style = new Style();
871                 styles.Add( style );
872 
873                 style->name = wxString( styleElem->Attribute( "name" ), wxConvUTF8 );
874                 style->sysname = wxString( styleElem->Attribute( "sysname" ), wxConvUTF8 );
875                 style->myConfigFileDir = fromPath;
876 
877                 TiXmlElement* subNode = styleElem->FirstChild()->ToElement();
878 
879                 for( ; subNode; subNode = subNode->NextSiblingElement() ) {
880                     wxString nodeType( subNode->Value(), wxConvUTF8 );
881 
882                     if( nodeType == _T("description") ) {
883                         style->description = wxString( subNode->GetText(), wxConvUTF8 );
884                         continue;
885                     }
886                     if( nodeType == _T("chart-status-icon") ) {
887                         int w = 0;
888                         subNode->QueryIntAttribute( "width", &w );
889                         style->chartStatusIconWidth = w;
890                         continue;
891                     }
892                     if( nodeType == _T("chart-status-window") ) {
893                         style->chartStatusWindowTransparent = wxString(
894                                 subNode->Attribute( "transparent" ), wxConvUTF8 ).Lower().IsSameAs(
895                                 _T("true") );
896                         continue;
897                     }
898                     if( nodeType == _T("embossed-indicators") ) {
899                         style->embossFont = wxString( subNode->Attribute( "font" ), wxConvUTF8 );
900                         subNode->QueryIntAttribute( "size", &(style->embossHeight) );
901                         continue;
902                     }
903                     if( nodeType == _T("graphics-file") ) {
904                         style->graphicsFile = wxString( subNode->Attribute( "name" ), wxConvUTF8 );
905                         isOK = true; // If we got this far we are at least partially OK...
906                         continue;
907                     }
908                     if( nodeType == _T("active-route") ) {
909                         TiXmlHandle handle( subNode );
910                         TiXmlElement* tag = handle.Child( "font-color", 0 ).ToElement();
911                         if( tag ) {
912                             int r, g, b;
913                             tag->QueryIntAttribute( "r", &r );
914                             tag->QueryIntAttribute( "g", &g );
915                             tag->QueryIntAttribute( "b", &b );
916                             style->consoleFontColor = wxColour( r, g, b );
917                         }
918                         tag = handle.Child( "text-background-location", 0 ).ToElement();
919                         if( tag ) {
920                             int x, y, w, h;
921                             tag->QueryIntAttribute( "x", &x );
922                             tag->QueryIntAttribute( "y", &y );
923                             tag->QueryIntAttribute( "width", &w );
924                             tag->QueryIntAttribute( "height", &h );
925                             style->consoleTextBackgroundLoc = wxPoint( x, y );
926                             style->consoleTextBackgroundSize = wxSize( w, h );
927                         }
928                         continue;
929                     }
930                     if( nodeType == _T("icons") ) {
931                         TiXmlElement* iconNode = subNode->FirstChild()->ToElement();
932 
933                         for( ; iconNode; iconNode = iconNode->NextSiblingElement() ) {
934                             wxString nodeType( iconNode->Value(), wxConvUTF8 );
935                             if( nodeType == _T("icon") ) {
936                                 Icon* icon = new Icon();
937                                 style->icons.Add( icon );
938                                 icon->name = wxString( iconNode->Attribute( "name" ), wxConvUTF8 );
939                                 style->iconIndex[icon->name] = style->icons.Count() - 1;
940                                 TiXmlHandle handle( iconNode );
941                                 TiXmlElement* tag = handle.Child( "icon-location", 0 ).ToElement();
942                                 if( tag ) {
943                                     int x, y;
944                                     tag->QueryIntAttribute( "x", &x );
945                                     tag->QueryIntAttribute( "y", &y );
946                                     icon->iconLoc = wxPoint( x, y );
947                                 }
948                                 tag = handle.Child( "size", 0 ).ToElement();
949                                 if( tag ) {
950                                     int x, y;
951                                     tag->QueryIntAttribute( "x", &x );
952                                     tag->QueryIntAttribute( "y", &y );
953                                     icon->size = wxSize( x, y );
954                                 }
955                             }
956                         }
957                     }
958                     if( nodeType == _T("tools") ) {
959                         TiXmlElement* toolNode = subNode->FirstChild()->ToElement();
960 
961                         for( ; toolNode; toolNode = toolNode->NextSiblingElement() ) {
962                             wxString nodeType( toolNode->Value(), wxConvUTF8 );
963 
964                             if( nodeType == _T("horizontal") || nodeType == _T("vertical") ) {
965                                 int orientation = 0;
966                                 if( nodeType == _T("vertical") ) orientation = 1;
967 
968                                 TiXmlElement* attrNode = toolNode->FirstChild()->ToElement();
969                                 for( ; attrNode; attrNode = attrNode->NextSiblingElement() ) {
970                                     wxString nodeType( attrNode->Value(), wxConvUTF8 );
971                                     if( nodeType == _T("separation") ) {
972                                         attrNode->QueryIntAttribute( "distance",
973                                                 &style->toolSeparation[orientation] );
974                                         continue;
975                                     }
976                                     if( nodeType == _T("margin") ) {
977                                         attrNode->QueryIntAttribute( "top",
978                                                 &style->toolMarginTop[orientation] );
979                                         attrNode->QueryIntAttribute( "right",
980                                                 &style->toolMarginRight[orientation] );
981                                         attrNode->QueryIntAttribute( "bottom",
982                                                 &style->toolMarginBottom[orientation] );
983                                         attrNode->QueryIntAttribute( "left",
984                                                 &style->toolMarginLeft[orientation] );
985                                         wxString invis = wxString(
986                                                 attrNode->Attribute( "invisible" ), wxConvUTF8 );
987                                         style->marginsInvisible = ( invis.Lower() == _T("true") );
988                                         continue;;
989                                     }
990                                     if( nodeType == _T("toggled-location") ) {
991                                         int x, y;
992                                         attrNode->QueryIntAttribute( "x", &x );
993                                         attrNode->QueryIntAttribute( "y", &y );
994                                         style->toggledBGlocation[orientation] = wxPoint( x, y );
995                                         x = 0;
996                                         y = 0;
997                                         attrNode->QueryIntAttribute( "width", &x );
998                                         attrNode->QueryIntAttribute( "height", &y );
999                                         style->toggledBGSize[orientation] = wxSize( x, y );
1000                                         continue;
1001                                     }
1002                                     if( nodeType == _T("toolbar-start") ) {
1003                                         int x, y;
1004                                         attrNode->QueryIntAttribute( "x", &x );
1005                                         attrNode->QueryIntAttribute( "y", &y );
1006                                         style->toolbarStartLoc[orientation] = wxPoint( x, y );
1007                                         x = 0;
1008                                         y = 0;
1009                                         attrNode->QueryIntAttribute( "width", &x );
1010                                         attrNode->QueryIntAttribute( "height", &y );
1011                                         style->toolbarStartSize[orientation] = wxSize( x, y );
1012                                         continue;
1013                                     }
1014                                     if( nodeType == _T("toolbar-end") ) {
1015                                         int x, y;
1016                                         attrNode->QueryIntAttribute( "x", &x );
1017                                         attrNode->QueryIntAttribute( "y", &y );
1018                                         style->toolbarEndLoc[orientation] = wxPoint( x, y );
1019                                         x = 0;
1020                                         y = 0;
1021                                         attrNode->QueryIntAttribute( "width", &x );
1022                                         attrNode->QueryIntAttribute( "height", &y );
1023                                         style->toolbarEndSize[orientation] = wxSize( x, y );
1024                                         continue;
1025                                     }
1026                                     if( nodeType == _T("toolbar-corners") ) {
1027                                         int r;
1028                                         attrNode->QueryIntAttribute( "radius", &r );
1029                                         style->cornerRadius[orientation] = r;
1030                                         continue;
1031                                     }
1032                                     if( nodeType == _T("background-location") ) {
1033                                         int x, y;
1034                                         attrNode->QueryIntAttribute( "x", &x );
1035                                         attrNode->QueryIntAttribute( "y", &y );
1036                                         style->normalBGlocation[orientation] = wxPoint( x, y );
1037                                         style->HasBackground( true );
1038                                         continue;
1039                                     }
1040                                     if( nodeType == _T("active-location") ) {
1041                                         int x, y;
1042                                         attrNode->QueryIntAttribute( "x", &x );
1043                                         attrNode->QueryIntAttribute( "y", &y );
1044                                         style->activeBGlocation[orientation] = wxPoint( x, y );
1045                                         continue;
1046                                     }
1047                                     if( nodeType == _T("size") ) {
1048                                         int x, y;
1049                                         attrNode->QueryIntAttribute( "x", &x );
1050                                         attrNode->QueryIntAttribute( "y", &y );
1051                                         style->toolSize[orientation] = wxSize( x, y );
1052                                         continue;
1053                                     }
1054                                     if( nodeType == _T("icon-offset") ) {
1055                                         int x, y;
1056                                         attrNode->QueryIntAttribute( "x", &x );
1057                                         attrNode->QueryIntAttribute( "y", &y );
1058                                         style->verticalIconOffset = wxSize( x, y );
1059                                         continue;
1060                                     }
1061                                 }
1062                                 continue;
1063                             }
1064                             if( nodeType == _T("compass") ) {
1065 
1066                                 TiXmlElement* attrNode = toolNode->FirstChild()->ToElement();
1067                                 for( ; attrNode; attrNode = attrNode->NextSiblingElement() ) {
1068                                     wxString nodeType( attrNode->Value(), wxConvUTF8 );
1069                                     if( nodeType == _T("margin") ) {
1070                                         attrNode->QueryIntAttribute( "top",
1071                                                                      &style->compassMarginTop );
1072                                         attrNode->QueryIntAttribute( "right",
1073                                                                      &style->compassMarginRight );
1074                                         attrNode->QueryIntAttribute( "bottom",
1075                                                                      &style->compassMarginBottom );
1076                                         attrNode->QueryIntAttribute( "left",
1077                                                                      &style->compassMarginLeft );
1078                                         continue;
1079                                     }
1080                                     if( nodeType == _T("compass-corners") ) {
1081                                             int r;
1082                                             attrNode->QueryIntAttribute( "radius", &r );
1083                                             style->compasscornerRadius = r;
1084                                             continue;
1085                                         }
1086                                     if( nodeType == _T("offset") ) {
1087                                         attrNode->QueryIntAttribute( "x",
1088                                                                      &style->compassXoffset );
1089                                         attrNode->QueryIntAttribute( "y",
1090                                                                      &style->compassYoffset );
1091                                         continue;
1092                                     }
1093                                 }
1094                              }
1095 
1096                              if( nodeType == _T("tool") ) {
1097                                 Tool* tool = new Tool();
1098                                 style->tools.Add( tool );
1099                                 tool->name = wxString( toolNode->Attribute( "name" ), wxConvUTF8 );
1100                                 style->toolIndex[tool->name] = style->tools.Count() - 1;
1101                                 TiXmlHandle toolHandle( toolNode );
1102                                 TiXmlElement* toolTag =
1103                                         toolHandle.Child( "icon-location", 0 ).ToElement();
1104                                 if( toolTag ) {
1105                                     int x, y;
1106                                     toolTag->QueryIntAttribute( "x", &x );
1107                                     toolTag->QueryIntAttribute( "y", &y );
1108                                     tool->iconLoc = wxPoint( x, y );
1109                                 }
1110                                 toolTag = toolHandle.Child( "rollover-location", 0 ).ToElement();
1111                                 if( toolTag ) {
1112                                     int x, y;
1113                                     toolTag->QueryIntAttribute( "x", &x );
1114                                     toolTag->QueryIntAttribute( "y", &y );
1115                                     tool->rolloverLoc = wxPoint( x, y );
1116                                 }
1117                                 toolTag = toolHandle.Child( "disabled-location", 0 ).ToElement();
1118                                 if( toolTag ) {
1119                                     int x, y;
1120                                     toolTag->QueryIntAttribute( "x", &x );
1121                                     toolTag->QueryIntAttribute( "y", &y );
1122                                     tool->disabledLoc = wxPoint( x, y );
1123                                 }
1124                                 toolTag = toolHandle.Child( "size", 0 ).ToElement();
1125                                 if( toolTag ) {
1126                                     int x, y;
1127                                     toolTag->QueryIntAttribute( "x", &x );
1128                                     toolTag->QueryIntAttribute( "y", &y );
1129                                     tool->customSize = wxSize( x, y );
1130                                 }
1131                                 continue;
1132                             }
1133                         }
1134                         continue;
1135                     }
1136                 }
1137             }
1138         }
1139     }
1140 }
1141 
SetStyle(wxString name)1142 void StyleManager::SetStyle(wxString name)
1143 {
1144     Style* style = NULL;
1145     bool ok = true;
1146     if( currentStyle ) currentStyle->Unload();
1147     else ok = false;
1148 
1149     bool selectFirst = false;
1150 
1151     // Verify the named style exists
1152     //  If not, just use the "first" style
1153     bool bstyleFound = false;
1154 
1155     for( unsigned int i = 0; i < styles.Count(); i++ ) {
1156         style = (Style*) ( styles.Item( i ) );
1157         if( style->name == name ) {
1158             bstyleFound = true;
1159             break;
1160         }
1161     }
1162 
1163     if( (name.Length() == 0) || !bstyleFound )
1164         selectFirst = true;
1165 
1166     for( unsigned int i = 0; i < styles.Count(); i++ ) {
1167         style = (Style*) ( styles[i] );
1168         if( style->name == name || selectFirst ) {
1169             if( style->graphics ) {
1170                 currentStyle = style;
1171                 ok = true;
1172                 break;
1173             }
1174 
1175             wxString fullFilePath = style->myConfigFileDir + wxFileName::GetPathSeparator()
1176                     + style->graphicsFile;
1177 
1178             if( !wxFileName::FileExists( fullFilePath ) ) {
1179                 wxString msg( _T("Styles Graphics File not found: ") );
1180                 msg += fullFilePath;
1181                 wxLogMessage( msg );
1182                 ok = false;
1183                 if( selectFirst ) continue;
1184                 break;
1185             }
1186 
1187             wxImage img; // Only image does PNG LoadFile properly on GTK.
1188 
1189             if( !img.LoadFile( fullFilePath, wxBITMAP_TYPE_PNG ) ) {
1190                 wxString msg( _T("Styles Graphics File failed to load: ") );
1191                 msg += fullFilePath;
1192                 wxLogMessage( msg );
1193                 ok = false;
1194                 break;
1195             }
1196             style->graphics = new wxBitmap( img );
1197             currentStyle = style;
1198             ok = true;
1199             break;
1200         }
1201     }
1202 
1203     if( !ok || !currentStyle->graphics ) {
1204         wxString msg( _T("The requested style was not found: ") );
1205         msg += name;
1206         wxLogMessage( msg );
1207         return;
1208     }
1209 
1210     if(currentStyle) {
1211         if( (currentStyle->consoleTextBackgroundSize.x) && (currentStyle->consoleTextBackgroundSize.y)) {
1212             currentStyle->consoleTextBackground = currentStyle->graphics->GetSubBitmap(
1213                 wxRect( currentStyle->consoleTextBackgroundLoc, currentStyle->consoleTextBackgroundSize ) );
1214         }
1215     }
1216 
1217     if(currentStyle)
1218         nextInvocationStyle = currentStyle->name;
1219 
1220     return;
1221 }
1222 
GetCurrentStyle()1223 Style* StyleManager::GetCurrentStyle()
1224 {
1225     return currentStyle;
1226 }
1227