NSAffineTransforms не используется? - PullRequest
1 голос
/ 09 июля 2009

У меня есть подкласс NSView, и в этом я рисую NSImage. Я использую NSAffineTransforms, чтобы вращать, переводить и масштабировать изображение.

Большая часть работает нормально. Однако иногда преобразования просто не активируются.

Например, когда я изменяю размер окна, преобразование поворота не происходит.

Когда я увеличиваю изображение, оно помещает нижний левый угол изображения в правильное место, но не увеличивает его, но увеличивает масштаб той части изображения, которая будет справа от исходного размера образ. Если я поверну это, он увеличится правильно, но переводится неправильно. (Перевод может быть ошибка расчета с моей стороны)

Вот код моего drawRect: (простите за длинный код)

- (void)drawRect:(NSRect)rect 
{
    // Drawing code here.
    double rotateDeg = -90* rotation;
    NSAffineTransform *afTrans = [[NSAffineTransform alloc] init];
    NSGraphicsContext *context = [NSGraphicsContext currentContext];
    NSSize sz;
    NSRect windowFrame = [[self window] frame];
    float deltaX, deltaY;
    NSSize superSize = [[self superview] frame].size;
    float height, width, sHeight, sWidth;

    NSRect imageRect;

    if(image)
    {
        sz = [ image size];
        imageRect.size = sz;
        imageRect.origin = NSZeroPoint;
        imageRect.size.width *= zoom;
        imageRect.size.height *= zoom;

        height = sz.height * zoom  ;
        width = sz.width *zoom ;
        sHeight = superSize.height;
        sWidth = superSize.width;
    }

Мне нужно заранее взять размеры всего, чтобы я мог использовать их позже, когда поверну. Я не уверен, что мне нужно защищать что-либо из этого, но я параноик от многолетнего К ...

    [context saveGraphicsState];

// rotate
    [afTrans rotateByDegrees:rotateDeg];
// translate to account for window size;
    deltaX = 0;
    deltaY = 0;

// translate to account for rotation

// in 1 and 3, X and Y are reversed because the entire FRAME
// (inculding axes) is rotated!
    switch (rotation)
    {
        case 0:
//          NSLog(@"No rotation ");
            break;
        case 1: 
            deltaY -= (sHeight - height); 
            deltaX -= sHeight ;
            break;
        case 2:
            deltaX -= width;
            deltaY -= ( 2*sHeight - height);    
            // it's rotating around the lower left of the FRAME, so,
            // we need to move it up two frame hights, and then down
            // the hieght of the image
            break;
        case 3:
            deltaX += (sHeight - width);
            deltaY -= sHeight;
            break;
    }

Поскольку я вращаюсь вокруг нижнего левого угла и хочу, чтобы изображение было зафиксировано в верхнем левом углу, мне нужно переместить изображение вокруг. Когда я поворачиваюсь один раз, изображение находится в квадранте + -, поэтому мне нужно сместить его на одну высоту просмотра, а влево - на высоту просмотра за вычетом высоты изображения. и т.д.

    [afTrans translateXBy:deltaX yBy:deltaY];

// for putting image in upper left

// zoom
    [afTrans scaleBy: zoom];
    printMatrix([afTrans  transformStruct]);
    NSLog(@"zoom %f", zoom);
    [afTrans concat];

    if(image)
    {
        NSRect drawingRect = imageRect;
        NSRect frame = imageRect;

        frame.size.height = MAX(superSize.height, imageRect.size.height) ;
        [self setFrame:frame];

        deltaY =  superSize.height - imageRect.size.height;
        drawingRect.origin.y += deltaY;

Это делает кадр правильного размера, чтобы изображение находилось в верхнем левом углу кадра. Если изображение больше окна, я хочу, чтобы рамка была достаточно большой, чтобы появлялись полосы прокрутки. Если это не так, я хочу, чтобы рамка была достаточно большой, чтобы она доходила до верхней части окна.

        [image drawInRect:drawingRect
               fromRect:imageRect
               operation:NSCompositeSourceOver
               fraction:1];

        if((rotation %2) )
        {
            float tmp;
            tmp = drawingRect.size.width;
            drawingRect.size.width = drawingRect.size.height;
            drawingRect.size.height = tmp;
        }

Этот код может быть полностью историческим, теперь, когда я смотрю на него ... идея состояла в том, чтобы поменять высоту и ширину, если я повернул на 90 или 270 градусов.

    }
    else
        NSLog(@"no image"); 

    [afTrans release];
    [context restoreGraphicsState];

}

1 Ответ

0 голосов
/ 19 июля 2009

Почему вы используете размер суперпредставления? Это то, о чем вам почти никогда не нужно беспокоиться. Вы должны заставить представление работать самостоятельно, без зависимости от встраивания в какое-либо конкретное представление.

Масштабирование размера imageRect, вероятно, не правильный путь. Обычно при вызове -drawImage вы хотите, чтобы исходный прямоугольник был границами изображения, и масштабировал целевой прямоугольник, чтобы увеличить его.

Проблемы, о которых вы сообщаете, звучат так, будто вы не перерисовываете весь вид после изменения преобразования. Вы звоните -setNeedsDisplay: ДА?

Как этот вид встроен в окно? Это внутри NSScrollView? Вы убедились, что размер прокрутки изменяется вместе с окном?

...