ATSUFontID coretext_font_to_atsufontid(void *p_font) { bool t_success; t_success = true; CTFontRef t_ctfont; t_ctfont = NULL; if (t_success) { t_ctfont = (CTFontRef)p_font; t_success = t_ctfont != NULL; } char t_name[256]; if (t_success) { CFStringRef t_cfname; t_cfname = CTFontCopyPostScriptName(t_ctfont); t_success = t_cfname != NULL && CFStringGetCString(t_cfname, t_name, 256, kCFStringEncodingMacRoman); if (t_cfname != NULL) CFRelease(t_cfname); } ATSUFontID t_font_id; t_font_id = 0; if (t_success) { uint32_t t_name_length; t_name_length = MCCStringLength(t_name); t_success = ATSUFindFontFromName(t_name, t_name_length, kFontPostscriptName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr; } return t_font_id; }
bool MCField::macmatchfontname(const char *p_font_name, char p_derived_font_name[]) { ATSUFontID t_font_id; if (ATSUFindFontFromName(p_font_name, strlen(p_font_name), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr || ATSUFindFontFromName(p_font_name, strlen(p_font_name), kFontUniqueName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr || ATSUFindFontFromName(p_font_name, strlen(p_font_name), kFontFamilyName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr || ATSUFindFontFromName(p_font_name, strlen(p_font_name), kFontNoName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr) { // Fetch the style name char t_style_name[64]; ByteCount t_style_name_length; t_style_name_length = 0; ATSUFindFontName(t_font_id, kFontStyleName, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, 63, t_style_name, &t_style_name_length, NULL); t_style_name[t_style_name_length] = '\0'; // Fetch the full name char t_full_name[256]; ByteCount t_full_name_length; t_full_name_length = 0; ATSUFindFontName(t_font_id, kFontFullName, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, 255, t_full_name, &t_full_name_length, NULL); t_full_name[t_full_name_length] = '\0'; // MW-2011-09-02: Make sure we don't do anything at all if style is regular // (output name should be fullname!) if (MCCStringEqualCaseless(t_style_name, "Regular")) p_font_name = p_font_name; // Do nothing else if (MCCStringEndsWithCaseless(t_full_name, "Bold Italic")) t_full_name[t_full_name_length - 12] = '\0'; else if (MCCStringEndsWithCaseless(t_full_name, "Bold")) t_full_name[t_full_name_length - 5] = '\0'; else if (MCCStringEndsWithCaseless(t_full_name, "Italic")) t_full_name[t_full_name_length - 7] = '\0'; strcpy(p_derived_font_name, t_full_name); return true; } return false; }
static OSStatus CreateStyleObjectWithFontName( char *fontName, Fixed *fontSize, RGBColor *fontColor, ATSUStyle *newStyle ) { OSStatus err; ATSUFontID fontID; ATSUAttributeTag tags[3]; ByteCount tagValueSizes[3]; ATSUAttributeValuePtr tagValuePtrs[3]; // try to find the font based on the font name err = ATSUFindFontFromName( fontName, strlen( fontName ), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &fontID ); require_noerr( err, CreateStyleObjectWithFontName_err ); // first, create the new style object err = ATSUCreateStyle( newStyle ); // set up the three tags that we are setting in the style tags[0] = kATSUFontTag; tagValueSizes[0] = sizeof( ATSUFontID ); tagValuePtrs[0] = &fontID; tags[1] = kATSUSizeTag; tagValueSizes[1] = sizeof( Fixed ); tagValuePtrs[1] = fontSize; tags[2] = kATSUColorTag; tagValueSizes[2] = sizeof( RGBColor ); tagValuePtrs[2] = fontColor; // set the attributes in the style object err = ATSUSetAttributes( *newStyle, 3, tags, tagValueSizes, tagValuePtrs ); check_noerr( err ); // if there was an error, then dispose of the style if ( err != noErr ) { ATSUDisposeStyle( *newStyle ); } CreateStyleObjectWithFontName_err: return err; }
OSStatus CreateATSUIStyleFromFontFullNameAndSize (const char *fontName, int fontSize, ATSUStyle *theStyle) { OSStatus err; ATSUStyle localStyle; ATSUFontID atsuFont; Fixed atsuSize; ATSUAttributeTag theTags[] = { kATSUFontTag, kATSUSizeTag }; ByteCount theSizes[] = { sizeof(ATSUFontID), sizeof(Fixed) }; ATSUAttributeValuePtr theValues[] = { NULL, NULL }; atsuFont = 0; atsuSize = FixRatio(fontSize, 1); localStyle = NULL; theValues[0] = &atsuFont; theValues[1] = &atsuSize; err = ATSUFindFontFromName(fontName, strlen(fontName), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &atsuFont); if (err == noErr) { err = ATSUCreateStyle(&localStyle); if (err == noErr) { err = ATSUSetAttributes(localStyle, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues); if (err == noErr) { *theStyle = localStyle; return (noErr); } } } if (localStyle != NULL) err = ATSUDisposeStyle(localStyle); return (err); }
// 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); }
void PlatformFont::enumeratePlatformFonts( Vector< StringTableEntry >& fonts, UTF16* fontFamily ) { if( fontFamily ) { // Determine the font ID from the family name. ATSUFontID fontID; if( ATSUFindFontFromName( fontFamily, dStrlen( fontFamily ) * 2, kFontFamilyName, kFontMicrosoftPlatform, kFontNoScriptCode, kFontNoLanguageCode, &fontID ) != kATSUInvalidFontErr ) { // Get the number of fonts in the family. ItemCount numFonts; ATSUCountFontNames( fontID, &numFonts ); // Read out font names. U32 bufferSize = 512; char* buffer = ( char* ) dMalloc( bufferSize ); for( U32 i = 0; i < numFonts; ++ i ) { for( U32 n = 0; n < 2; ++ n ) { ByteCount actualNameLength; FontNameCode fontNameCode; FontPlatformCode fontPlatformCode; FontScriptCode fontScriptCode; FontLanguageCode fontLanguageCode; if( ATSUGetIndFontName( fontID, i, bufferSize - 2, buffer, &actualNameLength, &fontNameCode, &fontPlatformCode, &fontScriptCode, &fontLanguageCode ) == noErr ) { *( ( UTF16* ) &buffer[ actualNameLength ] ) = '\0'; char* utf8 = convertUTF16toUTF8( ( UTF16* ) buffer ); fonts.push_back( StringTable->insert( utf8 ) ); delete [] utf8; break; } // Allocate larger buffer. bufferSize = actualNameLength + 2; buffer = ( char* ) dRealloc( buffer, bufferSize ); } } dFree( buffer ); } } else { // Get the number of installed fonts. ItemCount numFonts; ATSUFontCount( &numFonts ); // Get all the font IDs. ATSUFontID* fontIDs = new ATSUFontID[ numFonts ]; if( ATSUGetFontIDs( fontIDs, numFonts, &numFonts ) == noErr ) { U32 bufferSize = 512; char* buffer = ( char* ) dMalloc( bufferSize ); // Read all family names. for( U32 i = 0; i < numFonts; ++ i ) { for( U32 n = 0; n < 2; ++ n ) { ByteCount actualNameLength; ItemCount fontIndex; OSStatus result = ATSUFindFontName( fontIDs[ i ], kFontFamilyName, kFontMicrosoftPlatform, kFontNoScriptCode, kFontNoLanguageCode, bufferSize - 2, buffer, &actualNameLength, &fontIndex ); if( result == kATSUNoFontNameErr ) break; else if( result == noErr ) { *( ( UTF16* ) &buffer[ actualNameLength ] ) = '\0'; char* utf8 = convertUTF16toUTF8( ( UTF16* ) buffer ); StringTableEntry name = StringTable->insert( utf8 ); delete [] utf8; // Avoid duplicates. bool duplicate = false; for( U32 i = 0, num = fonts.size(); i < num; ++ i ) if( fonts[ i ] == name ) { duplicate = true; break; } if( !duplicate ) fonts.push_back( name ); break; } // Allocate larger buffer. bufferSize = actualNameLength + 2; buffer = ( char* ) dRealloc( buffer, bufferSize ); } } dFree( buffer ); } delete [] fontIDs; } }
void IGraphicsCarbon::CreateTextEntry(IControl* pControl, IText* pText, IRECT* pTextRect, const char* pString, IParam* pParam) { if (!pControl || mTextEntryView || !mIsComposited) return; // Only composited carbon supports text entry WindowRef window = mWindow; TXNFrameOptions txnFrameOptions = kTXNMonostyledTextMask | kTXNDisableDragAndDropMask | kTXNSingleLineOnlyMask; TXNObject txnObject = 0; TXNFrameID frameID = 0; TXNObjectRefcon txnObjectRefCon = 0; HIRect rct; HIViewGetFrame(this->mView, &rct); HIViewRef contentView; HIViewFindByID (HIViewGetRoot(this->mWindow), kHIViewWindowContentID, &contentView); HIViewConvertRect(&rct, HIViewGetSuperview((HIViewRef)this->mView), contentView); Rect rect = { rct.origin.y + pTextRect->T, rct.origin.x + pTextRect->L, rct.origin.y + pTextRect->B + 1, rct.origin.x + pTextRect->R + 1 }; if (TXNNewObject(NULL, window, &rect, txnFrameOptions, kTXNTextEditStyleFrameType, kTXNSingleStylePerTextDocumentResType, kTXNMacOSEncoding, &txnObject, &frameID, txnObjectRefCon) == noErr) { TXNSetFrameBounds(txnObject, rect.top, rect.left, rect.bottom, rect.right, frameID); mTextEntryView = txnObject; // Set the text to display by defualt TXNSetData(mTextEntryView, kTXNTextData, pString, strlen(pString)/*+1*/, kTXNStartOffset, kTXNEndOffset); // center aligned text has problems with uneven string lengths RGBColor tc; tc.red = pText->mTextEntryFGColor.R * 257; tc.green = pText->mTextEntryFGColor.G * 257; tc.blue = pText->mTextEntryFGColor.B * 257; TXNBackground bg; bg.bgType = kTXNBackgroundTypeRGB; bg.bg.color.red = pText->mTextEntryBGColor.R * 257; bg.bg.color.green = pText->mTextEntryBGColor.G * 257; bg.bg.color.blue = pText->mTextEntryBGColor.B * 257; TXNSetBackground(mTextEntryView, &bg); // Set justification SInt16 justification; Fract flushness; switch ( pText->mAlign ) { case IText::kAlignCenter: justification = kTXNCenter; // seems to be buggy wrt dragging and alignement with uneven string lengths flushness = kATSUCenterAlignment; break; case IText::kAlignFar: justification = kTXNFlushRight; flushness = kATSUEndAlignment; break; case IText::kAlignNear: default: justification = kTXNFlushLeft; flushness = kATSUStartAlignment; break; } TXNControlTag controlTag[1]; TXNControlData controlData[1]; controlTag[0] = kTXNJustificationTag; controlData[0].sValue = justification; TXNSetTXNObjectControls(mTextEntryView, false, 1, controlTag, controlData); ATSUFontID fontid = kATSUInvalidFontID; if (pText->mFont && pText->mFont[0]) { ATSUFindFontFromName(pText->mFont, strlen(pText->mFont), kFontFullName /* kFontFamilyName? */ , (FontPlatformCode)kFontNoPlatform, kFontNoScriptCode, kFontNoLanguageCode, &fontid); } // font (NOT working) TXNTypeAttributes attributes[3]; attributes[0].tag = kATSUFontTag; attributes[0].size = sizeof(ATSUFontID); attributes[0].data.dataPtr = &fontid; // size attributes[1].tag = kTXNQDFontSizeAttribute; attributes[1].size = kTXNFontSizeAttributeSize; attributes[1].data.dataValue = pText->mSize << 16; // color attributes[2].tag = kTXNQDFontColorAttribute; attributes[2].size = kTXNQDFontColorAttributeSize; attributes[2].data.dataPtr = &tc; // Finally set the attributes TXNSetTypeAttributes(mTextEntryView, 3, attributes, kTXNStartOffset, kTXNEndOffset); // Ensure focus remains consistent SetUserFocusWindow(window); AdvanceKeyboardFocus(window); // Set the focus to the edit window TXNFocus(txnObject, true); TXNSelectAll(mTextEntryView); TXNShowSelection(mTextEntryView, true); // The event types const static EventTypeSpec eventTypes[] = { { kEventClassMouse, kEventMouseMoved }, { kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseUp }, { kEventClassMouse, kEventMouseWheelMoved }, { kEventClassWindow, kEventWindowClosed }, { kEventClassWindow, kEventWindowDeactivated }, { kEventClassWindow, kEventWindowFocusRelinquish }, { kEventClassKeyboard, kEventRawKeyDown }, { kEventClassKeyboard, kEventRawKeyRepeat } }; // Install the event handler InstallWindowEventHandler(window, TextEntryHandler, GetEventTypeCount(eventTypes), eventTypes, this, &mTextEntryHandler); mEdControl = pControl; mEdParam = pParam; mTextEntryRect = *pTextRect; } }
static cairo_status_t _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options, cairo_scaled_font_t **font_out) { cairo_atsui_font_t *font = NULL; ATSUStyle style; ATSUFontID fontID; OSStatus err; Boolean isItalic, isBold; cairo_matrix_t scale; const char *family = toy_face->family; err = ATSUCreateStyle(&style); switch (toy_face->weight) { case CAIRO_FONT_WEIGHT_BOLD: isBold = true; break; case CAIRO_FONT_WEIGHT_NORMAL: default: isBold = false; break; } switch (toy_face->slant) { case CAIRO_FONT_SLANT_ITALIC: isItalic = true; break; case CAIRO_FONT_SLANT_OBLIQUE: isItalic = false; break; case CAIRO_FONT_SLANT_NORMAL: default: isItalic = false; break; } err = ATSUFindFontFromName(family, strlen(family), kFontFamilyName, kFontNoPlatformCode, kFontRomanScript, kFontNoLanguageCode, &fontID); if (err != noErr) { // couldn't get the font - remap css names and try again if (!strcmp(family, "serif")) family = "Times"; else if (!strcmp(family, "sans-serif")) family = "Helvetica"; else if (!strcmp(family, "cursive")) family = "Apple Chancery"; else if (!strcmp(family, "fantasy")) family = "Gadget"; else if (!strcmp(family, "monospace")) family = "Courier"; else // anything else - return error instead? family = "Courier"; err = ATSUFindFontFromName(family, strlen(family), kFontFamilyName, kFontNoPlatformCode, kFontRomanScript, kFontNoLanguageCode, &fontID); } ATSUAttributeTag styleTags[] = { kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag }; ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID }; ByteCount styleSizes[] = { sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) }; err = ATSUSetAttributes(style, sizeof(styleTags) / sizeof(styleTags[0]), styleTags, styleSizes, styleValues); font = malloc(sizeof(cairo_atsui_font_t)); _cairo_scaled_font_init(&font->base, toy_face, font_matrix, ctm, options, &cairo_atsui_scaled_font_backend); cairo_matrix_multiply(&scale, font_matrix, ctm); font->style = CreateSizedCopyOfStyle(style, &scale); Fixed theSize = FloatToFixed(1.0); const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag }; const ByteCount theFontStyleSizes[] = { sizeof(Fixed) }; ATSUAttributeValuePtr theFontStyleValues[] = { &theSize }; err = ATSUSetAttributes(style, sizeof(theFontStyleTags) / sizeof(ATSUAttributeTag), theFontStyleTags, theFontStyleSizes, theFontStyleValues); font->unscaled_style = style; font->fontID = fontID; font->scale = scale; *font_out = &font->base; return CAIRO_STATUS_SUCCESS; }