Attachment #516244: patch to add vhea/vmtx support to OTS for bug #637481

View | Details | Raw Unified | Return to bug 637481
Collapse All | Expand All

(-)a/gfx/ots/src/hhea.cc (-4 / +27 lines)
Line     Link Here 
 Lines 7-26    Link Here 
7
#include "head.h"
7
#include "head.h"
8
#include "maxp.h"
8
#include "maxp.h"
9
9
10
// hhea - Horizontal Header
10
// hhea - Horizontal Header
11
// http://www.microsoft.com/opentype/otspec/hhea.htm
11
// http://www.microsoft.com/opentype/otspec/hhea.htm
12
12
13
namespace ots {
13
namespace ots {
14
14
15
bool ots_hhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
15
bool ots_Xhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length,
16
                    OpenTypeHHEA **out_hhea) {
16
  Buffer table(data, length);
17
  Buffer table(data, length);
17
  OpenTypeHHEA *hhea = new OpenTypeHHEA;
18
  OpenTypeHHEA *hhea = new OpenTypeHHEA;
18
  file->hhea = hhea;
19
  *out_hhea = hhea;
19
20
20
  uint32_t version = 0;
21
  uint32_t version = 0;
21
  if (!table.ReadU32(&version)) {
22
  if (!table.ReadU32(&version)) {
22
    return OTS_FAILURE();
23
    return OTS_FAILURE();
23
  }
24
  }
24
  if (version >> 16 != 1) {
25
  if (version >> 16 != 1) {
25
    return OTS_FAILURE();
26
    return OTS_FAILURE();
26
  }
27
  }
 Lines 81-103   bool ots_hhea_parse(OpenTypeFile *file, Link Here 
81
82
82
  if (hhea->num_hmetrics > file->maxp->num_glyphs) {
83
  if (hhea->num_hmetrics > file->maxp->num_glyphs) {
83
    return OTS_FAILURE();
84
    return OTS_FAILURE();
84
  }
85
  }
85
86
86
  return true;
87
  return true;
87
}
88
}
88
89
90
bool ots_hhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
91
  return ots_Xhea_parse(file, data, length, &file->hhea);
92
}
93
94
bool ots_vhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
95
  return ots_Xhea_parse(file, data, length, reinterpret_cast<OpenTypeHHEA**>(&file->vhea));
96
}
97
89
bool ots_hhea_should_serialise(OpenTypeFile *file) {
98
bool ots_hhea_should_serialise(OpenTypeFile *file) {
90
  return file->hhea;
99
  return file->hhea;
91
}
100
}
92
101
93
bool ots_hhea_serialise(OTSStream *out, OpenTypeFile *file) {
102
bool ots_vhea_should_serialise(OpenTypeFile *file) {
94
  const OpenTypeHHEA *hhea = file->hhea;
103
  return file->preserve_otl && file->vhea;
104
}
95
105
106
bool ots_Xhea_serialise(OTSStream *out, OpenTypeFile *file, const OpenTypeHHEA *hhea) {
96
  if (!out->WriteU32(0x00010000) ||
107
  if (!out->WriteU32(0x00010000) ||
97
      !out->WriteS16(hhea->ascent) ||
108
      !out->WriteS16(hhea->ascent) ||
98
      !out->WriteS16(hhea->descent) ||
109
      !out->WriteS16(hhea->descent) ||
99
      !out->WriteS16(hhea->linegap) ||
110
      !out->WriteS16(hhea->linegap) ||
100
      !out->WriteU16(hhea->adv_width_max) ||
111
      !out->WriteU16(hhea->adv_width_max) ||
101
      !out->WriteS16(hhea->min_lsb) ||
112
      !out->WriteS16(hhea->min_lsb) ||
102
      !out->WriteS16(hhea->min_rsb) ||
113
      !out->WriteS16(hhea->min_rsb) ||
103
      !out->WriteS16(hhea->x_max_extent) ||
114
      !out->WriteS16(hhea->x_max_extent) ||
 Lines 108-120   bool ots_hhea_serialise(OTSStream *out, Link Here 
108
      !out->WriteS16(0) ||  // metric data format
119
      !out->WriteS16(0) ||  // metric data format
109
      !out->WriteU16(hhea->num_hmetrics)) {
120
      !out->WriteU16(hhea->num_hmetrics)) {
110
    return OTS_FAILURE();
121
    return OTS_FAILURE();
111
  }
122
  }
112
123
113
  return true;
124
  return true;
114
}
125
}
115
126
127
bool ots_hhea_serialise(OTSStream *out, OpenTypeFile *file) {
128
  return ots_Xhea_serialise(out, file, file->hhea);
129
}
130
131
bool ots_vhea_serialise(OTSStream *out, OpenTypeFile *file) {
132
  return ots_Xhea_serialise(out, file, reinterpret_cast<const OpenTypeHHEA*>(file->vhea));
133
}
134
116
void ots_hhea_free(OpenTypeFile *file) {
135
void ots_hhea_free(OpenTypeFile *file) {
117
  delete file->hhea;
136
  delete file->hhea;
118
}
137
}
119
138
139
void ots_vhea_free(OpenTypeFile *file) {
140
  delete file->vhea;
141
}
142
120
}  // namespace ots
143
}  // namespace ots
(-)a/gfx/ots/src/hhea.h (+14 lines)
Line     Link Here 
 Lines 18-28   struct OpenTypeHHEA { Link Here 
18
  int16_t min_rsb;
18
  int16_t min_rsb;
19
  int16_t x_max_extent;
19
  int16_t x_max_extent;
20
  int16_t caret_slope_rise;
20
  int16_t caret_slope_rise;
21
  int16_t caret_slope_run;
21
  int16_t caret_slope_run;
22
  int16_t caret_offset;
22
  int16_t caret_offset;
23
  uint16_t num_hmetrics;
23
  uint16_t num_hmetrics;
24
};
24
};
25
25
26
struct OpenTypeVHEA {
27
  int16_t ascent;
28
  int16_t descent;
29
  int16_t linegap;
30
  uint16_t adv_width_max;
31
  int16_t min_lsb;
32
  int16_t min_rsb;
33
  int16_t x_max_extent;
34
  int16_t caret_slope_rise;
35
  int16_t caret_slope_run;
36
  int16_t caret_offset;
37
  uint16_t num_hmetrics;
38
};
39
26
}  // namespace ots
40
}  // namespace ots
27
41
28
#endif  // OTS_HHEA_H_
42
#endif  // OTS_HHEA_H_
(-)a/gfx/ots/src/hmtx.cc (-15 / +38 lines)
Line     Link Here 
 Lines 8-35    Link Here 
8
#include "hhea.h"
8
#include "hhea.h"
9
#include "maxp.h"
9
#include "maxp.h"
10
10
11
// hmtx - Horizontal Metrics
11
// hmtx - Horizontal Metrics
12
// http://www.microsoft.com/opentype/otspec/hmtx.htm
12
// http://www.microsoft.com/opentype/otspec/hmtx.htm
13
13
14
namespace ots {
14
namespace ots {
15
15
16
bool ots_hmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
16
bool ots_Xmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length,
17
                    const OpenTypeHHEA *hhea, OpenTypeHMTX **out_hmtx) {
17
  Buffer table(data, length);
18
  Buffer table(data, length);
18
  OpenTypeHMTX *hmtx = new OpenTypeHMTX;
19
  OpenTypeHMTX *hmtx = new OpenTypeHMTX;
19
  file->hmtx = hmtx;
20
  *out_hmtx = hmtx;
20
21
21
  if (!file->hhea || !file->maxp) {
22
  if (!hhea || !file->maxp) {
22
    return OTS_FAILURE();
23
    return OTS_FAILURE();
23
  }
24
  }
24
25
25
  // |num_hmetrics| is a uint16_t, so it's bounded < 65536. This limits that
26
  // |num_hmetrics| is a uint16_t, so it's bounded < 65536. This limits that
26
  // amount of memory that we'll allocate for this to a sane amount.
27
  // amount of memory that we'll allocate for this to a sane amount.
27
  const unsigned num_hmetrics = file->hhea->num_hmetrics;
28
  const unsigned num_hmetrics = hhea->num_hmetrics;
28
29
29
  if (num_hmetrics > file->maxp->num_glyphs) {
30
  if (num_hmetrics > file->maxp->num_glyphs) {
30
    return OTS_FAILURE();
31
    return OTS_FAILURE();
31
  }
32
  }
32
  if (!num_hmetrics) {
33
  if (!num_hmetrics) {
33
    return OTS_FAILURE();
34
    return OTS_FAILURE();
34
  }
35
  }
35
  const unsigned num_lsbs = file->maxp->num_glyphs - num_hmetrics;
36
  const unsigned num_lsbs = file->maxp->num_glyphs - num_hmetrics;
 Lines 40-108   bool ots_hmtx_parse(OpenTypeFile *file, Link Here 
40
    int16_t lsb = 0;
41
    int16_t lsb = 0;
41
    if (!table.ReadU16(&adv) || !table.ReadS16(&lsb)) {
42
    if (!table.ReadU16(&adv) || !table.ReadS16(&lsb)) {
42
      return OTS_FAILURE();
43
      return OTS_FAILURE();
43
    }
44
    }
44
45
45
    // Since so many fonts don't have proper value on |adv| and |lsb|,
46
    // Since so many fonts don't have proper value on |adv| and |lsb|,
46
    // we should not call ots_failure() here. For example, about 20% of fonts
47
    // we should not call ots_failure() here. For example, about 20% of fonts
47
    // in http://www.princexml.com/fonts/ (200+ fonts) fails these tests.
48
    // in http://www.princexml.com/fonts/ (200+ fonts) fails these tests.
48
    if (adv > file->hhea->adv_width_max) {
49
    if (adv > hhea->adv_width_max) {
49
      OTS_WARNING("bad adv: %u > %u", adv, file->hhea->adv_width_max);
50
      OTS_WARNING("bad adv: %u > %u", adv, hhea->adv_width_max);
50
      adv = file->hhea->adv_width_max;
51
      adv = hhea->adv_width_max;
51
    }
52
    }
52
    if (lsb < file->hhea->min_lsb) {
53
    if (lsb < hhea->min_lsb) {
53
      OTS_WARNING("bad lsb: %d < %d", lsb, file->hhea->min_lsb);
54
      OTS_WARNING("bad lsb: %d < %d", lsb, hhea->min_lsb);
54
      lsb = file->hhea->min_lsb;
55
      lsb = hhea->min_lsb;
55
    }
56
    }
56
57
57
    hmtx->metrics.push_back(std::make_pair(adv, lsb));
58
    hmtx->metrics.push_back(std::make_pair(adv, lsb));
58
  }
59
  }
59
60
60
  hmtx->lsbs.reserve(num_lsbs);
61
  hmtx->lsbs.reserve(num_lsbs);
61
  for (unsigned i = 0; i < num_lsbs; ++i) {
62
  for (unsigned i = 0; i < num_lsbs; ++i) {
62
    int16_t lsb;
63
    int16_t lsb;
63
    if (!table.ReadS16(&lsb)) {
64
    if (!table.ReadS16(&lsb)) {
64
      // Some Japanese fonts (e.g., mona.ttf) fail this test.
65
      // Some Japanese fonts (e.g., mona.ttf) fail this test.
65
      return OTS_FAILURE();
66
      return OTS_FAILURE();
66
    }
67
    }
67
68
68
    if (lsb < file->hhea->min_lsb) {
69
    if (lsb < hhea->min_lsb) {
69
      // The same as above. Three fonts in http://www.fontsquirrel.com/fontface
70
      // The same as above. Three fonts in http://www.fontsquirrel.com/fontface
70
      // (e.g., Notice2Std.otf) have weird lsb values.
71
      // (e.g., Notice2Std.otf) have weird lsb values.
71
      OTS_WARNING("bad lsb: %d < %d", lsb, file->hhea->min_lsb);
72
      OTS_WARNING("bad lsb: %d < %d", lsb, hhea->min_lsb);
72
      lsb = file->hhea->min_lsb;
73
      lsb = hhea->min_lsb;
73
    }
74
    }
74
75
75
    hmtx->lsbs.push_back(lsb);
76
    hmtx->lsbs.push_back(lsb);
76
  }
77
  }
77
78
78
  return true;
79
  return true;
79
}
80
}
80
81
82
bool ots_hmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
83
  return ots_Xmtx_parse(file, data, length, file->hhea, &file->hmtx);
84
}
85
86
bool ots_vmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
87
  return ots_Xmtx_parse(file, data, length, reinterpret_cast<const OpenTypeHHEA*>(file->vhea), reinterpret_cast<OpenTypeHMTX**>(&file->vmtx));
88
}
89
81
bool ots_hmtx_should_serialise(OpenTypeFile *file) {
90
bool ots_hmtx_should_serialise(OpenTypeFile *file) {
82
  return file->hmtx;
91
  return file->hmtx;
83
}
92
}
84
93
85
bool ots_hmtx_serialise(OTSStream *out, OpenTypeFile *file) {
94
bool ots_vmtx_should_serialise(OpenTypeFile *file) {
86
  const OpenTypeHMTX *hmtx = file->hmtx;
95
  return file->preserve_otl && file->vmtx;
96
}
87
97
98
bool ots_Xmtx_serialise(OTSStream *out, OpenTypeFile *file, const OpenTypeHMTX *hmtx) {
88
  for (unsigned i = 0; i < hmtx->metrics.size(); ++i) {
99
  for (unsigned i = 0; i < hmtx->metrics.size(); ++i) {
89
    if (!out->WriteU16(hmtx->metrics[i].first) ||
100
    if (!out->WriteU16(hmtx->metrics[i].first) ||
90
        !out->WriteS16(hmtx->metrics[i].second)) {
101
        !out->WriteS16(hmtx->metrics[i].second)) {
91
      return OTS_FAILURE();
102
      return OTS_FAILURE();
92
    }
103
    }
93
  }
104
  }
94
105
95
  for (unsigned i = 0; i < hmtx->lsbs.size(); ++i) {
106
  for (unsigned i = 0; i < hmtx->lsbs.size(); ++i) {
96
    if (!out->WriteS16(hmtx->lsbs[i])) {
107
    if (!out->WriteS16(hmtx->lsbs[i])) {
97
      return OTS_FAILURE();
108
      return OTS_FAILURE();
98
    }
109
    }
99
  }
110
  }
100
111
101
  return true;
112
  return true;
102
}
113
}
103
114
115
bool ots_hmtx_serialise(OTSStream *out, OpenTypeFile *file) {
116
  return ots_Xmtx_serialise(out, file, file->hmtx);
117
}
118
119
bool ots_vmtx_serialise(OTSStream *out, OpenTypeFile *file) {
120
  return ots_Xmtx_serialise(out, file, reinterpret_cast<const OpenTypeHMTX*>(file->vmtx));
121
}
122
104
void ots_hmtx_free(OpenTypeFile *file) {
123
void ots_hmtx_free(OpenTypeFile *file) {
105
  delete file->hmtx;
124
  delete file->hmtx;
106
}
125
}
107
126
127
void ots_vmtx_free(OpenTypeFile *file) {
128
  delete file->vmtx;
129
}
130
108
}  // namespace ots
131
}  // namespace ots
(-)a/gfx/ots/src/hmtx.h (+5 lines)
Line     Link Here 
 Lines 12-22    Link Here 
12
12
13
namespace ots {
13
namespace ots {
14
14
15
struct OpenTypeHMTX {
15
struct OpenTypeHMTX {
16
  std::vector<std::pair<uint16_t, int16_t> > metrics;
16
  std::vector<std::pair<uint16_t, int16_t> > metrics;
17
  std::vector<int16_t> lsbs;
17
  std::vector<int16_t> lsbs;
18
};
18
};
19
19
20
struct OpenTypeVMTX {
21
  std::vector<std::pair<uint16_t, int16_t> > metrics;
22
  std::vector<int16_t> lsbs;
23
};
24
20
}  // namespace ots
25
}  // namespace ots
21
26
22
#endif  // OTS_HMTX_H_
27
#endif  // OTS_HMTX_H_
(-)a/gfx/ots/src/ots.cc (+4 lines)
Line     Link Here 
 Lines 137-152   const struct { Link Here 
137
  { Tag("prep"), ots::ots_prep_parse, ots::ots_prep_serialise,
137
  { Tag("prep"), ots::ots_prep_parse, ots::ots_prep_serialise,
138
    ots::ots_prep_should_serialise, ots::ots_prep_free, false },
138
    ots::ots_prep_should_serialise, ots::ots_prep_free, false },
139
  { Tag("LTSH"), ots::ots_ltsh_parse, ots::ots_ltsh_serialise,
139
  { Tag("LTSH"), ots::ots_ltsh_parse, ots::ots_ltsh_serialise,
140
    ots::ots_ltsh_should_serialise, ots::ots_ltsh_free, false },
140
    ots::ots_ltsh_should_serialise, ots::ots_ltsh_free, false },
141
  { Tag("VORG"), ots::ots_vorg_parse, ots::ots_vorg_serialise,
141
  { Tag("VORG"), ots::ots_vorg_parse, ots::ots_vorg_serialise,
142
    ots::ots_vorg_should_serialise, ots::ots_vorg_free, false },
142
    ots::ots_vorg_should_serialise, ots::ots_vorg_free, false },
143
  { Tag("kern"), ots::ots_kern_parse, ots::ots_kern_serialise,
143
  { Tag("kern"), ots::ots_kern_parse, ots::ots_kern_serialise,
144
    ots::ots_kern_should_serialise, ots::ots_kern_free, false },
144
    ots::ots_kern_should_serialise, ots::ots_kern_free, false },
145
  { Tag("vhea"), ots::ots_vhea_parse, ots::ots_vhea_serialise,
146
    ots::ots_vhea_should_serialise, ots::ots_vhea_free, false },
147
  { Tag("vmtx"), ots::ots_vmtx_parse, ots::ots_vmtx_serialise,
148
    ots::ots_vmtx_should_serialise, ots::ots_vmtx_free, false },
145
  { Tag("GDEF"), ots::ots_gdef_parse, ots::ots_gdef_serialise,
149
  { Tag("GDEF"), ots::ots_gdef_parse, ots::ots_gdef_serialise,
146
    ots::ots_gdef_should_serialise, ots::ots_gdef_free, false },
150
    ots::ots_gdef_should_serialise, ots::ots_gdef_free, false },
147
  { Tag("GPOS"), ots::ots_gpos_parse, ots::ots_gpos_serialise,
151
  { Tag("GPOS"), ots::ots_gpos_parse, ots::ots_gpos_serialise,
148
    ots::ots_gpos_should_serialise, ots::ots_gpos_free, false },
152
    ots::ots_gpos_should_serialise, ots::ots_gpos_free, false },
149
  { Tag("GSUB"), ots::ots_gsub_parse, ots::ots_gsub_serialise,
153
  { Tag("GSUB"), ots::ots_gsub_parse, ots::ots_gsub_serialise,
150
    ots::ots_gsub_should_serialise, ots::ots_gsub_free, false },
154
    ots::ots_gsub_should_serialise, ots::ots_gsub_free, false },
151
  // TODO(yusukes): Support GDEF, GPOS, GSUB, mort, base, and jstf tables.
155
  // TODO(yusukes): Support GDEF, GPOS, GSUB, mort, base, and jstf tables.
152
  { 0, NULL, NULL, NULL, NULL, false }
156
  { 0, NULL, NULL, NULL, NULL, false }
(-)a/gfx/ots/src/ots.h (+2 lines)
Line     Link Here 
 Lines 172-187   class Buffer { Link Here 
172
  F(loca, LOCA) \
172
  F(loca, LOCA) \
173
  F(ltsh, LTSH) \
173
  F(ltsh, LTSH) \
174
  F(maxp, MAXP) \
174
  F(maxp, MAXP) \
175
  F(name, NAME) \
175
  F(name, NAME) \
176
  F(os2, OS2) \
176
  F(os2, OS2) \
177
  F(post, POST) \
177
  F(post, POST) \
178
  F(prep, PREP) \
178
  F(prep, PREP) \
179
  F(vdmx, VDMX) \
179
  F(vdmx, VDMX) \
180
  F(vhea, VHEA) \
181
  F(vmtx, VMTX) \
180
  F(vorg, VORG) \
182
  F(vorg, VORG) \
181
  F(gdef, GDEF) \
183
  F(gdef, GDEF) \
182
  F(gpos, GPOS) \
184
  F(gpos, GPOS) \
183
  F(gsub, GSUB)
185
  F(gsub, GSUB)
184
186
185
#define F(name, capname) struct OpenType##capname;
187
#define F(name, capname) struct OpenType##capname;
186
FOR_EACH_TABLE_TYPE
188
FOR_EACH_TABLE_TYPE
187
#undef F
189
#undef F

Return to bug 637481