]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gdiimage.cpp
create the DIBs in correct (and not down up) line order
[wxWidgets.git] / src / msw / gdiimage.cpp
CommitLineData
0d0512bd
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: msw/gdiimage.cpp
3// Purpose: wxGDIImage implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.11.99
7// RCS-ID: $Id$
8// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
6c9a19aa 9// Licence: wxWindows licence
0d0512bd
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "gdiimage.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/string.h"
f94dfb38 33 #include "wx/log.h"
0d0512bd
VZ
34#endif // WX_PRECOMP
35
e42a6c18
VZ
36#include "wx/msw/private.h"
37
0d0512bd
VZ
38#include "wx/app.h"
39
04ef50df 40#ifndef __WXMICROWIN__
0d0512bd 41#include "wx/msw/dib.h"
04ef50df
JS
42#endif
43
c25a510b 44#include "wx/msw/bitmap.h"
0d0512bd 45#include "wx/msw/gdiimage.h"
f66f0fd7
GRG
46#include "wx/bitmap.h"
47
d162a7ee
VZ
48#include "wx/listimpl.cpp"
49WX_DEFINE_LIST(wxGDIImageHandlerList);
50
51
8f177c8e 52#ifdef __WIN16__
f66f0fd7 53# include "wx/msw/curico.h"
8f177c8e
VZ
54#endif // __WIN16__
55
0d0512bd
VZ
56// ----------------------------------------------------------------------------
57// private classes
58// ----------------------------------------------------------------------------
59
04ef50df
JS
60#ifndef __WXMICROWIN__
61
0d0512bd
VZ
62// all image handlers are declared/defined in this file because the outside
63// world doesn't have to know about them (but only about wxBITMAP_TYPE_XXX ids)
64
65class WXDLLEXPORT wxBMPFileHandler : public wxBitmapHandler
66{
67public:
68 wxBMPFileHandler() : wxBitmapHandler(_T("Windows bitmap file"), _T("bmp"),
69 wxBITMAP_TYPE_BMP)
70 {
71 }
72
73 virtual bool LoadFile(wxBitmap *bitmap,
74 const wxString& name, long flags,
75 int desiredWidth, int desiredHeight);
76 virtual bool SaveFile(wxBitmap *bitmap,
77 const wxString& name, int type,
78 const wxPalette *palette = NULL);
79
80private:
81 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
82};
83
84class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
85{
86public:
87 wxBMPResourceHandler() : wxBitmapHandler(_T("Windows bitmap resource"),
88 wxEmptyString,
89 wxBITMAP_TYPE_BMP_RESOURCE)
90 {
91 }
92
93 virtual bool LoadFile(wxBitmap *bitmap,
94 const wxString& name, long flags,
95 int desiredWidth, int desiredHeight);
96
97private:
98 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
99};
100
101class WXDLLEXPORT wxIconHandler : public wxGDIImageHandler
102{
103public:
104 wxIconHandler(const wxString& name, const wxString& ext, long type)
105 : wxGDIImageHandler(name, ext, type)
106 {
107 }
108
109 // creating and saving icons is not supported
110 virtual bool Create(wxGDIImage *WXUNUSED(image),
111 void *WXUNUSED(data),
112 long WXUNUSED(flags),
113 int WXUNUSED(width),
114 int WXUNUSED(height),
115 int WXUNUSED(depth) = 1)
116 {
4f8090e0 117 return false;
0d0512bd
VZ
118 }
119
120 virtual bool Save(wxGDIImage *WXUNUSED(image),
121 const wxString& WXUNUSED(name),
122 int WXUNUSED(type))
123 {
4f8090e0 124 return false;
0d0512bd
VZ
125 }
126
127 virtual bool Load(wxGDIImage *image,
128 const wxString& name,
129 long flags,
130 int desiredWidth, int desiredHeight)
131 {
132 wxIcon *icon = wxDynamicCast(image, wxIcon);
4f8090e0 133 wxCHECK_MSG( icon, false, _T("wxIconHandler only works with icons") );
0d0512bd
VZ
134
135 return LoadIcon(icon, name, flags, desiredWidth, desiredHeight);
136 }
137
138protected:
139 virtual bool LoadIcon(wxIcon *icon,
140 const wxString& name, long flags,
141 int desiredWidth = -1, int desiredHeight = -1) = 0;
142};
143
144class WXDLLEXPORT wxICOFileHandler : public wxIconHandler
145{
146public:
147 wxICOFileHandler() : wxIconHandler(_T("ICO icon file"),
148 _T("ico"),
149 wxBITMAP_TYPE_ICO)
150 {
151 }
152
153 virtual bool LoadIcon(wxIcon *icon,
154 const wxString& name, long flags,
155 int desiredWidth = -1, int desiredHeight = -1);
156
157private:
158 DECLARE_DYNAMIC_CLASS(wxICOFileHandler)
159};
160
161class WXDLLEXPORT wxICOResourceHandler: public wxIconHandler
162{
163public:
164 wxICOResourceHandler() : wxIconHandler(_T("ICO resource"),
165 _T("ico"),
166 wxBITMAP_TYPE_ICO_RESOURCE)
167 {
168 }
169
170 virtual bool LoadIcon(wxIcon *icon,
171 const wxString& name, long flags,
172 int desiredWidth = -1, int desiredHeight = -1);
173
174private:
175 DECLARE_DYNAMIC_CLASS(wxICOResourceHandler)
176};
177
178// ----------------------------------------------------------------------------
179// wxWin macros
180// ----------------------------------------------------------------------------
181
621b3e21
VZ
182IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
183IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
184IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxObject)
185IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxObject)
0d0512bd
VZ
186
187// ----------------------------------------------------------------------------
188// private functions
189// ----------------------------------------------------------------------------
190
04ef50df
JS
191#endif
192 // __MICROWIN__
0d0512bd
VZ
193
194// ============================================================================
195// implementation
196// ============================================================================
197
d162a7ee 198wxGDIImageHandlerList wxGDIImage::ms_handlers;
0d0512bd
VZ
199
200// ----------------------------------------------------------------------------
201// wxGDIImage functions forwarded to wxGDIImageRefData
202// ----------------------------------------------------------------------------
203
204bool wxGDIImage::FreeResource(bool WXUNUSED(force))
205{
206 if ( !IsNull() )
207 {
208 GetGDIImageData()->Free();
209 GetGDIImageData()->m_handle = 0;
210 }
211
4f8090e0 212 return true;
0d0512bd
VZ
213}
214
2b5f62a0 215WXHANDLE wxGDIImage::GetResourceHandle() const
0d0512bd
VZ
216{
217 return GetHandle();
218}
219
220// ----------------------------------------------------------------------------
221// wxGDIImage handler stuff
222// ----------------------------------------------------------------------------
223
224void wxGDIImage::AddHandler(wxGDIImageHandler *handler)
225{
226 ms_handlers.Append(handler);
227}
228
229void wxGDIImage::InsertHandler(wxGDIImageHandler *handler)
230{
231 ms_handlers.Insert(handler);
232}
233
234bool wxGDIImage::RemoveHandler(const wxString& name)
235{
236 wxGDIImageHandler *handler = FindHandler(name);
237 if ( handler )
238 {
239 ms_handlers.DeleteObject(handler);
4f8090e0 240 return true;
0d0512bd
VZ
241 }
242 else
4f8090e0 243 return false;
0d0512bd
VZ
244}
245
246wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& name)
247{
d162a7ee 248 wxGDIImageHandlerList::Node *node = ms_handlers.GetFirst();
0d0512bd
VZ
249 while ( node )
250 {
d162a7ee 251 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
252 if ( handler->GetName() == name )
253 return handler;
4f8090e0 254 node = node->GetNext();
0d0512bd
VZ
255 }
256
257 return NULL;
258}
259
260wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& extension,
261 long type)
262{
d162a7ee 263 wxGDIImageHandlerList::Node *node = ms_handlers.GetFirst();
0d0512bd
VZ
264 while ( node )
265 {
d162a7ee 266 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
267 if ( (handler->GetExtension() = extension) &&
268 (type == -1 || handler->GetType() == type) )
269 {
270 return handler;
271 }
272
4f8090e0 273 node = node->GetNext();
0d0512bd
VZ
274 }
275 return NULL;
276}
277
278wxGDIImageHandler *wxGDIImage::FindHandler(long type)
279{
d162a7ee 280 wxGDIImageHandlerList::Node *node = ms_handlers.GetFirst();
0d0512bd
VZ
281 while ( node )
282 {
d162a7ee 283 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
284 if ( handler->GetType() == type )
285 return handler;
286
4f8090e0 287 node = node->GetNext();
0d0512bd
VZ
288 }
289
290 return NULL;
291}
292
293void wxGDIImage::CleanUpHandlers()
294{
d162a7ee 295 wxGDIImageHandlerList::Node *node = ms_handlers.GetFirst();
0d0512bd
VZ
296 while ( node )
297 {
d162a7ee
VZ
298 wxGDIImageHandler *handler = node->GetData();
299 wxGDIImageHandlerList::Node *next = node->GetNext();
0d0512bd
VZ
300 delete handler;
301 delete node;
302 node = next;
303 }
304}
305
306void wxGDIImage::InitStandardHandlers()
307{
04ef50df 308#ifndef __WXMICROWIN__
0d0512bd
VZ
309 AddHandler(new wxBMPResourceHandler);
310 AddHandler(new wxBMPFileHandler);
0d0512bd
VZ
311 AddHandler(new wxICOResourceHandler);
312 AddHandler(new wxICOFileHandler);
04ef50df 313#endif
0d0512bd
VZ
314}
315
04ef50df
JS
316#ifndef __WXMICROWIN__
317
0d0512bd
VZ
318// ----------------------------------------------------------------------------
319// wxBitmap handlers
320// ----------------------------------------------------------------------------
321
322bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap,
323 const wxString& name, long WXUNUSED(flags),
324 int WXUNUSED(desiredWidth),
325 int WXUNUSED(desiredHeight))
326{
327 // TODO: load colourmap.
328 bitmap->SetHBITMAP((WXHBITMAP)::LoadBitmap(wxGetInstance(), name));
329
8bbbae21 330 if ( !bitmap->Ok() )
0d0512bd
VZ
331 {
332 // it's probably not found
333 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."),
334 name.c_str());
8bbbae21 335
4f8090e0 336 return false;
8bbbae21
VZ
337 }
338
339 BITMAP bm;
340 if ( !::GetObject(GetHbitmapOf(*bitmap), sizeof(BITMAP), (LPSTR) &bm) )
341 {
342 wxLogLastError(wxT("GetObject(HBITMAP)"));
0d0512bd
VZ
343 }
344
8bbbae21
VZ
345 bitmap->SetWidth(bm.bmWidth);
346 bitmap->SetHeight(bm.bmHeight);
347 bitmap->SetDepth(bm.bmBitsPixel);
348
4f8090e0 349 return true;
0d0512bd
VZ
350}
351
352bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap,
353 const wxString& name, long WXUNUSED(flags),
354 int WXUNUSED(desiredWidth),
355 int WXUNUSED(desiredHeight))
356{
357#if wxUSE_IMAGE_LOADING_IN_MSW
358 wxPalette *palette = NULL;
359 bool success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0;
d275c7eb
VZ
360
361#if wxUSE_PALETTE
0d0512bd
VZ
362 if ( success && palette )
363 {
364 bitmap->SetPalette(*palette);
365 }
366
367 // it was copied by the bitmap if it was loaded successfully
368 delete palette;
d275c7eb 369#endif // wxUSE_PALETTE
0d0512bd
VZ
370
371 return success;
372#else
4f8090e0 373 return false;
0d0512bd
VZ
374#endif
375}
376
377bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap,
378 const wxString& name,
379 int WXUNUSED(type),
380 const wxPalette *pal)
381{
382#if wxUSE_IMAGE_LOADING_IN_MSW
d275c7eb
VZ
383
384#if wxUSE_PALETTE
0d0512bd
VZ
385 wxPalette *actualPalette = (wxPalette *)pal;
386 if ( !actualPalette )
387 actualPalette = bitmap->GetPalette();
d275c7eb
VZ
388#else
389 wxPalette *actualPalette = NULL;
390#endif // wxUSE_PALETTE
391
0d0512bd
VZ
392 return wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0;
393#else
4f8090e0 394 return false;
0d0512bd
VZ
395#endif
396}
397
398// ----------------------------------------------------------------------------
399// wxIcon handlers
400// ----------------------------------------------------------------------------
401
402bool wxICOFileHandler::LoadIcon(wxIcon *icon,
403 const wxString& name,
33ac7e6f 404 long WXUNUSED(flags),
0d0512bd
VZ
405 int desiredWidth, int desiredHeight)
406{
407#if wxUSE_RESOURCE_LOADING_IN_MSW
408 icon->UnRef();
409
410 // actual size
411 wxSize size;
412
413#ifdef __WIN32__
a4352768
VZ
414 HICON hicon = NULL;
415
2dace059
VZ
416 // Parse the filename: it may be of the form "filename;n" in order to
417 // specify the nth icon in the file.
418 //
419 // For the moment, ignore the issue of possible semicolons in the
420 // filename.
ff9aab3c 421 int iconIndex = 0;
2dace059 422 wxString nameReal(name);
ff9aab3c 423 wxString strIconIndex = name.AfterLast(wxT(';'));
b642d457 424 if (strIconIndex != name)
ff9aab3c
JS
425 {
426 iconIndex = wxAtoi(strIconIndex);
2dace059 427 nameReal = name.BeforeLast(wxT(';'));
ff9aab3c
JS
428 }
429
2b5f62a0
VZ
430#if 0
431 // If we don't know what size icon we're looking for,
432 // try to find out what's there.
433 // Unfortunately this doesn't work, because ExtractIconEx
434 // will scale the icon to the 'desired' size, even if that
435 // size of icon isn't explicitly stored. So we would have
436 // to parse the icon file outselves.
437 if ( desiredWidth == -1 &&
438 desiredHeight == -1)
439 {
440 // Try loading a large icon first
441 if ( ::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) == 1)
442 {
443 }
444 // Then try loading a small icon
445 else if ( ::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) == 1)
446 {
447 }
448 }
449 else
450#endif
a4352768
VZ
451 // were we asked for a large icon?
452 if ( desiredWidth == ::GetSystemMetrics(SM_CXICON) &&
453 desiredHeight == ::GetSystemMetrics(SM_CYICON) )
454 {
ff9aab3c 455 // get the specified large icon from file
2dace059 456 if ( !::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) )
a4352768
VZ
457 {
458 // it is not an error, but it might still be useful to be informed
459 // about it optionally
460 wxLogTrace(_T("iconload"),
461 _T("No large icons found in the file '%s'."),
462 name.c_str());
463 }
464 }
465 else if ( desiredWidth == ::GetSystemMetrics(SM_CXSMICON) &&
466 desiredHeight == ::GetSystemMetrics(SM_CYSMICON) )
467 {
ff9aab3c 468 // get the specified small icon from file
2dace059 469 if ( !::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) )
a4352768
VZ
470 {
471 wxLogTrace(_T("iconload"),
472 _T("No small icons found in the file '%s'."),
473 name.c_str());
474 }
475 }
476 //else: not standard size, load below
477
478 if ( !hicon )
479 {
d8f3f983
RD
480 // take any size icon from the file by index
481 hicon = ::ExtractIcon(wxGetInstance(), nameReal, iconIndex);
a4352768
VZ
482 }
483
0d0512bd
VZ
484 if ( !hicon )
485 {
486 wxLogSysError(_T("Failed to load icon from the file '%s'"),
487 name.c_str());
488
4f8090e0 489 return false;
0d0512bd
VZ
490 }
491
6bad4c32 492 size = wxGetHiconSize(hicon);
0d0512bd
VZ
493#else // Win16
494 HICON hicon = ReadIconFile((wxChar *)name.c_str(),
495 wxGetInstance(),
496 &size.x, &size.y);
1cfa5d8e
JS
497 HICON hIcon = 0;
498 HANDLE hDIB = 0;
499
500 // Read the icon DIB from file
501 if( (hDIB = ReadIcon((wxChar *)name.c_str(), &size.x, &size.y)) == (HANDLE) NULL)
502 return false;
503
504 // Create an icon from DIB
505 hicon = MakeIcon( hDIB, wxGetInstance());
506 GlobalFree( hDIB);
0d0512bd
VZ
507#endif // Win32/Win16
508
509 if ( (desiredWidth != -1 && desiredWidth != size.x) ||
510 (desiredHeight != -1 && desiredHeight != size.y) )
511 {
a4352768 512 wxLogTrace(_T("iconload"),
4f8090e0 513 _T("Returning false from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"),
a4352768
VZ
514 size.x, size.y,
515 desiredWidth, desiredHeight);
0d0512bd
VZ
516
517 ::DestroyIcon(hicon);
518
4f8090e0 519 return false;
0d0512bd
VZ
520 }
521
522 icon->SetHICON((WXHICON)hicon);
523 icon->SetSize(size.x, size.y);
524
525 return icon->Ok();
526#else
4f8090e0 527 return false;
0d0512bd
VZ
528#endif
529}
530
531bool wxICOResourceHandler::LoadIcon(wxIcon *icon,
532 const wxString& name,
33ac7e6f 533 long WXUNUSED(flags),
0d0512bd
VZ
534 int desiredWidth, int desiredHeight)
535{
536 HICON hicon;
537
9cb9fdb3
VZ
538 // do we need the icon of the specific size or would any icon do?
539 bool hasSize = desiredWidth != -1 || desiredHeight != -1;
540
541 wxASSERT_MSG( !hasSize || (desiredWidth != -1 && desiredHeight != -1),
542 _T("width and height should be either both -1 or not") );
543
2dace059
VZ
544 // try to load the icon from this program first to allow overriding the
545 // standard icons (although why one would want to do it considering that
546 // we already have wxApp::GetStdIcon() is unclear)
9990cb50
VZ
547
548 // note that we can't just always call LoadImage() because it seems to do
549 // some icon rescaling internally which results in very ugly 16x16 icons
0d0512bd 550#if defined(__WIN32__) && !defined(__SC__)
9990cb50 551 if ( hasSize )
0d0512bd 552 {
9990cb50
VZ
553 hicon = (HICON)::LoadImage(wxGetInstance(), name, IMAGE_ICON,
554 desiredWidth, desiredHeight,
555 LR_DEFAULTCOLOR);
0d0512bd 556 }
9990cb50 557 else
fea2b62e 558#endif // Win32/!Win32
9990cb50
VZ
559 {
560 hicon = ::LoadIcon(wxGetInstance(), name);
561 }
fea2b62e 562
2dace059 563 // next check if it's not a standard icon
9cb9fdb3 564 if ( !hicon && !hasSize )
2dace059
VZ
565 {
566 static const struct
567 {
568 const wxChar *name;
569 LPTSTR id;
570 } stdIcons[] =
571 {
572 { wxT("wxICON_QUESTION"), IDI_QUESTION },
573 { wxT("wxICON_WARNING"), IDI_EXCLAMATION },
574 { wxT("wxICON_ERROR"), IDI_HAND },
c2edb18a 575 { wxT("wxICON_INFORMATION"), IDI_ASTERISK },
2dace059
VZ
576 };
577
578 for ( size_t nIcon = 0; !hicon && nIcon < WXSIZEOF(stdIcons); nIcon++ )
579 {
580 if ( name == stdIcons[nIcon].name )
581 {
9cb9fdb3 582 hicon = ::LoadIcon((HINSTANCE)NULL, stdIcons[nIcon].id);
2dace059
VZ
583 }
584 }
585 }
586
6bad4c32 587 wxSize size = wxGetHiconSize(hicon);
0d0512bd
VZ
588 icon->SetSize(size.x, size.y);
589
0d0512bd
VZ
590 icon->SetHICON((WXHICON)hicon);
591
592 return icon->Ok();
593}
594
595// ----------------------------------------------------------------------------
596// private functions
597// ----------------------------------------------------------------------------
598
6bad4c32 599wxSize wxGetHiconSize(HICON hicon)
0d0512bd
VZ
600{
601 wxSize size(32, 32); // default
602
603#ifdef __WIN32__
604 // Win32s doesn't have GetIconInfo function...
605 if ( hicon && wxGetOsVersion() != wxWIN32S )
606 {
607 ICONINFO info;
608 if ( !::GetIconInfo(hicon, &info) )
609 {
f6bcfd97 610 wxLogLastError(wxT("GetIconInfo"));
0d0512bd
VZ
611 }
612 else
613 {
614 HBITMAP hbmp = info.hbmMask;
615 if ( hbmp )
616 {
617 BITMAP bm;
618 if ( ::GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm) )
619 {
620 size = wxSize(bm.bmWidth, bm.bmHeight);
621 }
622
623 ::DeleteObject(info.hbmMask);
624 }
625 if ( info.hbmColor )
626 ::DeleteObject(info.hbmColor);
627 }
628 }
629#endif
630
631 return size;
632}
04ef50df
JS
633#endif
634 // __WXMICROWIN__