static char *get_font_file(CTFontDescriptorRef fontd) { CFURLRef url = CTFontDescriptorCopyAttribute(fontd, kCTFontURLAttribute); CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); char *buffer = cfstr2buf(path); SAFE_CFRelease(path); SAFE_CFRelease(url); return buffer; }
static void get_name(CTFontDescriptorRef fontd, CFStringRef attr, char **array, int *idx) { CFStringRef name = CTFontDescriptorCopyAttribute(fontd, attr); if (name) { array[*idx] = cfstr2buf(name); SAFE_CFRelease(name); *idx += 1; } }
CFIndex addCTFontDescriptor(CTFontDescriptorRef fd, JNIEnv *env, jobjectArray result, CFIndex index) { if (fd) { CFStringRef name = CTFontDescriptorCopyAttribute(fd, kCTFontDisplayNameAttribute); CFStringRef family = CTFontDescriptorCopyAttribute(fd, kCTFontFamilyNameAttribute); CFURLRef url = CTFontDescriptorCopyAttribute(fd, kCTFontURLAttribute); CFStringRef file = url ? CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle) : NULL; if (name && family && file) { jstring jname = createJavaString(env, name); jstring jfamily = createJavaString(env, family); jstring jfile = createJavaString(env, file); (*env)->SetObjectArrayElement(env, result, index++, jname); (*env)->SetObjectArrayElement(env, result, index++, jfamily); (*env)->SetObjectArrayElement(env, result, index++, jfile); } if (name) CFRelease(name); if (family) CFRelease(family); if (url) CFRelease(url); if (file) CFRelease(file); } return index; }
static bool check_postscript(void *priv) { CTFontDescriptorRef fontd = priv; CFNumberRef cfformat = CTFontDescriptorCopyAttribute(fontd, kCTFontFormatAttribute); int format; if (!CFNumberGetValue(cfformat, kCFNumberIntType, &format)) return false; SAFE_CFRelease(cfformat); return format == kCTFontFormatOpenTypePostScript || format == kCTFontFormatPostScript; }
static void process_descriptors(ASS_FontProvider *provider, CFArrayRef fontsd) { ASS_FontProviderMetaData meta; char *families[1]; char *identifiers[1]; char *fullnames[1]; if (!fontsd) return; for (int i = 0; i < CFArrayGetCount(fontsd); i++) { CTFontDescriptorRef fontd = CFArrayGetValueAtIndex(fontsd, i); int index = -1; char *path = get_font_file(fontd); if (strcmp("", path) == 0) { // skip the font if the URL field in the font descriptor is empty free(path); continue; } memset(&meta, 0, sizeof(meta)); get_font_traits(fontd, &meta); get_name(fontd, kCTFontFamilyNameAttribute, families, &meta.n_family); meta.families = families; int zero = 0; get_name(fontd, kCTFontNameAttribute, identifiers, &zero); get_name(fontd, kCTFontDisplayNameAttribute, fullnames, &meta.n_fullname); meta.fullnames = fullnames; CFCharacterSetRef chset = CTFontDescriptorCopyAttribute(fontd, kCTFontCharacterSetAttribute); ass_font_provider_add_font(provider, &meta, path, index, identifiers[0], (void*)chset); for (int j = 0; j < meta.n_family; j++) free(meta.families[j]); for (int j = 0; j < meta.n_fullname; j++) free(meta.fullnames[j]); free(identifiers[0]); free(path); } }
static bool check_glyph(void *priv, uint32_t code) { CTFontDescriptorRef fontd = priv; CFCharacterSetRef set = CTFontDescriptorCopyAttribute(fontd, kCTFontCharacterSetAttribute); if (!set) return true; if (code == 0) return true; bool result = CFCharacterSetIsLongCharacterMember(set, code); SAFE_CFRelease(set); return result; }
static string osxFontPathByName( string fontname ){ CFStringRef targetName = CFStringCreateWithCString(NULL, fontname.c_str(), kCFStringEncodingUTF8); CTFontDescriptorRef targetDescriptor = CTFontDescriptorCreateWithNameAndSize(targetName, 0.0); CFURLRef targetURL = (CFURLRef) CTFontDescriptorCopyAttribute(targetDescriptor, kCTFontURLAttribute); string fontPath = ""; if(targetURL) { UInt8 buffer[PATH_MAX]; CFURLGetFileSystemRepresentation(targetURL, true, buffer, PATH_MAX); fontPath = string((char *)buffer); CFRelease(targetURL); } CFRelease(targetName); CFRelease(targetDescriptor); return fontPath; }
bool coretext_get_font_names(MCListRef &r_names) { CTFontCollectionRef t_fonts; t_fonts = CTFontCollectionCreateFromAvailableFonts(NULL); CFArrayRef t_descriptors; t_descriptors = CTFontCollectionCreateMatchingFontDescriptors(t_fonts); MCAutoListRef t_names; MCListCreateMutable('\n', &t_names); char t_cstring_font_name[256]; bool t_success; t_success = true; for(CFIndex i = 0; t_success && i < CFArrayGetCount(t_descriptors); i++) { CTFontDescriptorRef t_font; t_font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(t_descriptors, i); CFStringRef t_font_name; t_font_name = (CFStringRef)CTFontDescriptorCopyAttribute(t_font, kCTFontDisplayNameAttribute); if (t_font_name != NULL && CFStringGetCString(t_font_name, t_cstring_font_name, 256, kCFStringEncodingMacRoman) && t_cstring_font_name[0] != '%' && t_cstring_font_name[0] != '.') t_success = MCListAppendCString(*t_names, t_cstring_font_name); if (t_font_name != NULL) CFRelease(t_font_name); } if (t_descriptors != NULL) CFRelease(t_descriptors); if (t_fonts != NULL) CFRelease(t_fonts); if (t_success) t_success = MCListCopy(*t_names, r_names); return t_success; }
static PangoCoverage * ct_font_descriptor_get_coverage (CTFontDescriptorRef desc) { CFCharacterSetRef charset; CFIndex i, length; CFDataRef bitmap; const UInt8 *ptr; PangoCoverage *coverage; coverage = pango_coverage_new (); charset = CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute); if (!charset) /* Return an empty coverage */ return coverage; bitmap = CFCharacterSetCreateBitmapRepresentation (kCFAllocatorDefault, charset); /* We only handle the BMP plane */ length = MIN (CFDataGetLength (bitmap), 8192); ptr = CFDataGetBytePtr (bitmap); /* FIXME: can and should this be done more efficiently? */ for (i = 0; i < length; i++) { int j; for (j = 0; j < 8; j++) pango_coverage_set (coverage, i * 8 + j, ((ptr[i] & (1 << j)) == (1 << j)) ? PANGO_COVERAGE_EXACT : PANGO_COVERAGE_NONE); } CFRelease (bitmap); CFRelease (charset); return coverage; }
void loadfonts(void) { int i, n; CTFontCollectionRef allc; CFArrayRef array; CFStringRef s; CTFontDescriptorRef f; allc = CTFontCollectionCreateFromAvailableFonts(0); array = CTFontCollectionCreateMatchingFontDescriptors(allc); n = CFArrayGetCount(array); xfont = emalloc9p(n*sizeof xfont[0]); for(i=0; i<n; i++) { f = (void*)CFArrayGetValueAtIndex(array, i); if(f == nil) continue; s = CTFontDescriptorCopyAttribute(f, kCTFontNameAttribute); xfont[nxfont].name = mac2c(s); CFRelease(s); nxfont++; } }
void XMacFontMgr::BuildFontList() { fFontFamilies.SetCount(0); //fFontNames.SetCount(0); fFontNames.clear(); /* FMFontFamilyIterator iterator; OSErr error = ::FMCreateFontFamilyIterator(NULL, NULL, kFMDefaultOptions, &iterator); if (error == noErr) { FMFontFamily family; assert(sizeof(FMFontFamily) == sizeof(sWORD)); while (::FMGetNextFontFamily(&iterator, &family) == noErr) { Str255 spFontName; if (testAssert(::FMGetFontFamilyName(family, spFontName) == noErr)) { VStr255 name; CFStringRef cfname; ATSFontFamilyRef ffref = ::ATSFontFamilyFindFromQuickDrawName(spFontName); ::ATSFontFamilyGetName(ffref, kATSOptionFlagsDefault, &cfname); //name.MAC_FromMacPString(spFontName); name.MAC_FromCFString(cfname); if(name[0] != '.' && name[0] != '%') { fFontNames.AppendString(name); fFontFamilies.AppendWord((sWORD) family); } //CFRelease(cfname); } } ::FMDisposeFontFamilyIterator(&iterator); }*/ CTFontCollectionRef FontCollection = ::CTFontCollectionCreateFromAvailableFonts(0);//kCTFontCollectionRemoveDuplicatesOption if(FontCollection) { CFArrayRef fonts = CTFontCollectionCreateMatchingFontDescriptors(FontCollection); if(fonts) { const int numFonts = CFArrayGetCount(fonts); for(int i = 0; i < numFonts; ++i) { VString vname; CTFontDescriptorRef vfont = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i); CFStringRef family_name = (CFStringRef)CTFontDescriptorCopyAttribute(vfont, kCTFontFamilyNameAttribute); if(family_name!=NULL) { vname.MAC_FromCFString(family_name); if( std::find(fFontNames.begin(), fFontNames.end(), vname) == fFontNames.end()) fFontNames.push_back(vname); } //CFRelease(family_name); } } } //fFontNames.SynchronizedSort(false, &fFontFamilies); //fFontNames.Sort(0, fFontNames.GetCount()-1); std::sort(fFontNames.begin(),fFontNames.end()); }
void QFontDatabase::load(const QFontPrivate *d, int script) { // sanity checks if(!qApp) qWarning("QFont: Must construct a QApplication before a QFont"); Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); Q_UNUSED(script); QFontDef req = d->request; req.pixelSize = qt_mac_pixelsize(req, d->dpi); // set the point size to 0 to get better caching req.pointSize = 0; QFontCache::Key key = QFontCache::Key(req, QUnicodeTables::Common, d->screen); if(!(d->engineData = QFontCache::instance()->findEngineData(key))) { d->engineData = new QFontEngineData; QFontCache::instance()->insertEngineData(key, d->engineData); } else { d->engineData->ref.ref(); } if(d->engineData->engine) // already loaded return; // set it to the actual pointsize, so QFontInfo will do the right thing req.pointSize = qRound(qt_mac_pointsize(d->request, d->dpi)); QFontEngine *e = QFontCache::instance()->findEngine(key); if(!e && qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { e = new QTestFontEngine(req.pixelSize); e->fontDef = req; } if(e) { e->ref.ref(); d->engineData->engine = e; return; // the font info and fontdef should already be filled } //find the font QStringList family_list = familyList(req); const char *stylehint = styleHint(req); if (stylehint) family_list << QLatin1String(stylehint); // add QFont::defaultFamily() to the list, for compatibility with // previous versions family_list << QApplication::font().defaultFamily(); ATSFontFamilyRef familyRef = 0; ATSFontRef fontRef = 0; QMutexLocker locker(fontDatabaseMutex()); QFontDatabasePrivate *db = privateDb(); if (!db->count) initializeDb(); for(int i = 0; i < family_list.size(); ++i) { for (int k = 0; k < db->count; ++k) { if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) { QByteArray family_name = db->families[k]->name.toUtf8(); familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); if (familyRef) { fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); goto FamilyFound; } else { #if defined(QT_MAC_USE_COCOA) // ATS and CT disagrees on what the family name should be, // use CT to look up the font if ATS fails. QCFString familyName = QString::fromAscii(family_name); QCFType<CTFontRef> CTfontRef = CTFontCreateWithName(familyName, 12, NULL); QCFType<CTFontDescriptorRef> fontDescriptor = CTFontCopyFontDescriptor(CTfontRef); QCFString displayName = (CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontDisplayNameAttribute); familyRef = ATSFontFamilyFindFromName(displayName, kATSOptionFlagsDefault); if (familyRef) { fontRef = ATSFontFindFromName(displayName, kATSOptionFlagsDefault); goto FamilyFound; } #endif } } } } FamilyFound: //fill in the engine's font definition QFontDef fontDef = d->request; //copy.. if(fontDef.pointSize < 0) fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi); else fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi); #if 0 ItemCount name_count; if(ATSUCountFontNames(fontID, &name_count) == noErr && name_count) { ItemCount actualName_size; if(ATSUGetIndFontName(fontID, 0, 0, 0, &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) { QByteArray actualName(actualName_size); if(ATSUGetIndFontName(fontID, 0, actualName_size, actualName.data(), &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) fontDef.family = QString::fromUtf8(actualName); } } #else { QCFString actualName; if(ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) fontDef.family = actualName; } #endif #ifdef QT_MAC_USE_COCOA QFontEngine *engine = new QCoreTextFontEngineMulti(familyRef, fontRef, fontDef, d->kerning); #elif 1 QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning); #else ATSFontFamilyRef atsFamily = familyRef; ATSFontFamilyRef atsFontRef = fontRef; FMFont fontID; FMFontFamily fmFamily; FMFontStyle fntStyle = 0; fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily); if (fmFamily == kInvalidFontFamily) { // Use the ATSFont then... fontID = FMGetFontFromATSFontRef(atsFontRef); } else { if (fontDef.weight >= QFont::Bold) fntStyle |= ::bold; if (fontDef.style != QFont::StyleNormal) fntStyle |= ::italic; FMFontStyle intrinsicStyle; FMFont fnt = 0; if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr) fontID = FMGetATSFontRefFromFont(fnt); } OSStatus status; const int maxAttributeCount = 5; ATSUAttributeTag tags[maxAttributeCount + 1]; ByteCount sizes[maxAttributeCount + 1]; ATSUAttributeValuePtr values[maxAttributeCount + 1]; int attributeCount = 0; Fixed size = FixRatio(fontDef.pixelSize, 1); tags[attributeCount] = kATSUSizeTag; sizes[attributeCount] = sizeof(size); values[attributeCount] = &size; ++attributeCount; tags[attributeCount] = kATSUFontTag; sizes[attributeCount] = sizeof(fontID); values[attributeCount] = &fontID; ++attributeCount; CGAffineTransform transform = CGAffineTransformIdentity; if (fontDef.stretch != 100) { transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); tags[attributeCount] = kATSUFontMatrixTag; sizes[attributeCount] = sizeof(transform); values[attributeCount] = &transform; ++attributeCount; } ATSUStyle style; status = ATSUCreateStyle(&style); Q_ASSERT(status == noErr); Q_ASSERT(attributeCount < maxAttributeCount + 1); status = ATSUSetAttributes(style, attributeCount, tags, sizes, values); Q_ASSERT(status == noErr); QFontEngine *engine = new QFontEngineMac(style, fontID, fontDef, /*multiEngine*/ 0); ATSUDisposeStyle(style); #endif d->engineData->engine = engine; engine->ref.ref(); //a ref for the engineData->engine QFontCache::instance()->insertEngine(key, engine); }
CPDF_Font* CPDF_Document::AddMacFont(CTFontRef pFont, FX_BOOL bVert, FX_BOOL bTranslateName) { CTFontRef font = (CTFontRef)pFont; CTFontDescriptorRef descriptor = CTFontCopyFontDescriptor(font); if (descriptor == NULL) { return NULL; } CFX_ByteString basefont; FX_BOOL bCJK = FALSE; int flags = 0, italicangle = 0, ascend = 0, descend = 0, capheight = 0, bbox[4]; FXSYS_memset32(bbox, 0, sizeof(int) * 4); CFArrayRef languages = (CFArrayRef)CTFontDescriptorCopyAttribute(descriptor, kCTFontLanguagesAttribute); if (languages == NULL) { CFRelease(descriptor); return NULL; } CFX_DWordArray charSets; charSets.Add(FXFONT_CHINESEBIG5_CHARSET); charSets.Add(FXFONT_GB2312_CHARSET); charSets.Add(FXFONT_HANGEUL_CHARSET); charSets.Add(FXFONT_SHIFTJIS_CHARSET); if (IsHasCharSet(languages, charSets)) { bCJK = TRUE; } CFRelease(descriptor); CFDictionaryRef traits = (CFDictionaryRef)CTFontCopyTraits(font); if (traits == NULL) { CFRelease(languages); return NULL; } CFNumberRef sybolicTrait = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait); CTFontSymbolicTraits trait = 0; CFNumberGetValue(sybolicTrait, kCFNumberSInt32Type, &trait); if (trait & kCTFontItalicTrait) { flags |= PDFFONT_ITALIC; } if (trait & kCTFontMonoSpaceTrait) { flags |= PDFFONT_FIXEDPITCH; } if (trait & kCTFontModernSerifsClass) { flags |= PDFFONT_SERIF; } if (trait & kCTFontScriptsClass) { flags |= PDFFONT_SCRIPT; } CFNumberRef weightTrait = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait); Float32 weight = 0; CFNumberGetValue(weightTrait, kCFNumberFloat32Type, &weight); italicangle = CTFontGetSlantAngle(font); ascend = CTFontGetAscent(font); descend = CTFontGetDescent(font); capheight = CTFontGetCapHeight(font); CGRect box = CTFontGetBoundingBox(font); bbox[0] = box.origin.x; bbox[1] = box.origin.y; bbox[2] = box.origin.x + box.size.width; bbox[3] = box.origin.y + box.size.height; if (bTranslateName && bCJK) { CFStringRef postName = CTFontCopyPostScriptName(font); _CFString2CFXByteString(postName, basefont); CFRelease(postName); } if (basefont.IsEmpty()) { CFStringRef fullName = CTFontCopyFullName(font); _CFString2CFXByteString(fullName, basefont); CFRelease(fullName); } basefont.Replace(" ", ""); CPDF_Dictionary* pFontDict = NULL; CPDF_Dictionary* pBaseDict = FX_NEW CPDF_Dictionary; pFontDict = pBaseDict; if (!bCJK) { charSets.RemoveAll(); charSets.Add(FXFONT_ANSI_CHARSET); charSets.Add(FXFONT_DEFAULT_CHARSET); charSets.Add(FXFONT_SYMBOL_CHARSET); if (IsHasCharSet(languages, charSets)) { charSets.RemoveAll(); charSets.Add(FXFONT_SYMBOL_CHARSET); if (IsHasCharSet(languages, charSets)) { flags |= PDFFONT_SYMBOLIC; } else { flags |= PDFFONT_NONSYMBOLIC; } pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding"); } else { flags |= PDFFONT_NONSYMBOLIC; int i; for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++) { charSets.RemoveAll(); charSets.Add(g_FX_CharsetUnicodes[i].m_Charset); if (IsHasCharSet(languages, charSets)) { break; } } if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) { CPDF_Dictionary* pEncoding = FX_NEW CPDF_Dictionary; pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding"); CPDF_Array* pArray = FX_NEW CPDF_Array; pArray->AddInteger(128); const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes; for (int j = 0; j < 128; j ++) { CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]); if (name.IsEmpty()) { pArray->AddName(FX_BSTRC(".notdef")); } else { pArray->AddName(name); } } pEncoding->SetAt(FX_BSTRC("Differences"), pArray); AddIndirectObject(pEncoding); pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding); } } if (weight > 0.0 && trait & kCTFontItalicTrait) { basefont += ",BoldItalic"; } else if (weight > 0.0) { basefont += ",Bold"; } else if (trait & kCTFontItalicTrait) { basefont += ",Italic"; } pBaseDict->SetAtName("Subtype", "TrueType"); pBaseDict->SetAtName("BaseFont", basefont); pBaseDict->SetAtNumber("FirstChar", 32); pBaseDict->SetAtNumber("LastChar", 255); int char_widths[224]; FX_GetCharWidth(font, 32, 255, char_widths); CPDF_Array* pWidths = FX_NEW CPDF_Array; for (int i = 0; i < 224; i ++) { pWidths->AddInteger(char_widths[i]); } pBaseDict->SetAt("Widths", pWidths); } else { flags |= PDFFONT_NONSYMBOLIC; CPDF_Array* pArray = NULL; pFontDict = FX_NEW CPDF_Dictionary; CFX_ByteString cmap; CFX_ByteString ordering; int supplement; FX_BOOL bFound = FALSE; CPDF_Array* pWidthArray = FX_NEW CPDF_Array; charSets.RemoveAll(); charSets.Add(FXFONT_CHINESEBIG5_CHARSET); if (IsHasCharSet(languages, charSets)) { cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H"; ordering = "CNS1"; supplement = 4; pWidthArray->AddInteger(1); _InsertWidthArray(font, 0x20, 0x7e, pWidthArray); bFound = TRUE; } charSets.RemoveAll(); charSets.Add(FXFONT_GB2312_CHARSET); if (!bFound && IsHasCharSet(languages, charSets)) { cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H"; ordering = "GB1", supplement = 2; pWidthArray->AddInteger(7716); _InsertWidthArray(font, 0x20, 0x20, pWidthArray); pWidthArray->AddInteger(814); _InsertWidthArray(font, 0x21, 0x7e, pWidthArray); bFound = TRUE; } charSets.RemoveAll(); charSets.Add(FXFONT_HANGEUL_CHARSET); if (!bFound && IsHasCharSet(languages, charSets)) { cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H"; ordering = "Korea1"; supplement = 2; pWidthArray->AddInteger(1); _InsertWidthArray(font, 0x20, 0x7e, pWidthArray); bFound = TRUE; } charSets.RemoveAll(); charSets.Add(FXFONT_SHIFTJIS_CHARSET); if (!bFound && IsHasCharSet(languages, charSets)) { cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H"; ordering = "Japan1"; supplement = 5; pWidthArray->AddInteger(231); _InsertWidthArray(font, 0x20, 0x7d, pWidthArray); pWidthArray->AddInteger(326); _InsertWidthArray(font, 0xa0, 0xa0, pWidthArray); pWidthArray->AddInteger(327); _InsertWidthArray(font, 0xa1, 0xdf, pWidthArray); pWidthArray->AddInteger(631); _InsertWidthArray(font, 0x7e, 0x7e, pWidthArray); } pBaseDict->SetAtName("Subtype", "Type0"); pBaseDict->SetAtName("BaseFont", basefont); pBaseDict->SetAtName("Encoding", cmap); pFontDict->SetAt("W", pWidthArray); pFontDict->SetAtName("Type", "Font"); pFontDict->SetAtName("Subtype", "CIDFontType2"); pFontDict->SetAtName("BaseFont", basefont); CPDF_Dictionary* pCIDSysInfo = FX_NEW CPDF_Dictionary; pCIDSysInfo->SetAtString("Registry", "Adobe"); pCIDSysInfo->SetAtString("Ordering", ordering); pCIDSysInfo->SetAtInteger("Supplement", supplement); pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo); pArray = FX_NEW CPDF_Array; pBaseDict->SetAt("DescendantFonts", pArray); AddIndirectObject(pFontDict); pArray->AddReference(this, pFontDict); } AddIndirectObject(pBaseDict); CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary; pFontDesc->SetAtName("Type", "FontDescriptor"); pFontDesc->SetAtName("FontName", basefont); pFontDesc->SetAtInteger("Flags", flags); CPDF_Array* pBBox = FX_NEW CPDF_Array; for (int i = 0; i < 4; i ++) { pBBox->AddInteger(bbox[i]); } pFontDesc->SetAt("FontBBox", pBBox); pFontDesc->SetAtInteger("ItalicAngle", italicangle); pFontDesc->SetAtInteger("Ascent", ascend); pFontDesc->SetAtInteger("Descent", descend); pFontDesc->SetAtInteger("CapHeight", capheight); CGFloat fStemV = 0; int16_t min_width = SHRT_MAX; static const UniChar stem_chars[] = {'i', 'I', '!', '1'}; const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]); CGGlyph glyphs[count]; CGRect boundingRects[count]; if (CTFontGetGlyphsForCharacters(font, stem_chars, glyphs, count)) { CTFontGetBoundingRectsForGlyphs(font, kCTFontHorizontalOrientation, glyphs, boundingRects, count); for (size_t i = 0; i < count; i++) { int16_t width = boundingRects[i].size.width; if (width > 0 && width < min_width) { min_width = width; fStemV = min_width; } } } pFontDesc->SetAtInteger("StemV", fStemV); AddIndirectObject(pFontDesc); pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); CFRelease(traits); CFRelease(languages); return LoadFont(pBaseDict); }
static PangoCoverage * ct_font_descriptor_get_coverage (CTFontDescriptorRef desc) { CFCharacterSetRef charset; CFIndex i, length; CFDataRef bitmap; const UInt8 *ptr, *plane_ptr; const UInt32 plane_size = 8192; PangoCoverage *coverage; coverage = pango_coverage_new (); charset = CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute); if (!charset) /* Return an empty coverage */ return coverage; bitmap = CFCharacterSetCreateBitmapRepresentation (kCFAllocatorDefault, charset); ptr = CFDataGetBytePtr (bitmap); /* First handle the BMP plane. */ length = MIN (CFDataGetLength (bitmap), plane_size); /* FIXME: can and should this be done more efficiently? */ for (i = 0; i < length; i++) { int j; for (j = 0; j < 8; j++) if ((ptr[i] & (1 << j)) == (1 << j)) pango_coverage_set (coverage, i * 8 + j, PANGO_COVERAGE_EXACT); } /* Next, handle the other planes. The plane number is encoded first as * a single byte. In the following 8192 bytes that plane's coverage bitmap * is stored. */ plane_ptr = ptr + plane_size; while (plane_ptr - ptr < CFDataGetLength (bitmap)) { const UInt8 plane_number = *plane_ptr; plane_ptr++; for (i = 0; i < plane_size; i++) { int j; for (j = 0; j < 8; j++) if ((plane_ptr[i] & (1 << j)) == (1 << j)) pango_coverage_set (coverage, (plane_number * plane_size + i) * 8 + j, PANGO_COVERAGE_EXACT); } plane_ptr += plane_size; } CFRelease (bitmap); CFRelease (charset); return coverage; }
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { bool result = false; #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 { /* Just copy the first part of the isocode. */ strecpy(lang, language_isocode, lastof(lang)); char *sep = strchr(lang, '_'); if (sep != NULL) *sep = '\0'; } /* Create a font descriptor matching the wanted language and latin (english) glyphs. */ CFStringRef lang_codes[2]; lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8); lang_codes[1] = CFSTR("en"); CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (const void **)lang_codes, lengthof(lang_codes), &kCFTypeArrayCallBacks); CFDictionaryRef lang_attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&kCTFontLanguagesAttribute, (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CTFontDescriptorRef lang_desc = CTFontDescriptorCreateWithAttributes(lang_attribs); CFRelease(lang_arr); CFRelease(lang_attribs); CFRelease(lang_codes[0]); /* Get array of all font descriptors for the wanted language. */ CFSetRef mandatory_attribs = CFSetCreate(kCFAllocatorDefault, (const void **)&kCTFontLanguagesAttribute, 1, &kCFTypeSetCallBacks); CFArrayRef descs = CTFontDescriptorCreateMatchingFontDescriptors(lang_desc, mandatory_attribs); CFRelease(mandatory_attribs); CFRelease(lang_desc); for (CFIndex i = 0; descs != NULL && i < CFArrayGetCount(descs); i++) { CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs, i); /* Get font traits. */ CFDictionaryRef traits = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute); CTFontSymbolicTraits symbolic_traits; CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits); CFRelease(traits); /* Skip symbol fonts and vertical fonts. */ if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue; /* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */ if (symbolic_traits & kCTFontBoldTrait) continue; /* Select monospaced fonts if asked for. */ if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue; /* Get font name. */ char name[128]; CFStringRef font_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute); CFStringGetCString(font_name, name, lengthof(name), kCFStringEncodingUTF8); CFRelease(font_name); /* There are some special fonts starting with an '.' and the last * resort font that aren't usable. Skip them. */ if (name[0] == '.' || strncmp(name, "LastResort", 10) == 0) continue; /* Save result. */ callback->SetFontNames(settings, name); if (!callback->FindMissingGlyphs(NULL)) { DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name); result = true; break; } } if (descs != NULL) CFRelease(descs); } else #endif { /* Create a font iterator and iterate over all fonts that * are available to the application. */ ATSFontIterator itr; ATSFontRef font; ATSFontIteratorCreate(kATSFontContextLocal, NULL, NULL, kATSOptionFlagsDefaultScope, &itr); while (!result && ATSFontIteratorNext(itr, &font) == noErr) { /* Get font name. */ char name[128]; CFStringRef font_name; ATSFontGetName(font, kATSOptionFlagsDefault, &font_name); CFStringGetCString(font_name, name, lengthof(name), kCFStringEncodingUTF8); bool monospace = IsMonospaceFont(font_name); CFRelease(font_name); /* Select monospaced fonts if asked for. */ if (monospace != callback->Monospace()) continue; /* We only want the base font and not bold or italic variants. */ if (strstr(name, "Italic") != NULL || strstr(name, "Bold")) continue; /* Skip some inappropriate or ugly looking fonts that have better alternatives. */ if (name[0] == '.' || strncmp(name, "Apple Symbols", 13) == 0 || strncmp(name, "LastResort", 10) == 0) continue; /* Save result. */ callback->SetFontNames(settings, name); if (!callback->FindMissingGlyphs(NULL)) { DEBUG(freetype, 2, "ATS-Font for %s: %s", language_isocode, name); result = true; break; } } ATSFontIteratorRelease(&itr); } if (!result) { /* For some OS versions, the font 'Arial Unicode MS' does not report all languages it * supports. If we didn't find any other font, just try it, maybe we get lucky. */ callback->SetFontNames(settings, "Arial Unicode MS"); result = !callback->FindMissingGlyphs(NULL); } callback->FindMissingGlyphs(NULL); return result; }
static void get_font_traits(CTFontDescriptorRef fontd, ASS_FontProviderMetaData *meta) { float weight, slant, width; CFDictionaryRef traits = CTFontDescriptorCopyAttribute(fontd, kCTFontTraitsAttribute); get_trait(traits, kCTFontWeightTrait, &weight); get_trait(traits, kCTFontSlantTrait, &slant); get_trait(traits, kCTFontWidthTrait, &width); SAFE_CFRelease(traits); // Printed all of my system fonts (see if'deffed code below). Here is how // CoreText 'normalized' weights maps to CSS/libass: // opentype: 0 100 200 300 400 500 600 700 800 900 // css: LIGHT REG MED SBOLD BOLD BLACK EXTRABL // libass: LIGHT MEDIUM BOLD // coretext: -0.4 0.0 0.23 0.3 0.4 0.62 if (weight >= 0.62) meta->weight = 800; else if (weight >= 0.4) meta->weight = 700; else if (weight >= 0.3) meta->weight = 600; else if (weight >= 0.23) meta->weight = 500; else if (weight >= -0.4) meta->weight = 400; else meta->weight = 200; if (slant > 0.03) meta->slant = FONT_SLANT_ITALIC; else meta->slant = FONT_SLANT_NONE; if (width <= -0.2) meta->width = FONT_WIDTH_CONDENSED; else if (width >= 0.2) meta->width = FONT_WIDTH_EXPANDED; else meta->width = FONT_WIDTH_NORMAL; #if 0 char *name[1]; int idx = 0; get_name(fontd, kCTFontDisplayNameAttribute, name, &idx); char *file = get_font_file(fontd); printf( "Font traits for: %-40s [%-50s] " "<slant: %f, %03d>, <weight: (%f, %03d)>, <width: %f, %03d>\n", name[0], file, slant, meta->slant, weight, meta->weight, width, meta->width); free(name[0]); free(file); #endif }
static inline PangoCoreTextFace * pango_core_text_face_from_ct_font_descriptor (CTFontDescriptorRef desc) { int font_traits; char *buffer; CFStringRef str; CFNumberRef number; CGFloat value; CFDictionaryRef dict; CFCharacterSetRef charset; PangoCoreTextFace *face = g_object_new (PANGO_TYPE_CORE_TEXT_FACE, NULL); face->synthetic_italic = FALSE; /* Get font name */ str = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute); buffer = gchar_from_cf_string (str); /* We strdup again to save space. */ face->postscript_name = g_strdup (buffer); CFRelease (str); g_free (buffer); /* Get style name */ str = CTFontDescriptorCopyAttribute (desc, kCTFontStyleNameAttribute); buffer = gchar_from_cf_string (str); face->style_name = g_strdup (buffer); CFRelease (str); g_free (buffer); /* Get font traits, symbolic traits */ dict = CTFontDescriptorCopyAttribute (desc, kCTFontTraitsAttribute); number = (CFNumberRef)CFDictionaryGetValue (dict, kCTFontWeightTrait); if (CFNumberGetValue (number, kCFNumberCGFloatType, &value)) { if (value < ct_weight_min || value > ct_weight_max) { face->weight = PANGO_WEIGHT_NORMAL; /* This is really an error */ } else { guint i; for (i = 0; i < G_N_ELEMENTS(ct_weight_limits); i++) if (value < ct_weight_limits[i].bound) { face->weight = ct_weight_limits[i].weight; break; } } } else face->weight = PANGO_WEIGHT_NORMAL; number = (CFNumberRef)CFDictionaryGetValue (dict, kCTFontSymbolicTrait); if (CFNumberGetValue (number, kCFNumberIntType, &font_traits)) { face->traits = font_traits; } CFRelease (dict); /* Get font coverage */ charset = CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute); face->coverage = pango_coverage_from_cf_charset (charset); CFRelease (charset); return face; }
static void initializeDb() { QFontDatabasePrivate *db = privateDb(); if(!db || db->count) return; #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0); if(!collection) return; QCFType<CFArrayRef> fonts = CTFontCollectionCreateMatchingFontDescriptors(collection); if(!fonts) return; QString foundry_name = "CoreText"; const int numFonts = CFArrayGetCount(fonts); for(int i = 0; i < numFonts; ++i) { CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i); QCFString family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); QtFontFamily *family = db->family(family_name, true); for(int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) family->writingSystems[ws] = QtFontFamily::Supported; QtFontFoundry *foundry = family->foundry(foundry_name, true); QtFontStyle::Key styleKey; if(QCFType<CFDictionaryRef> styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) { if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) { Q_ASSERT(CFNumberIsFloatType(weight)); double d; if(CFNumberGetValue(weight, kCFNumberDoubleType, &d)) { //qDebug() << "BOLD" << (QString)family_name << d; styleKey.weight = (d > 0.0) ? QFont::Bold : QFont::Normal; } } if(CFNumberRef italic = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontSlantTrait)) { Q_ASSERT(CFNumberIsFloatType(italic)); double d; if(CFNumberGetValue(italic, kCFNumberDoubleType, &d)) { //qDebug() << "ITALIC" << (QString)family_name << d; if (d > 0.0) styleKey.style = QFont::StyleItalic; } } } QtFontStyle *style = foundry->style(styleKey, true); style->smoothScalable = true; if(QCFType<CFNumberRef> size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) { //qDebug() << "WHEE"; int pixel_size=0; if(CFNumberIsFloatType(size)) { double d; CFNumberGetValue(size, kCFNumberDoubleType, &d); pixel_size = d; } else { CFNumberGetValue(size, kCFNumberIntType, &pixel_size); } //qDebug() << "SIZE" << (QString)family_name << pixel_size; if(pixel_size) style->pixelSize(pixel_size, true); } else { //qDebug() << "WTF?"; } } } else #endif { FMFontIterator it; if (!FMCreateFontIterator(0, 0, kFMUseGlobalScopeOption, &it)) { while (true) { FMFont fmFont; if (FMGetNextFont(&it, &fmFont) != noErr) break; FMFontFamily fmFamily; FMFontStyle fmStyle; QString familyName; QtFontStyle::Key styleKey; ATSFontRef atsFont = FMGetATSFontRefFromFont(fmFont); if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) { { //sanity check the font, and see if we can use it at all! --Sam ATSUFontID fontID; if(ATSUFONDtoFontID(fmFamily, 0, &fontID) != noErr) continue; } if (fmStyle & ::italic) styleKey.style = QFont::StyleItalic; if (fmStyle & ::bold) styleKey.weight = QFont::Bold; ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily); QCFString cfFamilyName;; ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName); familyName = cfFamilyName; } else { QCFString cfFontName; ATSFontGetName(atsFont, kATSOptionFlagsDefault, &cfFontName); familyName = cfFontName; quint16 macStyle = 0; { uchar data[4]; ByteCount len = 4; if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 44, 4, &data, &len) == noErr) macStyle = qFromBigEndian<quint16>(data); } if (macStyle & 1) styleKey.weight = QFont::Bold; if (macStyle & 2) styleKey.style = QFont::StyleItalic; } QtFontFamily *family = db->family(familyName, true); QtFontFoundry *foundry = family->foundry(QString(), true); QtFontStyle *style = foundry->style(styleKey, true); style->pixelSize(0, true); style->smoothScalable = true; initWritingSystems(family, atsFont); } FMDisposeFontIterator(&it); } } }
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) { ATSFontContainerRef handle; OSStatus e = noErr; if(fnt->data.isEmpty()) { #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp FSRef ref; if(qt_mac_create_fsref(fnt->fileName, &ref) != noErr) return; ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle); } else #endif { #ifndef Q_WS_MAC64 extern Q_CORE_EXPORT OSErr qt_mac_create_fsspec(const QString &, FSSpec *); // global.cpp FSSpec spec; if(qt_mac_create_fsspec(fnt->fileName, &spec) != noErr) return; e = ATSFontActivateFromFileSpecification(&spec, kATSFontContextLocal, kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle); #endif } } else { e = ATSFontActivateFromMemory((void *)fnt->data.constData(), fnt->data.size(), kATSFontContextLocal, kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle); fnt->data = QByteArray(); } if(e != noErr) return; ItemCount fontCount = 0; e = ATSFontFindFromContainer(handle, kATSOptionFlagsDefault, 0, 0, &fontCount); if(e != noErr) return; QVarLengthArray<ATSFontRef> containedFonts(fontCount); e = ATSFontFindFromContainer(handle, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount); if(e != noErr) return; fnt->families.clear(); #if defined(QT_MAC_USE_COCOA) // Make sure that the family name set on the font matches what // kCTFontFamilyNameAttribute returns in initializeDb(). // So far the best solution seems find the installed font // using CoreText and get the family name from it. // (ATSFontFamilyGetName appears to be the correct API, but also // returns the font display name.) for(int i = 0; i < containedFonts.size(); ++i) { QCFString fontPostScriptName; ATSFontGetPostScriptName(containedFonts[i], kATSOptionFlagsDefault, &fontPostScriptName); QCFType<CTFontDescriptorRef> font = CTFontDescriptorCreateWithNameAndSize(fontPostScriptName, 14); QCFString familyName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); fnt->families.append(familyName); } #else for(int i = 0; i < containedFonts.size(); ++i) { QCFString family; ATSFontGetName(containedFonts[i], kATSOptionFlagsDefault, &family); fnt->families.append(family); } #endif fnt->handle = handle; }