18eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary/* 28eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * Copyright 2011 Google Inc. 38eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * 48eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * Use of this source code is governed by a BSD-style license that can be 58eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * found in the LICENSE file. 68eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary */ 78eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 88eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary#include "SkPDFConvertType1FontStream.h" 94d1955c43aaab045511b74a495dfbea4ef0057c5Ben Wagner#include "SkTemplates.h" 108eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 118eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary#include <ctype.h> 128eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 138eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanarystatic bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType, 148eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t* size) { 158eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // PFB sections have a two or six bytes header. 0x80 and a one byte 168eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // section type followed by a four byte section length. Type one is 178eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // an ASCII section (includes a length), type two is a binary section 188eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // (includes a length) and type three is an EOF marker with no length. 198eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const uint8_t* buf = *src; 208eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) { 218eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return false; 228eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } else if (buf[1] == 3) { 238eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return true; 248eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } else if (*len < 6) { 258eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return false; 268eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 278eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 288eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) | 298eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary ((size_t)buf[5] << 24); 308eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t consumed = *size + 6; 318eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (consumed > *len) { 328eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return false; 338eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 348eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary *src = *src + consumed; 358eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary *len = *len - consumed; 368eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return true; 378eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary} 388eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 398eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanarystatic bool parsePFB(const uint8_t* src, size_t size, size_t* headerLen, 408eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t* dataLen, size_t* trailerLen) { 418eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const uint8_t* srcPtr = src; 428eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t remaining = size; 438eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 448eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return parsePFBSection(&srcPtr, &remaining, 1, headerLen) && 458eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary parsePFBSection(&srcPtr, &remaining, 2, dataLen) && 468eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary parsePFBSection(&srcPtr, &remaining, 1, trailerLen) && 478eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary parsePFBSection(&srcPtr, &remaining, 3, nullptr); 488eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary} 498eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 508eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary/* The sections of a PFA file are implicitly defined. The body starts 518eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * after the line containing "eexec," and the trailer starts with 512 528eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * literal 0's followed by "cleartomark" (plus arbitrary white space). 538eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * 548eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * This function assumes that src is NUL terminated, but the NUL 558eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * termination is not included in size. 568eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary * 578eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary */ 588eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanarystatic bool parsePFA(const char* src, size_t size, size_t* headerLen, 598eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t* hexDataLen, size_t* dataLen, size_t* trailerLen) { 608eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const char* end = src + size; 618eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 628eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const char* dataPos = strstr(src, "eexec"); 638eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (!dataPos) { 648eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return false; 658eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 668eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary dataPos += strlen("eexec"); 678eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') && 688eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary dataPos < end) { 698eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary dataPos++; 708eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 718eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary *headerLen = dataPos - src; 728eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 738eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const char* trailerPos = strstr(dataPos, "cleartomark"); 748eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (!trailerPos) { 758eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return false; 768eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 778eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary int zeroCount = 0; 788eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) { 798eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') { 808eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary continue; 818eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } else if (*trailerPos == '0') { 828eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary zeroCount++; 838eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } else { 848eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return false; 858eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 868eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 878eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (zeroCount != 512) { 888eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return false; 898eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 908eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 918eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary *hexDataLen = trailerPos - src - *headerLen; 928eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary *trailerLen = size - *headerLen - *hexDataLen; 938eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 948eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // Verify that the data section is hex encoded and count the bytes. 958eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary int nibbles = 0; 968eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary for (; dataPos < trailerPos; dataPos++) { 978eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (isspace(*dataPos)) { 988eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary continue; 998eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1008eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (!isxdigit(*dataPos)) { 1018eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return false; 1028eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1038eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary nibbles++; 1048eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1058eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary *dataLen = (nibbles + 1) / 2; 1068eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1078eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return true; 1088eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary} 1098eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1108eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanarystatic int8_t hexToBin(uint8_t c) { 1118eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (!isxdigit(c)) { 1128eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return -1; 1138eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } else if (c <= '9') { 1148eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return c - '0'; 1158eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } else if (c <= 'F') { 1168eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return c - 'A' + 10; 1178eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } else if (c <= 'f') { 1188eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return c - 'a' + 10; 1198eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1208eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return -1; 1218eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary} 1228eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1238eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanarysk_sp<SkData> SkPDFConvertType1FontStream( 1248eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary std::unique_ptr<SkStreamAsset> srcStream, size_t* headerLen, 1258eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t* dataLen, size_t* trailerLen) { 1268eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t srcLen = srcStream ? srcStream->getLength() : 0; 1278eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary SkASSERT(srcLen); 1288eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (!srcLen) { 1298eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return nullptr; 1308eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1318eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // Flatten and Nul-terminate the source stream so that we can use 1328eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // strstr() to search it. 1338eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary SkAutoTMalloc<uint8_t> sourceBuffer(SkToInt(srcLen + 1)); 1348eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary (void)srcStream->read(sourceBuffer.get(), srcLen); 1358eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary sourceBuffer[SkToInt(srcLen)] = 0; 1368eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const uint8_t* src = sourceBuffer.get(); 1378eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1388eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) { 1398eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary static const int kPFBSectionHeaderLength = 6; 1408eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const size_t length = *headerLen + *dataLen + *trailerLen; 1418eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary SkASSERT(length > 0); 1428eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary SkASSERT(length + (2 * kPFBSectionHeaderLength) <= srcLen); 1438eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1448eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary sk_sp<SkData> data(SkData::MakeUninitialized(length)); 1458eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1468eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const uint8_t* const srcHeader = src + kPFBSectionHeaderLength; 1478eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // There is a six-byte section header before header and data 1488eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // (but not trailer) that we're not going to copy. 1498eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const uint8_t* const srcData = srcHeader + *headerLen + kPFBSectionHeaderLength; 1508eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const uint8_t* const srcTrailer = srcData + *headerLen; 1518eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1528eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary uint8_t* const resultHeader = (uint8_t*)data->writable_data(); 1538eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary uint8_t* const resultData = resultHeader + *headerLen; 1548eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary uint8_t* const resultTrailer = resultData + *dataLen; 1558eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1568eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary SkASSERT(resultTrailer + *trailerLen == resultHeader + length); 1578eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1588eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary memcpy(resultHeader, srcHeader, *headerLen); 1598eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary memcpy(resultData, srcData, *dataLen); 1608eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary memcpy(resultTrailer, srcTrailer, *trailerLen); 1618eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1628eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return data; 1638eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1648eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1658eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary // A PFA has to be converted for PDF. 1668eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t hexDataLen; 1678eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (!parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen, 1688eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary trailerLen)) { 1698eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return nullptr; 1708eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1718eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const size_t length = *headerLen + *dataLen + *trailerLen; 1728eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary SkASSERT(length > 0); 1738eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary auto data = SkData::MakeUninitialized(length); 1748eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary uint8_t* buffer = (uint8_t*)data->writable_data(); 1758eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1768eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary memcpy(buffer, src, *headerLen); 1778eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary uint8_t* const resultData = &(buffer[*headerLen]); 1788eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 1798eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const uint8_t* hexData = src + *headerLen; 1808eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary const uint8_t* trailer = hexData + hexDataLen; 1818eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary size_t outputOffset = 0; 1828eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary uint8_t dataByte = 0; // To hush compiler. 1838eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary bool highNibble = true; 1848eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary for (; hexData < trailer; hexData++) { 1858eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary int8_t curNibble = hexToBin(*hexData); 1868eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (curNibble < 0) { 1878eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary continue; 1888eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1898eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (highNibble) { 1908eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary dataByte = curNibble << 4; 1918eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary highNibble = false; 1928eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } else { 1938eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary dataByte |= curNibble; 1948eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary highNibble = true; 1958eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary resultData[outputOffset++] = dataByte; 1968eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1978eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 1988eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary if (!highNibble) { 1998eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary resultData[outputOffset++] = dataByte; 2008eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary } 2018eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary SkASSERT(outputOffset == *dataLen); 2028eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary 2038eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary uint8_t* const resultTrailer = &(buffer[SkToInt(*headerLen + outputOffset)]); 2048eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen); 2058eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary return data; 2068eccc308c8adcdf26ffc7c4dd538b71f33c6f22bhalcanary} 207