• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Widow / Orphan protection in text layout
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Widow / Orphan protection in text layout


  • Subject: Widow / Orphan protection in text layout
  • From: Gideon King <email@hidden>
  • Date: Tue, 21 May 2013 00:26:29 +1000

Hi, I have inherited some code which has a subclass of NSATSTypesetter in it, and in the -willSetLineFragmentRect:forGlyphRange:usedRect:baselineOffset: method it works out whether it needs to put a page break in, and directly sets the currentTextContainer, currentTextContainerIndex, and currentTextContainerSize instance variables.

This is completely undocumented and presumably a very bad way to handle the pagination, so I want to fix it.

The problem is that I am not clear whether the typesetter is the place to do the pagination or whether it should be in the layout manager, and if so exactly how to handle the processing. Any advice on how best to handle the pagination would be most welcome.

Here's what got handed to me (in a subclass of NSATSTypesetter):

- (void)willSetLineFragmentRect:(NSRect *)lineRect forGlyphRange:(NSRange)glyphRange usedRect:(NSRect *)usedRect baselineOffset:(CGFloat *)baselineOffset {
    NSRange characterRange = [self characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL];
    NSString *string = [[[[self layoutManager] textStorage] string] substringWithRange:characterRange];
    NSSize size = [[self currentTextContainer] containerSize];
    // This is more like the forecast maximum y which is the line height plus the origin y.
    CGFloat forecastedHeight = ((*lineRect).size.height*2.0) + (*lineRect).origin.y;

    // If the last character of the line fragment is not a paragraph marker, and the text is on the last line, then put the text on the next page. This is so the
    // text is not split so that the character name is on one page and the dialog is on another etc
    if ([string characterAtIndex:characterRange.length-1] != NSParagraphSeparatorCharacter) {
        if (forecastedHeight > size.height) {
            NSFont *font = [[[self layoutManager] textStorage] attribute:NSFontAttributeName atIndex:[self paragraphCharacterRange].location effectiveRange:NULL];

            NSDictionary *attrs = [[[self layoutManager] textStorage] attributesAtIndex:[self paragraphCharacterRange].location effectiveRange:NULL];
            NSString *temp = [[[[self layoutManager] textStorage] string] substringWithRange:[self paragraphCharacterRange]];
            NSSize stringSize = [temp sizeWithAttributes:attrs];

            lineRect->origin.y = 0.0;
            lineRect->size.height = stringSize.height;
            usedRect->origin.y = 0.0;
            usedRect->size.height = stringSize.height;

            *baselineOffset = [[self layoutManager] defaultBaselineOffsetForFont:font];

            if (currentTextContainer == [[self textContainers] lastObject]) {
                currentTextContainerIndex = NSNotFound;
                currentTextContainer = nil;
                currentTextContainerSize = NSZeroSize;
            } else {
                unsigned indexOfOldTC = [[self textContainers] indexOfObjectIdenticalTo:currentTextContainer];
                currentTextContainerIndex = indexOfOldTC+1;
                currentTextContainer = [[self textContainers] objectAtIndex:currentTextContainerIndex];
                currentTextContainerSize = [currentTextContainer containerSize];
            }
        }
    }

    // If the line is a character name, then we will always put it down a line below whatever section was above it.
    NSString *section = [self.screenwriterLayoutManager.screenwriterView sectionFromRange:[self paragraphCharacterRange]];
    if (section == SWCharacterSectionIdentifier) {
        if (forecastedHeight > size.height) {
            if (lineRect->origin.y > 0.001) {
                NSFont *font = [[[self layoutManager] textStorage] attribute:NSFontAttributeName atIndex:[self paragraphCharacterRange].location effectiveRange:NULL];

				NSDictionary *attrs = [[[self layoutManager] textStorage] attributesAtIndex:[self paragraphCharacterRange].location effectiveRange:NULL];
				NSString *temp = [[[[self layoutManager] textStorage] string] substringWithRange:[self paragraphCharacterRange]];
				NSSize stringSize = [temp sizeWithAttributes:attrs];

                lineRect->origin.y = 0.0;
                lineRect->size.height = stringSize.height;
                usedRect->origin.y = 0.0;
                usedRect->size.height = stringSize.height;

                *baselineOffset = [[self layoutManager] defaultBaselineOffsetForFont:font];

                if (currentTextContainer == [[self textContainers] lastObject]) {
                    currentTextContainerIndex = NSNotFound;
                    currentTextContainer = nil;
                    currentTextContainerSize = NSZeroSize;
                } else {
                    unsigned indexOfOldTC = [[self textContainers] indexOfObjectIdenticalTo:currentTextContainer];
                    currentTextContainerIndex = indexOfOldTC+1;
                    currentTextContainer = [[self textContainers] objectAtIndex:currentTextContainerIndex];
                    currentTextContainerSize = [currentTextContainer containerSize];
                }
            }
        }
    }
}



PS Sorry about the number of questions at once - just seem to have run into multiple issues at once tonight.


Regards

Gideon



_______________________________________________

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

  • Follow-Ups:
    • Re: Widow / Orphan protection in text layout
      • From: Kyle Sluder <email@hidden>
  • Prev by Date: Re: NSDocument initWithContentsOfURL vs readFromURL
  • Next by Date: Re: Sandboxing and Apple System Log (asl) searches
  • Previous by thread: Re: Sandboxing and Apple System Log (asl) searches
  • Next by thread: Re: Widow / Orphan protection in text layout
  • Index(es):
    • Date
    • Thread