static void readGPOSTable(SFFontRef sfFont) { CFDataRef gposTable = CGFontCopyTableForTag(sfFont->_cgFont, 'GPOS'); if (gposTable) { const SFUByte * const tableBytes = CFDataGetBytePtr(gposTable); SFReadGPOS(tableBytes, &sfFont->_gpos); sfFont->_availableFontTables |= itGPOS; CFRelease(gposTable); } }
static void readGSUBTable(SFFontRef sfFont) { CFDataRef gsubTable = CGFontCopyTableForTag(sfFont->_cgFont, 'GSUB'); if (gsubTable) { const SFUByte * const tableBytes = CFDataGetBytePtr(gsubTable); SFReadGSUB(tableBytes, &sfFont->_gsub); sfFont->_availableFontTables |= itGSUB; CFRelease(gsubTable); } }
static void readGDEFTable(SFFontRef sfFont) { CFDataRef gdefData = CGFontCopyTableForTag(sfFont->_cgFont, 'GDEF'); if (gdefData) { const SFUByte * const tableBytes = CFDataGetBytePtr(gdefData); SFReadGDEF(tableBytes, &sfFont->_gdef); sfFont->_availableFontTables |= itGDEF; CFRelease(gdefData); } }
static void readCMAPTable(SFFontRef sfFont) { CFDataRef cmapData = CGFontCopyTableForTag(sfFont->_cgFont, 'cmap'); if (cmapData) { const SFUByte * const tableBytes = CFDataGetBytePtr(cmapData); SFReadCMAP(tableBytes, &sfFont->_cmap, CFDataGetLength(cmapData)); sfFont->_availableFontTables |= itCMAP; CFRelease(cmapData); } }
static hb_blob_t* harfBuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void* userData) { CGFontRef cgFont = reinterpret_cast<CGFontRef>(userData); CFDataRef cfData = CGFontCopyTableForTag(cgFont, tag); if (!cfData) return 0; const char* data = reinterpret_cast<const char*>(CFDataGetBytePtr(cfData)); const size_t length = CFDataGetLength(cfData); if (!data || !length) return 0; return hb_blob_create(data, length, HB_MEMORY_MODE_READONLY, reinterpret_cast<void*>(const_cast<__CFData*>(cfData)), releaseTableData); }
bool ScaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) { // We'll reconstruct a TTF font from the tables we can get from the CGFont CFArrayRef tags = CGFontCopyTableTags(mFont); CFIndex count = CFArrayGetCount(tags); TableRecord *records = new TableRecord[count]; uint32_t offset = 0; offset += sizeof(uint32_t)*3; offset += sizeof(uint32_t)*4*count; bool CFF = false; for (CFIndex i = 0; i<count; i++) { uint32_t tag = (uint32_t)(uintptr_t)CFArrayGetValueAtIndex(tags, i); if (tag == 0x43464620) // 'CFF ' CFF = true; CFDataRef data = CGFontCopyTableForTag(mFont, tag); records[i].tag = tag; records[i].offset = offset; records[i].data = data; records[i].length = CFDataGetLength(data); bool skipChecksumAdjust = (tag == 0x68656164); // 'head' records[i].checkSum = CalcTableChecksum(reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(data)), records[i].length, skipChecksumAdjust); offset += records[i].length; // 32 bit align the tables offset = (offset + 3) & ~3; } CFRelease(tags); struct writeBuf buf(offset); // write header/offset table if (CFF) { buf.writeElement(CFSwapInt32HostToBig(0x4f54544f)); } else { buf.writeElement(CFSwapInt32HostToBig(0x00010000)); } buf.writeElement(CFSwapInt16HostToBig(count)); buf.writeElement(CFSwapInt16HostToBig((1<<maxPow2LessThan(count))*16)); buf.writeElement(CFSwapInt16HostToBig(maxPow2LessThan(count))); buf.writeElement(CFSwapInt16HostToBig(count*16-((1<<maxPow2LessThan(count))*16))); // write table record entries for (CFIndex i = 0; i<count; i++) { buf.writeElement(CFSwapInt32HostToBig(records[i].tag)); buf.writeElement(CFSwapInt32HostToBig(records[i].checkSum)); buf.writeElement(CFSwapInt32HostToBig(records[i].offset)); buf.writeElement(CFSwapInt32HostToBig(records[i].length)); } // write tables int checkSumAdjustmentOffset = 0; for (CFIndex i = 0; i<count; i++) { if (records[i].tag == 0x68656164) { checkSumAdjustmentOffset = buf.offset + 2*4; } buf.writeMem(CFDataGetBytePtr(records[i].data), CFDataGetLength(records[i].data)); buf.align(); CFRelease(records[i].data); } delete[] records; // clear the checksumAdjust field before checksumming the whole font memset(&buf.data[checkSumAdjustmentOffset], 0, sizeof(uint32_t)); uint32_t fontChecksum = CFSwapInt32HostToBig(0xb1b0afba - CalcTableChecksum(reinterpret_cast<const uint32_t*>(buf.data), offset)); // set checkSumAdjust to the computed checksum memcpy(&buf.data[checkSumAdjustmentOffset], &fontChecksum, sizeof(fontChecksum)); // we always use an index of 0 aDataCallback(buf.data, buf.offset, 0, mSize, aBaton); return true; }