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

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') | 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 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 const int limit = SkMin32(lastGlyphID + 1, glyphToUnicode.count());
487 496
488 for (int i = 0; i < count + 1; ++i) { 497 for (int i = firstGlyphID; i < limit + 1; ++i) {
489 bool inSubset = i < count && (subset == NULL || subset->has(i)); 498 bool inSubset = i < limit &&
499 (subset == NULL || subset->has(i));
490 if (!rangeEmpty) { 500 if (!rangeEmpty) {
491 // PDF spec requires bfrange not changing the higher byte, 501 // PDF spec requires bfrange not changing the higher byte,
492 // e.g. <1035> <10FF> <2222> is ok, but 502 // e.g. <1035> <10FF> <2222> is ok, but
493 // <1035> <1100> <2222> is no good 503 // <1035> <1100> <2222> is no good
494 bool inRange = 504 bool inRange =
495 i == currentRangeEntry.fEnd + 1 && 505 i == currentRangeEntry.fEnd + 1 &&
496 i >> 8 == currentRangeEntry.fStart >> 8 && 506 i >> 8 == currentRangeEntry.fStart >> 8 &&
497 i < count && 507 i < limit &&
498 glyphToUnicode[i] == currentRangeEntry.fUnicode + i - 508 glyphToUnicode[i] == currentRangeEntry.fUnicode + i -
499 currentRangeEntry.fStart; 509 currentRangeEntry.fStart;
500 if (!inSubset || !inRange) { 510 if (!inSubset || !inRange) {
501 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) { 511 if (currentRangeEntry.fEnd > currentRangeEntry.fStart) {
502 bfrangeEntries.push(currentRangeEntry); 512 bfrangeEntries.push(currentRangeEntry);
503 } else { 513 } else {
504 BFChar* entry = bfcharEntries.append(); 514 BFChar* entry = bfcharEntries.append();
505 entry->fGlyphId = currentRangeEntry.fStart; 515 entry->fGlyphId = currentRangeEntry.fStart;
506 entry->fUnicode = currentRangeEntry.fUnicode; 516 entry->fUnicode = currentRangeEntry.fUnicode;
507 } 517 }
(...skipping 11 matching lines...) Expand all
519 } 529 }
520 530
521 // The spec requires all bfchar entries for a font must come before bfrange 531 // The spec requires all bfchar entries for a font must come before bfrange
522 // entries. 532 // entries.
523 append_bfchar_section(bfcharEntries, cmap); 533 append_bfchar_section(bfcharEntries, cmap);
524 append_bfrange_section(bfrangeEntries, cmap); 534 append_bfrange_section(bfrangeEntries, cmap);
525 } 535 }
526 536
527 static SkPDFStream* generate_tounicode_cmap( 537 static SkPDFStream* generate_tounicode_cmap(
528 const SkTDArray<SkUnichar>& glyphToUnicode, 538 const SkTDArray<SkUnichar>& glyphToUnicode,
529 const SkPDFGlyphSet* subset) { 539 const SkPDFGlyphSet* subset,
540 uint16_t firstGlyphID,
541 uint16_t lastGlyphID) {
530 SkDynamicMemoryWStream cmap; 542 SkDynamicMemoryWStream cmap;
531 append_tounicode_header(&cmap); 543 append_tounicode_header(&cmap, firstGlyphID, lastGlyphID);
532 append_cmap_sections(glyphToUnicode, subset, &cmap); 544 append_cmap_sections(glyphToUnicode, subset, &cmap,
545 firstGlyphID, lastGlyphID);
533 append_cmap_footer(&cmap); 546 append_cmap_footer(&cmap);
534 SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream()); 547 SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream());
535 cmapStream->setData(cmap.copyToData())->unref(); 548 cmapStream->setData(cmap.copyToData())->unref();
536 return new SkPDFStream(cmapStream.get()); 549 return new SkPDFStream(cmapStream.get());
537 } 550 }
538 551
539 #if defined (SK_SFNTLY_SUBSETTER) 552 #if defined (SK_SFNTLY_SUBSETTER)
540 static void sk_delete_array(const void* ptr, size_t, void*) { 553 static void sk_delete_array(const void* ptr, size_t, void*) {
541 // Use C-style cast to cast away const and cast type simultaneously. 554 // Use C-style cast to cast away const and cast type simultaneously.
542 delete[] (unsigned char*)ptr; 555 delete[] (unsigned char*)ptr;
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 : fFont(font), 1021 : fFont(font),
1009 fFontID(fontID), 1022 fFontID(fontID),
1010 fGlyphID(glyphID) { 1023 fGlyphID(glyphID) {
1011 } 1024 }
1012 1025
1013 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { 1026 void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) {
1014 if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) { 1027 if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) {
1015 return; 1028 return;
1016 } 1029 }
1017 SkAutoTUnref<SkPDFStream> pdfCmap( 1030 SkAutoTUnref<SkPDFStream> pdfCmap(
1018 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset)); 1031 generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset,
1032 firstGlyphID(), lastGlyphID()));
1019 addResource(pdfCmap.get()); 1033 addResource(pdfCmap.get());
1020 insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref(); 1034 insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref();
1021 } 1035 }
1022 1036
1023 /////////////////////////////////////////////////////////////////////////////// 1037 ///////////////////////////////////////////////////////////////////////////////
1024 // class SkPDFType0Font 1038 // class SkPDFType0Font
1025 /////////////////////////////////////////////////////////////////////////////// 1039 ///////////////////////////////////////////////////////////////////////////////
1026 1040
1027 SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info, 1041 SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info,
1028 SkTypeface* typeface) 1042 SkTypeface* typeface)
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
1409 1423
1410 insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); 1424 insert("FontBBox", makeFontBBox(bbox, 1000))->unref();
1411 insertInt("FirstChar", firstGlyphID()); 1425 insertInt("FirstChar", firstGlyphID());
1412 insertInt("LastChar", lastGlyphID()); 1426 insertInt("LastChar", lastGlyphID());
1413 insert("Widths", widthArray.get()); 1427 insert("Widths", widthArray.get());
1414 insertName("CIDToGIDMap", "Identity"); 1428 insertName("CIDToGIDMap", "Identity");
1415 1429
1416 populateToUnicodeTable(NULL); 1430 populateToUnicodeTable(NULL);
1417 return true; 1431 return true;
1418 } 1432 }
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