1 /* 2 * Copyright (c) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #define LOG_TAG "TextLayoutCache" 32 33 #include "HarfBuzzNGFaceSkia.h" 34 35 #include <cutils/log.h> 36 #include <SkPaint.h> 37 #include <SkPath.h> 38 #include <SkPoint.h> 39 #include <SkRect.h> 40 #include <SkTypeface.h> 41 #include <SkUtils.h> 42 43 #include <hb.h> 44 45 namespace android { 46 47 static const bool kDebugGlyphs = false; 48 49 // Our implementation of the callbacks which Harfbuzz requires by using Skia 50 // calls. See the Harfbuzz source for references about what these callbacks do. 51 52 struct HarfBuzzFontData { 53 HarfBuzzFontData(SkPaint* paint) : m_paint(paint) { } 54 SkPaint* m_paint; 55 }; 56 57 static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint, hb_position_t* width, hb_glyph_extents_t* extents) 58 { 59 ALOG_ASSERT(codepoint <= 0xFFFF); 60 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 61 62 SkScalar skWidth; 63 SkRect skBounds; 64 uint16_t glyph = codepoint; 65 66 paint->getTextWidths(&glyph, sizeof(glyph), &skWidth, &skBounds); 67 if (kDebugGlyphs) { 68 ALOGD("returned glyph for %i: width = %f", codepoint, skWidth); 69 } 70 if (width) 71 *width = SkScalarToHBFixed(skWidth); 72 if (extents) { 73 // Invert y-axis because Skia is y-grows-down but we set up harfbuzz to be y-grows-up. 74 extents->x_bearing = SkScalarToHBFixed(skBounds.fLeft); 75 extents->y_bearing = SkScalarToHBFixed(-skBounds.fTop); 76 extents->width = SkScalarToHBFixed(skBounds.width()); 77 extents->height = SkScalarToHBFixed(-skBounds.height()); 78 } 79 } 80 81 static hb_bool_t harfbuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoint_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* userData) 82 { 83 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); 84 85 if (unicode > 0x10ffff) { 86 unicode = 0xfffd; 87 } 88 SkPaint* paint = hbFontData->m_paint; 89 // It would be better to use kUTF32_TextEncoding directly 90 paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); 91 uint16_t glyph16; 92 uint16_t unichar[2]; 93 size_t size = SkUTF16_FromUnichar(unicode, unichar); 94 paint->textToGlyphs(unichar, size * sizeof(*unichar), &glyph16); 95 *glyph = glyph16; 96 return !!*glyph; 97 } 98 99 static hb_position_t harfbuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData) 100 { 101 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); 102 hb_position_t advance = 0; 103 104 SkiaGetGlyphWidthAndExtents(hbFontData->m_paint, glyph, &advance, 0); 105 return advance; 106 } 107 108 static hb_bool_t harfbuzzGetGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_position_t* x, hb_position_t* y, void* userData) 109 { 110 // Just return true, following the way that Harfbuzz-FreeType 111 // implementation does. 112 return true; 113 } 114 115 static hb_bool_t harfbuzzGetGlyphExtents(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_glyph_extents_t* extents, void* userData) 116 { 117 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); 118 119 SkiaGetGlyphWidthAndExtents(hbFontData->m_paint, glyph, 0, extents); 120 return true; 121 } 122 123 static hb_font_funcs_t* harfbuzzSkiaGetFontFuncs() 124 { 125 static hb_font_funcs_t* harfbuzzSkiaFontFuncs = 0; 126 127 // We don't set callback functions which we can't support. 128 // Harfbuzz will use the fallback implementation if they aren't set. 129 if (!harfbuzzSkiaFontFuncs) { 130 harfbuzzSkiaFontFuncs = hb_font_funcs_create(); 131 hb_font_funcs_set_glyph_func(harfbuzzSkiaFontFuncs, harfbuzzGetGlyph, 0, 0); 132 hb_font_funcs_set_glyph_h_advance_func(harfbuzzSkiaFontFuncs, harfbuzzGetGlyphHorizontalAdvance, 0, 0); 133 hb_font_funcs_set_glyph_h_origin_func(harfbuzzSkiaFontFuncs, harfbuzzGetGlyphHorizontalOrigin, 0, 0); 134 hb_font_funcs_set_glyph_extents_func(harfbuzzSkiaFontFuncs, harfbuzzGetGlyphExtents, 0, 0); 135 hb_font_funcs_make_immutable(harfbuzzSkiaFontFuncs); 136 } 137 return harfbuzzSkiaFontFuncs; 138 } 139 140 hb_blob_t* harfbuzzSkiaReferenceTable(hb_face_t* face, hb_tag_t tag, void* userData) 141 { 142 SkTypeface* typeface = reinterpret_cast<SkTypeface*>(userData); 143 144 const size_t tableSize = typeface->getTableSize(tag); 145 if (!tableSize) 146 return 0; 147 148 char* buffer = reinterpret_cast<char*>(malloc(tableSize)); 149 if (!buffer) 150 return 0; 151 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer); 152 if (tableSize != actualSize) { 153 free(buffer); 154 return 0; 155 } 156 157 return hb_blob_create(const_cast<char*>(buffer), tableSize, 158 HB_MEMORY_MODE_WRITABLE, buffer, free); 159 } 160 161 static void destroyHarfBuzzFontData(void* data) { 162 delete (HarfBuzzFontData*)data; 163 } 164 165 hb_font_t* createFont(hb_face_t* face, SkPaint* paint, float sizeX, float sizeY) { 166 hb_font_t* font = hb_font_create(face); 167 168 // Note: this needs to be reworked when we do subpixels 169 int x_ppem = floor(sizeX + 0.5); 170 int y_ppem = floor(sizeY + 0.5); 171 hb_font_set_ppem(font, x_ppem, y_ppem); 172 hb_font_set_scale(font, HBFloatToFixed(sizeX), HBFloatToFixed(sizeY)); 173 174 HarfBuzzFontData* data = new HarfBuzzFontData(paint); 175 hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), data, destroyHarfBuzzFontData); 176 177 return font; 178 } 179 180 } // namespace android 181