text layout crash
text layout crash
- Subject: text layout crash
- From: Jesse Grosjean <email@hidden>
- Date: Sun, 7 Nov 2004 19:53:26 -0500
When in "Wrap to Page" mode Text Edit will freeze and then crash if
there is a glyph that's too bit to fit on a single page. For example if
you make a large 'I' and then set the font size to 1000 or so you will
see the crash. More frequently this will show up with image attachments
that are too bit, or business card sized page layouts that are only a
few inches high.
The problem seems to be in this NSLayoutManager delegate method in
TextEdit's Document class.
- (void)layoutManager:(NSLayoutManager *)layoutManager
didCompleteLayoutForTextContainer:(NSTextContainer *)textContainer
atEnd:(BOOL)layoutFinishedFlag {
if ([self hasMultiplePages]) {
NSArray *containers = [layoutManager textContainers];
if (!layoutFinishedFlag || (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.
...
}
}
}
The problem being that when no text can be fit into a text container
textContainer == lastContainer and layotFinishedFlag == NO. This means
that TextEdit will just add a new page of the same size and so the
problem will happen again. It will freeze in this loop and eventually
crash after adding many many pages trying to get enough space.
So what's the best fix? Right now I'm trying to detect when this
happens and then I resize the current textContainer to fit the
problematic glyph. This seems to be working mostly, though I'm still
having trouble with some types of text attachments such as PDF files.
My current code is included below. I'd love to know if anyone's come up
with a solution to this.
Thanks,
Jesse
- (void)layoutManager:(NSLayoutManager *)layoutManager
didCompleteLayoutForTextContainer:(NSTextContainer *)textContainer
atEnd:(BOOL)layoutFinishedFlag {
NSArray *containers = [layoutManager textContainers];
if (!layoutFinishedFlag || (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)) {
NSRange glyphRange = [layoutManager
glyphRangeForTextContainer:textContainer];
if (glyphRange.length == 0) {
// Adjust text container size if textContainer doesn't contain any
glyphs.
unsigned int characterIndex = [layoutManager
characterIndexForGlyphAtIndex:glyphRange.location];
NSAttributedString *attributedString = [[layoutManager textStorage]
attributedSubstringFromRange:NSMakeRange(characterIndex, 1)];
NSSize stringSize = [attributedString size];
NSSize containerSize = [textContainer containerSize];
if (containerSize.width < stringSize.width) containerSize.width =
stringSize.width;
if (containerSize.height < stringSize.height) containerSize.height =
stringSize.height;
[textContainer setContainerSize:containerSize];
} else {
// 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.
unsigned lastUsedContainerIndex = [containers
indexOfObjectIdenticalTo:textContainer];
unsigned numContainers = [containers count];
while (++lastUsedContainerIndex < numContainers) {
[self removePage];
}
}
}
Jesse
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden