summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mfluadir/otfcc/src/otfccbuild.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/mfluadir/otfcc/src/otfccbuild.c')
-rw-r--r--Build/source/texk/web2c/mfluadir/otfcc/src/otfccbuild.c326
1 files changed, 326 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mfluadir/otfcc/src/otfccbuild.c b/Build/source/texk/web2c/mfluadir/otfcc/src/otfccbuild.c
new file mode 100644
index 00000000000..30c401a73a4
--- /dev/null
+++ b/Build/source/texk/web2c/mfluadir/otfcc/src/otfccbuild.c
@@ -0,0 +1,326 @@
+#include "otfcc/sfnt.h"
+#include "otfcc/font.h"
+#include "otfcc/sfnt-builder.h"
+
+#include "aliases.h"
+#include "platform.h"
+#include "stopwatch.h"
+
+#ifndef MAIN_VER
+#define MAIN_VER 0
+#endif
+#ifndef SECONDARY_VER
+#define SECONDARY_VER 0
+#endif
+#ifndef PATCH_VER
+#define PATCH_VER 0
+#endif
+
+static void printInfo() {
+ fprintf(stdout, "This is Polymorphic otfccbuild, version %d.%d.%d.\n", MAIN_VER, SECONDARY_VER,
+ PATCH_VER);
+}
+static void printHelp() {
+ fprintf(stdout,
+ "\n"
+ "Usage : otfccbuild [OPTIONS] [input.json] -o output.[ttf|otf]\n\n"
+ " input.json : Path to input file. When absent the input will be\n"
+ " read from the STDIN.\n\n"
+ " -h, --help : Display this help message and exit.\n"
+ " -v, --version : Display version information and exit.\n"
+ " -o <file> : Set output file path to <file>.\n"
+ " -s, --dummy-dsig : Include an empty DSIG table in the font. For some\n"
+ " Microsoft applications, DSIG is required to enable\n"
+ " OpenType features.\n"
+ " -O<n> : Specify the level for optimization.\n"
+ " -O0 Turn off any optimization.\n"
+ " -O1 Default optimization.\n"
+ " -O2 More aggressive optimizations for web font. In this\n"
+ " level, the following options will be set:\n"
+ " --merge-features\n"
+ " --short-post\n"
+ " --subroutinize\n"
+ " -O3 Most aggressive opptimization strategy will be\n"
+ " used. In this level, these options will be set:\n"
+ " --force-cid\n"
+ " --ignore-glyph-order\n"
+ " --verbose : Show more information when building.\n"
+ " -q, --quiet : Be silent when building.\n\n"
+ " --ignore-hints : Ignore the hinting information in the input.\n"
+ " --keep-average-char-width : Keep the OS/2.xAvgCharWidth value from the input\n"
+ " instead of stating the average width of glyphs.\n"
+ " Useful when creating a monospaced font.\n"
+ " --keep-unicode-ranges : Keep the OS/2.ulUnicodeRange[1-4] as-is.\n"
+ " --keep-modified-time : Keep the head.modified time in the json, instead of\n"
+ " using current time.\n\n"
+ " --short-post : Don't export glyph names in the result font.\n"
+ " --ignore-glyph-order, -i : Ignore the glyph order information in the input.\n"
+ " --keep-glyph-order, -k : Keep the glyph order information in the input.\n"
+ " Use to preserve glyph order under -O2 and -O3.\n"
+ " --dont-ignore-glyph-order : Same as --keep-glyph-order.\n"
+ " --merge-features : Merge duplicate OpenType feature definitions.\n"
+ " --dont-merge-features : Keep duplicate OpenType feature definitions.\n"
+ " --merge-lookups : Merge duplicate OpenType lookups.\n"
+ " --dont-merge-lookups : Keep duplicate OpenType lookups.\n"
+ " --force-cid : Convert name-keyed CFF OTF into CID-keyed.\n"
+ " --subroutinize : Subroutinize CFF table.\n"
+ " --stub-cmap4 : Create a stub `cmap` format 4 subtable if format\n"
+ " 12 subtable is present.\n"
+ "\n");
+}
+static void readEntireFile(char *inPath, char **_buffer, long *_length) {
+ char *buffer = NULL;
+ long length = 0;
+ FILE *f = u8fopen(inPath, "rb");
+ if (!f) {
+ fprintf(stderr, "Cannot read JSON file \"%s\". Exit.\n", inPath);
+ exit(EXIT_FAILURE);
+ }
+ fseek(f, 0, SEEK_END);
+ length = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buffer = malloc(length);
+ if (buffer) { fread(buffer, 1, length, f); }
+ fclose(f);
+
+ if (!buffer) {
+ fprintf(stderr, "Cannot read JSON file \"%s\". Exit.\n", inPath);
+ exit(EXIT_FAILURE);
+ }
+ *_buffer = buffer;
+ *_length = length;
+}
+
+static void readEntireStdin(char **_buffer, long *_length) {
+#ifdef _WIN32
+ freopen(NULL, "rb", stdin);
+#endif
+ static const long BUF_SIZE = 0x400000;
+ static const long BUF_MIN = 0x1000;
+ char *buffer = malloc(BUF_SIZE);
+ long length = 0;
+ long remain = BUF_SIZE;
+ while (!feof(stdin)) {
+ if (remain <= BUF_MIN) {
+ remain += (length >> 1) & 0xFFFFFF;
+ buffer = realloc(buffer, length + remain);
+ }
+
+ fgets(buffer + length, remain, stdin);
+ long n = (long)strlen(buffer + length);
+ length += n;
+ remain -= n;
+ }
+ *_buffer = buffer;
+ *_length = length;
+}
+
+#ifdef _WIN32
+int main() {
+ int argc;
+ char **argv;
+ get_argv_utf8(&argc, &argv);
+#else
+int main(int argc, char *argv[]) {
+#endif
+
+ struct timespec begin;
+ time_now(&begin);
+
+ bool show_help = false;
+ bool show_version = false;
+ sds outputPath = NULL;
+ sds inPath = NULL;
+ int option_index = 0;
+ int c;
+
+ otfcc_Options *options = otfcc_newOptions();
+ options->logger = otfcc_newLogger(otfcc_newStdErrTarget());
+ options->logger->indent(options->logger, "otfccbuild");
+ otfcc_Options_optimizeTo(options, 1);
+
+ struct option longopts[] = {{"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {"time", no_argument, NULL, 0},
+ {"ignore-glyph-order", no_argument, NULL, 0},
+ {"keep-glyph-order", no_argument, NULL, 0},
+ {"dont-ignore-glyph-order", no_argument, NULL, 0},
+ {"ignore-hints", no_argument, NULL, 0},
+ {"keep-average-char-width", no_argument, NULL, 0},
+ {"keep-unicode-ranges", no_argument, NULL, 0},
+ {"keep-modified-time", no_argument, NULL, 0},
+ {"merge-lookups", no_argument, NULL, 0},
+ {"merge-features", no_argument, NULL, 0},
+ {"dont-merge-lookups", no_argument, NULL, 0},
+ {"dont-merge-features", no_argument, NULL, 0},
+ {"short-post", no_argument, NULL, 0},
+ {"force-cid", no_argument, NULL, 0},
+ {"subroutinize", no_argument, NULL, 0},
+ {"stub-cmap4", no_argument, NULL, 0},
+ {"dummy-dsig", no_argument, NULL, 's'},
+ {"ship", no_argument, NULL, 0},
+ {"verbose", no_argument, NULL, 0},
+ {"quiet", no_argument, NULL, 0},
+ {"optimize", required_argument, NULL, 'O'},
+ {"output", required_argument, NULL, 'o'},
+ {0, 0, 0, 0}};
+
+ while ((c = getopt_long(argc, argv, "vhqskiO:o:", longopts, &option_index)) != (-1)) {
+ switch (c) {
+ case 0:
+ /* If this option set a flag, do nothing else now. */
+ if (longopts[option_index].flag != 0) {
+ break;
+ } else if (strcmp(longopts[option_index].name, "time") == 0) {
+ } else if (strcmp(longopts[option_index].name, "ignore-hints") == 0) {
+ options->ignore_hints = true;
+ } else if (strcmp(longopts[option_index].name, "keep-average-char-width") == 0) {
+ options->keep_average_char_width = true;
+ } else if (strcmp(longopts[option_index].name, "keep-unicode-ranges") == 0) {
+ options->keep_unicode_ranges = true;
+ } else if (strcmp(longopts[option_index].name, "keep-modified-time") == 0) {
+ options->keep_modified_time = true;
+ } else if (strcmp(longopts[option_index].name, "merge-features") == 0) {
+ options->merge_features = true;
+ } else if (strcmp(longopts[option_index].name, "merge-lookups") == 0) {
+ options->merge_lookups = true;
+ } else if (strcmp(longopts[option_index].name, "dont-merge-features") == 0) {
+ options->merge_features = false;
+ } else if (strcmp(longopts[option_index].name, "dont-merge-lookups") == 0) {
+ options->merge_lookups = false;
+ } else if (strcmp(longopts[option_index].name, "ignore-glyph-order") == 0) {
+ options->ignore_glyph_order = true;
+ } else if (strcmp(longopts[option_index].name, "keep-glyph-order") == 0) {
+ options->ignore_glyph_order = false;
+ } else if (strcmp(longopts[option_index].name, "dont-keep-glyph-order") == 0) {
+ options->ignore_glyph_order = false;
+ } else if (strcmp(longopts[option_index].name, "short-post") == 0) {
+ options->short_post = true;
+ } else if (strcmp(longopts[option_index].name, "force-cid") == 0) {
+ options->force_cid = true;
+ } else if (strcmp(longopts[option_index].name, "subroutinize") == 0) {
+ options->cff_doSubroutinize = true;
+ } else if (strcmp(longopts[option_index].name, "stub-cmap4") == 0) {
+ options->stub_cmap4 = true;
+ } else if (strcmp(longopts[option_index].name, "ship") == 0) {
+ options->ignore_glyph_order = true;
+ options->short_post = true;
+ options->dummy_DSIG = true;
+ } else if (strcmp(longopts[option_index].name, "verbose") == 0) {
+ options->verbose = true;
+ } else if (strcmp(longopts[option_index].name, "quiet") == 0) {
+ options->quiet = true;
+ }
+ break;
+ case 'v':
+ show_version = true;
+ break;
+ case 'h':
+ show_help = true;
+ break;
+ case 'k':
+ options->ignore_glyph_order = false;
+ break;
+ case 'i':
+ options->ignore_glyph_order = true;
+ break;
+ case 'o':
+ outputPath = sdsnew(optarg);
+ break;
+ case 's':
+ options->dummy_DSIG = true;
+ break;
+ case 'q':
+ options->quiet = true;
+ break;
+ case 'O':
+ otfcc_Options_optimizeTo(options, atoi(optarg));
+ break;
+ }
+ }
+ options->logger->setVerbosity(options->logger,
+ options->quiet ? 0 : options->verbose ? 0xFF : 1);
+ if (show_help) {
+ printInfo();
+ printHelp();
+ return 0;
+ }
+ if (show_version) {
+ printInfo();
+ return 0;
+ }
+
+ if (optind >= argc) {
+ inPath = NULL; // read from STDIN
+ } else {
+ inPath = sdsnew(argv[optind]); // read from file
+ }
+ if (!outputPath) {
+ logError("Unable to build OpenType font tile : output path not "
+ "specified. Exit.\n");
+ printHelp();
+ exit(EXIT_FAILURE);
+ }
+
+ char *buffer;
+ long length;
+ loggedStep("Load file") {
+ if (inPath) {
+ loggedStep("Load from file %s", inPath) {
+ readEntireFile(inPath, &buffer, &length);
+ sdsfree(inPath);
+ }
+ } else {
+ loggedStep("Load from stdin") {
+ readEntireStdin(&buffer, &length);
+ }
+ }
+ logStepTime;
+ }
+
+ json_value *jsonRoot = NULL;
+ loggedStep("Parse into JSON") {
+ jsonRoot = json_parse(buffer, length);
+ free(buffer);
+ logStepTime;
+ if (!jsonRoot) {
+ logError("Cannot parse JSON file \"%s\". Exit.\n", inPath);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ otfcc_Font *font;
+ loggedStep("Parse") {
+ otfcc_IFontBuilder *parser = otfcc_newJsonReader();
+ font = parser->read(jsonRoot, 0, options);
+ if (!font) {
+ logError("Cannot parse JSON file \"%s\" as a font. Exit.\n", inPath);
+ exit(EXIT_FAILURE);
+ }
+ parser->free(parser);
+ json_value_free(jsonRoot);
+ logStepTime;
+ }
+ loggedStep("Consolidate") {
+ otfcc_iFont.consolidate(font, options);
+ logStepTime;
+ }
+ loggedStep("Build") {
+ otfcc_IFontSerializer *writer = otfcc_newOTFWriter();
+ caryll_Buffer *otf = (caryll_Buffer *)writer->serialize(font, options);
+ loggedStep("Write to file") {
+ FILE *outfile = u8fopen(outputPath, "wb");
+ if (!outfile) {
+ logError("Cannot write to file \"%s\". Exit.\n", outputPath);
+ exit(EXIT_FAILURE);
+ }
+ fwrite(otf->data, sizeof(uint8_t), buflen(otf), outfile);
+ fclose(outfile);
+ }
+ logStepTime;
+ buffree(otf), writer->free(writer), otfcc_iFont.free(font), sdsfree(outputPath);
+ }
+ otfcc_deleteOptions(options);
+
+ return 0;
+}