OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 // This sample progam demonstrates how to use Skia and HarfBuzz to | 8 // This sample progam demonstrates how to use Skia and HarfBuzz to |
9 // produce a PDF file from UTF-8 text in stdin. | 9 // produce a PDF file from UTF-8 text in stdin. |
10 | 10 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 }; | 79 }; |
80 | 80 |
81 struct Config { | 81 struct Config { |
82 DoubleOption *page_width = new DoubleOption("-w", "Page width", 600.0f); | 82 DoubleOption *page_width = new DoubleOption("-w", "Page width", 600.0f); |
83 DoubleOption *page_height = new DoubleOption("-h", "Page height", 800.0f); | 83 DoubleOption *page_height = new DoubleOption("-h", "Page height", 800.0f); |
84 SkStringOption *title = new SkStringOption("-t", "PDF title", SkString("---"))
; | 84 SkStringOption *title = new SkStringOption("-t", "PDF title", SkString("---"))
; |
85 SkStringOption *author = new SkStringOption("-a", "PDF author", SkString("---"
)); | 85 SkStringOption *author = new SkStringOption("-a", "PDF author", SkString("---"
)); |
86 SkStringOption *subject = new SkStringOption("-k", "PDF subject", SkString("--
-")); | 86 SkStringOption *subject = new SkStringOption("-k", "PDF subject", SkString("--
-")); |
87 SkStringOption *keywords = new SkStringOption("-c", "PDF keywords", SkString("
---")); | 87 SkStringOption *keywords = new SkStringOption("-c", "PDF keywords", SkString("
---")); |
88 SkStringOption *creator = new SkStringOption("-t", "PDF creator", SkString("--
-")); | 88 SkStringOption *creator = new SkStringOption("-t", "PDF creator", SkString("--
-")); |
89 StdStringOption *font_file = new StdStringOption("-f", ".ttf font file", "font
s/DejaVuSans.ttf"); | 89 StdStringOption *font_file = new StdStringOption("-f", ".ttf font file", ""); |
90 DoubleOption *font_size = new DoubleOption("-z", "Font size", 8.0f); | 90 DoubleOption *font_size = new DoubleOption("-z", "Font size", 8.0f); |
91 DoubleOption *left_margin = new DoubleOption("-m", "Left margin", 20.0f); | 91 DoubleOption *left_margin = new DoubleOption("-m", "Left margin", 20.0f); |
92 DoubleOption *line_spacing_ratio = new DoubleOption("-h", "Line spacing ratio"
, 1.5f); | 92 DoubleOption *line_spacing_ratio = new DoubleOption("-h", "Line spacing ratio"
, 1.5f); |
93 StdStringOption *output_file_name = new StdStringOption("-o", ".pdf output fil
e name", "out-skiahf.pdf"); | 93 StdStringOption *output_file_name = new StdStringOption("-o", ".pdf output fil
e name", "out-skiahf.pdf"); |
94 | 94 |
95 std::map<std::string, BaseOption*> options = { | 95 std::map<std::string, BaseOption*> options = { |
96 { page_width->selector, page_width }, | 96 { page_width->selector, page_width }, |
97 { page_height->selector, page_height }, | 97 { page_height->selector, page_height }, |
98 { title->selector, title }, | 98 { title->selector, title }, |
99 { author->selector, author }, | 99 { author->selector, author }, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 } // end of Config::Config | 134 } // end of Config::Config |
135 }; | 135 }; |
136 | 136 |
137 const double FONT_SIZE_SCALE = 64.0f; | 137 const double FONT_SIZE_SCALE = 64.0f; |
138 | 138 |
139 struct Face { | 139 struct Face { |
140 struct HBFDel { void operator()(hb_face_t* f) { hb_face_destroy(f); } }; | 140 struct HBFDel { void operator()(hb_face_t* f) { hb_face_destroy(f); } }; |
141 std::unique_ptr<hb_face_t, HBFDel> fHarfBuzzFace; | 141 std::unique_ptr<hb_face_t, HBFDel> fHarfBuzzFace; |
142 sk_sp<SkTypeface> fSkiaTypeface; | 142 sk_sp<SkTypeface> fSkiaTypeface; |
143 | 143 |
| 144 Face(sk_sp<SkTypeface> skiaTypeface) : fSkiaTypeface(std::move(skiaTypeface))
{ |
| 145 int index; |
| 146 std::unique_ptr<SkStreamAsset> asset(fSkiaTypeface->openStream(&index)); |
| 147 size_t size = asset->getLength(); |
| 148 // TODO(halcanary): avoid this malloc and copy. |
| 149 char* buffer = (char*)malloc(size); |
| 150 asset->read(buffer, size); |
| 151 hb_blob_t* blob = hb_blob_create(buffer, |
| 152 size, |
| 153 HB_MEMORY_MODE_READONLY, |
| 154 nullptr, |
| 155 free); |
| 156 assert(blob); |
| 157 hb_blob_make_immutable(blob); |
| 158 hb_face_t* face = hb_face_create(blob, (unsigned)index); |
| 159 hb_blob_destroy(blob); |
| 160 assert(face); |
| 161 if (!face) { |
| 162 fSkiaTypeface.reset(); |
| 163 return; |
| 164 } |
| 165 hb_face_set_index(face, (unsigned)index); |
| 166 hb_face_set_upem(face, fSkiaTypeface->getUnitsPerEm()); |
| 167 fHarfBuzzFace.reset(face); |
| 168 } |
144 Face(const char* path, int index) { | 169 Face(const char* path, int index) { |
145 // fairly portable mmap impl | 170 // fairly portable mmap impl |
146 auto data = SkData::MakeFromFileName(path); | 171 auto data = SkData::MakeFromFileName(path); |
147 assert(data); | 172 assert(data); |
148 if (!data) { return; } | 173 if (!data) { return; } |
149 fSkiaTypeface = SkTypeface::MakeFromStream(new SkMemoryStream(data), index); | 174 fSkiaTypeface = SkTypeface::MakeFromStream(new SkMemoryStream(data), index); |
150 assert(fSkiaTypeface); | 175 assert(fSkiaTypeface); |
151 if (!fSkiaTypeface) { return; } | 176 if (!fSkiaTypeface) { return; } |
152 auto destroy = [](void *d) { static_cast<SkData*>(d)->unref(); }; | 177 auto destroy = [](void *d) { static_cast<SkData*>(d)->unref(); }; |
153 const char* bytes = (const char*)data->data(); | 178 const char* bytes = (const char*)data->data(); |
(...skipping 14 matching lines...) Expand all Loading... |
168 } | 193 } |
169 hb_face_set_index(face, (unsigned)index); | 194 hb_face_set_index(face, (unsigned)index); |
170 hb_face_set_upem(face, fSkiaTypeface->getUnitsPerEm()); | 195 hb_face_set_upem(face, fSkiaTypeface->getUnitsPerEm()); |
171 fHarfBuzzFace.reset(face); | 196 fHarfBuzzFace.reset(face); |
172 } | 197 } |
173 }; | 198 }; |
174 | 199 |
175 class Placement { | 200 class Placement { |
176 public: | 201 public: |
177 Placement(Config &_config, SkWStream* outputStream) : config(_config) { | 202 Placement(Config &_config, SkWStream* outputStream) : config(_config) { |
178 face = new Face(config.font_file->value.c_str(), 0 /* index */); | 203 const std::string& font_file = config.font_file->value; |
| 204 if (font_file.size() > 0) { |
| 205 face = new Face(font_file.c_str(), 0 /* index */); |
| 206 } else { |
| 207 face = new Face(SkTypeface::MakeDefault()); |
| 208 } |
179 hb_font = hb_font_create(face->fHarfBuzzFace.get()); | 209 hb_font = hb_font_create(face->fHarfBuzzFace.get()); |
180 | 210 |
181 hb_font_set_scale(hb_font, | 211 hb_font_set_scale(hb_font, |
182 FONT_SIZE_SCALE * config.font_size->value, | 212 FONT_SIZE_SCALE * config.font_size->value, |
183 FONT_SIZE_SCALE * config.font_size->value); | 213 FONT_SIZE_SCALE * config.font_size->value); |
184 hb_ot_font_set_funcs(hb_font); | 214 hb_ot_font_set_funcs(hb_font); |
185 | 215 |
186 SkDocument::PDFMetadata pdf_info; | 216 SkDocument::PDFMetadata pdf_info; |
187 pdf_info.fTitle = config.title->value; | 217 pdf_info.fTitle = config.title->value; |
188 pdf_info.fAuthor = config.author->value; | 218 pdf_info.fAuthor = config.author->value; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 Config config(argc, argv); | 329 Config config(argc, argv); |
300 | 330 |
301 Placement placement(config, new SkFILEWStream(config.output_file_name->value
.c_str())); | 331 Placement placement(config, new SkFILEWStream(config.output_file_name->value
.c_str())); |
302 for (std::string line; std::getline(std::cin, line);) { | 332 for (std::string line; std::getline(std::cin, line);) { |
303 placement.WriteLine(line.c_str()); | 333 placement.WriteLine(line.c_str()); |
304 } | 334 } |
305 placement.Close(); | 335 placement.Close(); |
306 | 336 |
307 return 0; | 337 return 0; |
308 } | 338 } |
OLD | NEW |