changeset 2434:404d9e9f1f08

iOS: Second attempt at a DWImage class that will actually work.... Doesn't work yet, might need to switch to the Core Graphics functions.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Tue, 06 Apr 2021 04:48:52 +0000
parents 87669cfe3c92
children 7d6c8b7f41d9
files ios/dw.m
diffstat 1 files changed, 169 insertions(+), 206 deletions(-) [+]
line wrap: on
line diff
--- a/ios/dw.m	Mon Apr 05 22:30:26 2021 +0000
+++ b/ios/dw.m	Tue Apr 06 04:48:52 2021 +0000
@@ -265,7 +265,7 @@
 void _dw_handle_resize_events(Box *thisbox);
 int _dw_remove_userdata(UserData **root, const char *varname, int all);
 int _dw_main_iteration(NSDate *date);
-CGContextRef _dw_draw_context(UIImage *image, bool antialias);
+CGContextRef _dw_draw_context(id image, bool antialias);
 typedef id (*DWIMP)(id, SEL, ...);
 
 /* Internal function to queue a window redraw */
@@ -793,13 +793,27 @@
 -(void)layoutSubviews { }
 @end
 
+@interface DWImage : NSObject
+{
+    UIImage *image;
+    CGContextRef cgcontext;
+}
+-(id)initWithSize:(CGSize)size;
+-(id)initWithCGImage:(CGImageRef)cgimage;
+-(id)initWithUIImage:(UIImage *)newimage;
+-(void)setImage:(UIImage *)input;
+-(UIImage *)image;
+-(CGContextRef)cgcontext;
+-(void)dealloc;
+@end
+
 /* Subclass for a render area type */
 @interface DWRender : UIControl
 {
     void *userdata;
     UIFont *font;
     CGSize size;
-    UIImage *cachedDrawingRep;
+    DWImage *cachedImage;
 }
 -(void *)userdata;
 -(void)setUserdata:(void *)input;
@@ -807,7 +821,7 @@
 -(UIFont *)font;
 -(void)setSize:(CGSize)input;
 -(CGSize)size;
--(UIImage *)cachedDrawingRep;
+-(DWImage *)cachedImage;
 -(void)mouseDown:(UIEvent *)theEvent;
 -(void)mouseUp:(UIEvent *)theEvent;
 -(DWMenu *)menuForEvent:(UIEvent *)theEvent;
@@ -826,31 +840,35 @@
 -(UIFont *)font { return font; }
 -(void)setSize:(CGSize)input {
     size = input;
-    if(cachedDrawingRep)
-    {
-        UIImage *oldrep = cachedDrawingRep;
+    if(cachedImage)
+    {
+        DWImage *oldimage = cachedImage;
+        UIImage *newimage;
         UIGraphicsBeginImageContext(self.frame.size);
         [[self layer] renderInContext:UIGraphicsGetCurrentContext()];
-        cachedDrawingRep = UIGraphicsGetImageFromCurrentImageContext();
+        newimage = UIGraphicsGetImageFromCurrentImageContext();
         UIGraphicsEndImageContext();
-        [cachedDrawingRep retain];
-        [oldrep release];
+        cachedImage = [[DWImage alloc] initWithUIImage:newimage];
+        [cachedImage retain];
+        [oldimage release];
     }
 }
 -(CGSize)size { return size; }
--(UIImage *)cachedDrawingRep {
-    if(!cachedDrawingRep)
-    {
+-(DWImage *)cachedImage {
+    if(!cachedImage)
+    {
+        UIImage *newimage;
         UIGraphicsBeginImageContext(self.frame.size);
         [[self layer] renderInContext:UIGraphicsGetCurrentContext()];
-        cachedDrawingRep = UIGraphicsGetImageFromCurrentImageContext();
+        newimage = UIGraphicsGetImageFromCurrentImageContext();
         UIGraphicsEndImageContext();
-        [cachedDrawingRep retain];
+        cachedImage = [[DWImage alloc] initWithUIImage:newimage];
+        [cachedImage retain];
     }
     /* Mark this render dirty if something is requesting it to draw */
     if(![_DWDirtyDrawables containsObject:self])
         [_DWDirtyDrawables addObject:self];
-    return cachedDrawingRep;
+    return cachedImage;
 }
 -(void)mouseDown:(UIEvent *)theEvent
 {
@@ -865,9 +883,9 @@
 -(void)mouseDragged:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 5); }
 -(void)drawRect:(CGRect)rect {
     _dw_event_handler(self, nil, 7);
-    if (cachedDrawingRep)
-    {
-        [cachedDrawingRep drawInRect:self.bounds];
+    if(cachedImage)
+    {
+        [[cachedImage image] drawInRect:self.bounds];
         [_DWDirtyDrawables removeObject:self];
         [self setNeedsDisplay];
     }
@@ -879,7 +897,7 @@
     _dw_remove_userdata(&root, NULL, TRUE);
     [font release];
     dw_signal_disconnect_by_window(self);
-    [cachedDrawingRep release];
+    [cachedImage release];
     [_DWDirtyDrawables removeObject:self];
     [super dealloc];
 }
@@ -1146,17 +1164,8 @@
     DWBitBlt *bltinfo = (DWBitBlt *)[bi pointerValue];
     id bltdest = bltinfo->dest;
     id bltsrc = bltinfo->src;
-
-    if([bltdest isMemberOfClass:[DWRender class]])
-    {
-        DWRender *render = bltdest;
-
-        bltdest = [render cachedDrawingRep];
-    }
-    if([bltdest isMemberOfClass:[UIImage class]])
-    {
-        _dw_draw_context(bltdest, NO);
-    }
+    /* TODO: CGContextRef context =*/ _dw_draw_context(bltdest, NO);
+
     if(bltdest && [bltsrc isMemberOfClass:[UIImage class]])
     {
         UIImage *rep = bltsrc;
@@ -1178,10 +1187,6 @@
         [bltsrc release];
         [image release];
     }
-    if([bltdest isMemberOfClass:[UIImage class]])
-    {
-        UIGraphicsEndImageContext();
-    }
     free(bltinfo);
 }
 -(void)doFlush:(id)param
@@ -1189,9 +1194,10 @@
     NSEnumerator *enumerator = [_DWDirtyDrawables objectEnumerator];
     DWRender *rend;
 
-    while (rend = [enumerator nextObject])
+    while(rend = [enumerator nextObject])
         [rend setNeedsDisplay];
     [_DWDirtyDrawables removeAllObjects];
+    UIGraphicsEndImageContext();
 }
 -(void)doWindowFunc:(id)param
 {
@@ -1496,24 +1502,80 @@
 -(void)dealloc { [super dealloc]; }
 @end
 
-@interface DWImage : NSObject
-{
-    UIImage *image;
-    CGImageRef cgimage;
-}
--(void)setImage:(UIImage *)input;
--(void)setCGImage:(CGImageRef)input;
--(UIImage *)image;
--(CGImageRef)cgimage;
--(void)dealloc;
-@end
-
 @implementation DWImage
--(void)setImage:(UIImage *)input { image = input; }
--(void)setCGImage:(CGImageRef)input { cgimage = input; }
--(UIImage *)image { return image; }
--(CGImageRef)cgimage { return cgimage; }
--(void)dealloc { if(cgimage) CGImageRelease(cgimage); if(image) [image release]; [super dealloc]; }
+-(id)initWithSize:(CGSize)size
+{
+    self = [super init];
+    if(self)
+    {
+        CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
+        CGContextRef cgcontext = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, rgb, kCGImageAlphaLast);
+        CGImageRef cgimage = CGBitmapContextCreateImage(cgcontext);
+        image = [UIImage imageWithCGImage:cgimage];
+        CGContextRelease(cgcontext);
+    }
+    return self;
+}
+-(id)initWithCGImage:(CGImageRef)cgimage
+{
+    self = [super init];
+    if(self)
+    {
+        image = [UIImage imageWithCGImage:cgimage];
+        [image retain];
+    }
+    return self;
+}
+-(id)initWithUIImage:(UIImage *)newimage
+{
+    self = [super init];
+    if(self)
+    {
+        image = newimage;
+        [image retain];
+    }
+    return self;
+}
+-(void)setImage:(UIImage *)input
+{
+    UIImage *oldimage = image;
+    image = input;
+    [image retain];
+    [oldimage release];
+}
+-(UIImage *)image
+{
+    /* If our CGContext has been modified... */
+    if(cgcontext)
+    {
+        UIImage *oldimage = image;
+        CGImageRef cgimage;
+
+        /* Create a new UIImage from the CGContext via CGImage */
+        cgimage = CGBitmapContextCreateImage(cgcontext);
+        image = [UIImage imageWithCGImage:cgimage];
+        CGContextRelease(cgcontext);
+        cgcontext = nil;
+        [oldimage release];
+    }
+    return image;
+}
+-(CGContextRef)cgcontext
+{
+    /* If we don't have an active context, create a bitmap
+     * context and copy the image from our UIImage.
+     */
+    if(!cgcontext)
+    {
+        CGSize size = [image size];
+        CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
+
+        cgcontext = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, rgb, kCGImageAlphaLast);
+        CGContextDrawImage(cgcontext, CGRectMake(0,0,size.width,size.height), [image CGImage]);
+    }
+    return cgcontext;
+}
+-(void)dealloc { if(cgcontext) CGContextRelease(cgcontext); if(image) [image release]; [super dealloc]; }
 @end
 
 /* Subclass for a scrollbox type */
@@ -5152,16 +5214,37 @@
     return newcolor;
 }
 
-CGContextRef _dw_draw_context(UIImage *image, bool antialiased)
-{
-    CGContextRef context;
-
-    UIGraphicsBeginImageContext(image.size);
-    context = UIGraphicsGetCurrentContext();
-    CGContextSetAllowsAntialiasing(context, antialiased);
+CGContextRef _dw_draw_context(id source, bool antialiased)
+{
+    CGContextRef context = nil;
+
+    if([source isMemberOfClass:[DWImage class]])
+    {
+        DWImage *image = source;
+
+        context = [image cgcontext];
+    }
+    else if([source isMemberOfClass:[DWRender class]])
+    {
+        DWRender *render = source;
+
+        UIGraphicsBeginImageContext([render frame].size);
+        context = UIGraphicsGetCurrentContext();
+    }
+    if(context)
+        CGContextSetAllowsAntialiasing(context, antialiased);
     return context;
 }
 
+DWImage *_dw_dest_image(HPIXMAP pixmap, id object)
+{
+    if(pixmap && pixmap->image)
+        return pixmap->image;
+    if([object isMemberOfClass:[DWRender class]])
+        return [object cachedImage];
+    return nil;
+}
+
 /* Draw a point on a window (preferably a render window).
  * Parameters:
  *       handle: Handle to the window.
@@ -5175,28 +5258,11 @@
 DW_FUNCTION_RESTORE_PARAM4(handle, HWND, pixmap, HPIXMAP, x, int, y, int)
 {
     DW_FUNCTION_INIT;
-    DW_LOCAL_POOL_IN;
-    id image = handle;
-    UIImage *bi = nil;
-    bool bCanDraw = YES;
-
-    if(pixmap)
-        bi = (id)pixmap->image;
-    else
-    {
-        if([image isMemberOfClass:[DWRender class]])
-        {
-            DWRender *render = image;
-
-            bi = [render cachedDrawingRep];
-        }
-    }
+    DWImage *bi = _dw_dest_image(pixmap, handle);
+    /*CGContextRef context =*/ _dw_draw_context(bi, NO);
+
     if(bi)
     {
-        _dw_draw_context(bi, NO);
-    }
-    if(bCanDraw == YES)
-    {
         UIBezierPath* aPath = [UIBezierPath bezierPath];
         [aPath setLineWidth: 0.5];
         UIColor *color = pthread_getspecific(_dw_fg_color_key);
@@ -5205,9 +5271,6 @@
         [aPath moveToPoint:CGPointMake(x, y)];
         [aPath stroke];
     }
-    if(bi)
-        UIGraphicsEndImageContext();
-    DW_LOCAL_POOL_OUT;
     DW_FUNCTION_RETURN_NOTHING;
 }
 
@@ -5226,28 +5289,11 @@
 DW_FUNCTION_RESTORE_PARAM6(handle, HWND, pixmap, HPIXMAP, x1, int, y1, int, x2, int, y2, int)
 {
     DW_FUNCTION_INIT;
-    DW_LOCAL_POOL_IN;
-    id image = handle;
-    UIImage *bi = nil;
-    bool bCanDraw = YES;
-
-    if(pixmap)
-        bi = (id)pixmap->image;
-    else
-    {
-        if([image isMemberOfClass:[DWRender class]])
-        {
-            DWRender *render = image;
-
-            bi = [render cachedDrawingRep];
-        }
-    }
+    DWImage *bi = _dw_dest_image(pixmap, handle);
+    /*CGContextRef context =*/ _dw_draw_context(bi, NO);
+
     if(bi)
     {
-       _dw_draw_context(bi, NO);
-    }
-    if(bCanDraw == YES)
-    {
         UIBezierPath* aPath = [UIBezierPath bezierPath];
         UIColor *color = pthread_getspecific(_dw_fg_color_key);
         [color set];
@@ -5256,10 +5302,6 @@
         [aPath addLineToPoint:CGPointMake(x2 + 0.5, y2 + 0.5)];
         [aPath stroke];
     }
-
-    if(bi)
-        UIGraphicsEndImageContext();
-    DW_LOCAL_POOL_OUT;
     DW_FUNCTION_RETURN_NOTHING;
 }
 
@@ -5277,13 +5319,11 @@
 DW_FUNCTION_RESTORE_PARAM5(handle, HWND, pixmap, HPIXMAP, x, int, y, int, text, const char *)
 {
     DW_FUNCTION_INIT;
-    DW_LOCAL_POOL_IN;
-    id image = handle;
     NSString *nstr = [ NSString stringWithUTF8String:text ];
-    UIImage *bi = nil;
+    DWImage *bi = nil;
     UIFont *font = nil;
     DWRender *render;
-    bool bCanDraw = YES;
+    id image = handle;
 
     if(pixmap)
     {
@@ -5299,15 +5339,12 @@
     {
         render = image;
         font = [render font];
-        bi = [render cachedDrawingRep];
+        bi = [render cachedImage];
     }
     if(bi)
     {
-        _dw_draw_context(bi, NO);
-    }
-
-    if(bCanDraw == YES)
-    {
+        /*CGContextRef context =*/ _dw_draw_context(bi, NO);
+
         UIColor *fgcolor = pthread_getspecific(_dw_fg_color_key);
         UIColor *bgcolor = pthread_getspecific(_dw_bg_color_key);
         NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:fgcolor, NSForegroundColorAttributeName, nil];
@@ -5318,10 +5355,6 @@
         [nstr drawAtPoint:CGPointMake(x, y) withAttributes:dict];
         [dict release];
     }
-
-    if(bi)
-        UIGraphicsEndImageContext();
-    DW_LOCAL_POOL_OUT;
     DW_FUNCTION_RETURN_NOTHING;
 }
 
@@ -5391,32 +5424,15 @@
 DW_FUNCTION_RESTORE_PARAM6(handle, HWND, pixmap, HPIXMAP, flags, int, npoints, int, x, int *, y, int *)
 {
     DW_FUNCTION_INIT;
-    DW_LOCAL_POOL_IN;
-    id image = handle;
-    UIImage *bi = nil;
-    bool bCanDraw = YES;
-    int z;
-
-    if(pixmap)
-        bi = (id)pixmap->image;
-    else
-    {
-        if([image isMemberOfClass:[DWRender class]])
-        {
-            DWRender *render = image;
-
-            bi = [render cachedDrawingRep];
-        }
-    }
+    DWImage *bi = _dw_dest_image(pixmap, handle);
+    /*CGContextRef context =*/ _dw_draw_context(bi, flags & DW_DRAW_NOAA ? NO : YES);
+
     if(bi)
     {
-        _dw_draw_context(bi, flags & DW_DRAW_NOAA ? NO : YES);
-    }
-
-    if(bCanDraw == YES)
-    {
         UIBezierPath* aPath = [UIBezierPath bezierPath];
         UIColor *color = pthread_getspecific(_dw_fg_color_key);
+        int z;
+
         [color set];
 
         [aPath moveToPoint:CGPointMake(*x + 0.5, *y + 0.5)];
@@ -5430,10 +5446,6 @@
         else
             [aPath stroke];
     }
-
-    if(bi)
-        UIGraphicsEndImageContext();
-    DW_LOCAL_POOL_OUT;
     DW_FUNCTION_RETURN_NOTHING;
 }
 
@@ -5453,29 +5465,11 @@
 DW_FUNCTION_RESTORE_PARAM7(handle, HWND, pixmap, HPIXMAP, flags, int, x, int, y, int, width, int, height, int)
 {
     DW_FUNCTION_INIT;
-    DW_LOCAL_POOL_IN;
-    id image = handle;
-    UIImage *bi = nil;
-    bool bCanDraw = YES;
-
-    if(pixmap)
-        bi = (id)pixmap->image;
-    else
-    {
-        if([image isMemberOfClass:[DWRender class]])
-        {
-            DWRender *render = image;
-
-            bi = [render cachedDrawingRep];
-        }
-    }
+    DWImage *bi = _dw_dest_image(pixmap, handle);
+    /*CGContextRef context =*/ _dw_draw_context(bi, flags & DW_DRAW_NOAA ? NO : YES);
+
     if(bi)
     {
-        _dw_draw_context(bi, flags & DW_DRAW_NOAA ? NO : YES);
-    }
-
-    if(bCanDraw == YES)
-    {
         UIColor *color = pthread_getspecific(_dw_fg_color_key);
         UIBezierPath *bp = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, width, height)];;
         
@@ -5486,10 +5480,6 @@
         else
             [bp stroke];
     }
-
-    if(bi)
-        UIGraphicsEndImageContext();
-    DW_LOCAL_POOL_OUT;
     DW_FUNCTION_RETURN_NOTHING;
 }
 
@@ -5512,29 +5502,11 @@
 DW_FUNCTION_RESTORE_PARAM9(handle, HWND, pixmap, HPIXMAP, flags, int, xorigin, int, yorigin, int, x1, int, y1, int, x2, int, y2, int)
 {
     DW_FUNCTION_INIT;
-    DW_LOCAL_POOL_IN;
-    id image = handle;
-    UIImage *bi = nil;
-    bool bCanDraw = YES;
-
-    if(pixmap)
-        bi = (id)pixmap->image;
-    else
-    {
-        if([image isMemberOfClass:[DWRender class]])
-        {
-            DWRender *render = image;
-
-            bi = [render cachedDrawingRep];
-        }
-    }
+    DWImage *bi = _dw_dest_image(pixmap, handle);
+    /*CGContextRef context =*/ _dw_draw_context(bi, flags & DW_DRAW_NOAA ? NO : YES);
+
     if(bi)
     {
-        _dw_draw_context(bi, flags & DW_DRAW_NOAA ? NO : YES);
-    }
-
-    if(bCanDraw)
-    {
         UIBezierPath* aPath;
         UIColor *color = pthread_getspecific(_dw_fg_color_key);
         [color set];
@@ -5564,10 +5536,6 @@
         else
             [aPath stroke];
     }
-
-    if(bi)
-        UIGraphicsEndImageContext();
-    DW_LOCAL_POOL_OUT;
     DW_FUNCTION_RETURN_NOTHING;
 }
 
@@ -6831,15 +6799,10 @@
 
     if((pixmap = calloc(1,sizeof(struct _hpixmap))))
     {
-        CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
-        CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, calloc(width*height, 4), width*height*4, NULL);
-        CGImageRef image = CGImageCreate(width, height, 8, 32, 4 * width,
-                                         rgb, kCGBitmapByteOrderDefault | kCGImageAlphaLast,
-                                         provider, NULL, false, kCGRenderingIntentDefault);
         pixmap->width = width;
         pixmap->height = height;
         pixmap->handle = handle;
-        pixmap->image = [[[UIImage alloc] initWithCGImage:image] retain];
+        pixmap->image = [[[DWImage alloc] initWithSize:CGSizeMake(width,height)] retain];
     }
     return pixmap;
 }
@@ -6880,7 +6843,7 @@
     pixmap->width = [tmpimage size].width;
     pixmap->height = [tmpimage size].height;
     pixmap->image = tmpimage;
-    pixmap->handle = handle;
+    pixmap->handle = [[DWImage alloc] initWithUIImage:tmpimage];
     DW_LOCAL_POOL_OUT;
     return pixmap;
 }
@@ -6914,7 +6877,7 @@
     }
     pixmap->width = [tmpimage size].width;
     pixmap->height = [tmpimage size].height;
-    pixmap->image = tmpimage;
+    pixmap->image = [[DWImage alloc] initWithUIImage:tmpimage];
     pixmap->handle = handle;
     DW_LOCAL_POOL_OUT;
     return pixmap;
@@ -6962,7 +6925,7 @@
     {
         pixmap->width = [tmpimage size].width;
         pixmap->height = [tmpimage size].height;
-        pixmap->image = tmpimage;
+        pixmap->image = [[DWImage alloc] initWithUIImage:tmpimage];
         pixmap->handle = handle;
         DW_LOCAL_POOL_OUT;
         return pixmap;
@@ -7014,7 +6977,7 @@
 {
     if(pixmap)
     {
-        UIImage *image = (UIImage *)pixmap->image;
+        DWImage *image = (DWImage *)pixmap->image;
         UIFont *font = pixmap->font;
         DW_LOCAL_POOL_IN;
         [image release];