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 |