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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }