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

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

Issue 2221163002: SkPDF: SkPDFFont organization changes. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 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/SkPDFFontImpl.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 <ctype.h> 8 #include <ctype.h>
9 9
10 #include "SkData.h" 10 #include "SkData.h"
11 #include "SkGlyphCache.h" 11 #include "SkGlyphCache.h"
12 #include "SkPaint.h" 12 #include "SkPaint.h"
13 #include "SkPDFCanon.h" 13 #include "SkPDFCanon.h"
14 #include "SkPDFConvertType1FontStream.h"
14 #include "SkPDFDevice.h" 15 #include "SkPDFDevice.h"
16 #include "SkPDFMakeToUnicodeCmap.h"
15 #include "SkPDFFont.h" 17 #include "SkPDFFont.h"
16 #include "SkPDFFontImpl.h"
17 #include "SkPDFUtils.h" 18 #include "SkPDFUtils.h"
18 #include "SkRefCnt.h" 19 #include "SkRefCnt.h"
19 #include "SkScalar.h" 20 #include "SkScalar.h"
20 #include "SkStream.h" 21 #include "SkStream.h"
21 #include "SkTypefacePriv.h" 22 #include "SkTypefacePriv.h"
22 #include "SkTypes.h" 23 #include "SkTypes.h"
23 #include "SkUtils.h" 24 #include "SkUtils.h"
24 25
25 #if defined (SK_SFNTLY_SUBSETTER) 26 #if defined (SK_SFNTLY_SUBSETTER)
26 #if defined (GOOGLE3) 27 #if defined (GOOGLE3)
27 // #including #defines doesn't work with this build system. 28 // #including #defines doesn't work with this build system.
28 #include "typography/font/sfntly/src/sample/chromium/font_subsetter.h" 29 #include "typography/font/sfntly/src/sample/chromium/font_subsetter.h"
29 #else 30 #else
30 #include SK_SFNTLY_SUBSETTER 31 #include SK_SFNTLY_SUBSETTER
31 #endif 32 #endif
32 #endif 33 #endif
33 34
35 namespace {
36
34 // PDF's notion of symbolic vs non-symbolic is related to the character set, not 37 // PDF's notion of symbolic vs non-symbolic is related to the character set, not
35 // symbols vs. characters. Rarely is a font the right character set to call it 38 // symbols vs. characters. Rarely is a font the right character set to call it
36 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) 39 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1)
37 static const int kPdfSymbolic = 4; 40 static const int kPdfSymbolic = 4;
38 41
39 struct AdvanceMetric { 42 struct AdvanceMetric {
40 enum MetricType { 43 enum MetricType {
41 kDefault, // Default advance: fAdvance.count = 1 44 kDefault, // Default advance: fAdvance.count = 1
42 kRange, // Advances for a range: fAdvance.count = fEndID-fStartID 45 kRange, // Advances for a range: fAdvance.count = fEndID-fStartID
43 kRun // fStartID-fEndID have same advance: fAdvance.count = 1 46 kRun // fStartID-fEndID have same advance: fAdvance.count = 1
44 }; 47 };
45 MetricType fType; 48 MetricType fType;
46 uint16_t fStartId; 49 uint16_t fStartId;
47 uint16_t fEndId; 50 uint16_t fEndId;
48 SkTDArray<int16_t> fAdvance; 51 SkTDArray<int16_t> fAdvance;
49 AdvanceMetric(uint16_t startId) : fStartId(startId) {} 52 AdvanceMetric(uint16_t startId) : fStartId(startId) {}
50 AdvanceMetric(AdvanceMetric&&) = default; 53 AdvanceMetric(AdvanceMetric&&) = default;
51 AdvanceMetric& operator=(AdvanceMetric&& other) = default; 54 AdvanceMetric& operator=(AdvanceMetric&& other) = default;
52 AdvanceMetric(const AdvanceMetric&) = delete; 55 AdvanceMetric(const AdvanceMetric&) = delete;
53 AdvanceMetric& operator=(const AdvanceMetric&) = delete; 56 AdvanceMetric& operator=(const AdvanceMetric&) = delete;
54 }; 57 };
55 58
56 namespace { 59 class SkPDFType0Font final : public SkPDFFont {
60 public:
61 SkPDFType0Font(const SkAdvancedTypefaceMetrics* info,
62 SkTypeface* typeface);
63 virtual ~SkPDFType0Font();
64 bool multiByteGlyphs() const override { return true; }
65 SkPDFFont* getFontSubset(const SkPDFGlyphSet* usage) override;
66 #ifdef SK_DEBUG
bungeman-skia 2016/08/09 14:36:43 It's really hard to see these ifdefs. I'd be fine
hal.canary 2016/08/09 16:13:38 Done.
67 void emitObject(SkWStream*,
68 const SkPDFObjNumMap&,
69 const SkPDFSubstituteMap&) const override;
70 #endif
71
72 private:
73 #ifdef SK_DEBUG
74 bool fPopulated;
75 #endif
76 bool populate(const SkPDFGlyphSet* subset);
77 typedef SkPDFDict INHERITED;
78 };
79
80 class SkPDFCIDFont final : public SkPDFFont {
81 public:
82 SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info,
83 SkTypeface* typeface,
84 const SkPDFGlyphSet* subset);
85 virtual ~SkPDFCIDFont();
86 bool multiByteGlyphs() const override { return true; }
87
88 private:
89 bool populate(const SkPDFGlyphSet* subset);
90 bool addFontDescriptor(int16_t defaultWidth,
91 const SkTDArray<uint32_t>* subset);
92 };
93
94 class SkPDFType1Font final : public SkPDFFont {
95 public:
96 SkPDFType1Font(const SkAdvancedTypefaceMetrics* info,
97 SkTypeface* typeface,
98 uint16_t glyphID,
99 SkPDFDict* relatedFontDescriptor);
100 virtual ~SkPDFType1Font();
101 bool multiByteGlyphs() const override { return false; }
102
103 private:
104 bool populate(int16_t glyphID);
105 bool addFontDescriptor(int16_t defaultWidth);
106 };
107
108 class SkPDFType3Font final : public SkPDFFont {
109 public:
110 SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
111 SkTypeface* typeface,
112 uint16_t glyphID);
113 virtual ~SkPDFType3Font();
114 bool multiByteGlyphs() const override { return false; }
115
116 private:
117 bool populate(uint16_t glyphID);
118 };
57 119
58 /////////////////////////////////////////////////////////////////////////////// 120 ///////////////////////////////////////////////////////////////////////////////
59 // File-Local Functions 121 // File-Local Functions
60 /////////////////////////////////////////////////////////////////////////////// 122 ///////////////////////////////////////////////////////////////////////////////
61 123
62 const int16_t kInvalidAdvance = SK_MinS16; 124 const int16_t kInvalidAdvance = SK_MinS16;
63 const int16_t kDontCareAdvance = SK_MinS16 + 1; 125 const int16_t kDontCareAdvance = SK_MinS16 + 1;
64 126
65 static void stripUninterestingTrailingAdvancesFromRange( 127 static void stripUninterestingTrailingAdvancesFromRange(
66 AdvanceMetric* range) { 128 AdvanceMetric* range) {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 } 315 }
254 } else { 316 } else {
255 FinishRange(&curRange, lastIndex - 1, AdvanceMetric::kRange); 317 FinishRange(&curRange, lastIndex - 1, AdvanceMetric::kRange);
256 glyphWidths->emplace_back(std::move(curRange)); 318 glyphWidths->emplace_back(std::move(curRange));
257 } 319 }
258 } 320 }
259 321
260 //////////////////////////////////////////////////////////////////////////////// 322 ////////////////////////////////////////////////////////////////////////////////
261 323
262 324
263 bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType,
264 size_t* size) {
265 // PFB sections have a two or six bytes header. 0x80 and a one byte
266 // section type followed by a four byte section length. Type one is
267 // an ASCII section (includes a length), type two is a binary section
268 // (includes a length) and type three is an EOF marker with no length.
269 const uint8_t* buf = *src;
270 if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) {
271 return false;
272 } else if (buf[1] == 3) {
273 return true;
274 } else if (*len < 6) {
275 return false;
276 }
277
278 *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) |
279 ((size_t)buf[5] << 24);
280 size_t consumed = *size + 6;
281 if (consumed > *len) {
282 return false;
283 }
284 *src = *src + consumed;
285 *len = *len - consumed;
286 return true;
287 }
288
289 bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen,
290 size_t* dataLen, size_t* trailerLen) {
291 const uint8_t* srcPtr = src;
292 size_t remaining = size;
293
294 return parsePFBSection(&srcPtr, &remaining, 1, headerLen) &&
295 parsePFBSection(&srcPtr, &remaining, 2, dataLen) &&
296 parsePFBSection(&srcPtr, &remaining, 1, trailerLen) &&
297 parsePFBSection(&srcPtr, &remaining, 3, nullptr);
298 }
299
300 /* The sections of a PFA file are implicitly defined. The body starts
301 * after the line containing "eexec," and the trailer starts with 512
302 * literal 0's followed by "cleartomark" (plus arbitrary white space).
303 *
304 * This function assumes that src is NUL terminated, but the NUL
305 * termination is not included in size.
306 *
307 */
308 bool parsePFA(const char* src, size_t size, size_t* headerLen,
309 size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) {
310 const char* end = src + size;
311
312 const char* dataPos = strstr(src, "eexec");
313 if (!dataPos) {
314 return false;
315 }
316 dataPos += strlen("eexec");
317 while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') &&
318 dataPos < end) {
319 dataPos++;
320 }
321 *headerLen = dataPos - src;
322
323 const char* trailerPos = strstr(dataPos, "cleartomark");
324 if (!trailerPos) {
325 return false;
326 }
327 int zeroCount = 0;
328 for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) {
329 if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') {
330 continue;
331 } else if (*trailerPos == '0') {
332 zeroCount++;
333 } else {
334 return false;
335 }
336 }
337 if (zeroCount != 512) {
338 return false;
339 }
340
341 *hexDataLen = trailerPos - src - *headerLen;
342 *trailerLen = size - *headerLen - *hexDataLen;
343
344 // Verify that the data section is hex encoded and count the bytes.
345 int nibbles = 0;
346 for (; dataPos < trailerPos; dataPos++) {
347 if (isspace(*dataPos)) {
348 continue;
349 }
350 if (!isxdigit(*dataPos)) {
351 return false;
352 }
353 nibbles++;
354 }
355 *dataLen = (nibbles + 1) / 2;
356
357 return true;
358 }
359
360 int8_t hexToBin(uint8_t c) {
361 if (!isxdigit(c)) {
362 return -1;
363 } else if (c <= '9') {
364 return c - '0';
365 } else if (c <= 'F') {
366 return c - 'A' + 10;
367 } else if (c <= 'f') {
368 return c - 'a' + 10;
369 }
370 return -1;
371 }
372
373 static sk_sp<SkData> handle_type1_stream(SkStream* srcStream, size_t* headerLen,
374 size_t* dataLen, size_t* trailerLen) {
375 // srcStream may be backed by a file or a unseekable fd, so we may not be
376 // able to use skip(), rewind(), or getMemoryBase(). read()ing through
377 // the input only once is doable, but very ugly. Furthermore, it'd be nice
378 // if the data was NUL terminated so that we can use strstr() to search it.
379 // Make as few copies as possible given these constraints.
380 SkDynamicMemoryWStream dynamicStream;
381 std::unique_ptr<SkMemoryStream> staticStream;
382 sk_sp<SkData> data;
383 const uint8_t* src;
384 size_t srcLen;
385 if ((srcLen = srcStream->getLength()) > 0) {
386 staticStream.reset(new SkMemoryStream(srcLen + 1));
387 src = (const uint8_t*)staticStream->getMemoryBase();
388 if (srcStream->getMemoryBase() != nullptr) {
389 memcpy((void *)src, srcStream->getMemoryBase(), srcLen);
390 } else {
391 size_t read = 0;
392 while (read < srcLen) {
393 size_t got = srcStream->read((void *)staticStream->getAtPos(),
394 srcLen - read);
395 if (got == 0) {
396 return nullptr;
397 }
398 read += got;
399 staticStream->seek(read);
400 }
401 }
402 ((uint8_t *)src)[srcLen] = 0;
403 } else {
404 static const size_t kBufSize = 4096;
405 uint8_t buf[kBufSize];
406 size_t amount;
407 while ((amount = srcStream->read(buf, kBufSize)) > 0) {
408 dynamicStream.write(buf, amount);
409 }
410 amount = 0;
411 dynamicStream.write(&amount, 1); // nullptr terminator.
412 data.reset(dynamicStream.copyToData());
413 src = data->bytes();
414 srcLen = data->size() - 1;
415 }
416
417 if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
418 static const int kPFBSectionHeaderLength = 6;
419 const size_t length = *headerLen + *dataLen + *trailerLen;
420 SkASSERT(length > 0);
421 SkASSERT(length + (2 * kPFBSectionHeaderLength) <= srcLen);
422
423 sk_sp<SkData> data(SkData::MakeUninitialized(length));
424
425 const uint8_t* const srcHeader = src + kPFBSectionHeaderLength;
426 // There is a six-byte section header before header and data
427 // (but not trailer) that we're not going to copy.
428 const uint8_t* const srcData = srcHeader + *headerLen + kPFBSectionHeade rLength;
429 const uint8_t* const srcTrailer = srcData + *headerLen;
430
431 uint8_t* const resultHeader = (uint8_t*)data->writable_data();
432 uint8_t* const resultData = resultHeader + *headerLen;
433 uint8_t* const resultTrailer = resultData + *dataLen;
434
435 SkASSERT(resultTrailer + *trailerLen == resultHeader + length);
436
437 memcpy(resultHeader, srcHeader, *headerLen);
438 memcpy(resultData, srcData, *dataLen);
439 memcpy(resultTrailer, srcTrailer, *trailerLen);
440
441 return data;
442 }
443
444 // A PFA has to be converted for PDF.
445 size_t hexDataLen;
446 if (parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen,
447 trailerLen)) {
448 const size_t length = *headerLen + *dataLen + *trailerLen;
449 SkASSERT(length > 0);
450 SkAutoTMalloc<uint8_t> buffer(length);
451
452 memcpy(buffer.get(), src, *headerLen);
453 uint8_t* const resultData = &(buffer[SkToInt(*headerLen)]);
454
455 const uint8_t* hexData = src + *headerLen;
456 const uint8_t* trailer = hexData + hexDataLen;
457 size_t outputOffset = 0;
458 uint8_t dataByte = 0; // To hush compiler.
459 bool highNibble = true;
460 for (; hexData < trailer; hexData++) {
461 int8_t curNibble = hexToBin(*hexData);
462 if (curNibble < 0) {
463 continue;
464 }
465 if (highNibble) {
466 dataByte = curNibble << 4;
467 highNibble = false;
468 } else {
469 dataByte |= curNibble;
470 highNibble = true;
471 resultData[outputOffset++] = dataByte;
472 }
473 }
474 if (!highNibble) {
475 resultData[outputOffset++] = dataByte;
476 }
477 SkASSERT(outputOffset == *dataLen);
478
479 uint8_t* const resultTrailer = &(buffer[SkToInt(*headerLen + outputOffse t)]);
480 memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
481
482 return SkData::MakeFromMalloc(buffer.release(), length);
483 }
484 return nullptr;
485 }
486
487 // scale from em-units to base-1000, returning as a SkScalar 325 // scale from em-units to base-1000, returning as a SkScalar
488 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { 326 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
489 SkScalar scaled = SkIntToScalar(val); 327 SkScalar scaled = SkIntToScalar(val);
490 if (emSize == 1000) { 328 if (emSize == 1000) {
491 return scaled; 329 return scaled;
492 } else { 330 } else {
493 return SkScalarMulDiv(scaled, 1000, emSize); 331 return SkScalarMulDiv(scaled, 1000, emSize);
494 } 332 }
495 } 333 }
496 334
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 scaleFromFontUnits(range.fAdvance[0], emSize)); 386 scaleFromFontUnits(range.fAdvance[0], emSize));
549 break; 387 break;
550 } 388 }
551 } 389 }
552 } 390 }
553 return result; 391 return result;
554 } 392 }
555 393
556 } // namespace 394 } // namespace
557 395
558 static void append_tounicode_header(SkDynamicMemoryWStream* cmap,
559 uint16_t firstGlyphID,
560 uint16_t lastGlyphID) {
561 // 12 dict begin: 12 is an Adobe-suggested value. Shall not change.
562 // It's there to prevent old version Adobe Readers from malfunctioning.
563 const char* kHeader =
564 "/CIDInit /ProcSet findresource begin\n"
565 "12 dict begin\n"
566 "begincmap\n";
567 cmap->writeText(kHeader);
568
569 // The /CIDSystemInfo must be consistent to the one in
570 // SkPDFFont::populateCIDFont().
571 // We can not pass over the system info object here because the format is
572 // different. This is not a reference object.
573 const char* kSysInfo =
574 "/CIDSystemInfo\n"
575 "<< /Registry (Adobe)\n"
576 "/Ordering (UCS)\n"
577 "/Supplement 0\n"
578 ">> def\n";
579 cmap->writeText(kSysInfo);
580
581 // The CMapName must be consistent to /CIDSystemInfo above.
582 // /CMapType 2 means ToUnicode.
583 // Codespace range just tells the PDF processor the valid range.
584 const char* kTypeInfoHeader =
585 "/CMapName /Adobe-Identity-UCS def\n"
586 "/CMapType 2 def\n"
587 "1 begincodespacerange\n";
588 cmap->writeText(kTypeInfoHeader);
589
590 // e.g. "<0000> <FFFF>\n"
591 SkString range;
592 range.appendf("<%04X> <%04X>\n", firstGlyphID, lastGlyphID);
593 cmap->writeText(range.c_str());
594
595 const char* kTypeInfoFooter = "endcodespacerange\n";
596 cmap->writeText(kTypeInfoFooter);
597 }
598
599 static void append_cmap_footer(SkDynamicMemoryWStream* cmap) {
600 const char* kFooter =
601 "endcmap\n"
602 "CMapName currentdict /CMap defineresource pop\n"
603 "end\n"
604 "end";
605 cmap->writeText(kFooter);
606 }
607
608 struct BFChar {
609 uint16_t fGlyphId;
610 SkUnichar fUnicode;
611 };
612
613 struct BFRange {
614 uint16_t fStart;
615 uint16_t fEnd;
616 SkUnichar fUnicode;
617 };
618
619 static void write_utf16be(SkDynamicMemoryWStream* wStream, SkUnichar utf32) {
620 uint16_t utf16[2] = {0, 0};
621 size_t len = SkUTF16_FromUnichar(utf32, utf16);
622 SkASSERT(len == 1 || len == 2);
623 SkPDFUtils::WriteUInt16BE(wStream, utf16[0]);
624 if (len == 2) {
625 SkPDFUtils::WriteUInt16BE(wStream, utf16[1]);
626 }
627 }
628
629 static void append_bfchar_section(const SkTDArray<BFChar>& bfchar,
630 SkDynamicMemoryWStream* cmap) {
631 // PDF spec defines that every bf* list can have at most 100 entries.
632 for (int i = 0; i < bfchar.count(); i += 100) {
633 int count = bfchar.count() - i;
634 count = SkMin32(count, 100);
635 cmap->writeDecAsText(count);
636 cmap->writeText(" beginbfchar\n");
637 for (int j = 0; j < count; ++j) {
638 cmap->writeText("<");
639 SkPDFUtils::WriteUInt16BE(cmap, bfchar[i + j].fGlyphId);
640 cmap->writeText("> <");
641 write_utf16be(cmap, bfchar[i + j].fUnicode);
642 cmap->writeText(">\n");
643 }
644 cmap->writeText("endbfchar\n");
645 }
646 }
647
648 static void append_bfrange_section(const SkTDArray<BFRange>& bfrange,
649 SkDynamicMemoryWStream* cmap) {
650 // PDF spec defines that every bf* list can have at most 100 entries.
651 for (int i = 0; i < bfrange.count(); i += 100) {
652 int count = bfrange.count() - i;
653 count = SkMin32(count, 100);
654 cmap->writeDecAsText(count);
655 cmap->writeText(" beginbfrange\n");
656 for (int j = 0; j < count; ++j) {
657 cmap->writeText("<");
658 SkPDFUtils::WriteUInt16BE(cmap, bfrange[i + j].fStart);
659 cmap->writeText("> <");
660 SkPDFUtils::WriteUInt16BE(cmap, bfrange[i + j].fEnd);
661 cmap->writeText("> <");
662 write_utf16be(cmap, bfrange[i + j].fUnicode);
663 cmap->writeText(">\n");
664 }
665 cmap->writeText("endbfrange\n");
666 }
667 }
668
669 // Generate <bfchar> and <bfrange> table according to PDF spec 1.4 and Adobe
670 // Technote 5014.
671 // The function is not static so we can test it in unit tests.
672 //
673 // Current implementation guarantees bfchar and bfrange entries do not overlap.
674 //
675 // Current implementation does not attempt aggresive optimizations against
676 // following case because the specification is not clear.
677 //
678 // 4 beginbfchar 1 beginbfchar
679 // <0003> <0013> <0020> <0014>
680 // <0005> <0015> to endbfchar
681 // <0007> <0017> 1 beginbfrange
682 // <0020> <0014> <0003> <0007> <0013>
683 // endbfchar endbfrange
684 //
685 // Adobe Technote 5014 said: "Code mappings (unlike codespace ranges) may
686 // overlap, but succeeding maps supersede preceding maps."
687 //
688 // In case of searching text in PDF, bfrange will have higher precedence so
689 // typing char id 0x0014 in search box will get glyph id 0x0004 first. However,
690 // the spec does not mention how will this kind of conflict being resolved.
691 //
692 // For the worst case (having 65536 continuous unicode and we use every other
693 // one of them), the possible savings by aggressive optimization is 416KB
694 // pre-compressed and does not provide enough motivation for implementation.
695
696 // TODO(halcanary): this should be in a header so that it is separately testable
697 // ( see caller in tests/ToUnicode.cpp )
698 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
699 const SkPDFGlyphSet* subset,
700 SkDynamicMemoryWStream* cmap,
701 bool multiByteGlyphs,
702 uint16_t firstGlyphID,
703 uint16_t lastGlyphID);
704
705 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
706 const SkPDFGlyphSet* subset,
707 SkDynamicMemoryWStream* cmap,
708 bool multiByteGlyphs,
709 uint16_t firstGlyphID,
710 uint16_t lastGlyphID) {
711 if (glyphToUnicode.isEmpty()) {
712 return;
713 }
714 int glyphOffset = 0;
715 if (!multiByteGlyphs) {
716 glyphOffset = firstGlyphID - 1;
717 }
718
719 SkTDArray<BFChar> bfcharEntries;
720 SkTDArray<BFRange> bfrangeEntries;
721
722 BFRange currentRangeEntry = {0, 0, 0};
723 bool rangeEmpty = true;
724 const int limit =
725 SkMin32(lastGlyphID + 1, glyphToUnicode.count()) - glyphOffset;
726
727 for (int i = firstGlyphID - glyphOffset; i < limit + 1; ++i) {
728 bool inSubset = i < limit &&
729 (subset == nullptr || subset->has(i + glyphOffset));
730 if (!rangeEmpty) {
731 // PDF spec requires bfrange not changing the higher byte,
732 // e.g. <1035> <10FF> <2222> is ok, but
733 // <1035> <1100> <2222> is no good
734 bool inRange =
735 i == currentRangeEntry.fEnd + 1 &&
736 i >> 8 == currentRangeEntry.fStart >> 8 &&
737 i < limit &&
738 glyphToUnicode[i + glyphOffset] ==
739 currentRangeEntry.fUnicode + i - currentRangeEntry.fStart;
740 if (!inSubset || !inRange) {
741 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) {
742 bfrangeEntries.push(currentRangeEntry);
743 } else {
744 BFChar* entry = bfcharEntries.append();
745 entry->fGlyphId = currentRangeEntry.fStart;
746 entry->fUnicode = currentRangeEntry.fUnicode;
747 }
748 rangeEmpty = true;
749 }
750 }
751 if (inSubset) {
752 currentRangeEntry.fEnd = i;
753 if (rangeEmpty) {
754 currentRangeEntry.fStart = i;
755 currentRangeEntry.fUnicode = glyphToUnicode[i + glyphOffset];
756 rangeEmpty = false;
757 }
758 }
759 }
760
761 // The spec requires all bfchar entries for a font must come before bfrange
762 // entries.
763 append_bfchar_section(bfcharEntries, cmap);
764 append_bfrange_section(bfrangeEntries, cmap);
765 }
766
767 static sk_sp<SkPDFStream> generate_tounicode_cmap(
768 const SkTDArray<SkUnichar>& glyphToUnicode,
769 const SkPDFGlyphSet* subset,
770 bool multiByteGlyphs,
771 uint16_t firstGlyphID,
772 uint16_t lastGlyphID) {
773 SkDynamicMemoryWStream cmap;
774 if (multiByteGlyphs) {
775 append_tounicode_header(&cmap, firstGlyphID, lastGlyphID);
776 } else {
777 append_tounicode_header(&cmap, 1, lastGlyphID - firstGlyphID + 1);
778 }
779 append_cmap_sections(glyphToUnicode, subset, &cmap, multiByteGlyphs,
780 firstGlyphID, lastGlyphID);
781 append_cmap_footer(&cmap);
782 return sk_make_sp<SkPDFStream>(
783 std::unique_ptr<SkStreamAsset>(cmap.detachAsStream()));
784 }
785 396
786 /////////////////////////////////////////////////////////////////////////////// 397 ///////////////////////////////////////////////////////////////////////////////
787 // class SkPDFGlyphSet 398 // class SkPDFGlyphSet
788 /////////////////////////////////////////////////////////////////////////////// 399 ///////////////////////////////////////////////////////////////////////////////
789 400
790 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { 401 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) {
791 } 402 }
792 403
793 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { 404 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) {
794 for (int i = 0; i < numGlyphs; ++i) { 405 for (int i = 0; i < numGlyphs; ++i) {
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 if (fLastGlyphID > fFirstGlyphID + 255 - 1) { 673 if (fLastGlyphID > fFirstGlyphID + 255 - 1) {
1063 fLastGlyphID = fFirstGlyphID + 255 - 1; 674 fLastGlyphID = fFirstGlyphID + 255 - 1;
1064 } 675 }
1065 } 676 }
1066 677
1067 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { 678 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) {
1068 if (fFontInfo == nullptr || fFontInfo->fGlyphToUnicode.begin() == nullptr) { 679 if (fFontInfo == nullptr || fFontInfo->fGlyphToUnicode.begin() == nullptr) {
1069 return; 680 return;
1070 } 681 }
1071 this->insertObjRef("ToUnicode", 682 this->insertObjRef("ToUnicode",
1072 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, 683 SkPDFMakeToUnicodeCmap(fFontInfo->fGlyphToUnicode,
1073 subset, 684 subset,
1074 multiByteGlyphs(), 685 multiByteGlyphs(),
1075 firstGlyphID(), 686 firstGlyphID(),
1076 lastGlyphID())); 687 lastGlyphID()));
1077 } 688 }
1078 689
1079 /////////////////////////////////////////////////////////////////////////////// 690 ///////////////////////////////////////////////////////////////////////////////
1080 // class SkPDFType0Font 691 // class SkPDFType0Font
1081 /////////////////////////////////////////////////////////////////////////////// 692 ///////////////////////////////////////////////////////////////////////////////
1082 693
1083 SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface * typeface) 694 SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface * typeface)
1084 : SkPDFFont(info, typeface, nullptr) { 695 : SkPDFFont(info, typeface, nullptr) {
1085 SkDEBUGCODE(fPopulated = false); 696 SkDEBUGCODE(fPopulated = false);
1086 if (!canSubset()) { 697 if (!canSubset()) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm()); 878 tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm());
1268 SkAutoGlyphCache autoGlyphCache(tmpPaint, nullptr, nullptr); 879 SkAutoGlyphCache autoGlyphCache(tmpPaint, nullptr, nullptr);
1269 if (!glyphIDs || glyphIDs->isEmpty()) { 880 if (!glyphIDs || glyphIDs->isEmpty()) {
1270 get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get( )); 881 get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get( ));
1271 } else { 882 } else {
1272 get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(), 883 get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(),
1273 glyphIDs->count(), autoGlyphCache.get()); 884 glyphIDs->count(), autoGlyphCache.get());
1274 } 885 }
1275 } 886 }
1276 887
888 sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithGlyphNames(
889 SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) {
890 return sk_sp<const SkAdvancedTypefaceMetrics>(
891 typeface->getAdvancedTypefaceMetrics(
892 SkTypeface::kGlyphNames_PerGlyphInfo, glyphs, glyphsCount));
893 }
894
895 sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithToUnicode(
896 SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) {
897 return sk_sp<const SkAdvancedTypefaceMetrics>(
898 typeface->getAdvancedTypefaceMetrics(
899 SkTypeface::kToUnicode_PerGlyphInfo, glyphs, glyphsCount));
900 }
901
1277 bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { 902 bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) {
1278 // Generate new font metrics with advance info for true type fonts. 903 // Generate new font metrics with advance info for true type fonts.
1279 // Generate glyph id array. 904 // Generate glyph id array.
1280 SkTDArray<uint32_t> glyphIDs; 905 SkTDArray<uint32_t> glyphIDs;
1281 if (subset) { 906 if (subset) {
1282 if (!subset->has(0)) { 907 if (!subset->has(0)) {
1283 glyphIDs.push(0); // Always include glyph 0. 908 glyphIDs.push(0); // Always include glyph 0.
1284 } 909 }
1285 subset->exportTo(&glyphIDs); 910 subset->exportTo(&glyphIDs);
1286 } 911 }
1287 if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { 912 if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) {
1288 SkTypeface::PerGlyphInfo info = SkTypeface::kGlyphNames_PerGlyphInfo;
1289 uint32_t* glyphs = (glyphIDs.count() == 0) ? nullptr : glyphIDs.begin(); 913 uint32_t* glyphs = (glyphIDs.count() == 0) ? nullptr : glyphIDs.begin();
1290 uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; 914 uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0;
1291 sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics( 915 sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics
1292 typeface()->getAdvancedTypefaceMetrics(info, glyphs, glyphsCount)); 916 = SkPDFFont::GetFontMetricsWithGlyphNames(this->typeface(), glyphs, glyphsCount);
1293 setFontInfo(fontMetrics.get()); 917 this->setFontInfo(fontMetrics.get());
1294 addFontDescriptor(0, &glyphIDs); 918 this->addFontDescriptor(0, &glyphIDs);
1295 } else { 919 } else {
1296 // Other CID fonts 920 // Other CID fonts
1297 addFontDescriptor(0, nullptr); 921 addFontDescriptor(0, nullptr);
1298 } 922 }
1299 923
1300 insertName("BaseFont", fontInfo()->fFontName); 924 insertName("BaseFont", fontInfo()->fFontName);
1301 925
1302 if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { 926 if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) {
1303 insertName("Subtype", "CIDFontType0"); 927 insertName("Subtype", "CIDFontType0");
1304 } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) { 928 } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 int ttcIndex; 979 int ttcIndex;
1356 size_t header SK_INIT_TO_AVOID_WARNING; 980 size_t header SK_INIT_TO_AVOID_WARNING;
1357 size_t data SK_INIT_TO_AVOID_WARNING; 981 size_t data SK_INIT_TO_AVOID_WARNING;
1358 size_t trailer SK_INIT_TO_AVOID_WARNING; 982 size_t trailer SK_INIT_TO_AVOID_WARNING;
1359 std::unique_ptr<SkStreamAsset> rawFontData(typeface()->openStream(&ttcIndex) ); 983 std::unique_ptr<SkStreamAsset> rawFontData(typeface()->openStream(&ttcIndex) );
1360 SkASSERT(rawFontData); 984 SkASSERT(rawFontData);
1361 SkASSERT(rawFontData->getLength() > 0); 985 SkASSERT(rawFontData->getLength() > 0);
1362 if (!rawFontData || 0 == rawFontData->getLength()) { 986 if (!rawFontData || 0 == rawFontData->getLength()) {
1363 return false; 987 return false;
1364 } 988 }
1365 sk_sp<SkData> fontData(handle_type1_stream(rawFontData.get(), &header, &data , &trailer)); 989 sk_sp<SkData> fontData(SkPDFConvertType1FontStream(
990 std::move(rawFontData), &header, &data, &trailer));
bungeman-skia 2016/08/09 14:36:43 nit: the indentation here is weird.
hal.canary 2016/08/09 16:13:38 Done.
1366 if (fontData.get() == nullptr) { 991 if (fontData.get() == nullptr) {
1367 return false; 992 return false;
1368 } 993 }
1369 SkASSERT(this->canEmbed()); 994 SkASSERT(this->canEmbed());
1370 auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData)); 995 auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData));
1371 fontStream->dict()->insertInt("Length1", header); 996 fontStream->dict()->insertInt("Length1", header);
1372 fontStream->dict()->insertInt("Length2", data); 997 fontStream->dict()->insertInt("Length2", data);
1373 fontStream->dict()->insertInt("Length3", trailer); 998 fontStream->dict()->insertInt("Length3", trailer);
1374 descriptor->insertObjRef("FontFile", std::move(fontStream)); 999 descriptor->insertObjRef("FontFile", std::move(fontStream));
1375 1000
1376 this->insertObjRef("FontDescriptor", std::move(descriptor)); 1001 this->insertObjRef("FontDescriptor", std::move(descriptor));
1377 1002
1378 return addCommonFontDescriptorEntries(defaultWidth); 1003 return addCommonFontDescriptorEntries(defaultWidth);
1379 } 1004 }
1380 1005
1381 bool SkPDFType1Font::populate(int16_t glyphID) { 1006 bool SkPDFType1Font::populate(int16_t glyphID) {
1007 this->insertName("Subtype", "Type1");
1008 this->insertName("BaseFont", fontInfo()->fFontName);
1382 adjustGlyphRangeForSingleByteEncoding(glyphID); 1009 adjustGlyphRangeForSingleByteEncoding(glyphID);
1010 SkGlyphID firstGlyphID = this->firstGlyphID();
1011 SkGlyphID lastGlyphID = this->lastGlyphID();
1383 1012
1384 int16_t defaultWidth = 0; 1013 // glyphCount not including glyph 0
1385 const AdvanceMetric* widthRangeEntry = nullptr; 1014 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
1015 SkASSERT(glyphCount > 0 && glyphCount <= 255);
1016 this->insertInt("FirstChar", (size_t)0);
1017 this->insertInt("LastChar", (size_t)glyphCount);
1386 { 1018 {
1387 SkSinglyLinkedList<AdvanceMetric> tmpMetrics; 1019 SkPaint tmpPaint;
1388 set_glyph_widths(this->typeface(), nullptr, &tmpMetrics); 1020 tmpPaint.setHinting(SkPaint::kNo_Hinting);
1389 for (const auto& widthEntry : tmpMetrics) { 1021 tmpPaint.setTypeface(sk_ref_sp(this->typeface()));
1390 switch (widthEntry.fType) { 1022 tmpPaint.setTextSize((SkScalar)this->typeface()->getUnitsPerEm());
1391 case AdvanceMetric::kDefault: 1023 SkAutoGlyphCache glyphCache(tmpPaint, nullptr, nullptr);
1392 defaultWidth = widthEntry.fAdvance[0]; 1024 auto widths = sk_make_sp<SkPDFArray>();
1393 break; 1025 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
1394 case AdvanceMetric::kRun: 1026 const uint16_t emSize = this->fontInfo()->fEmSize;
1395 SkASSERT(false); 1027 widths->appendScalar(scaleFromFontUnits(advance, emSize));
1396 break; 1028 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
1397 case AdvanceMetric::kRange: 1029 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
1398 SkASSERT(widthRangeEntry == nullptr); 1030 widths->appendScalar(scaleFromFontUnits(advance, emSize));
1399 widthRangeEntry = &widthEntry;
1400 break;
1401 }
1402 } 1031 }
1032 this->insertObject("Widths", std::move(widths));
1403 } 1033 }
1404 1034 if (!addFontDescriptor(0)) {
1405 if (!addFontDescriptor(defaultWidth)) {
1406 return false; 1035 return false;
1407 } 1036 }
1408
1409 insertName("Subtype", "Type1");
1410 insertName("BaseFont", fontInfo()->fFontName);
1411
1412 addWidthInfoFromRange(defaultWidth, widthRangeEntry);
1413 auto encDiffs = sk_make_sp<SkPDFArray>(); 1037 auto encDiffs = sk_make_sp<SkPDFArray>();
1414 encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); 1038 encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
1415 encDiffs->appendInt(1); 1039 encDiffs->appendInt(0);
1416 SkASSERT(this->fontInfo()->fGlyphNames.count() >= this->lastGlyphID()); 1040 const SkTArray<SkString>& glyphNames = this->fontInfo()->fGlyphNames;
1417 for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { 1041 SkASSERT(glyphNames.count() > lastGlyphID);
1418 encDiffs->appendName(fontInfo()->fGlyphNames[gID].c_str()); 1042 encDiffs->appendName(glyphNames[0].c_str());
1043 const SkString unknown("UNKNOWN");
1044 for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
1045 const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty( );
1046 const SkString& name = valid ? glyphNames[gID] : unknown;
1047 encDiffs->appendName(name);
1419 } 1048 }
1420 1049
1421 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); 1050 auto encoding = sk_make_sp<SkPDFDict>("Encoding");
1422 encoding->insertObject("Differences", std::move(encDiffs)); 1051 encoding->insertObject("Differences", std::move(encDiffs));
1423 this->insertObject("Encoding", std::move(encoding)); 1052 this->insertObject("Encoding", std::move(encoding));
1424 return true; 1053 return true;
1425 } 1054 }
1426 1055
1427 void SkPDFType1Font::addWidthInfoFromRange(
1428 int16_t defaultWidth,
1429 const AdvanceMetric* widthRangeEntry) {
1430 auto widthArray = sk_make_sp<SkPDFArray>();
1431 int firstChar = 0;
1432 if (widthRangeEntry) {
1433 const uint16_t emSize = fontInfo()->fEmSize;
1434 int startIndex = firstGlyphID() - widthRangeEntry->fStartId;
1435 int endIndex = startIndex + lastGlyphID() - firstGlyphID() + 1;
1436 if (startIndex < 0)
1437 startIndex = 0;
1438 if (endIndex > widthRangeEntry->fAdvance.count())
1439 endIndex = widthRangeEntry->fAdvance.count();
1440 if (widthRangeEntry->fStartId == 0) {
1441 widthArray->appendScalar(
1442 scaleFromFontUnits(widthRangeEntry->fAdvance[0], emSize));
1443 } else {
1444 firstChar = startIndex + widthRangeEntry->fStartId;
1445 }
1446 for (int i = startIndex; i < endIndex; i++) {
1447 widthArray->appendScalar(
1448 scaleFromFontUnits(widthRangeEntry->fAdvance[i], emSize));
1449 }
1450 } else {
1451 widthArray->appendScalar(
1452 scaleFromFontUnits(defaultWidth, 1000));
1453 }
1454 this->insertInt("FirstChar", firstChar);
1455 this->insertInt("LastChar", firstChar + widthArray->size() - 1);
1456 this->insertObject("Widths", std::move(widthArray));
1457 }
1458
1459 /////////////////////////////////////////////////////////////////////////////// 1056 ///////////////////////////////////////////////////////////////////////////////
1460 // class SkPDFType3Font 1057 // class SkPDFType3Font
1461 /////////////////////////////////////////////////////////////////////////////// 1058 ///////////////////////////////////////////////////////////////////////////////
1462 1059
1463 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, 1060 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
1464 SkTypeface* typeface, 1061 SkTypeface* typeface,
1465 uint16_t glyphID) 1062 uint16_t glyphID)
1466 : SkPDFFont(info, typeface, nullptr) { 1063 : SkPDFFont(info, typeface, nullptr) {
1467 this->populate(glyphID); 1064 this->populate(glyphID);
1468 } 1065 }
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 } 1175 }
1579 return *canon->fCanEmbedTypeface.set(id, canEmbed); 1176 return *canon->fCanEmbedTypeface.set(id, canEmbed);
1580 } 1177 }
1581 1178
1582 void SkPDFFont::drop() { 1179 void SkPDFFont::drop() {
1583 fTypeface = nullptr; 1180 fTypeface = nullptr;
1584 fFontInfo = nullptr; 1181 fFontInfo = nullptr;
1585 fDescriptor = nullptr; 1182 fDescriptor = nullptr;
1586 this->SkPDFDict::drop(); 1183 this->SkPDFDict::drop();
1587 } 1184 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFFont.h ('k') | src/pdf/SkPDFFontImpl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698