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