| OLD | NEW | 
 | (Empty) | 
|    1  |  | 
|    2 /* |  | 
|    3  * Copyright 2009 The Android Open Source Project |  | 
|    4  * |  | 
|    5  * Use of this source code is governed by a BSD-style license that can be |  | 
|    6  * found in the LICENSE file. |  | 
|    7  */ |  | 
|    8  |  | 
|    9  |  | 
|   10 #include "SkHarfBuzzFont.h" |  | 
|   11 #include "SkFontHost.h" |  | 
|   12 #include "SkPaint.h" |  | 
|   13 #include "SkPath.h" |  | 
|   14  |  | 
|   15 // HB_Fixed is a 26.6 fixed point format. |  | 
|   16 static inline HB_Fixed SkScalarToHarfbuzzFixed(SkScalar value) { |  | 
|   17     return static_cast<HB_Fixed>(value * 64); |  | 
|   18 } |  | 
|   19  |  | 
|   20 static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, |  | 
|   21                               hb_uint32 length, HB_Glyph* glyphs, |  | 
|   22                               hb_uint32* glyphsSize, HB_Bool isRTL) { |  | 
|   23     SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); |  | 
|   24     SkPaint paint; |  | 
|   25  |  | 
|   26     paint.setTypeface(font->getTypeface()); |  | 
|   27     paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); |  | 
|   28     int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), |  | 
|   29                                        reinterpret_cast<uint16_t*>(glyphs)); |  | 
|   30  |  | 
|   31     // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our |  | 
|   32     // |glyphs| array needs to be converted. |  | 
|   33     for (int i = numGlyphs - 1; i >= 0; --i) { |  | 
|   34         uint16_t value; |  | 
|   35         // We use a memcpy to avoid breaking strict aliasing rules. |  | 
|   36         memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, s
     izeof(uint16_t)); |  | 
|   37         glyphs[i] = value; |  | 
|   38     } |  | 
|   39  |  | 
|   40     *glyphsSize = numGlyphs; |  | 
|   41     return 1; |  | 
|   42 } |  | 
|   43  |  | 
|   44 static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, |  | 
|   45                          hb_uint32 numGlyphs, HB_Fixed* advances, int flags) { |  | 
|   46     SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); |  | 
|   47     SkPaint paint; |  | 
|   48  |  | 
|   49     font->setupPaint(&paint); |  | 
|   50     paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |  | 
|   51  |  | 
|   52     SkAutoMalloc storage(numGlyphs * (sizeof(SkScalar) + sizeof(uint16_t))); |  | 
|   53     SkScalar* scalarWidths = reinterpret_cast<SkScalar*>(storage.get()); |  | 
|   54     uint16_t* glyphs16 = reinterpret_cast<uint16_t*>(scalarWidths + numGlyphs); |  | 
|   55  |  | 
|   56     // convert HB 32bit glyphs to skia's 16bit |  | 
|   57     for (hb_uint32 i = 0; i < numGlyphs; ++i) { |  | 
|   58         glyphs16[i] = SkToU16(glyphs[i]); |  | 
|   59     } |  | 
|   60     paint.getTextWidths(glyphs16, numGlyphs * sizeof(uint16_t), scalarWidths); |  | 
|   61  |  | 
|   62     for (hb_uint32 i = 0; i < numGlyphs; ++i) { |  | 
|   63         advances[i] = SkScalarToHarfbuzzFixed(scalarWidths[i]); |  | 
|   64     } |  | 
|   65 } |  | 
|   66  |  | 
|   67 static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, |  | 
|   68                          hb_uint32 length) { |  | 
|   69     SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); |  | 
|   70     SkPaint paint; |  | 
|   71  |  | 
|   72     paint.setTypeface(font->getTypeface()); |  | 
|   73     paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); |  | 
|   74     return paint.containsText(characters, length * sizeof(uint16_t)); |  | 
|   75 } |  | 
|   76  |  | 
|   77 static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, |  | 
|   78                                 hb_uint32 index, HB_Fixed* xPos, HB_Fixed* yPos, |  | 
|   79                                 hb_uint32* resultingNumPoints) { |  | 
|   80     SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); |  | 
|   81     SkPaint paint; |  | 
|   82  |  | 
|   83     font->setupPaint(&paint); |  | 
|   84     paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |  | 
|   85     if (flags & HB_ShaperFlag_UseDesignMetrics) { |  | 
|   86         paint.setHinting(SkPaint::kNo_Hinting); |  | 
|   87     } |  | 
|   88  |  | 
|   89     SkPath path; |  | 
|   90     uint16_t glyph16 = SkToU16(glyph); |  | 
|   91     paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); |  | 
|   92     int numPoints = path.countPoints(); |  | 
|   93     if (index >= numPoints) { |  | 
|   94         return HB_Err_Invalid_SubTable; |  | 
|   95     } |  | 
|   96  |  | 
|   97     SkPoint pt = path.getPoint(index); |  | 
|   98     *xPos = SkScalarToHarfbuzzFixed(pt.fX); |  | 
|   99     *yPos = SkScalarToHarfbuzzFixed(pt.fY); |  | 
|  100     *resultingNumPoints = numPoints; |  | 
|  101  |  | 
|  102     return HB_Err_Ok; |  | 
|  103 } |  | 
|  104  |  | 
|  105 static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, |  | 
|  106                             HB_GlyphMetrics* metrics) { |  | 
|  107     SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); |  | 
|  108     SkPaint paint; |  | 
|  109  |  | 
|  110     font->setupPaint(&paint); |  | 
|  111     paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |  | 
|  112  |  | 
|  113     SkScalar width; |  | 
|  114     SkRect bounds; |  | 
|  115     uint16_t glyph16 = SkToU16(glyph); |  | 
|  116     paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); |  | 
|  117  |  | 
|  118     metrics->x = SkScalarToHarfbuzzFixed(bounds.fLeft); |  | 
|  119     metrics->y = SkScalarToHarfbuzzFixed(bounds.fTop); |  | 
|  120     metrics->width = SkScalarToHarfbuzzFixed(bounds.width()); |  | 
|  121     metrics->height = SkScalarToHarfbuzzFixed(bounds.height()); |  | 
|  122  |  | 
|  123     metrics->xOffset = SkScalarToHarfbuzzFixed(width); |  | 
|  124     // We can't actually get the |y| correct because Skia doesn't export |  | 
|  125     // the vertical advance. However, nor we do ever render vertical text at |  | 
|  126     // the moment so it's unimportant. |  | 
|  127     metrics->yOffset = 0; |  | 
|  128 } |  | 
|  129  |  | 
|  130 static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) |  | 
|  131 { |  | 
|  132     SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData); |  | 
|  133     SkPaint paint; |  | 
|  134     SkPaint::FontMetrics skiaMetrics; |  | 
|  135  |  | 
|  136     font->setupPaint(&paint); |  | 
|  137     paint.getFontMetrics(&skiaMetrics); |  | 
|  138  |  | 
|  139     switch (metric) { |  | 
|  140     case HB_FontAscent: |  | 
|  141         return SkScalarToHarfbuzzFixed(-skiaMetrics.fAscent); |  | 
|  142     default: |  | 
|  143         SkDebugf("--- unknown harfbuzz metric enum %d\n", metric); |  | 
|  144         return 0; |  | 
|  145     } |  | 
|  146 } |  | 
|  147  |  | 
|  148 static HB_FontClass gSkHarfBuzzFontClass = { |  | 
|  149     stringToGlyphs, |  | 
|  150     glyphsToAdvances, |  | 
|  151     canRender, |  | 
|  152     getOutlinePoint, |  | 
|  153     getGlyphMetrics, |  | 
|  154     getFontMetric, |  | 
|  155 }; |  | 
|  156  |  | 
|  157 const HB_FontClass& SkHarfBuzzFont::GetFontClass() { |  | 
|  158     return gSkHarfBuzzFontClass; |  | 
|  159 } |  | 
|  160  |  | 
|  161 HB_Error SkHarfBuzzFont::GetFontTableFunc(void* voidface, const HB_Tag tag, |  | 
|  162                                           HB_Byte* buffer, HB_UInt* len) { |  | 
|  163     SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(voidface); |  | 
|  164     SkTypeface* typeface = font->getTypeface(); |  | 
|  165  |  | 
|  166     const size_t tableSize = typeface->getTableSize(tag); |  | 
|  167     if (!tableSize) { |  | 
|  168         return HB_Err_Invalid_Argument; |  | 
|  169     } |  | 
|  170     // If Harfbuzz specified a NULL buffer then it's asking for the size. |  | 
|  171     if (!buffer) { |  | 
|  172         *len = tableSize; |  | 
|  173         return HB_Err_Ok; |  | 
|  174     } |  | 
|  175  |  | 
|  176     if (*len < tableSize) { |  | 
|  177         // is this right, or should we just copy less than the full table? |  | 
|  178         return HB_Err_Invalid_Argument; |  | 
|  179     } |  | 
|  180     typeface->getTableData(tag, 0, tableSize, buffer); |  | 
|  181     return HB_Err_Ok; |  | 
|  182 } |  | 
| OLD | NEW |