1/*
2 * Copyright 2011 Google Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18
19#include <vector>
20#include <string>
21#include <sstream>
22
23#include "sfntly/port/type.h"
24#include "font_subsetter.h"
25
26template <typename T>
27class HexTo {
28 public:
29  explicit HexTo(const char* in) {
30    std::stringstream ss;
31    ss << std::hex << in;
32    ss >> value_;
33  }
34  operator T() const { return value_; }
35
36 private:
37  T value_;
38};
39
40bool LoadFile(const char* input_file_path, sfntly::ByteVector* input_buffer) {
41  assert(input_file_path);
42  assert(input_buffer);
43
44  FILE* input_file = NULL;
45#if defined WIN32
46  fopen_s(&input_file, input_file_path, "rb");
47#else
48  input_file = fopen(input_file_path, "rb");
49#endif
50  if (input_file == NULL) {
51    return false;
52  }
53  fseek(input_file, 0, SEEK_END);
54  size_t file_size = ftell(input_file);
55  fseek(input_file, 0, SEEK_SET);
56  input_buffer->resize(file_size);
57  size_t bytes_read = fread(&((*input_buffer)[0]), 1, file_size, input_file);
58  fclose(input_file);
59  return bytes_read == file_size;
60}
61
62bool SaveFile(const char* output_file_path, const unsigned char* output_buffer,
63              int buffer_length) {
64  int byte_count = 0;
65  if (buffer_length > 0) {
66    FILE* output_file = NULL;
67#if defined WIN32
68    fopen_s(&output_file, output_file_path, "wb");
69#else
70    output_file = fopen(output_file_path, "wb");
71#endif
72    if (output_file) {
73      byte_count = fwrite(output_buffer, 1, buffer_length, output_file);
74      fflush(output_file);
75      fclose(output_file);
76    }
77    return buffer_length == byte_count;
78  }
79  return false;
80}
81
82bool StringToGlyphId(const char* input, std::vector<unsigned int>* glyph_ids) {
83  assert(input);
84  std::string hex_csv = input;
85  size_t start = 0;
86  size_t end = hex_csv.find_first_of(",");
87  while (end != std::string::npos) {
88    glyph_ids->push_back(
89        HexTo<unsigned int>(hex_csv.substr(start, end - start).c_str()));
90    start = end + 1;
91    end = hex_csv.find_first_of(",", start);
92  }
93  glyph_ids->push_back(HexTo<unsigned int>(hex_csv.substr(start).c_str()));
94  return glyph_ids->size() > 0;
95}
96
97int main(int argc, char** argv) {
98  if (argc < 5) {
99    fprintf(stderr,
100        "Usage: %s <input path> <output path> <font name> <glyph ids>\n",
101        argv[0]);
102    fprintf(stderr, "\tGlyph ids are comma separated hex values\n");
103    fprintf(stderr, "\te.g. 20,1a,3b,4f\n");
104    return 0;
105  }
106
107  sfntly::ByteVector input_buffer;
108  if (!LoadFile(argv[1], &input_buffer)) {
109    fprintf(stderr, "ERROR: unable to load font file %s\n", argv[1]);
110    return 0;
111  }
112
113  std::vector<unsigned int> glyph_ids;
114  if (!StringToGlyphId(argv[4], &glyph_ids)) {
115    fprintf(stderr, "ERROR: unable to parse input glyph id\n");
116    return 0;
117  }
118
119  unsigned char* output_buffer = NULL;
120  int output_length =
121      SfntlyWrapper::SubsetFont(argv[3],
122                                &(input_buffer[0]),
123                                input_buffer.size(),
124                                &(glyph_ids[0]),
125                                glyph_ids.size(),
126                                &output_buffer);
127
128  int result = SaveFile(argv[2], output_buffer, output_length) ? 1 : 0;
129  delete[] output_buffer;
130  return result;
131}
132