• 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
Re: number of rows for an attributed string
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: number of rows for an attributed string


  • Subject: Re: number of rows for an attributed string
  • From: Jerry Krinock <email@hidden>
  • Date: Wed, 21 Nov 2007 10:31:45 -0800

On 2007 Nov, 20, at 19:13, Mitchell Livingston wrote:

I want to display an attributed string in a table row, simulating 10.5's Console where the row expands to allow multiple text rows in a single table cell. I am having trouble determining the number of rows the attributed string will take, however.

As you can see from the dearth of answers, this is not an easy question.

I looked into NSString's boundingRectWithSize:options:attributes:, but that didn't seem to work.

Looks interesting, but I've never tried that.

Do a full-text search in Xcode Documentation for "Calculating Text Height", and read the article with that title which is the first hit in my Xcode 2.5. Below, I have pasted in functions that I use, based on that article, to calculate height and width for NSStrings with a given NSFont. I suppose it could be modified for attributed strings.

You see from the "fudge factors" I use that it doesn't come out quite right. When I couldn't get this resolved at WWDC last summer I submitted a bug report 5291163 with a sample project, but no one has touched it.

I'm hoping the reason it hasn't been touched is that Apple has long term plans to implement some string-measuring methods. It seems to me like a big missing piece in Cocoa that the solution to such a common problem should be so painful.

// Fudge numbers needed, from reverse-engineering experience
// Test with file /Users/jk/Projects/Bookdog/ StringDrawingFudgeTest.plist


// These fudge factors are used in SSMeasureStringDrawing,
// for fields that are only measured for width OR height
#define LAYOUT_MANAGER_WIDTH_FUDGE_FACTOR 1.15
#define LAYOUT_MANAGER_HEIGHT_FUDGE_FACTOR 1.15
// A possible reason why the height fudge factor is needed is
// because, when I read Apple's document "Font Handling"
// document, it seems that the line height would be:
//   ascender - descender + leading
//   (Note: descender is negative)
// But when I send -leading to one of my NSSystemFontOfSize...,
// I get 0.0

// These fudge numbers are used in SSResizeTextFieldForSuperview,
// for fields that are resized in BOTH width AND height
#define SIZE_TO_FIT_WIDTH_FUDGE_FACTOR 1.0
#define SIZE_TO_FIT_HEIGHT_FUDGE_FACTOR 1.10

float SSMeasureStringDrawing(NSString *myString, NSFont *desiredFont, float desiredWidth, float desiredHeight) {
// One of desiredHeight or desiredWidth must be set to 0.
// The size of the one set to 0 will be returned.
// Operation of this function is explained in:
// ADC Home > Reference Library > Documentation > Cocoa > Text & Fonts > Text Layout Programming Guide > Calculating Text Height


float output = 0.0 ;
// The Layout Manager likes to give a height of nominally one line for an empty string
// That's pretty stupid, so if there are no characters we leave output at 0.0 and bail out
if ([myString length] > 0) {
BOOL wantWidth ;


        if (desiredWidth == 0)
        {
            desiredWidth = 1e7 ;
            wantWidth = YES ;
        }
        else if (desiredHeight == 0)
        {
            desiredHeight = 1e7 ;
            wantWidth = NO ;
        }
        else
            NSLog(@"Internal error calling HeightForStringDrawing") ;

NSTextStorage *textStorage = [[[NSTextStorage alloc] initWithString:myString] autorelease];
NSTextContainer *textContainer = [[[NSTextContainer alloc] initWithContainerSize:NSMakeSize(desiredWidth / LAYOUT_MANAGER_WIDTH_FUDGE_FACTOR, desiredHeight / LAYOUT_MANAGER_HEIGHT_FUDGE_FACTOR)] autorelease];
NSLayoutManager *layoutManager = [[[NSLayoutManager alloc] init] autorelease];


[textStorage addAttribute:NSFontAttributeName value:desiredFont range:NSMakeRange(0, [textStorage length])];
[textContainer setLineFragmentPadding:0.0]; // padding usually is not appropriate for string drawing


        [layoutManager addTextContainer:textContainer];
        [textStorage addLayoutManager:layoutManager];

(void)[layoutManager glyphRangeForTextContainer:textContainer]; // force layout

if (wantWidth) {
output = [layoutManager usedRectForTextContainer:textContainer].size.width * LAYOUT_MANAGER_WIDTH_FUDGE_FACTOR ;
}
else {
output = [layoutManager usedRectForTextContainer:textContainer].size.height * LAYOUT_MANAGER_HEIGHT_FUDGE_FACTOR ;
}
}


    return output ;
}

float SSMeasureStringWidth(NSString* string, NSFont* font, float desiredHeight) {
if (desiredHeight == 0.0) {
desiredHeight = 1.0e8 ;
}
return SSMeasureStringDrawing(string, font, 0.0, desiredHeight) ;
}


float SSMeasureStringHeight(NSString* string, NSFont* font, float desiredWidth) {
if (desiredWidth == 0.0) {
desiredWidth = 1.0e8 ;
}
return SSMeasureStringDrawing(string, font, desiredWidth, 0.0) ;
}




_______________________________________________

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


References: 
 >number of rows for an attributed string (From: Mitchell Livingston <email@hidden>)

  • Prev by Date: Re: Concurrent NSOperation
  • Next by Date: Re: number of rows for an attributed string
  • Previous by thread: number of rows for an attributed string
  • Next by thread: Re: number of rows for an attributed string
  • Index(es):
    • Date
    • Thread