CATiledLayer, CGContextDrawImage и CGContextTranslateCTM - PullRequest
1 голос
/ 08 января 2012

У меня есть большой UIScrollView, который содержит CATiledLayer, который я использую для рисования тайлов гораздо большего размера в drawRect:, например:

- (void)drawRect:(CGRect)rect {
    int firstCol = floorf(CGRectGetMinX(rect) / tileSize);
    int lastCol = floorf((CGRectGetMaxX(rect)-1) / tileSize);
    int firstRow = floorf(CGRectGetMinY(rect) / tileSize);
    int lastRow = floorf((CGRectGetMaxY(rect)-1) / tileSize);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0, tileSize);
CGContextScaleCTM(context, 1.0, -1.0);

    for( int row = firstRow; row <= lastRow; row++ ) {
    for( int col = firstCol; col <= lastCol; col++ ) {
            UIImage = [self getTileWithRow:row column:col];

            CGRect tileRect = CGRectMake((col * tileSize), 
                                         row * tileSize),
                                         tileSize, tileSize);

            CGContextTranslateCTM(context, 0, tileRect.size.height);
            CGContextScaleCTM(context, 1.0, -1.0);
            CGContextDrawImage(context, tileRect, tile.CGImage);
        }
    }

    CGContextRestoreGState(context);
}

Это работает, когда я закомментирую вызовы CGContextSaveGState, CGContextSaveGState, CGContextScaleCTM и CGContextRestoreGState, но изображения перевернуты. При наличии вызовов изображение не рисуется вообще. Я мог бы использовать [tile drawInRect:], но это рисует строки в обратном направлении, что приводит к увеличению размера изображения.

Что я делаю не так с переводом?

РЕДАКТИРОВАТЬ: перемещены сохранить / восстановить и преобразовать из цикла, как предложено, но он по-прежнему ничего не рисует.

Ответы [ 2 ]

4 голосов
/ 08 января 2012

Установка правильных преобразований для переворачивания контента по вертикали, как известно, трудна.Вероятная причина не видеть ничего, потому что преобразования перемещают изображение за пределы прямоугольника.Я сделал это раньше, но не помню, как я это сделал.Теперь вместо этого я устанавливаю «geometryFlipped = YES» на CATiledLayer, что делает меня переворачиванием.

Кстати, почему бы вам не установить «tileSize» CATiledLayer равным размеру ваших плиток,тогда вам не нужен этот материал для отображения цикла петли.DrawRect вызывается один раз для каждой из ваших плиток, поэтому вы можете сделать следующее:

- (void)drawRect:(CGRect)rect 
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    int col = floorf(CGRectGetMinX(rect) / tileSize);
    int row = floorf(CGRectGetMinY(rect) / tileSize);

    UIImage tile = [self getTileWithRow:row column:col];

    CGContextDrawImage(context, rect, tile.CGImage);
}
2 голосов
/ 08 января 2012

Прежде всего, удалите все эти CGContextSaveGState / CGContextRestoreGState из этих циклов, поскольку они добавят больше нагрузки, чем необходимо для вашей реализации.

Во-вторых, добавьте CGContextRef context = UIGraphicsGetCurrentContext(); в качестве первой строкиэтого метода drawRect.

Таким образом, ваша реализация должна выглядеть так:

- (void)drawRect:(CGRect)rect 
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0, rect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    int firstCol = floorf(CGRectGetMinX(rect) / tileSize);
    int lastCol = floorf((CGRectGetMaxX(rect)-1) / tileSize);
    int firstRow = floorf(CGRectGetMinY(rect) / tileSize);
    int lastRow = floorf((CGRectGetMaxY(rect)-1) / tileSize);

    for( int row = firstRow; row <= lastRow; row++ ) 
    {
        for( int col = firstCol; col <= lastCol; col++ ) 
        {
            UIImage = [self getTileWithRow:row column:col];

            CGRect tileRect = CGRectMake((col * tileSize), 
                                         row * tileSize),
                                         tileSize, tileSize);

            CGContextDrawImage(context, tileRect, tile.CGImage);
        }
    }
    CGContextRestoreGState(context);
}
...