3

我正在使用 Objective-C++。

我正在尝试使用NSBezierPaths获取文本的路径轮廓appendBezierPathWithGlyphs。问题是:输出相当无意义:(

我写的:

  String str = Ascii8("test string");
  int length = str.getLength();

  NSFont* font = [NSFont fontWithDescriptor: [NSFontDescriptor fontDescriptorWithName:@"Times"
                                                                                 size:20]
                            textTransform: transform];

  NSTextStorage *storage = [[NSTextStorage alloc] initWithString:toNSString(str)];
  NSLayoutManager *manager = [[NSLayoutManager alloc] init];
  NSTextContainer *container = [[NSTextContainer alloc] init];

  [storage addLayoutManager:manager];
  [manager addTextContainer:container];

  NSGlyph* glyphs = new NSGlyph[length+1];
  [manager getGlyphs:glyphs range:NSMakeRange(0, length)];

  [container release];
  [manager release];
  [storage release];

  NSBezierPath* path = [NSBezierPath bezierPath];
  // If I don't do this I get an exception that currentPoint doesn't exist ...
  [path moveToPoint: NSMakePoint(0, 0)]; 
  [path appendBezierPathWithGlyphs:glyphs count:length inFont:font];

  delete[] glyphs;

  // NSBezierPath -> DoublePath
  for (NSInteger i=0; i<[path elementCount]; ++i)
  {
    NSPoint controlPoints[3];
    NSBezierPathElement el = [path elementAtIndex:i associatedPoints:controlPoints];
    if (el == NSMoveToBezierPathElement)
    {
      printf("move to (%f,%f)\n", controlPoints[0].x, controlPoints[0].y);
    }
    else if (el == NSLineToBezierPathElement)
    {
      printf("line to (%f, %f)\n", controlPoints[0].x, controlPoints[0].y);
    }
    else if (el == NSCurveToBezierPathElement)
    {
      printf("cubic to (%f, %f) (%f, %f) (%f, %f)\n", 
         controlPoints[0].x, controlPoints[0].y,
         controlPoints[1].x, controlPoints[1].y,
         controlPoints[2].x, controlPoints[2].y);
    }   
    else if (el == NSClosePathBezierPathElement) 
    {
      printf("close\n");
    }
  }

例如对于字母“t”,我得到以下输出:

move to (0.277832, 0.000000)
move to (0.254395, 0.450195)
line to (0.254395, 0.415039)
line to (0.154785, 0.415039)
line to (0.153809, 0.133789)
cubic to (0.153809, 0.109049) (0.155924, 0.090332) (0.160156, 0.077637)
cubic to (0.167969, 0.055176) (0.183268, 0.043945) (0.206055, 0.043945)
cubic to (0.217773, 0.043945) (0.227946, 0.046712) (0.236572, 0.052246)
cubic to (0.245199, 0.057780) (0.255046, 0.066569) (0.266113, 0.078613)
line to (0.278809, 0.067871)
line to (0.268066, 0.053223)
cubic to (0.251139, 0.030436) (0.233236, 0,014323) (0.214355, 0.004883)
cubic to (0.195475, -0.004557) (0.177246, -0.009277) (0.159668, -0.009277)
cubic to (0.121256, -0.009277) (0.095215, 0.007812) (0.081543, 0.041992)
cubic to (0.074056, 0.060547) (0.070312, 0.086263) (0.070312, 0.119141)
line to (0.070312, 0.415039)
line to (0.017090, 0.415039)
cubic to (0.015462, 0.416016) (0.014242, 0.416992) (0.013428, 0.417969)
cubic to (0.012614, 0.418945) (0.012207, 0.420247) (0.012207, 0.421875)
cubic to (0.012207, 0.425130) (0.012939, 0.427653) (0.014404, 0.429443)
cubic to (0.015869, 0.431234) (0.020508, 0.435384) (0.028320, 0.441895)
cubic to (0.050781, 0.460449) (0.066976, 0.475504) (0.076904, 0.487061)
cubic to (0.086833, 0.498617) (0.110189, 0.529134) (0.146973, 0.578613)
cubic to (0.151204, 0.578613) (0.153727, 0.578288) (0.154541, 0.577637)
cubic to (0.155355, 0.576986) (0.155762, 0.574544) (0.155762, 0.570312)
line to (0.155762, 0.450195)
close

这对我来说真的很不对劲!

4

1 回答 1

2

“看起来不对”是什么意思?您是否尝试过渲染数据?这是有效的。

下面是修改后的代码以输出曲线数据的 SVG,它看起来是正确的(但由于 SVG 的坐标约定不同,所以颠倒了)。除此之外,删除一些随机的 C++,并transform在提取中添加未定义的内容,唯一的区别是它正确地计算了带有[manager numberOfGlyphs]. 在测试用例中,这没有区别,但通常字形计数与字符串的长度不同。

NSString *str = @"test string";
int length = str.length;
NSAffineTransform *transform = [NSAffineTransform transform];

NSFont* font = [NSFont fontWithDescriptor: [NSFontDescriptor fontDescriptorWithName:@"Times" size:20]
                            textTransform: transform];

NSTextStorage *storage = [[NSTextStorage alloc] initWithString:str];
NSLayoutManager *manager = [[NSLayoutManager alloc] init];
NSTextContainer *container = [[NSTextContainer alloc] init];

[storage addLayoutManager:manager];
[manager addTextContainer:container];

NSUInteger glyphCount = [manager numberOfGlyphs];
NSGlyph glyphs[glyphCount];
[manager getGlyphs:glyphs range:NSMakeRange(0, glyphCount)];

[container release];
[manager release];
[storage release];

NSBezierPath* path = [NSBezierPath bezierPath];
[path moveToPoint: NSMakePoint(0, 0)]; // If I don't do this I get an exception that currentPoint doesn't exist ...
[path appendBezierPathWithGlyphs:glyphs count:length inFont:font];


printf("<?xml version=\"1.0\" standalone=\"no\"?>\n"
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
       "<svg viewBox=\"-5 -5 10 10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n"
       "\t<desc>Debug dump</desc>\n"
       "\t\n<path d=\"");

// NSBezierPath -> DoublePath
for (NSInteger i=0; i<[path elementCount]; ++i)
{
    if (i != 0)  printf(" ");

    NSPoint controlPoints[3];
    NSBezierPathElement el = [path elementAtIndex:i associatedPoints:controlPoints];
    if (el == NSMoveToBezierPathElement)
    {
    //  printf("move to (%f,%f)\n", controlPoints[0].x, controlPoints[0].y);
        printf("M%g %g", controlPoints[0].x, controlPoints[0].y);
    }
    else if (el == NSLineToBezierPathElement)
    {
    //  printf("line to (%f, %f)\n", controlPoints[0].x, controlPoints[0].y);
        printf("L%g %g", controlPoints[0].x, controlPoints[0].y);
    }
    else if (el == NSCurveToBezierPathElement)
    {
    //  printf("cubic to (%f, %f) (%f, %f) (%f, %f)\n", 
        printf("C%g %g %g %g %g %g",
               controlPoints[0].x, controlPoints[0].y,
               controlPoints[1].x, controlPoints[1].y,
               controlPoints[2].x, controlPoints[2].y);
    }   
    else if (el == NSClosePathBezierPathElement) 
    {
    //  printf("close\n");
        printf("Z");
    }
}

printf("\"/>\n</svg>\n");
于 2010-09-11T21:12:35.757 回答