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

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

Issue 23519006: pdf: write only ToUnicode mappings needed by the font, trimming anything out of [firstChar, lastCha… (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/ToUnicode.cpp » ('j') | tests/ToUnicode.cpp » ('J')
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 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 appendAdvance(advanceInfo->fAdvance[0], emSize, result); 335 appendAdvance(advanceInfo->fAdvance[0], emSize, result);
336 break; 336 break;
337 } 337 }
338 } 338 }
339 } 339 }
340 return result; 340 return result;
341 } 341 }
342 342
343 } // namespace 343 } // namespace
344 344
345 static void append_tounicode_header(SkDynamicMemoryWStream* cmap) { 345 static void append_tounicode_header(SkDynamicMemoryWStream* cmap,
346 uint16_t firstGlyphID,
347 uint16_t lastGlyphID) {
346 // 12 dict begin: 12 is an Adobe-suggested value. Shall not change. 348 // 12 dict begin: 12 is an Adobe-suggested value. Shall not change.
347 // It's there to prevent old version Adobe Readers from malfunctioning. 349 // It's there to prevent old version Adobe Readers from malfunctioning.
348 const char* kHeader = 350 const char* kHeader =
349 "/CIDInit /ProcSet findresource begin\n" 351 "/CIDInit /ProcSet findresource begin\n"
350 "12 dict begin\n" 352 "12 dict begin\n"
351 "begincmap\n"; 353 "begincmap\n";
352 cmap->writeText(kHeader); 354 cmap->writeText(kHeader);
353 355
354 // The /CIDSystemInfo must be consistent to the one in 356 // The /CIDSystemInfo must be consistent to the one in
355 // SkPDFFont::populateCIDFont(). 357 // SkPDFFont::populateCIDFont().
356 // We can not pass over the system info object here because the format is 358 // We can not pass over the system info object here because the format is
357 // different. This is not a reference object. 359 // different. This is not a reference object.
358 const char* kSysInfo = 360 const char* kSysInfo =
359 "/CIDSystemInfo\n" 361 "/CIDSystemInfo\n"
360 "<< /Registry (Adobe)\n" 362 "<< /Registry (Adobe)\n"
361 "/Ordering (UCS)\n" 363 "/Ordering (UCS)\n"
362 "/Supplement 0\n" 364 "/Supplement 0\n"
363 ">> def\n"; 365 ">> def\n";
364 cmap->writeText(kSysInfo); 366 cmap->writeText(kSysInfo);
365 367
366 // The CMapName must be consistent to /CIDSystemInfo above. 368 // The CMapName must be consistent to /CIDSystemInfo above.
367 // /CMapType 2 means ToUnicode. 369 // /CMapType 2 means ToUnicode.
368 // We specify codespacerange from 0x0000 to 0xFFFF because we convert our 370 // Codespace range just tells the PDF processor the valid range.
369 // code table from unsigned short (16-bits). Codespace range just tells the 371 const char* kTypeInfoHeader =
370 // PDF processor the valid range. It does not matter whether a complete
371 // mapping is provided or not.
372 const char* kTypeInfo =
373 "/CMapName /Adobe-Identity-UCS def\n" 372 "/CMapName /Adobe-Identity-UCS def\n"
374 "/CMapType 2 def\n" 373 "/CMapType 2 def\n"
375 "1 begincodespacerange\n" 374 "1 begincodespacerange\n";
376 "<0000> <FFFF>\n" 375 cmap->writeText(kTypeInfoHeader);
377 "endcodespacerange\n"; 376
378 cmap->writeText(kTypeInfo); 377 // e.g. "<0000> <FFFF>\n"
378 SkString range;
379 range.appendf("<%04X> <%04X>\n", firstGlyphID, lastGlyphID);
380 cmap->writeText(range.c_str());
381
382 const char* kTypeInfoFooter = "endcodespacerange\n";
383 cmap->writeText(kTypeInfoFooter);
379 } 384 }
380 385
381 static void append_cmap_footer(SkDynamicMemoryWStream* cmap) { 386 static void append_cmap_footer(SkDynamicMemoryWStream* cmap) {
382 const char* kFooter = 387 const char* kFooter =
383 "endcmap\n" 388 "endcmap\n"
384 "CMapName currentdict /CMap defineresource pop\n" 389 "CMapName currentdict /CMap defineresource pop\n"
385 "end\n" 390 "end\n"
386 "end"; 391 "end";
387 cmap->writeText(kFooter); 392 cmap->writeText(kFooter);
388 } 393 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 // 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.
463 // 468 //
464 // 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
465 // one of them), the possible savings by aggressive optimization is 416KB 470 // one of them), the possible savings by aggressive optimization is 416KB
466 // pre-compressed and does not provide enough motivation for implementation. 471 // pre-compressed and does not provide enough motivation for implementation.
467 472
468 // 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
469 // ( see caller in tests/ToUnicode.cpp ) 474 // ( see caller in tests/ToUnicode.cpp )
470 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 475 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
471 const SkPDFGlyphSet* subset, 476 const SkPDFGlyphSet* subset,
472 SkDynamicMemoryWStream* cmap); 477 SkDynamicMemoryWStream* cmap,
478 uint16_t firstGlyphID,
479 uint16_t lastGlyphID);
473 480
474 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 481 void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
475 const SkPDFGlyphSet* subset, 482 const SkPDFGlyphSet* subset,
476 SkDynamicMemoryWStream* cmap) { 483 SkDynamicMemoryWStream* cmap,
484 uint16_t firstGlyphID,
485 uint16_t lastGlyphID) {
477 if (glyphToUnicode.isEmpty()) { 486 if (glyphToUnicode.isEmpty()) {
478 return; 487 return;
479 } 488 }
480 489
481 SkTDArray<BFChar> bfcharEntries; 490 SkTDArray<BFChar> bfcharEntries;
482 SkTDArray<BFRange> bfrangeEntries; 491 SkTDArray<BFRange> bfrangeEntries;
483 492
484 BFRange currentRangeEntry = {0, 0, 0}; 493 BFRange currentRangeEntry = {0, 0, 0};
485 bool rangeEmpty = true; 494 bool rangeEmpty = true;
486 const int count = glyphToUnicode.count(); 495 // We must until lastGlyphID (inclusive) plus one more char.
496 const int limit = SkMin32(lastGlyphID, glyphToUnicode.count()) + 2;
vandebo (ex-Chrome) 2013/09/09 20:00:29 These changes seem to work for me and are closer t
edisonn 2013/09/10 14:50:11 It does not work with the new tests I added. Pleas
vandebo (ex-Chrome) 2013/09/12 22:23:39 Fair, I think this can be fixed by using another v
487 497
488 for (int i = 0; i < count + 1; ++i) { 498 for (int i = firstGlyphID; i < limit; ++i) {
vandebo (ex-Chrome) 2013/09/09 20:00:29 i < limit + 1
edisonn 2013/09/10 14:50:11 Done.
489 bool inSubset = i < count && (subset == NULL || subset->has(i)); 499 bool inSubset = i < glyphToUnicode.count() &&
vandebo (ex-Chrome) 2013/09/09 20:00:29 i < limit &&
500 i <= lastGlyphID &&
501 (subset == NULL || subset->has(i));
490 if (!rangeEmpty) { 502 if (!rangeEmpty) {
491 // PDF spec requires bfrange not changing the higher byte, 503 // PDF spec requires bfrange not changing the higher byte,
492 // e.g. <1035> <10FF> <2222> is ok, but 504 // e.g. <1035> <10FF> <2222> is ok, but
493 // <1035> <1100> <2222> is no good 505 // <1035> <1100> <2222> is no good
494 bool inRange = 506 bool inRange =
495 i == currentRangeEntry.fEnd + 1 && 507 i == currentRangeEntry.fEnd + 1 &&
496 i >> 8 == currentRangeEntry.fStart >> 8 && 508 i >> 8 == currentRangeEntry.fStart >> 8 &&
497 i < count && 509 i < glyphToUnicode.count() && i <= lastGlyphID &&
vandebo (ex-Chrome) 2013/09/09 20:00:29 i < limit &&
edisonn 2013/09/10 14:50:11 Done.
498 glyphToUnicode[i] == currentRangeEntry.fUnicode + i - 510 glyphToUnicode[i] == currentRangeEntry.fUnicode + i -
499 currentRangeEntry.fStart; 511 currentRangeEntry.fStart;
500 if (!inSubset || !inRange) { 512 if (!inSubset || !inRange) {
501 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) { 513 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) {
502 bfrangeEntries.push(currentRangeEntry); 514 bfrangeEntries.push(currentRangeEntry);
503 } else { 515 } else {
504 BFChar* entry = bfcharEntries.append(); 516 BFChar* entry = bfcharEntries.append();
505 entry->fGlyphId = currentRangeEntry.fStart; 517 entry->fGlyphId = currentRangeEntry.fStart;
506 entry->fUnicode = currentRangeEntry.fUnicode; 518 entry->fUnicode = currentRangeEntry.fUnicode;
507 } 519 }
(...skipping 11 matching lines...) Expand all
519 } 531 }
520 532
521 // The spec requires all bfchar entries for a font must come before bfrange 533 // The spec requires all bfchar entries for a font must come before bfrange
522 // entries. 534 // entries.
523 append_bfchar_section(bfcharEntries, cmap); 535 append_bfchar_section(bfcharEntries, cmap);
524 append_bfrange_section(bfrangeEntries, cmap); 536 append_bfrange_section(bfrangeEntries, cmap);
525 } 537 }
526 538
527 static SkPDFStream* generate_tounicode_cmap( 539 static SkPDFStream* generate_tounicode_cmap(
528 const SkTDArray<SkUnichar>& glyphToUnicode, 540 const SkTDArray<SkUnichar>& glyphToUnicode,
529 const SkPDFGlyphSet* subset) { 541 const SkPDFGlyphSet* subset,
542 uint16_t firstGlyphID,
543 uint16_t lastGlyphID) {
530 SkDynamicMemoryWStream cmap; 544 SkDynamicMemoryWStream cmap;
531 append_tounicode_header(&cmap); 545 append_tounicode_header(&cmap, firstGlyphID, lastGlyphID);
532 append_cmap_sections(glyphToUnicode, subset, &cmap); 546 append_cmap_sections(glyphToUnicode, subset, &cmap,
547 firstGlyphID, lastGlyphID);
533 append_cmap_footer(&cmap); 548 append_cmap_footer(&cmap);
534 SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream()); 549 SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream());
535 cmapStream->setData(cmap.copyToData())->unref(); 550 cmapStream->setData(cmap.copyToData())->unref();
536 return new SkPDFStream(cmapStream.get()); 551 return new SkPDFStream(cmapStream.get());
537 } 552 }
538 553
539 #if defined (SK_SFNTLY_SUBSETTER) 554 #if defined (SK_SFNTLY_SUBSETTER)
540 static void sk_delete_array(const void* ptr, size_t, void*) { 555 static void sk_delete_array(const void* ptr, size_t, void*) {
541 // Use C-style cast to cast away const and cast type simultaneously. 556 // Use C-style cast to cast away const and cast type simultaneously.
542 delete[] (unsigned char*)ptr; 557 delete[] (unsigned char*)ptr;
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 : fFont(font), 1023 : fFont(font),
1009 fFontID(fontID), 1024 fFontID(fontID),
1010 fGlyphID(glyphID) { 1025 fGlyphID(glyphID) {
1011 } 1026 }
1012 1027
1013 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { 1028 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) {
1014 if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) { 1029 if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) {
1015 return; 1030 return;
1016 } 1031 }
1017 SkAutoTUnref<SkPDFStream> pdfCmap( 1032 SkAutoTUnref<SkPDFStream> pdfCmap(
1018 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset)); 1033 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset,
1034 firstGlyphID(), lastGlyphID()));
1019 addResource(pdfCmap.get()); 1035 addResource(pdfCmap.get());
1020 insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref(); 1036 insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref();
1021 } 1037 }
1022 1038
1023 /////////////////////////////////////////////////////////////////////////////// 1039 ///////////////////////////////////////////////////////////////////////////////
1024 // class SkPDFType0Font 1040 // class SkPDFType0Font
1025 /////////////////////////////////////////////////////////////////////////////// 1041 ///////////////////////////////////////////////////////////////////////////////
1026 1042
1027 SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info, 1043 SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info,
1028 SkTypeface* typeface) 1044 SkTypeface* typeface)
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
1409 1425
1410 insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); 1426 insert("FontBBox", makeFontBBox(bbox, 1000))->unref();
1411 insertInt("FirstChar", firstGlyphID()); 1427 insertInt("FirstChar", firstGlyphID());
1412 insertInt("LastChar", lastGlyphID()); 1428 insertInt("LastChar", lastGlyphID());
1413 insert("Widths", widthArray.get()); 1429 insert("Widths", widthArray.get());
1414 insertName("CIDToGIDMap", "Identity"); 1430 insertName("CIDToGIDMap", "Identity");
1415 1431
1416 populateToUnicodeTable(NULL); 1432 populateToUnicodeTable(NULL);
1417 return true; 1433 return true;
1418 } 1434 }
OLDNEW
« no previous file with comments | « no previous file | tests/ToUnicode.cpp » ('j') | tests/ToUnicode.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698