Example #1
0
static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length, HB_Glyph* glyphs, hb_uint32* glyphsSize, HB_Bool isRTL)
{
    FontPlatformData* font = reinterpret_cast<FontPlatformData*>(hbFont->userData);
    SkPaint paint;

    font->setupPaint(&paint);
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);

    unsigned codepoints = 0;
    for (hb_uint32 i = 0; i < length; i++) {
        if (!SkUTF16_IsHighSurrogate(characters[i]))
            codepoints++;
        if (codepoints > *glyphsSize)
            return 0;
    }

    int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), reinterpret_cast<uint16_t*>(glyphs));

    // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our
    // |glyphs| array needs to be converted.
    for (int i = numGlyphs - 1; i >= 0; --i) {
        uint16_t value;
        // We use a memcpy to avoid breaking strict aliasing rules.
        memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, sizeof(uint16_t));
        glyphs[i] = value;
    }

    *glyphsSize = numGlyphs;
    return 1;
}
Example #2
0
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
        SkDebugf("%s last char is high-surrogate", __FUNCTION__);
        return false;
    }
    
    SkPaint paint;
    fontData->platformData().setupPaint(&paint);
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);

#if OS(WINDOWS)
    // FIXME: For some reason SkAutoSTMalloc fails to link on Windows.
    // SkAutoSTArray works fine though...
    SkAutoSTArray<GlyphPage::size, uint16_t> glyphStorage(length);
#else
    SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);
#endif

    uint16_t* glyphs = glyphStorage.get();
    // textToGlyphs takes a byte count, not a glyph count so we multiply by two.
    unsigned count = paint.textToGlyphs(buffer, bufferLength * 2, glyphs);
    if (count != length) {
        SkDebugf("%s count != length\n", __FUNCTION__);
        return false;
    }

    unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero
    for (unsigned i = 0; i < length; i++) {
        setGlyphDataForIndex(offset + i, glyphs[i], glyphs[i] ? fontData : NULL);
        allGlyphs |= glyphs[i];
    }

    return allGlyphs != 0;
}
static SkUnichar SkUTF16BE_NextUnichar(const uint16_t** srcPtr) {
    SkASSERT(srcPtr && *srcPtr);

    const uint16_t* src = *srcPtr;
    SkUnichar c = SkEndian_SwapBE16(*src++);

    SkASSERT(!SkUTF16_IsLowSurrogate(c));
    if (SkUTF16_IsHighSurrogate(c)) {
        unsigned c2 = SkEndian_SwapBE16(*src++);
        SkASSERT(SkUTF16_IsLowSurrogate(c2));

        c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
    }
    *srcPtr = src;
    return c;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
        SkDebugf("%s last char is high-surrogate", __FUNCTION__);
        return false;
    }
    
    SkPaint paint;
    fontData->platformData().setupPaint(&paint);
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    
    SkAutoSTMalloc <GlyphPage::size, uint16_t> glyphStorage(length);
    uint16_t* glyphs = glyphStorage.get();
    unsigned count = paint.textToGlyphs(buffer, bufferLength << 1, glyphs);
    if (count != length) {
        SkDebugf("%s count != length\n", __FUNCTION__);
        return false;
    }

    unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero

    // search for emoji. If we knew for sure that buffer was a contiguous range
    // of chars, we could quick-reject the range to avoid this loop (usually)
    if (EmojiFont::IsAvailable()) {
        const UChar* curr = buffer;
        for (unsigned i = 0; i < length; i++) {
            SkUnichar uni = SkUTF16_NextUnichar(&curr);
            uint16_t glyphID = glyphs[i];
            // only sniff if the normal font failed to recognize it
            if (!glyphID)
                glyphID = EmojiFont::UnicharToGlyph(uni);
            setGlyphDataForIndex(offset + i, glyphID, fontData);
            allGlyphs |= glyphID;
        }
    } else {
        for (unsigned i = 0; i < length; i++) {
            uint16_t glyphID = glyphs[i];
            setGlyphDataForIndex(offset + i, glyphID, fontData);
            allGlyphs |= glyphID;
        }
    }
    return allGlyphs != 0;
}
Example #5
0
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
        SkDebugf("%s last char is high-surrogate", __FUNCTION__);
        return false;
    }
    
    SkPaint paint;
    fontData->platformData().setupPaint(&paint);
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    
    SkAutoSTMalloc <GlyphPage::size, uint16_t> glyphStorage(length);
    uint16_t* glyphs = glyphStorage.get();
    // textToGlyphs takes a byte count, not a glyph count so we multiply by two.
    unsigned count = paint.textToGlyphs(buffer, bufferLength * 2, glyphs);
    if (count != length) {
        SkDebugf("%s count != length\n", __FUNCTION__);
        return false;
    }

    if (fontData->hasVerticalGlyphs()) {
        bool lookVariants = false;
        for (unsigned i = 0; i < bufferLength; ++i) {
            if (!Font::isCJKIdeograph(buffer[i])) {
                lookVariants = true;
                continue;
            }
        }
        if (lookVariants)
            substituteWithVerticalGlyphs(fontData, glyphs, bufferLength);
    }

    unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero
    for (unsigned i = 0; i < length; i++) {
        setGlyphDataForIndex(offset + i, glyphs[i], glyphs[i] ? fontData : NULL);
        allGlyphs |= glyphs[i];
    }

    return allGlyphs != 0;
}
bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const
{
    if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
        SkDebugf("%s last char is high-surrogate", __FUNCTION__);
        return false;
    }

    SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);

    uint16_t* glyphs = glyphStorage.get();
    SkTypeface* typeface = platformData().typeface();
    typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length);

    bool haveGlyphs = false;
    for (unsigned i = 0; i < length; i++) {
        if (glyphs[i]) {
            pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
            haveGlyphs = true;
        }
    }

    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
        SkDebugf("%s last char is high-surrogate", __FUNCTION__);
        return false;
    }
    
    SkPaint paint;
    fontData->platformData().setupPaint(&paint);
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);

    SkAutoSTMalloc <GlyphPage::size, uint16_t> glyphStorage(length);
    uint16_t* glyphs = glyphStorage.get();
    UChar *textBuffer = buffer;
    UChar vTextBuffer[bufferLength];

    if (fontData->platformData().orientation() == Vertical && !fontData->hasVerticalGlyphs()) {
        // Convert to vertical form if there is no vertical glyphs.
        for (unsigned i = 0; i < bufferLength; ++i) {
            vTextBuffer[i] = VerticalTextMap::getVerticalForm(buffer[i]);
            if (!vTextBuffer[i])
                vTextBuffer[i] = buffer[i];
        }
        textBuffer = vTextBuffer;
    }

    unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs);
    if (count != length) {
        SkDebugf("%s count != length\n", __FUNCTION__);
        return false;
    }

    if (fontData->hasVerticalGlyphs()) {
        bool lookVariants = false;
        for (unsigned i = 0; i < bufferLength; ++i) {
            if (!Font::isCJKIdeograph(textBuffer[i])) {
                lookVariants = true;
                continue;
            }
        }
        if (lookVariants)
            substituteWithVerticalGlyphs(fontData->platformData(), glyphs, bufferLength);
    }

    unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero

    // search for emoji. If we knew for sure that buffer was a contiguous range
    // of chars, we could quick-reject the range to avoid this loop (usually)
    if (EmojiFont::IsAvailable()) {
        const UChar* curr = textBuffer;
        for (unsigned i = 0; i < length; i++) {
            SkUnichar uni = SkUTF16_NextUnichar(&curr);
            uint16_t glyphID = glyphs[i];
            // only sniff if the normal font failed to recognize it
            if (!glyphID)
                glyphID = EmojiFont::UnicharToGlyph(uni);
            setGlyphDataForIndex(offset + i, glyphID, fontData);
            allGlyphs |= glyphID;
        }
    } else {
        for (unsigned i = 0; i < length; i++) {
            uint16_t glyphID = glyphs[i];
            setGlyphDataForIndex(offset + i, glyphID, fontData);
            allGlyphs |= glyphID;
        }
    }
    return allGlyphs != 0;
}