Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/pdf/SkPDFFont.cpp

Issue 2253283004: SkPDF: in-place font subsetting (Closed) Base URL: https://skia.googlesource.com/skia.git@SkPdfCacheMetrics
Patch Set: 2016-08-18 (Thursday) 16:02:16 EDT Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pdf/SkPDFFont.h ('k') | src/pdf/SkPDFGraphicState.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 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 #include "SkData.h" 8 #include "SkData.h"
9 #include "SkGlyphCache.h" 9 #include "SkGlyphCache.h"
10 #include "SkPaint.h" 10 #include "SkPaint.h"
(...skipping 19 matching lines...) Expand all
30 #include SK_SFNTLY_SUBSETTER 30 #include SK_SFNTLY_SUBSETTER
31 #endif 31 #endif
32 #endif 32 #endif
33 33
34 namespace { 34 namespace {
35 // PDF's notion of symbolic vs non-symbolic is related to the character set, not 35 // PDF's notion of symbolic vs non-symbolic is related to the character set, not
36 // symbols vs. characters. Rarely is a font the right character set to call it 36 // symbols vs. characters. Rarely is a font the right character set to call it
37 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) 37 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1)
38 static const int kPdfSymbolic = 4; 38 static const int kPdfSymbolic = 4;
39 39
40 class SkPDFType0Font final : public SkPDFFont { 40 struct SkPDFType0Font final : public SkPDFFont {
41 public: 41 SkPDFType0Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
42 SkPDFType0Font(const SkAdvancedTypefaceMetrics& info,
43 sk_sp<SkTypeface> typeface,
44 SkAdvancedTypefaceMetrics::FontType type);
45 virtual ~SkPDFType0Font(); 42 virtual ~SkPDFType0Font();
46 sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override ; 43 void getFontSubset(SkPDFCanon*) override;
47 #ifdef SK_DEBUG 44 #ifdef SK_DEBUG
48 void emitObject(SkWStream*, 45 void emitObject(SkWStream*, const SkPDFObjNumMap&) const override;
49 const SkPDFObjNumMap&,
50 const SkPDFSubstituteMap&) const override;
51 #endif
52
53 private:
54 #ifdef SK_DEBUG
55 bool fPopulated; 46 bool fPopulated;
56 #endif 47 #endif
57 bool populate(const SkPDFGlyphSet* subset,
58 const SkAdvancedTypefaceMetrics& metrics);
59 typedef SkPDFDict INHERITED; 48 typedef SkPDFDict INHERITED;
60 }; 49 };
61 50
62 class SkPDFType1Font final : public SkPDFFont { 51 struct SkPDFType1Font final : public SkPDFFont {
63 public: 52 SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon *);
64 SkPDFType1Font(const SkAdvancedTypefaceMetrics& info,
65 sk_sp<SkTypeface> typeface,
66 uint16_t glyphID,
67 SkPDFCanon* canon);
68 virtual ~SkPDFType1Font() {} 53 virtual ~SkPDFType1Font() {}
54 void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement
69 }; 55 };
70 56
71 class SkPDFType3Font final : public SkPDFFont { 57 struct SkPDFType3Font final : public SkPDFFont {
72 public: 58 SkPDFType3Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
73 SkPDFType3Font(const SkAdvancedTypefaceMetrics& info,
74 sk_sp<SkTypeface> typeface,
75 SkAdvancedTypefaceMetrics::FontType fontType,
76 uint16_t glyphID);
77 virtual ~SkPDFType3Font() {} 59 virtual ~SkPDFType3Font() {}
78 void emitObject(SkWStream*, 60 void getFontSubset(SkPDFCanon*) override;
79 const SkPDFObjNumMap&,
80 const SkPDFSubstituteMap&) const override {
81 SkDEBUGFAIL("should call getFontSubset!");
82 }
83 sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override ;
84 }; 61 };
85 62
86 /////////////////////////////////////////////////////////////////////////////// 63 ///////////////////////////////////////////////////////////////////////////////
87 // File-Local Functions 64 // File-Local Functions
88 /////////////////////////////////////////////////////////////////////////////// 65 ///////////////////////////////////////////////////////////////////////////////
89 66
90 static SkAutoGlyphCache vector_cache(SkTypeface* face, SkScalar size = 0) { 67 static SkAutoGlyphCache vector_cache(SkTypeface* face, SkScalar size = 0) {
91 SkPaint tmpPaint; 68 SkPaint tmpPaint;
92 tmpPaint.setHinting(SkPaint::kNo_Hinting); 69 tmpPaint.setHinting(SkPaint::kNo_Hinting);
93 tmpPaint.setTypeface(sk_ref_sp(face)); 70 tmpPaint.setTypeface(sk_ref_sp(face));
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 auto bbox = sk_make_sp<SkPDFArray>(); 113 auto bbox = sk_make_sp<SkPDFArray>();
137 bbox->reserve(4); 114 bbox->reserve(4);
138 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); 115 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize));
139 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); 116 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize));
140 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); 117 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize));
141 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); 118 bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize));
142 return bbox; 119 return bbox;
143 } 120 }
144 } // namespace 121 } // namespace
145 122
146
147 ///////////////////////////////////////////////////////////////////////////////
148 // class SkPDFGlyphSet
149 ///////////////////////////////////////////////////////////////////////////////
150
151 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) {
152 }
153
154 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) {
155 for (int i = 0; i < numGlyphs; ++i) {
156 fBitSet.setBit(glyphIDs[i], true);
157 }
158 }
159
160 bool SkPDFGlyphSet::has(uint16_t glyphID) const {
161 return fBitSet.isBitSet(glyphID);
162 }
163
164 void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const {
165 fBitSet.exportTo(glyphIDs);
166 }
167
168 ///////////////////////////////////////////////////////////////////////////////
169 // class SkPDFGlyphSetMap
170 ///////////////////////////////////////////////////////////////////////////////
171
172 SkPDFGlyphSetMap::SkPDFGlyphSetMap() {}
173
174 SkPDFGlyphSetMap::~SkPDFGlyphSetMap() {
175 fMap.reset();
176 }
177
178 void SkPDFGlyphSetMap::noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs,
179 int numGlyphs) {
180 SkPDFGlyphSet* subset = getGlyphSetForFont(font);
181 if (subset) {
182 subset->set(glyphIDs, numGlyphs);
183 }
184 }
185
186 SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) {
187 int index = fMap.count();
188 for (int i = 0; i < index; ++i) {
189 if (fMap[i].fFont == font) {
190 return &fMap[i].fGlyphSet;
191 }
192 }
193 FontGlyphSetPair& pair = fMap.push_back();
194 pair.fFont = font;
195 return &pair.fGlyphSet;
196 }
197
198 /////////////////////////////////////////////////////////////////////////////// 123 ///////////////////////////////////////////////////////////////////////////////
199 // class SkPDFFont 124 // class SkPDFFont
200 /////////////////////////////////////////////////////////////////////////////// 125 ///////////////////////////////////////////////////////////////////////////////
201 126
202 /* Font subset design: It would be nice to be able to subset fonts 127 /* Font subset design: It would be nice to be able to subset fonts
203 * (particularly type 3 fonts), but it's a lot of work and not a priority. 128 * (particularly type 3 fonts), but it's a lot of work and not a priority.
204 * 129 *
205 * Resources are canonicalized and uniqueified by pointer so there has to be 130 * Resources are canonicalized and uniqueified by pointer so there has to be
206 * some additional state indicating which subset of the font is used. It 131 * some additional state indicating which subset of the font is used. It
207 * must be maintained at the page granularity and then combined at the document 132 * must be maintained at the page granularity and then combined at the document
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 sk_sp<SkTypeface> typeface(face ? sk_ref_sp(face) : SkTypeface::MakeDefault( )); 240 sk_sp<SkTypeface> typeface(face ? sk_ref_sp(face) : SkTypeface::MakeDefault( ));
316 SkASSERT(typeface); 241 SkASSERT(typeface);
317 int glyphCount = typeface->countGlyphs(); 242 int glyphCount = typeface->countGlyphs();
318 // Validate typeface + glyph; 243 // Validate typeface + glyph;
319 if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph. 244 if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph.
320 glyphCount > 1 + SK_MaxU16 || // invalid glyphCount 245 glyphCount > 1 + SK_MaxU16 || // invalid glyphCount
321 glyphID >= glyphCount) { // invalid glyph 246 glyphID >= glyphCount) { // invalid glyph
322 return nullptr; 247 return nullptr;
323 } 248 }
324 249
250 SkGlyphID firstNonZeroGlyph;
251 SkGlyphID lastGlyph;
252 if (multibyte) {
253 firstNonZeroGlyph = 1;
254 lastGlyph = SkToU16(glyphCount - 1);
255 } else {
256 firstNonZeroGlyph = firstGlyph;
257 lastGlyph = SkToU16(SkTMin<int>(glyphCount - 1,
258 254 + (int)firstGlyph));
259 }
260 SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, t ype};
325 sk_sp<SkPDFFont> font; 261 sk_sp<SkPDFFont> font;
326 switch (type) { 262 switch (type) {
327 case SkAdvancedTypefaceMetrics::kType1CID_Font: 263 case SkAdvancedTypefaceMetrics::kType1CID_Font:
328 case SkAdvancedTypefaceMetrics::kTrueType_Font: 264 case SkAdvancedTypefaceMetrics::kTrueType_Font:
329 SkASSERT(multibyte); 265 SkASSERT(multibyte);
330 font = sk_make_sp<SkPDFType0Font>(metrics, 266 font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics);
331 std::move(typeface),
332 type);
333 break; 267 break;
334 case SkAdvancedTypefaceMetrics::kType1_Font: 268 case SkAdvancedTypefaceMetrics::kType1_Font:
335 SkASSERT(!multibyte); 269 SkASSERT(!multibyte);
336 font = sk_make_sp<SkPDFType1Font>(metrics, 270 font = sk_make_sp<SkPDFType1Font>(std::move(info), metrics, canon);
337 std::move(typeface),
338 glyphID,
339 canon);
340 break; 271 break;
341 default: 272 default:
342 SkASSERT(!multibyte); 273 SkASSERT(!multibyte);
343 // Type3 is our fallback font. 274 // Type3 is our fallback font.
344 font = sk_make_sp<SkPDFType3Font>(metrics, 275 font = sk_make_sp<SkPDFType3Font>(std::move(info), metrics);
345 std::move(typeface),
346 type,
347 glyphID);
348 break; 276 break;
349 } 277 }
350 canon->fFontMap.set(fontID, SkRef(font.get())); 278 canon->fFontMap.set(fontID, SkRef(font.get()));
351 return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>. 279 return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>.
352 } 280 }
353 281
354 sk_sp<SkPDFObject> SkPDFFont::getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) { 282 SkPDFFont::SkPDFFont(SkPDFFont::Info info)
355 return nullptr; // Default: no support.
356 }
357
358 SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface,
359 SkAdvancedTypefaceMetrics::FontType fontType)
360 : SkPDFDict("Font") 283 : SkPDFDict("Font")
361 , fTypeface(std::move(typeface)) 284 , fTypeface(std::move(info.fTypeface))
362 , fFirstGlyphID(1) 285 , fGlyphUsage(info.fLastGlyphID + 1) // TODO(halcanary): Adjust mapping?
363 , fFontType(fontType) { 286 , fFirstGlyphID(info.fFirstGlyphID)
287 , fLastGlyphID(info.fLastGlyphID)
288 , fFontType(info.fFontType) {
364 SkASSERT(fTypeface); 289 SkASSERT(fTypeface);
365 fLastGlyphID = SkToU16(fTypeface->countGlyphs() - 1);
366 } 290 }
367 291
368 static void add_common_font_descriptor_entries(SkPDFDict* descriptor, 292 static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
369 const SkAdvancedTypefaceMetrics& metrics, 293 const SkAdvancedTypefaceMetrics& metrics,
370 int16_t defaultWidth) { 294 int16_t defaultWidth) {
371 const uint16_t emSize = metrics.fEmSize; 295 const uint16_t emSize = metrics.fEmSize;
372 descriptor->insertName("FontName", metrics.fFontName); 296 descriptor->insertName("FontName", metrics.fFontName);
373 descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic)); 297 descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic));
374 descriptor->insertScalar("Ascent", 298 descriptor->insertScalar("Ascent",
375 scaleFromFontUnits(metrics.fAscent, emSize)); 299 scaleFromFontUnits(metrics.fAscent, emSize));
376 descriptor->insertScalar("Descent", 300 descriptor->insertScalar("Descent",
377 scaleFromFontUnits(metrics.fDescent, emSize)); 301 scaleFromFontUnits(metrics.fDescent, emSize));
378 descriptor->insertScalar("StemV", 302 descriptor->insertScalar("StemV",
379 scaleFromFontUnits(metrics.fStemV, emSize)); 303 scaleFromFontUnits(metrics.fStemV, emSize));
380 descriptor->insertScalar("CapHeight", 304 descriptor->insertScalar("CapHeight",
381 scaleFromFontUnits(metrics.fCapHeight, emSize)); 305 scaleFromFontUnits(metrics.fCapHeight, emSize));
382 descriptor->insertInt("ItalicAngle", metrics.fItalicAngle); 306 descriptor->insertInt("ItalicAngle", metrics.fItalicAngle);
383 descriptor->insertObject( 307 descriptor->insertObject(
384 "FontBBox", makeFontBBox(metrics.fBBox, metrics.fEmSize)); 308 "FontBBox", makeFontBBox(metrics.fBBox, metrics.fEmSize));
385 if (defaultWidth > 0) { 309 if (defaultWidth > 0) {
386 descriptor->insertScalar("MissingWidth", 310 descriptor->insertScalar("MissingWidth",
387 scaleFromFontUnits(defaultWidth, emSize)); 311 scaleFromFontUnits(defaultWidth, emSize));
388 } 312 }
389 } 313 }
390 314
391 void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(SkGlyphID glyphID) {
392 // Single byte glyph encoding supports a max of 255 glyphs.
393 fFirstGlyphID = first_glyph_for_single_byte_encoding(glyphID);
394 if (fLastGlyphID > fFirstGlyphID + 255 - 1) {
395 fLastGlyphID = fFirstGlyphID + 255 - 1;
396 }
397 }
398
399 /////////////////////////////////////////////////////////////////////////////// 315 ///////////////////////////////////////////////////////////////////////////////
400 // class SkPDFType0Font 316 // class SkPDFType0Font
401 /////////////////////////////////////////////////////////////////////////////// 317 ///////////////////////////////////////////////////////////////////////////////
402 318
403 SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics& info, 319 SkPDFType0Font::SkPDFType0Font(
404 sk_sp<SkTypeface> typeface, 320 SkPDFFont::Info info,
405 SkAdvancedTypefaceMetrics::FontType fontType) 321 const SkAdvancedTypefaceMetrics& metrics)
406 : SkPDFFont(std::move(typeface), fontType) { 322 : SkPDFFont(std::move(info)) {
407 SkDEBUGCODE(fPopulated = false); 323 SkDEBUGCODE(fPopulated = false);
408 if (!can_subset(info)) {
409 this->populate(nullptr, info);
410 }
411 } 324 }
412 325
413 SkPDFType0Font::~SkPDFType0Font() {} 326 SkPDFType0Font::~SkPDFType0Font() {}
414 327
415 sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(SkPDFCanon* canon,
416 const SkPDFGlyphSet* subset) {
417 const SkAdvancedTypefaceMetrics* metrics =
418 SkPDFFont::GetMetrics(this->typeface(), canon);
419 SkASSERT(metrics);
420 if (!metrics || !can_subset(*metrics)) {
421 return nullptr;
422 }
423 auto newSubset = sk_make_sp<SkPDFType0Font>(
424 *metrics, this->refTypeface(), this->getType());
425 newSubset->populate(subset, *metrics);
426 return newSubset;
427 }
428 328
429 #ifdef SK_DEBUG 329 #ifdef SK_DEBUG
430 void SkPDFType0Font::emitObject(SkWStream* stream, 330 void SkPDFType0Font::emitObject(SkWStream* stream,
431 const SkPDFObjNumMap& objNumMap, 331 const SkPDFObjNumMap& objNumMap) const {
432 const SkPDFSubstituteMap& substitutes) const {
433 SkASSERT(fPopulated); 332 SkASSERT(fPopulated);
434 return INHERITED::emitObject(stream, objNumMap, substitutes); 333 return INHERITED::emitObject(stream, objNumMap);
435 } 334 }
436 #endif 335 #endif
437 336
438 #ifdef SK_SFNTLY_SUBSETTER 337 #ifdef SK_SFNTLY_SUBSETTER
439 // if possible, make no copy. 338 // if possible, make no copy.
440 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { 339 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) {
441 SkASSERT(stream); 340 SkASSERT(stream);
442 (void)stream->rewind(); 341 (void)stream->rewind();
443 SkASSERT(stream->hasLength()); 342 SkASSERT(stream->hasLength());
444 size_t size = stream->getLength(); 343 size_t size = stream->getLength();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 auto subsetStream = sk_make_sp<SkPDFStream>( 380 auto subsetStream = sk_make_sp<SkPDFStream>(
482 SkData::MakeWithProc( 381 SkData::MakeWithProc(
483 subsetFont, subsetFontSize, 382 subsetFont, subsetFontSize,
484 [](const void* p, void*) { delete[] (unsigned char*)p; }, 383 [](const void* p, void*) { delete[] (unsigned char*)p; },
485 nullptr)); 384 nullptr));
486 subsetStream->dict()->insertInt("Length1", subsetFontSize); 385 subsetStream->dict()->insertInt("Length1", subsetFontSize);
487 return subsetStream; 386 return subsetStream;
488 } 387 }
489 #endif // SK_SFNTLY_SUBSETTER 388 #endif // SK_SFNTLY_SUBSETTER
490 389
491 bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset, 390 void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) {
492 const SkAdvancedTypefaceMetrics& metrics) { 391 const SkAdvancedTypefaceMetrics* metricsPtr =
392 SkPDFFont::GetMetrics(this->typeface(), canon);
393 SkASSERT(metricsPtr);
394 if (!metricsPtr) { return; }
395 const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
493 SkASSERT(can_embed(metrics)); 396 SkASSERT(can_embed(metrics));
494 SkAdvancedTypefaceMetrics::FontType type = this->getType(); 397 SkAdvancedTypefaceMetrics::FontType type = this->getType();
495 SkTypeface* face = this->typeface(); 398 SkTypeface* face = this->typeface();
496 SkASSERT(face); 399 SkASSERT(face);
497 const SkString& name = metrics.fFontName; 400 const SkString& name = metrics.fFontName;
498 401
499 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); 402 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
500 add_common_font_descriptor_entries(descriptor.get(), metrics, 0); 403 add_common_font_descriptor_entries(descriptor.get(), metrics, 0);
501 switch (type) { 404 switch (type) {
502 case SkAdvancedTypefaceMetrics::kTrueType_Font: { 405 case SkAdvancedTypefaceMetrics::kTrueType_Font: {
503 int ttcIndex; 406 int ttcIndex;
504 std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex) ); 407 std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex) );
505 SkASSERT(fontAsset); 408 SkASSERT(fontAsset);
506 if (!fontAsset) { 409 if (!fontAsset) {
507 return false; 410 return;
508 } 411 }
509 size_t fontSize = fontAsset->getLength(); 412 size_t fontSize = fontAsset->getLength();
510 SkASSERT(fontSize > 0); 413 SkASSERT(fontSize > 0);
511 if (fontSize == 0) { 414 if (fontSize == 0) {
512 return false; 415 return;
513 } 416 }
514 417
515 #ifdef SK_SFNTLY_SUBSETTER 418 #ifdef SK_SFNTLY_SUBSETTER
516 if (can_subset(metrics) && subset) { 419 if (can_subset(metrics)) {
517 // Generate glyph id array. in format needed by sfntly 420 // Generate glyph id array. in format needed by sfntly
518 SkTDArray<uint32_t> glyphIDs; 421 SkTDArray<uint32_t> glyphIDs;
519 if (subset) { 422 if (!this->glyphUsage().has(0)) {
520 if (!subset->has(0)) { 423 glyphIDs.push(0); // Always include glyph 0.
521 glyphIDs.push(0); // Always include glyph 0.
522 }
523 subset->exportTo(&glyphIDs);
524 } 424 }
425 this->glyphUsage().exportTo(&glyphIDs);
525 sk_sp<SkPDFObject> subsetStream = get_subset_font_stream( 426 sk_sp<SkPDFObject> subsetStream = get_subset_font_stream(
526 std::move(fontAsset), glyphIDs, name.c_str()); 427 std::move(fontAsset), glyphIDs, name.c_str());
527 if (subsetStream) { 428 if (subsetStream) {
528 descriptor->insertObjRef("FontFile2", std::move(subsetStream )); 429 descriptor->insertObjRef("FontFile2", std::move(subsetStream ));
529 break; 430 break;
530 } 431 }
531 // If subsetting fails, fall back to original font data. 432 // If subsetting fails, fall back to original font data.
532 fontAsset.reset(face->openStream(&ttcIndex)); 433 fontAsset.reset(face->openStream(&ttcIndex));
533 } 434 }
534 #endif // SK_SFNTLY_SUBSETTER 435 #endif // SK_SFNTLY_SUBSETTER
535 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset) ); 436 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset) );
536 fontStream->dict()->insertInt("Length1", fontSize); 437 fontStream->dict()->insertInt("Length1", fontSize);
537 descriptor->insertObjRef("FontFile2", std::move(fontStream)); 438 descriptor->insertObjRef("FontFile2", std::move(fontStream));
538 break; 439 break;
539 } 440 }
540 case SkAdvancedTypefaceMetrics::kType1CID_Font: { 441 case SkAdvancedTypefaceMetrics::kType1CID_Font: {
541 std::unique_ptr<SkStreamAsset> fontData(face->openStream(nullptr)); 442 std::unique_ptr<SkStreamAsset> fontData(face->openStream(nullptr));
542 SkASSERT(fontData); 443 SkASSERT(fontData);
543 SkASSERT(fontData->getLength() > 0); 444 SkASSERT(fontData->getLength() > 0);
544 if (!fontData || 0 == fontData->getLength()) { 445 if (!fontData || 0 == fontData->getLength()) {
545 return false; 446 return;
546 } 447 }
547 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData)) ; 448 auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData)) ;
548 fontStream->dict()->insertName("Subtype", "CIDFontType0c"); 449 fontStream->dict()->insertName("Subtype", "CIDFontType0c");
549 descriptor->insertObjRef("FontFile3", std::move(fontStream)); 450 descriptor->insertObjRef("FontFile3", std::move(fontStream));
550 break; 451 break;
551 } 452 }
552 default: 453 default:
553 SkASSERT(false); 454 SkASSERT(false);
554 } 455 }
555 456
(...skipping 11 matching lines...) Expand all
567 } 468 }
568 469
569 auto sysInfo = sk_make_sp<SkPDFDict>(); 470 auto sysInfo = sk_make_sp<SkPDFDict>();
570 sysInfo->insertString("Registry", "Adobe"); 471 sysInfo->insertString("Registry", "Adobe");
571 sysInfo->insertString("Ordering", "Identity"); 472 sysInfo->insertString("Ordering", "Identity");
572 sysInfo->insertInt("Supplement", 0); 473 sysInfo->insertInt("Supplement", 0);
573 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); 474 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo));
574 475
575 uint16_t emSize = metrics.fEmSize; 476 uint16_t emSize = metrics.fEmSize;
576 int16_t defaultWidth = 0; 477 int16_t defaultWidth = 0;
577 const SkBitSet* bitSet = subset ? &subset->bitSet() : nullptr;
578 { 478 {
579 SkAutoGlyphCache glyphCache = vector_cache(face); 479 SkAutoGlyphCache glyphCache = vector_cache(face);
580 sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( 480 sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
581 glyphCache.get(), bitSet, emSize, &defaultWidth); 481 glyphCache.get(), &this->glyphUsage(), emSize, &defaultWidth);
582 if (widths && widths->size() > 0) { 482 if (widths && widths->size() > 0) {
583 newCIDFont->insertObject("W", std::move(widths)); 483 newCIDFont->insertObject("W", std::move(widths));
584 } 484 }
585 newCIDFont->insertScalar( 485 newCIDFont->insertScalar(
586 "DW", scaleFromFontUnits(defaultWidth, emSize)); 486 "DW", scaleFromFontUnits(defaultWidth, emSize));
587 } 487 }
588 488
589 //////////////////////////////////////////////////////////////////////////// 489 ////////////////////////////////////////////////////////////////////////////
590 490
591 this->insertName("Subtype", "Type0"); 491 this->insertName("Subtype", "Type0");
592 this->insertName("BaseFont", metrics.fFontName); 492 this->insertName("BaseFont", metrics.fFontName);
593 this->insertName("Encoding", "Identity-H"); 493 this->insertName("Encoding", "Identity-H");
594 auto descendantFonts = sk_make_sp<SkPDFArray>(); 494 auto descendantFonts = sk_make_sp<SkPDFArray>();
595 descendantFonts->appendObjRef(std::move(newCIDFont)); 495 descendantFonts->appendObjRef(std::move(newCIDFont));
596 this->insertObject("DescendantFonts", std::move(descendantFonts)); 496 this->insertObject("DescendantFonts", std::move(descendantFonts));
597 497
598 if (metrics.fGlyphToUnicode.count() > 0) { 498 if (metrics.fGlyphToUnicode.count() > 0) {
599 this->insertObjRef("ToUnicode", 499 this->insertObjRef("ToUnicode",
600 SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode, 500 SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode,
601 subset, 501 &this->glyphUsage(),
602 multiByteGlyphs(), 502 multiByteGlyphs(),
603 firstGlyphID(), 503 firstGlyphID(),
604 lastGlyphID())); 504 lastGlyphID()));
605 } 505 }
606 SkDEBUGCODE(fPopulated = true); 506 SkDEBUGCODE(fPopulated = true);
607 return true; 507 return;
608 } 508 }
609 509
610 /////////////////////////////////////////////////////////////////////////////// 510 ///////////////////////////////////////////////////////////////////////////////
611 // class SkPDFType1Font 511 // class SkPDFType1Font
612 /////////////////////////////////////////////////////////////////////////////// 512 ///////////////////////////////////////////////////////////////////////////////
613 513
614 static sk_sp<SkPDFDict> make_type1_font_descriptor( 514 static sk_sp<SkPDFDict> make_type1_font_descriptor(
615 SkTypeface* typeface, 515 SkTypeface* typeface,
616 const SkAdvancedTypefaceMetrics& info) { 516 const SkAdvancedTypefaceMetrics& info) {
617 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); 517 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty( ); 572 const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty( );
673 const SkString& name = valid ? glyphNames[gID] : unknown; 573 const SkString& name = valid ? glyphNames[gID] : unknown;
674 encDiffs->appendName(name); 574 encDiffs->appendName(name);
675 } 575 }
676 576
677 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); 577 auto encoding = sk_make_sp<SkPDFDict>("Encoding");
678 encoding->insertObject("Differences", std::move(encDiffs)); 578 encoding->insertObject("Differences", std::move(encDiffs));
679 font->insertObject("Encoding", std::move(encoding)); 579 font->insertObject("Encoding", std::move(encoding));
680 } 580 }
681 581
682 SkPDFType1Font::SkPDFType1Font(const SkAdvancedTypefaceMetrics& info, 582 SkPDFType1Font::SkPDFType1Font(SkPDFFont::Info info,
683 sk_sp<SkTypeface> typeface, 583 const SkAdvancedTypefaceMetrics& metrics,
684 uint16_t glyphID,
685 SkPDFCanon* canon) 584 SkPDFCanon* canon)
686 : SkPDFFont(std::move(typeface), SkAdvancedTypefaceMetrics::kType1_Font) 585 : SkPDFFont(std::move(info))
687 { 586 {
688 SkFontID fontID = this->typeface()->uniqueID(); 587 SkFontID fontID = this->typeface()->uniqueID();
689 sk_sp<SkPDFDict> fontDescriptor; 588 sk_sp<SkPDFDict> fontDescriptor;
690 if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) { 589 if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) {
691 fontDescriptor = sk_ref_sp(*ptr); 590 fontDescriptor = sk_ref_sp(*ptr);
692 } else { 591 } else {
693 fontDescriptor = make_type1_font_descriptor(this->typeface(), info); 592 fontDescriptor = make_type1_font_descriptor(this->typeface(), metrics);
694 canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get())); 593 canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get()));
695 } 594 }
696 this->insertObjRef("FontDescriptor", std::move(fontDescriptor)); 595 this->insertObjRef("FontDescriptor", std::move(fontDescriptor));
697 this->adjustGlyphRangeForSingleByteEncoding(glyphID);
698 // TODO(halcanary): subset this (advances and names). 596 // TODO(halcanary): subset this (advances and names).
699 populate_type_1_font(this, info, this->typeface(), 597 populate_type_1_font(this, metrics, this->typeface(),
700 this->firstGlyphID(), this->lastGlyphID()); 598 this->firstGlyphID(), this->lastGlyphID());
701 } 599 }
702 600
703 /////////////////////////////////////////////////////////////////////////////// 601 ///////////////////////////////////////////////////////////////////////////////
704 // class SkPDFType3Font 602 // class SkPDFType3Font
705 /////////////////////////////////////////////////////////////////////////////// 603 ///////////////////////////////////////////////////////////////////////////////
706 604
707 namespace { 605 namespace {
708 // returns [0, first, first+1, ... last-1, last] 606 // returns [0, first, first+1, ... last-1, last]
709 struct SingleByteGlyphIdIterator { 607 struct SingleByteGlyphIdIterator {
(...skipping 21 matching lines...) Expand all
731 private: 629 private:
732 const SkGlyphID fFirst; 630 const SkGlyphID fFirst;
733 const SkGlyphID fLast; 631 const SkGlyphID fLast;
734 }; 632 };
735 } 633 }
736 634
737 static void add_type3_font_info(SkPDFCanon* canon, 635 static void add_type3_font_info(SkPDFCanon* canon,
738 SkPDFDict* font, 636 SkPDFDict* font,
739 SkTypeface* typeface, 637 SkTypeface* typeface,
740 SkScalar emSize, 638 SkScalar emSize,
741 const SkPDFGlyphSet* subset, 639 const SkBitSet& subset,
742 SkGlyphID firstGlyphID, 640 SkGlyphID firstGlyphID,
743 SkGlyphID lastGlyphID) { 641 SkGlyphID lastGlyphID) {
744 SkASSERT(lastGlyphID >= firstGlyphID); 642 SkASSERT(lastGlyphID >= firstGlyphID);
745 SkASSERT(emSize > 0.0f); 643 SkASSERT(emSize > 0.0f);
746 SkAutoGlyphCache cache = vector_cache(typeface, emSize); 644 SkAutoGlyphCache cache = vector_cache(typeface, emSize);
747 font->insertName("Subtype", "Type3"); 645 font->insertName("Subtype", "Type3");
748 // Flip about the x-axis and scale by 1/emSize. 646 // Flip about the x-axis and scale by 1/emSize.
749 SkMatrix fontMatrix; 647 SkMatrix fontMatrix;
750 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize)); 648 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
751 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix)); 649 font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));
(...skipping 11 matching lines...) Expand all
763 encDiffs->reserve(glyphCount + 1); 661 encDiffs->reserve(glyphCount + 1);
764 encDiffs->appendInt(0); // index of first glyph 662 encDiffs->appendInt(0); // index of first glyph
765 663
766 auto widthArray = sk_make_sp<SkPDFArray>(); 664 auto widthArray = sk_make_sp<SkPDFArray>();
767 widthArray->reserve(glyphCount); 665 widthArray->reserve(glyphCount);
768 666
769 SkIRect bbox = SkIRect::MakeEmpty(); 667 SkIRect bbox = SkIRect::MakeEmpty();
770 668
771 sk_sp<SkPDFStream> emptyStream; 669 sk_sp<SkPDFStream> emptyStream;
772 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { 670 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
773 bool skipGlyph = subset && gID != 0 && !subset->has(gID); 671 bool skipGlyph = gID != 0 && !subset.has(gID);
774 SkString characterName; 672 SkString characterName;
775 SkScalar advance = 0.0f; 673 SkScalar advance = 0.0f;
776 SkIRect glyphBBox; 674 SkIRect glyphBBox;
777 if (skipGlyph) { 675 if (skipGlyph) {
778 characterName.set("g0"); 676 characterName.set("g0");
779 } else { 677 } else {
780 characterName.printf("g%X", gID); 678 characterName.printf("g%X", gID);
781 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); 679 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
782 advance = SkFloatToScalar(glyph.fAdvanceX); 680 advance = SkFloatToScalar(glyph.fAdvanceX);
783 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, 681 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 fontBBox->appendInt(bbox.left()); 718 fontBBox->appendInt(bbox.left());
821 fontBBox->appendInt(bbox.bottom()); 719 fontBBox->appendInt(bbox.bottom());
822 fontBBox->appendInt(bbox.right()); 720 fontBBox->appendInt(bbox.right());
823 fontBBox->appendInt(bbox.top()); 721 fontBBox->appendInt(bbox.top());
824 font->insertObject("FontBBox", std::move(fontBBox)); 722 font->insertObject("FontBBox", std::move(fontBBox));
825 font->insertName("CIDToGIDMap", "Identity"); 723 font->insertName("CIDToGIDMap", "Identity");
826 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c anon); 724 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c anon);
827 if (metrics /* && metrics->fGlyphToUnicode.count() > 0 */) { 725 if (metrics /* && metrics->fGlyphToUnicode.count() > 0 */) {
828 font->insertObjRef("ToUnicode", 726 font->insertObjRef("ToUnicode",
829 SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, 727 SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode,
830 subset, 728 &subset,
831 false, 729 false,
832 firstGlyphID, 730 firstGlyphID,
833 lastGlyphID)); 731 lastGlyphID));
834 } 732 }
835 font->insertObject("Widths", std::move(widthArray)); 733 font->insertObject("Widths", std::move(widthArray));
836 font->insertObject("Encoding", std::move(encoding)); 734 font->insertObject("Encoding", std::move(encoding));
837 font->insertObject("CharProcs", std::move(charProcs)); 735 font->insertObject("CharProcs", std::move(charProcs));
838 } 736 }
839 737
840 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics& info, 738 SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info,
841 sk_sp<SkTypeface> typeface, 739 const SkAdvancedTypefaceMetrics& metrics)
842 SkAdvancedTypefaceMetrics::FontType fontType, 740 : SkPDFFont(std::move(info)) {}
843 uint16_t glyphID)
844 : SkPDFFont(std::move(typeface), fontType) {
845 this->adjustGlyphRangeForSingleByteEncoding(glyphID);
846 }
847 741
848 sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(SkPDFCanon* canon, 742 void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) {
849 const SkPDFGlyphSet* usage) {
850 // All fonts are subset before serialization.
851 // TODO(halcanary): all fonts should follow this pattern.
852 const SkAdvancedTypefaceMetrics* info = 743 const SkAdvancedTypefaceMetrics* info =
853 SkPDFFont::GetMetrics(this->typeface(), canon); 744 SkPDFFont::GetMetrics(this->typeface(), canon);
854 SkASSERT(info); 745 SkASSERT(info);
855 uint16_t emSize = info->fEmSize > 0 ? info->fEmSize : 1000; 746 uint16_t emSize = info->fEmSize > 0 ? info->fEmSize : 1000;
856 auto font = sk_make_sp<SkPDFDict>("Font"); 747 add_type3_font_info(canon, this, this->typeface(), (SkScalar)emSize,
857 add_type3_font_info(canon, font.get(), this->typeface(), (SkScalar)emSize, u sage, 748 this->glyphUsage(),
858 this->firstGlyphID(), this->lastGlyphID()); 749 this->firstGlyphID(), this->lastGlyphID());
859 return font;
860 } 750 }
861 751
862
863 //////////////////////////////////////////////////////////////////////////////// 752 ////////////////////////////////////////////////////////////////////////////////
864 753
865 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { 754 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) {
866 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c anon); 755 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, c anon);
867 return metrics && can_embed(*metrics); 756 return metrics && can_embed(*metrics);
868 } 757 }
869 758
870 void SkPDFFont::drop() { 759 void SkPDFFont::drop() {
871 fTypeface = nullptr; 760 fTypeface = nullptr;
872 this->SkPDFDict::drop(); 761 this->SkPDFDict::drop();
873 } 762 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFFont.h ('k') | src/pdf/SkPDFGraphicState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698