使用CGAffineTransform缩放上下文中的所有点时保留线宽

时间:2009-11-25 17:12:20

标签: core-graphics cgcontext cgaffinetransform cgpath stroke

我想在某个坐标系中有一个CGPath。这样做涉及将旧坐标系缩放到Context的坐标系上。为此,我使用了CGContextConcatCTM(),它确实可以转换所有点。但是,由于它是缩放操作,水平/垂直线宽变为。例如。 x方向上的刻度为10,但y方向上的刻度为1将导致垂直线的厚度是水平线的10倍。有没有办法保持翻译矩阵的易用性(例如CGAffineTransform),但不能同时缩放线宽,例如像CGPathApplyAffineTransformToPoints

这样的函数

干杯

MrMage

2 个答案:

答案 0 :(得分:6)

添加路径时进行变换,但在描边路径之前删除变换。而不是:

CGContextSaveGState(ctx);
CGContextScaleCTM(ctx, 10, 10);   // scale path 10x

CGContextAddPath(ctx, somePath);

CGContextSetStrokeColorWithColor(ctx, someColor);
CGContextSetLineWidth(ctx, someWidth);   // uh-oh, line width is 10x, too
CGContextStrokePath(ctx);

CGContextRestoreGState(ctx);      // back to normal

这样做:

CGContextSaveGState(ctx);
CGContextScaleCTM(ctx, 10, 10);   // scale path 10x

CGContextAddPath(ctx, somePath);

CGContextRestoreGState(ctx);      // back to normal

CGContextSetStrokeColorWithColor(ctx, someColor);
CGContextSetLineWidth(ctx, someWidth);
CGContextStrokePath(ctx);

答案 1 :(得分:3)

您可以使用CGPathApply遍历路径中的元素。它比单线程更复杂,但如果你用一个简单的辅助函数打包它,它可能对你有用。这是一个创建新路径并对其进行转换的版本:

typedef struct {
    CGMutablePathRef path;
    CGAffineTransform transform;
} PathTransformInfo;

static void
PathTransformer(void *info, const CGPathElement *element)
{
    PathTransformInfo *transformerInfo = info;

    switch (element->type) {
        case kCGPathElementMoveToPoint:
            CGPathMoveToPoint(transformerInfo->path, &transformerInfo->transform,
                              element->points[0].x, element->points[0].y);
            break;

        case kCGPathElementAddLineToPoint:
            CGPathAddLineToPoint(transformerInfo->path, &transformerInfo->transform,
                                 element->points[0].x, element->points[0].y);
            break;

        case kCGPathElementAddQuadCurveToPoint:
            CGPathAddQuadCurveToPoint(transformerInfo->path, &transformerInfo->transform,
                                      element->points[0].x, element->points[0].y,
                                      element->points[1].x, element->points[1].y);
            break;

        case kCGPathElementAddCurveToPoint:
            CGPathAddCurveToPoint(transformerInfo->path, &transformerInfo->transform,
                                  element->points[0].x, element->points[0].y,
                                  element->points[1].x, element->points[1].y,
                                  element->points[2].x, element->points[2].y);
            break;
        case kCGPathElementCloseSubpath:
            CGPathCloseSubpath(transformerInfo->path);
            break;
    }
}

要使用它你会做(这是我将放在辅助函数中的部分):

    PathTransformInfo info;
    info.path = CGPathCreateMutable();
    info.transform = CGAffineTransformMakeScale(2, 1);

    CGPathApply(originalPath, &info,  PathTransformer);

此时已转换的路径位于info.path