Skip to content

Commit

Permalink
Add CTVector, a preprocessor based template vector. Use it to store a…
Browse files Browse the repository at this point in the history
…rrays of CGFloats for glyph positions.
  • Loading branch information
gnachman committed Jul 28, 2016
1 parent 567bbca commit d4db5d8
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 23 deletions.
67 changes: 67 additions & 0 deletions sources/CVector.h
Expand Up @@ -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);


56 changes: 33 additions & 23 deletions sources/iTermTextDrawingHelper.m
Expand Up @@ -9,6 +9,7 @@
#import "iTermTextDrawingHelper.h"

#import "charmaps.h"
#import "CVector.h"
#import "DebugLogging.h"
#import "iTermAdvancedSettingsModel.h"
#import "iTermBackgroundColorRun.h"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -881,8 +884,10 @@ - (void)constructAndDrawRunsForLine:(screen_char_t *)theLine
matches:(NSData *)matches
forceTextColor:(NSColor *)forceTextColor // optional
context:(CGContextRef)ctx {
NSMutableArray<NSNumber *> *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) {
Expand All @@ -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<NSAttributedString *> *)attributedStrings
atPoint:(NSPoint)initialPoint
origin:(VT100GridCoord)initialOrigin
positions:(NSArray<NSNumber *> *)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
Expand Down Expand Up @@ -967,7 +974,7 @@ - (void)drawBoxDrawingCharacter:(unichar)theCharacter withAttributes:(NSDictiona
- (CGFloat)drawSinglePartAttributedString:(NSAttributedString *)attributedString
atPoint:(NSPoint)point
origin:(VT100GridCoord)origin
positions:(NSArray<NSNumber *> *)positions
positions:(CGFloat *)positions
inContext:(CGContextRef)ctx
backgroundColor:(NSColor *)backgroundColor {
NSDictionary *attributes = [attributedString attributesAtIndex:0 effectiveRange:nil];
Expand All @@ -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<NSNumber *> *)stringPositions
positions:(CGFloat *)stringPositions
width:(CGFloat)width
backgroundColor:(NSColor *)backgroundColor {
DLog(@"Draw attributed string beginning at %d", (int)round(origin.x));
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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]];
}
}];
}
Expand Down Expand Up @@ -1376,7 +1386,7 @@ - (NSDictionary *)imageAttributesForCharacter:(screen_char_t *)c {
forceTextColor:(NSColor *)forceTextColor
findMatches:(NSData *)findMatches
underlinedRange:(NSRange)underlinedRange
positions:(NSMutableArray<NSNumber *> *)positions {
positions:(CTVector(CGFloat) *)positions {
NSMutableArray<NSAttributedString *> *attributedStrings = [NSMutableArray array];
iTermColorMap *colorMap = self.colorMap;
iTermTextColorContext textColorContext = {
Expand Down Expand Up @@ -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]);
}
Expand Down

0 comments on commit d4db5d8

Please sign in to comment.