From 659d89d7410f3addd563b8eb9e8ba7ddaaeb3cbe Mon Sep 17 00:00:00 2001 From: randomguy3 Date: Tue, 17 Jan 2012 19:47:18 +0000 Subject: We can now render arrow heads (in the GTK port, at least). git-svn-id: https://tikzit.svn.sourceforge.net/svnroot/tikzit/trunk@390 7c02a99a-9b00-45e3-bf44-6f3dd7fddb64 --- tikzit/src/common/Edge.h | 22 ++++++++++++++++ tikzit/src/common/Edge.m | 60 +++++++++++++++++++++++++++++------------- tikzit/src/linux/Edge+Render.m | 46 ++++++++++++++++++++++++++++++-- 3 files changed, 108 insertions(+), 20 deletions(-) diff --git a/tikzit/src/common/Edge.h b/tikzit/src/common/Edge.h index b92d7a7..959a724 100644 --- a/tikzit/src/common/Edge.h +++ b/tikzit/src/common/Edge.h @@ -73,6 +73,8 @@ typedef enum { NSPoint cp2; NSPoint mid; NSPoint midTan; + NSPoint headTan; + NSPoint tailTan; } /*! @@ -199,6 +201,26 @@ typedef enum { */ @property (readonly) NSPoint rightNormal; +/*! + @property leftHeadNormal + */ +@property (readonly) NSPoint leftHeadNormal; + +/*! + @property rightHeadNormal + */ +@property (readonly) NSPoint rightHeadNormal; + +/*! + @property leftTailNormal + */ +@property (readonly) NSPoint leftTailNormal; + +/*! + @property rightTailNormal + */ +@property (readonly) NSPoint rightTailNormal; + /*! @property isSelfLoop @brief Returns YES if this edge is a self loop. diff --git a/tikzit/src/common/Edge.m b/tikzit/src/common/Edge.m index 1878165..d95d528 100644 --- a/tikzit/src/common/Edge.m +++ b/tikzit/src/common/Edge.m @@ -107,6 +107,22 @@ return rayStart; } +- (NSPoint) _findTanFor:(NSPoint)pt usingSpanFrom:(float)t1 to:(float)t2 { + float dx = bezierInterpolate(t2, head.x, cp1.x, cp2.x, tail.x) - + bezierInterpolate(t1, head.x, cp1.x, cp2.x, tail.x); + float dy = bezierInterpolate(t2, head.y, cp1.y, cp2.y, tail.y) - + bezierInterpolate(t1, head.y, cp1.y, cp2.y, tail.y); + + // normalise + float len = sqrt(dx*dx+dy*dy); + if (len != 0) { + dx = (dx/len) * 0.1f; + dy = (dy/len) * 0.1f; + } + + return NSMakePoint (pt.x + dx, pt.y + dy); +} + - (void)updateControls { // check for external modification to the node locations if (src.x != [source point].x || src.y != [source point].y || @@ -146,24 +162,12 @@ cp2 = NSMakePoint(targ.x + (cdist * cos(angleTarg)), targ.y + (cdist * sin(angleTarg))); - - mid.x = bezierInterpolate(0.5f, src.x, cp1.x, cp2.x, targ.x); - mid.y = bezierInterpolate(0.5f, src.y, cp1.y, cp2.y, targ.y); - - dx = bezierInterpolate(0.6f, src.x, cp1.x, cp2.x, targ.x) - - bezierInterpolate(0.4f, src.x, cp1.x, cp2.x, targ.x); - dy = bezierInterpolate(0.6f, src.y, cp1.y, cp2.y, targ.y) - - bezierInterpolate(0.4f, src.y, cp1.y, cp2.y, targ.y); - - // normalise - float len = sqrt(dx*dx+dy*dy); - if (len != 0) { - dx = (dx/len) * 0.1f; - dy = (dy/len) * 0.1f; - } - - midTan.x = mid.x + dx; - midTan.y = mid.y + dy; + + mid = bezierInterpolateFull (0.5f, head, cp1, cp2, tail); + midTan = [self _findTanFor:mid usingSpanFrom:0.4f to:0.6f]; + + headTan = [self _findTanFor:head usingSpanFrom:0.0f to:0.1f]; + tailTan = [self _findTanFor:tail usingSpanFrom:1.0f to:0.9f]; } dirty = NO; } @@ -221,6 +225,26 @@ return NSMakePoint(mid.x - (mid.y - midTan.y), mid.y + (mid.x - midTan.x)); } +- (NSPoint)leftHeadNormal { + [self updateControls]; + return NSMakePoint(headTan.x + (head.y - headTan.y), headTan.y - (head.x - headTan.x)); +} + +- (NSPoint)rightHeadNormal { + [self updateControls]; + return NSMakePoint(headTan.x - (head.y - headTan.y), headTan.y + (head.x - headTan.x)); +} + +- (NSPoint)leftTailNormal { + [self updateControls]; + return NSMakePoint(tailTan.x + (tail.y - tailTan.y), tailTan.y - (tail.x - tailTan.x)); +} + +- (NSPoint)rightTailNormal { + [self updateControls]; + return NSMakePoint(tailTan.x - (tail.y - tailTan.y), tailTan.y + (tail.x - tailTan.x)); +} + - (NSPoint) head { [self updateControls]; return head; diff --git a/tikzit/src/linux/Edge+Render.m b/tikzit/src/linux/Edge+Render.m index c64b35f..d4a49c9 100644 --- a/tikzit/src/linux/Edge+Render.m +++ b/tikzit/src/linux/Edge+Render.m @@ -124,6 +124,43 @@ static const float cpLineWidth = 1.0; [context restoreState]; } +- (void) createArrowStrokePathInContext:(id)context withTransformer:(Transformer*)transformer { + [context startPath]; + + if ([self style] != nil) { + switch ([[self style] headStyle]) { + case AH_None: + break; + case AH_Plain: + [context moveTo:[transformer toScreen:[self leftHeadNormal]]]; + [context lineTo:[transformer toScreen:head]]; + [context lineTo:[transformer toScreen:[self rightHeadNormal]]]; + break; + case AH_Latex: + [context moveTo:[transformer toScreen:[self leftHeadNormal]]]; + [context lineTo:[transformer toScreen:head]]; + [context lineTo:[transformer toScreen:[self rightHeadNormal]]]; + [context closeSubPath]; + break; + } + switch ([[self style] tailStyle]) { + case AH_None: + break; + case AH_Plain: + [context moveTo:[transformer toScreen:[self leftTailNormal]]]; + [context lineTo:[transformer toScreen:tail]]; + [context lineTo:[transformer toScreen:[self rightTailNormal]]]; + break; + case AH_Latex: + [context moveTo:[transformer toScreen:[self leftTailNormal]]]; + [context lineTo:[transformer toScreen:tail]]; + [context lineTo:[transformer toScreen:[self rightTailNormal]]]; + [context closeSubPath]; + break; + } + } +} + - (void) createStrokePathInContext:(id)context withTransformer:(Transformer*)transformer { NSPoint c_head = [transformer toScreen:head]; NSPoint c_cp1 = [transformer toScreen:cp1]; @@ -149,8 +186,8 @@ static const float cpLineWidth = 1.0; [context lineTo:[transformer toScreen:[self rightNormal]]]; break; } - } + } } - (void) renderToSurface:(id )surface withContext:(id)context selected:(BOOL)selected { @@ -159,12 +196,17 @@ static const float cpLineWidth = 1.0; [context saveState]; const CGFloat lineWidth = style ? [style thickness] : edgeWidth; [context setLineWidth:lineWidth]; - [self createStrokePathInContext:context withTransformer:[surface transformer]]; RColor color = BlackRColor; if (selected) { color.alpha = 0.5; } + + [self createStrokePathInContext:context withTransformer:[surface transformer]]; [context strokePathWithColor:color]; + + [self createArrowStrokePathInContext:context withTransformer:[surface transformer]]; + [context strokePathWithColor:color andFillWithColor:color]; + [context restoreState]; if (selected) { -- cgit v1.2.3