Problem getting subclass of NSTextContainer working properly
Problem getting subclass of NSTextContainer working properly
- Subject: Problem getting subclass of NSTextContainer working properly
- From: Graham Cox <email@hidden>
- Date: Sat, 10 May 2008 16:19:07 +1000
I'm working on implementing text flow into an irregular shape using a
custom subclass of NSTextContainer. I think my problem stems from the
lack of detail in the documentation, since I've implemented it based
on what is there but it doesn't work correctly.
It's OK for a convex shape where there is no splitting of lines, but
if there's any reason to split a line, it goes a bit wrong, as seen
here:
http://apptree.net/images/textflow1.jpg
I've verified that my algorithm for finding the intersections of the
fragment rectangle and the shape edges is correct, you can see that
working from this image:
http://apptree.net/images/textflow2.jpg
So what remains is the logic in my text container for returning the
split-up lines. Also, at this stage I'm not trying anything fancy with
the font - it's all the same font, same line height. (I've seen a
posting about having problem splitting a line when the font height
varies across the split, but that's not the case here).
According to the docs:
"In the second example [split line], the proposed rectangle crosses a
hole, so the text container must return a shorter rectangle (the white
rectangle on the left) along with a remainder (the white rectangle on
the right). The next rectangle proposed by the typesetter will then be
this remainder rectangle which will be returned unchanged by the text
container."
What this suggests to me is that the text container needs to keep
track of the previous non-zero remainder rect that it set, and if the
proposedRect is the same, then it should return it unchanged,
resetting the remainderRect. Here's the code to do just that:
- (NSRect) lineFragmentRectForProposedRect:(NSRect) proposedRect
sweepDirection:(NSLineSweepDirection) sweepDirection
movementDirection:(NSLineMovementDirection) movementDirection
remainingRect:(NSRectPointer) remainingRect
{
#pragma unused(sweepDirection)
#pragma unused(movementDirection)
if( NSEqualRects( proposedRect, mLastRemainderRect ))
{
// proposed rect matches last remainder rect issued, so return it
unchanged as per docs
mLastRemainderRect = NSZeroRect;
if( remainingRect != nil )
*remainingRect = NSZeroRect;
return proposedRect;
}
NSRect remRect = NSZeroRect;
NSRect result = [mPath lineFragmentRectForProposedRect:proposedRect
remainingRect:&remRect];
if( remainingRect != nil )
{
*remainingRect = remRect;
mLastRemainderRect = remRect; //track the remainder rect for next call
}
return result;
}
Here the hard work of modifying the line fragment rects is really done
by the NSBezierPath category method
lineFragmentRectForProposedRect:remainingRect: but that's been tested
separately and definitely returns the right rects (as seen in image 2
above). So the fault I'm pretty sure lies in the (possibly naive)
logic here and/or the differences between what the docs say and what
NSLayoutManager really does. Either that or I've done something silly
in my interpretation of the docs and/or the code logic above - but I
can't see what it is. If anyone's familiar with solving this problem,
I'd love to hear any insight you might have!
tia,
Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden