| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 Google Inc. All rights reserved. | |
| 3 * Copyright (c) 2014 BlackBerry Limited. All rights reserved. | |
| 4 * | |
| 5 * Redistribution and use in source and binary forms, with or without | |
| 6 * modification, are permitted provided that the following conditions are | |
| 7 * met: | |
| 8 * | |
| 9 * * Redistributions of source code must retain the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer. | |
| 11 * * Redistributions in binary form must reproduce the above | |
| 12 * copyright notice, this list of conditions and the following disclaimer | |
| 13 * in the documentation and/or other materials provided with the | |
| 14 * distribution. | |
| 15 * * Neither the name of Google Inc. nor the names of its | |
| 16 * contributors may be used to endorse or promote products derived from | |
| 17 * this software without specific prior written permission. | |
| 18 * | |
| 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 30 */ | |
| 31 | |
| 32 #include "config.h" | |
| 33 #include "platform/fonts/harfbuzz/HarfBuzzFace.h" | |
| 34 | |
| 35 #include "SkPaint.h" | |
| 36 #include "SkPath.h" | |
| 37 #include "SkPoint.h" | |
| 38 #include "SkRect.h" | |
| 39 #include "SkTypeface.h" | |
| 40 #include "SkUtils.h" | |
| 41 #include "platform/fonts/FontPlatformData.h" | |
| 42 #include "platform/fonts/SimpleFontData.h" | |
| 43 #include "platform/fonts/harfbuzz/HarfBuzzShaper.h" | |
| 44 | |
| 45 #include "hb.h" | |
| 46 #include "wtf/HashMap.h" | |
| 47 | |
| 48 namespace blink { | |
| 49 | |
| 50 // Our implementation of the callbacks which HarfBuzz requires by using Skia | |
| 51 // calls. See the HarfBuzz source for references about what these callbacks do. | |
| 52 | |
| 53 struct HarfBuzzFontData { | |
| 54 HarfBuzzFontData(WTF::HashMap<uint32_t, uint16_t>* glyphCacheForFaceCacheEnt
ry) | |
| 55 : m_glyphCacheForFaceCacheEntry(glyphCacheForFaceCacheEntry) | |
| 56 { } | |
| 57 SkPaint m_paint; | |
| 58 WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry; | |
| 59 }; | |
| 60 | |
| 61 static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) | |
| 62 { | |
| 63 return SkScalarToFixed(value); | |
| 64 } | |
| 65 | |
| 66 static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint
, hb_position_t* width, hb_glyph_extents_t* extents) | |
| 67 { | |
| 68 ASSERT(codepoint <= 0xFFFF); | |
| 69 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); | |
| 70 | |
| 71 SkScalar skWidth; | |
| 72 SkRect skBounds; | |
| 73 uint16_t glyph = codepoint; | |
| 74 | |
| 75 paint->getTextWidths(&glyph, sizeof(glyph), &skWidth, &skBounds); | |
| 76 if (width) | |
| 77 *width = SkiaScalarToHarfBuzzPosition(skWidth); | |
| 78 if (extents) { | |
| 79 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to
be y-grows-up. | |
| 80 extents->x_bearing = SkiaScalarToHarfBuzzPosition(skBounds.fLeft); | |
| 81 extents->y_bearing = SkiaScalarToHarfBuzzPosition(-skBounds.fTop); | |
| 82 extents->width = SkiaScalarToHarfBuzzPosition(skBounds.width()); | |
| 83 extents->height = SkiaScalarToHarfBuzzPosition(-skBounds.height()); | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 static hb_bool_t harfBuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoin
t_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* user
Data) | |
| 88 { | |
| 89 // Variation selectors not supported. | |
| 90 if (variationSelector) | |
| 91 return false; | |
| 92 | |
| 93 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData)
; | |
| 94 | |
| 95 WTF::HashMap<uint32_t, uint16_t>::AddResult result = hbFontData->m_glyphCach
eForFaceCacheEntry->add(unicode, 0); | |
| 96 if (result.isNewEntry) { | |
| 97 SkPaint* paint = &hbFontData->m_paint; | |
| 98 paint->setTextEncoding(SkPaint::kUTF32_TextEncoding); | |
| 99 uint16_t glyph16; | |
| 100 paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &glyph16); | |
| 101 result.storedValue->value = glyph16; | |
| 102 *glyph = glyph16; | |
| 103 } | |
| 104 *glyph = result.storedValue->value; | |
| 105 return !!*glyph; | |
| 106 } | |
| 107 | |
| 108 static hb_position_t harfBuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void*
fontData, hb_codepoint_t glyph, void* userData) | |
| 109 { | |
| 110 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData)
; | |
| 111 hb_position_t advance = 0; | |
| 112 | |
| 113 SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0); | |
| 114 return advance; | |
| 115 } | |
| 116 | |
| 117 static hb_bool_t harfBuzzGetGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontD
ata, hb_codepoint_t glyph, hb_position_t* x, hb_position_t* y, void* userData) | |
| 118 { | |
| 119 // Just return true, following the way that HarfBuzz-FreeType | |
| 120 // implementation does. | |
| 121 return true; | |
| 122 } | |
| 123 | |
| 124 static hb_position_t harfBuzzGetGlyphHorizontalKerning(hb_font_t*, void* fontDat
a, hb_codepoint_t leftGlyph, hb_codepoint_t rightGlyph, void*) | |
| 125 { | |
| 126 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData)
; | |
| 127 if (hbFontData->m_paint.isVerticalText()) { | |
| 128 // We don't support cross-stream kerning | |
| 129 return 0; | |
| 130 } | |
| 131 | |
| 132 SkTypeface* typeface = hbFontData->m_paint.getTypeface(); | |
| 133 | |
| 134 const uint16_t glyphs[2] = { static_cast<uint16_t>(leftGlyph), static_cast<u
int16_t>(rightGlyph) }; | |
| 135 int32_t kerningAdjustments[1] = { 0 }; | |
| 136 | |
| 137 if (typeface->getKerningPairAdjustments(glyphs, 2, kerningAdjustments)) { | |
| 138 SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm()); | |
| 139 SkScalar size = hbFontData->m_paint.getTextSize(); | |
| 140 return SkiaScalarToHarfBuzzPosition(SkScalarMulDiv(SkIntToScalar(kerning
Adjustments[0]), size, upm)); | |
| 141 } | |
| 142 | |
| 143 return 0; | |
| 144 } | |
| 145 | |
| 146 static hb_position_t harfBuzzGetGlyphVerticalKerning(hb_font_t*, void* fontData,
hb_codepoint_t topGlyph, hb_codepoint_t bottomGlyph, void*) | |
| 147 { | |
| 148 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData)
; | |
| 149 if (!hbFontData->m_paint.isVerticalText()) { | |
| 150 // We don't support cross-stream kerning | |
| 151 return 0; | |
| 152 } | |
| 153 | |
| 154 SkTypeface* typeface = hbFontData->m_paint.getTypeface(); | |
| 155 | |
| 156 const uint16_t glyphs[2] = { static_cast<uint16_t>(topGlyph), static_cast<ui
nt16_t>(bottomGlyph) }; | |
| 157 int32_t kerningAdjustments[1] = { 0 }; | |
| 158 | |
| 159 if (typeface->getKerningPairAdjustments(glyphs, 2, kerningAdjustments)) { | |
| 160 SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm()); | |
| 161 SkScalar size = hbFontData->m_paint.getTextSize(); | |
| 162 return SkiaScalarToHarfBuzzPosition(SkScalarMulDiv(SkIntToScalar(kerning
Adjustments[0]), size, upm)); | |
| 163 } | |
| 164 | |
| 165 return 0; | |
| 166 } | |
| 167 | |
| 168 static hb_bool_t harfBuzzGetGlyphExtents(hb_font_t* hbFont, void* fontData, hb_c
odepoint_t glyph, hb_glyph_extents_t* extents, void* userData) | |
| 169 { | |
| 170 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData)
; | |
| 171 | |
| 172 SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, 0, extents); | |
| 173 return true; | |
| 174 } | |
| 175 | |
| 176 static hb_font_funcs_t* harfBuzzSkiaGetFontFuncs() | |
| 177 { | |
| 178 static hb_font_funcs_t* harfBuzzSkiaFontFuncs = 0; | |
| 179 | |
| 180 // We don't set callback functions which we can't support. | |
| 181 // HarfBuzz will use the fallback implementation if they aren't set. | |
| 182 if (!harfBuzzSkiaFontFuncs) { | |
| 183 harfBuzzSkiaFontFuncs = hb_font_funcs_create(); | |
| 184 hb_font_funcs_set_glyph_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyph, 0,
0); | |
| 185 hb_font_funcs_set_glyph_h_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe
tGlyphHorizontalAdvance, 0, 0); | |
| 186 hb_font_funcs_set_glyph_h_kerning_func(harfBuzzSkiaFontFuncs, harfBuzzGe
tGlyphHorizontalKerning, 0, 0); | |
| 187 hb_font_funcs_set_glyph_h_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGet
GlyphHorizontalOrigin, 0, 0); | |
| 188 hb_font_funcs_set_glyph_v_kerning_func(harfBuzzSkiaFontFuncs, harfBuzzGe
tGlyphVerticalKerning, 0, 0); | |
| 189 hb_font_funcs_set_glyph_extents_func(harfBuzzSkiaFontFuncs, harfBuzzGetG
lyphExtents, 0, 0); | |
| 190 hb_font_funcs_make_immutable(harfBuzzSkiaFontFuncs); | |
| 191 } | |
| 192 return harfBuzzSkiaFontFuncs; | |
| 193 } | |
| 194 | |
| 195 static hb_blob_t* harfBuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user
Data) | |
| 196 { | |
| 197 SkTypeface* typeface = reinterpret_cast<SkTypeface*>(userData); | |
| 198 | |
| 199 const size_t tableSize = typeface->getTableSize(tag); | |
| 200 if (!tableSize) | |
| 201 return 0; | |
| 202 | |
| 203 char* buffer = reinterpret_cast<char*>(fastMalloc(tableSize)); | |
| 204 if (!buffer) | |
| 205 return 0; | |
| 206 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer); | |
| 207 if (tableSize != actualSize) { | |
| 208 fastFree(buffer); | |
| 209 return 0; | |
| 210 } | |
| 211 | |
| 212 return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_W
RITABLE, buffer, fastFree); | |
| 213 } | |
| 214 | |
| 215 static void destroyHarfBuzzFontData(void* userData) | |
| 216 { | |
| 217 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(userData)
; | |
| 218 delete hbFontData; | |
| 219 } | |
| 220 | |
| 221 hb_face_t* HarfBuzzFace::createFace() | |
| 222 { | |
| 223 hb_face_t* face = hb_face_create_for_tables(harfBuzzSkiaGetTable, m_platform
Data->typeface(), 0); | |
| 224 ASSERT(face); | |
| 225 return face; | |
| 226 } | |
| 227 | |
| 228 hb_font_t* HarfBuzzFace::createFont() | |
| 229 { | |
| 230 HarfBuzzFontData* hbFontData = new HarfBuzzFontData(m_glyphCacheForFaceCache
Entry); | |
| 231 m_platformData->setupPaint(&hbFontData->m_paint); | |
| 232 hb_font_t* font = hb_font_create(m_face); | |
| 233 hb_font_set_funcs(font, harfBuzzSkiaGetFontFuncs(), hbFontData, destroyHarfB
uzzFontData); | |
| 234 float size = m_platformData->size(); | |
| 235 int scale = SkiaScalarToHarfBuzzPosition(size); | |
| 236 hb_font_set_scale(font, scale, scale); | |
| 237 hb_font_make_immutable(font); | |
| 238 return font; | |
| 239 } | |
| 240 | |
| 241 } // namespace blink | |
| OLD | NEW |