@@ -607,9 +607,12 @@ static inline CGFloat _SquareDistanceFromPointToLine(CGFloat x0, CGFloat y0, CGF
607
607
return SQUARE (x1 * (y2 - y0) - y1 * (x2 - x0) + x2 * y0 - y2 * x0) / (SQUARE (y2 - y0) + SQUARE (x2 - x0));
608
608
}
609
609
610
- static void _DrawLine (GILine* line, CGContextRef context, CGFloat offset, CGFloat minY, CGFloat maxY) {
610
+ - (void )drawLine : (GILine*)line inContext : (CGContextRef)context clampedToRect : (CGRect)dirtyRect {
611
+ CGFloat offset = _graph.size .height ;
611
612
NSArray * nodes = line.nodes ;
612
613
NSUInteger count = nodes.count ;
614
+ CGFloat minY = CGRectGetMinY (dirtyRect);
615
+ CGFloat maxY = CGRectGetMaxY (dirtyRect);
613
616
BOOL recompute = YES ;
614
617
615
618
// Generate list of node coordinates aka points
@@ -795,6 +798,7 @@ static void _DrawLine(GILine* line, CGContextRef context, CGFloat offset, CGFloa
795
798
}
796
799
797
800
// Draw line
801
+ CGContextBeginPath (context);
798
802
BOOL visible = NO ;
799
803
size_t i = 0 ;
800
804
while (1 ) {
@@ -819,7 +823,6 @@ static void _DrawLine(GILine* line, CGContextRef context, CGFloat offset, CGFloa
819
823
if (!visible) {
820
824
CGContextMoveToPoint (context, x0, y0);
821
825
CGContextAddLineToPoint (context, x1, y1);
822
- CGContextStrokePath (context);
823
826
824
827
x0 = x1;
825
828
y0 = y1;
@@ -831,7 +834,6 @@ static void _DrawLine(GILine* line, CGContextRef context, CGFloat offset, CGFloa
831
834
// Draw line segment
832
835
CGContextMoveToPoint (context, x0, y0);
833
836
CGContextAddLineToPoint (context, x1, y1);
834
- CGContextStrokePath (context);
835
837
836
838
// Check if exiting visible area
837
839
if (y0 < minY) {
@@ -846,8 +848,8 @@ static void _DrawLine(GILine* line, CGContextRef context, CGFloat offset, CGFloa
846
848
y1 = pointList[i + 2 ].y ;
847
849
CGContextMoveToPoint (context, x0, y0);
848
850
CGContextAddLineToPoint (context, x1, y1);
849
- CGContextStrokePath (context);
850
851
852
+ visible = YES ;
851
853
break ; // We're done
852
854
}
853
855
@@ -860,12 +862,26 @@ static void _DrawLine(GILine* line, CGContextRef context, CGFloat offset, CGFloa
860
862
CGFloat y2 = pointList[i + 3 ].y ;
861
863
CGContextMoveToPoint (context, x0, y0);
862
864
CGContextAddQuadCurveToPoint (context, x1, y1, x2, y2);
863
- CGContextStrokePath (context);
864
865
865
866
i += 3 ;
866
867
visible = YES ;
867
868
}
868
869
870
+ BOOL shouldDraw = visible && [self needsToDrawRect: CGRectInset (CGContextGetPathBoundingBox (context), -kMainLineWidth , -kMainLineWidth )];
871
+ if (shouldDraw) {
872
+ XLOG_DEBUG_CHECK (!line.virtual || [[(GINode*)line.nodes[0 ] layer ] index ] == 0 );
873
+ CGContextSaveGState (context);
874
+ CGContextSetLineWidth (context, line.branchMainLine && !line.virtual ? kMainLineWidth : kSubLineWidth );
875
+ CGContextSetLineJoin (context, kCGLineJoinRound );
876
+ if (line.virtual ) {
877
+ const CGFloat pattern[] = {4 , 2 };
878
+ CGContextSetLineDash (context, 0 , pattern, 2 );
879
+ }
880
+ CGContextSetStrokeColorWithColor (context, line.color .CGColor );
881
+ CGContextStrokePath (context);
882
+ CGContextRestoreGState (context);
883
+ }
884
+
869
885
if (recompute) {
870
886
data = [[NSData alloc ] initWithBytesNoCopy: pointList length: (pointCount * sizeof (CGPoint)) freeWhenDone: YES ];
871
887
objc_setAssociatedObject (line, _associatedObjectDataKey, data, OBJC_ASSOCIATION_RETAIN_NONATOMIC );
@@ -1433,8 +1449,9 @@ - (void)drawRect:(NSRect)dirtyRect {
1433
1449
NSUInteger layerCount = layers.count ;
1434
1450
NSUInteger startIndex = layerCount ? [self _indexOfLayerContainingPosition: (dirtyRect.origin.y + dirtyRect.size.height + kOverdrawMargin )] : NSNotFound ;
1435
1451
NSUInteger endIndex = layerCount ? [self _indexOfLayerContainingPosition: dirtyRect.origin.y - kOverdrawMargin ] : 0 ;
1452
+ NSIndexSet * indexes = layerCount ? [[NSIndexSet alloc ] initWithIndexesInRange: NSMakeRange (startIndex, MIN (endIndex + 1 , layerCount) - startIndex)] : [[NSIndexSet alloc ] init ];
1436
1453
CGFloat offset = _graph.size .height ;
1437
- NSMutableArray * lines = [[NSMutableArray alloc ] init ];
1454
+ NSMutableSet * lines = [[NSMutableSet alloc ] init ];
1438
1455
1439
1456
// Cache attributes
1440
1457
static NSDictionary * tagAttributes = nil ;
@@ -1480,13 +1497,12 @@ - (void)drawRect:(NSRect)dirtyRect {
1480
1497
// Draw grid
1481
1498
CGContextSetLineWidth (context, 1 );
1482
1499
CGContextSetRGBStrokeColor (context, 1.0 , 1.0 , 1.0 , 0.25 );
1483
- for (NSUInteger index = startIndex; index <= endIndex; ++index) {
1484
- GILayer* layer = layers[index];
1500
+ [layers enumerateObjectsAtIndexes: indexes options: 0 usingBlock: ^(GILayer* layer, NSUInteger index, BOOL *stop) {
1485
1501
CGFloat y = CONVERT_Y (offset - layer.y );
1486
1502
CGContextMoveToPoint (context, dirtyRect.origin .x , y);
1487
1503
CGContextAddLineToPoint (context, dirtyRect.origin .x + dirtyRect.size .width , y);
1488
1504
CGContextStrokePath (context);
1489
- }
1505
+ }];
1490
1506
for (NSUInteger i = 0 ; i < 100 ; ++i) {
1491
1507
CGFloat x = CONVERT_X (i);
1492
1508
CGContextMoveToPoint (context, x, dirtyRect.origin .y );
@@ -1495,51 +1511,31 @@ - (void)drawRect:(NSRect)dirtyRect {
1495
1511
}
1496
1512
#endif
1497
1513
1498
- // Find all lines in the drawing area
1499
- for (NSUInteger index = startIndex; index <= endIndex; ++index) {
1500
- GILayer* layer = layers[index];
1501
- for (GILine* line in layer.lines ) {
1502
- if (![lines containsObject: line]) {
1503
- [lines addObject: line];
1504
- }
1505
- }
1506
- }
1507
-
1508
- // Draw lines
1509
- if (lines.count ) {
1510
- CGContextSetLineJoin (context, kCGLineJoinMiter );
1511
-
1514
+ // Draw all lines in the drawing area
1515
+ {
1512
1516
// Can’t multiply against a dark background.
1513
1517
if (!self.effectiveAppearance .matchesDarkAppearance ) {
1514
1518
CGContextSetBlendMode (context, kCGBlendModeMultiply );
1515
1519
}
1516
1520
1517
- for (NSInteger i = 0 , count = lines.count ; i < count; ++i) {
1518
- GILine* line = lines[i];
1519
- BOOL onBranchMainLine = line.branchMainLine ;
1520
- BOOL virtualLine = line.virtual ;
1521
- XLOG_DEBUG_CHECK (!virtualLine || [[(GINode*)line.nodes[0 ] layer ] index ] == 0 );
1522
- if (virtualLine) {
1523
- onBranchMainLine = NO ;
1524
- }
1525
- CGContextSetLineWidth (context, onBranchMainLine ? kMainLineWidth : kSubLineWidth );
1526
- CGContextSetStrokeColorWithColor (context, line.color .CGColor );
1527
- if (virtualLine) {
1528
- const CGFloat pattern[] = {4 , 2 };
1529
- CGContextSetLineDash (context, 0 , pattern, 2 );
1530
- }
1531
- _DrawLine (line, context, offset, dirtyRect.origin .y , dirtyRect.origin .y + dirtyRect.size .height );
1532
- if (virtualLine) {
1533
- CGContextSetLineDash (context, 0 , NULL , 0 );
1534
- }
1535
- }
1521
+ [layers enumerateObjectsAtIndexes: indexes
1522
+ options: 0
1523
+ usingBlock: ^(GILayer* layer, NSUInteger index, BOOL * stop) {
1524
+ for (GILine* line in layer.lines ) {
1525
+ if ([lines containsObject: line]) {
1526
+ continue ;
1527
+ }
1528
+ [self drawLine: line inContext: context clampedToRect: dirtyRect];
1529
+ [lines addObject: line];
1530
+ }
1531
+ }];
1532
+
1536
1533
CGContextSetBlendMode (context, kCGBlendModeNormal );
1537
1534
}
1538
1535
1539
1536
// Draw nodes
1540
1537
CGContextSetLineWidth (context, 1 );
1541
- for (NSUInteger index = startIndex; index <= endIndex; ++index) {
1542
- GILayer* layer = layers[index];
1538
+ [layers enumerateObjectsAtIndexes: indexes options: 0 usingBlock: ^(GILayer* layer, NSUInteger index, BOOL *stop) {
1543
1539
CGFloat y = CONVERT_Y (offset - layer.y );
1544
1540
for (GINode* node in layer.nodes ) {
1545
1541
CGFloat x = CONVERT_X (node.x );
@@ -1566,7 +1562,7 @@ - (void)drawRect:(NSRect)dirtyRect {
1566
1562
1567
1563
_DrawNode (node, context, x, y);
1568
1564
}
1569
- }
1565
+ }];
1570
1566
1571
1567
#if __DEBUG_MAIN_LINE__ || __DEBUG_DESCENDANTS__ || __DEBUG_ANCESTORS__
1572
1568
// Draw highlighted debug nodes
0 commit comments