代码之家  ›  专栏  ›  技术社区  ›  olaf

自定义ctline结构

  •  0
  • olaf  · 技术社区  · 6 年前

    我正在为我的项目创建自定义ctline结构。这是一个非常简单的实现,因为它不使用cfattributestring来创建行。整条线只有一种颜色,所有的字形大小相等。但是cfstring越长,创建它所需的时间就越多,并且比ctlinecreatewithattributedstring()慢。

    #import <Cocoa/Cocoa.h>
    
    #define sc (CFStringRef)
    
        struct Line {
            CGGlyph*line_glyphs;
            CGPoint*point;
            CTFontRef font;
            int length;
        };
    
    
        typedef  struct Line* LineRef;
    
        LineRef create(CFStringRef str, CTFontRef font);
    
        @interface View : NSView
        {
            LineRef line;
            CTLineRef l;
            CTFontRef font;
            CGFontRef font2;
            CFMutableStringRef string;
    
        }
     @end
    
    
    
     #import "View.h"
        #include <time.h>
    
    
        LineRef create(CFStringRef str, CTFontRef font){
    
            LineRef line = malloc(sizeof(struct Line));
            long length = CFStringGetLength(str);
    
            CGGlyph* gl = malloc(sizeof(CGGlyph)*length);
            CGPoint* points = malloc(sizeof(CGPoint)*length);
            CGRect rects[length];
            UniChar buffer[length];
            CFStringGetCharacters(str, CFRangeMake(0, length), buffer);
            CTFontGetGlyphsForCharacters(font, buffer, gl, length);
            CTFontGetBoundingRectsForGlyphs(font, kCTFontOrientationHorizontal, gl, rects, length);
            int x_offset  = 0;
            int y = 200;
            CGPoint temp;
            for(int i = 0;i<length;i++)
            {
                temp = CGPointMake(x_offset , y);
                x_offset += rects[i].size.width + (rects[i].size.width == 0)*10;
    
                points[i] = temp;
            }
    
            line->line_glyphs = gl;
            line->point = points;
            line->font = font;
            line->length = length;
            return line;
        }
    
    
    
        @implementation View
    
    
        -(void)awakeFromNib{
            font = CTFontCreateWithName(CFSTR("Comic Sans MS"), 30, 0);
            font2= CGFontCreateWithFontName(CFSTR("Comic Sans MS"));
            line = create(CFSTR(""), font);
            string = CFStringCreateMutable(kCFAllocatorDefault, 0);
            [[self window] makeFirstResponder:self];
    
    
        }
    
    
    
        -(void)keyDown:(NSEvent *)event{
            static int index = 0;
    
            NSString* i = [event characters];
    
            CFStringAppend(string,sc  i);
            CFMutableAttributedStringRef s = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
            CFAttributedStringReplaceString(s, CFRangeMake(0, 0), string);
            CFAttributedStringSetAttribute(s, CFRangeMake(0, CFStringGetLength(string)), kCTFontAttributeName, font);
            CFAbsoluteTime t1 = CFAbsoluteTimeGetCurrent();
            l = CTLineCreateWithAttributedString(s);
            CFAbsoluteTime t2 = CFAbsoluteTimeGetCurrent();
            double d1 = t2-t1;
            CFAbsoluteTime T1 = CFAbsoluteTimeGetCurrent();
            line = create(string, font);
            CFAbsoluteTime T2 = CFAbsoluteTimeGetCurrent();
            double d2 = T2 - T1;
            printf("test:%i core text: %f       my implem : %f \n",index, d1,d2);
    
    
    
            index++;
        }
    @end
    

    输出:

      test:0 core text: 0.000761       my implem : 0.000016 
        test:1 core text: 0.000047       my implem : 0.000029 
        test:2 core text: 0.000041       my implem : 0.000027 
        test:3 core text: 0.000045       my implem : 0.000032 
        test:4 core text: 0.000045       my implem : 0.000032 
        test:5 core text: 0.000046       my implem : 0.000034
        ...
        test:176 core text: 0.000068     my implem : 0.000151 
        test:177 core text: 0.000084     my implem : 0.000171 
        test:178 core text: 0.000099     my implem : 0.000230 
        test:179 core text: 0.000061     my implem : 0.000145 
        test:180 core text: 0.000071     my implem : 0.000224 
        test:181 core text: 0.000057     my implem : 0.000149
    

    您可以看到,前两个调用比ctline创建快,但比我的实现开始花更多的时间来完成工作。 可能是多个ctFontGetGlyphForCharacters()调用错误?你能给我一些建议来加速这段代码吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   jjrscott    6 年前

    使用 CTLineCreateWithAttributedString() 如有必要,请继续;您的管道中的其他地方存在更大的性能问题。 CGContextDrawPath() 是你真正的敌人。

    作为凭据,我编写了一个iOS应用程序,它允许 OSM's entire dataset 在iphone上显示-一直到人行道和建筑物。看起来是这样的(请注意,所有用于人行道的小脚都是字体中的字形):

    a map tile

    我的管道看起来有点像这样:

    1. 选中每个字符串的边界框并尽可能丢弃
    2. 呼叫 CtlineCreateWithAttributedString() 在剩下的琴弦上。
    3. 迭代每个 CTRun 使用 CTFontCreatePathForGlyph() 获取每个字形路径。
    4. 选中每个路径的边界框,并尽可能丢弃。
    5. 呼叫 CGContextDrawPath() 剩下的路

    步骤1和4是优化的地方。绘制摇摆的线(字形)是计算密集型的,没有办法绕过它。唯一的赢家是不玩 ¹ 是的。

    (要获得更多的优化乐趣,请查看 MinimumRubber ,特别是 MRPathMetrics 可以用来避免昂贵的 CGPath 基于功能)