From d4db5d85acae8730ae94d2fa65fc4261f12f4cda Mon Sep 17 00:00:00 2001 From: George Nachman Date: Thu, 28 Jul 2016 11:19:06 -0700 Subject: [PATCH] Add CTVector, a preprocessor based template vector. Use it to store arrays of CGFloats for glyph positions. --- sources/CVector.h | 67 ++++++++++++++++++++++++++++++++ sources/iTermTextDrawingHelper.m | 56 +++++++++++++++----------- 2 files changed, 100 insertions(+), 23 deletions(-) diff --git a/sources/CVector.h b/sources/CVector.h index 209d1fd3cd..7fbd2e29b4 100644 --- a/sources/CVector.h +++ b/sources/CVector.h @@ -56,3 +56,70 @@ NS_INLINE id CVectorLastObject(const CVector *vector) { return CVectorGet(vector, vector->count - 1); } +// Hacky but fast templates in C. +// +// CTVector(double) myVector; +// CTVectorCreate(&myVector, 1); +// CTVectorAppend(&myVector, 123.456); +// CTVectorAppend(&myVector, 987.654); +// NSLog(@"Value is %f", CTVectorGet(&myVector, 0)); +// CTVectorDestroy(&myVector); +// +// To pass a vector: +// static void DoSomething(CTVector(double) *vector) { +// CTVectorAppend(vector, 123.456); +// } +// +// static void Caller() { +// CTVector(double) myVector; +// CTVectorCreate(&myVector, 1); +// DoSomething(&myVector); +// ... +// } +// +// All vector types must be defined at the bottom of this file with CTVectorDefine(t). + +#define CTVector(__type) CTVector_##__type + +#define CTVectorDefine(__type) \ +typedef struct { \ + int capacity; \ + __type *elements; \ + int count; \ +} CTVector(__type) + +#define CTVectorCreate(__vector, __capacity) \ +do { \ + __typeof(__vector) __v = __vector; \ + \ + __v->capacity = __capacity; \ + __v->elements = (__typeof(__v->elements))malloc(__v->capacity * sizeof(*__v->elements)); \ + __v->count = 0; \ +} while(0) + +#define CTVectorDestroy(__vector) CVectorDestroy((CVector *)(__vector)) +#define CTVectorGet(__vector, __index) (__vector)->elements[(__index)] +#define CTVectorCount(__vector) (__vector)->count +#define CTVectorSet(__vector, __index, __value) (__vector)->elements[(__index)] = (__value) +#define CTVectorAppend(__vector, __value) do { \ + __typeof(__vector) __v = (__vector); \ + \ + while (__v->count + 1 >= __v->capacity) { \ + __v->capacity *= 2; \ + __v->elements = realloc(__v->elements, sizeof(*__v->elements) * __v->capacity); \ + } \ + __v->elements[__v->count++] = (__value); \ +} while(0) +#define CTVectorElementsFromIndex(__vector, __index) (__vector)->elements + __index + +// Registry for typed vectors. +CTVectorDefine(CGFloat); +CTVectorDefine(float); +CTVectorDefine(double); +CTVectorDefine(int); +CTVectorDefine(short); +CTVectorDefine(char); +CTVectorDefine(NSInteger); +CTVectorDefine(NSUInteger); + + diff --git a/sources/iTermTextDrawingHelper.m b/sources/iTermTextDrawingHelper.m index d1824266f9..c905356c26 100644 --- a/sources/iTermTextDrawingHelper.m +++ b/sources/iTermTextDrawingHelper.m @@ -9,6 +9,7 @@ #import "iTermTextDrawingHelper.h" #import "charmaps.h" +#import "CVector.h" #import "DebugLogging.h" #import "iTermAdvancedSettingsModel.h" #import "iTermBackgroundColorRun.h" @@ -246,12 +247,14 @@ - (void)drawTextViewContentInRect:(NSRect)rect } -// NSColor *c = [NSColor colorWithCalibratedRed:(rand() % 255) / 255.0 -// green:(rand() % 255) / 255.0 -// blue:(rand() % 255) / 255.0 -// alpha:1]; -// [c set]; -// NSFrameRect(rect); + if (_debug) { + NSColor *c = [NSColor colorWithCalibratedRed:(rand() % 255) / 255.0 + green:(rand() % 255) / 255.0 + blue:(rand() % 255) / 255.0 + alpha:1]; + [c set]; + NSFrameRect(rect); + } } - (void)drawRanges:(NSRange *)ranges count:(NSInteger)numRanges origin:(VT100GridCoord)origin boundingRect:(NSRect)boundingRect { @@ -881,8 +884,10 @@ - (void)constructAndDrawRunsForLine:(screen_char_t *)theLine matches:(NSData *)matches forceTextColor:(NSColor *)forceTextColor // optional context:(CGContextRef)ctx { - NSMutableArray *positions = [NSMutableArray array]; - + CTVector(CGFloat) positions; + CTVectorCreate(&positions, _gridSize.width); + + if (indexRange.location > 0) { screen_char_t firstCharacter = theLine[indexRange.location]; if (firstCharacter.code == DWC_RIGHT && !firstCharacter.complexChar) { @@ -903,30 +908,32 @@ - (void)constructAndDrawRunsForLine:(screen_char_t *)theLine forceTextColor:forceTextColor findMatches:matches underlinedRange:[self underlinedRangeOnLine:row + _totalScrollbackOverflow] - positions:positions]; + positions:&positions]; iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats[TIMER_STAT_CONSTRUCTION]); iTermPreciseTimerStatsStartTimer(&_stats[TIMER_STAT_DRAW]); [self drawMultipartAttributedString:attributedStrings atPoint:initialPoint origin:VT100GridCoordMake(indexRange.location, row) - positions:positions + positions:&positions inContext:ctx backgroundColor:processedBackgroundColor]; + + CTVectorDestroy(&positions); iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats[TIMER_STAT_DRAW]); } - (void)drawMultipartAttributedString:(NSArray *)attributedStrings atPoint:(NSPoint)initialPoint origin:(VT100GridCoord)initialOrigin - positions:(NSArray *)positions + positions:(CTVector(CGFloat) *)positions inContext:(CGContextRef)ctx backgroundColor:(NSColor *)backgroundColor { NSPoint point = initialPoint; VT100GridCoord origin = initialOrigin; NSInteger start = 0; for (NSAttributedString *singlePartAttributedString in attributedStrings) { - NSArray *subpositions = [positions subarrayWithRange:NSMakeRange(start, singlePartAttributedString.length)]; + CGFloat *subpositions = CTVectorElementsFromIndex(positions, start); start += singlePartAttributedString.length; CGFloat width = [self drawSinglePartAttributedString:singlePartAttributedString @@ -967,7 +974,7 @@ - (void)drawBoxDrawingCharacter:(unichar)theCharacter withAttributes:(NSDictiona - (CGFloat)drawSinglePartAttributedString:(NSAttributedString *)attributedString atPoint:(NSPoint)point origin:(VT100GridCoord)origin - positions:(NSArray *)positions + positions:(CGFloat *)positions inContext:(CGContextRef)ctx backgroundColor:(NSColor *)backgroundColor { NSDictionary *attributes = [attributedString attributesAtIndex:0 effectiveRange:nil]; @@ -984,26 +991,29 @@ - (CGFloat)drawSinglePartAttributedString:(NSAttributedString *)attributedString } else if ([attributes[iTermIsBoxDrawingAttribute] boolValue]) { // Special box-drawing cells don't use the font so they look prettier. [attributedString.string enumerateComposedCharacters:^(NSRange range, unichar simple, NSString *complexString, BOOL *stop) { - NSPoint p = NSMakePoint(point.x + [positions[range.location] doubleValue], point.y); + NSPoint p = NSMakePoint(point.x + positions[range.location], point.y); [self drawBoxDrawingCharacter:simple withAttributes:[attributedString attributesAtIndex:range.location effectiveRange:nil] at:p]; }]; return _cellSize.width * attributedString.length; - } else { - CGFloat width = [[positions lastObject] doubleValue] + _cellSize.width; + } else if (attributedString.length > 0) { + CGFloat width = positions[attributedString.length - 1] + _cellSize.width; NSPoint offsetPoint = point; offsetPoint.y -= round((_cellSize.height - _cellSizeWithoutSpacing.height) / 2.0); [self drawTextOnlyAttributedString:attributedString atPoint:offsetPoint positions:positions width:width backgroundColor:backgroundColor]; DLog(@"Return width of %d", (int)round(width)); return width; + } else { + // attributedString is empty + return 0; } } - (void)drawTextOnlyAttributedString:(NSAttributedString *)attributedString atPoint:(NSPoint)origin - positions:(NSArray *)stringPositions + positions:(CGFloat *)stringPositions width:(CGFloat)width backgroundColor:(NSColor *)backgroundColor { DLog(@"Draw attributed string beginning at %d", (int)round(origin.x)); @@ -1081,9 +1091,9 @@ - (void)drawTextOnlyAttributedString:(NSAttributedString *)attributedString CGFloat positionOfFirstGlyphInCluster = positions[0].x; for (size_t glyphIndex = 0; glyphIndex < length; glyphIndex++) { CFIndex characterIndex = glyphIndexToCharacterIndex[glyphIndex]; - if (characterIndex != previousCharacterIndex && [stringPositions[characterIndex] doubleValue] != cellOrigin) { + if (characterIndex != previousCharacterIndex && stringPositions[characterIndex] != cellOrigin) { positionOfFirstGlyphInCluster = positions[glyphIndex].x; - cellOrigin = [stringPositions[characterIndex] doubleValue]; + cellOrigin = stringPositions[characterIndex]; } positions[glyphIndex].x += cellOrigin - positionOfFirstGlyphInCluster; } @@ -1121,9 +1131,9 @@ - (void)drawTextOnlyAttributedString:(NSAttributedString *)attributedString NSColor *underline = [self.colorMap colorForKey:kColorMapUnderline]; NSColor *color = (underline ? underline : attributes[NSForegroundColorAttributeName]); [self drawUnderlineOfColor:color - atCellOrigin:NSMakePoint(origin.x + [stringPositions[range.location] doubleValue], origin.y) + atCellOrigin:NSMakePoint(origin.x + stringPositions[range.location], origin.y) font:attributes[NSFontAttributeName] - width:[stringPositions[NSMaxRange(range) - 1] doubleValue] + self.cellSize.width - [stringPositions[range.location] doubleValue]]; + width:stringPositions[NSMaxRange(range) - 1] + self.cellSize.width - stringPositions[range.location]]; } }]; } @@ -1376,7 +1386,7 @@ - (NSDictionary *)imageAttributesForCharacter:(screen_char_t *)c { forceTextColor:(NSColor *)forceTextColor findMatches:(NSData *)findMatches underlinedRange:(NSRange)underlinedRange - positions:(NSMutableArray *)positions { + positions:(CTVector(CGFloat) *)positions { NSMutableArray *attributedStrings = [NSMutableArray array]; iTermColorMap *colorMap = self.colorMap; iTermTextColorContext textColorContext = { @@ -1479,7 +1489,7 @@ - (NSDictionary *)imageAttributesForCharacter:(screen_char_t *)c { // Append to positions. CGFloat offset = (i - indexRange.location) * _cellSize.width; for (NSUInteger j = 0; j < length; j++) { - [positions addObject:@(offset)]; + CTVectorAppend(positions, offset); } iTermPreciseTimerStatsAccumulate(&_stats[TIMER_ADVANCES]); }