Example #1
0
MacCarbFont::~MacCarbFont()
{
   // apple docs say we should dispose the layout first.
   ATSUDisposeTextLayout(mLayout);
   ATSUDisposeStyle(mStyle);
   CGColorSpaceRelease(mColorSpace);
}
static
void CloseDemoWindow(
	WindowRef windowRef )
{
	WindowListItem 		*currentItem = gWindowList;
	WindowListItem 		*previousItem = NULL;
	DrawContextStruct	*windowContext;

	// search through the window list, looking for the windowRef
	while( currentItem != NULL )
	{
		// check to see if the current item is the one that we're looking for
		if ( currentItem->windowRef == windowRef )
		{
			// we've got a match, so set the previous item's next item pointer
			// to the current item's next item pointer
			if ( previousItem != NULL )
			{
				previousItem->nextItem = currentItem->nextItem;
			}
			else
			{
				gWindowList = currentItem->nextItem;
			}
			
			// free up the current item
			free( currentItem );
			break;
		}
		
		// move on to the next item
		previousItem = currentItem;
		currentItem = currentItem->nextItem;
	}
	
	// get the draw context struct from the window's refCon
	windowContext = (DrawContextStruct *) GetWRefCon( windowRef );
	
	// if we have a context, then we need to make sure to dispose of everything
	// that's in the context before we free the context.
	if ( windowContext != NULL )
	{		
		// dispose of the text layout object
		if ( windowContext->layoutObject != NULL ) 
		{
			verify_noerr( 
				ATSUDisposeTextLayout( windowContext->layoutObject ) );
		}
		
		// free the text buffer, if there is one
		if( windowContext->textBuffer != NULL )
		{
			free( windowContext->textBuffer );
		}
		
		// free the context itself
		free( windowContext );
	}
}
Example #3
0
QFontEngineMacMulti::~QFontEngineMacMulti()
{
    ATSUDisposeTextLayout(textLayout);
    ATSUDisposeStyle(style);

    for (int i = 0; i < engines.count(); ++i) {
        QFontEngineMac *fe = const_cast<QFontEngineMac *>(static_cast<const QFontEngineMac *>(engines.at(i)));
        fe->multiEngine = 0;
        if (!fe->ref.deref())
            delete fe;
    }
    engines.clear();
}
extern
OSStatus InvalidateAndRedrawWindows( void )
{
	OSStatus			err = noErr;
	WindowListItem 		*currentItem = gWindowList;
	DrawContextStruct	*windowContext;
	
	// search through the window list
	while( currentItem != NULL )
	{
		// get the draw context struct from the window's refCon
		windowContext = (DrawContextStruct *) GetWRefCon( 
			currentItem->windowRef );
		
		// make sure that we have a context
		if ( windowContext != NULL )
		{	
			// if we have a text layout, then make sure that we get rid of it.
			// This really is invalidation!
			if ( windowContext->layoutObject != NULL )
			{
				err = ATSUDisposeTextLayout( windowContext->layoutObject );
				require_noerr( err, InvalidateAndRedrawWindows_err );
				
				windowContext->layoutObject = NULL;
			}
		
			// nifty. Now, we need to redraw the window
			HIViewSetNeedsDisplay( ((DrawContextStruct*)GetWRefCon(currentItem->windowRef))->viewRef, true);
		}
		
		// grab the next context
		currentItem = currentItem->nextItem;
	}

InvalidateAndRedrawWindows_err:

	return err;

}
Example #5
0
// This example is almost identical to the helloworld example, except that
// in this case, there are two styles instead of just one. ATSUSetRunStyle
// is used to apply a style to different parts of the text.
//
void DrawMultipleStylesContents(WindowRef window)
{
	CFStringRef					string;
	UniChar						*text;
	UniCharCount				length;
    UniCharArrayOffset			currentStart, currentEnd;
	ATSUStyle					style1, style2;
	ATSUTextLayout				layout;
	ATSUFontID					font;
	Fixed						pointSize;
    ATSUAttributeTag			tags[2];
    ByteCount					sizes[2];
    ATSUAttributeValuePtr		values[2];
	Fixed						lineWidth, ascent, descent;
	CGContextRef				cgContext;
	float						x, y, cgY, windowHeight;
    ItemCount					numSoftBreaks;
    UniCharArrayOffset			*theSoftBreaks;
    int							i;
    GrafPtr						port, savedPort;
	Rect						portBounds;

    // Set up the graphics port
	port = GetWindowPort(window);
    GetPort(&savedPort);
    SetPort(port);
    GetPortBounds(port, &portBounds);
    EraseRect(&portBounds);

	// Create a style object. This is one of two objects necessary to draw using ATSUI.
	// (The layout is the other.)
	verify_noerr( ATSUCreateStyle(&style1) );

    // Look up the font we are going to use, and set it in the style object, using
	// the aforementioned "triple" (tag, size, value) semantics. This is how almost
	// all settings in ATSUI are applied.
	verify_noerr( ATSUFindFontFromName(kMultipleStylesFontName, strlen(kMultipleStylesFontName), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &font) );
    tags[0] = kATSUFontTag;
    sizes[0] = sizeof(ATSUFontID);
    values[0] = &font;
    verify_noerr( ATSUSetAttributes(style1, 1, tags, sizes, values) );

    // Set the point size, also using a triple. You can actually set multiple triples at once,
	// since the tag, size, and value parameters are arrays. Other examples do this, such as
	// the vertical text example.
	// 
	pointSize = Long2Fix(kMultipleStylesFontSize);
	tags[0] = kATSUSizeTag;
    sizes[0] = sizeof(Fixed);
    values[0] = &pointSize;
    verify_noerr( ATSUSetAttributes(style1, 1, tags, sizes, values) );
	
	// Now we create the second of two objects necessary to draw text using ATSUI, the layout.
	// You can specify a pointer to the text buffer at layout creation time, or later using
	// the routine ATSUSetTextPointerLocation(). Below, we do it after layout creation time.
	verify_noerr( ATSUCreateTextLayout(&layout) );

	// Before assigning text to the layout, we must first convert the string we plan to draw
	// from a CFStringRef into an array of UniChar.
	string = CFStringCreateWithCString(NULL, "In this example, various parts of the text have different styles applied. The same style is used more than once.", kCFStringEncodingASCII);

    // Extract the raw Unicode from the CFString, then dispose of the CFString
    length = CFStringGetLength(string);
    text = (UniChar *)malloc(length * sizeof(UniChar));
    CFStringGetCharacters(string, CFRangeMake(0, length), text);
	CFRelease(string);

    // Attach the resulting UTF-16 Unicode text to the layout
    verify_noerr( ATSUSetTextPointerLocation(layout, text, kATSUFromTextBeginning, kATSUToTextEnd, length) );
	
	// Now we tie the two necessary objects, the layout and the style, together
	verify_noerr( ATSUSetRunStyle(layout, style1, kATSUFromTextBeginning, kATSUToTextEnd) );

	// Now, for this example we create a second style, and assign it to various runs within
	// the text. For our example, the run offsets are hard-coded for simplicity's sake. In
	// a real application, style runs are often assigned from external sources, such as user
	// selection.
	verify_noerr( ATSUCreateAndCopyStyle(style1, &style2) );

	// Change the font for the second style
	verify_noerr( ATSUFindFontFromName(kMultipleStylesFontName2, strlen(kMultipleStylesFontName2), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &font) );
    tags[0] = kATSUFontTag;
    sizes[0] = sizeof(ATSUFontID);
    values[0] = &font;
    verify_noerr( ATSUSetAttributes(style2, 1, tags, sizes, values) );

	// Apply the new style to the text in various places
	verify_noerr( ATSUSetRunStyle(layout, style2, 8, 7) ); // The word "example"
	verify_noerr( ATSUSetRunStyle(layout, style2, 65, 7) ); // The word "applied"
	verify_noerr( ATSUSetRunStyle(layout, style2, 83, 5) ); // The word "style"
	verify_noerr( ATSUSetRunStyle(layout, style2, 107, 4) ); // The word "once"

	// In this example, we are breaking text into lines.
	// Therefore, we need to know the width of the line.
    lineWidth = X2Fix(portBounds.right - portBounds.left - 2.0*kMultipleStylesMargin);
    tags[0] = kATSULineWidthTag;
    sizes[0] = sizeof(Fixed);
    values[0] = &lineWidth;
	verify_noerr( ATSUSetLayoutControls(layout, 1, tags, sizes, values) );

	// Prepare the CGContext for drawing
	QDBeginCGContext(port, &cgContext);
	tags[0] = kATSUCGContextTag;
	sizes[0] = sizeof(CGContextRef);
	values[0] = &cgContext;
	verify_noerr( ATSUSetLayoutControls(layout, 1, tags, sizes, values) );
	
	// Prepare the coordinates for drawing. In our example, "x" and "y" are the coordinates
	// in QD space. "cgY" contains the y coordinate in CG space.
	//
	windowHeight = portBounds.bottom - portBounds.top;
	x = kMultipleStylesMargin; // leave a small left margin
	y = kMultipleStylesMargin; // leave a small top margin
	cgY = windowHeight - y; // Subtract the y coordinate from the height of the
							// window to get the coordinate in CG-aware space.

	// Break the text into lines
	verify_noerr( ATSUBatchBreakLines(layout, kATSUFromTextBeginning, length, lineWidth, &numSoftBreaks) );
    verify_noerr( ATSUGetSoftLineBreaks(layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, NULL, &numSoftBreaks) );
    theSoftBreaks = (UniCharArrayOffset *) malloc(numSoftBreaks * sizeof(UniCharArrayOffset));
    verify_noerr( ATSUGetSoftLineBreaks(layout, kATSUFromTextBeginning, kATSUToTextEnd, numSoftBreaks, theSoftBreaks, &numSoftBreaks) );
	
    // Loop over all the lines and draw them
    currentStart = 0;
    for (i=0; i <= numSoftBreaks; i++) {
        currentEnd = ((numSoftBreaks > 0 ) && (numSoftBreaks > i)) ? theSoftBreaks[i] : length;

        // This is the height of a line, the ascent and descent. Getting the values this way is the preferred method.
		ATSUGetLineControl(layout, currentStart, kATSULineAscentTag, sizeof(ATSUTextMeasurement), &ascent, NULL);
        ATSUGetLineControl(layout, currentStart, kATSULineDescentTag, sizeof(ATSUTextMeasurement), &descent, NULL);

        // Make room for the area above the baseline
		y += Fix2X(ascent);
		cgY = windowHeight - y;

		// Draw the text
        verify_noerr( ATSUDrawText(layout, currentStart, currentEnd - currentStart, X2Fix(x), X2Fix(cgY)) );

		// Make room for the area beloww the baseline
        y += Fix2X(descent);
		
		// Prepare for next line
        currentStart = currentEnd;
    }

	// This is a one-shot window, so we are now ready to dispose of all our objects.
	// Normally, we would want to keep everything around in case we needed to redraw or change
	// the text at some point.
	
    // Tear down the CGContext
	CGContextFlush(cgContext);
	QDEndCGContext(port, &cgContext);

	// Deallocate string storage
	free(text);

	// Layout and styles also need to be disposed
	verify_noerr( ATSUDisposeStyle(style1) );
	verify_noerr( ATSUDisposeStyle(style2) );
	verify_noerr( ATSUDisposeTextLayout(layout) );

    // Restore the graphics port
    SetPort(savedPort);
}
Example #6
0
PR_CALLBACK PRIntn ATSUILayoutCache::FreeHashEntries(PLHashEntry *he, PRIntn italic, void *arg)
{
	delete (atsuiLayoutCacheKey*)he->key;
	ATSUDisposeTextLayout((ATSUTextLayout)he->value);
	return HT_ENUMERATE_REMOVE;
}
Example #7
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;
}
Example #8
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;
}
Example #9
0
static cairo_status_t
_cairo_atsui_font_text_to_glyphs(void		*abstract_font,
                                 const char     *utf8,
                                 cairo_glyph_t **glyphs,
				 int		*num_glyphs)
{
    cairo_atsui_font_t *font = abstract_font;
    size_t i;
    OSStatus err;
    ATSUTextLayout textLayout;
    ATSLayoutRecord *layoutRecords;
    ItemCount glyphCount;
    int charCount;
    UniChar *theText;
    cairo_status_t status;

    // liberal estimate of size
    charCount = strlen(utf8);

    if (charCount == 0) {
       *glyphs = NULL;
       *num_glyphs = 0;
       return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_utf8_to_utf16 (utf8, -1, &theText, &charCount);
    if (status)
	return status;

    err = ATSUCreateTextLayout(&textLayout);

    err = ATSUSetTextPointerLocation(textLayout,
                                     theText, 0, charCount, charCount);


    // Set the style for all of the text
    err = ATSUSetRunStyle(textLayout,
                          font->unscaled_style, kATSUFromTextBeginning, kATSUToTextEnd);

    // Get the glyphs from the text layout object
    err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
                                                        0,
                                                        kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
                                                        (void *)
                                                        &layoutRecords,
                                                        &glyphCount);

    *num_glyphs = glyphCount - 1;


    *glyphs =
        (cairo_glyph_t *) malloc(*num_glyphs * (sizeof(cairo_glyph_t)));
    if (*glyphs == NULL) {
        return CAIRO_STATUS_NO_MEMORY;
    }

    for (i = 0; i < *num_glyphs; i++) {
        (*glyphs)[i].index = layoutRecords[i].glyphID;
        (*glyphs)[i].x = FixedToFloat(layoutRecords[i].realPos);
        (*glyphs)[i].y = 0;
    }


    free(theText);

    ATSUDirectReleaseLayoutDataArrayPtr(NULL,
                                        kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
                                        (void *) &layoutRecords);

    ATSUDisposeTextLayout(textLayout);

    return CAIRO_STATUS_SUCCESS;
}
Example #10
0
OSStatus ATSUDisposeTextLayout_wrap(ATSUTextLayout lay) {
  void* oText;
  OSStatus e = ATSUGetTextLocation(lay, &oText, NULL, NULL, NULL, NULL);
  if (!e)  FreeHeap(oText);
  return ATSUDisposeTextLayout(lay);
}
Example #11
0
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;

}