changeset 909:c092eab43ae3

Experimental change to pixmap rendering. Switch from using NSImage to NSBitmapImageRef to store the image. This is closer to the core backing store used to display images. Using this I was able to avoid using lockFocus on the images and instead set the graphics context manually allowing us to draw directly on the backing image. However NSBitmapImageRef is a more simple format and didn't work with the flipped Y axis... so... I had to perform some voodoo to get the flipping to work with the graphics context. Not sure it is 100% right.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 20 Apr 2011 14:09:00 +0000
parents 850b2e6cfeab
children 329f2ca62f1b
files mac/dw.m
diffstat 1 files changed, 108 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/mac/dw.m	Tue Apr 19 08:24:52 2011 +0000
+++ b/mac/dw.m	Wed Apr 20 14:09:00 2011 +0000
@@ -418,9 +418,14 @@
     id bltdest = bltinfo->dest;
     id bltsrc = bltinfo->src;
 
-    if([bltdest isMemberOfClass:[NSImage class]])
-    {
-        [bltdest lockFocus];
+    if([bltdest isMemberOfClass:[NSBitmapImageRep class]])
+    {
+        [NSGraphicsContext saveGraphicsState];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithBitmapImageRep:bltdest]];  
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithGraphicsPort:[[NSGraphicsContext currentContext] graphicsPort] flipped:YES]];    
+        [[NSDictionary alloc] initWithObjectsAndKeys:bltdest, NSGraphicsContextDestinationAttributeName, nil];
     }
     else
     {
@@ -430,14 +435,33 @@
         }
         _DWLastDrawable = bltinfo->dest;
     }
-    if([bltsrc isMemberOfClass:[NSImage class]])
-    {
-        NSImage *image = bltsrc;
+    if([bltsrc isMemberOfClass:[NSBitmapImageRep class]])
+    {
+        NSImage *image = [[NSImage alloc] initWithCGImage:[(NSBitmapImageRep *)bltsrc CGImage] size:NSZeroSize];
+        // make a new transform:
+        NSAffineTransform *t = [NSAffineTransform transform];
+        
+        // by scaling Y negatively, we effectively flip the image:
+        [t scaleXBy:1.0 yBy:-1.0];
+        
+        // but we also have to translate it back by its height:
+        [t translateXBy:0.0 yBy:-bltinfo->height];
+        
+        // apply the transform:
+        [t concat];        
         [image drawAtPoint:NSMakePoint(bltinfo->xdest, bltinfo->ydest) fromRect:NSMakeRect(bltinfo->xsrc, bltinfo->ysrc, bltinfo->width, bltinfo->height)
                         operation:NSCompositeCopy fraction:1.0];
         [bltsrc release];
-    }
-    [bltdest unlockFocus];
+        [image release];
+    }
+    if([bltdest isMemberOfClass:[NSBitmapImageRep class]])
+    {
+        [NSGraphicsContext restoreGraphicsState];
+    }
+    else
+    {
+        [bltdest unlockFocus];
+    }
     free(bltinfo);
 }
 -(void)doFlush:(id)param
@@ -4354,7 +4378,11 @@
     if(pixmap)
     {
         image = (id)pixmap->image;
-        [image lockFocus];
+        [NSGraphicsContext saveGraphicsState];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithBitmapImageRep:image]];    
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithGraphicsPort:[[NSGraphicsContext currentContext] graphicsPort] flipped:YES]];    
     }
     else
     {
@@ -4372,7 +4400,14 @@
 
     [aPath moveToPoint:NSMakePoint(x, y)];
     [aPath stroke];
-    [image unlockFocus];
+    if(pixmap)
+    {
+        [NSGraphicsContext restoreGraphicsState];
+    }
+    else
+    {
+        [image unlockFocus];
+    }
     DW_MUTEX_UNLOCK;
 }
 
@@ -4393,7 +4428,11 @@
     if(pixmap)
     {
         image = (id)pixmap->image;
-        [image lockFocus];
+        [NSGraphicsContext saveGraphicsState];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithBitmapImageRep:image]];    
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithGraphicsPort:[[NSGraphicsContext currentContext] graphicsPort] flipped:YES]];    
     }
     else
     {
@@ -4413,7 +4452,14 @@
     [aPath lineToPoint:NSMakePoint(x2, y2)];
     [aPath stroke];
 
-    [image unlockFocus];
+    if(pixmap)
+    {
+        [NSGraphicsContext restoreGraphicsState];
+    }
+    else
+    {
+        [image unlockFocus];
+    }
     DW_MUTEX_UNLOCK;
 }
 
@@ -4468,7 +4514,11 @@
             font = [render font];
         }
         image = (id)pixmap->image;
-        [image lockFocus];
+        [NSGraphicsContext saveGraphicsState];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithBitmapImageRep:image]];    
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithGraphicsPort:[[NSGraphicsContext currentContext] graphicsPort] flipped:YES]];    
         NSColor *fgcolor = pthread_getspecific(_dw_fg_color_key);
         NSColor *bgcolor = pthread_getspecific(_dw_bg_color_key);
         NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:fgcolor, NSForegroundColorAttributeName, nil];
@@ -4481,7 +4531,7 @@
             [dict setValue:font forKey:NSFontAttributeName];
         }
         [nstr drawAtPoint:NSMakePoint(x, y) withAttributes:dict];
-        [image unlockFocus];
+        [NSGraphicsContext restoreGraphicsState];
         [dict release];
     }
     DW_MUTEX_UNLOCK;
@@ -4544,7 +4594,11 @@
     if(pixmap)
     {
         image = (id)pixmap->image;
-        [image lockFocus];
+        [NSGraphicsContext saveGraphicsState];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithBitmapImageRep:image]];    
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithGraphicsPort:[[NSGraphicsContext currentContext] graphicsPort] flipped:YES]];    
     }
     else
     {
@@ -4571,7 +4625,14 @@
         [aPath fill];
     }
     [aPath stroke];
-    [image unlockFocus];
+    if(pixmap)
+    {
+        [NSGraphicsContext restoreGraphicsState];
+    }
+    else
+    {
+        [image unlockFocus];
+    }
     DW_MUTEX_UNLOCK;
 }
 
@@ -4593,7 +4654,11 @@
     if(pixmap)
     {
         image = (id)pixmap->image;
-        [image lockFocus];
+        [NSGraphicsContext saveGraphicsState];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithBitmapImageRep:image]];    
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithGraphicsPort:[[NSGraphicsContext currentContext] graphicsPort] flipped:YES]];    
     }
     else
     {
@@ -4617,7 +4682,14 @@
     if(fill)
        [aPath fill];
     [aPath stroke];
-    [image unlockFocus];
+    if(pixmap)
+    {
+        [NSGraphicsContext restoreGraphicsState];
+    }
+    else
+    {
+        [image unlockFocus];
+    }
     DW_MUTEX_UNLOCK;
 }
 
@@ -5728,7 +5800,6 @@
  */
 HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth)
 {
-    NSSize size = { (float)width, (float)height };
     HPIXMAP pixmap;
 
     if(!(pixmap = calloc(1,sizeof(struct _hpixmap))))
@@ -5736,8 +5807,18 @@
     pixmap->width = width;
     pixmap->height = height;
     pixmap->handle = handle;
-    NSImage *image = pixmap->image = [[NSImage alloc] initWithSize:size];
-    [image setFlipped:YES];
+    id image = pixmap->image = [[NSBitmapImageRep alloc] 
+                                    initWithBitmapDataPlanes:NULL 
+                                    pixelsWide:width 
+                                    pixelsHigh:height 
+                                    bitsPerSample:8 
+                                    samplesPerPixel:4 
+                                    hasAlpha:YES 
+                                    isPlanar:NO 
+                                    colorSpaceName:@"NSCalibratedRGBColorSpace" 
+                                    bytesPerRow:0 
+                                    bitsPerPixel:0];
+    [image retain];
     return pixmap;
 }
 
@@ -5758,18 +5839,17 @@
     if(!(pixmap = calloc(1,sizeof(struct _hpixmap))))
         return NULL;
     NSString *nstr = [ NSString stringWithUTF8String:filename ];
-    NSImage *image = [[NSImage alloc] initWithContentsOfFile:nstr];
+    NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithContentsOfFile:nstr];
     if(!image)
     {
         nstr = [nstr stringByAppendingString:@".png"];
-        image = [[NSImage alloc] initWithContentsOfFile:nstr];
+        image = [[NSBitmapImageRep alloc] initWithContentsOfFile:nstr];
     }
     NSSize size = [image size];
     pixmap->width = size.width;
     pixmap->height = size.height;
     pixmap->image = image;
     pixmap->handle = handle;
-    [image setFlipped:YES];
     return pixmap;
 }
 
@@ -5790,13 +5870,12 @@
     if(!(pixmap = calloc(1,sizeof(struct _hpixmap))))
         return NULL;
     NSData *thisdata = [NSData dataWithBytes:data length:len];
-    NSImage *image = [[NSImage alloc] initWithData:thisdata];
+    NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:thisdata];
     NSSize size = [image size];
     pixmap->width = size.width;
     pixmap->height = size.height;
     pixmap->image = image;
     pixmap->handle = handle;
-    [image setFlipped:YES];
     return pixmap;
 }
 
@@ -5832,13 +5911,12 @@
     NSBundle *bundle = [NSBundle mainBundle];
     NSString *respath = [bundle resourcePath];
     NSString *filepath = [respath stringByAppendingFormat:@"/%u.png", resid];
-    NSImage *image = [[NSImage alloc] initWithContentsOfFile:filepath];
+    NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithContentsOfFile:filepath];
     NSSize size = [image size];
     pixmap->width = size.width;
     pixmap->height = size.height;
     pixmap->image = image;
     pixmap->handle = handle;
-    [image setFlipped:YES];
     return pixmap;
 }
 
@@ -5850,8 +5928,8 @@
  */
 void API dw_pixmap_destroy(HPIXMAP pixmap)
 {
-    NSImage *image = (NSImage *)pixmap->image;
-    [image dealloc];
+    NSBitmapImageRep *image = (NSBitmapImageRep *)pixmap->image;
+    [image release];
     free(pixmap);
 }