mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
135 lines
3.7 KiB
C++
135 lines
3.7 KiB
C++
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include <new>
|
|
#include "hmtx.h"
|
|
|
|
#include "hhea.h"
|
|
#include "maxp.h"
|
|
|
|
// hmtx - Horizontal Metrics
|
|
// http://www.microsoft.com/opentype/otspec/hmtx.htm
|
|
// vmtx - Vertical Metrics
|
|
// http://www.microsoft.com/opentype/otspec/vmtx.htm
|
|
// This file is used for both tables because they share the same structures.
|
|
|
|
namespace ots {
|
|
|
|
bool ots_Xmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length,
|
|
const OpenTypeHHEA *hhea, OpenTypeHMTX **out_hmtx) {
|
|
Buffer table(data, length);
|
|
OpenTypeHMTX *hmtx = new OpenTypeHMTX;
|
|
*out_hmtx = hmtx;
|
|
|
|
if (!hhea || !file->maxp) {
|
|
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 = hhea->num_hmetrics;
|
|
|
|
if (num_hmetrics > file->maxp->num_glyphs) {
|
|
return OTS_FAILURE();
|
|
}
|
|
if (!num_hmetrics) {
|
|
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 > hhea->adv_width_max) {
|
|
OTS_WARNING("bad adv: %u > %u", adv, hhea->adv_width_max);
|
|
adv = hhea->adv_width_max;
|
|
}
|
|
if (lsb < hhea->min_lsb) {
|
|
OTS_WARNING("bad lsb: %d < %d", lsb, hhea->min_lsb);
|
|
lsb = 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 < 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, hhea->min_lsb);
|
|
lsb = hhea->min_lsb;
|
|
}
|
|
|
|
hmtx->lsbs.push_back(lsb);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ots_hmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
|
return ots_Xmtx_parse(file, data, length, file->hhea, &file->hmtx);
|
|
}
|
|
|
|
bool ots_vmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
|
return ots_Xmtx_parse(file, data, length, file->vhea, &file->vmtx);
|
|
}
|
|
|
|
bool ots_hmtx_should_serialise(OpenTypeFile *file) {
|
|
return file->hmtx;
|
|
}
|
|
|
|
bool ots_vmtx_should_serialise(OpenTypeFile *file) {
|
|
return file->preserve_otl && file->vmtx;
|
|
}
|
|
|
|
bool ots_Xmtx_serialise(OTSStream *out, OpenTypeFile *file, const OpenTypeHMTX *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();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ots_hmtx_serialise(OTSStream *out, OpenTypeFile *file) {
|
|
return ots_Xmtx_serialise(out, file, file->hmtx);
|
|
}
|
|
|
|
bool ots_vmtx_serialise(OTSStream *out, OpenTypeFile *file) {
|
|
return ots_Xmtx_serialise(out, file, file->vmtx);
|
|
}
|
|
|
|
void ots_hmtx_free(OpenTypeFile *file) {
|
|
delete file->hmtx;
|
|
}
|
|
|
|
void ots_vmtx_free(OpenTypeFile *file) {
|
|
delete file->vmtx;
|
|
}
|
|
|
|
} // namespace ots
|