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

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

Issue 112053005: [PDF] Fix bug in ToUnicode table generation for Type 3 fonts. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/ToUnicode.cpp » ('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"
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 // following case because the specification is not clear. 453 // following case because the specification is not clear.
454 // 454 //
455 // 4 beginbfchar 1 beginbfchar 455 // 4 beginbfchar 1 beginbfchar
456 // <0003> <0013> <0020> <0014> 456 // <0003> <0013> <0020> <0014>
457 // <0005> <0015> to endbfchar 457 // <0005> <0015> to endbfchar
458 // <0007> <0017> 1 beginbfrange 458 // <0007> <0017> 1 beginbfrange
459 // <0020> <0014> <0003> <0007> <0013> 459 // <0020> <0014> <0003> <0007> <0013>
460 // endbfchar endbfrange 460 // endbfchar endbfrange
461 // 461 //
462 // Adobe Technote 5014 said: "Code mappings (unlike codespace ranges) may 462 // Adobe Technote 5014 said: "Code mappings (unlike codespace ranges) may
463 // overlap, but succeeding maps superceded preceding maps." 463 // overlap, but succeeding maps supersede preceding maps."
464 // 464 //
465 // In case of searching text in PDF, bfrange will have higher precedence so 465 // In case of searching text in PDF, bfrange will have higher precedence so
466 // typing char id 0x0014 in search box will get glyph id 0x0004 first. However, 466 // typing char id 0x0014 in search box will get glyph id 0x0004 first. However,
467 // the spec does not mention how will this kind of conflict being resolved. 467 // the spec does not mention how will this kind of conflict being resolved.
468 // 468 //
469 // For the worst case (having 65536 continuous unicode and we use every other 469 // For the worst case (having 65536 continuous unicode and we use every other
470 // one of them), the possible savings by aggressive optimization is 416KB 470 // one of them), the possible savings by aggressive optimization is 416KB
471 // pre-compressed and does not provide enough motivation for implementation. 471 // pre-compressed and does not provide enough motivation for implementation.
472 472
473 // FIXME: this should be in a header so that it is separately testable 473 // FIXME: this should be in a header so that it is separately testable
474 // ( see caller in tests/ToUnicode.cpp ) 474 // ( see caller in tests/ToUnicode.cpp )
475 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 475 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
476 const SkPDFGlyphSet* subset, 476 const SkPDFGlyphSet* subset,
477 SkDynamicMemoryWStream* cmap, 477 SkDynamicMemoryWStream* cmap,
478 bool multiByteGlyphs,
478 uint16_t firstGlyphID, 479 uint16_t firstGlyphID,
479 uint16_t lastGlyphID); 480 uint16_t lastGlyphID);
480 481
481 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 482 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
482 const SkPDFGlyphSet* subset, 483 const SkPDFGlyphSet* subset,
483 SkDynamicMemoryWStream* cmap, 484 SkDynamicMemoryWStream* cmap,
485 bool multiByteGlyphs,
484 uint16_t firstGlyphID, 486 uint16_t firstGlyphID,
485 uint16_t lastGlyphID) { 487 uint16_t lastGlyphID) {
486 if (glyphToUnicode.isEmpty()) { 488 if (glyphToUnicode.isEmpty()) {
487 return; 489 return;
488 } 490 }
491 int glyphOffset = 0;
492 if (!multiByteGlyphs) {
493 glyphOffset = firstGlyphID - 1;
494 }
489 495
490 SkTDArray<BFChar> bfcharEntries; 496 SkTDArray<BFChar> bfcharEntries;
491 SkTDArray<BFRange> bfrangeEntries; 497 SkTDArray<BFRange> bfrangeEntries;
492 498
493 BFRange currentRangeEntry = {0, 0, 0}; 499 BFRange currentRangeEntry = {0, 0, 0};
494 bool rangeEmpty = true; 500 bool rangeEmpty = true;
495 const int limit = SkMin32(lastGlyphID + 1, glyphToUnicode.count()); 501 const int limit =
502 SkMin32(lastGlyphID + 1, glyphToUnicode.count()) - glyphOffset;
496 503
497 for (int i = firstGlyphID; i < limit + 1; ++i) { 504 for (int i = firstGlyphID - glyphOffset; i < limit + 1; ++i) {
498 bool inSubset = i < limit && 505 bool inSubset = i < limit &&
499 (subset == NULL || subset->has(i)); 506 (subset == NULL || subset->has(i + glyphOffset));
500 if (!rangeEmpty) { 507 if (!rangeEmpty) {
501 // PDF spec requires bfrange not changing the higher byte, 508 // PDF spec requires bfrange not changing the higher byte,
502 // e.g. <1035> <10FF> <2222> is ok, but 509 // e.g. <1035> <10FF> <2222> is ok, but
503 // <1035> <1100> <2222> is no good 510 // <1035> <1100> <2222> is no good
504 bool inRange = 511 bool inRange =
505 i == currentRangeEntry.fEnd + 1 && 512 i == currentRangeEntry.fEnd + 1 &&
506 i >> 8 == currentRangeEntry.fStart >> 8 && 513 i >> 8 == currentRangeEntry.fStart >> 8 &&
507 i < limit && 514 i < limit &&
508 glyphToUnicode[i] == currentRangeEntry.fUnicode + i - 515 glyphToUnicode[i + glyphOffset] ==
509 currentRangeEntry.fStart; 516 currentRangeEntry.fUnicode + i - currentRangeEntry.fStart;
510 if (!inSubset || !inRange) { 517 if (!inSubset || !inRange) {
511 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) { 518 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) {
512 bfrangeEntries.push(currentRangeEntry); 519 bfrangeEntries.push(currentRangeEntry);
513 } else { 520 } else {
514 BFChar* entry = bfcharEntries.append(); 521 BFChar* entry = bfcharEntries.append();
515 entry->fGlyphId = currentRangeEntry.fStart; 522 entry->fGlyphId = currentRangeEntry.fStart;
516 entry->fUnicode = currentRangeEntry.fUnicode; 523 entry->fUnicode = currentRangeEntry.fUnicode;
517 } 524 }
518 rangeEmpty = true; 525 rangeEmpty = true;
519 } 526 }
520 } 527 }
521 if (inSubset) { 528 if (inSubset) {
522 currentRangeEntry.fEnd = i; 529 currentRangeEntry.fEnd = i;
523 if (rangeEmpty) { 530 if (rangeEmpty) {
524 currentRangeEntry.fStart = i; 531 currentRangeEntry.fStart = i;
525 currentRangeEntry.fUnicode = glyphToUnicode[i]; 532 currentRangeEntry.fUnicode = glyphToUnicode[i + glyphOffset];
526 rangeEmpty = false; 533 rangeEmpty = false;
527 } 534 }
528 } 535 }
529 } 536 }
530 537
531 // The spec requires all bfchar entries for a font must come before bfrange 538 // The spec requires all bfchar entries for a font must come before bfrange
532 // entries. 539 // entries.
533 append_bfchar_section(bfcharEntries, cmap); 540 append_bfchar_section(bfcharEntries, cmap);
534 append_bfrange_section(bfrangeEntries, cmap); 541 append_bfrange_section(bfrangeEntries, cmap);
535 } 542 }
536 543
537 static SkPDFStream* generate_tounicode_cmap( 544 static SkPDFStream* generate_tounicode_cmap(
538 const SkTDArray<SkUnichar>& glyphToUnicode, 545 const SkTDArray<SkUnichar>& glyphToUnicode,
539 const SkPDFGlyphSet* subset, 546 const SkPDFGlyphSet* subset,
547 bool multiByteGlyphs,
540 uint16_t firstGlyphID, 548 uint16_t firstGlyphID,
541 uint16_t lastGlyphID) { 549 uint16_t lastGlyphID) {
542 SkDynamicMemoryWStream cmap; 550 SkDynamicMemoryWStream cmap;
543 append_tounicode_header(&cmap, firstGlyphID, lastGlyphID); 551 if (multiByteGlyphs) {
544 append_cmap_sections(glyphToUnicode, subset, &cmap, 552 append_tounicode_header(&cmap, firstGlyphID, lastGlyphID);
553 } else {
554 append_tounicode_header(&cmap, 1, lastGlyphID - firstGlyphID + 1);
555 }
556 append_cmap_sections(glyphToUnicode, subset, &cmap, multiByteGlyphs,
545 firstGlyphID, lastGlyphID); 557 firstGlyphID, lastGlyphID);
546 append_cmap_footer(&cmap); 558 append_cmap_footer(&cmap);
547 SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream()); 559 SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream());
548 cmapStream->setData(cmap.copyToData())->unref(); 560 cmapStream->setData(cmap.copyToData())->unref();
549 return new SkPDFStream(cmapStream.get()); 561 return new SkPDFStream(cmapStream.get());
550 } 562 }
551 563
552 #if defined (SK_SFNTLY_SUBSETTER) 564 #if defined (SK_SFNTLY_SUBSETTER)
553 static void sk_delete_array(const void* ptr, size_t, void*) { 565 static void sk_delete_array(const void* ptr, size_t, void*) {
554 // Use C-style cast to cast away const and cast type simultaneously. 566 // Use C-style cast to cast away const and cast type simultaneously.
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 fFontID(fontID), 1049 fFontID(fontID),
1038 fGlyphID(glyphID) { 1050 fGlyphID(glyphID) {
1039 } 1051 }
1040 1052
1041 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { 1053 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) {
1042 if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) { 1054 if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) {
1043 return; 1055 return;
1044 } 1056 }
1045 SkAutoTUnref<SkPDFStream> pdfCmap( 1057 SkAutoTUnref<SkPDFStream> pdfCmap(
1046 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset, 1058 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset,
1047 firstGlyphID(), lastGlyphID())); 1059 multiByteGlyphs(), firstGlyphID(),
1060 lastGlyphID()));
1048 addResource(pdfCmap.get()); 1061 addResource(pdfCmap.get());
1049 insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref(); 1062 insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref();
1050 } 1063 }
1051 1064
1052 /////////////////////////////////////////////////////////////////////////////// 1065 ///////////////////////////////////////////////////////////////////////////////
1053 // class SkPDFType0Font 1066 // class SkPDFType0Font
1054 /////////////////////////////////////////////////////////////////////////////// 1067 ///////////////////////////////////////////////////////////////////////////////
1055 1068
1056 SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info, 1069 SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info,
1057 SkTypeface* typeface) 1070 SkTypeface* typeface)
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 glyphStream->setData(content.copyToData())->unref(); 1465 glyphStream->setData(content.copyToData())->unref();
1453 1466
1454 SkAutoTUnref<SkPDFStream> glyphDescription( 1467 SkAutoTUnref<SkPDFStream> glyphDescription(
1455 new SkPDFStream(glyphStream.get())); 1468 new SkPDFStream(glyphStream.get()));
1456 addResource(glyphDescription.get()); 1469 addResource(glyphDescription.get());
1457 charProcs->insert(characterName.c_str(), 1470 charProcs->insert(characterName.c_str(),
1458 new SkPDFObjRef(glyphDescription.get()))->unref(); 1471 new SkPDFObjRef(glyphDescription.get()))->unref();
1459 } 1472 }
1460 1473
1461 insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); 1474 insert("FontBBox", makeFontBBox(bbox, 1000))->unref();
1462 insertInt("FirstChar", firstGlyphID()); 1475 insertInt("FirstChar", 1);
1463 insertInt("LastChar", lastGlyphID()); 1476 insertInt("LastChar", lastGlyphID() - firstGlyphID() + 1);
1464 insert("Widths", widthArray.get()); 1477 insert("Widths", widthArray.get());
1465 insertName("CIDToGIDMap", "Identity"); 1478 insertName("CIDToGIDMap", "Identity");
1466 1479
1467 populateToUnicodeTable(NULL); 1480 populateToUnicodeTable(NULL);
1468 return true; 1481 return true;
1469 } 1482 }
OLDNEW
« no previous file with comments | « no previous file | tests/ToUnicode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698