static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
     int score = 0;
     score += (pattern.width() - candidate.width()) * 100;
     score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000;
     score += pattern.weight() - candidate.weight();
     return score;
 }
예제 #2
0
 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
     int score = 0;
     score += SkTAbs((pattern.width() - candidate.width()) * 100);
     score += SkTAbs((pattern.slant() == candidate.slant()) ? 0 : 1000);
     score += SkTAbs(pattern.weight() - candidate.weight());
     return score;
 }
예제 #3
0
static void TypefaceStyle_test(skiatest::Reporter* reporter,
                               uint16_t weight, uint16_t width, SkData* data)
{
    sk_sp<SkData> dataCopy;
    SkData* dataToUse = data;
    if (!dataToUse->unique()) {
        dataCopy = SkData::MakeWithCopy(data->data(), data->size());
        dataToUse = dataCopy.get();
    }
    SkSFNTHeader* sfntHeader = static_cast<SkSFNTHeader*>(dataToUse->writable_data());

    SkSFNTHeader::TableDirectoryEntry* tableEntry =
        SkTAfter<SkSFNTHeader::TableDirectoryEntry>(sfntHeader);
    SkSFNTHeader::TableDirectoryEntry* os2TableEntry = nullptr;
    int numTables = SkEndian_SwapBE16(sfntHeader->numTables);
    for (int tableEntryIndex = 0; tableEntryIndex < numTables; ++tableEntryIndex) {
        if (SkOTTableOS2::TAG == tableEntry[tableEntryIndex].tag) {
            os2TableEntry = tableEntry + tableEntryIndex;
            break;
        }
    }
    SkASSERT_RELEASE(os2TableEntry);

    size_t os2TableOffset = SkEndian_SwapBE32(os2TableEntry->offset);
    SkOTTableOS2_V0* os2Table = SkTAddOffset<SkOTTableOS2_V0>(sfntHeader, os2TableOffset);
    os2Table->usWeightClass.value = SkEndian_SwapBE16(weight);
    using WidthType = SkOTTableOS2_V0::WidthClass::Value;
    os2Table->usWidthClass.value = static_cast<WidthType>(SkEndian_SwapBE16(width));

    sk_sp<SkTypeface> newTypeface(SkTypeface::MakeFromStream(new SkMemoryStream(dataToUse)));
    SkASSERT_RELEASE(newTypeface);

    SkFontStyle newStyle = newTypeface->fontStyle();

    //printf("%d, %f\n", weight, (newStyle.weight() - (float)0x7FFF) / (float)0x7FFF);
    //printf("%d, %f\n", width , (newStyle.width()  - (float)0x7F)   / (float)0x7F);
    //printf("%d, %d\n", weight, newStyle.weight());
    //printf("%d, %d\n", width , newStyle.width());

    // Some back-ends (CG, GDI, DW) support OS/2 version A which uses 0 - 10 (but all differently).
    REPORTER_ASSERT(reporter,
                    newStyle.weight() == weight ||
                    (weight <=   10 && newStyle.weight() == 100 * weight) ||
                    (weight ==    4 && newStyle.weight() == 350) ||  // GDI weirdness
                    (weight ==    5 && newStyle.weight() == 400) ||  // GDI weirdness
                    (weight ==    0 && newStyle.weight() ==   1) ||  // DW weirdness
                    (weight == 1000 && newStyle.weight() == 999)     // DW weirdness
    );

    // Some back-ends (GDI) don't support width, ensure these always report 'medium'.
    REPORTER_ASSERT(reporter,
                    newStyle.width() == width ||
                    newStyle.width() == 5);
}
예제 #4
0
파일: FontMgrTest.cpp 프로젝트: Just-D/skia
static void test_fontiter(skiatest::Reporter* reporter, bool verbose) {
    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
    int count = fm->countFamilies();

    for (int i = 0; i < count; ++i) {
        SkString fname;
        fm->getFamilyName(i, &fname);

        SkAutoTUnref<SkFontStyleSet> fnset(fm->matchFamily(fname.c_str()));
        SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
        REPORTER_ASSERT(reporter, fnset->count() == set->count());

        if (verbose) {
            SkDebugf("[%2d] %s\n", i, fname.c_str());
        }

        for (int j = 0; j < set->count(); ++j) {
            SkString sname;
            SkFontStyle fs;
            set->getStyle(j, &fs, &sname);
//            REPORTER_ASSERT(reporter, sname.size() > 0);

            SkAutoTUnref<SkTypeface> face(set->createTypeface(j));
//            REPORTER_ASSERT(reporter, face.get());

            if (verbose) {
                SkDebugf("\t[%d] %s [%3d %d %d]\n", j, sname.c_str(),
                         fs.weight(), fs.width(), fs.isItalic());
            }
        }
    }
}
예제 #5
0
    explicit SkFontStyleSet_Android(const FontFamily& family,
                                    const SkTypeface_FreeType::Scanner& scanner)
    {
        const SkString* cannonicalFamilyName = NULL;
        if (family.fNames.count() > 0) {
            cannonicalFamilyName = &family.fNames[0];
        }
        // TODO? make this lazy
        for (int i = 0; i < family.fFonts.count(); ++i) {
            const FontFileInfo& fontFile = family.fFonts[i];

            SkString pathName(family.fBasePath);
            pathName.append(fontFile.fFileName);

            SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
            if (!stream.get()) {
                SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n",
                          pathName.c_str()));
                continue;
            }

            const int ttcIndex = fontFile.fIndex;
            SkString familyName;
            SkFontStyle style;
            bool isFixedWidth;
            if (!scanner.scanFont(stream.get(), ttcIndex, &familyName, &style, &isFixedWidth)) {
                SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n",
                          pathName.c_str()));
                continue;
            }

            int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
            SkFontStyle::Slant slant = style.slant();
            switch (fontFile.fStyle) {
                case FontFileInfo::Style::kAuto: slant = style.slant(); break;
                case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
                case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
                default: SkASSERT(false); break;
            }
            style = SkFontStyle(weight, style.width(), slant);

            const SkLanguage& lang = family.fLanguage;
            uint32_t variant = family.fVariant;
            if (kDefault_FontVariant == variant) {
                variant = kCompact_FontVariant | kElegant_FontVariant;
            }

            // The first specified family name overrides the family name found in the font.
            // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
            // all of the specified family names in addition to the names found in the font.
            if (cannonicalFamilyName != NULL) {
                familyName = *cannonicalFamilyName;
            }

            fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
                                                 (pathName, ttcIndex,
                                                  style, isFixedWidth, familyName,
                                                  lang, variant)));
        }
    }
예제 #6
0
sk_sp<SkTypeface> SkTypeface::MakeFromName(const char name[],
                                           SkFontStyle fontStyle) {
    if (gCreateTypefaceDelegate) {
        sk_sp<SkTypeface> result = (*gCreateTypefaceDelegate)(name, fontStyle);
        if (result) {
            return result;
        }
    }
    if (nullptr == name && (fontStyle.slant() == SkFontStyle::kItalic_Slant ||
                            fontStyle.slant() == SkFontStyle::kUpright_Slant) &&
                           (fontStyle.weight() == SkFontStyle::kBold_Weight ||
                            fontStyle.weight() == SkFontStyle::kNormal_Weight)) {
        return MakeDefault(static_cast<SkTypeface::Style>(
            (fontStyle.slant() == SkFontStyle::kItalic_Slant ? SkTypeface::kItalic :
                                                               SkTypeface::kNormal) |
            (fontStyle.weight() == SkFontStyle::kBold_Weight ? SkTypeface::kBold :
                                                               SkTypeface::kNormal)));
    }
    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
    return sk_sp<SkTypeface>(fm->legacyCreateTypeface(name, fontStyle));
}
예제 #7
0
    explicit DWriteStyle(const SkFontStyle& pattern) {
        switch (pattern.slant()) {
        case SkFontStyle::kUpright_Slant:
            fSlant = DWRITE_FONT_STYLE_NORMAL;
            break;
        case SkFontStyle::kItalic_Slant:
            fSlant = DWRITE_FONT_STYLE_ITALIC;
            break;
        default:
            SkASSERT(false);
        }

        fWeight = (DWRITE_FONT_WEIGHT)pattern.weight();
        fWidth = (DWRITE_FONT_STRETCH)pattern.width();
    }
예제 #8
0
void SkGlyphCache::dump() const {
    const SkTypeface* face = fScalerContext->getTypeface();
    const SkScalerContextRec& rec = fScalerContext->getRec();
    SkMatrix matrix;
    rec.getSingleMatrix(&matrix);
    matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize));
    SkString name;
    face->getFamilyName(&name);

    SkString msg;
    SkFontStyle style = face->fontStyle();
    msg.printf("cache typeface:%x %25s:(%d,%d,%d)\n %s glyphs:%3d",
               face->uniqueID(), name.c_str(), style.weight(), style.width(), style.slant(),
               rec.dump().c_str(), fGlyphMap.count());
    SkDebugf("%s\n", msg.c_str());
}
예제 #9
0
파일: fontmgr.cpp 프로젝트: JavierJF/skia
    void iterateFamily(SkCanvas* canvas, const SkPaint& paint,
                       SkFontStyleSet* fset) {
        SkPaint p(paint);
        SkScalar y = 0;

        for (int j = 0; j < fset->count(); ++j) {
            SkString sname;
            SkFontStyle fs;
            fset->getStyle(j, &fs, &sname);

            sname.appendf(" [%d %d]", fs.weight(), fs.width());

            SkSafeUnref(p.setTypeface(fset->createTypeface(j)));
            (void)drawString(canvas, sname, 0, y, p);
            y += 24;
        }
    }
예제 #10
0
파일: fontmgr.cpp 프로젝트: JavierJF/skia
    void onDraw(SkCanvas* canvas) override {
        SkScalar y = 20;
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setLCDRenderText(true);
        paint.setSubpixelText(true);
        paint.setTextSize(17);

        SkFontMgr* fm = fFM;
        int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);

        for (int i = 0; i < count; ++i) {
            SkString familyName;
            fm->getFamilyName(i, &familyName);
            paint.setTypeface(nullptr);
            (void)drawString(canvas, familyName, 20, y, paint);

            SkScalar x = 220;

            SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
            for (int j = 0; j < set->count(); ++j) {
                SkString sname;
                SkFontStyle fs;
                set->getStyle(j, &fs, &sname);
                sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.slant());

                SkSafeUnref(paint.setTypeface(set->createTypeface(j)));
                x = drawString(canvas, sname, x, y, paint) + 20;

                // check to see that we get different glyphs in japanese and chinese
                x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &zh, 1, fs);
                x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &ja, 1, fs);
                // check that emoji characters are found
                x = drawCharacter(canvas, 0x1f601, x, y, paint, fm, familyName.c_str(), nullptr,0, fs);
            }
            y += 24;
        }
    }
예제 #11
0
sk_sp<SkTypeface> create_font(const char* name, SkFontStyle style) {
    SkTestFontData* fontData = nullptr;
    const SubFont* sub;
    if (name) {
        for (int index = 0; index < gSubFontsCount; ++index) {
            sub = &gSubFonts[index];
            if (!strcmp(name, sub->fName) && sub->fStyle == style) {
                fontData = &sub->fFont;
                break;
            }
        }
        if (!fontData) {
            // Once all legacy callers to portable fonts are converted, replace this with
            // SK_ABORT();
            SkDebugf("missing %s weight %d, width %d, slant %d\n",
                     name, style.weight(), style.width(), style.slant());
            // If we called SkTypeface::CreateFromName() here we'd recurse infinitely,
            // so we reimplement its core logic here inline without the recursive aspect.
            sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
            return fm->legacyMakeTypeface(name, style);
        }
    } else {
        sub = &gSubFonts[gDefaultFontIndex];
        fontData = &sub->fFont;
    }
    sk_sp<SkTestFont> font;
    {
        SkAutoMutexAcquire ac(gTestFontMutex);
        if (fontData->fCachedFont) {
            font = fontData->fCachedFont;
        } else {
            font = sk_make_sp<SkTestFont>(*fontData);
            fontData->fCachedFont = font;
        }
    }
    return sk_make_sp<SkTestTypeface>(std::move(font), style);
}