19f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio/* 29f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * Copyright 2011, The Android Open Source Project 39f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * Copyright 2011, Google Inc. All rights reserved. 49f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * 59f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * Redistribution and use in source and binary forms, with or without 69f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * modification, are permitted provided that the following conditions 79f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * are met: 89f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * * Redistributions of source code must retain the above copyright 99f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * notice, this list of conditions and the following disclaimer. 109f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * * Redistributions in binary form must reproduce the above copyright 119f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * notice, this list of conditions and the following disclaimer in the 129f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * documentation and/or other materials provided with the distribution. 139f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * 149f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 159f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 169f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 179f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 189f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 199f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 209f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 219f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 229f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 239f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 249f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 259f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio */ 269f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 27208d4592f6e8db90eab30cfca3dc294731258d1cFabrice Di Meglio#define LOG_TAG "HarfbuzzSkia" 28208d4592f6e8db90eab30cfca3dc294731258d1cFabrice Di Meglio 299f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "HarfbuzzSkia.h" 309f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 319f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "SkFontHost.h" 329f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 339f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "SkPaint.h" 349f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "SkPath.h" 359f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "SkPoint.h" 369f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "SkRect.h" 379f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "SkTypeface.h" 389f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 39eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <utils/Log.h> 40eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 419f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglioextern "C" { 429f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "harfbuzz-shaper.h" 439f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} 449f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 459f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio// This file implements the callbacks which Harfbuzz requires by using Skia 469f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio// calls. See the Harfbuzz source for references about what these callbacks do. 479f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 489f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglionamespace android { 499f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 509f82b580d744ce4baf057b061994394dcf239eedFabrice Di Megliostatic HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length, 519f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio HB_Glyph* glyphs, hb_uint32* glyphsSize, HB_Bool isRTL) 529f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio{ 530af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); 540af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); 559f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 56eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio uint16_t* skiaGlyphs = reinterpret_cast<uint16_t*>(glyphs); 570af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio int numGlyphs = paint->textToGlyphs(characters, length * sizeof(uint16_t), skiaGlyphs); 589f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 599f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our 609f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // |glyphs| array needs to be converted. 619f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio for (int i = numGlyphs - 1; i >= 0; --i) { 62eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio glyphs[i] = skiaGlyphs[i]; 639f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio } 649f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 659f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio *glyphsSize = numGlyphs; 669f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return 1; 679f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} 689f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 699f82b580d744ce4baf057b061994394dcf239eedFabrice Di Megliostatic void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, hb_uint32 numGlyphs, 709f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio HB_Fixed* advances, int flags) 719f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio{ 720af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); 730af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 749f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 759f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio uint16_t* glyphs16 = new uint16_t[numGlyphs]; 769f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio if (!glyphs16) 779f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return; 789f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio for (unsigned i = 0; i < numGlyphs; ++i) 799f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio glyphs16[i] = glyphs[i]; 80eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio SkScalar* scalarAdvances = reinterpret_cast<SkScalar*>(advances); 810af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->getTextWidths(glyphs16, numGlyphs * sizeof(uint16_t), scalarAdvances); 829f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 839f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // The |advances| values which Skia outputs are SkScalars, which are floats 849f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // in Chromium. However, Harfbuzz wants them in 26.6 fixed point format. 859f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // These two formats are both 32-bits long. 869f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio for (unsigned i = 0; i < numGlyphs; ++i) { 87eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio advances[i] = SkScalarToHBFixed(scalarAdvances[i]); 88eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#if DEBUG_ADVANCES 895baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("glyphsToAdvances -- advances[%d]=%d", i, advances[i]); 90eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#endif 919f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio } 929f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio delete glyphs16; 939f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} 949f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 959f82b580d744ce4baf057b061994394dcf239eedFabrice Di Megliostatic HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length) 969f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio{ 970af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); 980af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); 999f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1009f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio uint16_t* glyphs16 = new uint16_t[length]; 1010af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio int numGlyphs = paint->textToGlyphs(characters, length * sizeof(uint16_t), glyphs16); 1029f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1039f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio bool result = true; 1049f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio for (int i = 0; i < numGlyphs; ++i) { 1059f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio if (!glyphs16[i]) { 1069f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio result = false; 1079f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio break; 1089f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio } 1099f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio } 1109f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio delete glyphs16; 1119f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return result; 1129f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} 1139f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1149f82b580d744ce4baf057b061994394dcf239eedFabrice Di Megliostatic HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_uint32 point, 1159f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio HB_Fixed* xPos, HB_Fixed* yPos, hb_uint32* resultingNumPoints) 1169f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio{ 1179f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio if (flags & HB_ShaperFlag_UseDesignMetrics) 1189f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // This is requesting pre-hinted positions. We can't support this. 1199f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return HB_Err_Invalid_Argument; 1209f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1210af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); 1220af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 1230af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio 1249f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio uint16_t glyph16 = glyph; 1259f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio SkPath path; 1260af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); 1279f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio uint32_t numPoints = path.getPoints(0, 0); 1289f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio if (point >= numPoints) 1299f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return HB_Err_Invalid_SubTable; 1300af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio SkPoint* points = static_cast<SkPoint*>(malloc(sizeof(SkPoint) * (point + 1))); 1319f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio if (!points) 1329f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return HB_Err_Invalid_SubTable; 1339f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // Skia does let us get a single point from the path. 1349f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio path.getPoints(points, point + 1); 135eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio *xPos = SkScalarToHBFixed(points[point].fX); 136eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio *yPos = SkScalarToHBFixed(points[point].fY); 1379f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio *resultingNumPoints = numPoints; 1389f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio delete points; 1399f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1409f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return HB_Err_Ok; 1419f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} 1429f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1439f82b580d744ce4baf057b061994394dcf239eedFabrice Di Megliostatic void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, HB_GlyphMetrics* metrics) 1449f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio{ 1450af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); 1460af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 1479f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1489f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio uint16_t glyph16 = glyph; 1499f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio SkScalar width; 1509f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio SkRect bounds; 1510af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); 1529f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 153eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio metrics->x = SkScalarToHBFixed(bounds.fLeft); 154eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio metrics->y = SkScalarToHBFixed(bounds.fTop); 155eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio metrics->width = SkScalarToHBFixed(bounds.width()); 156eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio metrics->height = SkScalarToHBFixed(bounds.height()); 1579f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 158eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio metrics->xOffset = SkScalarToHBFixed(width); 1599f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // We can't actually get the |y| correct because Skia doesn't export 1609f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // the vertical advance. However, nor we do ever render vertical text at 1619f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // the moment so it's unimportant. 1629f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio metrics->yOffset = 0; 1639f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} 1649f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1659f82b580d744ce4baf057b061994394dcf239eedFabrice Di Megliostatic HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) 1669f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio{ 1670af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); 1689f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1699f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio SkPaint::FontMetrics skiaMetrics; 1700af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio paint->getFontMetrics(&skiaMetrics); 1719f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1729f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio switch (metric) { 1739f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio case HB_FontAscent: 174eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio return SkScalarToHBFixed(-skiaMetrics.fAscent); 1759f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // We don't support getting the rest of the metrics and Harfbuzz doesn't seem to need them. 1769f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio default: 1779f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return 0; 1789f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio } 1799f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return 0; 1809f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} 1819f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1829f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglioconst HB_FontClass harfbuzzSkiaClass = { 1839f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio stringToGlyphs, 1849f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio glyphsToAdvances, 1859f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio canRender, 1869f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio getOutlinePoint, 1879f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio getGlyphMetrics, 1889f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio getFontMetric, 1899f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio}; 1909f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 1910af10b54bf110653b74cb92793484b412a90b657Fabrice Di MeglioHB_Error harfbuzzSkiaGetTable(void* font, const HB_Tag tag, HB_Byte* buffer, HB_UInt* len) 1929f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio{ 1930af10b54bf110653b74cb92793484b412a90b657Fabrice Di Meglio SkTypeface* typeface = static_cast<SkTypeface*>(font); 1949f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 195208d4592f6e8db90eab30cfca3dc294731258d1cFabrice Di Meglio if (!typeface) { 1965baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Typeface cannot be null"); 197208d4592f6e8db90eab30cfca3dc294731258d1cFabrice Di Meglio return HB_Err_Invalid_Argument; 198208d4592f6e8db90eab30cfca3dc294731258d1cFabrice Di Meglio } 1999f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio const size_t tableSize = SkFontHost::GetTableSize(typeface->uniqueID(), tag); 2009f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio if (!tableSize) 2019f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return HB_Err_Invalid_Argument; 2029f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio // If Harfbuzz specified a NULL buffer then it's asking for the size of the table. 2039f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio if (!buffer) { 2049f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio *len = tableSize; 2059f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return HB_Err_Ok; 2069f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio } 2079f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 2089f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio if (*len < tableSize) 2099f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return HB_Err_Invalid_Argument; 2109f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio SkFontHost::GetTableData(typeface->uniqueID(), tag, 0, tableSize, buffer); 2119f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio return HB_Err_Ok; 2129f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} 2139f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio 2149f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio} // namespace android 215