Drawing strings on a line

View: New views
5 Messages — Rating Filter:   Alert me  

Drawing strings on a line

by Andreas Höschler :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello all,

I am developing a mapping application where I need to draw labels in a
view. Currently I am using (as a first approach)

              [_name drawAtPoint:labelPoint withAttributes:nil];

This works: However, it does not exactly has the desired effect, since
the labels are always drawn horizontally. The labels are actually
street names and the streets are drawn with NSBezierPath stroke.
Ideally I would like the street label to be exactly drawn on the
NSBezierPath which is a connected list of points, but at least to be
drawn with the same angle as the NSBezierPath segment. There is this
NSBezierPath

- (void)appendBezierPathWithGlyphs:(NSGlyph *)glyphs count:(int)count
inFont:(NSFont *)fontObj

method that might be of interest in conjunction with

NSBezierPath *bezierPath = [NSBezierPath bezierPath];
NSAffineTransform *transform = [NSAffineTransform transform];

[bezierPath moveToPoint: NSMakePoint(0.0, 0.0)];
[bezierPath lineToPoint: NSMakePoint(100.0, 100.0)];

[transform translateXBy: 10.0 yBy: 10.0];
[bezierPath transformUsingAffineTransform: transform];

but this means to manually find the glyphs for each character in the
label ([NSFont glyphWithName:]). This probably works on MacOSX, but
does it also work under GNUstep? I am wondering if there is even an
easier approach for accomplishing this!?

Hints are greatly appreciated!

Thanks,

   Andreas







_______________________________________________
Discuss-gnustep mailing list
Discuss-gnustep@...
http://lists.gnu.org/mailman/listinfo/discuss-gnustep

Re: Drawing strings on a line

by Fred Kiefer :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Andreas Höschler wrote:

> Hello all,
>
> I am developing a mapping application where I need to draw labels in a
> view. Currently I am using (as a first approach)
>
> [_name drawAtPoint:labelPoint withAttributes:nil];
>
> This works: However, it does not exactly has the desired effect, since
> the labels are always drawn horizontally. The labels are actually street
> names and the streets are drawn with NSBezierPath stroke. Ideally I
> would like the street label to be exactly drawn on the NSBezierPath
> which is a connected list of points, but at least to be drawn with the
> same angle as the NSBezierPath segment. There is this NSBezierPath
>
> - (void)*appendBezierPathWithGlyphs:*(NSGlyph *)/glyphs/
> *count:*(int)/count/ *inFont:*(NSFont *)/fontObj/
>
> method that might be of interest in conjunction with
>
> NSBezierPath *bezierPath = [NSBezierPath bezierPath];
> NSAffineTransform *transform = [NSAffineTransform transform];
>
> [bezierPath moveToPoint: NSMakePoint(0.0, 0.0)];
> [bezierPath lineToPoint: NSMakePoint(100.0, 100.0)];
>
> [transform translateXBy: 10.0 yBy: 10.0];
> [bezierPath transformUsingAffineTransform: transform];
>
> but this means to manually find the glyphs for each character in the
> label ([NSFont glyphWithName:]). This probably works on MacOSX, but does
> it also work under GNUstep? I am wondering if there is even an easier
> approach for accomplishing this!?

I don't think that appendBezierPathWithGlyphs: will help you on your
specific problem. (Although the method itself should work) That way you
would get a path with all the outlines of the string, again you could
only transform the whole of it, but as I understand you, you would like
to transform each single glyph.

In the cairo mailing list this is a subject that comes up from time to
time. The last time was November last year and the subject was " render
text along path" it should be easy to google for that. Here are some of
the hints that came up at that discussion.

Pycairo comes with the example examples/warpedtext.py which draws text
along a path.

 http://svn.gnome.org/viewvc/pango/trunk/examples/cairotwisted.c?view=markup
http://www.flickr.com/photos/behdad/3058628981/sizes/o/


Hope this helps
Fred


_______________________________________________
Discuss-gnustep mailing list
Discuss-gnustep@...
http://lists.gnu.org/mailman/listinfo/discuss-gnustep

Re: Drawing strings on a line

by David Chisnall :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 Jun 2009, at 19:19, Andreas Höschler wrote:

> Hello all,
>
> I am developing a mapping application where I need to draw labels in  
> a view. Currently I am using (as a first approach)
>
>      [_name drawAtPoint:labelPoint withAttributes:nil];
>
> This works: However, it does not exactly has the desired effect,  
> since the labels are always drawn horizontally. The labels are  
> actually street names and the streets are drawn with NSBezierPath  
> stroke. Ideally I would like the street label to be exactly drawn on  
> the NSBezierPath which is a connected list of points, but at least  
> to be drawn with the same angle as the NSBezierPath segment. There  
> is this NSBezierPath
>
> - (void)appendBezierPathWithGlyphs:(NSGlyph *)glyphs count:
> (int)count inFont:(NSFont *)fontObj

This is, without any doubts in my mind, the worst-named method in the  
whole of AppKit.  It appends a set of gylphs, but they are drawn  
horizontally at the current point, not along the path.  I've not  
tested it on GNUstep, but the easiest way of doing this on OS X is to  
do something like this:

void drawAtPointWithAngle(NSAttributedString *str, NSPoint p, CGFloat  
angle)
{
     NSAffineTransform * transform = [NSAffineTransform transform];
     [transform translateXBy: -p.x yBy: -p.y];
     [transform rotateByDegrees: angle];
     [NSGraphicsContext saveGraphicsState];
     [transform concat];
     [str drawAtPoint: NSMakePoint(0,0)];
     [NSGraphicsContext restoreGraphicsState];
}

Assuming I've not mixed up the transforms (it's late - I probably  
have), this will set a coordinate transform for a translated, rotated,  
system, draw the string horizontally at the origin in this space (i.e.  
translated and rotated) and then reset the context.

David

P.S. Prior to 10.5, this was really slow because the  
NSAttrubutedString method set up all of the text system objects and  
then destroyed them at the end.  With 10.5, there is just one instance  
of the text system objects that is shared between all  
NSAttributedString instances, so this is very fast.  If this isn't the  
case in GNUstep, it should be, because Cocoa programmers are likely to  
use this convenience method a lot more now that it's fast for them.

_______________________________________________
Discuss-gnustep mailing list
Discuss-gnustep@...
http://lists.gnu.org/mailman/listinfo/discuss-gnustep

Re: Drawing strings on a line

by Matt Rice-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/6/3 David Chisnall <theraven@...>:
>
> P.S. Prior to 10.5, this was really slow because the NSAttrubutedString
> method set up all of the text system objects and then destroyed them at the
> end.  With 10.5, there is just one instance of the text system objects that
> is shared between all NSAttributedString instances, so this is very fast.
>  If this isn't the case in GNUstep, it should be, because Cocoa programmers
> are likely to use this convenience method a lot more now that it's fast for
> them.
>

been a long time since i looked at it but i think this has been the
case since this patch
in 2003

http://svn.gna.org/viewcvs/gnustep/libs/gui/trunk/Source/NSStringDrawing.m?r2=16250&rev=16250&r1=15774&dir_pagestart=150


_______________________________________________
Discuss-gnustep mailing list
Discuss-gnustep@...
http://lists.gnu.org/mailman/listinfo/discuss-gnustep

Re: Drawing strings on a line

by Andreas Höschler :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi David,

>>
>> I am developing a mapping application where I need to draw labels in
>> a view. Currently I am using (as a first approach)
>>
>>      [_name drawAtPoint:labelPoint withAttributes:nil];
>>
>> This works: However, it does not exactly has the desired effect,
>> since the labels are always drawn horizontally. The labels are
>> actually street names and the streets are drawn with NSBezierPath
>> stroke. Ideally I would like the street label to be exactly drawn on
>> the NSBezierPath which is a connected list of points, but at least to
>> be drawn with the same angle as the NSBezierPath segment. There is
>> this NSBezierPath
>>
>> - (void)appendBezierPathWithGlyphs:(NSGlyph *)glyphs count:(int)count
>> inFont:(NSFont *)fontObj
>
> This is, without any doubts in my mind, the worst-named method in the
> whole of AppKit.  It appends a set of gylphs, but they are drawn
> horizontally at the current point, not along the path.  I've not
> tested it on GNUstep, but the easiest way of doing this on OS X is to
> do something like this:
>
> void drawAtPointWithAngle(NSAttributedString *str, NSPoint p, CGFloat
> angle)
> {
>     NSAffineTransform * transform = [NSAffineTransform transform];
>     [transform translateXBy: -p.x yBy: -p.y];
>     [transform rotateByDegrees: angle];
>     [NSGraphicsContext saveGraphicsState];
>     [transform concat];
>     [str drawAtPoint: NSMakePoint(0,0)];
>     [NSGraphicsContext restoreGraphicsState];
> }
>
> Assuming I've not mixed up the transforms (it's late - I probably
> have), this will set a coordinate transform for a translated, rotated,
> system, draw the string horizontally at the origin in this space (i.e.
> translated and rotated) and then reset the context.

Thanks for your responses. Since neither core foundation (MacOSX) nor
cairo can be used I did stick to the above approach. The method that
actually works for me is

- (void)drawString:(NSString *)str atPoint:(NSPoint)point
angle:(float)angle offset:(BOOL)offset
{
    static NSDictionary *_attr = nil;
    if (!_attr) _attr = [[NSDictionary alloc]
initWithObjectsAndKeys:LABELFONT, NSFontAttributeName, nil];
    NSSize size = [str sizeWithAttributes:_attr];
    NSAffineTransform * transform = [NSAffineTransform transform];
    [transform translateXBy: point.x yBy: point.y];
    [transform rotateByDegrees:angle];
    [transform translateXBy: (offset ? - size.width / 2 : 0.0) yBy: -
size.height / 2]; // <--
    [NSGraphicsContext saveGraphicsState];
    [transform concat];
    [str drawAtPoint:NSMakePoint(0,0) withAttributes:_attr];
    [NSGraphicsContext restoreGraphicsState];
}

Thanks a lot,

   Andreas



_______________________________________________
Discuss-gnustep mailing list
Discuss-gnustep@...
http://lists.gnu.org/mailman/listinfo/discuss-gnustep