aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2011-05-26 09:14:45 +1000
committernyamatongwe <unknown>2011-05-26 09:14:45 +1000
commit82266f54fef82a3481bf9ec091d85c2c202df5ec (patch)
tree9478fbba514910e3648d97940ccd3771c9b64509
parent1ef9f42a4e839bf12d454e8560e7d697e1e3b0c9 (diff)
downloadscintilla-mirror-82266f54fef82a3481bf9ec091d85c2c202df5ec.tar.gz
Convert text drawing and measurement to use Core Text API.
Contributed by Elizabeth Irizarry of Adobe with some modifications by Neil Hodgson.
-rw-r--r--cocoa/PlatCocoa.mm207
-rw-r--r--cocoa/QuartzTextLayout.h150
-rw-r--r--cocoa/QuartzTextStyle.h114
-rw-r--r--cocoa/QuartzTextStyleAttribute.h145
4 files changed, 201 insertions, 415 deletions
diff --git a/cocoa/PlatCocoa.mm b/cocoa/PlatCocoa.mm
index 6e8620b0b..3a70fcd93 100644
--- a/cocoa/PlatCocoa.mm
+++ b/cocoa/PlatCocoa.mm
@@ -156,23 +156,15 @@ void Font::Create(const char *faceName, int characterSet, int size, bool bold, b
int extraFontFlag)
{
// TODO: How should I handle the characterSet request?
- Release();
-
- QuartzTextStyle* style = new QuartzTextStyle();
- fid = style;
-
- // Find the font
- QuartzFont font(faceName, strlen(faceName));
-
- // We set Font, Size, Bold, Italic
- QuartzTextSize textSize(size);
- QuartzTextBold isBold(bold);
- QuartzTextItalic isItalic(italic);
-
- // Actually set the attributes
- QuartzTextStyleAttribute* attributes[] = { &font, &textSize, &isBold, &isItalic };
- style->setAttributes(attributes, sizeof(attributes) / sizeof(*attributes));
- style->setFontFeature(kLigaturesType, kCommonLigaturesOffSelector);
+ Release();
+
+ QuartzTextStyle* style = new QuartzTextStyle();
+ fid = style;
+
+ // Create the font with attributes
+ QuartzFont font(faceName, strlen(faceName), size, bold, italic);
+ CTFontRef fontRef = font.getFontID();
+ style->setFontRef(fontRef);
}
//--------------------------------------------------------------------------------------------------
@@ -774,78 +766,49 @@ void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const c
void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
ColourAllocated fore)
{
- textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
-
- // The Quartz RGB fill color influences the ATSUI color
- FillColour(fore);
-
- // Draw text vertically flipped as OS X uses a coordinate system where +Y is upwards.
- textLayout->draw(rc.left, ybase, true);
+ ColourDesired colour(fore.AsLong());
+ CGColorRef color = CGColorCreateGenericRGB(colour.GetRed()/255.0,colour.GetGreen()/255.0,colour.GetBlue()/255.0,1.0);
+
+ QuartzTextStyle* style = reinterpret_cast<QuartzTextStyle*>(font_.GetID());
+ style->setCTStyleColor(color);
+
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+ textLayout->draw(rc.left, ybase);
}
//--------------------------------------------------------------------------------------------------
void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions)
{
- // sample at http://developer.apple.com/samplecode/ATSUICurveAccessDemo/listing1.html
- // sample includes use of ATSUGetGlyphInfo which would be better for older
- // OSX systems. We should expand to using that on older systems as well.
- for (int i = 0; i < len; i++)
- positions [i] = 0;
-
- // We need the right X coords, so we have to append a char to get the left coord of thast extra char
- char* buf = (char*) malloc (len+1);
- if (!buf)
- return;
-
- memcpy (buf, s, len);
- buf [len] = '.';
-
- textLayout->setText (reinterpret_cast<const UInt8*>(buf), len+1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
- ATSUGlyphInfoArray* theGlyphInfoArrayPtr;
- ByteCount theArraySize;
-
- // Get the GlyphInfoArray
- ATSUTextLayout layout = textLayout->getLayout();
- if ( noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, NULL))
- {
- theGlyphInfoArrayPtr = (ATSUGlyphInfoArray *) malloc (theArraySize + sizeof(ItemCount) + sizeof(ATSUTextLayout));
- if (theGlyphInfoArrayPtr)
- {
- if (noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, theGlyphInfoArrayPtr))
- {
- // do not count the first item, which is at the beginning of the line
- for ( UniCharCount unicodePosition = 1, i = 0; i < len && unicodePosition < theGlyphInfoArrayPtr->numGlyphs; unicodePosition ++ )
- {
- // The ideal position is the x coordinate of the glyph, relative to the beginning of the line
- int position = (int)( theGlyphInfoArrayPtr->glyphs[unicodePosition].idealX + 0.5 ); // These older APIs return float values
- unsigned char uch = s[i];
- positions[i++] = position;
-
- // If we are using unicode (UTF8), map the Unicode position back to the UTF8 characters,
- // as 1 unicode character can map to multiple UTF8 characters.
- // See: http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF
- // Or: http://www.cl.cam.ac.uk/~mgk25/unicode.html
- if ( unicodeMode )
- {
- unsigned char mask = 0xc0;
- int count = 1;
- // Add one additonal byte for each extra high order one in the byte
- while ( uch >= mask && count < 8 )
- {
- positions[i++] = position;
- count ++;
- mask = mask >> 1 | 0x80; // add an additional one in the highest order position
- }
- }
- }
- }
-
- // Free the GlyphInfoArray
- free (theGlyphInfoArrayPtr);
- }
- }
- free (buf);
+ for (int i = 0; i < len; i++)
+ positions [i] = 0;
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+
+ CTLineRef mLine = textLayout->getCTLine();
+ assert(mLine != NULL);
+
+ CGFloat* secondaryOffset= 0;
+ int unicodeCharStart = 0;
+ for ( int i = 0; i < len+1; i ++ ){
+ unsigned char uch = s[i];
+ CFIndex charIndex = unicodeCharStart+1;
+ CGFloat advance = CTLineGetOffsetForStringIndex(mLine, charIndex, secondaryOffset);
+
+ if ( unicodeMode )
+ {
+ unsigned char mask = 0xc0;
+ int lcount = 1;
+ // Add one additonal byte for each extra high order one in the byte
+ while ( uch >= mask && lcount < 8 )
+ {
+ positions[i++] = (int)(advance+0.5);
+ lcount ++;
+ mask = mask >> 1 | 0x80; // add an additional one in the highest order position
+ }
+ }
+ positions[i] = (int)(advance+0.5);
+ unicodeCharStart++;
+ }
}
int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
@@ -853,19 +816,7 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
{
textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
- // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout?
- unsigned long actualNumberOfBounds = 0;
- ATSTrapezoid glyphBounds;
-
- // We get a single bound, since the text should only require one. If it requires more, there is an issue
- if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 )
- {
- Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthText" );
- return 0;
- }
-
- //Platform::DebugPrintf( "WidthText: \"%*s\" = %ld\n", len, s, Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ) );
- return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+ return textLayout->MeasureStringWidth();
}
return 1;
}
@@ -876,32 +827,12 @@ int SurfaceImpl::WidthChar(Font &font_, char ch) {
{
textLayout->setText (reinterpret_cast<const UInt8*>(str), 1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
- // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout?
- unsigned long actualNumberOfBounds = 0;
- ATSTrapezoid glyphBounds;
-
- // We get a single bound, since the text should only require one. If it requires more, there is an issue
- if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 )
- {
- Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthChar" );
- return 0;
- }
-
- return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+ return textLayout->MeasureStringWidth();
}
else
return 1;
}
-// Three possible strategies for determining ascent and descent of font:
-// 1) Call ATSUGetGlyphBounds with string containing all letters, numbers and punctuation.
-// 2) Use the ascent and descent fields of the font.
-// 3) Call ATSUGetGlyphBounds with string as 1 but also including accented capitals.
-// Smallest values given by 1 and largest by 3 with 2 in between.
-// Techniques 1 and 2 sometimes chop off extreme portions of ascenders and
-// descenders but are mostly OK except for accented characters which are
-// rarely used in code.
-
// This string contains a good range of characters to test for size.
const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -910,16 +841,18 @@ int SurfaceImpl::Ascent(Font &font_) {
if (!font_.GetID())
return 1;
- ATSUTextMeasurement ascent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSUAscentTag );
- return Fix2Long( ascent );
+ float ascent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAscent();
+ return ascent + 0.5;
+
}
int SurfaceImpl::Descent(Font &font_) {
if (!font_.GetID())
return 1;
- ATSUTextMeasurement descent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSUDescentTag );
- return Fix2Long( descent );
+ float descent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getDescent();
+ return descent + 0.5;
+
}
int SurfaceImpl::InternalLeading(Font &) {
@@ -932,12 +865,15 @@ int SurfaceImpl::ExternalLeading(Font &font_) {
if (!font_.GetID())
return 1;
- ATSUTextMeasurement lineGap = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSULeadingTag );
- return Fix2Long( lineGap );
+ float leading = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getLeading();
+ return leading + 0.5;
+
}
int SurfaceImpl::Height(Font &font_) {
- return Ascent(font_) + Descent(font_);
+
+ int ht = Ascent(font_) + Descent(font_);
+ return ht;
}
int SurfaceImpl::AverageCharWidth(Font &font_) {
@@ -949,29 +885,6 @@ int SurfaceImpl::AverageCharWidth(Font &font_) {
int width = WidthText( font_, sizeString, sizeStringLength );
return (int) ((width / (float) sizeStringLength) + 0.5);
-
- /*
- ATSUStyle textStyle = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getATSUStyle();
- ATSUFontID fontID;
-
- ByteCount actualSize = 0;
- if ( ATSUGetAttribute( textStyle, kATSUFontTag, sizeof( fontID ), &fontID, &actualSize ) != noErr )
- {
- Platform::DebugDisplay( "ATSUGetAttribute failed" );
- return 1;
- }
-
- ATSFontMetrics metrics;
- memset( &metrics, 0, sizeof( metrics ) );
- if ( ATSFontGetHorizontalMetrics( fontID, kATSOptionFlagsDefault, &metrics ) != noErr )
- {
- Platform::DebugDisplay( "ATSFontGetHorizontalMetrics failed in AverageCharWidth" );
- return 1;
- }
-
- printf( "%f %f %f\n", metrics.avgAdvanceWidth * 32, metrics.ascent * 32, metrics.descent * 32 );
-
- return (int) (metrics.avgAdvanceWidth + 0.5);*/
}
int SurfaceImpl::SetPalette(Scintilla::Palette *, bool) {
diff --git a/cocoa/QuartzTextLayout.h b/cocoa/QuartzTextLayout.h
index 64bf492d4..033ac98fb 100644
--- a/cocoa/QuartzTextLayout.h
+++ b/cocoa/QuartzTextLayout.h
@@ -15,127 +15,89 @@
#include "QuartzTextStyle.h"
+
class QuartzTextLayout
{
public:
/** Create a text layout for drawing on the specified context. */
- QuartzTextLayout( CGContextRef context ) : layout( NULL ), unicode_string( NULL ), unicode_length( 0 )
+ QuartzTextLayout( CGContextRef context )
{
- OSStatus err = ATSUCreateTextLayout( &layout );
- if (0 != err)
- layout = NULL;
-
+ mString = NULL;
+ mLine = NULL;
setContext(context);
-
- ATSUAttributeTag tag = kATSULineLayoutOptionsTag;
- ByteCount size = sizeof( ATSLineLayoutOptions );
- ATSLineLayoutOptions rendering = kATSLineUseDeviceMetrics; //| kATSLineFractDisable | kATSLineUseQDRendering
- ATSUAttributeValuePtr valuePtr = &rendering;
- err = ATSUSetLayoutControls( layout, 1, &tag, &size, &valuePtr );
}
~QuartzTextLayout()
{
- if (NULL != layout)
- ATSUDisposeTextLayout( layout );
- layout = NULL;
-
- if ( unicode_string != NULL )
- {
- delete[] unicode_string;
- unicode_string = NULL;
- unicode_length = 0;
- }
- }
-
- /** Assign a string to the text layout object. */
- // TODO: Create a UTF8 version
- // TODO: Optimise the ASCII version by not copying so much
- OSStatus setText( const UInt8* buffer, size_t byteLength, CFStringEncoding encoding )
- {
- if (NULL == layout)
- return -1;
- CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, encoding, false );
- if (!str)
- return -1;
-
- unicode_length = CFStringGetLength( str );
- if (unicode_string)
- delete[] unicode_string;
- unicode_string = new UniChar[ unicode_length ];
- CFStringGetCharacters( str, CFRangeMake( 0, unicode_length ), unicode_string );
-
- CFRelease( str );
- str = NULL;
-
- OSStatus err;
- err = ATSUSetTextPointerLocation( layout, unicode_string, kATSUFromTextBeginning, kATSUToTextEnd, unicode_length );
- if( err != noErr ) return err;
-
- // Turn on the default font fallbacks
- return ATSUSetTransientFontMatching( layout, true );
+ if ( mString != NULL )
+ {
+ CFRelease(mString);
+ mString = NULL;
+ }
+ if ( mLine != NULL )
+ {
+ CFRelease(mLine);
+ mLine = NULL;
+ }
}
inline void setText( const UInt8* buffer, size_t byteLength, const QuartzTextStyle& r )
{
- this->setText( buffer, byteLength, kCFStringEncodingUTF8 );
- ATSUSetRunStyle( layout, r.getATSUStyle(), 0, unicode_length );
- }
-
- /** Apply the specified text style on the entire range of text. */
- void setStyle( const QuartzTextStyle& style )
- {
- ATSUSetRunStyle( layout, style.getATSUStyle(), kATSUFromTextBeginning, kATSUToTextEnd );
+ CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, kCFStringEncodingUTF8, false );
+ if (!str)
+ return;
+
+ CFMutableDictionaryRef stringAttribs = r.getCTStyle();
+
+ if (mString != NULL)
+ CFRelease(mString);
+ mString = ::CFAttributedStringCreate(NULL, str, stringAttribs);
+
+ if (mLine != NULL)
+ CFRelease(mLine);
+ mLine = ::CTLineCreateWithAttributedString(mString);
+
+ CFRelease( str );
}
- /** Draw the text layout into the current CGContext at the specified position, flipping the CGContext's Y axis if required.
+ /** Draw the text layout into the current CGContext at the specified position.
* @param x The x axis position to draw the baseline in the current CGContext.
- * @param y The y axis position to draw the baseline in the current CGContext.
- * @param flipTextYAxis If true, the CGContext's Y axis will be flipped before drawing the text, and restored afterwards. Use this when drawing in an HIView's CGContext, where the origin is the top left corner. */
- void draw( float x, float y, bool flipTextYAxis = false )
+ * @param y The y axis position to draw the baseline in the current CGContext. */
+ void draw( float x, float y )
{
- if (NULL == layout || 0 == unicode_length)
- return;
- if ( flipTextYAxis )
- {
- CGContextSaveGState( gc );
- CGContextScaleCTM( gc, 1.0, -1.0 );
- y = -y;
- }
-
- OSStatus err;
- err = ATSUDrawText( layout, kATSUFromTextBeginning, kATSUToTextEnd, X2Fix( x ), X2Fix( y ) );
-
- if ( flipTextYAxis ) CGContextRestoreGState( gc );
+ if (mLine == NULL)
+ return;
+
+ ::CGContextSetTextMatrix(gc, CGAffineTransformMakeScale(1.0, -1.0));
+
+ // Set the text drawing position.
+ ::CGContextSetTextPosition(gc, x, y);
+
+ // And finally, draw!
+ ::CTLineDraw(mLine, gc);
}
-
- /** Sets a single text layout control on the ATSUTextLayout object.
- * @param tag The control to set.
- * @param size The size of the parameter pointed to by value.
- * @param value A pointer to the new value for the control.
- */
- void setControl( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value )
- {
- ATSUSetLayoutControls( layout, 1, &tag, &size, &value );
+
+ float MeasureStringWidth()
+ {
+ if (mLine == NULL)
+ return 0.0f;
+
+ return ::CTLineGetTypographicBounds(mLine, NULL, NULL, NULL);
+ }
+
+ CTLineRef getCTLine() {
+ return mLine;
}
-
- ATSUTextLayout getLayout() {
- return layout;
- }
-
- inline CFIndex getLength() const { return unicode_length; }
+
inline void setContext (CGContextRef context)
{
gc = context;
- if (NULL != layout)
- setControl( kATSUCGContextTag, sizeof( gc ), &gc );
}
private:
- ATSUTextLayout layout;
- UniChar* unicode_string;
- int unicode_length;
CGContextRef gc;
+ CFAttributedStringRef mString;
+ CTLineRef mLine;
};
#endif
diff --git a/cocoa/QuartzTextStyle.h b/cocoa/QuartzTextStyle.h
index 36729b77b..2825fbb2f 100644
--- a/cocoa/QuartzTextStyle.h
+++ b/cocoa/QuartzTextStyle.h
@@ -15,75 +15,63 @@ class QuartzTextStyle
public:
QuartzTextStyle()
{
- ATSUCreateStyle( &style );
+ styleDict = CFDictionaryCreateMutable(NULL, 1, NULL, NULL);
}
~QuartzTextStyle()
{
- if ( style != NULL )
- ATSUDisposeStyle( style );
- style = NULL;
+ if (styleDict != NULL)
+ {
+ CFRelease(styleDict);
+ styleDict = NULL;
+ }
}
-
- void setAttribute( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value )
- {
- ATSUSetAttributes( style, 1, &tag, &size, &value );
- }
-
- void setAttribute( QuartzTextStyleAttribute& attribute )
- {
- setAttribute( attribute.getTag(), attribute.getSize(), attribute.getValuePtr() );
- }
-
- void getAttribute( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value, ByteCount* actualSize )
- {
- ATSUGetAttribute( style, tag, size, value, actualSize );
- }
-
- template <class T>
- T getAttribute( ATSUAttributeTag tag )
- {
- T value;
- ByteCount actualSize;
- ATSUGetAttribute( style, tag, sizeof( T ), &value, &actualSize );
- return value;
- }
-
- // TODO: Is calling this actually faster than calling setAttribute multiple times?
- void setAttributes( QuartzTextStyleAttribute* attributes[], int number )
- {
- // Create the parallel arrays and initialize them properly
- ATSUAttributeTag* tags = new ATSUAttributeTag[ number ];
- ByteCount* sizes = new ByteCount[ number ];
- ATSUAttributeValuePtr* values = new ATSUAttributeValuePtr[ number ];
-
- for ( int i = 0; i < number; ++ i )
- {
- tags[i] = attributes[i]->getTag();
- sizes[i] = attributes[i]->getSize();
- values[i] = attributes[i]->getValuePtr();
- }
-
- ATSUSetAttributes( style, number, tags, sizes, values );
-
- // Free the arrays that were allocated
- delete[] tags;
- delete[] sizes;
- delete[] values;
- }
-
- void setFontFeature( ATSUFontFeatureType featureType, ATSUFontFeatureSelector selector )
- {
- ATSUSetFontFeatures( style, 1, &featureType, &selector );
- }
-
- const ATSUStyle& getATSUStyle() const
- {
- return style;
- }
-
+
+ CFMutableDictionaryRef getCTStyle() const
+ {
+ return styleDict;
+ }
+
+ void setCTStyleColor(CGColor* inColor )
+ {
+ CFDictionarySetValue(styleDict, kCTForegroundColorAttributeName, inColor);
+ }
+
+ float getAscent() const
+ {
+ return ::CTFontGetAscent(fontRef);
+ }
+
+ float getDescent() const
+ {
+ return ::CTFontGetDescent(fontRef);
+ }
+
+ float getLeading() const
+ {
+ return ::CTFontGetLeading(fontRef);
+ }
+
+ void setFontRef(CTFontRef inRef)
+ {
+ fontRef = inRef;
+
+ if (styleDict != NULL)
+ CFRelease(styleDict);
+
+ styleDict = CFDictionaryCreateMutable(NULL, 1, NULL, NULL);
+
+ CFDictionaryAddValue(styleDict, kCTFontAttributeName, fontRef);
+ }
+
+ CTFontRef getFontRef()
+ {
+ return fontRef;
+ }
+
private:
- ATSUStyle style;
+ CFMutableDictionaryRef styleDict;
+ CTFontRef fontRef;
};
#endif
diff --git a/cocoa/QuartzTextStyleAttribute.h b/cocoa/QuartzTextStyleAttribute.h
index cf227e47f..41582e8ec 100644
--- a/cocoa/QuartzTextStyleAttribute.h
+++ b/cocoa/QuartzTextStyleAttribute.h
@@ -12,131 +12,54 @@
#ifndef _QUARTZ_TEXT_STYLE_ATTRIBUTE_H
#define _QUARTZ_TEXT_STYLE_ATTRIBUTE_H
-class QuartzTextStyleAttribute
-{
-public:
- QuartzTextStyleAttribute() {}
- virtual ~QuartzTextStyleAttribute() {}
- virtual ByteCount getSize() const = 0;
- virtual ATSUAttributeValuePtr getValuePtr() = 0;
- virtual ATSUAttributeTag getTag() const = 0;
-};
-
-class QuartzTextSize : public QuartzTextStyleAttribute
-{
-public:
- QuartzTextSize( float points )
- {
- size = X2Fix( points );
- }
-
- ByteCount getSize() const
- {
- return sizeof( size );
- }
-
- ATSUAttributeValuePtr getValuePtr()
- {
- return &size;
- }
-
- ATSUAttributeTag getTag() const
- {
- return kATSUSizeTag;
- }
-
-private:
- Fixed size;
-};
-
-class QuartzTextStyleAttributeBoolean : public QuartzTextStyleAttribute
-{
-public:
- QuartzTextStyleAttributeBoolean( bool newVal ) : value( newVal ) {}
-
- ByteCount getSize() const
- {
- return sizeof( value );
- }
- ATSUAttributeValuePtr getValuePtr()
- {
- return &value;
- }
-
- virtual ATSUAttributeTag getTag() const = 0;
-
-private:
- Boolean value;
-};
-
-class QuartzTextBold : public QuartzTextStyleAttributeBoolean
-{
-public:
- QuartzTextBold( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
- ATSUAttributeTag getTag() const
- {
- return kATSUQDBoldfaceTag;
- }
-};
-
-class QuartzTextItalic : public QuartzTextStyleAttributeBoolean
-{
-public:
- QuartzTextItalic( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
- ATSUAttributeTag getTag() const
- {
- return kATSUQDItalicTag;
- }
-};
-
-class QuartzTextUnderline : public QuartzTextStyleAttributeBoolean
-{
-public:
- QuartzTextUnderline( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
- ATSUAttributeTag getTag() const {
- return kATSUQDUnderlineTag;
- }
-};
-
-class QuartzFont : public QuartzTextStyleAttribute
+class QuartzFont
{
public:
/** Create a font style from a name. */
- QuartzFont( const char* name, int length )
+ QuartzFont( const char* name, int length, float size, bool bold, bool italic )
{
assert( name != NULL && length > 0 && name[length] == '\0' );
- // try to create font
- OSStatus err = ATSUFindFontFromName( const_cast<char*>( name ), length, kFontFullName, (unsigned) kFontNoPlatform, kFontRomanScript, (unsigned) kFontNoLanguage, &fontid );
- // need a fallback if font isn't installed
- if( err != noErr || fontid == kATSUInvalidFontID )
- ::ATSUFindFontFromName( "Lucida Grande", 13, kFontFullName, (unsigned) kFontNoPlatform, kFontRomanScript, (unsigned) kFontNoLanguage, &fontid );
+ CFStringRef fontName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman);
+ assert(fontName != NULL);
+
+ if (bold || italic)
+ {
+ CTFontSymbolicTraits desiredTrait = 0;
+ CTFontSymbolicTraits traitMask = 0;
+
+ // if bold was specified, add the trait
+ if (bold) {
+ desiredTrait |= kCTFontBoldTrait;
+ traitMask |= kCTFontBoldTrait;
+ }
+
+ // if italic was specified, add the trait
+ if (italic) {
+ desiredTrait |= kCTFontItalicTrait;
+ traitMask |= kCTFontItalicTrait;
+ }
+
+ // create a font and then a copy of it with the sym traits
+ CTFontRef iFont = ::CTFontCreateWithName(fontName, size, NULL);
+ fontid = ::CTFontCreateCopyWithSymbolicTraits(iFont, size, NULL, desiredTrait, traitMask);
+ CFRelease(iFont);
+ }
+ else
+ {
+ // create the font, no traits
+ fontid = ::CTFontCreateWithName(fontName, size, NULL);
+ }
}
- ByteCount getSize() const
- {
- return sizeof( fontid );
- }
-
- ATSUAttributeValuePtr getValuePtr()
- {
- return &fontid;
- }
-
- ATSUAttributeTag getTag() const
- {
- return kATSUFontTag;
- }
-
- ATSUFontID getFontID() const
+ CTFontRef getFontID()
{
return fontid;
}
private:
- ATSUFontID fontid;
+ CTFontRef fontid;
};
-
#endif