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