Skip navigation.
 
mlRe: NSBezierPath geometry question...
FROM : Serge Meynard
DATE : Mon Apr 11 00:37:25 2005

On Apr 10, 2005, at 17:40, Keith Blount wrote:
> Hello,
>
> I am trying to use NSBezierPath to create a shape that
> highlights text in a text view. Basically, I want to
> create a shape that has rounded corners (like the
> traditional Apple rounded rectangles you get in Mail
> etc), but this may highlight text that spills over
> several lines - so the shape is irregular.
>
> This shape is actually defined by several rectangles
> that are got using:
>
> NSRectArray rectArray = [layoutManager
> rectArrayForCharacterRange:charRange
> withinSelectedCharacterRange:NSMakeRange(NSNotFound,0)
> inTextContainer:textContainer rectCount:&rectCount];
>
> So what I actually need to do is take the rectangles
> returned by this method, create one compound shape
> from them, and then round the corners of this shape
> into one NSBezierPath.
>
> I have tried several approaches with differing degrees
> of succes, such as getting all of the right points
> then all of the left points and using
> appendBezierPathWithArcFromPoint..., for instance, but
> everything I have tried has had some odd effects.
>
> Does anybody know how to take several rects and turn
> them into one shape with rounded corners?
>
> Many thanks for any advice,
> Keith


Well, the first issue I can see here is whether or not the rectangles
all touch or not. If there are gaps between them, then you'll have to
adjust the rects first to eliminate those gaps.

Since the rectangles represent ranges of text, we can assume they are
all vertically stacked and non-overlapping, which simplifies things.
Assuming also that you have them ordered from top to bottom, you could
start at the top left corner of the top rectangle and go down:
rect1.topleft, rect1.bottomLeft, rect2.topLeft, rect2.bottomLeft,
rect3.topLeft, etc. When you get to the bottom rect, move over to the
right side and go back up.

As you go, generate segments in your bezier that match each pair of
edges. For example, the first segment would correspond to the two edges
formed by the three points (rect1.topLeft, rect1.bottomLeft,
rect2.topLeft). For a given set of three points, the rounded corner can
be created using curveToPoint:controlPoint1:controlPoint2: where both
control points are the middle point of the set (the corner). The
endpoints of the curveTo call you'll have to calculate depending on the
amount of curvature you want; interpolate them somewhere between
point1/point2 and point2/point3 respectively, with a ratio anywhere
from 0.0 to 0.5. If your endpoints are not at 0.5, you'll have to
create straight line segments between the end of one curve and the
start of the next one.

I hope all this isn't too confused! :)

Serge

Related mailsAuthorDate
mlNSBezierPath geometry question... Keith Blount Apr 10, 23:40
mlRe: NSBezierPath geometry question... Serge Meynard Apr 11, 00:37
mlRe: NSBezierPath geometry question... Robert Clair Apr 11, 13:01
mlRe: NSBezierPath geometry question... Keith Blount Apr 11, 13:17
mlRe: NSBezierPath geometry question... Serge Meynard Apr 11, 16:02
mlRe: NSBezierPath geometry question... Nicko van Someren Apr 11, 17:48
mlRe: NSBezierPath geometry question... Serge Meynard Apr 11, 18:41
mlRe: NSBezierPath geometry question... David Phillip Oste… Apr 11, 18:46
mlRe: NSBezierPath geometry question... Nicko van Someren Apr 11, 19:48
mlRe: NSBezierPath geometry question... Heinrich Giesen Apr 11, 20:49
mlRe: NSBezierPath geometry question... Robert Clair Apr 11, 21:02
mlRe: NSBezierPath geometry question... Keith Blount Apr 11, 21:19
mlRe: NSBezierPath geometry question... Scott Thompson Apr 11, 23:25
mlRe: NSBezierPath geometry question... Robert Clair Apr 11, 23:54
mlRe: NSBezierPath geometry question... Keith Blount Apr 12, 00:24
mlRe: NSBezierPath geometry question... Nicko van Someren Apr 12, 10:04
mlRe: NSBezierPath geometry question... Keith Blount Apr 12, 18:08
mlRe: NSBezierPath geometry question... Jonathon Mah Apr 13, 17:11