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; }
bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const { if (U16_IS_LEAD(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 SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const { if (U16_IS_LEAD(buffer[bufferLength-1])) { DLOG(ERROR) << "Last UTF-16 code unit is high-surrogate."; return false; } SkTypeface* typeface = platformData().typeface(); if (!typeface) { DLOG(ERROR) << "fillGlyphPage called on an empty Skia typeface."; return false; } SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length); uint16_t* glyphs = glyphStorage.get(); 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; }
static void drawKernText(SkCanvas* canvas, const void* text, size_t len, SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) { SkTypeface* face = font.getTypefaceOrDefault(); if (!face) { canvas->drawSimpleText(text, len, SkTextEncoding::kUTF8, x, y, font, paint); return; } SkAutoSTMalloc<128, uint16_t> glyphStorage(len); uint16_t* glyphs = glyphStorage.get(); int glyphCount = font.textToGlyphs(text, len, SkTextEncoding::kUTF8, glyphs, len); if (glyphCount < 1) { return; } SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1); int32_t* adjustments = adjustmentStorage.get(); if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) { canvas->drawSimpleText(text, len, SkTextEncoding::kUTF8, x, y, font, paint); return; } SkTextBlobBuilder builder; auto rec = builder.allocRunPos(font, glyphCount); memcpy(rec.glyphs, glyphs, glyphCount * sizeof(SkGlyphID)); getGlyphPositions(font, glyphs, glyphCount, x, y, rec.points()); applyKerning(rec.points(), adjustments, glyphCount, font); canvas->drawTextBlob(builder.make(), 0, 0, paint); }
static void drawKernText(SkCanvas* canvas, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { SkTypeface* face = paint.getTypeface(); if (!face) { canvas->drawText(text, len, x, y, paint); return; } SkAutoSTMalloc<128, uint16_t> glyphStorage(len); uint16_t* glyphs = glyphStorage.get(); int glyphCount = paint.textToGlyphs(text, len, glyphs); if (glyphCount < 1) { return; } SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1); int32_t* adjustments = adjustmentStorage.get(); if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) { canvas->drawText(text, len, x, y, paint); return; } SkPaint glyphPaint(paint); glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); SkAutoSTMalloc<128, SkPoint> posStorage(glyphCount); SkPoint* pos = posStorage.get(); getGlyphPositions(glyphPaint, glyphs, glyphCount, x, y, pos); applyKerning(pos, adjustments, glyphCount, glyphPaint); canvas->drawPosText(glyphs, glyphCount * sizeof(uint16_t), pos, glyphPaint); }
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(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 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; }