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

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: 2016-08-09 (Tuesday) 15:24:15 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/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>
9
10 #include "SkData.h" 8 #include "SkData.h"
11 #include "SkGlyphCache.h" 9 #include "SkGlyphCache.h"
12 #include "SkPaint.h" 10 #include "SkPaint.h"
13 #include "SkPDFCanon.h" 11 #include "SkPDFCanon.h"
12 #include "SkPDFConvertType1FontStream.h"
14 #include "SkPDFDevice.h" 13 #include "SkPDFDevice.h"
14 #include "SkPDFMakeToUnicodeCmap.h"
15 #include "SkPDFFont.h" 15 #include "SkPDFFont.h"
16 #include "SkPDFFontImpl.h"
17 #include "SkPDFUtils.h" 16 #include "SkPDFUtils.h"
18 #include "SkRefCnt.h" 17 #include "SkRefCnt.h"
19 #include "SkScalar.h" 18 #include "SkScalar.h"
20 #include "SkStream.h" 19 #include "SkStream.h"
21 #include "SkTypefacePriv.h" 20 #include "SkTypefacePriv.h"
22 #include "SkTypes.h" 21 #include "SkTypes.h"
23 #include "SkUtils.h" 22 #include "SkUtils.h"
24 23
25 #if defined (SK_SFNTLY_SUBSETTER) 24 #if defined (SK_SFNTLY_SUBSETTER)
26 #if defined (GOOGLE3) 25 #if defined (GOOGLE3)
27 // #including #defines doesn't work with this build system. 26 // #including #defines doesn't work with this build system.
28 #include "typography/font/sfntly/src/sample/chromium/font_subsetter.h" 27 #include "typography/font/sfntly/src/sample/chromium/font_subsetter.h"
29 #else 28 #else
30 #include SK_SFNTLY_SUBSETTER 29 #include SK_SFNTLY_SUBSETTER
31 #endif 30 #endif
32 #endif 31 #endif
33 32
33 namespace {
34
34 // 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
35 // 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
36 // 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)
37 static const int kPdfSymbolic = 4; 38 static const int kPdfSymbolic = 4;
38 39
39 struct AdvanceMetric { 40 struct AdvanceMetric {
40 enum MetricType { 41 enum MetricType {
41 kDefault, // Default advance: fAdvance.count = 1 42 kDefault, // Default advance: fAdvance.count = 1
42 kRange, // Advances for a range: fAdvance.count = fEndID-fStartID 43 kRange, // Advances for a range: fAdvance.count = fEndID-fStartID
43 kRun // fStartID-fEndID have same advance: fAdvance.count = 1 44 kRun // fStartID-fEndID have same advance: fAdvance.count = 1
44 }; 45 };
45 MetricType fType; 46 MetricType fType;
46 uint16_t fStartId; 47 uint16_t fStartId;
47 uint16_t fEndId; 48 uint16_t fEndId;
48 SkTDArray<int16_t> fAdvance; 49 SkTDArray<int16_t> fAdvance;
49 AdvanceMetric(uint16_t startId) : fStartId(startId) {} 50 AdvanceMetric(uint16_t startId) : fStartId(startId) {}
50 AdvanceMetric(AdvanceMetric&&) = default; 51 AdvanceMetric(AdvanceMetric&&) = default;
51 AdvanceMetric& operator=(AdvanceMetric&& other) = default; 52 AdvanceMetric& operator=(AdvanceMetric&& other) = default;
52 AdvanceMetric(const AdvanceMetric&) = delete; 53 AdvanceMetric(const AdvanceMetric&) = delete;
53 AdvanceMetric& operator=(const AdvanceMetric&) = delete; 54 AdvanceMetric& operator=(const AdvanceMetric&) = delete;
54 }; 55 };
55 56
56 namespace { 57 class SkPDFType0Font final : public SkPDFFont {
58 public:
59 SkPDFType0Font(const SkAdvancedTypefaceMetrics* info,
60 SkTypeface* typeface);
61 virtual ~SkPDFType0Font();
62 bool multiByteGlyphs() const override { return true; }
63 SkPDFFont* getFontSubset(const SkPDFGlyphSet* usage) override;
64 #ifdef SK_DEBUG
65 void emitObject(SkWStream*,
66 const SkPDFObjNumMap&,
67 const SkPDFSubstituteMap&) const override;
68 #endif
69
70 private:
71 #ifdef SK_DEBUG
72 bool fPopulated;
73 #endif
74 bool populate(const SkPDFGlyphSet* subset);
75 typedef SkPDFDict INHERITED;
76 };
77
78 class SkPDFCIDFont final : public SkPDFFont {
79 public:
80 SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info,
81 SkTypeface* typeface,
82 const SkPDFGlyphSet* subset);
83 virtual ~SkPDFCIDFont();
84 bool multiByteGlyphs() const override { return true; }
85
86 private:
87 bool populate(const SkPDFGlyphSet* subset);
88 bool addFontDescriptor(int16_t defaultWidth,
89 const SkTDArray<uint32_t>* subset);
90 };
91
92 class SkPDFType1Font final : public SkPDFFont {
93 public:
94 SkPDFType1Font(const SkAdvancedTypefaceMetrics* info,
95 SkTypeface* typeface,
96 uint16_t glyphID,
97 SkPDFDict* relatedFontDescriptor);
98 virtual ~SkPDFType1Font();
99 bool multiByteGlyphs() const override { return false; }
100
101 private:
102 bool populate(int16_t glyphID);
103 bool addFontDescriptor(int16_t defaultWidth);
104 };
105
106 class SkPDFType3Font final : public SkPDFFont {
107 public:
108 SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
109 SkTypeface* typeface,
110 uint16_t glyphID);
111 virtual ~SkPDFType3Font();
112 bool multiByteGlyphs() const override { return false; }
113
114 private:
115 bool populate(uint16_t glyphID);
116 };
57 117
58 /////////////////////////////////////////////////////////////////////////////// 118 ///////////////////////////////////////////////////////////////////////////////
59 // File-Local Functions 119 // File-Local Functions
60 /////////////////////////////////////////////////////////////////////////////// 120 ///////////////////////////////////////////////////////////////////////////////
61 121
62 const int16_t kInvalidAdvance = SK_MinS16; 122 const int16_t kInvalidAdvance = SK_MinS16;
63 const int16_t kDontCareAdvance = SK_MinS16 + 1; 123 const int16_t kDontCareAdvance = SK_MinS16 + 1;
64 124
65 static void stripUninterestingTrailingAdvancesFromRange( 125 static void stripUninterestingTrailingAdvancesFromRange(
66 AdvanceMetric* range) { 126 AdvanceMetric* range) {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 } 313 }
254 } else { 314 } else {
255 FinishRange(&curRange, lastIndex - 1, AdvanceMetric::kRange); 315 FinishRange(&curRange, lastIndex - 1, AdvanceMetric::kRange);
256 glyphWidths->emplace_back(std::move(curRange)); 316 glyphWidths->emplace_back(std::move(curRange));
257 } 317 }
258 } 318 }
259 319
260 //////////////////////////////////////////////////////////////////////////////// 320 ////////////////////////////////////////////////////////////////////////////////
261 321
262 322
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 323 // scale from em-units to base-1000, returning as a SkScalar
488 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { 324 SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
489 SkScalar scaled = SkIntToScalar(val);
490 if (emSize == 1000) { 325 if (emSize == 1000) {
491 return scaled; 326 return scaled;
492 } else { 327 } else {
493 return SkScalarMulDiv(scaled, 1000, emSize); 328 return SkScalarMulDiv(scaled, 1000, emSize);
494 } 329 }
495 } 330 }
496 331
332 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
333 return from_font_units(SkIntToScalar(val), emSize);
334 }
335
336
497 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, 337 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box,
498 SkWStream* content) { 338 SkWStream* content) {
499 // Specify width and bounding box for the glyph. 339 // Specify width and bounding box for the glyph.
500 SkPDFUtils::AppendScalar(width, content); 340 SkPDFUtils::AppendScalar(width, content);
501 content->writeText(" 0 "); 341 content->writeText(" 0 ");
502 content->writeDecAsText(box.fLeft); 342 content->writeDecAsText(box.fLeft);
503 content->writeText(" "); 343 content->writeText(" ");
504 content->writeDecAsText(box.fTop); 344 content->writeDecAsText(box.fTop);
505 content->writeText(" "); 345 content->writeText(" ");
506 content->writeDecAsText(box.fRight); 346 content->writeDecAsText(box.fRight);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 scaleFromFontUnits(range.fAdvance[0], emSize)); 388 scaleFromFontUnits(range.fAdvance[0], emSize));
549 break; 389 break;
550 } 390 }
551 } 391 }
552 } 392 }
553 return result; 393 return result;
554 } 394 }
555 395
556 } // namespace 396 } // namespace
557 397
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 398
786 /////////////////////////////////////////////////////////////////////////////// 399 ///////////////////////////////////////////////////////////////////////////////
787 // class SkPDFGlyphSet 400 // class SkPDFGlyphSet
788 /////////////////////////////////////////////////////////////////////////////// 401 ///////////////////////////////////////////////////////////////////////////////
789 402
790 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { 403 SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) {
791 } 404 }
792 405
793 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { 406 void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) {
794 for (int i = 0; i < numGlyphs; ++i) { 407 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) { 675 if (fLastGlyphID > fFirstGlyphID + 255 - 1) {
1063 fLastGlyphID = fFirstGlyphID + 255 - 1; 676 fLastGlyphID = fFirstGlyphID + 255 - 1;
1064 } 677 }
1065 } 678 }
1066 679
1067 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { 680 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) {
1068 if (fFontInfo == nullptr || fFontInfo->fGlyphToUnicode.begin() == nullptr) { 681 if (fFontInfo == nullptr || fFontInfo->fGlyphToUnicode.begin() == nullptr) {
1069 return; 682 return;
1070 } 683 }
1071 this->insertObjRef("ToUnicode", 684 this->insertObjRef("ToUnicode",
1072 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, 685 SkPDFMakeToUnicodeCmap(fFontInfo->fGlyphToUnicode,
1073 subset, 686 subset,
1074 multiByteGlyphs(), 687 multiByteGlyphs(),
1075 firstGlyphID(), 688 firstGlyphID(),
1076 lastGlyphID())); 689 lastGlyphID()));
1077 } 690 }
1078 691
1079 /////////////////////////////////////////////////////////////////////////////// 692 ///////////////////////////////////////////////////////////////////////////////
1080 // class SkPDFType0Font 693 // class SkPDFType0Font
1081 /////////////////////////////////////////////////////////////////////////////// 694 ///////////////////////////////////////////////////////////////////////////////
1082 695
1083 SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface * typeface) 696 SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface * typeface)
1084 : SkPDFFont(info, typeface, nullptr) { 697 : SkPDFFont(info, typeface, nullptr) {
1085 SkDEBUGCODE(fPopulated = false); 698 SkDEBUGCODE(fPopulated = false);
1086 if (!canSubset()) { 699 if (!canSubset()) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm()); 880 tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm());
1268 SkAutoGlyphCache autoGlyphCache(tmpPaint, nullptr, nullptr); 881 SkAutoGlyphCache autoGlyphCache(tmpPaint, nullptr, nullptr);
1269 if (!glyphIDs || glyphIDs->isEmpty()) { 882 if (!glyphIDs || glyphIDs->isEmpty()) {
1270 get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get( )); 883 get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get( ));
1271 } else { 884 } else {
1272 get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(), 885 get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(),
1273 glyphIDs->count(), autoGlyphCache.get()); 886 glyphIDs->count(), autoGlyphCache.get());
1274 } 887 }
1275 } 888 }
1276 889
890 sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithGlyphNames(
891 SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) {
892 return sk_sp<const SkAdvancedTypefaceMetrics>(
893 typeface->getAdvancedTypefaceMetrics(
894 SkTypeface::kGlyphNames_PerGlyphInfo, glyphs, glyphsCount));
895 }
896
897 sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithToUnicode(
898 SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) {
899 return sk_sp<const SkAdvancedTypefaceMetrics>(
900 typeface->getAdvancedTypefaceMetrics(
901 SkTypeface::kToUnicode_PerGlyphInfo, glyphs, glyphsCount));
902 }
903
1277 bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { 904 bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) {
1278 // Generate new font metrics with advance info for true type fonts. 905 // Generate new font metrics with advance info for true type fonts.
1279 // Generate glyph id array. 906 // Generate glyph id array.
1280 SkTDArray<uint32_t> glyphIDs; 907 SkTDArray<uint32_t> glyphIDs;
1281 if (subset) { 908 if (subset) {
1282 if (!subset->has(0)) { 909 if (!subset->has(0)) {
1283 glyphIDs.push(0); // Always include glyph 0. 910 glyphIDs.push(0); // Always include glyph 0.
1284 } 911 }
1285 subset->exportTo(&glyphIDs); 912 subset->exportTo(&glyphIDs);
1286 } 913 }
1287 if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { 914 if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) {
1288 SkTypeface::PerGlyphInfo info = SkTypeface::kGlyphNames_PerGlyphInfo;
1289 uint32_t* glyphs = (glyphIDs.count() == 0) ? nullptr : glyphIDs.begin(); 915 uint32_t* glyphs = (glyphIDs.count() == 0) ? nullptr : glyphIDs.begin();
1290 uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; 916 uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0;
1291 sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics( 917 sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics =
1292 typeface()->getAdvancedTypefaceMetrics(info, glyphs, glyphsCount)); 918 SkPDFFont::GetFontMetricsWithGlyphNames(this->typeface(), glyphs, gl yphsCount);
1293 setFontInfo(fontMetrics.get()); 919 this->setFontInfo(fontMetrics.get());
1294 addFontDescriptor(0, &glyphIDs); 920 this->addFontDescriptor(0, &glyphIDs);
1295 } else { 921 } else {
1296 // Other CID fonts 922 // Other CID fonts
1297 addFontDescriptor(0, nullptr); 923 addFontDescriptor(0, nullptr);
1298 } 924 }
1299 925
1300 insertName("BaseFont", fontInfo()->fFontName); 926 insertName("BaseFont", fontInfo()->fFontName);
1301 927
1302 if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { 928 if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) {
1303 insertName("Subtype", "CIDFontType0"); 929 insertName("Subtype", "CIDFontType0");
1304 } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) { 930 } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1350 } 976 }
1351 977
1352 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); 978 auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
1353 setFontDescriptor(descriptor.get()); 979 setFontDescriptor(descriptor.get());
1354 980
1355 int ttcIndex; 981 int ttcIndex;
1356 size_t header SK_INIT_TO_AVOID_WARNING; 982 size_t header SK_INIT_TO_AVOID_WARNING;
1357 size_t data SK_INIT_TO_AVOID_WARNING; 983 size_t data SK_INIT_TO_AVOID_WARNING;
1358 size_t trailer SK_INIT_TO_AVOID_WARNING; 984 size_t trailer SK_INIT_TO_AVOID_WARNING;
1359 std::unique_ptr<SkStreamAsset> rawFontData(typeface()->openStream(&ttcIndex) ); 985 std::unique_ptr<SkStreamAsset> rawFontData(typeface()->openStream(&ttcIndex) );
1360 SkASSERT(rawFontData); 986 sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData),
1361 SkASSERT(rawFontData->getLength() > 0); 987 &header, &data, &traile r);
1362 if (!rawFontData || 0 == rawFontData->getLength()) { 988 if (!fontData) {
1363 return false;
1364 }
1365 sk_sp<SkData> fontData(handle_type1_stream(rawFontData.get(), &header, &data , &trailer));
1366 if (fontData.get() == nullptr) {
1367 return false; 989 return false;
1368 } 990 }
1369 SkASSERT(this->canEmbed()); 991 SkASSERT(this->canEmbed());
1370 auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData)); 992 auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData));
1371 fontStream->dict()->insertInt("Length1", header); 993 fontStream->dict()->insertInt("Length1", header);
1372 fontStream->dict()->insertInt("Length2", data); 994 fontStream->dict()->insertInt("Length2", data);
1373 fontStream->dict()->insertInt("Length3", trailer); 995 fontStream->dict()->insertInt("Length3", trailer);
1374 descriptor->insertObjRef("FontFile", std::move(fontStream)); 996 descriptor->insertObjRef("FontFile", std::move(fontStream));
1375 997
1376 this->insertObjRef("FontDescriptor", std::move(descriptor)); 998 this->insertObjRef("FontDescriptor", std::move(descriptor));
1377 999
1378 return addCommonFontDescriptorEntries(defaultWidth); 1000 return addCommonFontDescriptorEntries(defaultWidth);
1379 } 1001 }
1380 1002
1381 bool SkPDFType1Font::populate(int16_t glyphID) { 1003 bool SkPDFType1Font::populate(int16_t glyphID) {
1004 this->insertName("Subtype", "Type1");
1005 this->insertName("BaseFont", fontInfo()->fFontName);
1382 adjustGlyphRangeForSingleByteEncoding(glyphID); 1006 adjustGlyphRangeForSingleByteEncoding(glyphID);
1007 SkGlyphID firstGlyphID = this->firstGlyphID();
1008 SkGlyphID lastGlyphID = this->lastGlyphID();
1383 1009
1384 int16_t defaultWidth = 0; 1010 // glyphCount not including glyph 0
1385 const AdvanceMetric* widthRangeEntry = nullptr; 1011 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
1012 SkASSERT(glyphCount > 0 && glyphCount <= 255);
1013 this->insertInt("FirstChar", (size_t)0);
1014 this->insertInt("LastChar", (size_t)glyphCount);
1386 { 1015 {
1387 SkSinglyLinkedList<AdvanceMetric> tmpMetrics; 1016 SkPaint tmpPaint;
1388 set_glyph_widths(this->typeface(), nullptr, &tmpMetrics); 1017 tmpPaint.setHinting(SkPaint::kNo_Hinting);
1389 for (const auto& widthEntry : tmpMetrics) { 1018 tmpPaint.setTypeface(sk_ref_sp(this->typeface()));
1390 switch (widthEntry.fType) { 1019 tmpPaint.setTextSize((SkScalar)this->typeface()->getUnitsPerEm());
1391 case AdvanceMetric::kDefault: 1020 SkAutoGlyphCache glyphCache(tmpPaint, nullptr, nullptr);
1392 defaultWidth = widthEntry.fAdvance[0]; 1021 auto widths = sk_make_sp<SkPDFArray>();
1393 break; 1022 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
1394 case AdvanceMetric::kRun: 1023 const uint16_t emSize = this->fontInfo()->fEmSize;
1395 SkASSERT(false); 1024 widths->appendScalar(from_font_units(advance, emSize));
1396 break; 1025 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
1397 case AdvanceMetric::kRange: 1026 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
1398 SkASSERT(widthRangeEntry == nullptr); 1027 widths->appendScalar(from_font_units(advance, emSize));
1399 widthRangeEntry = &widthEntry;
1400 break;
1401 }
1402 } 1028 }
1029 this->insertObject("Widths", std::move(widths));
1403 } 1030 }
1404 1031 if (!addFontDescriptor(0)) {
1405 if (!addFontDescriptor(defaultWidth)) {
1406 return false; 1032 return false;
1407 } 1033 }
1408
1409 insertName("Subtype", "Type1");
1410 insertName("BaseFont", fontInfo()->fFontName);
1411
1412 addWidthInfoFromRange(defaultWidth, widthRangeEntry);
1413 auto encDiffs = sk_make_sp<SkPDFArray>(); 1034 auto encDiffs = sk_make_sp<SkPDFArray>();
1414 encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); 1035 encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
1415 encDiffs->appendInt(1); 1036 encDiffs->appendInt(0);
1416 SkASSERT(this->fontInfo()->fGlyphNames.count() >= this->lastGlyphID()); 1037 const SkTArray<SkString>& glyphNames = this->fontInfo()->fGlyphNames;
1417 for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { 1038 SkASSERT(glyphNames.count() > lastGlyphID);
1418 encDiffs->appendName(fontInfo()->fGlyphNames[gID].c_str()); 1039 encDiffs->appendName(glyphNames[0].c_str());
1040 const SkString unknown("UNKNOWN");
1041 for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
1042 const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty( );
1043 const SkString& name = valid ? glyphNames[gID] : unknown;
1044 encDiffs->appendName(name);
1419 } 1045 }
1420 1046
1421 auto encoding = sk_make_sp<SkPDFDict>("Encoding"); 1047 auto encoding = sk_make_sp<SkPDFDict>("Encoding");
1422 encoding->insertObject("Differences", std::move(encDiffs)); 1048 encoding->insertObject("Differences", std::move(encDiffs));
1423 this->insertObject("Encoding", std::move(encoding)); 1049 this->insertObject("Encoding", std::move(encoding));
1424 return true; 1050 return true;
1425 } 1051 }
1426 1052
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 /////////////////////////////////////////////////////////////////////////////// 1053 ///////////////////////////////////////////////////////////////////////////////
1460 // class SkPDFType3Font 1054 // class SkPDFType3Font
1461 /////////////////////////////////////////////////////////////////////////////// 1055 ///////////////////////////////////////////////////////////////////////////////
1462 1056
1463 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info, 1057 SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
1464 SkTypeface* typeface, 1058 SkTypeface* typeface,
1465 uint16_t glyphID) 1059 uint16_t glyphID)
1466 : SkPDFFont(info, typeface, nullptr) { 1060 : SkPDFFont(info, typeface, nullptr) {
1467 this->populate(glyphID); 1061 this->populate(glyphID);
1468 } 1062 }
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 } 1172 }
1579 return *canon->fCanEmbedTypeface.set(id, canEmbed); 1173 return *canon->fCanEmbedTypeface.set(id, canEmbed);
1580 } 1174 }
1581 1175
1582 void SkPDFFont::drop() { 1176 void SkPDFFont::drop() {
1583 fTypeface = nullptr; 1177 fTypeface = nullptr;
1584 fFontInfo = nullptr; 1178 fFontInfo = nullptr;
1585 fDescriptor = nullptr; 1179 fDescriptor = nullptr;
1586 this->SkPDFDict::drop(); 1180 this->SkPDFDict::drop();
1587 } 1181 }
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