gfx/ots/src/hdmx.cc

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #include "hdmx.h"
michael@0 6 #include "head.h"
michael@0 7 #include "maxp.h"
michael@0 8
michael@0 9 // hdmx - Horizontal Device Metrics
michael@0 10 // http://www.microsoft.com/typography/otspec/hdmx.htm
michael@0 11
michael@0 12 #define TABLE_NAME "hdmx"
michael@0 13
michael@0 14 #define DROP_THIS_TABLE \
michael@0 15 do { \
michael@0 16 delete file->hdmx; \
michael@0 17 file->hdmx = 0; \
michael@0 18 OTS_FAILURE_MSG("Table discarded"); \
michael@0 19 } while (0)
michael@0 20
michael@0 21 namespace ots {
michael@0 22
michael@0 23 bool ots_hdmx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
michael@0 24 Buffer table(data, length);
michael@0 25 file->hdmx = new OpenTypeHDMX;
michael@0 26 OpenTypeHDMX * const hdmx = file->hdmx;
michael@0 27
michael@0 28 if (!file->head || !file->maxp) {
michael@0 29 return OTS_FAILURE_MSG("Missing maxp or head tables in font, needed by hdmx");
michael@0 30 }
michael@0 31
michael@0 32 if ((file->head->flags & 0x14) == 0) {
michael@0 33 // http://www.microsoft.com/typography/otspec/recom.htm
michael@0 34 OTS_WARNING("the table should not be present when bit 2 and 4 of the "
michael@0 35 "head->flags are not set");
michael@0 36 DROP_THIS_TABLE;
michael@0 37 return true;
michael@0 38 }
michael@0 39
michael@0 40 int16_t num_recs;
michael@0 41 if (!table.ReadU16(&hdmx->version) ||
michael@0 42 !table.ReadS16(&num_recs) ||
michael@0 43 !table.ReadS32(&hdmx->size_device_record)) {
michael@0 44 return OTS_FAILURE_MSG("Failed to read hdmx header");
michael@0 45 }
michael@0 46 if (hdmx->version != 0) {
michael@0 47 OTS_WARNING("bad version: %u", hdmx->version);
michael@0 48 DROP_THIS_TABLE;
michael@0 49 return true;
michael@0 50 }
michael@0 51 if (num_recs <= 0) {
michael@0 52 OTS_WARNING("bad num_recs: %d", num_recs);
michael@0 53 DROP_THIS_TABLE;
michael@0 54 return true;
michael@0 55 }
michael@0 56 const int32_t actual_size_device_record = file->maxp->num_glyphs + 2;
michael@0 57 if (hdmx->size_device_record < actual_size_device_record) {
michael@0 58 OTS_WARNING("bad hdmx->size_device_record: %d", hdmx->size_device_record);
michael@0 59 DROP_THIS_TABLE;
michael@0 60 return true;
michael@0 61 }
michael@0 62
michael@0 63 hdmx->pad_len = hdmx->size_device_record - actual_size_device_record;
michael@0 64 if (hdmx->pad_len > 3) {
michael@0 65 return OTS_FAILURE_MSG("Bad padding %d", hdmx->pad_len);
michael@0 66 }
michael@0 67
michael@0 68 uint8_t last_pixel_size = 0;
michael@0 69 hdmx->records.reserve(num_recs);
michael@0 70 for (int i = 0; i < num_recs; ++i) {
michael@0 71 OpenTypeHDMXDeviceRecord rec;
michael@0 72
michael@0 73 if (!table.ReadU8(&rec.pixel_size) ||
michael@0 74 !table.ReadU8(&rec.max_width)) {
michael@0 75 return OTS_FAILURE_MSG("Failed to read hdmx record %d", i);
michael@0 76 }
michael@0 77 if ((i != 0) &&
michael@0 78 (rec.pixel_size <= last_pixel_size)) {
michael@0 79 OTS_WARNING("records are not sorted");
michael@0 80 DROP_THIS_TABLE;
michael@0 81 return true;
michael@0 82 }
michael@0 83 last_pixel_size = rec.pixel_size;
michael@0 84
michael@0 85 rec.widths.reserve(file->maxp->num_glyphs);
michael@0 86 for (unsigned j = 0; j < file->maxp->num_glyphs; ++j) {
michael@0 87 uint8_t width;
michael@0 88 if (!table.ReadU8(&width)) {
michael@0 89 return OTS_FAILURE_MSG("Failed to read glyph width %d in record %d", j, i);
michael@0 90 }
michael@0 91 rec.widths.push_back(width);
michael@0 92 }
michael@0 93
michael@0 94 if ((hdmx->pad_len > 0) &&
michael@0 95 !table.Skip(hdmx->pad_len)) {
michael@0 96 return OTS_FAILURE_MSG("Failed to skip padding %d", hdmx->pad_len);
michael@0 97 }
michael@0 98
michael@0 99 hdmx->records.push_back(rec);
michael@0 100 }
michael@0 101
michael@0 102 return true;
michael@0 103 }
michael@0 104
michael@0 105 bool ots_hdmx_should_serialise(OpenTypeFile *file) {
michael@0 106 if (!file->hdmx) return false;
michael@0 107 if (!file->glyf) return false; // this table is not for CFF fonts.
michael@0 108 return true;
michael@0 109 }
michael@0 110
michael@0 111 bool ots_hdmx_serialise(OTSStream *out, OpenTypeFile *file) {
michael@0 112 OpenTypeHDMX * const hdmx = file->hdmx;
michael@0 113
michael@0 114 if (!out->WriteU16(hdmx->version) ||
michael@0 115 !out->WriteS16(hdmx->records.size()) ||
michael@0 116 !out->WriteS32(hdmx->size_device_record)) {
michael@0 117 return OTS_FAILURE_MSG("Failed to write hdmx header");
michael@0 118 }
michael@0 119
michael@0 120 for (unsigned i = 0; i < hdmx->records.size(); ++i) {
michael@0 121 const OpenTypeHDMXDeviceRecord& rec = hdmx->records[i];
michael@0 122 if (!out->Write(&rec.pixel_size, 1) ||
michael@0 123 !out->Write(&rec.max_width, 1) ||
michael@0 124 !out->Write(&rec.widths[0], rec.widths.size())) {
michael@0 125 return OTS_FAILURE_MSG("Failed to write hdmx record %d", i);
michael@0 126 }
michael@0 127 if ((hdmx->pad_len > 0) &&
michael@0 128 !out->Write((const uint8_t *)"\x00\x00\x00", hdmx->pad_len)) {
michael@0 129 return OTS_FAILURE_MSG("Failed to write hdmx padding of length %d", hdmx->pad_len);
michael@0 130 }
michael@0 131 }
michael@0 132
michael@0 133 return true;
michael@0 134 }
michael@0 135
michael@0 136 void ots_hdmx_free(OpenTypeFile *file) {
michael@0 137 delete file->hdmx;
michael@0 138 }
michael@0 139
michael@0 140 } // namespace ots

mercurial