142 lines
4.7 KiB
C++
142 lines
4.7 KiB
C++
/*
|
|
* 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
|