Drawing in CATiledLayer with CoreGraphics CGContextDrawImage

后端 未结 1 541
醉酒成梦
醉酒成梦 2021-01-01 00:21

I would like to use a CATiledLayer in iPhone OS 3.1.3 and to do so all drawing in -(void)drawLayer:(CALayer *)layer inContext:(CGContext)context has to be done

1条回答
  •  礼貌的吻别
    2021-01-01 01:01

    Thomas, I started by following the WWDC 2010 ScrollView talk and there is little or no documentation on working within drawLayer:inContext for iOS 3.x. I had the same issues as you do when I moved the demo code from drawRect: across to drawLayer:inContext:.

    Some investigation showed me that within drawLayer:inContext: the size and offset of rect returned from CGContextGetClipBoundingBox(context) is exactly what you want to draw in. Where drawRect: gives you the whole bounds.

    Knowing this you can remove the row and column iteration, as well as the CGRect intersection for the edge tiles and just draw to the rect once you've translated the context.

    Here's what I've ended up with:

    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
      CGRect rect = CGContextGetClipBoundingBox(ctx);
      CGFloat scale = CGContextGetCTM(ctx).a;
    
      CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
      CGSize tileSize = tiledLayer.tileSize;
      tileSize.width /= scale;
      tileSize.height /= scale;
    
      int col = floorf((CGRectGetMaxX(rect)-1) / tileSize.width);
      int row = floorf((CGRectGetMaxY(rect)-1) / tileSize.height);
    
      CGImageRef image = [self imageForScale:scale row:row col:col];
    
      if(NULL != image) {
        CGContextTranslateCTM(ctx, 0.0, rect.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);
        rect = CGContextGetClipBoundingBox(ctx);
    
        CGContextDrawImage(ctx, rect, image);
        CGImageRelease(image);
      }
    }
    

    Notice that rect is redefined after the TranslateCTM and ScaleCTM.

    And for reference here is my imageForScale:row:col function:

    - (CGImageRef) imageForScale:(CGFloat)scale row:(int)row col:(int)col {
      CGImageRef image = NULL;
      CGDataProviderRef provider = NULL;
      NSString *filename = [NSString stringWithFormat:@"img_name_here%0.0f_%d_%d",ceilf(scale * 100),col,row];
      NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:@"png"];
    
      if(path != nil) {
        NSURL *imageURL = [NSURL fileURLWithPath:path];
    
        provider = CGDataProviderCreateWithURL((CFURLRef)imageURL);
    
        image = CGImageCreateWithPNGDataProvider(provider,NULL,FALSE,kCGRenderingIntentDefault); 
        CFRelease(provider);
      }
      return image;
    }
    

    There's still a bit of work to be done on these two functions in order to support high resolution graphics properly, but it does look nice on everything but an iPhone 4.

    0 讨论(0)
提交回复
热议问题