1 /*
2 * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
17 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25 #include "third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.h"
26
27 #include "base/memory/scoped_refptr.h"
28 #include "third_party/blink/renderer/platform/fonts/opentype/open_type_types.h"
29 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
30 #include "third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h"
31 #include "third_party/blink/renderer/platform/geometry/float_rect.h"
32 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
33 #include "third_party/skia/include/core/SkTypeface.h"
34
35 namespace blink {
36 namespace open_type {
37
38 // The input characters are big-endian (first is most significant).
39 #define OT_MAKE_TAG(ch1, ch2, ch3, ch4) \
40 ((((uint32_t)(ch1)) << 24) | (((uint32_t)(ch2)) << 16) | \
41 (((uint32_t)(ch3)) << 8) | ((uint32_t)(ch4)))
42
43 const SkFontTableTag kHheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a');
44 const SkFontTableTag kHmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x');
45 const SkFontTableTag kVheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a');
46 const SkFontTableTag kVmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x');
47 const SkFontTableTag kVORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G');
48
49 #pragma pack(1)
50
51 struct HheaTable {
52 DISALLOW_NEW();
53 open_type::Fixed version;
54 open_type::Int16 ascender;
55 open_type::Int16 descender;
56 open_type::Int16 line_gap;
57 open_type::Int16 advance_width_max;
58 open_type::Int16 min_left_side_bearing;
59 open_type::Int16 min_right_side_bearing;
60 open_type::Int16 x_max_extent;
61 open_type::Int16 caret_slope_rise;
62 open_type::Int16 caret_slope_run;
63 open_type::Int16 caret_offset;
64 open_type::Int16 reserved[4];
65 open_type::Int16 metric_data_format;
66 open_type::UInt16 number_of_h_metrics;
67 };
68
69 struct VheaTable {
70 DISALLOW_NEW();
71 open_type::Fixed version;
72 open_type::Int16 ascent;
73 open_type::Int16 descent;
74 open_type::Int16 line_gap;
75 open_type::Int16 advance_height_max;
76 open_type::Int16 min_top_side_bearing;
77 open_type::Int16 min_bottom_side_bearing;
78 open_type::Int16 y_max_extent;
79 open_type::Int16 caret_slope_rise;
80 open_type::Int16 caret_slope_run;
81 open_type::Int16 caret_offset;
82 open_type::Int16 reserved[4];
83 open_type::Int16 metric_data_format;
84 open_type::UInt16 num_of_long_ver_metrics;
85 };
86
87 struct HmtxTable {
88 DISALLOW_NEW();
89 struct Entry {
90 DISALLOW_NEW();
91 open_type::UInt16 advance_width;
92 open_type::Int16 lsb;
93 } entries[1];
94 };
95
96 struct VmtxTable {
97 DISALLOW_NEW();
98 struct Entry {
99 DISALLOW_NEW();
100 open_type::UInt16 advance_height;
101 open_type::Int16 top_side_bearing;
102 } entries[1];
103 };
104
105 struct VORGTable {
106 DISALLOW_NEW();
107 open_type::UInt16 major_version;
108 open_type::UInt16 minor_version;
109 open_type::Int16 default_vert_origin_y;
110 open_type::UInt16 num_vert_origin_y_metrics;
111 struct VertOriginYMetrics {
112 DISALLOW_NEW();
113 open_type::UInt16 glyph_index;
114 open_type::Int16 vert_origin_y;
115 } vert_origin_y_metrics[1];
116
RequiredSizeblink::open_type::VORGTable117 size_t RequiredSize() const {
118 return sizeof(*this) +
119 sizeof(VertOriginYMetrics) * (num_vert_origin_y_metrics - 1);
120 }
121 };
122
123 #pragma pack()
124
125 } // namespace open_type
126
OpenTypeVerticalData(sk_sp<SkTypeface> typeface)127 OpenTypeVerticalData::OpenTypeVerticalData(sk_sp<SkTypeface> typeface)
128 : default_vert_origin_y_(0),
129 size_per_unit_(0),
130 ascent_fallback_(0),
131 height_fallback_(0) {
132 LoadMetrics(typeface);
133 }
134
CopyOpenTypeTable(sk_sp<SkTypeface> typeface,SkFontTableTag tag,Vector<char> & destination)135 static void CopyOpenTypeTable(sk_sp<SkTypeface> typeface,
136 SkFontTableTag tag,
137 Vector<char>& destination) {
138 const size_t table_size = typeface->getTableSize(tag);
139 destination.resize(SafeCast<wtf_size_t>(table_size));
140 if (table_size) {
141 typeface->getTableData(tag, 0, table_size, destination.data());
142 }
143 }
144
LoadMetrics(sk_sp<SkTypeface> typeface)145 void OpenTypeVerticalData::LoadMetrics(sk_sp<SkTypeface> typeface) {
146 // Load hhea and hmtx to get x-component of vertical origins.
147 // If these tables are missing, it's not an OpenType font.
148 Vector<char> buffer;
149 CopyOpenTypeTable(typeface, open_type::kHheaTag, buffer);
150 const open_type::HheaTable* hhea =
151 open_type::ValidateTable<open_type::HheaTable>(buffer);
152 if (!hhea)
153 return;
154 uint16_t count_hmtx_entries = hhea->number_of_h_metrics;
155 if (!count_hmtx_entries) {
156 DLOG(ERROR) << "Invalid numberOfHMetrics";
157 return;
158 }
159
160 CopyOpenTypeTable(typeface, open_type::kHmtxTag, buffer);
161 const open_type::HmtxTable* hmtx =
162 open_type::ValidateTable<open_type::HmtxTable>(buffer,
163 count_hmtx_entries);
164 if (!hmtx) {
165 DLOG(ERROR) << "hhea exists but hmtx does not (or broken)";
166 return;
167 }
168 advance_widths_.resize(count_hmtx_entries);
169 for (uint16_t i = 0; i < count_hmtx_entries; ++i)
170 advance_widths_[i] = hmtx->entries[i].advance_width;
171
172 // Load vhea first. This table is required for fonts that support vertical
173 // flow.
174 CopyOpenTypeTable(typeface, open_type::kVheaTag, buffer);
175 const open_type::VheaTable* vhea =
176 open_type::ValidateTable<open_type::VheaTable>(buffer);
177 if (!vhea)
178 return;
179 uint16_t count_vmtx_entries = vhea->num_of_long_ver_metrics;
180 if (!count_vmtx_entries) {
181 DLOG(ERROR) << "Invalid numOfLongVerMetrics";
182 return;
183 }
184
185 // Load VORG. This table is optional.
186 CopyOpenTypeTable(typeface, open_type::kVORGTag, buffer);
187 const open_type::VORGTable* vorg =
188 open_type::ValidateTable<open_type::VORGTable>(buffer);
189 if (vorg && buffer.size() >= vorg->RequiredSize()) {
190 default_vert_origin_y_ = vorg->default_vert_origin_y;
191 uint16_t count_vert_origin_y_metrics = vorg->num_vert_origin_y_metrics;
192 if (!count_vert_origin_y_metrics) {
193 // Add one entry so that hasVORG() becomes true
194 vert_origin_y_.Set(0, default_vert_origin_y_);
195 } else {
196 for (uint16_t i = 0; i < count_vert_origin_y_metrics; ++i) {
197 const open_type::VORGTable::VertOriginYMetrics& metrics =
198 vorg->vert_origin_y_metrics[i];
199 vert_origin_y_.Set(metrics.glyph_index, metrics.vert_origin_y);
200 }
201 }
202 }
203
204 // Load vmtx then. This table is required for fonts that support vertical
205 // flow.
206 CopyOpenTypeTable(typeface, open_type::kVmtxTag, buffer);
207 const open_type::VmtxTable* vmtx =
208 open_type::ValidateTable<open_type::VmtxTable>(buffer,
209 count_vmtx_entries);
210 if (!vmtx) {
211 DLOG(ERROR) << "vhea exists but vmtx does not (or broken)";
212 return;
213 }
214 advance_heights_.resize(count_vmtx_entries);
215 for (uint16_t i = 0; i < count_vmtx_entries; ++i)
216 advance_heights_[i] = vmtx->entries[i].advance_height;
217
218 // VORG is preferred way to calculate vertical origin than vmtx,
219 // so load topSideBearing from vmtx only if VORG is missing.
220 if (HasVORG())
221 return;
222
223 wtf_size_t size_extra =
224 buffer.size() - sizeof(open_type::VmtxTable::Entry) * count_vmtx_entries;
225 if (size_extra % sizeof(open_type::Int16)) {
226 DLOG(ERROR) << "vmtx has incorrect tsb count";
227 return;
228 }
229 wtf_size_t count_top_side_bearings =
230 count_vmtx_entries + size_extra / sizeof(open_type::Int16);
231 top_side_bearings_.resize(count_top_side_bearings);
232 wtf_size_t i;
233 for (i = 0; i < count_vmtx_entries; ++i)
234 top_side_bearings_[i] = vmtx->entries[i].top_side_bearing;
235 if (i < count_top_side_bearings) {
236 const open_type::Int16* p_top_side_bearings_extra =
237 reinterpret_cast<const open_type::Int16*>(
238 &vmtx->entries[count_vmtx_entries]);
239 for (; i < count_top_side_bearings; ++i, ++p_top_side_bearings_extra)
240 top_side_bearings_[i] = *p_top_side_bearings_extra;
241 }
242 }
243
SetScaleAndFallbackMetrics(float size_per_unit,float ascent,int height)244 void OpenTypeVerticalData::SetScaleAndFallbackMetrics(float size_per_unit,
245 float ascent,
246 int height) {
247 size_per_unit_ = size_per_unit;
248 ascent_fallback_ = ascent;
249 height_fallback_ = height;
250 }
251
AdvanceHeight(Glyph glyph) const252 float OpenTypeVerticalData::AdvanceHeight(Glyph glyph) const {
253 wtf_size_t count_heights = advance_heights_.size();
254 if (count_heights) {
255 uint16_t advance_f_unit =
256 advance_heights_[glyph < count_heights ? glyph : count_heights - 1];
257 float advance = advance_f_unit * size_per_unit_;
258 return advance;
259 }
260
261 // No vertical info in the font file; use height as advance.
262 return height_fallback_;
263 }
264
GetVerticalTranslationsForGlyphs(const SkFont & font,const Glyph * glyphs,size_t count,float * out_xy_array) const265 void OpenTypeVerticalData::GetVerticalTranslationsForGlyphs(
266 const SkFont& font,
267 const Glyph* glyphs,
268 size_t count,
269 float* out_xy_array) const {
270 wtf_size_t count_widths = advance_widths_.size();
271 DCHECK_GT(count_widths, 0u);
272 bool use_vorg = HasVORG();
273 wtf_size_t count_top_side_bearings = top_side_bearings_.size();
274 float default_vert_origin_y = std::numeric_limits<float>::quiet_NaN();
275 for (float *end = &(out_xy_array[count * 2]); out_xy_array != end;
276 ++glyphs, out_xy_array += 2) {
277 Glyph glyph = *glyphs;
278 uint16_t width_f_unit =
279 advance_widths_[glyph < count_widths ? glyph : count_widths - 1];
280 float width = width_f_unit * size_per_unit_;
281 out_xy_array[0] = -width / 2;
282
283 // For Y, try VORG first.
284 if (use_vorg) {
285 if (glyph) {
286 int16_t vert_origin_yf_unit = vert_origin_y_.at(glyph);
287 if (vert_origin_yf_unit) {
288 out_xy_array[1] = -vert_origin_yf_unit * size_per_unit_;
289 continue;
290 }
291 }
292 if (std::isnan(default_vert_origin_y))
293 default_vert_origin_y = -default_vert_origin_y_ * size_per_unit_;
294 out_xy_array[1] = default_vert_origin_y;
295 continue;
296 }
297
298 // If no VORG, try vmtx next.
299 if (count_top_side_bearings) {
300 int16_t top_side_bearing_f_unit =
301 top_side_bearings_[glyph < count_top_side_bearings
302 ? glyph
303 : count_top_side_bearings - 1];
304 float top_side_bearing = top_side_bearing_f_unit * size_per_unit_;
305
306 SkRect skiaBounds;
307 SkFontGetBoundsForGlyph(font, glyph, &skiaBounds);
308 FloatRect bounds(skiaBounds);
309 out_xy_array[1] = bounds.Y() - top_side_bearing;
310 continue;
311 }
312
313 // No vertical info in the font file; use ascent as vertical origin.
314 out_xy_array[1] = -ascent_fallback_;
315 }
316 }
317
318 } // namespace blink
319