| OLD | NEW |
| (Empty) |
| 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 #include "config.h" | |
| 32 #include "core/platform/graphics/harfbuzz/HarfBuzzFace.h" | |
| 33 | |
| 34 #include "SkPaint.h" | |
| 35 #include "SkPath.h" | |
| 36 #include "SkPoint.h" | |
| 37 #include "SkRect.h" | |
| 38 #include "SkTypeface.h" | |
| 39 #include "SkUtils.h" | |
| 40 #include "core/platform/graphics/FontPlatformData.h" | |
| 41 #include "core/platform/graphics/SimpleFontData.h" | |
| 42 #include "core/platform/graphics/harfbuzz/HarfBuzzShaper.h" | |
| 43 #include "platform/fonts/GlyphBuffer.h" | |
| 44 | |
| 45 #include "hb.h" | |
| 46 #include "wtf/HashMap.h" | |
| 47 | |
| 48 namespace WebCore { | |
| 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 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData)
; | |
| 90 | |
| 91 WTF::HashMap<uint32_t, uint16_t>::AddResult result = hbFontData->m_glyphCach
eForFaceCacheEntry->add(unicode, 0); | |
| 92 if (result.isNewEntry) { | |
| 93 SkPaint* paint = &hbFontData->m_paint; | |
| 94 paint->setTextEncoding(SkPaint::kUTF32_TextEncoding); | |
| 95 uint16_t glyph16; | |
| 96 paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &glyph16); | |
| 97 result.iterator->value = glyph16; | |
| 98 *glyph = glyph16; | |
| 99 } | |
| 100 *glyph = result.iterator->value; | |
| 101 return !!*glyph; | |
| 102 } | |
| 103 | |
| 104 static hb_position_t harfBuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void*
fontData, hb_codepoint_t glyph, void* userData) | |
| 105 { | |
| 106 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData)
; | |
| 107 hb_position_t advance = 0; | |
| 108 | |
| 109 SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0); | |
| 110 return advance; | |
| 111 } | |
| 112 | |
| 113 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) | |
| 114 { | |
| 115 // Just return true, following the way that HarfBuzz-FreeType | |
| 116 // implementation does. | |
| 117 return true; | |
| 118 } | |
| 119 | |
| 120 static hb_bool_t harfBuzzGetGlyphExtents(hb_font_t* hbFont, void* fontData, hb_c
odepoint_t glyph, hb_glyph_extents_t* extents, void* userData) | |
| 121 { | |
| 122 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData)
; | |
| 123 | |
| 124 SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, 0, extents); | |
| 125 return true; | |
| 126 } | |
| 127 | |
| 128 static hb_font_funcs_t* harfBuzzSkiaGetFontFuncs() | |
| 129 { | |
| 130 static hb_font_funcs_t* harfBuzzSkiaFontFuncs = 0; | |
| 131 | |
| 132 // We don't set callback functions which we can't support. | |
| 133 // HarfBuzz will use the fallback implementation if they aren't set. | |
| 134 if (!harfBuzzSkiaFontFuncs) { | |
| 135 harfBuzzSkiaFontFuncs = hb_font_funcs_create(); | |
| 136 hb_font_funcs_set_glyph_func(harfBuzzSkiaFontFuncs, harfBuzzGetGlyph, 0,
0); | |
| 137 hb_font_funcs_set_glyph_h_advance_func(harfBuzzSkiaFontFuncs, harfBuzzGe
tGlyphHorizontalAdvance, 0, 0); | |
| 138 hb_font_funcs_set_glyph_h_origin_func(harfBuzzSkiaFontFuncs, harfBuzzGet
GlyphHorizontalOrigin, 0, 0); | |
| 139 hb_font_funcs_set_glyph_extents_func(harfBuzzSkiaFontFuncs, harfBuzzGetG
lyphExtents, 0, 0); | |
| 140 hb_font_funcs_make_immutable(harfBuzzSkiaFontFuncs); | |
| 141 } | |
| 142 return harfBuzzSkiaFontFuncs; | |
| 143 } | |
| 144 | |
| 145 static hb_blob_t* harfBuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user
Data) | |
| 146 { | |
| 147 SkTypeface* typeface = reinterpret_cast<SkTypeface*>(userData); | |
| 148 | |
| 149 const size_t tableSize = typeface->getTableSize(tag); | |
| 150 if (!tableSize) | |
| 151 return 0; | |
| 152 | |
| 153 char* buffer = reinterpret_cast<char*>(fastMalloc(tableSize)); | |
| 154 if (!buffer) | |
| 155 return 0; | |
| 156 size_t actualSize = typeface->getTableData(tag, 0, tableSize, buffer); | |
| 157 if (tableSize != actualSize) { | |
| 158 fastFree(buffer); | |
| 159 return 0; | |
| 160 } | |
| 161 | |
| 162 return hb_blob_create(const_cast<char*>(buffer), tableSize, HB_MEMORY_MODE_W
RITABLE, buffer, fastFree); | |
| 163 } | |
| 164 | |
| 165 static void destroyHarfBuzzFontData(void* userData) | |
| 166 { | |
| 167 HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(userData)
; | |
| 168 delete hbFontData; | |
| 169 } | |
| 170 | |
| 171 hb_face_t* HarfBuzzFace::createFace() | |
| 172 { | |
| 173 hb_face_t* face = hb_face_create_for_tables(harfBuzzSkiaGetTable, m_platform
Data->typeface(), 0); | |
| 174 ASSERT(face); | |
| 175 return face; | |
| 176 } | |
| 177 | |
| 178 hb_font_t* HarfBuzzFace::createFont() | |
| 179 { | |
| 180 HarfBuzzFontData* hbFontData = new HarfBuzzFontData(m_glyphCacheForFaceCache
Entry); | |
| 181 m_platformData->setupPaint(&hbFontData->m_paint); | |
| 182 hb_font_t* font = hb_font_create(m_face); | |
| 183 hb_font_set_funcs(font, harfBuzzSkiaGetFontFuncs(), hbFontData, destroyHarfB
uzzFontData); | |
| 184 float size = m_platformData->size(); | |
| 185 int scale = SkiaScalarToHarfBuzzPosition(size); | |
| 186 hb_font_set_scale(font, scale, scale); | |
| 187 hb_font_make_immutable(font); | |
| 188 return font; | |
| 189 } | |
| 190 | |
| 191 GlyphBufferAdvance HarfBuzzShaper::createGlyphBufferAdvance(float width, float h
eight) | |
| 192 { | |
| 193 return GlyphBufferAdvance(width, height); | |
| 194 } | |
| 195 | |
| 196 } // namespace WebCore | |
| OLD | NEW |