/* * Class: com_sun_javafx_font_MacFontFinder * Method: getFontData * Signature: ()[Ljava/lang/String; */ JNIEXPORT jobjectArray JNICALL Java_com_sun_javafx_font_MacFontFinder_getFontData (JNIEnv *env, jclass obj) { /* No caching as this method is only invoked once */ jclass jStringClass = (*env)->FindClass(env, "java/lang/String"); if (jStringClass == NULL) return NULL; CTFontCollectionRef collection = CTFontCollectionCreateFromAvailableFonts(NULL); CFArrayRef fonts = CTFontCollectionCreateMatchingFontDescriptors(collection); CFRelease(collection); CFIndex count = CFArrayGetCount(fonts); jobjectArray result = (*env)->NewObjectArray(env, (count + 2) * 3, jStringClass, NULL); if (result == NULL) { /* out of memory */ CFRelease(fonts); return NULL; } CFIndex i = 0, j = 0; while (i < count) { CTFontDescriptorRef fd = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i++); j = addCTFontDescriptor(fd, env, result, j); } CFRelease(fonts); /* Sometimes a font name starting with dot (internal font, e.g. ".Helvetica NeueUI") * is returned as a system UI font, but such font is not available in the collection * of available fonts. Thus, it is safer to always add the system font manually * to the list so JavaFX can find it. If the UI font is added twice it gets * handled in Java. */ CTFontRef font = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, 0, NULL); CTFontDescriptorRef fd = CTFontCopyFontDescriptor(font); j = addCTFontDescriptor(fd, env, result, j); CFRelease(fd); CFRelease(font); /* Also add the EmphasizedSystemFont as it might make the bold version * for the system font available to JavaFX. */ font = CTFontCreateUIFontForLanguage(kCTFontEmphasizedSystemFontType, 0, NULL); fd = CTFontCopyFontDescriptor(font); j = addCTFontDescriptor(fd, env, result, j); CFRelease(fd); CFRelease(font); return result; }
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); }