1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/pdf/SkPDFFont.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1446 @@ 1.4 +/* 1.5 + * Copyright 2011 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include <ctype.h> 1.12 + 1.13 +#include "SkData.h" 1.14 +#include "SkFontHost.h" 1.15 +#include "SkGlyphCache.h" 1.16 +#include "SkPaint.h" 1.17 +#include "SkPDFCatalog.h" 1.18 +#include "SkPDFDevice.h" 1.19 +#include "SkPDFFont.h" 1.20 +#include "SkPDFFontImpl.h" 1.21 +#include "SkPDFStream.h" 1.22 +#include "SkPDFTypes.h" 1.23 +#include "SkPDFUtils.h" 1.24 +#include "SkRefCnt.h" 1.25 +#include "SkScalar.h" 1.26 +#include "SkStream.h" 1.27 +#include "SkTypefacePriv.h" 1.28 +#include "SkTypes.h" 1.29 +#include "SkUtils.h" 1.30 + 1.31 +#if defined (SK_SFNTLY_SUBSETTER) 1.32 +#include SK_SFNTLY_SUBSETTER 1.33 +#endif 1.34 + 1.35 +// PDF's notion of symbolic vs non-symbolic is related to the character set, not 1.36 +// symbols vs. characters. Rarely is a font the right character set to call it 1.37 +// non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) 1.38 +static const int kPdfSymbolic = 4; 1.39 + 1.40 +namespace { 1.41 + 1.42 +/////////////////////////////////////////////////////////////////////////////// 1.43 +// File-Local Functions 1.44 +/////////////////////////////////////////////////////////////////////////////// 1.45 + 1.46 +bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType, 1.47 + size_t* size) { 1.48 + // PFB sections have a two or six bytes header. 0x80 and a one byte 1.49 + // section type followed by a four byte section length. Type one is 1.50 + // an ASCII section (includes a length), type two is a binary section 1.51 + // (includes a length) and type three is an EOF marker with no length. 1.52 + const uint8_t* buf = *src; 1.53 + if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) { 1.54 + return false; 1.55 + } else if (buf[1] == 3) { 1.56 + return true; 1.57 + } else if (*len < 6) { 1.58 + return false; 1.59 + } 1.60 + 1.61 + *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) | 1.62 + ((size_t)buf[5] << 24); 1.63 + size_t consumed = *size + 6; 1.64 + if (consumed > *len) { 1.65 + return false; 1.66 + } 1.67 + *src = *src + consumed; 1.68 + *len = *len - consumed; 1.69 + return true; 1.70 +} 1.71 + 1.72 +bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen, 1.73 + size_t* dataLen, size_t* trailerLen) { 1.74 + const uint8_t* srcPtr = src; 1.75 + size_t remaining = size; 1.76 + 1.77 + return parsePFBSection(&srcPtr, &remaining, 1, headerLen) && 1.78 + parsePFBSection(&srcPtr, &remaining, 2, dataLen) && 1.79 + parsePFBSection(&srcPtr, &remaining, 1, trailerLen) && 1.80 + parsePFBSection(&srcPtr, &remaining, 3, NULL); 1.81 +} 1.82 + 1.83 +/* The sections of a PFA file are implicitly defined. The body starts 1.84 + * after the line containing "eexec," and the trailer starts with 512 1.85 + * literal 0's followed by "cleartomark" (plus arbitrary white space). 1.86 + * 1.87 + * This function assumes that src is NUL terminated, but the NUL 1.88 + * termination is not included in size. 1.89 + * 1.90 + */ 1.91 +bool parsePFA(const char* src, size_t size, size_t* headerLen, 1.92 + size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) { 1.93 + const char* end = src + size; 1.94 + 1.95 + const char* dataPos = strstr(src, "eexec"); 1.96 + if (!dataPos) { 1.97 + return false; 1.98 + } 1.99 + dataPos += strlen("eexec"); 1.100 + while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') && 1.101 + dataPos < end) { 1.102 + dataPos++; 1.103 + } 1.104 + *headerLen = dataPos - src; 1.105 + 1.106 + const char* trailerPos = strstr(dataPos, "cleartomark"); 1.107 + if (!trailerPos) { 1.108 + return false; 1.109 + } 1.110 + int zeroCount = 0; 1.111 + for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) { 1.112 + if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') { 1.113 + continue; 1.114 + } else if (*trailerPos == '0') { 1.115 + zeroCount++; 1.116 + } else { 1.117 + return false; 1.118 + } 1.119 + } 1.120 + if (zeroCount != 512) { 1.121 + return false; 1.122 + } 1.123 + 1.124 + *hexDataLen = trailerPos - src - *headerLen; 1.125 + *trailerLen = size - *headerLen - *hexDataLen; 1.126 + 1.127 + // Verify that the data section is hex encoded and count the bytes. 1.128 + int nibbles = 0; 1.129 + for (; dataPos < trailerPos; dataPos++) { 1.130 + if (isspace(*dataPos)) { 1.131 + continue; 1.132 + } 1.133 + if (!isxdigit(*dataPos)) { 1.134 + return false; 1.135 + } 1.136 + nibbles++; 1.137 + } 1.138 + *dataLen = (nibbles + 1) / 2; 1.139 + 1.140 + return true; 1.141 +} 1.142 + 1.143 +int8_t hexToBin(uint8_t c) { 1.144 + if (!isxdigit(c)) { 1.145 + return -1; 1.146 + } else if (c <= '9') { 1.147 + return c - '0'; 1.148 + } else if (c <= 'F') { 1.149 + return c - 'A' + 10; 1.150 + } else if (c <= 'f') { 1.151 + return c - 'a' + 10; 1.152 + } 1.153 + return -1; 1.154 +} 1.155 + 1.156 +SkStream* handleType1Stream(SkStream* srcStream, size_t* headerLen, 1.157 + size_t* dataLen, size_t* trailerLen) { 1.158 + // srcStream may be backed by a file or a unseekable fd, so we may not be 1.159 + // able to use skip(), rewind(), or getMemoryBase(). read()ing through 1.160 + // the input only once is doable, but very ugly. Furthermore, it'd be nice 1.161 + // if the data was NUL terminated so that we can use strstr() to search it. 1.162 + // Make as few copies as possible given these constraints. 1.163 + SkDynamicMemoryWStream dynamicStream; 1.164 + SkAutoTUnref<SkMemoryStream> staticStream; 1.165 + SkData* data = NULL; 1.166 + const uint8_t* src; 1.167 + size_t srcLen; 1.168 + if ((srcLen = srcStream->getLength()) > 0) { 1.169 + staticStream.reset(new SkMemoryStream(srcLen + 1)); 1.170 + src = (const uint8_t*)staticStream->getMemoryBase(); 1.171 + if (srcStream->getMemoryBase() != NULL) { 1.172 + memcpy((void *)src, srcStream->getMemoryBase(), srcLen); 1.173 + } else { 1.174 + size_t read = 0; 1.175 + while (read < srcLen) { 1.176 + size_t got = srcStream->read((void *)staticStream->getAtPos(), 1.177 + srcLen - read); 1.178 + if (got == 0) { 1.179 + return NULL; 1.180 + } 1.181 + read += got; 1.182 + staticStream->seek(read); 1.183 + } 1.184 + } 1.185 + ((uint8_t *)src)[srcLen] = 0; 1.186 + } else { 1.187 + static const size_t kBufSize = 4096; 1.188 + uint8_t buf[kBufSize]; 1.189 + size_t amount; 1.190 + while ((amount = srcStream->read(buf, kBufSize)) > 0) { 1.191 + dynamicStream.write(buf, amount); 1.192 + } 1.193 + amount = 0; 1.194 + dynamicStream.write(&amount, 1); // NULL terminator. 1.195 + data = dynamicStream.copyToData(); 1.196 + src = data->bytes(); 1.197 + srcLen = data->size() - 1; 1.198 + } 1.199 + 1.200 + // this handles releasing the data we may have gotten from dynamicStream. 1.201 + // if data is null, it is a no-op 1.202 + SkAutoDataUnref aud(data); 1.203 + 1.204 + if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) { 1.205 + SkMemoryStream* result = 1.206 + new SkMemoryStream(*headerLen + *dataLen + *trailerLen); 1.207 + memcpy((char*)result->getAtPos(), src + 6, *headerLen); 1.208 + result->seek(*headerLen); 1.209 + memcpy((char*)result->getAtPos(), src + 6 + *headerLen + 6, *dataLen); 1.210 + result->seek(*headerLen + *dataLen); 1.211 + memcpy((char*)result->getAtPos(), src + 6 + *headerLen + 6 + *dataLen, 1.212 + *trailerLen); 1.213 + result->rewind(); 1.214 + return result; 1.215 + } 1.216 + 1.217 + // A PFA has to be converted for PDF. 1.218 + size_t hexDataLen; 1.219 + if (parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen, 1.220 + trailerLen)) { 1.221 + SkMemoryStream* result = 1.222 + new SkMemoryStream(*headerLen + *dataLen + *trailerLen); 1.223 + memcpy((char*)result->getAtPos(), src, *headerLen); 1.224 + result->seek(*headerLen); 1.225 + 1.226 + const uint8_t* hexData = src + *headerLen; 1.227 + const uint8_t* trailer = hexData + hexDataLen; 1.228 + size_t outputOffset = 0; 1.229 + uint8_t dataByte = 0; // To hush compiler. 1.230 + bool highNibble = true; 1.231 + for (; hexData < trailer; hexData++) { 1.232 + int8_t curNibble = hexToBin(*hexData); 1.233 + if (curNibble < 0) { 1.234 + continue; 1.235 + } 1.236 + if (highNibble) { 1.237 + dataByte = curNibble << 4; 1.238 + highNibble = false; 1.239 + } else { 1.240 + dataByte |= curNibble; 1.241 + highNibble = true; 1.242 + ((char *)result->getAtPos())[outputOffset++] = dataByte; 1.243 + } 1.244 + } 1.245 + if (!highNibble) { 1.246 + ((char *)result->getAtPos())[outputOffset++] = dataByte; 1.247 + } 1.248 + SkASSERT(outputOffset == *dataLen); 1.249 + result->seek(*headerLen + outputOffset); 1.250 + 1.251 + memcpy((char *)result->getAtPos(), src + *headerLen + hexDataLen, 1.252 + *trailerLen); 1.253 + result->rewind(); 1.254 + return result; 1.255 + } 1.256 + 1.257 + return NULL; 1.258 +} 1.259 + 1.260 +// scale from em-units to base-1000, returning as a SkScalar 1.261 +SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) { 1.262 + SkScalar scaled = SkIntToScalar(val); 1.263 + if (emSize == 1000) { 1.264 + return scaled; 1.265 + } else { 1.266 + return SkScalarMulDiv(scaled, 1000, emSize); 1.267 + } 1.268 +} 1.269 + 1.270 +void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, 1.271 + SkWStream* content) { 1.272 + // Specify width and bounding box for the glyph. 1.273 + SkPDFScalar::Append(width, content); 1.274 + content->writeText(" 0 "); 1.275 + content->writeDecAsText(box.fLeft); 1.276 + content->writeText(" "); 1.277 + content->writeDecAsText(box.fTop); 1.278 + content->writeText(" "); 1.279 + content->writeDecAsText(box.fRight); 1.280 + content->writeText(" "); 1.281 + content->writeDecAsText(box.fBottom); 1.282 + content->writeText(" d1\n"); 1.283 +} 1.284 + 1.285 +SkPDFArray* makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { 1.286 + SkPDFArray* bbox = new SkPDFArray; 1.287 + bbox->reserve(4); 1.288 + bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize)); 1.289 + bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize)); 1.290 + bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize)); 1.291 + bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize)); 1.292 + return bbox; 1.293 +} 1.294 + 1.295 +SkPDFArray* appendWidth(const int16_t& width, uint16_t emSize, 1.296 + SkPDFArray* array) { 1.297 + array->appendScalar(scaleFromFontUnits(width, emSize)); 1.298 + return array; 1.299 +} 1.300 + 1.301 +SkPDFArray* appendVerticalAdvance( 1.302 + const SkAdvancedTypefaceMetrics::VerticalMetric& advance, 1.303 + uint16_t emSize, SkPDFArray* array) { 1.304 + appendWidth(advance.fVerticalAdvance, emSize, array); 1.305 + appendWidth(advance.fOriginXDisp, emSize, array); 1.306 + appendWidth(advance.fOriginYDisp, emSize, array); 1.307 + return array; 1.308 +} 1.309 + 1.310 +template <typename Data> 1.311 +SkPDFArray* composeAdvanceData( 1.312 + SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* advanceInfo, 1.313 + uint16_t emSize, 1.314 + SkPDFArray* (*appendAdvance)(const Data& advance, uint16_t emSize, 1.315 + SkPDFArray* array), 1.316 + Data* defaultAdvance) { 1.317 + SkPDFArray* result = new SkPDFArray(); 1.318 + for (; advanceInfo != NULL; advanceInfo = advanceInfo->fNext.get()) { 1.319 + switch (advanceInfo->fType) { 1.320 + case SkAdvancedTypefaceMetrics::WidthRange::kDefault: { 1.321 + SkASSERT(advanceInfo->fAdvance.count() == 1); 1.322 + *defaultAdvance = advanceInfo->fAdvance[0]; 1.323 + break; 1.324 + } 1.325 + case SkAdvancedTypefaceMetrics::WidthRange::kRange: { 1.326 + SkAutoTUnref<SkPDFArray> advanceArray(new SkPDFArray()); 1.327 + for (int j = 0; j < advanceInfo->fAdvance.count(); j++) 1.328 + appendAdvance(advanceInfo->fAdvance[j], emSize, 1.329 + advanceArray.get()); 1.330 + result->appendInt(advanceInfo->fStartId); 1.331 + result->append(advanceArray.get()); 1.332 + break; 1.333 + } 1.334 + case SkAdvancedTypefaceMetrics::WidthRange::kRun: { 1.335 + SkASSERT(advanceInfo->fAdvance.count() == 1); 1.336 + result->appendInt(advanceInfo->fStartId); 1.337 + result->appendInt(advanceInfo->fEndId); 1.338 + appendAdvance(advanceInfo->fAdvance[0], emSize, result); 1.339 + break; 1.340 + } 1.341 + } 1.342 + } 1.343 + return result; 1.344 +} 1.345 + 1.346 +} // namespace 1.347 + 1.348 +static void append_tounicode_header(SkDynamicMemoryWStream* cmap, 1.349 + uint16_t firstGlyphID, 1.350 + uint16_t lastGlyphID) { 1.351 + // 12 dict begin: 12 is an Adobe-suggested value. Shall not change. 1.352 + // It's there to prevent old version Adobe Readers from malfunctioning. 1.353 + const char* kHeader = 1.354 + "/CIDInit /ProcSet findresource begin\n" 1.355 + "12 dict begin\n" 1.356 + "begincmap\n"; 1.357 + cmap->writeText(kHeader); 1.358 + 1.359 + // The /CIDSystemInfo must be consistent to the one in 1.360 + // SkPDFFont::populateCIDFont(). 1.361 + // We can not pass over the system info object here because the format is 1.362 + // different. This is not a reference object. 1.363 + const char* kSysInfo = 1.364 + "/CIDSystemInfo\n" 1.365 + "<< /Registry (Adobe)\n" 1.366 + "/Ordering (UCS)\n" 1.367 + "/Supplement 0\n" 1.368 + ">> def\n"; 1.369 + cmap->writeText(kSysInfo); 1.370 + 1.371 + // The CMapName must be consistent to /CIDSystemInfo above. 1.372 + // /CMapType 2 means ToUnicode. 1.373 + // Codespace range just tells the PDF processor the valid range. 1.374 + const char* kTypeInfoHeader = 1.375 + "/CMapName /Adobe-Identity-UCS def\n" 1.376 + "/CMapType 2 def\n" 1.377 + "1 begincodespacerange\n"; 1.378 + cmap->writeText(kTypeInfoHeader); 1.379 + 1.380 + // e.g. "<0000> <FFFF>\n" 1.381 + SkString range; 1.382 + range.appendf("<%04X> <%04X>\n", firstGlyphID, lastGlyphID); 1.383 + cmap->writeText(range.c_str()); 1.384 + 1.385 + const char* kTypeInfoFooter = "endcodespacerange\n"; 1.386 + cmap->writeText(kTypeInfoFooter); 1.387 +} 1.388 + 1.389 +static void append_cmap_footer(SkDynamicMemoryWStream* cmap) { 1.390 + const char* kFooter = 1.391 + "endcmap\n" 1.392 + "CMapName currentdict /CMap defineresource pop\n" 1.393 + "end\n" 1.394 + "end"; 1.395 + cmap->writeText(kFooter); 1.396 +} 1.397 + 1.398 +struct BFChar { 1.399 + uint16_t fGlyphId; 1.400 + SkUnichar fUnicode; 1.401 +}; 1.402 + 1.403 +struct BFRange { 1.404 + uint16_t fStart; 1.405 + uint16_t fEnd; 1.406 + SkUnichar fUnicode; 1.407 +}; 1.408 + 1.409 +static void append_bfchar_section(const SkTDArray<BFChar>& bfchar, 1.410 + SkDynamicMemoryWStream* cmap) { 1.411 + // PDF spec defines that every bf* list can have at most 100 entries. 1.412 + for (int i = 0; i < bfchar.count(); i += 100) { 1.413 + int count = bfchar.count() - i; 1.414 + count = SkMin32(count, 100); 1.415 + cmap->writeDecAsText(count); 1.416 + cmap->writeText(" beginbfchar\n"); 1.417 + for (int j = 0; j < count; ++j) { 1.418 + cmap->writeText("<"); 1.419 + cmap->writeHexAsText(bfchar[i + j].fGlyphId, 4); 1.420 + cmap->writeText("> <"); 1.421 + cmap->writeHexAsText(bfchar[i + j].fUnicode, 4); 1.422 + cmap->writeText(">\n"); 1.423 + } 1.424 + cmap->writeText("endbfchar\n"); 1.425 + } 1.426 +} 1.427 + 1.428 +static void append_bfrange_section(const SkTDArray<BFRange>& bfrange, 1.429 + SkDynamicMemoryWStream* cmap) { 1.430 + // PDF spec defines that every bf* list can have at most 100 entries. 1.431 + for (int i = 0; i < bfrange.count(); i += 100) { 1.432 + int count = bfrange.count() - i; 1.433 + count = SkMin32(count, 100); 1.434 + cmap->writeDecAsText(count); 1.435 + cmap->writeText(" beginbfrange\n"); 1.436 + for (int j = 0; j < count; ++j) { 1.437 + cmap->writeText("<"); 1.438 + cmap->writeHexAsText(bfrange[i + j].fStart, 4); 1.439 + cmap->writeText("> <"); 1.440 + cmap->writeHexAsText(bfrange[i + j].fEnd, 4); 1.441 + cmap->writeText("> <"); 1.442 + cmap->writeHexAsText(bfrange[i + j].fUnicode, 4); 1.443 + cmap->writeText(">\n"); 1.444 + } 1.445 + cmap->writeText("endbfrange\n"); 1.446 + } 1.447 +} 1.448 + 1.449 +// Generate <bfchar> and <bfrange> table according to PDF spec 1.4 and Adobe 1.450 +// Technote 5014. 1.451 +// The function is not static so we can test it in unit tests. 1.452 +// 1.453 +// Current implementation guarantees bfchar and bfrange entries do not overlap. 1.454 +// 1.455 +// Current implementation does not attempt aggresive optimizations against 1.456 +// following case because the specification is not clear. 1.457 +// 1.458 +// 4 beginbfchar 1 beginbfchar 1.459 +// <0003> <0013> <0020> <0014> 1.460 +// <0005> <0015> to endbfchar 1.461 +// <0007> <0017> 1 beginbfrange 1.462 +// <0020> <0014> <0003> <0007> <0013> 1.463 +// endbfchar endbfrange 1.464 +// 1.465 +// Adobe Technote 5014 said: "Code mappings (unlike codespace ranges) may 1.466 +// overlap, but succeeding maps supersede preceding maps." 1.467 +// 1.468 +// In case of searching text in PDF, bfrange will have higher precedence so 1.469 +// typing char id 0x0014 in search box will get glyph id 0x0004 first. However, 1.470 +// the spec does not mention how will this kind of conflict being resolved. 1.471 +// 1.472 +// For the worst case (having 65536 continuous unicode and we use every other 1.473 +// one of them), the possible savings by aggressive optimization is 416KB 1.474 +// pre-compressed and does not provide enough motivation for implementation. 1.475 + 1.476 +// FIXME: this should be in a header so that it is separately testable 1.477 +// ( see caller in tests/ToUnicode.cpp ) 1.478 +void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 1.479 + const SkPDFGlyphSet* subset, 1.480 + SkDynamicMemoryWStream* cmap, 1.481 + bool multiByteGlyphs, 1.482 + uint16_t firstGlyphID, 1.483 + uint16_t lastGlyphID); 1.484 + 1.485 +void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode, 1.486 + const SkPDFGlyphSet* subset, 1.487 + SkDynamicMemoryWStream* cmap, 1.488 + bool multiByteGlyphs, 1.489 + uint16_t firstGlyphID, 1.490 + uint16_t lastGlyphID) { 1.491 + if (glyphToUnicode.isEmpty()) { 1.492 + return; 1.493 + } 1.494 + int glyphOffset = 0; 1.495 + if (!multiByteGlyphs) { 1.496 + glyphOffset = firstGlyphID - 1; 1.497 + } 1.498 + 1.499 + SkTDArray<BFChar> bfcharEntries; 1.500 + SkTDArray<BFRange> bfrangeEntries; 1.501 + 1.502 + BFRange currentRangeEntry = {0, 0, 0}; 1.503 + bool rangeEmpty = true; 1.504 + const int limit = 1.505 + SkMin32(lastGlyphID + 1, glyphToUnicode.count()) - glyphOffset; 1.506 + 1.507 + for (int i = firstGlyphID - glyphOffset; i < limit + 1; ++i) { 1.508 + bool inSubset = i < limit && 1.509 + (subset == NULL || subset->has(i + glyphOffset)); 1.510 + if (!rangeEmpty) { 1.511 + // PDF spec requires bfrange not changing the higher byte, 1.512 + // e.g. <1035> <10FF> <2222> is ok, but 1.513 + // <1035> <1100> <2222> is no good 1.514 + bool inRange = 1.515 + i == currentRangeEntry.fEnd + 1 && 1.516 + i >> 8 == currentRangeEntry.fStart >> 8 && 1.517 + i < limit && 1.518 + glyphToUnicode[i + glyphOffset] == 1.519 + currentRangeEntry.fUnicode + i - currentRangeEntry.fStart; 1.520 + if (!inSubset || !inRange) { 1.521 + if (currentRangeEntry.fEnd > currentRangeEntry.fStart) { 1.522 + bfrangeEntries.push(currentRangeEntry); 1.523 + } else { 1.524 + BFChar* entry = bfcharEntries.append(); 1.525 + entry->fGlyphId = currentRangeEntry.fStart; 1.526 + entry->fUnicode = currentRangeEntry.fUnicode; 1.527 + } 1.528 + rangeEmpty = true; 1.529 + } 1.530 + } 1.531 + if (inSubset) { 1.532 + currentRangeEntry.fEnd = i; 1.533 + if (rangeEmpty) { 1.534 + currentRangeEntry.fStart = i; 1.535 + currentRangeEntry.fUnicode = glyphToUnicode[i + glyphOffset]; 1.536 + rangeEmpty = false; 1.537 + } 1.538 + } 1.539 + } 1.540 + 1.541 + // The spec requires all bfchar entries for a font must come before bfrange 1.542 + // entries. 1.543 + append_bfchar_section(bfcharEntries, cmap); 1.544 + append_bfrange_section(bfrangeEntries, cmap); 1.545 +} 1.546 + 1.547 +static SkPDFStream* generate_tounicode_cmap( 1.548 + const SkTDArray<SkUnichar>& glyphToUnicode, 1.549 + const SkPDFGlyphSet* subset, 1.550 + bool multiByteGlyphs, 1.551 + uint16_t firstGlyphID, 1.552 + uint16_t lastGlyphID) { 1.553 + SkDynamicMemoryWStream cmap; 1.554 + if (multiByteGlyphs) { 1.555 + append_tounicode_header(&cmap, firstGlyphID, lastGlyphID); 1.556 + } else { 1.557 + append_tounicode_header(&cmap, 1, lastGlyphID - firstGlyphID + 1); 1.558 + } 1.559 + append_cmap_sections(glyphToUnicode, subset, &cmap, multiByteGlyphs, 1.560 + firstGlyphID, lastGlyphID); 1.561 + append_cmap_footer(&cmap); 1.562 + SkAutoTUnref<SkMemoryStream> cmapStream(new SkMemoryStream()); 1.563 + cmapStream->setData(cmap.copyToData())->unref(); 1.564 + return new SkPDFStream(cmapStream.get()); 1.565 +} 1.566 + 1.567 +#if defined (SK_SFNTLY_SUBSETTER) 1.568 +static void sk_delete_array(const void* ptr, size_t, void*) { 1.569 + // Use C-style cast to cast away const and cast type simultaneously. 1.570 + delete[] (unsigned char*)ptr; 1.571 +} 1.572 +#endif 1.573 + 1.574 +static int get_subset_font_stream(const char* fontName, 1.575 + const SkTypeface* typeface, 1.576 + const SkTDArray<uint32_t>& subset, 1.577 + SkPDFStream** fontStream) { 1.578 + int ttcIndex; 1.579 + SkAutoTUnref<SkStream> fontData(typeface->openStream(&ttcIndex)); 1.580 + 1.581 + int fontSize = fontData->getLength(); 1.582 + 1.583 +#if defined (SK_SFNTLY_SUBSETTER) 1.584 + // Read font into buffer. 1.585 + SkPDFStream* subsetFontStream = NULL; 1.586 + SkTDArray<unsigned char> originalFont; 1.587 + originalFont.setCount(fontSize); 1.588 + if (fontData->read(originalFont.begin(), fontSize) == (size_t)fontSize) { 1.589 + unsigned char* subsetFont = NULL; 1.590 + // sfntly requires unsigned int* to be passed in, as far as we know, 1.591 + // unsigned int is equivalent to uint32_t on all platforms. 1.592 + SK_COMPILE_ASSERT(sizeof(unsigned int) == sizeof(uint32_t), 1.593 + unsigned_int_not_32_bits); 1.594 + int subsetFontSize = SfntlyWrapper::SubsetFont(fontName, 1.595 + originalFont.begin(), 1.596 + fontSize, 1.597 + subset.begin(), 1.598 + subset.count(), 1.599 + &subsetFont); 1.600 + if (subsetFontSize > 0 && subsetFont != NULL) { 1.601 + SkAutoDataUnref data(SkData::NewWithProc(subsetFont, 1.602 + subsetFontSize, 1.603 + sk_delete_array, 1.604 + NULL)); 1.605 + subsetFontStream = new SkPDFStream(data.get()); 1.606 + fontSize = subsetFontSize; 1.607 + } 1.608 + } 1.609 + if (subsetFontStream) { 1.610 + *fontStream = subsetFontStream; 1.611 + return fontSize; 1.612 + } 1.613 + fontData->rewind(); 1.614 +#else 1.615 + sk_ignore_unused_variable(fontName); 1.616 + sk_ignore_unused_variable(subset); 1.617 +#endif 1.618 + 1.619 + // Fail over: just embed the whole font. 1.620 + *fontStream = new SkPDFStream(fontData.get()); 1.621 + return fontSize; 1.622 +} 1.623 + 1.624 +/////////////////////////////////////////////////////////////////////////////// 1.625 +// class SkPDFGlyphSet 1.626 +/////////////////////////////////////////////////////////////////////////////// 1.627 + 1.628 +SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { 1.629 +} 1.630 + 1.631 +void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { 1.632 + for (int i = 0; i < numGlyphs; ++i) { 1.633 + fBitSet.setBit(glyphIDs[i], true); 1.634 + } 1.635 +} 1.636 + 1.637 +bool SkPDFGlyphSet::has(uint16_t glyphID) const { 1.638 + return fBitSet.isBitSet(glyphID); 1.639 +} 1.640 + 1.641 +void SkPDFGlyphSet::merge(const SkPDFGlyphSet& usage) { 1.642 + fBitSet.orBits(usage.fBitSet); 1.643 +} 1.644 + 1.645 +void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { 1.646 + fBitSet.exportTo(glyphIDs); 1.647 +} 1.648 + 1.649 +/////////////////////////////////////////////////////////////////////////////// 1.650 +// class SkPDFGlyphSetMap 1.651 +/////////////////////////////////////////////////////////////////////////////// 1.652 +SkPDFGlyphSetMap::FontGlyphSetPair::FontGlyphSetPair(SkPDFFont* font, 1.653 + SkPDFGlyphSet* glyphSet) 1.654 + : fFont(font), 1.655 + fGlyphSet(glyphSet) { 1.656 +} 1.657 + 1.658 +SkPDFGlyphSetMap::F2BIter::F2BIter(const SkPDFGlyphSetMap& map) { 1.659 + reset(map); 1.660 +} 1.661 + 1.662 +const SkPDFGlyphSetMap::FontGlyphSetPair* SkPDFGlyphSetMap::F2BIter::next() const { 1.663 + if (fIndex >= fMap->count()) { 1.664 + return NULL; 1.665 + } 1.666 + return &((*fMap)[fIndex++]); 1.667 +} 1.668 + 1.669 +void SkPDFGlyphSetMap::F2BIter::reset(const SkPDFGlyphSetMap& map) { 1.670 + fMap = &(map.fMap); 1.671 + fIndex = 0; 1.672 +} 1.673 + 1.674 +SkPDFGlyphSetMap::SkPDFGlyphSetMap() { 1.675 +} 1.676 + 1.677 +SkPDFGlyphSetMap::~SkPDFGlyphSetMap() { 1.678 + reset(); 1.679 +} 1.680 + 1.681 +void SkPDFGlyphSetMap::merge(const SkPDFGlyphSetMap& usage) { 1.682 + for (int i = 0; i < usage.fMap.count(); ++i) { 1.683 + SkPDFGlyphSet* myUsage = getGlyphSetForFont(usage.fMap[i].fFont); 1.684 + myUsage->merge(*(usage.fMap[i].fGlyphSet)); 1.685 + } 1.686 +} 1.687 + 1.688 +void SkPDFGlyphSetMap::reset() { 1.689 + for (int i = 0; i < fMap.count(); ++i) { 1.690 + delete fMap[i].fGlyphSet; // Should not be NULL. 1.691 + } 1.692 + fMap.reset(); 1.693 +} 1.694 + 1.695 +void SkPDFGlyphSetMap::noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs, 1.696 + int numGlyphs) { 1.697 + SkPDFGlyphSet* subset = getGlyphSetForFont(font); 1.698 + if (subset) { 1.699 + subset->set(glyphIDs, numGlyphs); 1.700 + } 1.701 +} 1.702 + 1.703 +SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) { 1.704 + int index = fMap.count(); 1.705 + for (int i = 0; i < index; ++i) { 1.706 + if (fMap[i].fFont == font) { 1.707 + return fMap[i].fGlyphSet; 1.708 + } 1.709 + } 1.710 + fMap.append(); 1.711 + index = fMap.count() - 1; 1.712 + fMap[index].fFont = font; 1.713 + fMap[index].fGlyphSet = new SkPDFGlyphSet(); 1.714 + return fMap[index].fGlyphSet; 1.715 +} 1.716 + 1.717 +/////////////////////////////////////////////////////////////////////////////// 1.718 +// class SkPDFFont 1.719 +/////////////////////////////////////////////////////////////////////////////// 1.720 + 1.721 +/* Font subset design: It would be nice to be able to subset fonts 1.722 + * (particularly type 3 fonts), but it's a lot of work and not a priority. 1.723 + * 1.724 + * Resources are canonicalized and uniqueified by pointer so there has to be 1.725 + * some additional state indicating which subset of the font is used. It 1.726 + * must be maintained at the page granularity and then combined at the document 1.727 + * granularity. a) change SkPDFFont to fill in its state on demand, kind of 1.728 + * like SkPDFGraphicState. b) maintain a per font glyph usage class in each 1.729 + * page/pdf device. c) in the document, retrieve the per font glyph usage 1.730 + * from each page and combine it and ask for a resource with that subset. 1.731 + */ 1.732 + 1.733 +SkPDFFont::~SkPDFFont() { 1.734 + SkAutoMutexAcquire lock(CanonicalFontsMutex()); 1.735 + int index = -1; 1.736 + for (int i = 0 ; i < CanonicalFonts().count() ; i++) { 1.737 + if (CanonicalFonts()[i].fFont == this) { 1.738 + index = i; 1.739 + } 1.740 + } 1.741 + 1.742 + SkDEBUGCODE(int indexFound;) 1.743 + SkASSERT(index == -1 || 1.744 + (Find(fTypeface->uniqueID(), 1.745 + fFirstGlyphID, 1.746 + &indexFound) && 1.747 + index == indexFound)); 1.748 + if (index >= 0) { 1.749 + CanonicalFonts().removeShuffle(index); 1.750 + } 1.751 + fResources.unrefAll(); 1.752 +} 1.753 + 1.754 +void SkPDFFont::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 1.755 + SkTSet<SkPDFObject*>* newResourceObjects) { 1.756 + GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects); 1.757 +} 1.758 + 1.759 +SkTypeface* SkPDFFont::typeface() { 1.760 + return fTypeface.get(); 1.761 +} 1.762 + 1.763 +SkAdvancedTypefaceMetrics::FontType SkPDFFont::getType() { 1.764 + return fFontType; 1.765 +} 1.766 + 1.767 +bool SkPDFFont::hasGlyph(uint16_t id) { 1.768 + return (id >= fFirstGlyphID && id <= fLastGlyphID) || id == 0; 1.769 +} 1.770 + 1.771 +size_t SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs, 1.772 + size_t numGlyphs) { 1.773 + // A font with multibyte glyphs will support all glyph IDs in a single font. 1.774 + if (this->multiByteGlyphs()) { 1.775 + return numGlyphs; 1.776 + } 1.777 + 1.778 + for (size_t i = 0; i < numGlyphs; i++) { 1.779 + if (glyphIDs[i] == 0) { 1.780 + continue; 1.781 + } 1.782 + if (glyphIDs[i] < fFirstGlyphID || glyphIDs[i] > fLastGlyphID) { 1.783 + return i; 1.784 + } 1.785 + glyphIDs[i] -= (fFirstGlyphID - 1); 1.786 + } 1.787 + 1.788 + return numGlyphs; 1.789 +} 1.790 + 1.791 +// static 1.792 +SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { 1.793 + SkAutoMutexAcquire lock(CanonicalFontsMutex()); 1.794 + 1.795 + SkAutoResolveDefaultTypeface autoResolve(typeface); 1.796 + typeface = autoResolve.get(); 1.797 + 1.798 + const uint32_t fontID = typeface->uniqueID(); 1.799 + int relatedFontIndex; 1.800 + if (Find(fontID, glyphID, &relatedFontIndex)) { 1.801 + CanonicalFonts()[relatedFontIndex].fFont->ref(); 1.802 + return CanonicalFonts()[relatedFontIndex].fFont; 1.803 + } 1.804 + 1.805 + SkAutoTUnref<SkAdvancedTypefaceMetrics> fontMetrics; 1.806 + SkPDFDict* relatedFontDescriptor = NULL; 1.807 + if (relatedFontIndex >= 0) { 1.808 + SkPDFFont* relatedFont = CanonicalFonts()[relatedFontIndex].fFont; 1.809 + fontMetrics.reset(relatedFont->fontInfo()); 1.810 + SkSafeRef(fontMetrics.get()); 1.811 + relatedFontDescriptor = relatedFont->getFontDescriptor(); 1.812 + 1.813 + // This only is to catch callers who pass invalid glyph ids. 1.814 + // If glyph id is invalid, then we will create duplicate entries 1.815 + // for True Type fonts. 1.816 + SkAdvancedTypefaceMetrics::FontType fontType = 1.817 + fontMetrics.get() ? fontMetrics.get()->fType : 1.818 + SkAdvancedTypefaceMetrics::kOther_Font; 1.819 + 1.820 + if (fontType == SkAdvancedTypefaceMetrics::kType1CID_Font || 1.821 + fontType == SkAdvancedTypefaceMetrics::kTrueType_Font) { 1.822 + CanonicalFonts()[relatedFontIndex].fFont->ref(); 1.823 + return CanonicalFonts()[relatedFontIndex].fFont; 1.824 + } 1.825 + } else { 1.826 + SkAdvancedTypefaceMetrics::PerGlyphInfo info; 1.827 + info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo; 1.828 + info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( 1.829 + info, SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo); 1.830 +#if !defined (SK_SFNTLY_SUBSETTER) 1.831 + info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( 1.832 + info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); 1.833 +#endif 1.834 + fontMetrics.reset( 1.835 + typeface->getAdvancedTypefaceMetrics(info, NULL, 0)); 1.836 +#if defined (SK_SFNTLY_SUBSETTER) 1.837 + if (fontMetrics.get() && 1.838 + fontMetrics->fType != SkAdvancedTypefaceMetrics::kTrueType_Font) { 1.839 + // Font does not support subsetting, get new info with advance. 1.840 + info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( 1.841 + info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); 1.842 + fontMetrics.reset( 1.843 + typeface->getAdvancedTypefaceMetrics(info, NULL, 0)); 1.844 + } 1.845 +#endif 1.846 + } 1.847 + 1.848 + SkPDFFont* font = Create(fontMetrics.get(), typeface, glyphID, 1.849 + relatedFontDescriptor); 1.850 + FontRec newEntry(font, fontID, font->fFirstGlyphID); 1.851 + CanonicalFonts().push(newEntry); 1.852 + return font; // Return the reference new SkPDFFont() created. 1.853 +} 1.854 + 1.855 +SkPDFFont* SkPDFFont::getFontSubset(const SkPDFGlyphSet*) { 1.856 + return NULL; // Default: no support. 1.857 +} 1.858 + 1.859 +// static 1.860 +SkTDArray<SkPDFFont::FontRec>& SkPDFFont::CanonicalFonts() { 1.861 + // This initialization is only thread safe with gcc. 1.862 + static SkTDArray<FontRec> gCanonicalFonts; 1.863 + return gCanonicalFonts; 1.864 +} 1.865 + 1.866 +// static 1.867 +SkBaseMutex& SkPDFFont::CanonicalFontsMutex() { 1.868 + // This initialization is only thread safe with gcc, or when 1.869 + // POD-style mutex initialization is used. 1.870 + SK_DECLARE_STATIC_MUTEX(gCanonicalFontsMutex); 1.871 + return gCanonicalFontsMutex; 1.872 +} 1.873 + 1.874 +// static 1.875 +bool SkPDFFont::Find(uint32_t fontID, uint16_t glyphID, int* index) { 1.876 + // TODO(vandebo): Optimize this, do only one search? 1.877 + FontRec search(NULL, fontID, glyphID); 1.878 + *index = CanonicalFonts().find(search); 1.879 + if (*index >= 0) { 1.880 + return true; 1.881 + } 1.882 + search.fGlyphID = 0; 1.883 + *index = CanonicalFonts().find(search); 1.884 + return false; 1.885 +} 1.886 + 1.887 +SkPDFFont::SkPDFFont(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, 1.888 + SkPDFDict* relatedFontDescriptor) 1.889 + : SkPDFDict("Font"), 1.890 + fTypeface(ref_or_default(typeface)), 1.891 + fFirstGlyphID(1), 1.892 + fLastGlyphID(info ? info->fLastGlyphID : 0), 1.893 + fFontInfo(SkSafeRef(info)), 1.894 + fDescriptor(SkSafeRef(relatedFontDescriptor)) { 1.895 + if (info == NULL) { 1.896 + fFontType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 1.897 + } else if (info->fMultiMaster) { 1.898 + fFontType = SkAdvancedTypefaceMetrics::kOther_Font; 1.899 + } else { 1.900 + fFontType = info->fType; 1.901 + } 1.902 +} 1.903 + 1.904 +// static 1.905 +SkPDFFont* SkPDFFont::Create(SkAdvancedTypefaceMetrics* info, 1.906 + SkTypeface* typeface, uint16_t glyphID, 1.907 + SkPDFDict* relatedFontDescriptor) { 1.908 + SkAdvancedTypefaceMetrics::FontType type = 1.909 + info ? info->fType : SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 1.910 + 1.911 + if (info && info->fMultiMaster) { 1.912 + NOT_IMPLEMENTED(true, true); 1.913 + return new SkPDFType3Font(info, 1.914 + typeface, 1.915 + glyphID); 1.916 + } 1.917 + if (type == SkAdvancedTypefaceMetrics::kType1CID_Font || 1.918 + type == SkAdvancedTypefaceMetrics::kTrueType_Font) { 1.919 + SkASSERT(relatedFontDescriptor == NULL); 1.920 + return new SkPDFType0Font(info, typeface); 1.921 + } 1.922 + if (type == SkAdvancedTypefaceMetrics::kType1_Font) { 1.923 + return new SkPDFType1Font(info, 1.924 + typeface, 1.925 + glyphID, 1.926 + relatedFontDescriptor); 1.927 + } 1.928 + 1.929 + SkASSERT(type == SkAdvancedTypefaceMetrics::kCFF_Font || 1.930 + type == SkAdvancedTypefaceMetrics::kOther_Font || 1.931 + type == SkAdvancedTypefaceMetrics::kNotEmbeddable_Font); 1.932 + 1.933 + return new SkPDFType3Font(info, typeface, glyphID); 1.934 +} 1.935 + 1.936 +SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() { 1.937 + return fFontInfo.get(); 1.938 +} 1.939 + 1.940 +void SkPDFFont::setFontInfo(SkAdvancedTypefaceMetrics* info) { 1.941 + if (info == NULL || info == fFontInfo.get()) { 1.942 + return; 1.943 + } 1.944 + fFontInfo.reset(info); 1.945 + SkSafeRef(info); 1.946 +} 1.947 + 1.948 +uint16_t SkPDFFont::firstGlyphID() const { 1.949 + return fFirstGlyphID; 1.950 +} 1.951 + 1.952 +uint16_t SkPDFFont::lastGlyphID() const { 1.953 + return fLastGlyphID; 1.954 +} 1.955 + 1.956 +void SkPDFFont::setLastGlyphID(uint16_t glyphID) { 1.957 + fLastGlyphID = glyphID; 1.958 +} 1.959 + 1.960 +void SkPDFFont::addResource(SkPDFObject* object) { 1.961 + SkASSERT(object != NULL); 1.962 + fResources.push(object); 1.963 + object->ref(); 1.964 +} 1.965 + 1.966 +SkPDFDict* SkPDFFont::getFontDescriptor() { 1.967 + return fDescriptor.get(); 1.968 +} 1.969 + 1.970 +void SkPDFFont::setFontDescriptor(SkPDFDict* descriptor) { 1.971 + fDescriptor.reset(descriptor); 1.972 + SkSafeRef(descriptor); 1.973 +} 1.974 + 1.975 +bool SkPDFFont::addCommonFontDescriptorEntries(int16_t defaultWidth) { 1.976 + if (fDescriptor.get() == NULL) { 1.977 + return false; 1.978 + } 1.979 + 1.980 + const uint16_t emSize = fFontInfo->fEmSize; 1.981 + 1.982 + fDescriptor->insertName("FontName", fFontInfo->fFontName); 1.983 + fDescriptor->insertInt("Flags", fFontInfo->fStyle | kPdfSymbolic); 1.984 + fDescriptor->insertScalar("Ascent", 1.985 + scaleFromFontUnits(fFontInfo->fAscent, emSize)); 1.986 + fDescriptor->insertScalar("Descent", 1.987 + scaleFromFontUnits(fFontInfo->fDescent, emSize)); 1.988 + fDescriptor->insertScalar("StemV", 1.989 + scaleFromFontUnits(fFontInfo->fStemV, emSize)); 1.990 + fDescriptor->insertScalar("CapHeight", 1.991 + scaleFromFontUnits(fFontInfo->fCapHeight, emSize)); 1.992 + fDescriptor->insertInt("ItalicAngle", fFontInfo->fItalicAngle); 1.993 + fDescriptor->insert("FontBBox", makeFontBBox(fFontInfo->fBBox, 1.994 + fFontInfo->fEmSize))->unref(); 1.995 + 1.996 + if (defaultWidth > 0) { 1.997 + fDescriptor->insertScalar("MissingWidth", 1.998 + scaleFromFontUnits(defaultWidth, emSize)); 1.999 + } 1.1000 + return true; 1.1001 +} 1.1002 + 1.1003 +void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(int16_t glyphID) { 1.1004 + // Single byte glyph encoding supports a max of 255 glyphs. 1.1005 + fFirstGlyphID = glyphID - (glyphID - 1) % 255; 1.1006 + if (fLastGlyphID > fFirstGlyphID + 255 - 1) { 1.1007 + fLastGlyphID = fFirstGlyphID + 255 - 1; 1.1008 + } 1.1009 +} 1.1010 + 1.1011 +bool SkPDFFont::FontRec::operator==(const SkPDFFont::FontRec& b) const { 1.1012 + if (fFontID != b.fFontID) { 1.1013 + return false; 1.1014 + } 1.1015 + if (fFont != NULL && b.fFont != NULL) { 1.1016 + return fFont->fFirstGlyphID == b.fFont->fFirstGlyphID && 1.1017 + fFont->fLastGlyphID == b.fFont->fLastGlyphID; 1.1018 + } 1.1019 + if (fGlyphID == 0 || b.fGlyphID == 0) { 1.1020 + return true; 1.1021 + } 1.1022 + 1.1023 + if (fFont != NULL) { 1.1024 + return fFont->fFirstGlyphID <= b.fGlyphID && 1.1025 + b.fGlyphID <= fFont->fLastGlyphID; 1.1026 + } else if (b.fFont != NULL) { 1.1027 + return b.fFont->fFirstGlyphID <= fGlyphID && 1.1028 + fGlyphID <= b.fFont->fLastGlyphID; 1.1029 + } 1.1030 + return fGlyphID == b.fGlyphID; 1.1031 +} 1.1032 + 1.1033 +SkPDFFont::FontRec::FontRec(SkPDFFont* font, uint32_t fontID, uint16_t glyphID) 1.1034 + : fFont(font), 1.1035 + fFontID(fontID), 1.1036 + fGlyphID(glyphID) { 1.1037 +} 1.1038 + 1.1039 +void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { 1.1040 + if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) { 1.1041 + return; 1.1042 + } 1.1043 + SkAutoTUnref<SkPDFStream> pdfCmap( 1.1044 + generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset, 1.1045 + multiByteGlyphs(), firstGlyphID(), 1.1046 + lastGlyphID())); 1.1047 + addResource(pdfCmap.get()); 1.1048 + insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref(); 1.1049 +} 1.1050 + 1.1051 +/////////////////////////////////////////////////////////////////////////////// 1.1052 +// class SkPDFType0Font 1.1053 +/////////////////////////////////////////////////////////////////////////////// 1.1054 + 1.1055 +SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info, 1.1056 + SkTypeface* typeface) 1.1057 + : SkPDFFont(info, typeface, NULL) { 1.1058 + SkDEBUGCODE(fPopulated = false); 1.1059 +} 1.1060 + 1.1061 +SkPDFType0Font::~SkPDFType0Font() {} 1.1062 + 1.1063 +SkPDFFont* SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) { 1.1064 + SkPDFType0Font* newSubset = new SkPDFType0Font(fontInfo(), typeface()); 1.1065 + newSubset->populate(subset); 1.1066 + return newSubset; 1.1067 +} 1.1068 + 1.1069 +#ifdef SK_DEBUG 1.1070 +void SkPDFType0Font::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 1.1071 + bool indirect) { 1.1072 + SkASSERT(fPopulated); 1.1073 + return INHERITED::emitObject(stream, catalog, indirect); 1.1074 +} 1.1075 +#endif 1.1076 + 1.1077 +bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) { 1.1078 + insertName("Subtype", "Type0"); 1.1079 + insertName("BaseFont", fontInfo()->fFontName); 1.1080 + insertName("Encoding", "Identity-H"); 1.1081 + 1.1082 + SkAutoTUnref<SkPDFCIDFont> newCIDFont( 1.1083 + new SkPDFCIDFont(fontInfo(), typeface(), subset)); 1.1084 + addResource(newCIDFont.get()); 1.1085 + SkAutoTUnref<SkPDFArray> descendantFonts(new SkPDFArray()); 1.1086 + descendantFonts->append(new SkPDFObjRef(newCIDFont.get()))->unref(); 1.1087 + insert("DescendantFonts", descendantFonts.get()); 1.1088 + 1.1089 + populateToUnicodeTable(subset); 1.1090 + 1.1091 + SkDEBUGCODE(fPopulated = true); 1.1092 + return true; 1.1093 +} 1.1094 + 1.1095 +/////////////////////////////////////////////////////////////////////////////// 1.1096 +// class SkPDFCIDFont 1.1097 +/////////////////////////////////////////////////////////////////////////////// 1.1098 + 1.1099 +SkPDFCIDFont::SkPDFCIDFont(SkAdvancedTypefaceMetrics* info, 1.1100 + SkTypeface* typeface, const SkPDFGlyphSet* subset) 1.1101 + : SkPDFFont(info, typeface, NULL) { 1.1102 + populate(subset); 1.1103 +} 1.1104 + 1.1105 +SkPDFCIDFont::~SkPDFCIDFont() {} 1.1106 + 1.1107 +bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, 1.1108 + const SkTDArray<uint32_t>* subset) { 1.1109 + SkAutoTUnref<SkPDFDict> descriptor(new SkPDFDict("FontDescriptor")); 1.1110 + setFontDescriptor(descriptor.get()); 1.1111 + addResource(descriptor.get()); 1.1112 + 1.1113 + switch (getType()) { 1.1114 + case SkAdvancedTypefaceMetrics::kTrueType_Font: { 1.1115 + SkASSERT(subset); 1.1116 + // Font subsetting 1.1117 + SkPDFStream* rawStream = NULL; 1.1118 + int fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(), 1.1119 + typeface(), 1.1120 + *subset, 1.1121 + &rawStream); 1.1122 + SkASSERT(fontSize); 1.1123 + SkASSERT(rawStream); 1.1124 + SkAutoTUnref<SkPDFStream> fontStream(rawStream); 1.1125 + addResource(fontStream.get()); 1.1126 + 1.1127 + fontStream->insertInt("Length1", fontSize); 1.1128 + descriptor->insert("FontFile2", 1.1129 + new SkPDFObjRef(fontStream.get()))->unref(); 1.1130 + break; 1.1131 + } 1.1132 + case SkAdvancedTypefaceMetrics::kCFF_Font: 1.1133 + case SkAdvancedTypefaceMetrics::kType1CID_Font: { 1.1134 + int ttcIndex; 1.1135 + SkAutoTUnref<SkStream> fontData(typeface()->openStream(&ttcIndex)); 1.1136 + SkAutoTUnref<SkPDFStream> fontStream( 1.1137 + new SkPDFStream(fontData.get())); 1.1138 + addResource(fontStream.get()); 1.1139 + 1.1140 + if (getType() == SkAdvancedTypefaceMetrics::kCFF_Font) { 1.1141 + fontStream->insertName("Subtype", "Type1C"); 1.1142 + } else { 1.1143 + fontStream->insertName("Subtype", "CIDFontType0c"); 1.1144 + } 1.1145 + descriptor->insert("FontFile3", 1.1146 + new SkPDFObjRef(fontStream.get()))->unref(); 1.1147 + break; 1.1148 + } 1.1149 + default: 1.1150 + SkASSERT(false); 1.1151 + } 1.1152 + 1.1153 + insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref(); 1.1154 + return addCommonFontDescriptorEntries(defaultWidth); 1.1155 +} 1.1156 + 1.1157 +bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { 1.1158 + // Generate new font metrics with advance info for true type fonts. 1.1159 + if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { 1.1160 + // Generate glyph id array. 1.1161 + SkTDArray<uint32_t> glyphIDs; 1.1162 + if (subset) { 1.1163 + // Always include glyph 0. 1.1164 + if (!subset->has(0)) { 1.1165 + glyphIDs.push(0); 1.1166 + } 1.1167 + subset->exportTo(&glyphIDs); 1.1168 + } 1.1169 + 1.1170 + SkAdvancedTypefaceMetrics::PerGlyphInfo info; 1.1171 + info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo; 1.1172 + info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( 1.1173 + info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); 1.1174 + uint32_t* glyphs = (glyphIDs.count() == 0) ? NULL : glyphIDs.begin(); 1.1175 + uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; 1.1176 + SkAutoTUnref<SkAdvancedTypefaceMetrics> fontMetrics( 1.1177 + typeface()->getAdvancedTypefaceMetrics(info, glyphs, glyphsCount)); 1.1178 + setFontInfo(fontMetrics.get()); 1.1179 + addFontDescriptor(0, &glyphIDs); 1.1180 + } else { 1.1181 + // Other CID fonts 1.1182 + addFontDescriptor(0, NULL); 1.1183 + } 1.1184 + 1.1185 + insertName("BaseFont", fontInfo()->fFontName); 1.1186 + 1.1187 + if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { 1.1188 + insertName("Subtype", "CIDFontType0"); 1.1189 + } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) { 1.1190 + insertName("Subtype", "CIDFontType2"); 1.1191 + insertName("CIDToGIDMap", "Identity"); 1.1192 + } else { 1.1193 + SkASSERT(false); 1.1194 + } 1.1195 + 1.1196 + SkAutoTUnref<SkPDFDict> sysInfo(new SkPDFDict); 1.1197 + sysInfo->insert("Registry", new SkPDFString("Adobe"))->unref(); 1.1198 + sysInfo->insert("Ordering", new SkPDFString("Identity"))->unref(); 1.1199 + sysInfo->insertInt("Supplement", 0); 1.1200 + insert("CIDSystemInfo", sysInfo.get()); 1.1201 + 1.1202 + if (fontInfo()->fGlyphWidths.get()) { 1.1203 + int16_t defaultWidth = 0; 1.1204 + SkAutoTUnref<SkPDFArray> widths( 1.1205 + composeAdvanceData(fontInfo()->fGlyphWidths.get(), 1.1206 + fontInfo()->fEmSize, &appendWidth, 1.1207 + &defaultWidth)); 1.1208 + if (widths->size()) 1.1209 + insert("W", widths.get()); 1.1210 + if (defaultWidth != 0) { 1.1211 + insertScalar("DW", scaleFromFontUnits(defaultWidth, 1.1212 + fontInfo()->fEmSize)); 1.1213 + } 1.1214 + } 1.1215 + if (fontInfo()->fVerticalMetrics.get()) { 1.1216 + struct SkAdvancedTypefaceMetrics::VerticalMetric defaultAdvance; 1.1217 + defaultAdvance.fVerticalAdvance = 0; 1.1218 + defaultAdvance.fOriginXDisp = 0; 1.1219 + defaultAdvance.fOriginYDisp = 0; 1.1220 + SkAutoTUnref<SkPDFArray> advances( 1.1221 + composeAdvanceData(fontInfo()->fVerticalMetrics.get(), 1.1222 + fontInfo()->fEmSize, &appendVerticalAdvance, 1.1223 + &defaultAdvance)); 1.1224 + if (advances->size()) 1.1225 + insert("W2", advances.get()); 1.1226 + if (defaultAdvance.fVerticalAdvance || 1.1227 + defaultAdvance.fOriginXDisp || 1.1228 + defaultAdvance.fOriginYDisp) { 1.1229 + insert("DW2", appendVerticalAdvance(defaultAdvance, 1.1230 + fontInfo()->fEmSize, 1.1231 + new SkPDFArray))->unref(); 1.1232 + } 1.1233 + } 1.1234 + 1.1235 + return true; 1.1236 +} 1.1237 + 1.1238 +/////////////////////////////////////////////////////////////////////////////// 1.1239 +// class SkPDFType1Font 1.1240 +/////////////////////////////////////////////////////////////////////////////// 1.1241 + 1.1242 +SkPDFType1Font::SkPDFType1Font(SkAdvancedTypefaceMetrics* info, 1.1243 + SkTypeface* typeface, 1.1244 + uint16_t glyphID, 1.1245 + SkPDFDict* relatedFontDescriptor) 1.1246 + : SkPDFFont(info, typeface, relatedFontDescriptor) { 1.1247 + populate(glyphID); 1.1248 +} 1.1249 + 1.1250 +SkPDFType1Font::~SkPDFType1Font() {} 1.1251 + 1.1252 +bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) { 1.1253 + if (getFontDescriptor() != NULL) { 1.1254 + SkPDFDict* descriptor = getFontDescriptor(); 1.1255 + addResource(descriptor); 1.1256 + insert("FontDescriptor", new SkPDFObjRef(descriptor))->unref(); 1.1257 + return true; 1.1258 + } 1.1259 + 1.1260 + SkAutoTUnref<SkPDFDict> descriptor(new SkPDFDict("FontDescriptor")); 1.1261 + setFontDescriptor(descriptor.get()); 1.1262 + 1.1263 + int ttcIndex; 1.1264 + size_t header SK_INIT_TO_AVOID_WARNING; 1.1265 + size_t data SK_INIT_TO_AVOID_WARNING; 1.1266 + size_t trailer SK_INIT_TO_AVOID_WARNING; 1.1267 + SkAutoTUnref<SkStream> rawFontData(typeface()->openStream(&ttcIndex)); 1.1268 + SkStream* fontData = handleType1Stream(rawFontData.get(), &header, &data, 1.1269 + &trailer); 1.1270 + if (fontData == NULL) { 1.1271 + return false; 1.1272 + } 1.1273 + SkAutoTUnref<SkPDFStream> fontStream(new SkPDFStream(fontData)); 1.1274 + addResource(fontStream.get()); 1.1275 + fontStream->insertInt("Length1", header); 1.1276 + fontStream->insertInt("Length2", data); 1.1277 + fontStream->insertInt("Length3", trailer); 1.1278 + descriptor->insert("FontFile", new SkPDFObjRef(fontStream.get()))->unref(); 1.1279 + 1.1280 + addResource(descriptor.get()); 1.1281 + insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref(); 1.1282 + 1.1283 + return addCommonFontDescriptorEntries(defaultWidth); 1.1284 +} 1.1285 + 1.1286 +bool SkPDFType1Font::populate(int16_t glyphID) { 1.1287 + SkASSERT(!fontInfo()->fVerticalMetrics.get()); 1.1288 + SkASSERT(fontInfo()->fGlyphWidths.get()); 1.1289 + 1.1290 + adjustGlyphRangeForSingleByteEncoding(glyphID); 1.1291 + 1.1292 + int16_t defaultWidth = 0; 1.1293 + const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry = NULL; 1.1294 + const SkAdvancedTypefaceMetrics::WidthRange* widthEntry; 1.1295 + for (widthEntry = fontInfo()->fGlyphWidths.get(); 1.1296 + widthEntry != NULL; 1.1297 + widthEntry = widthEntry->fNext.get()) { 1.1298 + switch (widthEntry->fType) { 1.1299 + case SkAdvancedTypefaceMetrics::WidthRange::kDefault: 1.1300 + defaultWidth = widthEntry->fAdvance[0]; 1.1301 + break; 1.1302 + case SkAdvancedTypefaceMetrics::WidthRange::kRun: 1.1303 + SkASSERT(false); 1.1304 + break; 1.1305 + case SkAdvancedTypefaceMetrics::WidthRange::kRange: 1.1306 + SkASSERT(widthRangeEntry == NULL); 1.1307 + widthRangeEntry = widthEntry; 1.1308 + break; 1.1309 + } 1.1310 + } 1.1311 + 1.1312 + if (!addFontDescriptor(defaultWidth)) { 1.1313 + return false; 1.1314 + } 1.1315 + 1.1316 + insertName("Subtype", "Type1"); 1.1317 + insertName("BaseFont", fontInfo()->fFontName); 1.1318 + 1.1319 + addWidthInfoFromRange(defaultWidth, widthRangeEntry); 1.1320 + 1.1321 + SkAutoTUnref<SkPDFDict> encoding(new SkPDFDict("Encoding")); 1.1322 + insert("Encoding", encoding.get()); 1.1323 + 1.1324 + SkAutoTUnref<SkPDFArray> encDiffs(new SkPDFArray); 1.1325 + encoding->insert("Differences", encDiffs.get()); 1.1326 + 1.1327 + encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); 1.1328 + encDiffs->appendInt(1); 1.1329 + for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { 1.1330 + encDiffs->appendName(fontInfo()->fGlyphNames->get()[gID].c_str()); 1.1331 + } 1.1332 + 1.1333 + return true; 1.1334 +} 1.1335 + 1.1336 +void SkPDFType1Font::addWidthInfoFromRange( 1.1337 + int16_t defaultWidth, 1.1338 + const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry) { 1.1339 + SkAutoTUnref<SkPDFArray> widthArray(new SkPDFArray()); 1.1340 + int firstChar = 0; 1.1341 + if (widthRangeEntry) { 1.1342 + const uint16_t emSize = fontInfo()->fEmSize; 1.1343 + int startIndex = firstGlyphID() - widthRangeEntry->fStartId; 1.1344 + int endIndex = startIndex + lastGlyphID() - firstGlyphID() + 1; 1.1345 + if (startIndex < 0) 1.1346 + startIndex = 0; 1.1347 + if (endIndex > widthRangeEntry->fAdvance.count()) 1.1348 + endIndex = widthRangeEntry->fAdvance.count(); 1.1349 + if (widthRangeEntry->fStartId == 0) { 1.1350 + appendWidth(widthRangeEntry->fAdvance[0], emSize, widthArray.get()); 1.1351 + } else { 1.1352 + firstChar = startIndex + widthRangeEntry->fStartId; 1.1353 + } 1.1354 + for (int i = startIndex; i < endIndex; i++) { 1.1355 + appendWidth(widthRangeEntry->fAdvance[i], emSize, widthArray.get()); 1.1356 + } 1.1357 + } else { 1.1358 + appendWidth(defaultWidth, 1000, widthArray.get()); 1.1359 + } 1.1360 + insertInt("FirstChar", firstChar); 1.1361 + insertInt("LastChar", firstChar + widthArray->size() - 1); 1.1362 + insert("Widths", widthArray.get()); 1.1363 +} 1.1364 + 1.1365 +/////////////////////////////////////////////////////////////////////////////// 1.1366 +// class SkPDFType3Font 1.1367 +/////////////////////////////////////////////////////////////////////////////// 1.1368 + 1.1369 +SkPDFType3Font::SkPDFType3Font(SkAdvancedTypefaceMetrics* info, 1.1370 + SkTypeface* typeface, 1.1371 + uint16_t glyphID) 1.1372 + : SkPDFFont(info, typeface, NULL) { 1.1373 + populate(glyphID); 1.1374 +} 1.1375 + 1.1376 +SkPDFType3Font::~SkPDFType3Font() {} 1.1377 + 1.1378 +bool SkPDFType3Font::populate(int16_t glyphID) { 1.1379 + SkPaint paint; 1.1380 + paint.setTypeface(typeface()); 1.1381 + paint.setTextSize(1000); 1.1382 + SkAutoGlyphCache autoCache(paint, NULL, NULL); 1.1383 + SkGlyphCache* cache = autoCache.getCache(); 1.1384 + // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. 1.1385 + if (lastGlyphID() == 0) { 1.1386 + setLastGlyphID(cache->getGlyphCount() - 1); 1.1387 + } 1.1388 + 1.1389 + adjustGlyphRangeForSingleByteEncoding(glyphID); 1.1390 + 1.1391 + insertName("Subtype", "Type3"); 1.1392 + // Flip about the x-axis and scale by 1/1000. 1.1393 + SkMatrix fontMatrix; 1.1394 + fontMatrix.setScale(SkScalarInvert(1000), -SkScalarInvert(1000)); 1.1395 + insert("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix))->unref(); 1.1396 + 1.1397 + SkAutoTUnref<SkPDFDict> charProcs(new SkPDFDict); 1.1398 + insert("CharProcs", charProcs.get()); 1.1399 + 1.1400 + SkAutoTUnref<SkPDFDict> encoding(new SkPDFDict("Encoding")); 1.1401 + insert("Encoding", encoding.get()); 1.1402 + 1.1403 + SkAutoTUnref<SkPDFArray> encDiffs(new SkPDFArray); 1.1404 + encoding->insert("Differences", encDiffs.get()); 1.1405 + encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); 1.1406 + encDiffs->appendInt(1); 1.1407 + 1.1408 + SkAutoTUnref<SkPDFArray> widthArray(new SkPDFArray()); 1.1409 + 1.1410 + SkIRect bbox = SkIRect::MakeEmpty(); 1.1411 + for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { 1.1412 + SkString characterName; 1.1413 + characterName.printf("gid%d", gID); 1.1414 + encDiffs->appendName(characterName.c_str()); 1.1415 + 1.1416 + const SkGlyph& glyph = cache->getGlyphIDMetrics(gID); 1.1417 + widthArray->appendScalar(SkFixedToScalar(glyph.fAdvanceX)); 1.1418 + SkIRect glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop, 1.1419 + glyph.fWidth, glyph.fHeight); 1.1420 + bbox.join(glyphBBox); 1.1421 + 1.1422 + SkDynamicMemoryWStream content; 1.1423 + setGlyphWidthAndBoundingBox(SkFixedToScalar(glyph.fAdvanceX), glyphBBox, 1.1424 + &content); 1.1425 + const SkPath* path = cache->findPath(glyph); 1.1426 + if (path) { 1.1427 + SkPDFUtils::EmitPath(*path, paint.getStyle(), &content); 1.1428 + SkPDFUtils::PaintPath(paint.getStyle(), path->getFillType(), 1.1429 + &content); 1.1430 + } 1.1431 + SkAutoTUnref<SkMemoryStream> glyphStream(new SkMemoryStream()); 1.1432 + glyphStream->setData(content.copyToData())->unref(); 1.1433 + 1.1434 + SkAutoTUnref<SkPDFStream> glyphDescription( 1.1435 + new SkPDFStream(glyphStream.get())); 1.1436 + addResource(glyphDescription.get()); 1.1437 + charProcs->insert(characterName.c_str(), 1.1438 + new SkPDFObjRef(glyphDescription.get()))->unref(); 1.1439 + } 1.1440 + 1.1441 + insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); 1.1442 + insertInt("FirstChar", 1); 1.1443 + insertInt("LastChar", lastGlyphID() - firstGlyphID() + 1); 1.1444 + insert("Widths", widthArray.get()); 1.1445 + insertName("CIDToGIDMap", "Identity"); 1.1446 + 1.1447 + populateToUnicodeTable(NULL); 1.1448 + return true; 1.1449 +}