How to draw text in a non-flipped view ?
25/02/04 09:52
To draw text in a NSView view of my own, the view has to return YES from its isFlipped method. But if I really need to draw text in a non-flipped view, how ?
(If you don't see what we refer to, open the Sketch example in your Developer folder and comment out the isFlipped method of the SKGraphicView...).
(If you don't see what we refer to, open the Sketch example in your Developer folder and comment out the isFlipped method of the SKGraphicView...).
This is a classical problem in any sketch board-like view, if you don't want a flipped view, the text will be drawn mirrored if you use the NSLayoutManager 's method drawGlyphsForGlyphRange without any precaution.
Here is a solution:
1. add a method to your NSView subclass to turn on/off the flipped state on the fly:
- (void)setFlipped:(BOOL)inFlipped
{
fFlipped = inFlipped ;
}
- (BOOL)isFlipped
{
return fFlipped;
}
fFlipped being of course an instance BOOL of your NSView sub-class.
2. in your drawing code, apply the following steps:
a. call your new setFlipped method with argument YES;
b. create a new NSAffineTransform *transform with the following matrix:
1 0 0
0 -1 0
0 H 1
where H is the height of the bounding box of the text to be drawn;
c. save the current graphic state with [[NSGraphicsContext currentContext] saveGraphicsState];
d. apply the newly created affine transform with [transform concat];
e. draw your text mostly as usual: (example)
[myTextContainer setContainerSize:myBounds.size];
[myContents addLayoutManager:myLayoutManager];
[myLayoutManager drawBackgroundForGlyphRange:glyphRange atPoint:NSMakePoint(myBounds.origin.x, -myBounds.origin.y)];
[myLayoutManager drawGlyphsForGlyphRange:glyphRange atPoint:NSMakePoint(myBounds.origin.x, -myBounds.origin.y)];
BUT note the important reversing of the y value of the origin for the atPoint parameter !
f. restore the graphic state [[NSGraphicsContext currentContext] restoreGraphicsState];
g. restore the non flipped state of your view: [myView setFlipped:NO].
Here is a solution:
1. add a method to your NSView subclass to turn on/off the flipped state on the fly:
- (void)setFlipped:(BOOL)inFlipped
{
fFlipped = inFlipped ;
}
- (BOOL)isFlipped
{
return fFlipped;
}
fFlipped being of course an instance BOOL of your NSView sub-class.
2. in your drawing code, apply the following steps:
a. call your new setFlipped method with argument YES;
b. create a new NSAffineTransform *transform with the following matrix:
1 0 0
0 -1 0
0 H 1
where H is the height of the bounding box of the text to be drawn;
c. save the current graphic state with [[NSGraphicsContext currentContext] saveGraphicsState];
d. apply the newly created affine transform with [transform concat];
e. draw your text mostly as usual: (example)
[myTextContainer setContainerSize:myBounds.size];
[myContents addLayoutManager:myLayoutManager];
[myLayoutManager drawBackgroundForGlyphRange:glyphRange atPoint:NSMakePoint(myBounds.origin.x, -myBounds.origin.y)];
[myLayoutManager drawGlyphsForGlyphRange:glyphRange atPoint:NSMakePoint(myBounds.origin.x, -myBounds.origin.y)];
BUT note the important reversing of the y value of the origin for the atPoint parameter !
f. restore the graphic state [[NSGraphicsContext currentContext] restoreGraphicsState];
g. restore the non flipped state of your view: [myView setFlipped:NO].