Created
February 23, 2012 13:21
-
-
Save Bokugene/1892760 to your computer and use it in GitHub Desktop.
Read Table Data from a CGFont, then wrap them into a OTF/TTF font.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef struct FontHeader { | |
int32_t fVersion; | |
uint16_t fNumTables; | |
uint16_t fSearchRange; | |
uint16_t fEntrySelector; | |
uint16_t fRangeShift; | |
}FontHeader; | |
typedef struct TableEntry { | |
uint32_t fTag; | |
uint32_t fCheckSum; | |
uint32_t fOffset; | |
uint32_t fLength; | |
}TableEntry; | |
static uint32_t CalcTableCheckSum(const uint32_t *table, uint32_t numberOfBytesInTable) { | |
uint32_t sum = 0; | |
uint32_t nLongs = (numberOfBytesInTable + 3) / 4; | |
while (nLongs-- > 0) { | |
sum += CFSwapInt32HostToBig(*table++); | |
} | |
return sum; | |
} | |
static uint32_t CalcTableDataRefCheckSum(CFDataRef dataRef) { | |
const uint32_t *dataBuff = (const uint32_t *)CFDataGetBytePtr(dataRef); | |
uint32_t dataLength = (uint32_t)CFDataGetLength(dataRef); | |
return CalcTableCheckSum(dataBuff, dataLength); | |
} | |
//Reference: | |
//http://skia.googlecode.com/svn-history/r1473/trunk/src/ports/SkFontHost_mac_coretext.cpp | |
- (NSData *)fontDataForCGFont:(CGFontRef)cgFont{ | |
if (!cgFont) { | |
return nil; | |
} | |
CFRetain(cgFont); | |
CFArrayRef tags = CGFontCopyTableTags(cgFont); | |
int tableCount = CFArrayGetCount(tags); | |
size_t *tableSizes = malloc(sizeof(size_t) * tableCount); | |
memset(tableSizes, 0, sizeof(size_t) * tableCount); | |
BOOL containsCFFTable = NO; | |
size_t totalSize = sizeof(FontHeader) + sizeof(TableEntry) * tableCount; | |
for (int index = 0; index < tableCount; ++index) { | |
//get size | |
size_t tableSize = 0; | |
uint32_t aTag = (uint32_t)CFArrayGetValueAtIndex(tags, index); | |
if (aTag == 'CFF ' && !containsCFFTable) { | |
containsCFFTable = YES; | |
} | |
CFDataRef tableDataRef = CGFontCopyTableForTag(cgFont, aTag); | |
if (tableDataRef != NULL) { | |
tableSize = CFDataGetLength(tableDataRef); | |
CFRelease(tableDataRef); | |
} | |
totalSize += (tableSize + 3) & ~3; | |
tableSizes[index] = tableSize; | |
} | |
unsigned char *stream = malloc(totalSize); | |
memset(stream, 0, totalSize); | |
char* dataStart = (char*)stream; | |
char* dataPtr = dataStart; | |
// compute font header entries | |
uint16_t entrySelector = 0; | |
uint16_t searchRange = 1; | |
while (searchRange < tableCount >> 1) { | |
entrySelector++; | |
searchRange <<= 1; | |
} | |
searchRange <<= 4; | |
uint16_t rangeShift = (tableCount << 4) - searchRange; | |
// write font header (also called sfnt header, offset subtable) | |
FontHeader* offsetTable = (FontHeader*)dataPtr; | |
//OpenType Font contains CFF Table use 'OTTO' as version, and with .otf extension | |
//otherwise 0001 0000 | |
offsetTable->fVersion = containsCFFTable ? 'OTTO' : CFSwapInt16HostToBig(1); | |
offsetTable->fNumTables = CFSwapInt16HostToBig((uint16_t)tableCount); | |
offsetTable->fSearchRange = CFSwapInt16HostToBig((uint16_t)searchRange); | |
offsetTable->fEntrySelector = CFSwapInt16HostToBig((uint16_t)entrySelector); | |
offsetTable->fRangeShift = CFSwapInt16HostToBig((uint16_t)rangeShift); | |
dataPtr += sizeof(FontHeader); | |
// write tables | |
TableEntry* entry = (TableEntry*)dataPtr; | |
dataPtr += sizeof(TableEntry) * tableCount; | |
for (int index = 0; index < tableCount; ++index) { | |
uint32_t aTag = (uint32_t)CFArrayGetValueAtIndex(tags, index); | |
CFDataRef tableDataRef = CGFontCopyTableForTag(cgFont, aTag); | |
size_t tableSize = CFDataGetLength(tableDataRef); | |
memcpy(dataPtr, CFDataGetBytePtr(tableDataRef), tableSize); | |
entry->fTag = CFSwapInt32HostToBig((uint32_t)aTag); | |
entry->fCheckSum = CFSwapInt32HostToBig(CalcTableCheckSum((uint32_t *)dataPtr, tableSize)); | |
uint32_t offset = dataPtr - dataStart; | |
entry->fOffset = CFSwapInt32HostToBig((uint32_t)offset); | |
entry->fLength = CFSwapInt32HostToBig((uint32_t)tableSize); | |
dataPtr += (tableSize + 3) & ~3; | |
++entry; | |
CFRelease(tableDataRef); | |
} | |
CFRelease(cgFont); | |
free(tableSizes); | |
NSData *fontData = [NSData dataWithBytesNoCopy:stream | |
length:totalSize | |
freeWhenDone:YES]; | |
return fontData; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Would it be possible for you to specify a license for this code? According to the GitHub guidelines, when a license isn't specified (like here), essentially nobody is legally allowed to use the code.