示例#1
0
ATSUTextLayout ATSUCreateTextLayoutWithTextPtr_wrap(
  ATSUStyle     style,
  u_char* text,        int     len,
  int32  textOffset,   int32  textLength,
  void*   FH ) {
  
  ATSUTextLayout layout;
  ResourceMark rm;

  UniChar* unis = NEW_C_HEAP_ARRAY(UniChar, len);
  for (uint i = 0;  i < len;  ++i)
      unis[i] = UniChar(text[i]);  // hack to unicode
      
  OSStatus e = ATSUCreateTextLayoutWithTextPtr(
                 unis, (uint32)textOffset, (int32)textLength, len,
                 1,  (const UniCharCount*)&textLength,  &style,
                 &layout);
  return  e != noErr  ?  (ATSUTextLayout)reportOSError(e, "ATSUCreateTextLayoutWithTextPtr", FH)  :  layout;
}
示例#2
0
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
{
	const char *str;
	bool result = false;

	callback->FindMissingGlyphs(&str);

#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
	if (MacOSVersionIsAtLeast(10, 5, 0)) {
		/* Determine fallback font using CoreText. This uses the language isocode
		 * to find a suitable font. CoreText is available from 10.5 onwards. */
		char lang[16];
		if (strcmp(language_isocode, "zh_TW") == 0) {
			/* Traditional Chinese */
			strecpy(lang, "zh-Hant", lastof(lang));
		} else if (strcmp(language_isocode, "zh_CN") == 0) {
			/* Simplified Chinese */
			strecpy(lang, "zh-Hans", lastof(lang));
		} else if (strncmp(language_isocode, "ur", 2) == 0) {
			/* The urdu alphabet is variant of persian. As OS X has no default
			 * font that advertises an urdu language code, search for persian
			 * support instead. */
			strecpy(lang, "fa", lastof(lang));
		} else {
			/* Just copy the first part of the isocode. */
			strecpy(lang, language_isocode, lastof(lang));
			char *sep = strchr(lang, '_');
			if (sep != NULL) *sep = '\0';
		}

		CFStringRef lang_code;
		lang_code = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8);

		/* Create a font iterator and iterate over all fonts that
		 * are available to the application. */
		ATSFontIterator itr;
		ATSFontRef font;
		ATSFontIteratorCreate(kATSFontContextLocal, NULL, NULL, kATSOptionFlagsUnRestrictedScope, &itr);
		while (!result && ATSFontIteratorNext(itr, &font) == noErr) {
			/* Get CoreText font handle. */
			CTFontRef font_ref = CTFontCreateWithPlatformFont(font, 0.0, NULL, NULL);
			CFArrayRef langs = CTFontCopySupportedLanguages(font_ref);
			if (langs != NULL) {
				/* Font has a list of supported languages. */
				for (CFIndex i = 0; i < CFArrayGetCount(langs); i++) {
					CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(langs, i);
					if (CFStringCompare(lang, lang_code, kCFCompareAnchored) == kCFCompareEqualTo) {
						/* Lang code is supported by font, get full font name. */
						CFStringRef font_name = CTFontCopyFullName(font_ref);
						char name[128];
						CFStringGetCString(font_name, name, lengthof(name), kCFStringEncodingUTF8);
						CFRelease(font_name);
						/* Skip some inappropriate or ugly looking fonts that have better alternatives. */
						if (strncmp(name, "Courier", 7) == 0 || strncmp(name, "Apple Symbols", 13) == 0 ||
								strncmp(name, ".Aqua", 5) == 0 || strncmp(name, "LastResort", 10) == 0 ||
								strncmp(name, "GB18030 Bitmap", 14) == 0) continue;

						/* Save result. */
						callback->SetFontNames(settings, name);
						DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name);
						result = true;
						break;
					}
				}
				CFRelease(langs);
			}
			CFRelease(font_ref);
		}
		ATSFontIteratorRelease(&itr);
		CFRelease(lang_code);
	} else
#endif
	{
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !__LP64__
		/* Determine fallback font using ATSUI. This uses a string sample with
		 * missing characters. This is not failure-proof, but a better way like
		 * using the isocode as in the CoreText code path is not available.
		 * ATSUI was deprecated with 10.6 and is only partially available in
		 * 64-bit mode. */

		/* Remove all control characters in the range from SCC_CONTROL_START to
		 * SCC_CONTROL_END as well as all ASCII < 0x20 from the string as it will
		 * mess with the automatic font detection */
		char buff[256]; // This length is enough to find a suitable replacement font
		strecpy(buff, str, lastof(buff));
		str_validate(buff, lastof(buff), SVS_ALLOW_NEWLINE);

		/* Extract a UniChar representation of the sample string. */
		CFStringRef cf_str = CFStringCreateWithCString(kCFAllocatorDefault, buff, kCFStringEncodingUTF8);
		if (cf_str == NULL) {
			/* Something went wrong. Corrupt/invalid sample string? */
			return false;
		}
		CFIndex str_len = CFStringGetLength(cf_str);
		UniChar string[str_len];
		CFStringGetCharacters(cf_str, CFRangeMake(0, str_len), string);

		/* Create a default text style with the default font. */
		ATSUStyle style;
		ATSUCreateStyle(&style);

		/* Create a text layout object from the sample string using the text style. */
		UniCharCount run_len = kATSUToTextEnd;
		ATSUTextLayout text_layout;
		ATSUCreateTextLayoutWithTextPtr(string, kATSUFromTextBeginning, kATSUToTextEnd, str_len, 1, &run_len, &style, &text_layout);

		/* Try to match a font for the sample text. ATSUMatchFontsToText stops after
		 * it finds the first continuous character run not renderable with the currently
		 * selected font starting at offset. The matching needs to be repeated until
		 * the end of the string is reached to make sure the fallback font matches for
		 * all characters in the string and not only the first run. */
		UniCharArrayOffset offset = kATSUFromTextBeginning;
		OSStatus os_err;
		do {
			ATSUFontID font;
			UniCharCount run_len;
			os_err = ATSUMatchFontsToText(text_layout, offset, kATSUToTextEnd, &font, &offset, &run_len);
			if (os_err == kATSUFontsMatched) {
				/* Found a better fallback font. Update the text layout
				 * object with the new font. */
				ATSUAttributeTag tag = kATSUFontTag;
				ByteCount size = sizeof(font);
				ATSUAttributeValuePtr val = &font;
				ATSUSetAttributes(style, 1, &tag, &size, &val);
				offset += run_len;
			}
			/* Exit if the end of the string is reached or some other error occurred. */
		} while (os_err == kATSUFontsMatched && offset < (UniCharArrayOffset)str_len);

		if (os_err == noErr || os_err == kATSUFontsMatched) {
			/* ATSUMatchFontsToText exited normally. Extract font
			 * out of the text layout object. */
			ATSUFontID font;
			ByteCount act_len;
			ATSUGetAttribute(style, kATSUFontTag, sizeof(font), &font, &act_len);

			/* Get unique font name. The result is not a c-string, we have
			 * to leave space for a \0 and terminate it ourselves. */
			char name[128];
			ATSUFindFontName(font, kFontUniqueName, kFontNoPlatformCode, kFontNoScriptCode, kFontNoLanguageCode, 127, name, &act_len, NULL);
			name[act_len > 127 ? 127 : act_len] = '\0';

			/* Save Result. */
			callback->SetFontNames(settings, name);
			DEBUG(freetype, 2, "ATSUI-Font for %s: %s", language_isocode, name);
			result = true;
		}

		ATSUDisposeTextLayout(text_layout);
		ATSUDisposeStyle(style);
		CFRelease(cf_str);
#endif
	}

	if (result && strncmp(settings->medium.font, "Geeza Pro", 9) == 0) {
		/* The font 'Geeza Pro' is often found for arabic characters, but
		 * it has the 'tiny' problem of not having any latin characters.
		 * 'Arial Unicode MS' on the other hand has arabic and latin glyphs,
		 * but seems to 'forget' to inform the OS about this fact. Manually
		 * substitute the latter for the former if it is loadable. */
		bool ft_init = _library != NULL;
		FT_Face face;
		/* Init FreeType if needed. */
		if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && GetFontByFaceName("Arial Unicode MS", &face) == FT_Err_Ok) {
			FT_Done_Face(face);
			callback->SetFontNames(settings, "Arial Unicode MS");
			DEBUG(freetype, 1, "Replacing font 'Geeza Pro' with 'Arial Unicode MS'");
		}
		if (!ft_init) {
			/* Uninit FreeType if we did the init. */
			FT_Done_FreeType(_library);
			_library = NULL;
		}
	 }

	callback->FindMissingGlyphs(NULL);
	return result;
}
示例#3
0
void drawPlugin(NPP instance, NPCocoaEvent* event)
{
  if (!browserUAString)
    return;

  PluginInstance* currentInstance = (PluginInstance*)(instance->pdata);
  CGContextRef cgContext = event->data.draw.context;
  if (!cgContext)
    return;

  float windowWidth = currentInstance->window.width;
  float windowHeight = currentInstance->window.height;
  
  // save the cgcontext gstate
  CGContextSaveGState(cgContext);
  
  // we get a flipped context
  CGContextTranslateCTM(cgContext, 0.0, windowHeight);
  CGContextScaleCTM(cgContext, 1.0, -1.0);
  
  // draw a gray background for the plugin
  CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
  CGContextSetGrayFillColor(cgContext, 0.5, 1.0);
  CGContextDrawPath(cgContext, kCGPathFill);
  
  // draw a black frame around the plugin
  CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
  CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0);
  CGContextSetLineWidth(cgContext, 6.0);
  CGContextStrokePath(cgContext);
  
  // draw the UA string using ATSUI
  CGContextSetGrayFillColor(cgContext, 0.0, 1.0);
  ATSUStyle atsuStyle;
  ATSUCreateStyle(&atsuStyle);
  CFIndex stringLength = CFStringGetLength(browserUAString);
  UniChar* unicharBuffer = (UniChar*)malloc((stringLength + 1) * sizeof(UniChar));
  CFStringGetCharacters(browserUAString, CFRangeMake(0, stringLength), unicharBuffer);
  UniCharCount runLengths = kATSUToTextEnd;
  ATSUTextLayout atsuLayout;
  ATSUCreateTextLayoutWithTextPtr(unicharBuffer,
                                  kATSUFromTextBeginning,
                                  kATSUToTextEnd,
                                  stringLength,
                                  1,
                                  &runLengths,
                                  &atsuStyle,
                                  &atsuLayout);
  ATSUAttributeTag contextTag = kATSUCGContextTag;
  ByteCount byteSize = sizeof(CGContextRef);
  ATSUAttributeValuePtr contextATSUPtr = &cgContext;
  ATSUSetLayoutControls(atsuLayout, 1, &contextTag, &byteSize, &contextATSUPtr);
  ATSUTextMeasurement lineAscent, lineDescent;
  ATSUGetLineControl(atsuLayout,
                    kATSUFromTextBeginning,
                    kATSULineAscentTag,
                    sizeof(ATSUTextMeasurement),
                    &lineAscent,
                    &byteSize);
  ATSUGetLineControl(atsuLayout,
                    kATSUFromTextBeginning,
                    kATSULineDescentTag,
                    sizeof(ATSUTextMeasurement),
                    &lineDescent,
                    &byteSize);
  float lineHeight = FixedToFloat(lineAscent) + FixedToFloat(lineDescent);  
  ItemCount softBreakCount;
  ATSUBatchBreakLines(atsuLayout,
                      kATSUFromTextBeginning,
                      stringLength,
                      FloatToFixed(windowWidth - 10.0),
                      &softBreakCount);
  ATSUGetSoftLineBreaks(atsuLayout,
                        kATSUFromTextBeginning,
                        kATSUToTextEnd,
                        0, NULL, &softBreakCount);
  UniCharArrayOffset* softBreaks = (UniCharArrayOffset*)malloc(softBreakCount * sizeof(UniCharArrayOffset));
  ATSUGetSoftLineBreaks(atsuLayout,
                        kATSUFromTextBeginning,
                        kATSUToTextEnd,
                        softBreakCount, softBreaks, &softBreakCount);
  UniCharArrayOffset currentDrawOffset = kATSUFromTextBeginning;
  int i = 0;
  while (i < softBreakCount) {
    ATSUDrawText(atsuLayout, currentDrawOffset, softBreaks[i], FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
    currentDrawOffset = softBreaks[i];
    i++;
  }
  ATSUDrawText(atsuLayout, currentDrawOffset, kATSUToTextEnd, FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
  free(unicharBuffer);
  free(softBreaks);
  
  // restore the cgcontext gstate
  CGContextRestoreGState(cgContext);
}
示例#4
0
void Text::calculate_position_and_advance_cursor(TextWriter &tw, int *out_x, int *out_y) const
{
#ifdef WIN32

   const long options = DT_LEFT | DT_NOPREFIX;

   Context c = tw.renderer.m_context;
   int previous_map_mode = SetMapMode(c, MM_TEXT);

   HFONT font = font_handle_lookup[tw.size];

   // Create the font we want to use, and swap it out with
   // whatever is currently in there, along with our color
   HFONT previous_font = (HFONT)SelectObject(c, font);

   // Call DrawText to find out how large our text is
   RECT drawing_rect = { tw.x, tw.y, 0, 0 };
   tw.last_line_height = DrawText(c, m_text.c_str(), int(m_text.length()), &drawing_rect, options | DT_CALCRECT);

   // Return the hdc settings to their previous setting
   SelectObject(c, previous_font);
   SetMapMode(c, previous_map_mode);

#else

   // Convert passed-in text to Unicode
   CFStringRef cftext = MacStringFromWide(m_text, true).get();
   CFDataRef unitext = CFStringCreateExternalRepresentation(kCFAllocatorDefault, cftext, kCFStringEncodingUnicode, 0);
   if (!unitext) throw PianoGameError(WSTRING(L"Couldn't convert string to unicode: '" << m_text << L"'"));
   CFRelease(cftext);

   // Create an ATSU layout
   ATSUTextLayout layout;
   const UniCharCount run_length = kATSUToTextEnd;
   OSStatus status = ATSUCreateTextLayoutWithTextPtr((ConstUniCharArrayPtr)CFDataGetBytePtr(unitext), kATSUFromTextBeginning, kATSUToTextEnd, CFDataGetLength(unitext) / 2, 1, &run_length, &atsu_style_lookup[tw.size], &layout);
   if (status != noErr) throw PianoGameError(WSTRING(L"Couldn't create ATSU text layout for string: '" << m_text << L"', Error code: " << static_cast<int>(status)));

   // Measure the size of the resulting text
   Rect drawing_rect = { 0, 0, 0, 0 };
   
   ATSUTextMeasurement before = 0;
   ATSUTextMeasurement after = 0;
   ATSUTextMeasurement ascent = 0;
   ATSUTextMeasurement descent = 0;
   
   status = ATSUGetUnjustifiedBounds(layout, 0, kATSUToTextEnd, &before, &after, &ascent, &descent);
   if (status != noErr) throw PianoGameError(WSTRING(L"Couldn't get unjustified bounds for text layout for string: '" << m_text << L"', Error code: " << static_cast<int>(status)));

   // NOTE: the +1 here is completely arbitrary and seemed to place the text better.
   // It may just be a difference between the Windows and Mac text placement systems.
   drawing_rect.top += tw.y + 1;
   drawing_rect.left += tw.x + FixRound(before);
   drawing_rect.right += tw.x + FixRound(after);

   // Not used.
   drawing_rect.bottom = 0;

   // Clean-up
	ATSUDisposeTextLayout(layout);
   CFRelease(unitext);

#endif

   // Update the text-writer with post-draw coordinates
   if (tw.centered) drawing_rect.left -= (drawing_rect.right - drawing_rect.left) / 2;
   if (!tw.centered) tw.x += drawing_rect.right - drawing_rect.left;

   // Tell the draw function where to put the text
   *out_x = drawing_rect.left;
   *out_y = drawing_rect.top;
}
示例#5
0
文件: osxtext.cpp 项目: kant/livecode
static bool osx_draw_text_to_cgcontext_at_location(const void *p_text, uindex_t p_length, MCGPoint p_location, const MCGFont &p_font, CGContextRef p_cgcontext, MCGIntRectangle &r_bounds)
{	
	OSStatus t_err;
	t_err = noErr;	
	
	ATSUFontID t_font_id;
	Fixed t_font_size;
	t_font_size = p_font . size << 16;	
	
	ATSUAttributeTag t_tags[] =
	{
		kATSUFontTag,
		kATSUSizeTag,
	};
	ByteCount t_sizes[] =
	{
		sizeof(ATSUFontID),
		sizeof(Fixed),
	};
	ATSUAttributeValuePtr t_attrs[] =
	{
		&t_font_id,
		&t_font_size,
	};	
	
	ATSLineLayoutOptions t_layout_options;
	ATSUAttributeTag t_layout_tags[] =
	{
		kATSULineLayoutOptionsTag,
		kATSUCGContextTag,
	};
	ByteCount t_layout_sizes[] =
	{
		sizeof(ATSLineLayoutOptions),
		sizeof(CGContextRef),
	};
	ATSUAttributeValuePtr t_layout_attrs[] =
	{
		&t_layout_options,
		&p_cgcontext,
	};	
	
	if (t_err == noErr)
	{
		// if the specified fon't can't be found, just use the default
		if (ATSUFONDtoFontID((short)(intptr_t)p_font . fid, p_font . style, &t_font_id) != noErr)
			t_err = ATSUFONDtoFontID(0, p_font . style, &t_font_id);
	}
	
	ATSUStyle t_style;
	t_style = NULL;
	if (t_err == noErr)
		t_err = ATSUCreateStyle(&t_style);
	if (t_err == noErr)
		t_err = ATSUSetAttributes(t_style, sizeof(t_tags) / sizeof(ATSUAttributeTag), t_tags, t_sizes, t_attrs);
	
	ATSUTextLayout t_layout;
	t_layout = NULL;
	if (t_err == noErr)
	{
		UniCharCount t_run;
		t_run = p_length / 2;
		t_err = ATSUCreateTextLayoutWithTextPtr((const UniChar *)p_text, 0, p_length / 2, p_length / 2, 1, &t_run, &t_style, &t_layout);
	}
	if (t_err == noErr)
		t_err = ATSUSetTransientFontMatching(t_layout, true);
	if (t_err == noErr)
	{
		t_layout_options = kATSLineUseDeviceMetrics | kATSLineFractDisable;
		t_err = ATSUSetLayoutControls(t_layout, sizeof(t_layout_tags) / sizeof(ATSUAttributeTag), t_layout_tags, t_layout_sizes, t_layout_attrs);
	}	
	
	MCGIntRectangle t_bounds;
	if (p_cgcontext == NULL)
	{
		ATSUTextMeasurement t_before, t_after, t_ascent, t_descent;
		if (t_err == noErr)
			t_err = ATSUGetUnjustifiedBounds(t_layout, 0, p_length / 2, &t_before, &t_after, &t_ascent, &t_descent);
		
		if (t_err == noErr)
		{
			t_ascent = (t_ascent + 0xffff) >> 16;
			t_descent = (t_descent + 0xffff) >> 16;
			t_after = (t_after + 0xffff) >> 16;
			
			t_bounds . x = p_location . x;
			t_bounds . y = p_location . y - p_font . ascent;
			t_bounds . width = t_after;
			t_bounds . height = p_font . descent + p_font . ascent;
			
			r_bounds = t_bounds;
		}
static
OSStatus AddNewTextLayoutToContext( 
	DrawContextStruct	*context )
{
	OSStatus				err = noErr;
	ATSUAttributeTag		tag;
	ByteCount				valueSize;
	ATSUAttributeValuePtr	valuePtr;
	UniCharCount			runLength = kATSUToTextEnd;
	
	if (context->cgContext == NULL)
		return err;

	// create a text layout object
	err = ATSUCreateTextLayoutWithTextPtr( context->textBuffer,
		kATSUFromTextBeginning, kATSUToTextEnd, context->characterCount, 1,
		&runLength, &gGlobalStyle, &context->layoutObject );
	require_noerr( err, AddNewTextLayoutToContext_err );
	
	// add the cgContext to the text layout
	tag = kATSUCGContextTag;
	valueSize = sizeof( CGContextRef );
	valuePtr = &context->cgContext;
	err = ATSUSetLayoutControls( context->layoutObject, 1, &tag, &valueSize, &valuePtr );
	require_noerr( err, AddNewTextLayoutToContext_err );
	
	// set font substitution for the new layout	
	err = ATSUSetTransientFontMatching( context->layoutObject, true );
	require_noerr( err, AddNewTextLayoutToContext_err );
	
	// now, check the menu and see if we need to install a callback
	switch ( gDemoMenuSelection )
	{
		case kDemoMenuItemStretch:
			err = InstallStrechyGlyphCallback( context->layoutObject );
			require_noerr( err, AddNewTextLayoutToContext_err );
			break;
			
		case kDemoMenuItemShrink:
			err = InstallShrinkyGlyphCallback( context->layoutObject );
			require_noerr( err, AddNewTextLayoutToContext_err );
			break;
		
		case kDemoMenuItemWhitespaceReplace:		
			err = InstallGlyphReplacementCallback( context->layoutObject );
			require_noerr( err, AddNewTextLayoutToContext_err );
			break;
			
		case kDemoMenuItemSineWave:
			err = InstallGlyphWaveCallback( context->layoutObject );
			require_noerr( err, AddNewTextLayoutToContext_err );
			break;
		
		case kDemoMenuItemNone:
		default:		
			break;
			
	}

AddNewTextLayoutToContext_err:
	
	return err;
}
示例#7
0
文件: main.c 项目: arnelh/Examples
static
OSStatus DrawLayoutForStyleAndRunInfo( 
	ATSUStyle			styleArray[], 
	ItemCount			styleArraySize,
	ATSUStyleRunInfo	styleRunArray[],
	ItemCount			styleRunArraySize,
	UniChar				*stringPtr,
	UniCharCount		stringLen,
	CGContextRef		cgContext,
	Fixed				currentXPos,
	Fixed				*currentYPos  )
{
	OSStatus				err;
	ATSUStyle				*seperateStyles = NULL;
	UniCharCount			*seperateRunLengths = NULL;
	ItemCount				numberOfRuns = 0;
	ATSUAttributeTag		attrTag;
	ByteCount				attrSize;
	ATSUAttributeValuePtr	attrPtr;
	ATSUTextLayout			newLayout;
	
	// check to see if we have a style array
	if ( styleArray != NULL )
	{
		// if the styleRunArray is NULL, then there is only one run
		if ( styleRunArray == NULL )
		{
			numberOfRuns = 1;
			seperateStyles = styleArray;
			seperateRunLengths = &stringLen;
		}
		else
		{
			ItemCount	i;
		
			// the number of runs is equal to the number of runs passed in
			numberOfRuns = styleRunArraySize;
		
			// allocate a seperateStyles and seperateRuns array
			seperateStyles = (ATSUStyle *) malloc( sizeof( ATSUStyle ) * 
				numberOfRuns );
			require_action( seperateStyles != NULL, 
				CreateLayoutForStyleAndRunInfo_err, err = memFullErr );
				
			seperateRunLengths = (UniCharCount *) malloc( sizeof( UniCharCount ) *
				numberOfRuns );
			require_action( seperateRunLengths != NULL, 
				CreateLayoutForStyleAndRunInfo_err, err = memFullErr );
				
			// loop through and assign the runs to the seperate arrays. I'm not
			// sure that this is the best way to do this. Perhaps it's best to
			// simply create the layout and assign the style runs to it individually.
			for ( i = 0; i < numberOfRuns; i++ )
			{
				seperateStyles[i] = styleArray[styleRunArray[i].styleObjectIndex];
				seperateRunLengths[i] = styleRunArray[i].runLength;
			}
			
		}
		
	}

	// first of all, create the layout with the text information passed in
	err = ATSUCreateTextLayoutWithTextPtr( stringPtr, kATSUFromTextBeginning,
		kATSUToTextEnd, stringLen, numberOfRuns, seperateRunLengths, seperateStyles,
		&newLayout );
	require_noerr( err, CreateLayoutForStyleAndRunInfo_err );
	
	// if we've got a layout, then assign the CGContext to it
	attrTag = kATSUCGContextTag;
	attrSize = sizeof( CGContextRef );
	attrPtr = &cgContext;
	
	err = ATSUSetLayoutControls( newLayout, 1, &attrTag, &attrSize, &attrPtr );
	require_noerr( err, CreateLayoutForStyleAndRunInfoLayout_err );
	
	// set the Y position before we draw
	err = SetYPositionForLineHeight( newLayout, currentYPos );
	require_noerr( err, CreateLayoutForStyleAndRunInfoLayout_err );
	
	// do some drawin'
	err = ATSUDrawText( newLayout, kATSUFromTextBeginning, kATSUToTextEnd,
		currentXPos, *currentYPos );
	require_noerr( err, CreateLayoutForStyleAndRunInfoLayout_err );
	
CreateLayoutForStyleAndRunInfoLayout_err:

	ATSUDisposeTextLayout( newLayout );
	
CreateLayoutForStyleAndRunInfo_err:

	if ( ( styleRunArray != NULL ) && ( styleArray != NULL ) ) 
	{
		if ( seperateStyles != NULL )
		{
			free( seperateStyles );
		}
		
		if ( seperateRunLengths != NULL );
		{
			free( seperateRunLengths );
		}
		
	}
	
	return err;

}