Example #1
0
static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters,
                         hb_uint32 length) {
    SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
    SkPaint paint;

    paint.setTypeface(font->getTypeface());
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    return paint.containsText(characters, length * sizeof(uint16_t));
}
Example #2
0
DEF_TEST(Paint_cmap, reporter) {
    // need to implement charsToGlyphs on other backends (e.g. linux, win)
    // before we can run this tests everywhere
    return;

    static const int NGLYPHS = 64;

    SkUnichar src[NGLYPHS];
    SkUnichar dst[NGLYPHS]; // used for utf8, utf16, utf32 storage

    static const struct {
        size_t (*fSeedTextProc)(const SkUnichar[], void* dst, int count);
        SkPaint::TextEncoding   fEncoding;
    } gRec[] = {
        { uni_to_utf8,  SkPaint::kUTF8_TextEncoding },
        { uni_to_utf16, SkPaint::kUTF16_TextEncoding },
        { uni_to_utf32, SkPaint::kUTF32_TextEncoding },
    };

    SkRandom rand;
    SkPaint paint;
    paint.setTypeface(SkTypeface::RefDefault())->unref();
    SkTypeface* face = paint.getTypeface();

    for (int i = 0; i < 1000; ++i) {
        // generate some random text
        for (int j = 0; j < NGLYPHS; ++j) {
            src[j] = ' ' + j;
        }
        // inject some random chars, to sometimes abort early
        src[rand.nextU() & 63] = rand.nextU() & 0xFFF;

        for (size_t k = 0; k < SK_ARRAY_COUNT(gRec); ++k) {
            paint.setTextEncoding(gRec[k].fEncoding);

            size_t len = gRec[k].fSeedTextProc(src, dst, NGLYPHS);

            uint16_t    glyphs0[NGLYPHS], glyphs1[NGLYPHS];

            bool contains = paint.containsText(dst, len);
            int nglyphs = paint.textToGlyphs(dst, len, glyphs0);
            int first = face->charsToGlyphs(dst, paint2encoding(paint), glyphs1, NGLYPHS);
            int index = find_first_zero(glyphs1, NGLYPHS);

            REPORTER_ASSERT(reporter, NGLYPHS == nglyphs);
            REPORTER_ASSERT(reporter, index == first);
            REPORTER_ASSERT(reporter, 0 == memcmp(glyphs0, glyphs1, NGLYPHS * sizeof(uint16_t)));
            if (contains) {
                REPORTER_ASSERT(reporter, NGLYPHS == first);
            } else {
                REPORTER_ASSERT(reporter, NGLYPHS > first);
            }
        }
    }
}
SkTypeface* OsmAnd::EmbeddedFontFinder::findFontForCharacterUCS4(
    const uint32_t character,
    const SkFontStyle style /*= SkFontStyle()*/) const
{
    SkPaint paint;
    paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);

    SkTypeface* bestMatch = nullptr;
    auto bestMatchDifference = std::numeric_limits<float>::quiet_NaN();
    for (const auto font : constOf(_fonts))
    {
        paint.setTypeface(font);

        // If font doesn't contain requested character, it should be completely ignored
        if (!paint.containsText(&character, sizeof(uint32_t)))
            continue;

        // Calculate difference between this font style and requested style
        auto difference = 0.0f;
        const auto fontStyle = font->fontStyle();
        if (fontStyle.slant() != style.slant())
            difference += 1.0f;
        if (fontStyle.width() != style.width())
            difference += static_cast<float>(qAbs(fontStyle.width() - style.width())) / SkFontStyle::kUltaExpanded_Width;
        if (fontStyle.weight() != style.weight())
            difference += static_cast<float>(qAbs(fontStyle.weight() - style.weight())) / SkFontStyle::kBlack_Weight;

        // If there was previous best match, check if this match is better
        if (bestMatch && bestMatchDifference < difference)
            continue;
        
        bestMatch = font;
        bestMatchDifference = difference;

        // In case difference is 0, there won't be better match
        if (qFuzzyIsNull(bestMatchDifference))
            break;
    }

    return bestMatch;
}
Example #4
0
QVector<OsmAnd::TextRasterizer_P::LinePaint> OsmAnd::TextRasterizer_P::evaluatePaints(
    const QVector<QStringRef>& lineRefs,
    const Style& style) const
{
    // Prepare default paint
    SkPaint paint = _defaultPaint;
    paint.setTextSize(style.size);
    paint.setColor(style.color.toSkColor());

    // Transform text style to font style
    const SkFontStyle fontStyle(
        style.bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight,
        SkFontStyle::kNormal_Width,
        style.italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);

    const auto pText = lineRefs.first().string()->constData();

    QVector<LinePaint> linePaints;
    linePaints.reserve(lineRefs.count());
    for (const auto& lineRef : constOf(lineRefs))
    {
        LinePaint linePaint;
        linePaint.line = lineRef;

        TextPaint* pTextPaint = nullptr;
        const auto pLine = lineRef.constData();
        const auto pEnd = pLine + lineRef.size();
        auto pNextCharacter = pLine;
        while (pNextCharacter != pEnd)
        {
            const auto pCharacter = pNextCharacter;
            const auto position = pNextCharacter - pText;
            const auto characterUCS4 = SkUTF16_NextUnichar(reinterpret_cast<const uint16_t**>(&pNextCharacter));

            // First of all check previous font if it contains this character
            auto font = pTextPaint ? pTextPaint->paint.getTypeface() : nullptr;
            if (font)
            {
                SkPaint paint;
                paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
                paint.setTypeface(font);
                if (!paint.containsText(&characterUCS4, sizeof(uint32_t)))
                    font = nullptr;
#if OSMAND_LOG_CHARACTERS_FONT
                else
                {
                    SkString fontName;
                    font->getFamilyName(&fontName);

                    LogPrintf(LogSeverityLevel::Warning,
                              "UCS4 character 0x%08x (%u) has been found in '%s' font (reused)",
                              characterUCS4,
                              characterUCS4,
                              fontName.c_str());
                }
#endif // OSMAND_LOG_CHARACTERS_FONT
            }
            if (!font)
            {
                font = owner->fontFinder->findFontForCharacterUCS4(characterUCS4, fontStyle);

#if OSMAND_LOG_CHARACTERS_WITHOUT_FONT
                if (!font)
                {
                    LogPrintf(LogSeverityLevel::Warning,
                              "UCS4 character 0x%08x (%u) has not been found in any font",
                              characterUCS4,
                              characterUCS4);
                }
#endif // OSMAND_LOG_CHARACTERS_WITHOUT_FONT

#if OSMAND_LOG_CHARACTERS_FONT
                if (font)
                {
                    SkString fontName;
                    font->getFamilyName(&fontName);

                    LogPrintf(LogSeverityLevel::Warning,
                              "UCS4 character 0x%08x (%u) has been found in '%s' font",
                              characterUCS4,
                              characterUCS4,
                              fontName.c_str());
                }
#endif // OSMAND_LOG_CHARACTERS_FONT
            }

            if (pTextPaint == nullptr || pTextPaint->paint.getTypeface() != font)
            {
                linePaint.textPaints.push_back(qMove(TextPaint()));
                pTextPaint = &linePaint.textPaints.last();

                pTextPaint->text = QStringRef(lineRef.string(), position, 1);
                pTextPaint->paint = paint;
                pTextPaint->paint.setTypeface(font);

                SkPaint::FontMetrics metrics;
                pTextPaint->height = paint.getFontMetrics(&metrics);
                linePaint.maxFontHeight = qMax(linePaint.maxFontHeight, pTextPaint->height);
                linePaint.minFontHeight = qMin(linePaint.minFontHeight, pTextPaint->height);
                linePaint.maxFontLineSpacing = qMax(linePaint.maxFontLineSpacing, metrics.fLeading);
                linePaint.minFontLineSpacing = qMin(linePaint.minFontLineSpacing, metrics.fLeading);
                linePaint.maxFontTop = qMax(linePaint.maxFontTop, -metrics.fTop);
                linePaint.minFontTop = qMin(linePaint.minFontTop, -metrics.fTop);
                linePaint.maxFontBottom = qMax(linePaint.maxFontBottom, metrics.fBottom);
                linePaint.minFontBottom = qMin(linePaint.minFontBottom, metrics.fBottom);

                if (style.bold && (!font || (font && font->fontStyle().weight() <= SkFontStyle::kNormal_Weight)))
                    pTextPaint->paint.setFakeBoldText(true);
            }
            else
            {
                pTextPaint->text = QStringRef(lineRef.string(), pTextPaint->text.position(), pTextPaint->text.size() + 1);
            }
        }

        linePaints.push_back(qMove(linePaint));
    }

    return linePaints;
}
Example #5
0
static void containsText_proc(int loops, const SkPaint& paint, const void* text, size_t len,
                              int glyphCount) {
    for (int i = 0; i < loops; ++i) {
        paint.containsText(text, len);
    }
}