Skip to content

Commit

Permalink
dd vhea/vmtx table support.
Browse files Browse the repository at this point in the history
- Added vhea.{cc,h} and vmtx.{cc,h}.
- Added metrics.{cc,h} to integrate common functions of hhea/hmtx and vhea/vmtx.
- Moved functions in hhea.cc to metrics.cc.

BUG=77386
TEST=http://code.google.com/p/ots/wiki/HowToTestOts (verified with 3500+ font files)
TEST=test/table_dependencies_test.cc
  • Loading branch information
[email protected] committed Mar 28, 2011
1 parent 3552f4c commit 0c22449
Show file tree
Hide file tree
Showing 15 changed files with 495 additions and 167 deletions.
6 changes: 6 additions & 0 deletions ots-common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
'src/ltsh.h',
'src/maxp.cc',
'src/maxp.h',
'src/metrics.cc',
'src/metrics.h',
'src/name.cc',
'src/os2.cc',
'src/os2.h',
Expand All @@ -56,6 +58,10 @@
'src/prep.h',
'src/vdmx.cc',
'src/vdmx.h',
'src/vhea.cc',
'src/vhea.h',
'src/vmtx.cc',
'src/vmtx.h',
'src/vorg.cc',
'src/vorg.h',
],
Expand Down
79 changes: 4 additions & 75 deletions src/hhea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,69 +17,14 @@ bool ots_hhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
OpenTypeHHEA *hhea = new OpenTypeHHEA;
file->hhea = hhea;

uint32_t version = 0;
if (!table.ReadU32(&version)) {
if (!table.ReadU32(&hhea->header.version)) {
return OTS_FAILURE();
}
if (version >> 16 != 1) {
if (hhea->header.version >> 16 != 1) {
return OTS_FAILURE();
}

if (!table.ReadS16(&hhea->ascent) ||
!table.ReadS16(&hhea->descent) ||
!table.ReadS16(&hhea->linegap) ||
!table.ReadU16(&hhea->adv_width_max) ||
!table.ReadS16(&hhea->min_lsb) ||
!table.ReadS16(&hhea->min_rsb) ||
!table.ReadS16(&hhea->x_max_extent) ||
!table.ReadS16(&hhea->caret_slope_rise) ||
!table.ReadS16(&hhea->caret_slope_run) ||
!table.ReadS16(&hhea->caret_offset)) {
return OTS_FAILURE();
}

if (hhea->ascent < 0) {
OTS_WARNING("bad ascent: %d", hhea->ascent);
hhea->ascent = 0;
}
if (hhea->linegap < 0) {
OTS_WARNING("bad linegap: %d", hhea->linegap);
hhea->linegap = 0;
}

if (!file->head) {
return OTS_FAILURE();
}

// if the font is non-slanted, caret_offset should be zero.
if (!(file->head->mac_style & 2) &&
(hhea->caret_offset != 0)) {
OTS_WARNING("bad caret offset: %d", hhea->caret_offset);
hhea->caret_offset = 0;
}

// skip the reserved bytes
if (!table.Skip(8)) {
return OTS_FAILURE();
}

int16_t data_format;
if (!table.ReadS16(&data_format)) {
return OTS_FAILURE();
}
if (data_format) {
return OTS_FAILURE();
}

if (!table.ReadU16(&hhea->num_hmetrics)) {
return OTS_FAILURE();
}

if (!file->maxp) {
return OTS_FAILURE();
}

if (hhea->num_hmetrics > file->maxp->num_glyphs) {
if (!ParseMetricsHeader(file, &table, &hhea->header)) {
return OTS_FAILURE();
}

Expand All @@ -91,25 +36,9 @@ bool ots_hhea_should_serialise(OpenTypeFile *file) {
}

bool ots_hhea_serialise(OTSStream *out, OpenTypeFile *file) {
const OpenTypeHHEA *hhea = file->hhea;

if (!out->WriteU32(0x00010000) ||
!out->WriteS16(hhea->ascent) ||
!out->WriteS16(hhea->descent) ||
!out->WriteS16(hhea->linegap) ||
!out->WriteU16(hhea->adv_width_max) ||
!out->WriteS16(hhea->min_lsb) ||
!out->WriteS16(hhea->min_rsb) ||
!out->WriteS16(hhea->x_max_extent) ||
!out->WriteS16(hhea->caret_slope_rise) ||
!out->WriteS16(hhea->caret_slope_run) ||
!out->WriteS16(hhea->caret_offset) ||
!out->WriteR64(0) || // reserved
!out->WriteS16(0) || // metric data format
!out->WriteU16(hhea->num_hmetrics)) {
if (!SerialiseMetricsHeader(out, &file->hhea->header)) {
return OTS_FAILURE();
}

return true;
}

Expand Down
13 changes: 2 additions & 11 deletions src/hhea.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,13 @@
#ifndef OTS_HHEA_H_
#define OTS_HHEA_H_

#include "metrics.h"
#include "ots.h"

namespace ots {

struct OpenTypeHHEA {
int16_t ascent;
int16_t descent;
int16_t linegap;
uint16_t adv_width_max;
int16_t min_lsb;
int16_t min_rsb;
int16_t x_max_extent;
int16_t caret_slope_rise;
int16_t caret_slope_run;
int16_t caret_offset;
uint16_t num_hmetrics;
OpenTypeMetricsHeader header;
};

} // namespace ots
Expand Down
68 changes: 4 additions & 64 deletions src/hmtx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,58 +21,10 @@ bool ots_hmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
return OTS_FAILURE();
}

// |num_hmetrics| is a uint16_t, so it's bounded < 65536. This limits that
// amount of memory that we'll allocate for this to a sane amount.
const unsigned num_hmetrics = file->hhea->num_hmetrics;

if (num_hmetrics > file->maxp->num_glyphs) {
return OTS_FAILURE();
}
if (!num_hmetrics) {
if (!ParseMetricsTable(&table, file->maxp->num_glyphs,
&file->hhea->header, &hmtx->metrics)) {
return OTS_FAILURE();
}
const unsigned num_lsbs = file->maxp->num_glyphs - num_hmetrics;

hmtx->metrics.reserve(num_hmetrics);
for (unsigned i = 0; i < num_hmetrics; ++i) {
uint16_t adv = 0;
int16_t lsb = 0;
if (!table.ReadU16(&adv) || !table.ReadS16(&lsb)) {
return OTS_FAILURE();
}

// Since so many fonts don't have proper value on |adv| and |lsb|,
// we should not call ots_failure() here. For example, about 20% of fonts
// in http://www.princexml.com/fonts/ (200+ fonts) fails these tests.
if (adv > file->hhea->adv_width_max) {
OTS_WARNING("bad adv: %u > %u", adv, file->hhea->adv_width_max);
adv = file->hhea->adv_width_max;
}
if (lsb < file->hhea->min_lsb) {
OTS_WARNING("bad lsb: %d < %d", lsb, file->hhea->min_lsb);
lsb = file->hhea->min_lsb;
}

hmtx->metrics.push_back(std::make_pair(adv, lsb));
}

hmtx->lsbs.reserve(num_lsbs);
for (unsigned i = 0; i < num_lsbs; ++i) {
int16_t lsb;
if (!table.ReadS16(&lsb)) {
// Some Japanese fonts (e.g., mona.ttf) fail this test.
return OTS_FAILURE();
}

if (lsb < file->hhea->min_lsb) {
// The same as above. Three fonts in http://www.fontsquirrel.com/fontface
// (e.g., Notice2Std.otf) have weird lsb values.
OTS_WARNING("bad lsb: %d < %d", lsb, file->hhea->min_lsb);
lsb = file->hhea->min_lsb;
}

hmtx->lsbs.push_back(lsb);
}

return true;
}
Expand All @@ -82,21 +34,9 @@ bool ots_hmtx_should_serialise(OpenTypeFile *file) {
}

bool ots_hmtx_serialise(OTSStream *out, OpenTypeFile *file) {
const OpenTypeHMTX *hmtx = file->hmtx;

for (unsigned i = 0; i < hmtx->metrics.size(); ++i) {
if (!out->WriteU16(hmtx->metrics[i].first) ||
!out->WriteS16(hmtx->metrics[i].second)) {
return OTS_FAILURE();
}
}

for (unsigned i = 0; i < hmtx->lsbs.size(); ++i) {
if (!out->WriteS16(hmtx->lsbs[i])) {
return OTS_FAILURE();
}
if (!SerialiseMetricsTable(out, &file->hmtx->metrics)) {
return OTS_FAILURE();
}

return true;
}

Expand Down
7 changes: 2 additions & 5 deletions src/hmtx.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@
#ifndef OTS_HMTX_H_
#define OTS_HMTX_H_

#include <utility> // std::pair
#include <vector>

#include "metrics.h"
#include "ots.h"

namespace ots {

struct OpenTypeHMTX {
std::vector<std::pair<uint16_t, int16_t> > metrics;
std::vector<int16_t> lsbs;
OpenTypeMetricsTable metrics;
};

} // namespace ots
Expand Down
Loading

0 comments on commit 0c22449

Please sign in to comment.