Include wx/dcmemory.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / cocoa / dcmemory.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/dcmemory.mm
3 // Purpose:     wxMemoryDC class
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2003/03/16
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2002 David Elliott
9 // Licence:     wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #ifndef WX_PRECOMP
15     #include "wx/log.h"
16     #include "wx/dcmemory.h"
17 #endif //WX_PRECOMP
18
19 #include "wx/cocoa/autorelease.h"
20
21 #import <AppKit/NSImage.h>
22 #import <AppKit/NSAffineTransform.h>
23 #import <AppKit/NSGraphicsContext.h>
24 #import <AppKit/NSColor.h>
25 #import <AppKit/NSBezierPath.h>
26
27 //-----------------------------------------------------------------------------
28 // wxMemoryDC
29 //-----------------------------------------------------------------------------
30
31 IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC,wxDC)
32
33 wxMemoryDC::wxMemoryDC(void)
34 {
35     m_cocoaNSImage = NULL;
36     m_ok = false;
37 }
38
39 wxMemoryDC::wxMemoryDC( wxDC *WXUNUSED(dc) )
40 {
41     m_cocoaNSImage = NULL;
42     m_ok = false;
43 }
44
45 wxMemoryDC::~wxMemoryDC(void)
46 {
47     CocoaUnwindStackAndLoseFocus();
48     [m_cocoaNSImage release];
49 }
50
51 bool wxMemoryDC::CocoaLockFocus()
52 {
53     if(m_cocoaNSImage)
54     {
55         [m_cocoaNSImage lockFocus];
56         sm_cocoaDCStack.Insert(this);
57         NSAffineTransform *newTransform = CocoaGetWxToBoundsTransform([m_cocoaNSImage isFlipped], [m_cocoaNSImage size].height);
58         [newTransform retain];
59         [m_cocoaWxToBoundsTransform release];
60         m_cocoaWxToBoundsTransform = newTransform;
61         CocoaApplyTransformations();
62         return true;
63     }
64     return false;
65 }
66
67 bool wxMemoryDC::CocoaUnlockFocus()
68 {
69     [m_cocoaNSImage unlockFocus];
70     return true;
71 }
72
73 // NOTE: The AppKit is unable to draw onto an NSBitmapImageRep so we must
74 // instead copy the data to an offscreen window, then copy it back
75 void wxMemoryDC::SelectObject( const wxBitmap& bitmap )
76 {
77     wxAutoNSAutoreleasePool pool;
78     if(m_selectedBitmap.Ok())
79     {
80         CocoaTakeFocus();
81         wxASSERT(m_cocoaNSImage);
82         m_selectedBitmap.SetNSBitmapImageRep(
83             [[NSBitmapImageRep alloc]
84                 initWithFocusedViewRect:NSMakeRect(0.0,0.0,
85                     m_selectedBitmap.GetWidth(),
86                     m_selectedBitmap.GetHeight())]);
87     }
88     CocoaUnwindStackAndLoseFocus();
89     [m_cocoaNSImage release];
90     m_cocoaNSImage = nil;
91     m_selectedBitmap = bitmap;
92     if(m_selectedBitmap.Ok())
93     {
94         // Create an offscreen window of the same size
95         m_cocoaNSImage = [[NSImage alloc]
96                 initWithSize:NSMakeSize(m_selectedBitmap.GetWidth(),
97                     m_selectedBitmap.GetHeight())];
98
99         // Now copy the data
100         NSImage *nsimage = [m_selectedBitmap.GetNSImage(false) retain];
101         [m_cocoaNSImage lockFocus];
102         [nsimage drawAtPoint: NSMakePoint(0,0)
103             fromRect: NSMakeRect(0.0,0.0,m_selectedBitmap.GetWidth(),m_selectedBitmap.GetHeight())
104             operation: NSCompositeCopy
105             fraction: 1.0];
106         [m_cocoaNSImage unlockFocus];
107
108         [nsimage release];
109     }
110 }
111
112 void wxMemoryDC::DoGetSize( int *width, int *height ) const
113 {
114     if(width)
115         *width = m_selectedBitmap.GetWidth();
116     if(height)
117         *height = m_selectedBitmap.GetHeight();
118 }
119
120 bool wxMemoryDC::CocoaDoBlitOnFocusedDC(wxCoord xdest, wxCoord ydest,
121     wxCoord width, wxCoord height, wxCoord xsrc, wxCoord ysrc,
122     int logicalFunc, bool useMask, wxCoord xsrcMask, wxCoord ysrcMask)
123 {
124     if(!m_selectedBitmap.Ok())
125         return false;
126
127     NSAffineTransform *transform = [NSAffineTransform transform];
128     [transform translateXBy:xdest yBy:ydest];
129
130     NSAffineTransform *flipTransform = [NSAffineTransform transform];
131     /*  x' = 1x + 0y + 0
132         y' = 0x + -1y + window's height
133     */
134     NSAffineTransformStruct matrix = {
135         1,  0
136     ,   0, -1
137     ,   0, height
138     };
139     [flipTransform setTransformStruct: matrix];
140
141     NSGraphicsContext *context = [NSGraphicsContext currentContext];
142     [context saveGraphicsState];
143     [transform concat];
144     [flipTransform concat];
145
146     wxLogTrace(wxTRACE_COCOA,wxT("[m_cocoaNSImage isFlipped]=%d"), [m_cocoaNSImage isFlipped]);
147     [m_cocoaNSImage drawAtPoint: NSMakePoint(0,0)
148         fromRect: NSMakeRect(xsrc,
149             m_selectedBitmap.GetHeight()-height-ysrc,
150             width, height)
151         operation: NSCompositeCopy // FIXME: raster ops
152         fraction: 1.0];
153
154     [context restoreGraphicsState];
155     return false;
156 }
157
158 bool wxMemoryDC::CocoaGetBounds(void *rectData)
159 {
160     if(!rectData)
161         return false;
162     if(!m_cocoaNSImage)
163         return false;
164     NSRect *pRect = (NSRect*)rectData;
165     pRect->origin.x = 0.0;
166     pRect->origin.y = 0.0;
167     pRect->size = [m_cocoaNSImage size];
168     return true;
169 }
170