On Aug 15, 2011, at 2:22 PM, Martin Wierschin wrote:

>>> I don't know the particulars of your situation or what might be triggering 
>>> the cutoff display (are they just descenders?), but have you tried reducing 
>>> the height of the NSTextContainer while keeping your NSTextView height the 
>>> same? (You'll have to disable automatic resizing).
> 
>> 
>> I did
> 
> Can you post your new code? Your first post shows that you are modifying the 
> text view. It might help to see the rest of your code as well.

When the controlling class is created, it makes a new NSTextStorage and gives 
it a brand new NSLayoutManager. The NSLayoutManager's delegate is set to the 
controller, which implements this delegate method:

- (void)layoutManager:(NSLayoutManager *)layoutManager 
didCompleteLayoutForTextContainer:(NSTextContainer *)textContainer 
atEnd:(BOOL)atEnd
{
        NSArray *containers = [layoutManager textContainers];
        
        if (!atEnd || textContainer == nil) 
        {
                // Either layout is not finished or it is but there are glyphs 
laid nowhere.
                NSTextContainer *lastContainer = [containers lastObject];
                
                if (textContainer == lastContainer || textContainer == nil) 
                {
                        // Add a new page only if the newly full container is 
the last container or the nowhere container.
                        [self addPage];
                }
        } 
        else 
        {
                // Layout is done and it all fit.  See if we can axe some pages.
                NSUInteger lastUsedContainerIndex = [containers 
indexOfObjectIdenticalTo: textContainer];
                NSUInteger numContainers = [containers count];
                
                while (++lastUsedContainerIndex < numContainers) 
                        [self removePage];
                [self setNumberOfPages:[containers count]];
        }
}

The -addPage method creates a new NSTextContainer object and new NSTextView 
object with the container, adds the text container to the layout manager, and 
adds the text view as a subview to the master view. At that point, their frame 
sizes are synchronized, and the text container is set to track the text view's 
width but not its height. The sizes are equal to the size of a piece of paper 
acquired from the print manager, minus some margins set by the user.

The -removePage method pops the last NSTextContainer and NSTextView from the 
layout manager and master view respectively.

Right after filling in the master text storage in the usual way using 
-beginEditing/-appendAttributedString:/-endEditing, I added the following loop:

NSUInteger i;

for (i = 0UL ; i < self.layoutManager.textContainers.count ; i++)
{
        NSTextContainer *tc = [self.layoutManager.textContainers 
objectAtIndex:i];
        NSRect usedRect;
        NSSize containerSize;
        
        (void)[self.layoutManager glyphRangeForTextContainer:tc];       // 
force layout
        usedRect = [self.layoutManager usedRectForTextContainer:tc];
        containerSize = tc.containerSize;
        
        if (usedRect.size.height > containerSize.height)
        {
                containerSize.height = 
containerSize.height-(usedRect.size.height-containerSize.height);
                tc.containerSize = containerSize;
        }
}

The loop forces the NSLayoutManager to force layout of the text in the 
NSTextStorage, which ends up calling the delegate to add new 
NSTextStorage/NSTextView objects as necessary. (There is always one present no 
matter what.) I can't use fast enumeration here because the text containers 
that contain all pages beyond the first aren't guaranteed to exist until layout 
is first performed.

I added this loop to try and shrink the text container if the used rect is 
greater than the container size, since a larger used rect means text is being 
cut off at the bottom of the container. It works, but instead of sending the 
cut-off line to the next text container as I expected would happen, it places 
the line out of sight so it will never be seen or printed. This happens 
careless of whether I shrink the text storage with container height tracking 
off, or the text view with container height tracking on.

Of course, if there is a better way of using the Cocoa text system to layout 
multiple non-contiguous pages of text with margins, I'd like to hear about it. 
Maybe it'll even solve the problem I'm having.

>> what happens is the layout manager keeps the last line in the text container 
>> where it will not be drawn. It will not move the last line to the next 
>> container unless I resize the text container to be two pixels smaller than 
>> needed, which results in text getting partially cut off later in the 
>> document.
> 
> You're saying that if you decrease the height of text container (N), forcing 
> the last line onward, you see drawing artifacts in container (N + 1)? Can you 
> post a screenshot?

I'll do better: I'll post PDFs. Here is what the text looks like without the 
resizing loop (all containers have exactly the same height): 
<http://dl.dropbox.com/u/13168713/Text%20cut-off.pdf>

The text on page 1 is being cut off at the bottom, and it's not just the 
descneders. Here is the output with the loop in place: 
<http://dl.dropbox.com/u/13168713/Invisible%20lines.pdf>

Notice how the last line on page 1 disappeared entirely.

When I shrink the text container by two pixels, the last line on page 1 gets 
bounced to page 2, but now descenders on both the first and second pages are 
being cut off at the bottom: 
<http://dl.dropbox.com/u/13168713/Descenders%20cut-off.pdf>

> Honestly this sounds unusual- do you have any other modifications at work? 
> Also, at what point are you running this loop where you modify the text 
> container heights? You're not doing it from a layout delegate method are you? 
> NSLayoutManager is quite finicky about that (or at least it used to be).


The code adds containers & views from a layout delegate, and gives them an 
initial size, but doesn't resize them.

Nick Zitzmann
<http://www.chronosnet.com/>

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to