From 5e83da96d55d04feb9af611eceaf3d734b1dc45e Mon Sep 17 00:00:00 2001 From: Edwin Flores Date: Thu, 6 Sep 2012 16:57:02 +1200 Subject: [PATCH] Bug 719286 - Add OTS support for OpenType SVG table r=jfkthame --- gfx/ots/src/Makefile.in | 1 + gfx/ots/src/ots.cc | 3 + gfx/ots/src/ots.h | 3 +- gfx/ots/src/svg.cc | 125 ++++++++++++++++++++++++++++++++++++++++ gfx/ots/src/svg.h | 21 +++++++ 5 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 gfx/ots/src/svg.cc create mode 100644 gfx/ots/src/svg.h diff --git a/gfx/ots/src/Makefile.in b/gfx/ots/src/Makefile.in index 1f30cef495ac..bc05a286cb1a 100644 --- a/gfx/ots/src/Makefile.in +++ b/gfx/ots/src/Makefile.in @@ -76,6 +76,7 @@ CPPSRCS = \ gpos.cc \ gsub.cc \ graphite.cc \ + svg.cc \ $(NULL) EXPORTS = \ diff --git a/gfx/ots/src/ots.cc b/gfx/ots/src/ots.cc index 25b9ed267332..ccce1248edca 100644 --- a/gfx/ots/src/ots.cc +++ b/gfx/ots/src/ots.cc @@ -172,6 +172,9 @@ const struct { ots::ots_glat_should_serialise, ots::ots_glat_free, false }, { "Feat", ots::ots_feat_parse, ots::ots_feat_serialise, ots::ots_feat_should_serialise, ots::ots_feat_free, false }, + // SVG glyph table + { "SVG ", ots::ots_svg_parse, ots::ots_svg_serialise, + ots::ots_svg_should_serialise, ots::ots_svg_free, false}, // TODO(bashi): Support mort, base, and jstf tables. { 0, NULL, NULL, NULL, NULL, false }, }; diff --git a/gfx/ots/src/ots.h b/gfx/ots/src/ots.h index 8fdadab54d26..d09d57790532 100644 --- a/gfx/ots/src/ots.h +++ b/gfx/ots/src/ots.h @@ -222,7 +222,8 @@ class Buffer { F(sill, SILL) \ F(glat, GLAT) \ F(gloc, GLOC) \ - F(feat, FEAT) + F(feat, FEAT) \ + F(svg, SVG) #define F(name, capname) struct OpenType##capname; FOR_EACH_TABLE_TYPE diff --git a/gfx/ots/src/svg.cc b/gfx/ots/src/svg.cc new file mode 100644 index 000000000000..cd0d460f90aa --- /dev/null +++ b/gfx/ots/src/svg.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2012 Mozilla Foundation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ots.h" + +#include "svg.h" + +#define NONFATAL_FAILURE(msg) \ + do { \ + OTS_WARNING(msg); \ + delete file->svg; file->svg = 0; \ + return true; \ + } while (0) + +namespace ots { + +bool ots_svg_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { + Buffer table(data, length); + + OpenTypeSVG *svg = new OpenTypeSVG; + file->svg = svg; + + std::map doc_locations; + typedef std::map::iterator lociter_t; + + uint16_t version; + uint16_t index_length; + if (!table.ReadU16(&version) || + !table.ReadU16(&index_length)) { + NONFATAL_FAILURE("Couldn't read SVG table header"); + } + + if (version != 1) { + NONFATAL_FAILURE("Unknown SVG table version"); + } + + uint32_t max_address = 0; + uint32_t total_docs_length = 0; + + uint16_t start_glyph; + uint16_t end_glyph; + uint32_t doc_offset; + uint32_t doc_length; + uint16_t last_end_glyph = 0; + + for (uint16_t i = 0; i < index_length; i++) { + if (!table.ReadU16(&start_glyph) || + !table.ReadU16(&end_glyph) || + !table.ReadU32(&doc_offset) || + !table.ReadU32(&doc_length)) { + NONFATAL_FAILURE("Couldn't read SVG table index"); + } + + if (end_glyph < start_glyph) { + NONFATAL_FAILURE("Bad SVG table index range"); + } + + if (last_end_glyph && start_glyph < last_end_glyph) { + NONFATAL_FAILURE("SVG table index range is not sorted"); + } + + if (doc_locations.find(doc_offset) != doc_locations.end()) { + if (doc_locations[doc_offset] != doc_length) { + NONFATAL_FAILURE("SVG table contains overlapping document range"); + } + } else { + doc_locations[doc_offset] = doc_length; + total_docs_length += doc_length; + if (doc_offset + doc_length > max_address) { + max_address = doc_offset + doc_length; + } + } + + if (doc_offset > 1024 * 1024 * 1024 || + doc_length > 1024 * 1024 * 1024 || + total_docs_length > 1024 * 1024 * 1024) { + NONFATAL_FAILURE("Bad SVG document length"); + } + + last_end_glyph = end_glyph; + } + + uint32_t last_end = 4 + 12 * index_length; + for (lociter_t iter = doc_locations.begin(); + iter != doc_locations.end(); ++iter) { + if (iter->first != last_end) { + NONFATAL_FAILURE("SVG table contains overlapping document range"); + } + last_end = iter->first + iter->second; + } + + if (max_address != length) { + NONFATAL_FAILURE("Bad SVG document length"); + } + + if (!table.Skip(total_docs_length)) { + NONFATAL_FAILURE("SVG table is too short"); + } + + svg->data = data; + svg->length = length; + + return true; +} + +bool ots_svg_serialise(OTSStream *out, OpenTypeFile *file) { + OpenTypeSVG *svg = file->svg; + + if (!out->Write(svg->data, svg->length)) { + return OTS_FAILURE(); + } + + return true; +} + +bool ots_svg_should_serialise(OpenTypeFile *file) { + return file->svg; +} + +void ots_svg_free(OpenTypeFile *file) { + delete file->svg; +} + +} diff --git a/gfx/ots/src/svg.h b/gfx/ots/src/svg.h new file mode 100644 index 000000000000..195972b5e340 --- /dev/null +++ b/gfx/ots/src/svg.h @@ -0,0 +1,21 @@ +// Copyright (c) 2012 Mozilla Foundation. 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_SVG_H +#define OTS_SVG_H + +#include + +#include "ots.h" + +namespace ots { + +struct OpenTypeSVG { + const uint8_t *data; + size_t length; +}; + +} + +#endif