180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2009 The Android Open Source Project 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkHarfBuzzFont.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFontHost.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPaint.h" 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// HB_Fixed is a 26.6 fixed point format. 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline HB_Fixed SkScalarToHarfbuzzFixed(SkScalar value) { 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return static_cast<HB_Fixed>(value * 64); 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // convert .16 to .6 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value >> (16 - 6); 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru hb_uint32 length, HB_Glyph* glyphs, 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru hb_uint32* glyphsSize, HB_Bool isRTL) { 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPaint paint; 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.setTypeface(font->getTypeface()); 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru reinterpret_cast<uint16_t*>(glyphs)); 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // |glyphs| array needs to be converted. 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = numGlyphs - 1; i >= 0; --i) { 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint16_t value; 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // We use a memcpy to avoid breaking strict aliasing rules. 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, sizeof(uint16_t)); 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru glyphs[i] = value; 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *glyphsSize = numGlyphs; 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 1; 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru hb_uint32 numGlyphs, HB_Fixed* advances, int flags) { 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPaint paint; 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru font->setupPaint(&paint); 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoMalloc storage(numGlyphs * (sizeof(SkScalar) + sizeof(uint16_t))); 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar* scalarWidths = reinterpret_cast<SkScalar*>(storage.get()); 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint16_t* glyphs16 = reinterpret_cast<uint16_t*>(scalarWidths + numGlyphs); 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // convert HB 32bit glyphs to skia's 16bit 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (hb_uint32 i = 0; i < numGlyphs; ++i) { 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru glyphs16[i] = SkToU16(glyphs[i]); 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.getTextWidths(glyphs16, numGlyphs * sizeof(uint16_t), scalarWidths); 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (hb_uint32 i = 0; i < numGlyphs; ++i) { 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru advances[i] = SkScalarToHarfbuzzFixed(scalarWidths[i]); 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru hb_uint32 length) { 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPaint paint; 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.setTypeface(font->getTypeface()); 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return paint.containsText(characters, length * sizeof(uint16_t)); 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru hb_uint32 index, HB_Fixed* xPos, HB_Fixed* yPos, 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru hb_uint32* resultingNumPoints) { 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPaint paint; 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru font->setupPaint(&paint); 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (flags & HB_ShaperFlag_UseDesignMetrics) { 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.setHinting(SkPaint::kNo_Hinting); 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPath path; 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint16_t glyph16 = SkToU16(glyph); 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int numPoints = path.countPoints(); 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (index >= numPoints) { 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return HB_Err_Invalid_SubTable; 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint pt = path.getPoint(index); 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *xPos = SkScalarToHarfbuzzFixed(pt.fX); 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *yPos = SkScalarToHarfbuzzFixed(pt.fY); 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *resultingNumPoints = numPoints; 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return HB_Err_Ok; 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru HB_GlyphMetrics* metrics) { 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPaint paint; 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru font->setupPaint(&paint); 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar width; 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkRect bounds; 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint16_t glyph16 = SkToU16(glyph); 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru metrics->x = SkScalarToHarfbuzzFixed(bounds.fLeft); 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru metrics->y = SkScalarToHarfbuzzFixed(bounds.fTop); 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru metrics->width = SkScalarToHarfbuzzFixed(bounds.width()); 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru metrics->height = SkScalarToHarfbuzzFixed(bounds.height()); 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru metrics->xOffset = SkScalarToHarfbuzzFixed(width); 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // We can't actually get the |y| correct because Skia doesn't export 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // the vertical advance. However, nor we do ever render vertical text at 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // the moment so it's unimportant. 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru metrics->yOffset = 0; 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPaint paint; 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPaint::FontMetrics skiaMetrics; 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru font->setupPaint(&paint); 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru paint.getFontMetrics(&skiaMetrics); 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru switch (metric) { 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case HB_FontAscent: 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkScalarToHarfbuzzFixed(-skiaMetrics.fAscent); 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru default: 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf("--- unknown harfbuzz metric enum %d\n", metric); 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0; 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic HB_FontClass gSkHarfBuzzFontClass = { 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru stringToGlyphs, 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru glyphsToAdvances, 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru canRender, 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru getOutlinePoint, 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru getGlyphMetrics, 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru getFontMetric, 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst HB_FontClass& SkHarfBuzzFont::GetFontClass() { 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return gSkHarfBuzzFontClass; 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruHB_Error SkHarfBuzzFont::GetFontTableFunc(void* voidface, const HB_Tag tag, 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru HB_Byte* buffer, HB_UInt* len) { 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(voidface); 169e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkTypeface* typeface = font->getTypeface(); 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 171e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const size_t tableSize = typeface->getTableSize(tag); 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!tableSize) { 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return HB_Err_Invalid_Argument; 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // If Harfbuzz specified a NULL buffer then it's asking for the size. 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!buffer) { 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *len = tableSize; 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return HB_Err_Ok; 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (*len < tableSize) { 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // is this right, or should we just copy less than the full table? 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return HB_Err_Invalid_Argument; 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 185e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger typeface->getTableData(tag, 0, tableSize, buffer); 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return HB_Err_Ok; 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 188