HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Optimizing text drawing on screen

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
screentextoptimizingdrawing

Problem

I'm looking to speed up this method. Ideally, I would like to cut the time in 1/2 or more. At the moment I have to draw the screen line-by-line as the font is 16 pixels high, but it is being drawn with an extra blank pixel on the bottom. If I could figure out how to set the line-height to 16 pixels I would imagine that drawing 1 string over 24 strings would help speed it up. Baring that what else can I do to increase the speed?

- (void)drawRect:(NSRect)dirtyRect
{
    NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
    CGContextRef context = (CGContextRef) [nsGraphicsContext graphicsPort];

    CGContextSetShouldSmoothFonts(context, false);

    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@""];
    for (int y=24; y >= 0; y--) {
        [[string mutableString] setString:@""];;
        for (int x=0; x < 80; x++) {
            AnsiScreenChar *c = [self.screen objectAtIndex:(y*80)+x];
            [self.fontAttributes setValue:c.fgColor forKey:NSForegroundColorAttributeName];
            [self.fontAttributes setValue:c.bgColor forKey:NSBackgroundColorAttributeName];

            NSAttributedString *subString = [[NSAttributedString alloc] initWithString:c.data
                                                                            attributes:self.fontAttributes];
            [string appendAttributedString:subString];
        }
        [string drawAtPoint:NSMakePoint(0, self.frame.size.height - ((y+1)*16))];
    }
}


Profile

`Running Time Self Symbol Name
3276.0ms 9.5% 3276.0 -[AnsiView drawRect:]
1726.0ms 5.0% 1726.0 -[NSLayoutManager(NSTextViewSupport) showCGGlyphs:positions:count:font:matrix:attributes:inContext:]
1540.0ms 4.4% 1540.0 -[__NSCFDictionary setObject:forKey:]
1467.0ms 4.2% 1467.0 -[NSObject dealloc]
1118.0ms 3.2% 1118.0 -[NSView _drawRect:clip:]
1108.0ms 3.2% 1108.0 -[NSConcreteHashTable getItem:]
1106.0ms 3

Solution

You want to avoid as much work inside drawRect: as possible. Instead of recalculating the attributed string for each line here do it whenever self.screen changes. That way it's done once instead of every time the some portion of the view is redrawn (which will happen a lot).

Maybe keep a self.lines array with the attributed string for each line in it. Or maybe it's a dictionary with the key being the line number and you just keep adding lines and drawRect just draws the last displayHeight lines.

Basically do everything you can to remove unnecessary work from drawRect.

Context

StackExchange Code Review Q#8880, answer score: 5

Revisions (0)

No revisions yet.