summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/otfcmap.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/otfcmap.cc')
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/otfcmap.cc462
1 files changed, 0 insertions, 462 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/otfcmap.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/otfcmap.cc
deleted file mode 100644
index b91970c9600..00000000000
--- a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/otfcmap.cc
+++ /dev/null
@@ -1,462 +0,0 @@
-// -*- related-file-name: "../include/efont/otfcmap.hh" -*-
-
-/* otfcmap.{cc,hh} -- OpenType cmap table
- *
- * Copyright (c) 2002-2019 Eddie Kohler
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version. This program is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <efont/otfcmap.hh>
-#include <lcdf/error.hh>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <efont/otfdata.hh> // for ntohl()
-
-#define USHORT_AT(d) (Data::u16_aligned(d))
-#define SHORT_AT(d) (Data::s16_aligned(d))
-#define ULONG_AT(d) (Data::u32_aligned(d))
-#define ULONG_AT2(d) (Data::u32_aligned16(d))
-
-namespace Efont { namespace OpenType {
-
-Cmap::Cmap(const String &s, ErrorHandler *errh)
- : _str(s)
-{
- _str.align(4);
- _error = parse_header(errh ? errh : ErrorHandler::silent_handler());
-}
-
-int
-Cmap::parse_header(ErrorHandler *errh)
-{
- // HEADER FORMAT:
- // USHORT version
- // USHORT numTables
- int len = _str.length();
- const uint8_t *data = _str.udata();
- if (HEADER_SIZE > len)
- return errh->error("OTF cmap too small"), -EFAULT;
- if (!(data[0] == '\000' && data[1] == '\000'))
- return errh->error("bad cmap version number"), -ERANGE;
- _ntables = USHORT_AT(data + 2);
- if (_ntables == 0)
- return errh->error("OTF cmap contains no tables"), -EINVAL;
- if (HEADER_SIZE + ENCODING_SIZE * _ntables > len)
- return errh->error("cmap directory out of range"), -EFAULT;
-
- // ENCODING ENTRY FORMAT:
- // USHORT platformID
- // USHORT encodingID
- // ULONG offset
- int last_platform = -1;
- int last_encoding = -1;
- int last_language = -1;
- _first_unicode_table = -1;
- for (int i = 0; i < _ntables; i++) {
- int loc = HEADER_SIZE + ENCODING_SIZE * i;
- int platform = USHORT_AT(data + loc);
- int encoding = USHORT_AT(data + loc + 2);
- uint32_t offset = ULONG_AT(data + loc + 4);
- if (offset + 8 > (uint32_t) len) {
- length_error:
- return errh->error("encoding data for entry %d out of range", i);
- }
- int format = USHORT_AT(data + offset);
- int language;
- if (format == F_BYTE || format == F_HIBYTE || format == F_SEGMENTED
- || format == F_TRIMMED) {
- if (USHORT_AT(data + offset + 2) < 6)
- goto length_error;
- language = USHORT_AT(data + offset + 4);
- } else if (format == F_HIBYTE32 || format == F_TRIMMED32
- || format == F_SEGMENTED32) {
- if (offset + 12 > (uint32_t) len || ULONG_AT2(data + offset + 4) < 12)
- goto length_error;
- language = ULONG_AT2(data + offset + 8);
- } else
- continue;
- if (!(platform > last_platform
- || (platform == last_platform
- && (encoding > last_encoding
- || (encoding == last_encoding
- && language > last_language)))))
- errh->warning("unsorted cmap encoding records at entry %d (%d,%d,%d follows %d,%d,%d)", i, platform, encoding, language, last_platform, last_encoding, last_language);
- if ((platform == 0 || (platform == 3 && encoding == 1))
- && _first_unicode_table < 0)
- _first_unicode_table = i;
- last_platform = platform, last_encoding = encoding, last_language = language;
- }
-
- _table_error.assign(_ntables, -2);
- return 0;
-}
-
-int
-Cmap::first_table(int platform, int encoding) const
-{
- if (error() < 0)
- return -1;
- const uint8_t *data = _str.udata();
- data += HEADER_SIZE;
- for (int i = 0; i < _ntables; i++, data += ENCODING_SIZE) {
- int p = USHORT_AT(data), e = USHORT_AT(data + 2);
- if (platform == p && (encoding < 0 || encoding == e))
- return i;
- }
- return -1;
-}
-
-int
-Cmap::check_table(int t, ErrorHandler *errh) const
-{
- if (!errh)
- errh = ErrorHandler::silent_handler();
- if (t == USE_FIRST_UNICODE_TABLE && _first_unicode_table == -1) {
- errh->warning("font appears not to support Unicode");
- _first_unicode_table = 0;
- }
- if (t == USE_FIRST_UNICODE_TABLE)
- t = _first_unicode_table;
- if (_error < 0 || t < 0 || t >= _ntables)
- return errh->error("no such table");
- if (_table_error[t] != -2)
- return _table_error[t];
- _table_error[t] = -1;
-
- const uint8_t *data = table_data(t);
- uint32_t left = _str.uend() - data;
- int format = USHORT_AT(data);
- uint32_t length = 0; // value not used
-
- switch (format) {
-
- case F_BYTE:
- if (left < 4
- || (length = USHORT_AT(data + 2)) > left
- || length != 259)
- return errh->error("bad table %d length (format %d)", t, format);
- break;
-
- case F_HIBYTE:
- if (left < 4
- || (length = USHORT_AT(data + 2)) > left
- || length < 524)
- return errh->error("bad table %d length (format %d)", t, format);
- for (int hi_byte = 0; hi_byte < 256; hi_byte++)
- if (uint32_t subh_key = USHORT_AT(data + 6 + 2 * hi_byte)) {
- if ((subh_key & 7) || HIBYTE_SUBHEADERS + subh_key + 8 > length)
- return errh->error("bad table %d subheader %d offset (format 2)", t, hi_byte);
- const uint8_t *subh = data + HIBYTE_SUBHEADERS + subh_key;
- int firstCode = USHORT_AT(subh);
- int entryCount = USHORT_AT(subh + 2);
- int idRangeOffset = USHORT_AT(subh + 6);
- if (firstCode + entryCount > 256 || entryCount == 0)
- return errh->error("bad table %d subheader %d contents (format 2)", t, hi_byte);
- if ((HIBYTE_SUBHEADERS + subh_key + 6) // pos[idRangeOffset]
- + idRangeOffset + entryCount * 2 > length)
- return errh->error("bad table %d subheader %d length (format 2)", t, hi_byte);
- }
- break;
-
- case F_SEGMENTED: {
- if (left < 4
- || (length = USHORT_AT(data + 2)) > left
- || length < 16)
- return errh->error("bad table %d length (format %d)", t, format);
- int segCountX2 = USHORT_AT(data + 6);
- int searchRange = USHORT_AT(data + 8);
- int entrySelector = USHORT_AT(data + 10);
- int rangeShift = USHORT_AT(data + 12);
- if ((segCountX2 & 1)
- || segCountX2 == 0
- || (searchRange & (searchRange - 1)) /* not a power of 2? */
- || searchRange <= segCountX2/2
- || (searchRange>>1) > segCountX2/2
- || 1 << (entrySelector + 1) != searchRange
- || rangeShift != segCountX2 - searchRange)
- return errh->error("bad table %d segment counts (format %d)", format);
- uint32_t segCount = segCountX2 >> 1;
- if (length < 16 + 8 * segCount)
- return errh->error("bad table %d length (format %d, length %u, need %u)", t, format, length, 16 + 8 * segCount);
- const uint8_t *endCodes = data + 14;
- const uint8_t *startCodes = endCodes + 2 + segCountX2;
- const uint8_t *idDeltas = startCodes + segCountX2;
- const uint8_t *idRangeOffsets = idDeltas + segCountX2;
- uint32_t idRangeOffsetsPos = idRangeOffsets - data;
- int last_end = 0;
- for (int i = 0; i < segCountX2; i += 2) {
- int endCode = USHORT_AT(endCodes + i);
- int startCode = USHORT_AT(startCodes + i);
- /* int idDelta = SHORT_AT(idDeltas + i); // not needed */
- int idRangeOffset = USHORT_AT(idRangeOffsets + i);
- if (endCode < startCode || startCode < last_end)
- return errh->error("bad table %d overlapping range %d (format %d)", t, i/2, format);
- if (idRangeOffset
- && idRangeOffset != 65535
- && idRangeOffsetsPos + i + idRangeOffset + (endCode - startCode)*2 + 2 > length)
- return errh->error("bad table %d range %d length (format %d, range %d-%d, idRangeOffset %d, length %u)", t, i/2, format, startCode, endCode, idRangeOffset, length);
- last_end = endCode + 1;
- }
- if (USHORT_AT(endCodes + segCountX2 - 2) != 0xFFFF)
- return errh->error("bad table %d incorrect final endCode (format 4)", t);
- break;
- }
-
- case F_TRIMMED: {
- if (left < 4
- || (length = USHORT_AT(data + 2)) > left
- || length < 10)
- return errh->error("bad table %d length (format %d)", t, format);
- uint32_t entryCount = USHORT_AT(data + 8);
- if (10 + entryCount * 2 > length)
- return errh->error("bad table %d length (format %d)", t, format);
- break;
- }
-
- case F_SEGMENTED32: {
- if (left < 8
- || (length = ULONG_AT(data + 4)) > left
- || length < 16)
- return errh->error("bad table %d length (format %d)", t, format);
- uint32_t nGroups = ULONG_AT(data + 16);
- if ((length - 16) / 12 < nGroups)
- return errh->error("bad table %d length (format %d)", t, format);
- uint32_t last_post_end = 0;
- data += 16;
- for (uint32_t i = 0; i < nGroups; i++, data += 12) {
- uint32_t startCharCode = ULONG_AT(data);
- uint32_t endCharCode = ULONG_AT(data + 4);
- if (startCharCode < last_post_end || endCharCode < startCharCode)
- return errh->error("bad table %d overlapping range %d (format %d)", t, i, format);
- last_post_end = endCharCode + 1;
- }
- break;
- }
-
- case F_HIBYTE32:
- case F_TRIMMED32:
- default:
- return errh->error("bad table %d unsupported format %d", t, format);
-
- }
-
- _table_error[t] = t;
- return t;
-}
-
-Glyph
-Cmap::map_table(int t, uint32_t uni, ErrorHandler *errh) const
-{
- if ((t = check_table(t, errh)) < 0)
- return 0;
-
- const uint8_t *data = table_data(t);
- switch (USHORT_AT(data)) {
-
- case F_BYTE:
- if (uni < 256)
- return data[6 + uni];
- else
- return 0;
-
- case F_HIBYTE: {
- if (uni >= 65536)
- return 0;
- int hi_byte = (uni >> 8) & 255;
- int subh = USHORT_AT(data + 6 + hi_byte * 2);
- if (subh == 0 && hi_byte) // XXX?
- return 0;
- data += 524 + subh;
- int firstCode = USHORT_AT(data);
- int entryCount = USHORT_AT(data + 2);
- int idDelta = SHORT_AT(data + 4);
- int idRangeOffset = USHORT_AT(data + 6);
- int lo_byte = uni & 255;
- if (lo_byte < firstCode || lo_byte >= firstCode + entryCount)
- return 0;
- int answer = USHORT_AT(data + 6 + idRangeOffset + (lo_byte - firstCode) * 2);
- if (answer == 0)
- return 0;
- return (answer + idDelta) & 65535;
- }
-
- case F_SEGMENTED: {
- if (uni >= 65536)
- return 0;
- int segCount = USHORT_AT(data + 6) >> 1;
- const uint8_t *endCounts = data + 14;
- const uint8_t *startCounts = endCounts + (segCount << 1) + 2;
- const uint8_t *idDeltas = startCounts + (segCount << 1);
- const uint8_t *idRangeOffsets = idDeltas + (segCount << 1);
- int l = 0, r = segCount;
- while (l < r) {
- int m = l + (r - l) / 2;
- uint32_t endCount = USHORT_AT(endCounts + (m << 1));
- uint32_t startCount = USHORT_AT(startCounts + (m << 1));
- if (uni < startCount)
- r = m;
- else if (uni <= endCount) {
- int idDelta = SHORT_AT(idDeltas + (m << 1));
- int idRangeOffset = USHORT_AT(idRangeOffsets + (m << 1));
- if (idRangeOffset == 0)
- return (idDelta + uni) & 65535;
- else if (idRangeOffset == 65535)
- return 0;
- int g = USHORT_AT(idRangeOffsets + (m << 1) + idRangeOffset + ((uni - startCount) << 1));
- if (g == 0)
- return 0;
- return (idDelta + g) & 65535;
- } else
- l = m + 1;
- }
- return 0;
- }
-
- case F_TRIMMED: {
- uint32_t firstCode = USHORT_AT(data + 6);
- uint32_t entryCount = USHORT_AT(data + 8);
- if (uni < firstCode || uni >= firstCode + entryCount)
- return 0;
- return USHORT_AT(data + 10 + ((uni - firstCode) << 1));
- }
-
- case F_SEGMENTED32: {
- uint32_t nGroups = ULONG_AT2(data + 12);
- uint32_t l = 0, r = nGroups;
- const uint8_t *groups = data + 16;
- while (l < r) {
- uint32_t m = l + (r - l) / 2;
- uint32_t startCharCode = ULONG_AT2(groups + m * 12);
- uint32_t endCharCode = ULONG_AT2(groups + m * 12 + 4);
- if (uni < startCharCode)
- r = m;
- else if (uni <= endCharCode)
- return ULONG_AT2(groups + m * 12 + 8) + uni - startCharCode;
- else
- l = m + 1;
- }
- return 0;
- }
-
- default:
- return 0;
-
- }
-}
-
-void
-Cmap::dump_table(int t, Vector<std::pair<uint32_t, Glyph> > &ugp, ErrorHandler *errh) const
-{
- if ((t = check_table(t, errh)) < 0)
- return;
-
- const uint8_t *data = table_data(t);
- switch (USHORT_AT(data)) {
-
- case F_BYTE:
- for (uint32_t u = 0; u < 256; ++u)
- if (int g = data[6 + u])
- ugp.push_back(std::make_pair(u, g));
- break;
-
- case F_HIBYTE:
- assert(USHORT_AT(data + 6) == 0);
- for (int hi_byte = 0; hi_byte < 256; hi_byte++) {
- int subh = USHORT_AT(data + 6 + hi_byte * 4);
- if (subh == 0 && hi_byte > 0)
- continue;
- const uint8_t *tdata = data + 524 + subh;
- int firstCode = USHORT_AT(tdata);
- int entryCount = USHORT_AT(tdata + 2);
- int idDelta = SHORT_AT(tdata + 4);
- int idRangeOffset = USHORT_AT(tdata + 6);
- const uint8_t *gdata = tdata + 6 + idRangeOffset;
- for (int i = 0; i < entryCount; i++)
- if (Glyph g = USHORT_AT(gdata + (i << 1))) {
- g = (idDelta + g) & 65535;
- uint32_t u = (hi_byte << 8) + firstCode + i;
- ugp.push_back(std::make_pair(u, g));
- }
- }
- break;
-
- case F_SEGMENTED: {
- int segCountX2 = USHORT_AT(data + 6);
- const uint8_t *endCounts = data + 14;
- const uint8_t *startCounts = endCounts + segCountX2 + 2;
- const uint8_t *idDeltas = startCounts + segCountX2;
- const uint8_t *idRangeOffsets = idDeltas + segCountX2;
- for (int i = 0; i < segCountX2; i += 2) {
- uint32_t endCount = USHORT_AT(endCounts + i);
- uint32_t startCount = USHORT_AT(startCounts + i);
- int idDelta = SHORT_AT(idDeltas + i);
- int idRangeOffset = USHORT_AT(idRangeOffsets + i);
- if (idRangeOffset == 0) {
- for (uint32_t u = startCount; u <= endCount; ++u) {
- Glyph g = (u + idDelta) & 65535;
- ugp.push_back(std::make_pair(u, g));
- }
- } else {
- const uint8_t *gdata = idRangeOffsets + i + idRangeOffset;
- for (uint32_t u = startCount; u <= endCount; ++u, gdata += 2)
- if (Glyph g = USHORT_AT(gdata)) {
- g = (g + idDelta) & 65535;
- ugp.push_back(std::make_pair(u, g));
- }
- }
- }
- break;
- }
-
- case F_TRIMMED: {
- uint32_t firstCode = USHORT_AT(data + 6);
- int entryCount = USHORT_AT(data + 8);
- for (int i = 0; i < entryCount; i++)
- if (Glyph g = USHORT_AT(data + 10 + (i << 1)))
- ugp.push_back(std::make_pair(firstCode + i, g));
- break;
- }
-
- case F_SEGMENTED32: {
- uint32_t nGroups = ULONG_AT2(data + 12);
- const uint8_t *groups = data + 16;
- for (uint32_t i = 0; i < nGroups; i++, groups += 12) {
- uint32_t startCharCode = ULONG_AT2(groups);
- uint32_t nCharCodes = ULONG_AT2(groups + 4) - startCharCode;
- Glyph startGlyphID = ULONG_AT2(groups + 8);
- for (uint32_t i = 0; i <= nCharCodes; i++)
- ugp.push_back(std::make_pair(startCharCode + i, startGlyphID + i));
- }
- break;
- }
-
- default:
- break;
-
- }
-}
-
-int
-Cmap::map_uni(const Vector<uint32_t> &vin, Vector<Glyph> &vout) const
-{
- int t;
- if ((t = check_table(USE_FIRST_UNICODE_TABLE)) < 0)
- return -1;
- vout.resize(vin.size(), 0);
- for (int i = 0; i < vin.size(); i++)
- vout[i] = map_table(t, vin[i]);
- return 0;
-}
-
-}}