Commit a72cd111 authored by bashi's avatar bashi Committed by Commit bot

Revert of Updating OTS repo from https://github.com/khaledhosny/ots.git...

Revert of Updating OTS repo from https://github.com/khaledhosny/ots.git (patchset #4 id:60001 of https://codereview.chromium.org/775893002/)

Reason for revert:
Broke bots

Original issue's description:
> The original CL is https://codereview.chromium.org/658573004
>
> Updating with to new OTS repo from https://github.com/khaledhosny/ots.git
> Hash tag imported: c24a839b1c66c4de09e58fabaacb82bf3bd692a4
>
> Some important differences between new and old version of OTS:
> 1. Support for MATH table
> 2. Implementation changes related to new WOFF 2.0
> 3. Bug fixes related to OTF tables (GDEF, GSUB etc) parsing
> 4. Accept platform 0 encoding 1 cmap subtables
> 5. Allow fonts with CMAP format-12 or format-13 table
>
> A dummy version of EnableWOFF() is added to get Blink compiled.
> After the following CL is landed in Blink, it'll be removed.
> Blink CL: https://codereview.chromium.org/774253008
>
> # TODO(jschuh): 4267, 4334 are 64-bit cleanness issue. http://crbug.com/167187
>
> # TODO(h.joshi) : Make 4800 go away. <https://github.com/khaledhosny/ots/issues/44>.
> Currently patch to github (https://github.com/himanshuispresent/ots/commit/02f724f758ddb1cb264cc0259ffd5ef1cafa164a) is
> submitted so that taking OTS repository to Chromium should not cause issue on Windows bots.
>
> TEST: Blink layout tests: fast/css/font-face*
> BUG=339857
>
> Committed: https://crrev.com/3b6cd2d4bf9e0b4a9311343a2997ef9363530b14
> Cr-Commit-Position: refs/heads/master@{#308054}

TBR=jshin@chromium.org,behdad@chromium.org,h.joshi@samsung.com
NOTREECHECKS=true
NOTRY=true
BUG=339857

Review URL: https://codereview.chromium.org/797183002

Cr-Commit-Position: refs/heads/master@{#308061}
parent bc6edc0d
...@@ -339,6 +339,7 @@ v8.log ...@@ -339,6 +339,7 @@ v8.log
/third_party/omaha/src/omaha /third_party/omaha/src/omaha
/third_party/openmax_dl/ /third_party/openmax_dl/
/third_party/opus/src /third_party/opus/src
/third_party/ots
/third_party/pdfsqueeze /third_party/pdfsqueeze
/third_party/pdfium /third_party/pdfium
/third_party/pefile /third_party/pefile
......
...@@ -186,6 +186,9 @@ deps = { ...@@ -186,6 +186,9 @@ deps = {
'src/third_party/skia': 'src/third_party/skia':
Var('chromium_git') + '/skia.git' + '@' + Var('skia_revision'), Var('chromium_git') + '/skia.git' + '@' + Var('skia_revision'),
'src/third_party/ots':
Var('chromium_git') + '/external/ots.git' + '@' + '98897009f3ea8a5fa3e20a4a74977da7aaa8e61a',
'src/third_party/brotli/src': 'src/third_party/brotli/src':
Var('chromium_git') + '/external/font-compression-reference.git' + '@' + '8c9c83426beb4a58da34be76ea1fccb4054c4703', Var('chromium_git') + '/external/font-compression-reference.git' + '@' + '8c9c83426beb4a58da34be76ea1fccb4054c4703',
......
*.Makefile
*.swp
*.target.mk
/Makefile
/out/
/third_party/gyp
[submodule "third_party/brotli"]
path = third_party/brotli
url = https://github.com/google/brotli.git
# Copyright 2014 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.
config("ots_config") {
include_dirs = [ "include" ]
}
source_set("ots") {
sources = [
"include/ots-memory-stream.h",
"include/opentype-sanitiser.h",
"src/cff.cc",
"src/cff.h",
"src/cff_type2_charstring.cc",
"src/cff_type2_charstring.h",
"src/cmap.cc",
"src/cmap.h",
"src/cvt.cc",
"src/cvt.h",
"src/fpgm.cc",
"src/fpgm.h",
"src/gasp.cc",
"src/gasp.h",
"src/gdef.cc",
"src/gdef.h",
"src/glyf.cc",
"src/glyf.h",
"src/gpos.cc",
"src/gpos.h",
"src/gsub.cc",
"src/gsub.h",
"src/hdmx.cc",
"src/hdmx.h",
"src/head.cc",
"src/head.h",
"src/hhea.cc",
"src/hhea.h",
"src/hmtx.cc",
"src/hmtx.h",
"src/kern.cc",
"src/kern.h",
"src/layout.cc",
"src/layout.h",
"src/loca.cc",
"src/loca.h",
"src/ltsh.cc",
"src/ltsh.h",
"src/maxp.cc",
"src/maxp.h",
"src/math.cc",
"src/math_.h",
"src/metrics.cc",
"src/metrics.h",
"src/name.cc",
"src/name.h",
"src/os2.cc",
"src/os2.h",
"src/ots.cc",
"src/ots.h",
"src/post.cc",
"src/post.h",
"src/prep.cc",
"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",
"src/woff2.cc",
"src/woff2.h",
]
direct_dependent_configs = [ ":ots_config" ]
deps = [
"//third_party/brotli",
"//third_party/zlib",
]
if (is_win) {
cflags = [
"/wd4267", # Conversion from size_t to 'type'.
"/wd4334", # 32-bit shift implicitly converted to 64-bits.
"/wd4800", # 'type' : forcing value to bool 'true' or 'false'.
]
}
}
How to build (using gyp):
(Note: test programs which require gtest can't build with gyp for now)
1. If you are building OTS on Windows, download both the source
code and compiled driver for zlib from http://www.zlib.net/
and put them in third_party/zlib.
2. If you are building from cloned Git repository, make sure to update the
submodules as well:
$ git submodule init
$ git submodule update
3. Run gyp_ots
$ python gyp_ots
This will fetch gyp and generate build files. By default, following
files will be generated:
- MSVS solution file on Windows
- Xcode project file on Mac
- Makefile on Linux
If you want to generate Makefile on Mac, you can use -f option:
$ python gyp_ots -f make
4. Build OTS
Using MSVS:
Open ots-standalone.sln and build the solution.
Using Xcode:
$ xcodebuild -target ots-standalone.xcodeproj -target all
Using Makefile:
$ make
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
bashi@chromium.org
behdad@chromium.org
behdad@google.com
jshin@chromium.org
Sanitiser for OpenType
----------------------
(Idea from Alex Russell)
The CSS font-face property[1] is great for web typography. Having to use images
in order to get the correct typeface is a great sadness; one should be able to
use vectors.
However, the TrueType renderers on many platforms have never been part of the
attack surface before and putting them on the front line is a scary proposition.
Esp on platforms like Windows where it's a closed-source blob running with high
privilege.
Thus, the OpenType Sanitiser (OTS) is designed to parse and serialise OpenType
files, validating them and sanitising them as it goes.
See INSTALL for build instructions.
[1] http://www.w3.org/TR/CSS2/fonts.html#font-descriptions
Name: OTS
URL: https://github.com/khaledhosny/ots.git
Version: 09caf8373ae377e16c453476deb7c2d4ca384add
Security Critical: yes
License: BSD
What's OTS?
===========
Sanitiser for OpenType (OTS) is a small library which parses OpenType files
(usually from `@font-face`) and attempts to validate and sanitise them. This
library is primarily intended to be used with Chromium. We hope this reduces
the attack surface of the system font libraries.
What the sanitiser does is as follows:
1. Parses an original font. If the parsing fails, OTS rejects the original
font.
2. Validates the parsed data structure. If the validation fails, it rejects the
original font as well.
3. Creates a new font on memory by serializing the data structure, and we call
this "transcoding".
By transcoding fonts in this way, it is ensured that:
1. All information in an original font that OTS doesn't know or can't parse is
dropped from the transcoded font.
2. All information in the transcoded font is valid (standard compliant).
Particularly 'length' and 'offset' values, that are often used as attack
vectors, are ensured to be correct.
Supported OpenType tables
=========================
| Name | Mandatory table? | Supported by OTS? | Note |
|--------|-----------------------------|-------------------|--------|
| `sfnt` | Yes | Yes | Overlapped tables are not allowed; it is treated as a fatal parser error.|
| `maxp` | Yes | Yes | |
| `head` | Yes | Yes | |
| `hhea` | Yes | Yes | |
| `hmtx` | Yes | Yes | |
| `name` | Yes | Yes | |
| `OS/2` | Yes | Yes | |
| `post` | Yes | Yes | |
| `cmap` | Yes | Partialy | see below |
| `glyf` | Yes, for TrueType fonts | Yes | TrueType bytecode is supported, but OTS does **not** validate it.|
| `loca` | Yes, when glyf table exists | Yes | |
| `CFF ` | Yes, for OpenType fonts | Yes | OpenType bytecode is also supported, and OTS **does** validate it.|
| `cvt ` | No | Yes | Though this table is not mandatory, OTS can't drop the table from a transcoded font since it might be referred from other hinting-related tables. Errors on this table should be treated as fatal.|
| `fpgm` | No | Yes | Ditto. |
| `prep` | No | Yes | Ditto. |
| `VDMX` | No | Yes | This table is important for calculating the correct line spacing, at least on Chromium Windows and Chromium Linux.|
| `hdmx` | No | Yes | |
| `gasp` | No | Yes | |
| `VORG` | No | Yes | |
| `LTSH` | No | Yes | |
| `kern` | No | Yes | |
| `GDEF` | No | Yes | |
| `GSUB` | No | Yes | |
| `GPOS` | No | Yes | |
| `morx` | No | No | |
| `jstf` | No | No | |
| `vmtx` | No | Yes | |
| `vhea` | No | Yes | |
| `EBDT` | No | No | We don't support embedded bitmap strikes.|
| `EBLC` | No | No | Ditto. |
| `EBSC` | No | No | Ditto. |
| `bdat` | No | No | Ditto. |
| `bhed` | No | No | Ditto. |
| `bloc` | No | No | Ditto. |
| `DSIG` | No | No | |
| All other tables | - | No | |
Please note that OTS library does not parse "unsupported" tables. These
unsupported tables never appear in a transcoded font.
Supported cmap formats
----------------------
The following 9 formats are supported:
* "MS Unicode" (platform 3 encoding 1 format 4)
* BMP
* "MS UCS-4" (platform 3 encoding 10 format 12)
* "MS UCS-4 fallback" (platform 3 encoding 10 format 13)
* "MS Symbol" (platform 3 encoding 0 format 4)
* "Mac Roman" (platform 1 encoding 0 format 0)
* 1-0-0 format is supported while 1-0-6 is not.
* "Unicode default" format (platform 0 encoding 0 format 4)
* treated as 3-1-4 format
* "Unicode 1.1" format (platform 0 encoding 1 format 4)
* ditto
* "Unicode 2.0+" format (platform 0 encoding 3 format 4)
* "Unicode UCS-4" format (platform 0 encoding 4 format 12)
* treated as 3-10-12 format
* Unicode Variation Sequences (platform 0 encoding 5 format 14)
All other types of subtables are not supported and do not appear in transcoded fonts.
Validation strategies
=====================
With regards to 8 mandatory tables, glyph-related tables (`glyf`, `loca` and `CFF`),
and hinting-related tables (`cvt`, `prep`, and `fpgm`):
* If OTS finds table-length, table-offset, or table-alignment errors, in other
words it cannot continue parsing, OTS treats the error as fatal.
* If OTS finds simple value error which could be automatically fixed (e.g.,
font weight is greater than 900 - that's undefined), and if the error is
considered common among non-malicious fonts, OTS rewrites the value and
continues transcoding.
* If OTS finds a value error which is hard to fix (e.g., values which should be
sorted are left unsorted), OTS treats the error as fatal.
With regards to optional tables (`VORG`, `gasp`, `hdmx`, `LTSH`, and `VDMX`):
* If OTS finds table-length, table-offset, or table-alignment errors, OTS
treats the error as fatal.
* If OTS finds other errors, it simply drops the table from a transcoded font.
Files
=====
* include/opentype-sanitiser.h
* Declaration for the public API, `ots::Process()`.
* Definition of the `OTSStream` interface, a write-only memory stream.
* include/ots-memory-stream.h
* Definition of the `MemoryStream` class which implements the `OTSStream`
interface above.
* src/ots.h
* Debug macros.
* Definition of a `Buffer` class which is a read-only memory stream.
* src/ots.cc
* Definition of the `ots::Process()` function.
* `sfnt` table parser.
* test/\*.cc
* test tools. see test/README for details.
Known issues
============
Please check the [issues](https://github.com/khaledhosny/ots/issues) page.
Prerequisites
=============
You can use your Ubuntu box (>= 8.04. 9.10 is recommended) to test OTS library.
First, install TrueType and OpenType fonts to the Ubuntu box as many as
possible.
% sudo apt-get install ttf-.*[^0]$
Then, put malicious TrueType fonts on `~/malicious/`. For details, please check
http://code.google.com/p/chromium/issues/detail?id=27139#c2. Currently access
to the issue is limited to chromium-security team members for security reasons.
% cd
% tar xjf ~/ttf-testsuite.tar.bz2
Test
====
In order to verify that:
1. OTS does not reject these unmalicious fonts.
2. and transcoded fonts OTS generates can be loaded by a system font renderer (FreeType2).
Run `test_unmalicious_fonts.sh` script:
% cd /path/to/ots/tests
% ./test_unmalicious_fonts.sh
............................................... (verify that no FAIL: is displayed)
Then in order to verify that:
1. OTS can reject malicious fonts
2. or transcoded fonts generated by OTS do not crash a system font renderer (FreeType2).
Run `test_malicious_fonts.sh` script:
% cd /path/to/ots/tests
% ./test_malicious_fonts.sh
............................................... (verify that no FAIL: is displayed)
Command line tools
==================
We have some command line tools for tests. To build them:
- On Linux:
% gyp --depth=. -f make ots-standalone.gyp
% make
(tool is located at build/Default directory)
- On Windows (VC++ is needed):
% gyp --depth=. -f msvs ots-standalone.gyp
% devenv.exe /build Default ots-standalone.sln /project idempotent.vcproj
(tool is located at Default directory)
- On Mac (XCode is needed):
% gyp --depth=. -f xcode ots-standalone.gyp
% xcodebuild -configuration Default -project ots-standalone.xcodeproj -target All
(tool is located at build/Default directory)
You can use `idempotent` tool to check whether a font will be rejected or not.
You can also use `ot-sanitise` tool to get sanitised font (it is available on
Linux for now). See README file in the test directory for more details.
#!/usr/bin/env python
# Copyright (c) 2012 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.
import os
import subprocess
import sys
_GYP_REVISION = '1344'
_GYP_FETCH_URL = 'https://gyp.googlecode.com/svn/trunk@' + _GYP_REVISION
def _fetch_gyp():
gyp_dir = os.path.join('third_party', 'gyp')
if not os.path.exists(gyp_dir):
retcode = subprocess.call(['svn', 'checkout', _GYP_FETCH_URL, gyp_dir])
if retcode < 0:
raise "Couldn't fetch gyp"
# TODO(bashi): Check revision, etc
sys.path.insert(0, os.path.abspath(os.path.join(gyp_dir, 'pylib')))
def main():
script_dir = os.path.abspath(os.path.dirname(__file__))
os.chdir(script_dir)
_fetch_gyp()
import gyp
args = []
args.extend(['--depth', '.'])
args.extend(sys.argv[1:])
args.append(os.path.join(script_dir, 'ots-standalone.gyp'))
sys.exit(gyp.main(args))
if __name__ == '__main__':
main()
// 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.
#ifndef OPENTYPE_SANITISER_H_
#define OPENTYPE_SANITISER_H_
#if defined(_WIN32)
#include <stdlib.h>
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define ntohl(x) _byteswap_ulong (x)
#define ntohs(x) _byteswap_ushort (x)
#define htonl(x) _byteswap_ulong (x)
#define htons(x) _byteswap_ushort (x)
#else
#include <arpa/inet.h>
#include <stdint.h>
#endif
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
namespace ots {
// -----------------------------------------------------------------------------
// This is an interface for an abstract stream class which is used for writing
// the serialised results out.
// -----------------------------------------------------------------------------
class OTSStream {
public:
OTSStream() {
ResetChecksum();
}
virtual ~OTSStream() {}
// This should be implemented to perform the actual write.
virtual bool WriteRaw(const void *data, size_t length) = 0;
bool Write(const void *data, size_t length) {
if (!length) return false;
const size_t orig_length = length;
size_t offset = 0;
if (chksum_buffer_offset_) {
const size_t l =
std::min(length, static_cast<size_t>(4) - chksum_buffer_offset_);
std::memcpy(chksum_buffer_ + chksum_buffer_offset_, data, l);
chksum_buffer_offset_ += l;
offset += l;
length -= l;
}
if (chksum_buffer_offset_ == 4) {
uint32_t tmp;
std::memcpy(&tmp, chksum_buffer_, 4);
chksum_ += ntohl(tmp);
chksum_buffer_offset_ = 0;
}
while (length >= 4) {
uint32_t tmp;
std::memcpy(&tmp, reinterpret_cast<const uint8_t *>(data) + offset,
sizeof(uint32_t));
chksum_ += ntohl(tmp);
length -= 4;
offset += 4;
}
if (length) {
if (chksum_buffer_offset_ != 0) return false; // not reached
if (length > 4) return false; // not reached
std::memcpy(chksum_buffer_,
reinterpret_cast<const uint8_t*>(data) + offset, length);
chksum_buffer_offset_ = length;
}
return WriteRaw(data, orig_length);
}
virtual bool Seek(off_t position) = 0;
virtual off_t Tell() const = 0;
virtual bool Pad(size_t bytes) {
static const uint32_t kZero = 0;
while (bytes >= 4) {
if (!WriteTag(kZero)) return false;
bytes -= 4;
}
while (bytes) {
static const uint8_t kZerob = 0;
if (!Write(&kZerob, 1)) return false;
bytes--;
}
return true;
}
bool WriteU8(uint8_t v) {
return Write(&v, sizeof(v));
}
bool WriteU16(uint16_t v) {
v = htons(v);
return Write(&v, sizeof(v));
}
bool WriteS16(int16_t v) {
v = htons(v);
return Write(&v, sizeof(v));
}
bool WriteU24(uint32_t v) {
v = htonl(v);
return Write(reinterpret_cast<uint8_t*>(&v)+1, 3);
}
bool WriteU32(uint32_t v) {
v = htonl(v);
return Write(&v, sizeof(v));
}
bool WriteS32(int32_t v) {
v = htonl(v);
return Write(&v, sizeof(v));
}
bool WriteR64(uint64_t v) {
return Write(&v, sizeof(v));
}
bool WriteTag(uint32_t v) {
return Write(&v, sizeof(v));
}
void ResetChecksum() {
chksum_ = 0;
chksum_buffer_offset_ = 0;
}
uint32_t chksum() const {
assert(chksum_buffer_offset_ == 0);
return chksum_;
}
struct ChecksumState {
uint32_t chksum;
uint8_t chksum_buffer[4];
unsigned chksum_buffer_offset;
};
ChecksumState SaveChecksumState() const {
ChecksumState s;
s.chksum = chksum_;
s.chksum_buffer_offset = chksum_buffer_offset_;
std::memcpy(s.chksum_buffer, chksum_buffer_, 4);
return s;
}
void RestoreChecksum(const ChecksumState &s) {
assert(chksum_buffer_offset_ == 0);
chksum_ += s.chksum;
chksum_buffer_offset_ = s.chksum_buffer_offset;
std::memcpy(chksum_buffer_, s.chksum_buffer, 4);
}
protected:
uint32_t chksum_;
uint8_t chksum_buffer_[4];
unsigned chksum_buffer_offset_;
};
#ifdef __GCC__
#define MSGFUNC_FMT_ATTR __attribute__((format(printf, 2, 3)))
#else
#define MSGFUNC_FMT_ATTR
#endif
enum TableAction {
TABLE_ACTION_DEFAULT, // Use OTS's default action for that table
TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it
TABLE_ACTION_PASSTHRU, // Serialize the table unchanged
TABLE_ACTION_DROP // Drop the table
};
class OTSContext {
public:
OTSContext() {}
virtual ~OTSContext() {}
// Process a given OpenType file and write out a sanitised version
// output: a pointer to an object implementing the OTSStream interface. The
// sanitisied output will be written to this. In the even of a failure,
// partial output may have been written.
// input: the OpenType file
// length: the size, in bytes, of |input|
// context: optional context that holds various OTS settings like user callbacks
bool Process(OTSStream *output, const uint8_t *input, size_t length);
// This function will be called when OTS is reporting an error.
// level: the severity of the generated message:
// 0: error messages in case OTS fails to sanitize the font.
// 1: warning messages about issue OTS fixed in the sanitized font.
virtual void Message(int level, const char *format, ...) MSGFUNC_FMT_ATTR {}
// This function will be called when OTS needs to decide what to do for a
// font table.
// tag: table tag as an integer in big-endian byte order, independent of
// platform endianness
virtual TableAction GetTableAction(uint32_t tag) { return ots::TABLE_ACTION_DEFAULT; }
};
// For backward compatibility - remove once Chrome switches over to the new API.
bool Process(OTSStream *output, const uint8_t *input, size_t length);
// For backward compatibility - remove once https://codereview.chromium.org/774253008/
// is submitted.
void EnableWOFF2();
} // namespace ots
#endif // OPENTYPE_SANITISER_H_
// 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.
#ifndef OTS_MEMORY_STREAM_H_
#define OTS_MEMORY_STREAM_H_
#include <cstring>
#include <limits>
#include "opentype-sanitiser.h"
namespace ots {
class MemoryStream : public OTSStream {
public:
MemoryStream(void *ptr, size_t length)
: ptr_(ptr), length_(length), off_(0) {
}
virtual bool WriteRaw(const void *data, size_t length) {
if ((off_ + length > length_) ||
(length > std::numeric_limits<size_t>::max() - off_)) {
return false;
}
std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
off_ += length;
return true;
}
virtual bool Seek(off_t position) {
if (position < 0) return false;
if (static_cast<size_t>(position) > length_) return false;
off_ = position;
return true;
}
virtual off_t Tell() const {
return off_;
}
private:
void* const ptr_;
size_t length_;
off_t off_;
};
class ExpandingMemoryStream : public OTSStream {
public:
ExpandingMemoryStream(size_t initial, size_t limit)
: length_(initial), limit_(limit), off_(0) {
ptr_ = new uint8_t[length_];
}
~ExpandingMemoryStream() {
delete[] static_cast<uint8_t*>(ptr_);
}
void* get() const {
return ptr_;
}
bool WriteRaw(const void *data, size_t length) {
if ((off_ + length > length_) ||
(length > std::numeric_limits<size_t>::max() - off_)) {
if (length_ == limit_)
return false;
size_t new_length = (length_ + 1) * 2;
if (new_length < length_)
return false;
if (new_length > limit_)
new_length = limit_;
uint8_t* new_buf = new uint8_t[new_length];
std::memcpy(new_buf, ptr_, length_);
length_ = new_length;
delete[] static_cast<uint8_t*>(ptr_);
ptr_ = new_buf;
return WriteRaw(data, length);
}
std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
off_ += length;
return true;
}
bool Seek(off_t position) {
if (position < 0) return false;
if (static_cast<size_t>(position) > length_) return false;
off_ = position;
return true;
}
off_t Tell() const {
return off_;
}
private:
void* ptr_;
size_t length_;
const size_t limit_;
off_t off_;
};
} // namespace ots
#endif // OTS_MEMORY_STREAM_H_
# 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.
{
'variables': {
'ots_sources': [
'include/ots-memory-stream.h',
'include/opentype-sanitiser.h',
'src/cff.cc',
'src/cff.h',
'src/cff_type2_charstring.cc',
'src/cff_type2_charstring.h',
'src/cmap.cc',
'src/cmap.h',
'src/cvt.cc',
'src/cvt.h',
'src/fpgm.cc',
'src/fpgm.h',
'src/gasp.cc',
'src/gasp.h',
'src/gdef.cc',
'src/gdef.h',
'src/glyf.cc',
'src/glyf.h',
'src/gpos.cc',
'src/gpos.h',
'src/gsub.cc',
'src/gsub.h',
'src/hdmx.cc',
'src/hdmx.h',
'src/head.cc',
'src/head.h',
'src/hhea.cc',
'src/hhea.h',
'src/hmtx.cc',
'src/hmtx.h',
'src/kern.cc',
'src/kern.h',
'src/layout.cc',
'src/layout.h',
'src/loca.cc',
'src/loca.h',
'src/ltsh.cc',
'src/ltsh.h',
'src/maxp.cc',
'src/maxp.h',
'src/math.cc',
'src/math_.h',
'src/metrics.cc',
'src/metrics.h',
'src/name.cc',
'src/name.h',
'src/os2.cc',
'src/os2.h',
'src/ots.cc',
'src/ots.h',
'src/post.cc',
'src/post.h',
'src/prep.cc',
'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',
'src/woff2.cc',
'src/woff2.h',
],
'ots_include_dirs': [
'include',
],
},
}
# Copyright (c) 2012 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.
{
'variables': {
'gcc_cflags': [
'-ggdb',
'-W',
'-Wall',
'-Wshadow',
'-Wno-unused-parameter',
'-fPIE',
'-fstack-protector',
],
'gcc_ldflags': [
'-ggdb',
'-fpie',
'-Wl,-z,relro',
'-Wl,-z,now',
],
},
'includes': [
'ots-common.gypi',
],
'target_defaults': {
'include_dirs': [
'.',
'third_party/brotli/dec',
],
'conditions': [
['OS=="linux"', {
'cflags': [
'<@(gcc_cflags)',
'-O',
],
'ldflags': [
'<@(gcc_ldflags)',
],
'defines': [
'_FORTIFY_SOURCE=2',
],
'link_settings': {
'libraries': ['-lz'],
},
}],
['OS=="mac"', {
'xcode_settings': {
'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic
'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
'OTHER_CFLAGS': [
'<@(gcc_cflags)',
],
},
'link_settings': {
'libraries': [
'/System/Library/Frameworks/ApplicationServices.framework',
'/usr/lib/libz.dylib'
],
},
}],
['OS=="win"', {
'link_settings': {
'libraries': [
'-lzdll.lib',
],
},
'msvs_settings': {
'VCLinkerTool': {
'AdditionalLibraryDirectories': ['third_party/zlib'],
'DelayLoadDLLs': ['zlib1.dll'],
},
},
'include_dirs': [
'third_party/zlib',
],
'defines': [
'NOMINMAX', # To suppress max/min macro definition.
'WIN32',
],
}],
],
},
'targets': [
{
'target_name': 'ots',
'type': 'static_library',
'sources': [
'<@(ots_sources)',
],
'dependencies': [
'third_party/brotli.gyp:brotli',
],
'include_dirs': [
'<@(ots_include_dirs)',
],
'direct_dependent_settings': {
'include_dirs': [
'<@(ots_include_dirs)',
],
},
},
{
'target_name': 'freetype2',
'type': 'none',
'conditions': [
['OS=="linux"', {
'direct_dependent_settings': {
'cflags': [
'<!(pkg-config freetype2 --cflags)',
],
'link_settings': {
'libraries': [
'<!(pkg-config freetype2 --libs)',
],
},
},
}],
],
},
{
'target_name': 'idempotent',
'type': 'executable',
'sources': [
'test/idempotent.cc',
],
'dependencies': [
'ots',
],
'conditions': [
['OS=="linux"', {
'dependencies': [
'freetype2',
]
}],
['OS=="win"', {
'link_settings': {
'libraries': [
'-lgdi32.lib',
],
},
}],
],
},
{
'target_name': 'ot-sanitise',
'type': 'executable',
'sources': [
'test/ot-sanitise.cc',
'test/file-stream.h',
],
'dependencies': [
'ots',
],
},
],
'conditions': [
['OS=="linux" or OS=="mac"', {
'targets': [
{
'target_name': 'validator_checker',
'type': 'executable',
'sources': [
'test/validator-checker.cc',
],
'dependencies': [
'ots',
],
'conditions': [
['OS=="linux"', {
'dependencies': [
'freetype2',
]
}],
],
},
{
'target_name': 'perf',
'type': 'executable',
'sources': [
'test/perf.cc',
],
'dependencies': [
'ots',
],
},
{
'target_name': 'cff_type2_charstring_test',
'type': 'executable',
'sources': [
'test/cff_type2_charstring_test.cc',
],
'dependencies': [
'ots',
],
'libraries': [
'-lgtest',
'-lgtest_main',
],
'include_dirs': [
'src',
],
},
{
'target_name': 'layout_common_table_test',
'type': 'executable',
'sources': [
'test/layout_common_table_test.cc',
],
'dependencies': [
'ots',
],
'libraries': [
'-lgtest',
'-lgtest_main',
],
'include_dirs': [
'src',
],
},
{
'target_name': 'table_dependencies_test',
'type': 'executable',
'sources': [
'test/table_dependencies_test.cc',
],
'dependencies': [
'ots',
],
'libraries': [
'-lgtest',
'-lgtest_main',
],
'include_dirs': [
'src',
],
},
],
}],
['OS=="linux"', {
'targets': [
{
'target_name': 'side_by_side',
'type': 'executable',
'sources': [
'test/side-by-side.cc',
],
'dependencies': [
'freetype2',
'ots',
],
},
],
}],
],
}
# 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.
{
'variables': {
'chromium_code': 1,
},
'includes': [
'ots-common.gypi',
],
'targets': [
{
'target_name': 'ots',
'type': 'static_library',
'sources': [
'<@(ots_sources)',
],
'include_dirs': [
'../..',
'<@(ots_include_dirs)',
],
'direct_dependent_settings': {
'include_dirs': [
'<@(ots_include_dirs)',
],
},
'dependencies': [
'../brotli/brotli.gyp:brotli',
'../zlib/zlib.gyp:zlib',
],
# TODO(jschuh): http://crbug.com/167187
'msvs_disabled_warnings': [
4267,
4334,
4800,
],
},
],
}
This diff is collapsed.
// 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.
#ifndef OTS_CFF_H_
#define OTS_CFF_H_
#include "ots.h"
#include <map>
#include <string>
#include <vector>
namespace ots {
struct CFFIndex {
CFFIndex()
: count(0), off_size(0), offset_to_next(0) {}
uint16_t count;
uint8_t off_size;
std::vector<uint32_t> offsets;
uint32_t offset_to_next;
};
struct OpenTypeCFF {
const uint8_t *data;
size_t length;
// Name INDEX. This name is used in name.cc as a postscript font name.
std::string name;
// The number of fonts the file has.
size_t font_dict_length;
// A map from glyph # to font #.
std::map<uint16_t, uint8_t> fd_select;
// A list of char strings.
std::vector<CFFIndex *> char_strings_array;
// A list of Local Subrs associated with FDArrays. Can be empty.
std::vector<CFFIndex *> local_subrs_per_font;
// A Local Subrs associated with Top DICT. Can be NULL.
CFFIndex *local_subrs;
};
} // namespace ots
#endif // OTS_CFF_H_
This diff is collapsed.
// Copyright (c) 2010 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.
#ifndef OTS_CFF_TYPE2_CHARSTRING_H_
#define OTS_CFF_TYPE2_CHARSTRING_H_
#include "cff.h"
#include "ots.h"
#include <map>
#include <vector>
namespace ots {
// Validates all charstrings in |char_strings_index|. Charstring is a small
// language for font hinting defined in Adobe Technical Note #5177.
// http://www.adobe.com/devnet/font/pdfs/5177.Type2.pdf
//
// The validation will fail if one of the following conditions is met:
// 1. The code uses more than 48 values of argument stack.
// 2. The code uses deeply nested subroutine calls (more than 10 levels.)
// 3. The code passes invalid number of operands to an operator.
// 4. The code calls an undefined global or local subroutine.
// 5. The code uses one of the following operators that are unlikely used in
// an ordinary fonts, and could be dangerous: random, put, get, index, roll.
//
// Arguments:
// global_subrs_index: Global subroutines which could be called by a charstring
// in |char_strings_index|.
// fd_select: A map from glyph # to font #.
// local_subrs_per_font: A list of Local Subrs associated with FDArrays. Can be
// empty.
// local_subrs: A Local Subrs associated with Top DICT. Can be NULL.
// cff_table: A buffer which contains actual byte code of charstring, global
// subroutines and local subroutines.
bool ValidateType2CharStringIndex(
OpenTypeFile *file,
const CFFIndex &char_strings_index,
const CFFIndex &global_subrs_index,
const std::map<uint16_t, uint8_t> &fd_select,
const std::vector<CFFIndex *> &local_subrs_per_font,
const CFFIndex *local_subrs,
Buffer *cff_table);
// The list of Operators. See Appendix. A in Adobe Technical Note #5177.
enum Type2CharStringOperator {
kHStem = 1,
kVStem = 3,
kVMoveTo = 4,
kRLineTo = 5,
kHLineTo = 6,
kVLineTo = 7,
kRRCurveTo = 8,
kCallSubr = 10,
kReturn = 11,
kEndChar = 14,
kHStemHm = 18,
kHintMask = 19,
kCntrMask = 20,
kRMoveTo = 21,
kHMoveTo = 22,
kVStemHm = 23,
kRCurveLine = 24,
kRLineCurve = 25,
kVVCurveTo = 26,
kHHCurveTo = 27,
kCallGSubr = 29,
kVHCurveTo = 30,
kHVCurveTo = 31,
kDotSection = 12 << 8,
kAnd = (12 << 8) + 3,
kOr = (12 << 8) + 4,
kNot = (12 << 8) + 5,
kAbs = (12 << 8) + 9,
kAdd = (12 << 8) + 10,
kSub = (12 << 8) + 11,
kDiv = (12 << 8) + 12,
kNeg = (12 << 8) + 14,
kEq = (12 << 8) + 15,
kDrop = (12 << 8) + 18,
kPut = (12 << 8) + 20,
kGet = (12 << 8) + 21,
kIfElse = (12 << 8) + 22,
kRandom = (12 << 8) + 23,
kMul = (12 << 8) + 24,
kSqrt = (12 << 8) + 26,
kDup = (12 << 8) + 27,
kExch = (12 << 8) + 28,
kIndex = (12 << 8) + 29,
kRoll = (12 << 8) + 30,
kHFlex = (12 << 8) + 34,
kFlex = (12 << 8) + 35,
kHFlex1 = (12 << 8) + 36,
kFlex1 = (12 << 8) + 37,
// Operators that are undocumented, such as 'blend', will be rejected.
};
} // namespace ots
#endif // OTS_CFF_TYPE2_CHARSTRING_H_
This diff is collapsed.
// 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.
#ifndef OTS_CMAP_H_
#define OTS_CMAP_H_
#include <vector>
#include "ots.h"
namespace ots {
struct OpenTypeCMAPSubtableRange {
uint32_t start_range;
uint32_t end_range;
uint32_t start_glyph_id;
};
struct OpenTypeCMAPSubtableVSRange {
uint32_t unicode_value;
uint8_t additional_count;
};
struct OpenTypeCMAPSubtableVSMapping {
uint32_t unicode_value;
uint16_t glyph_id;
};
struct OpenTypeCMAPSubtableVSRecord {
uint32_t var_selector;
uint32_t default_offset;
uint32_t non_default_offset;
std::vector<OpenTypeCMAPSubtableVSRange> ranges;
std::vector<OpenTypeCMAPSubtableVSMapping> mappings;
};
struct OpenTypeCMAP {
OpenTypeCMAP()
: subtable_0_3_4_data(NULL),
subtable_0_3_4_length(0),
subtable_0_5_14_length(0),
subtable_3_0_4_data(NULL),
subtable_3_0_4_length(0),
subtable_3_1_4_data(NULL),
subtable_3_1_4_length(0) {
}
// Platform 0, Encoding 3, Format 4, Unicode BMP table.
const uint8_t *subtable_0_3_4_data;
size_t subtable_0_3_4_length;
// Platform 0, Encoding 5, Format 14, Unicode Variation Sequence table.
size_t subtable_0_5_14_length;
std::vector<OpenTypeCMAPSubtableVSRecord> subtable_0_5_14;
// Platform 3, Encoding 0, Format 4, MS Symbol table.
const uint8_t *subtable_3_0_4_data;
size_t subtable_3_0_4_length;
// Platform 3, Encoding 1, Format 4, MS Unicode BMP table.
const uint8_t *subtable_3_1_4_data;
size_t subtable_3_1_4_length;
// Platform 3, Encoding 10, Format 12, MS Unicode UCS-4 table.
std::vector<OpenTypeCMAPSubtableRange> subtable_3_10_12;
// Platform 3, Encoding 10, Format 13, MS UCS-4 Fallback table.
std::vector<OpenTypeCMAPSubtableRange> subtable_3_10_13;
// Platform 1, Encoding 0, Format 0, Mac Roman table.
std::vector<uint8_t> subtable_1_0_0;
};
} // namespace ots
#endif
// 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 "cvt.h"
// cvt - Control Value Table
// http://www.microsoft.com/typography/otspec/cvt.htm
#define TABLE_NAME "cvt"
namespace ots {
bool ots_cvt_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
Buffer table(data, length);
OpenTypeCVT *cvt = new OpenTypeCVT;
file->cvt = cvt;
if (length >= 128 * 1024u) {
return OTS_FAILURE_MSG("Length (%d) > 120K"); // almost all cvt tables are less than 4k bytes.
}
if (length % 2 != 0) {
return OTS_FAILURE_MSG("Uneven cvt length (%d)", length);
}
if (!table.Skip(length)) {
return OTS_FAILURE_MSG("Length too high");
}
cvt->data = data;
cvt->length = length;
return true;
}
bool ots_cvt_should_serialise(OpenTypeFile *file) {
if (!file->glyf) {
return false; // this table is not for CFF fonts.
}
return file->cvt;
}
bool ots_cvt_serialise(OTSStream *out, OpenTypeFile *file) {
const OpenTypeCVT *cvt = file->cvt;
if (!out->Write(cvt->data, cvt->length)) {
return OTS_FAILURE_MSG("Failed to write CVT table");
}
return true;
}
void ots_cvt_free(OpenTypeFile *file) {
delete file->cvt;
}
} // namespace ots
#undef TABLE_NAME
// 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.
#ifndef OTS_CVT_H_
#define OTS_CVT_H_
#include "ots.h"
namespace ots {
struct OpenTypeCVT {
const uint8_t *data;
uint32_t length;
};
} // namespace ots
#endif // OTS_CVT_H_
// 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 "fpgm.h"
// fpgm - Font Program
// http://www.microsoft.com/typography/otspec/fpgm.htm
#define TABLE_NAME "fpgm"
namespace ots {
bool ots_fpgm_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
Buffer table(data, length);
OpenTypeFPGM *fpgm = new OpenTypeFPGM;
file->fpgm = fpgm;
if (length >= 128 * 1024u) {
return OTS_FAILURE_MSG("length (%ld) > 120", length); // almost all fpgm tables are less than 5k bytes.
}
if (!table.Skip(length)) {
return OTS_FAILURE_MSG("Bad fpgm length");
}
fpgm->data = data;
fpgm->length = length;
return true;
}
bool ots_fpgm_should_serialise(OpenTypeFile *file) {
if (!file->glyf) return false; // this table is not for CFF fonts.
return file->fpgm;
}
bool ots_fpgm_serialise(OTSStream *out, OpenTypeFile *file) {
const OpenTypeFPGM *fpgm = file->fpgm;
if (!out->Write(fpgm->data, fpgm->length)) {
return OTS_FAILURE_MSG("Failed to write fpgm");
}
return true;
}
void ots_fpgm_free(OpenTypeFile *file) {
delete file->fpgm;
}
} // namespace ots
#undef TABLE_NAME
// 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.
#ifndef OTS_FPGM_H_
#define OTS_FPGM_H_
#include "ots.h"
namespace ots {
struct OpenTypeFPGM {
const uint8_t *data;
uint32_t length;
};
} // namespace ots
#endif // OTS_FPGM_H_
// 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 "gasp.h"
// gasp - Grid-fitting And Scan-conversion Procedure
// http://www.microsoft.com/typography/otspec/gasp.htm
#define TABLE_NAME "gasp"
#define DROP_THIS_TABLE(...) \
do { \
OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__); \
OTS_FAILURE_MSG("Table discarded"); \
delete file->gasp; \
file->gasp = 0; \
} while (0)
namespace ots {
bool ots_gasp_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
Buffer table(data, length);
OpenTypeGASP *gasp = new OpenTypeGASP;
file->gasp = gasp;
uint16_t num_ranges = 0;
if (!table.ReadU16(&gasp->version) ||
!table.ReadU16(&num_ranges)) {
return OTS_FAILURE_MSG("Failed to read table header");
}
if (gasp->version > 1) {
// Lots of Linux fonts have bad version numbers...
DROP_THIS_TABLE("bad version: %u", gasp->version);
return true;
}
if (num_ranges == 0) {
DROP_THIS_TABLE("num_ranges is zero");
return true;
}
gasp->gasp_ranges.reserve(num_ranges);
for (unsigned i = 0; i < num_ranges; ++i) {
uint16_t max_ppem = 0;
uint16_t behavior = 0;
if (!table.ReadU16(&max_ppem) ||
!table.ReadU16(&behavior)) {
return OTS_FAILURE_MSG("Failed to read subrange %d", i);
}
if ((i > 0) && (gasp->gasp_ranges[i - 1].first >= max_ppem)) {
// The records in the gaspRange[] array must be sorted in order of
// increasing rangeMaxPPEM value.
DROP_THIS_TABLE("ranges are not sorted");
return true;
}
if ((i == num_ranges - 1u) && // never underflow.
(max_ppem != 0xffffu)) {
DROP_THIS_TABLE("The last record should be 0xFFFF as a sentinel value "
"for rangeMaxPPEM");
return true;
}
if (behavior >> 8) {
OTS_WARNING("undefined bits are used: %x", behavior);
// mask undefined bits.
behavior &= 0x000fu;
}
if (gasp->version == 0 && (behavior >> 2) != 0) {
OTS_WARNING("changed the version number to 1");
gasp->version = 1;
}
gasp->gasp_ranges.push_back(std::make_pair(max_ppem, behavior));
}
return true;
}
bool ots_gasp_should_serialise(OpenTypeFile *file) {
return file->gasp != NULL;
}
bool ots_gasp_serialise(OTSStream *out, OpenTypeFile *file) {
const OpenTypeGASP *gasp = file->gasp;
const uint16_t num_ranges = static_cast<uint16_t>(gasp->gasp_ranges.size());
if (num_ranges != gasp->gasp_ranges.size() ||
!out->WriteU16(gasp->version) ||
!out->WriteU16(num_ranges)) {
return OTS_FAILURE_MSG("failed to write gasp header");
}
for (uint16_t i = 0; i < num_ranges; ++i) {
if (!out->WriteU16(gasp->gasp_ranges[i].first) ||
!out->WriteU16(gasp->gasp_ranges[i].second)) {
return OTS_FAILURE_MSG("Failed to write gasp subtable %d", i);
}
}
return true;
}
void ots_gasp_free(OpenTypeFile *file) {
delete file->gasp;
}
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE
// 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.
#ifndef OTS_GASP_H_
#define OTS_GASP_H_
#include <new>
#include <utility>
#include <vector>
#include "ots.h"
namespace ots {
struct OpenTypeGASP {
uint16_t version;
// A array of (max PPEM, GASP behavior) pairs.
std::vector<std::pair<uint16_t, uint16_t> > gasp_ranges;
};
} // namespace ots
#endif // OTS_GASP_H_
This diff is collapsed.
// Copyright (c) 2011 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.
#ifndef OTS_GDEF_H_
#define OTS_GDEF_H_
#include "ots.h"
namespace ots {
struct OpenTypeGDEF {
OpenTypeGDEF()
: version_2(false),
has_glyph_class_def(false),
has_mark_attachment_class_def(false),
has_mark_glyph_sets_def(false),
num_mark_glyph_sets(0),
data(NULL),
length(0) {
}
bool version_2;
bool has_glyph_class_def;
bool has_mark_attachment_class_def;
bool has_mark_glyph_sets_def;
uint16_t num_mark_glyph_sets;
const uint8_t *data;
size_t length;
};
} // namespace ots
#endif
This diff is collapsed.
// 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.
#ifndef OTS_GLYF_H_
#define OTS_GLYF_H_
#include <new>
#include <utility>
#include <vector>
#include "ots.h"
namespace ots {
struct OpenTypeGLYF {
std::vector<std::pair<const uint8_t*, size_t> > iov;
};
} // namespace ots
#endif // OTS_GLYF_H_
This diff is collapsed.
// Copyright (c) 2011 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.
#ifndef OTS_GPOS_H_
#define OTS_GPOS_H_
#include "ots.h"
namespace ots {
struct OpenTypeGPOS {
OpenTypeGPOS()
: num_lookups(0),
data(NULL),
length(0) {
}
// Number of lookups in GPOS table
uint16_t num_lookups;
const uint8_t *data;
size_t length;
};
} // namespace ots
#endif
This diff is collapsed.
// Copyright (c) 2011 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.
#ifndef OTS_GSUB_H_
#define OTS_GSUB_H_
#include "ots.h"
namespace ots {
struct OpenTypeGSUB {
OpenTypeGSUB()
: num_lookups(0),
data(NULL),
length(0) {
}
// Number of lookups in GPSUB table
uint16_t num_lookups;
const uint8_t *data;
size_t length;
};
} // namespace ots
#endif // OTS_GSUB_H_
// 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 "hdmx.h"
#include "head.h"
#include "maxp.h"
// hdmx - Horizontal Device Metrics
// http://www.microsoft.com/typography/otspec/hdmx.htm
#define TABLE_NAME "hdmx"
#define DROP_THIS_TABLE(...) \
do { \
OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__); \
OTS_FAILURE_MSG("Table discarded"); \
delete file->hdmx; \
file->hdmx = 0; \
} while (0)
namespace ots {
bool ots_hdmx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
Buffer table(data, length);
file->hdmx = new OpenTypeHDMX;
OpenTypeHDMX * const hdmx = file->hdmx;
if (!file->head || !file->maxp) {
return OTS_FAILURE_MSG("Missing maxp or head tables in font, needed by hdmx");
}
if ((file->head->flags & 0x14) == 0) {
// http://www.microsoft.com/typography/otspec/recom.htm
DROP_THIS_TABLE("the table should not be present when bit 2 and 4 of the "
"head->flags are not set");
return true;
}
int16_t num_recs;
if (!table.ReadU16(&hdmx->version) ||
!table.ReadS16(&num_recs) ||
!table.ReadS32(&hdmx->size_device_record)) {
return OTS_FAILURE_MSG("Failed to read hdmx header");
}
if (hdmx->version != 0) {
DROP_THIS_TABLE("bad version: %u", hdmx->version);
return true;
}
if (num_recs <= 0) {
DROP_THIS_TABLE("bad num_recs: %d", num_recs);
return true;
}
const int32_t actual_size_device_record = file->maxp->num_glyphs + 2;
if (hdmx->size_device_record < actual_size_device_record) {
DROP_THIS_TABLE("bad hdmx->size_device_record: %d", hdmx->size_device_record);
return true;
}
hdmx->pad_len = hdmx->size_device_record - actual_size_device_record;
if (hdmx->pad_len > 3) {
return OTS_FAILURE_MSG("Bad padding %d", hdmx->pad_len);
}
uint8_t last_pixel_size = 0;
hdmx->records.reserve(num_recs);
for (int i = 0; i < num_recs; ++i) {
OpenTypeHDMXDeviceRecord rec;
if (!table.ReadU8(&rec.pixel_size) ||
!table.ReadU8(&rec.max_width)) {
return OTS_FAILURE_MSG("Failed to read hdmx record %d", i);
}
if ((i != 0) &&
(rec.pixel_size <= last_pixel_size)) {
DROP_THIS_TABLE("records are not sorted");
return true;
}
last_pixel_size = rec.pixel_size;
rec.widths.reserve(file->maxp->num_glyphs);
for (unsigned j = 0; j < file->maxp->num_glyphs; ++j) {
uint8_t width;
if (!table.ReadU8(&width)) {
return OTS_FAILURE_MSG("Failed to read glyph width %d in record %d", j, i);
}
rec.widths.push_back(width);
}
if ((hdmx->pad_len > 0) &&
!table.Skip(hdmx->pad_len)) {
return OTS_FAILURE_MSG("Failed to skip padding %d", hdmx->pad_len);
}
hdmx->records.push_back(rec);
}
return true;
}
bool ots_hdmx_should_serialise(OpenTypeFile *file) {
if (!file->hdmx) return false;
if (!file->glyf) return false; // this table is not for CFF fonts.
return true;
}
bool ots_hdmx_serialise(OTSStream *out, OpenTypeFile *file) {
OpenTypeHDMX * const hdmx = file->hdmx;
const int16_t num_recs = static_cast<int16_t>(hdmx->records.size());
if (hdmx->records.size() >
static_cast<size_t>(std::numeric_limits<int16_t>::max()) ||
!out->WriteU16(hdmx->version) ||
!out->WriteS16(num_recs) ||
!out->WriteS32(hdmx->size_device_record)) {
return OTS_FAILURE_MSG("Failed to write hdmx header");
}
for (int16_t i = 0; i < num_recs; ++i) {
const OpenTypeHDMXDeviceRecord& rec = hdmx->records[i];
if (!out->Write(&rec.pixel_size, 1) ||
!out->Write(&rec.max_width, 1) ||
!out->Write(&rec.widths[0], rec.widths.size())) {
return OTS_FAILURE_MSG("Failed to write hdmx record %d", i);
}
if ((hdmx->pad_len > 0) &&
!out->Write((const uint8_t *)"\x00\x00\x00", hdmx->pad_len)) {
return OTS_FAILURE_MSG("Failed to write hdmx padding of length %d", hdmx->pad_len);
}
}
return true;
}
void ots_hdmx_free(OpenTypeFile *file) {
delete file->hdmx;
}
} // namespace ots
#undef TABLE_NAME
#undef DROP_THIS_TABLE
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment