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