Commit 22a7248e authored by rjw's avatar rjw

Implementation of replacement code for NSLayoutManager. Huge

performance gains.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@768 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b623d8c8
2002-03-17 Richard Williamson <rjw@apple.com>
Implementation of replacement code for NSLayoutManager. Huge
performance gains.
* src/kdelibs/khtml/rendering/render_text.cpp: (RenderText::calcMinMaxWidth),
(RenderText::width):
* src/kwq/KWQFontMetrics.mm: (ROUND_TO_INT), (__IFInitATSGlyphVector),
(__IFResetATSGlyphVector), (__IFFillStyleWithAttributes), (-[KWQLayoutInfo
drawString:atPoint:withFont:color:]), (+[KWQLayoutInfo
drawString:atPoint:withFont:color:]), (-[KWQLayoutInfo
drawUnderlineForString:atPoint:withFont:color:]), (+[KWQLayoutInfo
drawUnderlineForString:atPoint:withFont:color:]), (-[KWQLayoutInfo
initWithFont:]), (-[KWQLayoutInfo _initializeCaches]), (_rectForString),
(-[KWQLayoutInfo rectForString:]), (-[KWQLayoutInfo attributes]),
(-[KWQLayoutInfo lineHeight]), (-[KWQLayoutInfo font]), (-[KWQLayoutInfo
dealloc]), (QFontMetrics::_width):
* src/kwq/KWQMetrics.h:
* src/kwq/Makefile.am:
* src/kwq/qt/qfontmetrics.h:
2002-03-16 Richard Williamson <rjw@apple.com>
Fixed error handling. Removed ObjC code for url handle client from KHTMLPart.
......
2002-03-17 Richard Williamson <rjw@apple.com>
Implementation of replacement code for NSLayoutManager. Huge
performance gains.
* src/kdelibs/khtml/rendering/render_text.cpp: (RenderText::calcMinMaxWidth),
(RenderText::width):
* src/kwq/KWQFontMetrics.mm: (ROUND_TO_INT), (__IFInitATSGlyphVector),
(__IFResetATSGlyphVector), (__IFFillStyleWithAttributes), (-[KWQLayoutInfo
drawString:atPoint:withFont:color:]), (+[KWQLayoutInfo
drawString:atPoint:withFont:color:]), (-[KWQLayoutInfo
drawUnderlineForString:atPoint:withFont:color:]), (+[KWQLayoutInfo
drawUnderlineForString:atPoint:withFont:color:]), (-[KWQLayoutInfo
initWithFont:]), (-[KWQLayoutInfo _initializeCaches]), (_rectForString),
(-[KWQLayoutInfo rectForString:]), (-[KWQLayoutInfo attributes]),
(-[KWQLayoutInfo lineHeight]), (-[KWQLayoutInfo font]), (-[KWQLayoutInfo
dealloc]), (QFontMetrics::_width):
* src/kwq/KWQMetrics.h:
* src/kwq/Makefile.am:
* src/kwq/qt/qfontmetrics.h:
2002-03-16 Richard Williamson <rjw@apple.com>
Fixed error handling. Removed ObjC code for url handle client from KHTMLPart.
......
2002-03-17 Richard Williamson <rjw@apple.com>
Implementation of replacement code for NSLayoutManager. Huge
performance gains.
* src/kdelibs/khtml/rendering/render_text.cpp: (RenderText::calcMinMaxWidth),
(RenderText::width):
* src/kwq/KWQFontMetrics.mm: (ROUND_TO_INT), (__IFInitATSGlyphVector),
(__IFResetATSGlyphVector), (__IFFillStyleWithAttributes), (-[KWQLayoutInfo
drawString:atPoint:withFont:color:]), (+[KWQLayoutInfo
drawString:atPoint:withFont:color:]), (-[KWQLayoutInfo
drawUnderlineForString:atPoint:withFont:color:]), (+[KWQLayoutInfo
drawUnderlineForString:atPoint:withFont:color:]), (-[KWQLayoutInfo
initWithFont:]), (-[KWQLayoutInfo _initializeCaches]), (_rectForString),
(-[KWQLayoutInfo rectForString:]), (-[KWQLayoutInfo attributes]),
(-[KWQLayoutInfo lineHeight]), (-[KWQLayoutInfo font]), (-[KWQLayoutInfo
dealloc]), (QFontMetrics::_width):
* src/kwq/KWQMetrics.h:
* src/kwq/Makefile.am:
* src/kwq/qt/qfontmetrics.h:
2002-03-16 Richard Williamson <rjw@apple.com>
Fixed error handling. Removed ObjC code for url handle client from KHTMLPart.
......
......@@ -45,9 +45,6 @@
#ifdef APPLE_CHANGES
#define OPTIMIZE_STRING_USAGE
#ifdef OPTIMIZE_STRING_USAGE
static CFMutableStringRef reuseableString = 0;
#endif
#endif
......@@ -695,7 +692,7 @@ void RenderText::calcMinMaxWidth()
if (wordlen)
{
#if (defined(APPLE_CHANGES) && defined(OPTIMIZE_STRING_USAGE))
int w = _fm._width(QString::gstring_toCFString(&reuseableString, (UniChar *)(str->s+i), wordlen));
int w = _fm._width((const UniChar *)(str->s+i), wordlen);
#else
int w = _fm.width(QConstString(str->s+i, wordlen).string());
#endif
......@@ -718,7 +715,7 @@ void RenderText::calcMinMaxWidth()
if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
currMinWidth = 0;
#if (defined(APPLE_CHANGES) && defined(OPTIMIZE_STRING_USAGE))
currMaxWidth += _fm._width(QString::gstring_toCFString(&reuseableString, (UniChar *)(str->s+i+wordlen), 1));
currMaxWidth += _fm._width((const UniChar *)(str->s+i+wordlen), 1);
#else
currMaxWidth += _fm.width( *(str->s+i+wordlen) );
#endif
......@@ -900,7 +897,7 @@ unsigned int RenderText::width(unsigned int from, unsigned int len, QFontMetrics
w = _fm->width( *(str->s+from) );
else
#if (defined(APPLE_CHANGES) && defined(OPTIMIZE_STRING_USAGE))
w = _fm->_width(QString::gstring_toCFString(&reuseableString, (UniChar *)(str->s+from), len));
w = _fm->_width((const UniChar *)(str->s+from), len);
#else
w = _fm->width(QConstString(str->s+from, len).string());
#endif
......
......@@ -71,6 +71,7 @@ public:
int width(const QString &, int len=-1) const;
#if (defined(__APPLE__))
int _width (CFStringRef string) const;
int _width (const UniChar *uchars, int len) const;
#endif
int descent() const;
......
......@@ -28,13 +28,26 @@
#include <qfontmetrics.h>
#import <Cocoa/Cocoa.h>
#define DIRECT_TO_CG
#import <KWQMetrics.h>
#import <KWQTextStorage.h>
#import <KWQTextContainer.h>
#define FLOOR_TO_INT(x) (int)(floor(x))
#define ROUND_TO_INT(x) (int)(((x) > (floor(x) + .5)) ? ceil(x) : floor(x))
//#define ROUND_TO_INT(f) ((int)(rint(f)))
//#define ROUND_TO_INT(x) (int)(((x) > (floor(x) + .5)) ? ceil(x) : floor(x))
#define ROUND_TO_INT(x) (int)(x+.5)
#ifdef FOOOOFOOO
static inline int ROUND_TO_INT (float x)
{
int floored = (int)(x);
if (((float)x) > ((float)(floored) + .5))
return (int)ceil(x);
return floored;
}
#endif
@implementation KWQSmallLayoutFragment
- (NSRange)glyphRange
......@@ -142,41 +155,180 @@ static NSMutableDictionary *metricsCache = nil;
*/
@implementation KWQLayoutInfo
+ (void)drawString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)font color: (NSColor *)color
#ifdef DIRECT_TO_CG
static void __IFInitATSGlyphVector(ATSGlyphVector *glyphVector, UInt32 numGlyphs) {
if (glyphVector->numAllocatedGlyphs == 0) {
ATSInitializeGlyphVector(numGlyphs, 0, glyphVector);
//#warning Aki: 6/28/00 Need to reconsider these when we do bidi
ATSFree(glyphVector->levelIndexes);
glyphVector->levelIndexes = NULL;
} else if (glyphVector->numAllocatedGlyphs < numGlyphs) {
ATSGrowGlyphVector(numGlyphs - glyphVector->numAllocatedGlyphs, glyphVector);
}
}
static void __IFResetATSGlyphVector(ATSGlyphVector *glyphVector) {
ATSGlyphVector tmpVector = *glyphVector;
// Prevents glyph array & style settings from deallocated
glyphVector->firstRecord = NULL;
glyphVector->styleSettings = NULL;
glyphVector->levelIndexes = NULL;
ATSClearGlyphVector(glyphVector);
glyphVector->numAllocatedGlyphs = tmpVector.numAllocatedGlyphs;
glyphVector->recordSize = tmpVector.recordSize;
glyphVector->firstRecord = tmpVector.firstRecord;
glyphVector->styleSettings = tmpVector.styleSettings;
glyphVector->levelIndexes = tmpVector.levelIndexes;
}
@class NSCGSFont;
static void __IFFillStyleWithAttributes(ATSUStyle style, NSFont *theFont) {
if (theFont) {
ATSUFontID fontId = (ATSUFontID)[theFont _atsFontID];
ATSUAttributeTag tag = kATSUFontTag;
ByteCount size = sizeof(ATSUFontID);
ATSUFontID *valueArray[1] = {&fontId};
if (fontId) {
if (ATSUSetAttributes(style, 1, &tag, &size, (const ATSUAttributeValuePtr)valueArray) != noErr)
[NSException raise:NSInternalInconsistencyException format:@"Failed to set font (%@) ATSUStyle 0x%X", theFont, style];
#if 1
//#warning Aki 7/20/2000 This code should be disabled once the brain dead bug 2499383 is fixed
{
ATSUFontFeatureType types[8] = {kDiacriticsType, kTypographicExtrasType, kFractionsType, kSmartSwashType, kSmartSwashType, kSmartSwashType, kSmartSwashType, kSmartSwashType};
ATSUFontFeatureSelector selectors[8] = {kDecomposeDiacriticsSelector, kSmartQuotesOffSelector, kNoFractionsSelector, kWordInitialSwashesOffSelector, kWordFinalSwashesOffSelector, kLineInitialSwashesOffSelector, kLineFinalSwashesOffSelector, kNonFinalSwashesOffSelector};
ATSUSetFontFeatures(style, 8, types, selectors);
}
#endif
}
}
}
#endif
- (void)drawString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)aFont color: (NSColor *)color
{
KWQLayoutInfo *layoutInfo = [KWQLayoutInfo getMetricsForFont: font];
NSLayoutManager *manager = [layoutInfo layoutManager];
KWQTextStorage *storage = [layoutInfo textStorage];
#ifdef DIRECT_TO_CG
UniChar localBuffer[LOCAL_GLYPH_BUFFER_SIZE];
const UniChar *_internalBuffer = CFStringGetCharactersPtr ((CFStringRef)string);
const UniChar *internalBuffer;
if (manager != nil){
id <KWQLayoutFragment> frag = [storage getFragmentForString: (NSString *)string];
if (!_internalBuffer){
CFStringGetCharacters((CFStringRef)string, CFRangeMake(0, CFStringGetLength((CFStringRef)string)), &localBuffer[0]);
internalBuffer = &localBuffer[0];
}
else
internalBuffer = _internalBuffer;
CGContextRef cgContext;
[layoutInfo setColor: color];
[layoutInfo setFont: font];
[[layoutInfo textStorage] setAttributes: [layoutInfo attributes]];
[[layoutInfo textStorage] setString: string];
[manager drawGlyphsForGlyphRange:[frag glyphRange] atPoint:p];
__IFInitATSGlyphVector(&_glyphVector, [string length]);
(void)ATSUConvertCharToGlyphs(_styleGroup, internalBuffer, 0, [string length], 0, (ATSGlyphVector *)&_glyphVector);
[color set];
[aFont set];
if ([aFont glyphPacking] != NSNativeShortGlyphPacking &&
[aFont glyphPacking] != NSTwoByteGlyphPacking)
[NSException raise:NSInternalInconsistencyException format:@"%@: Don't know how to deal with font %@", self, [aFont displayName]];
{
int i, numGlyphs = _glyphVector.numGlyphs;
char localGlyphBuf[LOCAL_GLYPH_BUFFER_SIZE];
char *usedGlyphBuf, *glyphBufPtr, *glyphBuf = 0;
ATSLayoutRecord *glyphRecords = _glyphVector.firstRecord;
if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE/2)
usedGlyphBuf = glyphBufPtr = glyphBuf = (char *)malloc (numGlyphs * 2);
else
usedGlyphBuf = glyphBufPtr = &localGlyphBuf[0];
for (i = 0; i < numGlyphs; i++){
*glyphBufPtr++ = (char)((glyphRecords->glyphID >> 8) & 0x00FF);
*glyphBufPtr++ = (char)(glyphRecords->glyphID & 0x00FF);
glyphRecords++;
}
cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGContextSetCharacterSpacing(cgContext, 0.0);
//CGContextShowGlyphsAtPoint (cgContext, p.x, p.y + [frag boundingRect].size.height + (int)[font descender] - 1, (const short unsigned int *)usedGlyphBuf, numGlyphs);
CGContextShowGlyphsAtPoint (cgContext, p.x, p.y + lineHeight - 1, (const short unsigned int *)usedGlyphBuf, numGlyphs);
if (glyphBuf)
free (glyphBuf);
}
__IFResetATSGlyphVector(&_glyphVector);
#else
id <KWQLayoutFragment> frag = [storage getFragmentForString: (NSString *)string];
NSLog (@"WARNING: Unable to use CG for drawString:atPoint:withFont:color:\n");
[self setColor: color];
[textStorage setAttributes: [layoutInfo attributes]];
[textStorage setString: string];
[layoutManager drawGlyphsForGlyphRange:[frag glyphRange] atPoint:p];
#endif
}
+ (void)drawUnderlineForString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)font color: (NSColor *)color
+ (void)drawString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)aFont color: (NSColor *)color
{
KWQLayoutInfo *layoutInfo = [KWQLayoutInfo getMetricsForFont: font];
NSLayoutManager *manager = [layoutInfo layoutManager];
KWQTextStorage *storage = [layoutInfo textStorage];
KWQLayoutInfo *layoutInfo = [KWQLayoutInfo getMetricsForFont: aFont];
[layoutInfo drawString: string atPoint: p withFont: aFont color: color];
}
if (manager != nil){
id <KWQLayoutFragment>frag = [storage getFragmentForString: (NSString *)string];
[layoutInfo setColor: color];
[layoutInfo setFont: font];
[[layoutInfo textStorage] setAttributes: [layoutInfo attributes]];
[[layoutInfo textStorage] setString: string];
NSRect lineRect = [manager lineFragmentRectForGlyphAtIndex: 0 effectiveRange: 0];
[manager underlineGlyphRange:[frag glyphRange] underlineType:NSSingleUnderlineStyle lineFragmentRect:lineRect lineFragmentGlyphRange:[frag glyphRange] containerOrigin:p];
- (void)drawUnderlineForString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)aFont color: (NSColor *)color
{
#ifdef DIRECT_TO_CG
NSRect rect = [self rectForString: string];
NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
CGContextRef cgContext;
float lineWidth;
[color set];
BOOL flag = [graphicsContext shouldAntialias];
[graphicsContext setShouldAntialias: NO];
cgContext = (CGContextRef)[graphicsContext graphicsPort];
lineWidth = 0.0;
if ([graphicsContext isDrawingToScreen] && lineWidth == 0.0) {
CGSize size = CGSizeApplyAffineTransform(CGSizeMake(1.0, 1.0), CGAffineTransformInvert(CGContextGetCTM(cgContext)));
lineWidth = size.width;
}
CGContextSetLineWidth(cgContext, lineWidth);
CGContextMoveToPoint(cgContext, p.x, p.y + lineHeight + 0.5);
CGContextAddLineToPoint(cgContext, p.x + rect.size.width, p.y + lineHeight + 0.5);
CGContextStrokePath(cgContext);
[graphicsContext setShouldAntialias: flag];
#else
id <KWQLayoutFragment>frag = [storage getFragmentForString: (NSString *)string];
[self setColor: color];
[textStorage setAttributes: [self attributes]];
[textStorage setString: string];
NSRect lineRect = [self lineFragmentRectForGlyphAtIndex: 0 effectiveRange: 0];
[self underlineGlyphRange:[frag glyphRange] underlineType:NSSingleUnderlineStyle lineFragmentRect:lineRect lineFragmentGlyphRange:[frag glyphRange] containerOrigin:p];
#endif
}
+ (void)drawUnderlineForString: (NSString *)string atPoint: (NSPoint)p withFont: (NSFont *)aFont color: (NSColor *)color
{
KWQLayoutInfo *layoutInfo = [KWQLayoutInfo getMetricsForFont: aFont];
[layoutInfo drawUnderlineForString: string atPoint: p withFont: aFont color: color];
}
#ifdef _DEBUG_LAYOUT_FRAGMENT
+ (void)_dumpLayoutCache: (NSDictionary *)fragCache
{
......@@ -245,9 +397,34 @@ static NSMutableDictionary *metricsCache = nil;
- initWithFont: (NSFont *)aFont
{
OSStatus errCode;
[super init];
attributes = [[NSMutableDictionary dictionaryWithObjectsAndKeys:aFont, NSFontAttributeName, nil] retain];
font = [aFont retain];
lineHeight = ROUND_TO_INT([font ascender]) - ROUND_TO_INT([font descender]) + 1;
#ifdef DIRECT_TO_CG
if ((errCode = ATSUCreateStyle(&_style)) != noErr)
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to alloc ATSUStyle %d", self, errCode];
__IFFillStyleWithAttributes(_style, aFont);
if ((errCode = ATSUGetStyleGroup(_style, &_styleGroup)) != noErr) {
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to create attribute group from ATSUStyle 0x%X %d", self, _style, errCode];
}
if ((errCode = ATSUCreateStyle(&_asciiStyle)) != noErr)
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to alloc ATSUStyle %d", self, errCode];
__IFFillStyleWithAttributes(_asciiStyle, aFont);
if ((errCode = ATSUGetStyleGroup(_asciiStyle, &_asciiStyleGroup)) != noErr) {
[NSException raise:NSInternalInconsistencyException format:@"%@: Failed to create attribute group from ATSUStyle 0x%X %d", self, _style, errCode];
}
#endif
textStorage = [[KWQTextStorage alloc] initWithFontAttribute: attributes];
layoutManager = [[NSLayoutManager alloc] init];
......@@ -269,14 +446,196 @@ static NSMutableDictionary *metricsCache = nil;
return textStorage;
}
#ifdef DIRECT_TO_CG
- (void)_initializeCaches
{
int i, errorResult;
size_t numGlyphsInFont = CGFontGetNumberOfGlyphs([font _backingCGSFont]);
short unsigned int sequentialGlyphs[GLYPH_CACHE_MAX];
if (numGlyphsInFont > GLYPH_CACHE_MAX)
widthCacheSize = GLYPH_CACHE_MAX;
else
widthCacheSize = (int)numGlyphsInFont;
for (i = 0; i < widthCacheSize; i++)
sequentialGlyphs[i] = i;
fprintf (stdout, "number of glyphs in font %s %f = %ld\n", [[font displayName] cString], [font pointSize], CGFontGetNumberOfGlyphs([font _backingCGSFont]));
widthCache = (float *)calloc (1, widthCacheSize * sizeof(float));
errorResult = CGFontGetGlyphScaledAdvances ([font _backingCGSFont], &sequentialGlyphs[0], widthCacheSize, widthCache, [font pointSize]);
if (errorResult == 0)
[NSException raise:NSInternalInconsistencyException format:@"Optimization assumption violation: unable to cache glyph advances - for %@ %f", self, [font displayName], [font pointSize]];
unsigned int asciiCount = LAST_ASCII_CHAR - FIRST_ASCII_CHAR + 1;
short unsigned int asciiBuffer[LAST_ASCII_CHAR+1];
for (i = FIRST_ASCII_CHAR; i <= LAST_ASCII_CHAR; i++){
asciiBuffer[i] = i;
}
__IFInitATSGlyphVector(&_asciiCacheGlyphVector, asciiCount);
(void)ATSUConvertCharToGlyphs(_asciiStyleGroup, &asciiBuffer[FIRST_ASCII_CHAR], 0, asciiCount, 0, (ATSGlyphVector *)&_asciiCacheGlyphVector);
if (_asciiCacheGlyphVector.numGlyphs != asciiCount)
[NSException raise:NSInternalInconsistencyException format:@"Optimization assumption violation: ascii and glyphID count not equal - for %@ %f", self, [font displayName], [font pointSize]];
}
#endif
#ifdef DIRECT_TO_CG
static NSRect _rectForString (KWQLayoutInfo *self, const UniChar *internalBuffer, unsigned int stringLength)
{
CGContextRef cgContext;
int totalWidth = 0;
unsigned int i, numGlyphs, index;
int glyphID;
ATSLayoutRecord *glyphRecords, *glyphRecordsPtr;
NSFont *font = [self font];
BOOL needGlyphAdvanceLookup = NO;
BOOL needCharToGlyphLookup = NO;
if ([font glyphPacking] != NSNativeShortGlyphPacking &&
[font glyphPacking] != NSTwoByteGlyphPacking)
[NSException raise:NSInternalInconsistencyException format:@"%@: Don't know how to pack glyphs for font %@ %f", self, [font displayName], [font pointSize]];
cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
if (self->widthCache == 0)
[self _initializeCaches];
// Check if we can use the cached character-to-glyph map. We only use the character-to-glyph map
// if all the characters in the string fall in the safe ASCII range.
for (i = 0; i < stringLength; i++){
if (internalBuffer[i] < FIRST_ASCII_CHAR || internalBuffer[i] > LAST_ASCII_CHAR){
//fprintf (stdout, "char to glyph cache miss because of character 0x%04x\n", internalBuffer[i]);
needCharToGlyphLookup = YES;
break;
}
}
// If we can't use the cached map, the calculate a map for this string.
if (needCharToGlyphLookup){
__IFInitATSGlyphVector(&self->_glyphVector, stringLength);
(void)ATSUConvertCharToGlyphs(self->_styleGroup, internalBuffer, 0, stringLength, 0, (ATSGlyphVector *)&self->_glyphVector);
glyphRecords = self->_glyphVector.firstRecord;
numGlyphs = self->_glyphVector.numGlyphs;
}
else {
glyphRecords = self->_asciiCacheGlyphVector.firstRecord;
numGlyphs = stringLength;
}
// Now we have the glyphs, determine if we can use the cached glyph measurements.
for (i = 0; i < numGlyphs; i++){
if (needCharToGlyphLookup)
index = i;
else
index = internalBuffer[i]-FIRST_ASCII_CHAR;
glyphID = glyphRecords[index].glyphID;
if (glyphID > self->widthCacheSize){
needGlyphAdvanceLookup = YES;
break;
}
}
// If we can't use the cached glyph measurement ask CG for the measurements.
if (needGlyphAdvanceLookup){
char localGlyphBuf[LOCAL_GLYPH_BUFFER_SIZE];
char *usedGlyphBuf, *glyphBufPtr, *allocatedGlyphBuf = 0;
fprintf (stdout, "glyph measurement cache miss\n");
// Now construct the glyph buffer.
if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE/2)
usedGlyphBuf = glyphBufPtr = allocatedGlyphBuf = (char *)malloc (numGlyphs * 2);
else
usedGlyphBuf = glyphBufPtr = &localGlyphBuf[0];
if (needCharToGlyphLookup){
int glyphID;
glyphRecordsPtr = glyphRecords;
for (i = 0; i < numGlyphs; i++){
glyphID = glyphRecordsPtr->glyphID;
*glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
*glyphBufPtr++ = (char)(glyphID & 0x00FF);
glyphRecordsPtr++;
}
}
else {
int glyphID;
for (i = 0; i < numGlyphs; i++){
index = internalBuffer[i]-FIRST_ASCII_CHAR;
glyphID = glyphRecords[index].glyphID;
*glyphBufPtr++ = (char)((glyphID >> 8) & 0x00FF);
*glyphBufPtr++ = (char)(glyphID & 0x00FF);
}
}
float localAdvanceBuf[LOCAL_GLYPH_BUFFER_SIZE];
float *usedAdvanceBuf, *allocatedAdvanceBuf = 0;
if (numGlyphs > LOCAL_GLYPH_BUFFER_SIZE)
usedAdvanceBuf = allocatedAdvanceBuf = (float *)malloc (numGlyphs * sizeof(float));
else
usedAdvanceBuf = &localAdvanceBuf[0];
if (numGlyphs < LOCAL_GLYPH_BUFFER_SIZE){
CGFontGetGlyphScaledAdvances ([font _backingCGSFont], (const short unsigned int *)usedGlyphBuf, numGlyphs, usedAdvanceBuf, [font pointSize]);
for (i = 0; i < numGlyphs; i++){
//totalWidth += ScaleEmToUnits (advance[i], info->unitsPerEm);
totalWidth += ROUND_TO_INT(usedAdvanceBuf[i]);
}
}
if (allocatedAdvanceBuf)
free (allocatedAdvanceBuf);
if (allocatedGlyphBuf)
free (allocatedGlyphBuf);
}
else {
float *widthCache = self->widthCache;
for (i = 0; i < numGlyphs; i++){
if (needCharToGlyphLookup)
index = i;
else
index = internalBuffer[i]-FIRST_ASCII_CHAR;
totalWidth += ROUND_TO_INT(widthCache[glyphRecords[index].glyphID]);
}
}
if (needCharToGlyphLookup)
__IFResetATSGlyphVector(&self->_glyphVector);
return NSMakeRect (0,0,(float)totalWidth, (float)self->lineHeight);
}
#endif
- (NSRect)rectForString:(NSString *)string
{
#ifdef DIRECT_TO_CG
UniChar localBuffer[LOCAL_GLYPH_BUFFER_SIZE];
const UniChar *_internalBuffer = CFStringGetCharactersPtr ((CFStringRef)string);
const UniChar *internalBuffer;
if (!_internalBuffer){
CFStringGetCharacters((CFStringRef)string, CFRangeMake(0, CFStringGetLength((CFStringRef)string)), &localBuffer[0]);
internalBuffer = &localBuffer[0];
}
else
internalBuffer = _internalBuffer;
return _rectForString (self, internalBuffer, [string length]);
#else
id <KWQLayoutFragment> cachedFragment;
cachedFragment = [textStorage getFragmentForString: string];
return [cachedFragment boundingRect];
#endif
}
......@@ -285,18 +644,24 @@ static NSMutableDictionary *metricsCache = nil;
[attributes setObject: color forKey: NSForegroundColorAttributeName];
}
- (void)setFont: (NSFont *)aFont
- (NSDictionary *)attributes
{
[attributes setObject: aFont forKey: NSFontAttributeName];
return attributes;
}
- (NSDictionary *)attributes
- (int)lineHeight
{
return attributes;
return lineHeight;
}
- (NSFont *)font
{
return font;
}
- (void)dealloc
{
[font release];
[attributes release];
[super dealloc];
}
......@@ -419,6 +784,13 @@ int QFontMetrics::width(const QString &qstring, int len) const
return stringWidth;
}
int QFontMetrics::