bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    // bufferLength will be greater than the requested number of glyphs if the buffer contains surrogate pairs.
    // We won't support this for now.
    if (bufferLength > length)
        return false;

    bool haveGlyphs = false;

    HDC dc = GetDC((HWND)0);
    SaveDC(dc);
    SelectObject(dc, fontData->platformData().hfont());

    TEXTMETRIC tm;
    GetTextMetrics(dc, &tm);

    WORD localGlyphBuffer[GlyphPage::size * 2];
    DWORD result = GetGlyphIndices(dc, buffer, bufferLength, localGlyphBuffer, 0);
    bool success = result != GDI_ERROR && static_cast<unsigned>(result) == bufferLength;
    if (success) {
        for (unsigned i = 0; i < length; i++) {
            Glyph glyph = localGlyphBuffer[i];
            if (!glyph)
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyph, fontData);
                haveGlyphs = true;
            }
        }
    }
    RestoreDC(dc, -1);
    ReleaseDC(0, dc);

    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const Font* fontData)
{
    cairo_scaled_font_t* scaledFont = fontData->platformData().scaledFont();
    ASSERT(scaledFont);

    FT_Face face = cairo_ft_scaled_font_lock_face(scaledFont);
    if (!face)
        return false;

    bool haveGlyphs = false;
    UTF16UChar32Iterator iterator(buffer, bufferLength);
    for (unsigned i = 0; i < length; i++) {
        UChar32 character = iterator.next();
        if (character == iterator.end())
            break;

        Glyph glyph = FcFreeTypeCharIndex(face, character);
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
    }

    cairo_ft_scaled_font_unlock_face(scaledFont);
    return haveGlyphs;
}
Example #3
0
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    // The bufferLength will be greater than the glyph page size if the buffer has Unicode supplementary characters.
    // We won't support this for now.
    if (bufferLength > GlyphPage::size)
        return false;

    cairo_scaled_font_t* scaledFont = fontData->platformData().scaledFont();
    if (!scaledFont)
        return false;

    FT_Face face = cairo_ft_scaled_font_lock_face(scaledFont);
    if (!face)
        return false;

    bool haveGlyphs = false;
    for (unsigned i = 0; i < length; i++) {
        Glyph glyph = FcFreeTypeCharIndex(face, buffer[i]);
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
    }

    cairo_ft_scaled_font_unlock_face(scaledFont);
    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool haveGlyphs = false;

#ifndef BUILDING_ON_TIGER
    Vector<CGGlyph, 512> glyphs(bufferLength);
    wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);

    for (unsigned i = 0; i < length; ++i) {
        if (!glyphs[i])
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyphs[i], fontData);
            haveGlyphs = true;
        }
    }
#else
    // Use an array of long so we get good enough alignment.
    long glyphVector[(GLYPH_VECTOR_SIZE + sizeof(long) - 1) / sizeof(long)];
    
    OSStatus status = wkInitializeGlyphVector(GlyphPage::size, &glyphVector);
    if (status != noErr)
        // This should never happen, perhaps indicates a bad font!  If it does the
        // font substitution code will find an alternate font.
        return false;

    wkConvertCharToGlyphs(fontData->m_styleGroup, buffer, bufferLength, &glyphVector);

    unsigned numGlyphs = wkGetGlyphVectorNumGlyphs(&glyphVector);
    if (numGlyphs != length) {
        // This should never happen, perhaps indicates a bad font?
        // If it does happen, the font substitution code will find an alternate font.
        wkClearGlyphVector(&glyphVector);
        return false;
    }

    ATSLayoutRecord* glyphRecord = (ATSLayoutRecord*)wkGetGlyphVectorFirstRecord(glyphVector);
    for (unsigned i = 0; i < length; i++) {
        Glyph glyph = glyphRecord->glyphID;
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
        glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector));
    }
    wkClearGlyphVector(&glyphVector);
#endif

    return haveGlyphs;
}
bool BTGlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData)
{
    for (unsigned i = 0; i < bufferLength; i++)
        setGlyphDataForIndex(i, static_cast<uint8_t> (buffer[i]), fontData);

    return true;
}
bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData)
{
    // Use an array of long so we get good enough alignment.
    long glyphVector[(GLYPH_VECTOR_SIZE + sizeof(long) - 1) / sizeof(long)];
    
    OSStatus status = wkInitializeGlyphVector(GlyphPage::size, &glyphVector);
    if (status != noErr)
        // This should never happen, perhaps indicates a bad font!  If it does the
        // font substitution code will find an alternate font.
        return false;

    wkConvertCharToGlyphs(fontData->m_styleGroup, buffer, bufferLength, &glyphVector);

    unsigned numGlyphs = wkGetGlyphVectorNumGlyphs(&glyphVector);
    if (numGlyphs != GlyphPage::size) {
        // This should never happen, perhaps indicates a bad font?
        // If it does happen, the font substitution code will find an alternate font.
        wkClearGlyphVector(&glyphVector);
        return false;
    }

    bool haveGlyphs = false;
    ATSLayoutRecord* glyphRecord = (ATSLayoutRecord*)wkGetGlyphVectorFirstRecord(glyphVector);
    for (unsigned i = 0; i < GlyphPage::size; i++) {
        Glyph glyph = glyphRecord->glyphID;
        setGlyphDataForIndex(i, glyph, fontData);
        if (!haveGlyphs && glyph)
            haveGlyphs = true;
        glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector));
    }
    wkClearGlyphVector(&glyphVector);

    return haveGlyphs;
}
Example #7
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;
}
Example #8
0
 MixedFontGlyphPage(const GlyphPage* initialPage)
 {
     if (initialPage) {
         for (unsigned i = 0; i < GlyphPage::size; ++i)
             setGlyphDataForIndex(i, initialPage->glyphDataForIndex(i));
     }
 }
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    QRawFont rawFont = fontData->platformData().rawFont();
    QString qstring = QString::fromRawData(reinterpret_cast<const QChar*>(buffer), static_cast<int>(bufferLength));
    QVector<quint32> indexes = rawFont.glyphIndexesForString(qstring);

    bool haveGlyphs = false;

    for (unsigned i = 0; i < length; ++i) {
        Glyph glyph = (i < indexes.size()) ? indexes.at(i) : 0;
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            haveGlyphs = true;
            setGlyphDataForIndex(offset + i, glyph, fontData);
        }
    }
    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();
    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 #11
0
bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const Font* fontData)
{
    bool haveGlyphs = false;

    Vector<CGGlyph, 512> glyphs(bufferLength);
    if (!shouldUseCoreText(buffer, bufferLength, fontData)) {
        // We pass in either 256 or 512 UTF-16 characters: 256 for U+FFFF and less, 512 (double character surrogates)
        // for U+10000 and above. It is indeed possible to get back 512 glyphs back from the API, so the glyph buffer
        // we pass in must be 512. If we get back more than 256 glyphs though we'll ignore all the ones after 256,
        // this should not happen as the only time we pass in 512 characters is when they are surrogates.
        CGFontGetGlyphsForUnichars(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
        for (unsigned i = 0; i < GlyphPage::size; ++i) {
            if (!glyphs[i])
                setGlyphDataForIndex(i, 0, 0);
            else {
                setGlyphDataForIndex(i, glyphs[i], fontData);
                haveGlyphs = true;
            }
        }
    } else {
        // Because we know the implementation of shouldUseCoreText(), if the font isn't for text combine and it isn't a system font,
        // we know it must have vertical glyphs.
        if (fontData->platformData().isForTextCombine() || fontData->isSystemFont())
            CTFontGetGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength);
        else
            CTFontGetVerticalGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength);
        // When buffer consists of surrogate pairs, CTFontGetVerticalGlyphsForCharacters and CTFontGetGlyphsForCharacters
        // place the glyphs at indices corresponding to the first character of each pair.
        ASSERT(bufferLength == GlyphPage::size || bufferLength == 2 * GlyphPage::size);
        unsigned glyphStep = bufferLength / GlyphPage::size;
        for (unsigned i = 0; i < GlyphPage::size; ++i) {
            if (!glyphs[i * glyphStep])
                setGlyphDataForIndex(i, 0, 0);
            else {
                setGlyphDataForIndex(i, glyphs[i * glyphStep], fontData);
                haveGlyphs = true;
            }
        }
    }

    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    if (length != bufferLength)
        return false;

    if (fontData->platformData().hfont()) {
        DWORD fontCodePages = fontData->platformData().codePages();
        if (fontCodePages) {
            if (getCharCodePages) {
                unsigned lastPos = 0;
                for (unsigned i = 0; i < bufferLength; ++i) {
                    DWORD actualCodePages = getCharCodePages(buffer[i], lastPos);
                    if (!actualCodePages || (actualCodePages & fontCodePages))
                        setGlyphDataForIndex(offset + i, buffer[i], fontData);
                    else
                        setGlyphDataForIndex(offset + i, buffer[i], 0);
                }
                return true;
#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
            } else if (IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface()) {
#else
            } else if (IMLangFontLink* langFontLink = fontCache()->getFontLinkInterface()) {
#endif
                for (unsigned i = 0; i < bufferLength; ++i) {
                    DWORD actualCodePages;
                    langFontLink->GetCharCodePages(buffer[i], &actualCodePages);
                    if (!actualCodePages || (actualCodePages & fontCodePages))
                        setGlyphDataForIndex(offset + i, buffer[i], fontData);
                    else
                        setGlyphDataForIndex(offset + i, buffer[i], 0);
                }
                return true;
            }
        }
    }

    for (unsigned i = 0; i < length; ++i)
        setGlyphDataForIndex(offset + i, buffer[i], fontData);

    return true;
}
bool BTGlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData)
{
    FT_Face face = static_cast<BCFontPlatformDataPrivateFT *> (fontData->platformData().impl())->ftFace();

    if (!face)
        return false;

    for (unsigned i = 0; i < bufferLength; i++)
        setGlyphDataForIndex(i, FT_Get_Char_Index(face, buffer[i]), fontData);

    return true;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    // bufferLength will be greater than the requested number of glyphs if the buffer contains surrogate pairs.
    // We won't support this for now.
    if (bufferLength > length)
        return false;

    bool haveGlyphs = false;
    CGGlyph localGlyphBuffer[GlyphPage::size];
    wkGetGlyphs(fontData->platformData().cgFont(), buffer, localGlyphBuffer, bufferLength);
    for (unsigned i = 0; i < length; i++) {
        Glyph glyph = localGlyphBuffer[i];
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
    }
    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* charBuffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    const bool isUtf16 = (bufferLength != length);

    for (unsigned i = 0; i < length; ++i) {
        Glyph character = isUtf16
            ? U16_GET_SUPPLEMENTARY(charBuffer[i*2], charBuffer[i*2 + 1])
            : charBuffer[i];

        setGlyphDataForIndex(offset + i, character, fontData);
    }
    return true;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    if (bufferLength > GlyphPage::size)
        return false;

    FT_Face face = fontData->m_font.m_face;

    if (!face)
        return false;

    bool haveGlyphs = false;
    for (unsigned i = 0; i < bufferLength; i++) {
        Glyph glyph = FT_Get_Char_Index(face, buffer[i]);
        if (!glyph)
            setGlyphDataForIndex(i, 0, 0);
        else {
            setGlyphDataForIndex(i, glyph, fontData);
            haveGlyphs = true;
        }
    }

    return haveGlyphs;
}
Example #17
0
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    // The bufferLength will be greater than the glyph page size if the buffer has Unicode supplementary characters.
    // We won't support this for now.
    if (bufferLength > GlyphPage::size)
        return false;

    if (!fontData->platformData().m_font || fontData->platformData().m_font == reinterpret_cast<PangoFont*>(-1))
        return false;

    bool haveGlyphs = false;
    for (unsigned i = 0; i < length; i++) {
        Glyph glyph = pango_font_get_glyph(fontData->platformData().m_font, fontData->platformData().m_context, buffer[i]);
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
    }

    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool haveGlyphs = false;
    unsigned position = 0;
    int i = 0;
    while (position < bufferLength) {
        UChar32 character;
        unsigned nextPosition = position;
        U16_NEXT(buffer, nextPosition, bufferLength, character);

        FS_USHORT glyph = FS_map_char(fontData->platformData().font(), static_cast<FS_ULONG>(character));
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            haveGlyphs = true;
            setGlyphDataForIndex(offset + i, glyph, fontData);
        }

        i++;
        position = nextPosition;
    }

    return haveGlyphs;
}
bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData)
{
    HDC dc = GetDC((HWND)0);
    SaveDC(dc);
    SelectObject(dc, fontData->m_font.hfont());

    TEXTMETRIC tm;
    GetTextMetrics(dc, &tm);
    WORD localGlyphBuffer[GlyphPage::size];
    GetGlyphIndices(dc, buffer, bufferLength, localGlyphBuffer, 0);
    for (unsigned i = 0; i < GlyphPage::size; i++)
        setGlyphDataForIndex(i, localGlyphBuffer[i], fontData);
    RestoreDC(dc, -1);
    ReleaseDC(0, dc);
    return true;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool isUtf16 = bufferLength != length;

    for (unsigned i = 0; i < length; i++) {
        UChar32 character;

        if(isUtf16) {
            UChar lead = buffer[i * 2];
            UChar trail = buffer[i * 2 + 1];
            character = U16_GET_SUPPLEMENTARY(lead, trail);
        } else {
            character = buffer[i];
        }

        setGlyphDataForIndex(offset + i, character, fontData);
    }

    return true;
}
Example #21
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;
}
Example #22
0
 void setGlyphDataForCharacter(UChar32 c, GlyphData glyphData)
 {
     setGlyphDataForIndex(GlyphPage::indexForCharacter(c), glyphData);
 }
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool haveGlyphs = false;

    Vector<CGGlyph, 512> glyphs(bufferLength);
    if (!shouldUseCoreText(buffer, bufferLength, fontData)) {
        // We pass in either 256 or 512 UTF-16 characters: 256 for U+FFFF and less, 512 (double character surrogates)
        // for U+10000 and above. It is indeed possible to get back 512 glyphs back from the API, so the glyph buffer
        // we pass in must be 512. If we get back more than 256 glyphs though we'll ignore all the ones after 256,
        // this should not happen as the only time we pass in 512 characters is when they are surrogates.
        CGFontGetGlyphsForUnichars(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
        for (unsigned i = 0; i < length; ++i) {
            if (!glyphs[i])
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyphs[i], fontData);
                haveGlyphs = true;
            }
        }
    } else if (!fontData->platformData().isCompositeFontReference() && ((fontData->platformData().widthVariant() == RegularWidth) ? wkGetVerticalGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength)
               : CTFontGetGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength))) {
        // When buffer consists of surrogate pairs, wkGetVerticalGlyphsForCharacters and CTFontGetGlyphsForCharacters
        // place the glyphs at indices corresponding to the first character of each pair.
        unsigned glyphStep = bufferLength / length;
        for (unsigned i = 0; i < length; ++i) {
            if (!glyphs[i * glyphStep])
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], fontData);
                haveGlyphs = true;
            }
        }
    } else {
        // We ask CoreText for possible vertical variant glyphs
        RetainPtr<CFStringRef> string = adoptCF(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
        RetainPtr<CFAttributedStringRef> attributedString = adoptCF(CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal)));
        RetainPtr<CTLineRef> line = adoptCF(CTLineCreateWithAttributedString(attributedString.get()));

        CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
        CFIndex runCount = CFArrayGetCount(runArray);

        // Initialize glyph entries
        for (unsigned index = 0; index < length; ++index)
            setGlyphDataForIndex(offset + index, 0, 0);

        Vector<CGGlyph, 512> glyphVector;
        Vector<CFIndex, 512> indexVector;
        bool done = false;

        // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may
        // be non-CFEqual to fontData->platformData().cgFont().
        RetainPtr<CGFontRef> cgFont = adoptCF(CTFontCopyGraphicsFont(fontData->platformData().ctFont(), 0));

        for (CFIndex r = 0; r < runCount && !done ; ++r) {
            // CTLine could map characters over multiple fonts using its own font fallback list.
            // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont().
            CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
            ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());

            CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
            CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
            RetainPtr<CGFontRef> runCGFont = adoptCF(CTFontCopyGraphicsFont(runFont, 0));
            // Use CGFont here as CFEqual for CTFont counts all attributes for font.
            bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get());
            if (gotBaseFont || fontData->platformData().isCompositeFontReference()) {
                // This run uses the font we want. Extract glyphs.
                CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
                const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
                if (!glyphs) {
                    glyphVector.resize(glyphCount);
                    CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
                    glyphs = glyphVector.data();
                }
                const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
                if (!stringIndices) {
                    indexVector.resize(glyphCount);
                    CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
                    stringIndices = indexVector.data();
                }

                if (gotBaseFont) {
                    for (CFIndex i = 0; i < glyphCount; ++i) {
                        if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                            done = true;
                            break;
                        }
                        if (glyphs[i]) {
                            setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
                            haveGlyphs = true;
                        }
                    }
#if !PLATFORM(IOS)
                } else {
                    const SimpleFontData* runSimple = fontData->getCompositeFontReferenceFontData((NSFont *)runFont);
                    if (runSimple) {
                        for (CFIndex i = 0; i < glyphCount; ++i) {
                            if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                                done = true;
                                break;
                            }
                            if (glyphs[i]) {
                                setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple);
                                haveGlyphs = true;
                            }
                        }
                    }
#endif // !PLATFORM(IOS)
                }
            }
        }
    }

    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool haveGlyphs = false;

#ifndef BUILDING_ON_TIGER
    if (fontData->orientation() == Horizontal || fontData->isBrokenIdeographFont()) {
        Vector<CGGlyph, 512> glyphs(bufferLength);
        wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
        for (unsigned i = 0; i < length; ++i) {
            if (!glyphs[i])
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyphs[i], fontData);
                haveGlyphs = true;
            }
        }
    } else {
        // We ask CoreText for possible vertical variant glyphs
        RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
        RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0)));
        RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));

        CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
        CFIndex runCount = CFArrayGetCount(runArray);

        // Initialize glyph entries
        for (unsigned index = 0; index < length; ++index)
            setGlyphDataForIndex(offset + index, 0, 0);

        Vector<CGGlyph, 512> glyphVector;
        Vector<CFIndex, 512> indexVector;
        bool done = false;
        for (CFIndex r = 0; r < runCount && !done ; ++r) {
            // CTLine could map characters over multiple fonts using its own font fallback list.
            // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont().
            CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
            ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());

            CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
            CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
            RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
            // Use CGFont here as CFEqual for CTFont counts all attributes for font.
            if (CFEqual(fontData->platformData().cgFont(), runCGFont.get())) {
                // This run uses the font we want. Extract glyphs.
                CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
                const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
                if (!glyphs) {
                    glyphVector.resize(glyphCount);
                    CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
                    glyphs = glyphVector.data();
                }
                const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
                if (!stringIndices) {
                    indexVector.resize(glyphCount);
                    CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
                    stringIndices = indexVector.data();
                }

                for (CFIndex i = 0; i < glyphCount; ++i) {
                    if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                        done = true;
                        break;
                    }
                    if (glyphs[i]) {
                        setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
                        haveGlyphs = true;
                    }
                }
            }
        }
    }
#else
    // Use an array of long so we get good enough alignment.
    long glyphVector[(GLYPH_VECTOR_SIZE + sizeof(long) - 1) / sizeof(long)];
    
    OSStatus status = wkInitializeGlyphVector(GlyphPage::size, &glyphVector);
    if (status != noErr)
        // This should never happen, perhaps indicates a bad font!  If it does the
        // font substitution code will find an alternate font.
        return false;

    wkConvertCharToGlyphs(fontData->m_styleGroup, buffer, bufferLength, &glyphVector);

    unsigned numGlyphs = wkGetGlyphVectorNumGlyphs(&glyphVector);
    if (numGlyphs != length) {
        // This should never happen, perhaps indicates a bad font?
        // If it does happen, the font substitution code will find an alternate font.
        wkClearGlyphVector(&glyphVector);
        return false;
    }

    ATSLayoutRecord* glyphRecord = (ATSLayoutRecord*)wkGetGlyphVectorFirstRecord(glyphVector);
    for (unsigned i = 0; i < length; i++) {
        Glyph glyph = glyphRecord->glyphID;
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
        glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector));
    }
    wkClearGlyphVector(&glyphVector);
#endif

    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool haveGlyphs = false;

    if (!shouldUseCoreText(buffer, bufferLength, fontData)) {
        Vector<CGGlyph, 512> glyphs(bufferLength);

        CMFontGetGlyphsForUnichars(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
//        wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);

        for (unsigned i = 0; i < length; ++i) {
            if (!glyphs[i])
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyphs[i], fontData);
                haveGlyphs = true;
            }
        }
    } else {
        // We ask CoreText for possible vertical variant glyphs
        RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
        RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal)));
        RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));

        CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
        CFIndex runCount = CFArrayGetCount(runArray);

        // Initialize glyph entries
        for (unsigned index = 0; index < length; ++index)
            setGlyphDataForIndex(offset + index, 0, 0);

        Vector<CGGlyph, 512> glyphVector;
        Vector<CFIndex, 512> indexVector;
        bool done = false;

        // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may
        // be non-CFEqual to fontData->platformData().cgFont().
        RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(fontData->platformData().ctFont(), 0));

        for (CFIndex r = 0; r < runCount && !done ; ++r) {
            // CTLine could map characters over multiple fonts using its own font fallback list.
            // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont().
            CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
            ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());

            CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
            CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
            RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
            // Use CGFont here as CFEqual for CTFont counts all attributes for font.
            if (CFEqual(cgFont.get(), runCGFont.get())) {
                // This run uses the font we want. Extract glyphs.
                CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
                const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
                if (!glyphs) {
                    glyphVector.resize(glyphCount);
                    CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
                    glyphs = glyphVector.data();
                }
                const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
                if (!stringIndices) {
                    indexVector.resize(glyphCount);
                    CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
                    stringIndices = indexVector.data();
                }

                for (CFIndex i = 0; i < glyphCount; ++i) {
                    if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                        done = true;
                        break;
                    }
                    if (glyphs[i]) {
                        setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
                        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;
}