/*
 * 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;
}
Пример #2
0
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);
}
Пример #3
0
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);
}