diff options
Diffstat (limited to 'cocoa/QuartzTextLayout.h')
| -rw-r--r-- | cocoa/QuartzTextLayout.h | 141 | 
1 files changed, 141 insertions, 0 deletions
| diff --git a/cocoa/QuartzTextLayout.h b/cocoa/QuartzTextLayout.h new file mode 100644 index 000000000..64bf492d4 --- /dev/null +++ b/cocoa/QuartzTextLayout.h @@ -0,0 +1,141 @@ +/* + *  QuartzTextLayout.h + * + *  Original Code by Evan Jones on Wed Oct 02 2002. + *  Contributors: + *  Shane Caraveo, ActiveState + *  Bernd Paradies, Adobe + * + */ + +#ifndef _QUARTZ_TEXT_LAYOUT_H +#define _QUARTZ_TEXT_LAYOUT_H + +#include <Cocoa/Cocoa.h> + +#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 ) +    { +        OSStatus err = ATSUCreateTextLayout( &layout ); +        if (0 != err) +                layout = 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 ); +    } + +    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 ); +    } + +    /** Draw the text layout into the current CGContext at the specified position, flipping the CGContext's Y axis if required. +    * @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 ) +    { +        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 ); +    } + +    /** 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 ); +    } + +    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; +}; + +#endif | 
