将 CGPathRef 转换为 NSBezierPath

2023-12-25

在 Apple 文档中,他们为您提供了如何将 NSBezierPath 转换为 CGPathRef 的代码。我需要以相反的方式进行转换,从 CGPathRef 转换为 NSBezierPath。 UIBezierPath 有一个名为 cgPath 的属性,因此如果我在 iPhone 上工作,这不会有问题,但我在 MacOS 上工作。

这一定是一个老问题了,我肯定会在互联网上找到答案,但没有运气。可能是我错过了一些东西。任何帮助表示赞赏。


老问题,但我相信这对其他人仍然有帮助。 (您没有指定 Objective-C 或 Swift;这是 Objective-C 答案。)

您可以转换一个CGPathRef to an NSBezierPath using CGPathApply()使用应用程序函数回调来翻译CGPathRef指着NSBezierPath点。唯一棘手的部分是从CGPathRef的二次曲线为NSBezierPath的三次曲线但是有一个方程式 http://fontforge.github.io/bezier.html:

任何二次样条都可以表示为三次样条(其中三次项为零)。三次方程的端点与二次方程的端点相同。

 CP0 = QP0
 CP3 = QP2 

三次方的两个控制点是:

 CP1 = QP0 + 2/3 * (QP1-QP0)
 CP2 = QP2 + 2/3 * (QP1-QP2)

...由于舍入而引入了轻微的误差,但通常不明显。

使用上面的等式,这是一个NSBezierPath转换自的类别CGPathRef:

NSBezierPath+BezierPathWithCGPath.h

@interface NSBezierPath (BezierPathWithCGPath)
+ (NSBezierPath *)JNS_bezierPathWithCGPath:(CGPathRef)cgPath; //prefixed as Apple may add bezierPathWithCGPath: method someday
@end

NSBezierPath+BezierPathWithCGPath.m

static void CGPathToBezierPathApplierFunction(void *info, const CGPathElement *element) {
    NSBezierPath *bezierPath = (__bridge NSBezierPath *)info;
    CGPoint *points = element->points;
    switch(element->type) {
        case kCGPathElementMoveToPoint: [bezierPath moveToPoint:points[0]]; break;
        case kCGPathElementAddLineToPoint: [bezierPath lineToPoint:points[0]]; break;
        case kCGPathElementAddQuadCurveToPoint: {
            NSPoint qp0 = bezierPath.currentPoint, qp1 = points[0], qp2 = points[1], cp1, cp2;
            CGFloat m = (2.0 / 3.0);
            cp1.x = (qp0.x + ((qp1.x - qp0.x) * m));
            cp1.y = (qp0.y + ((qp1.y - qp0.y) * m));
            cp2.x = (qp2.x + ((qp1.x - qp2.x) * m));
            cp2.y = (qp2.y + ((qp1.y - qp2.y) * m));
            [bezierPath curveToPoint:qp2 controlPoint1:cp1 controlPoint2:cp2];
            break;
        }
        case kCGPathElementAddCurveToPoint: [bezierPath curveToPoint:points[2] controlPoint1:points[0] controlPoint2:points[1]]; break;
        case kCGPathElementCloseSubpath: [bezierPath closePath]; break;
    }
}

@implementation NSBezierPath (BezierPathWithCGPath)
+ (NSBezierPath *)JNS_bezierPathWithCGPath:(CGPathRef)cgPath {
    NSBezierPath *bezierPath = [NSBezierPath bezierPath];
    CGPathApply(cgPath, (__bridge void *)bezierPath, CGPathToBezierPathApplierFunction);
    return bezierPath;
}
@end

像这样调用:

//...get cgPath (CGPathRef) from somewhere
NSBezierPath *bezierPath = [NSBezierPath JNS_bezierPathWithCGPath:cgPath];
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 CGPathRef 转换为 NSBezierPath 的相关文章

随机推荐

  • ODBC 管理员找不到 Oracle TNS 名称文件

    当我去安装新的 Oracle 时Configuration Management Tools gt Microsoft ODBC Administrator gt System DSN gt Add gt new installation
  • 支持使用 ajax 的浏览器后退按钮而不依赖于哈希更改?

    我目前正在使用 jQuery BBQ 插件来启用 Bowser 导航按钮 但我有一个问题 如果用户为其中一个页面保存书签 比如说 www mysite com page1 当用户通过书签返回时 必须首先加载整个页面 www mysite c
  • 释放指针变量指向的内容后重用它们是否安全?

    释放指针指向的数据后重用指针是否安全且可预测 例如 char fileNames words txt moreWords txt char words NULL int wordsCount NULL for i 0 i lt 2 i da
  • 是否有 Google 自定义搜索 REST API 的工作示例?

    我需要创建一个自动执行 Google 搜索的屏幕 我了解 JavaScript 并且我正在努力让 GSE 工作 我有一个搜索引擎和一个 API 密钥 问题是谷歌的文档是循环的 即页面相互指向 没有可以让我开始研究的工作样本 如果您知道工作示
  • 这两个递归函数可以合并为一个吗?

    int sorted a int arr int N if N 1 N 0 return 1 if arr N 1 lt arr N 2 return 0 return sorted a arr N 1 int sorted d int a
  • 如何从 asmx Web 服务返回纯 XML?

    我想要一个带有方法 GetPeople 的 asmx Web 服务 该方法返回以下 XML 不是 SOAP 响应
  • Perl 中浮点到十进制转换的二进制表示

    我读了堆栈溢出问题如何在 Perl 中将二进制字符串转换为数字 https stackoverflow com questions 483655 how do i convert a binary string to a number in
  • 异步 System.Threading.Timer 有时会抛出空异常[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我试图在一段时间间隔后异步执行代码 并且只想在完成代码执行后再次检查以防止重叠 为此 我使用以下变量和计时器代码 pri
  • 伪类和伪元素有什么区别?

    有什么区别div after and div after 我们什么时候必须使用 over 双冒号和单冒号表示法是区分的 伪类和伪元素 上述说法的实际含义是什么 From https developer mozilla org en US d
  • 如何在 Markdown 标记中缩进几行?

    我想写几行文字 它们的格式应正常 但每行应从第六列开始 IE 我不希望代码块格式化规则使这块文本看起来像代码 因为我将使用其他格式 如粗体等 如何在 Markdown 中做到这一点 Markdown 的原生功能无法做到这一点 然而 mark
  • Xcode 9 - 测试目标 X 遇到错误(无法连接到测试管理器)

    我正在尝试运行一些单元测试 但它一直给我错误 Showing Recent Issues Test target X encountered an error Unable to connect to test manager on d73
  • 使用什么算法来计算校验位?

    使用什么算法来计算数字列表的校验位 列表的长度在 8 到 12 位数字之间 也可以看看 如何生成验证码 号码 https stackoverflow com questions 46231 how to generate a verific
  • Firebase HTTP v1 API 不再批量发送?

    我收到了一封来自 Google 的电子邮件 通知我以下服务即将停用 在对 FCM 的单个 HTTP 请求中包含多个发送请求 称为批量发送 推荐的方法是 通过 HTTP v1 API 发送消息 该 API 已针对扇出性能进行了优化 在本页面
  • Symfony2 twig 翻译 {% trans %} 标签中的变量值

    我正在开发一个 Symfony2 项目并有一个问题 合而为一twig模板我从控制器收到一个变量 这是一个字符串 我需要翻译它 但语法 trans post name endtrans 返回错误 消息必须是 中的简单文本 那么有没有办法翻译变
  • C++0x 原子模板实现

    我知道英特尔的 TBB 中存在类似的模板 除此之外我在 google 或 Boost 库中找不到任何实现 您可以在 boost 中找到有关此功能实现的讨论 http lists boost org Archives boost 2008 1
  • 使用 htaccess 从特定文件夹中删除 SSL 集成

    我的整个网站都集成了 SSL 并放置了 htaccess 代码 以便在任何人访问我的域 URL 时重定向到 https 但我想将一个文件夹保留在 https 重定向之外 请帮我解决这个问题 下面是放置在我的根目录中的 htaccess 代码
  • 使用 pandas.merge_asof 进行全外连接

    您好 我需要将一些时间序列数据与最近的时间戳对齐 所以我认为pandas merge asof可能是一个很好的候选人 但是 它没有设置选项how outer 就像标准中一样merge method 一个例子可以是 df1 Value1 Ti
  • form_for 中 :model 和 @model 的区别?

    使用 form for 以下方式有什么区别 and 使用 user 是否会自动对 URL 操作使用 CRUD 方法 如果你只是给出一个模型实例 例如 user如果不指定操作 如第一个
  • Django:删除关系末尾时不会触发 m2m_changed

    NOTICE 由于生产环境限制 我必须坚持django 1 4暂时 我刚刚做了一个测试 看看当 ManyToMany 发生变化时是否可以挂钩事件 我有一个Group模型可容纳多个Item对象 每当任何组中的项目发生变化时 我都想对相关的 G
  • 将 CGPathRef 转换为 NSBezierPath

    在 Apple 文档中 他们为您提供了如何将 NSBezierPath 转换为 CGPathRef 的代码 我需要以相反的方式进行转换 从 CGPathRef 转换为 NSBezierPath UIBezierPath 有一个名为 cgPa