【问题标题】:Preserve line width while scaling all points in the context with CGAffineTransform使用 CGAffineTransform 缩放上下文中的所有点时保留线宽
【发布时间】:2009-11-25 17:12:19
【问题描述】:

我在某个坐标系中有一个CGPath,我想绘制它。这样做涉及将旧坐标系缩放到上下文的坐标系上。为此,我使用了CGContextConcatCTM(),它会按应有的方式转换所有点。但是,由于它是缩放操作,因此水平/垂直线宽会更改为。例如。 x 方向的比例为 10,而 y 方向的比例为 1 将导致垂直线的粗度是水平线的 10 倍。有没有办法保持平移矩阵的易用性(例如CGAffineTransform)但不能同时缩放线宽,例如像CGPathApplyAffineTransformToPoints这样的函数?

干杯

魔法师

【问题讨论】:

    标签: core-graphics cgcontext cgaffinetransform cgpath stroke


    【解决方案1】:

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

    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);
    

    【讨论】:

    • 我现在没有这个问题了,但是你试过了吗?如果它按描述工作,那将是更好的答案。
    • @MrMage 是的,当我遇到同样的问题时,我发现了你的问题,然后过了一会儿我想出了自己的解决方案。
    • 谢谢,这对我有用。好像应该是官方的回答。
    【解决方案2】:

    您可以使用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

    【讨论】:

    • 谢谢!这将满足我的要求,但不幸的是,它不会给我带来不必重新创建整个路径的性能提升。如果这仍然是唯一的答案,我会将其标记为解决方案。
    猜你喜欢
    • 2019-02-26
    • 2012-02-04
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多