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