David PHAM-VAN

Support 64k glyphs per TTF font

# 1.3.7
* Add Pdf Creation date
* Support 64k glyphs per TTF font
# 1.3.6
* Fix TTF Font SubSetting
... ...
... ... @@ -27,6 +27,9 @@ class PdfTtfFont extends PdfFont {
widthsObject = PdfArrayObject(pdfDocument, <String>[]);
}
@override
String get subtype => font.unicode ? '/Type0' : super.subtype;
PdfUnicodeCmap unicodeCMap;
PdfFontDescriptor descriptor;
... ... @@ -57,26 +60,60 @@ class PdfTtfFont extends PdfFont {
return font.glyphInfoMap[g] ?? PdfFontMetrics.zero;
}
@override
void _prepare() {
void _buildTrueType(Map<String, PdfStream> params) {
int charMin;
int charMax;
super._prepare();
file.buf.putBytes(font.bytes.buffer.asUint8List());
file.params['/Length1'] = PdfStream.intNum(font.bytes.lengthInBytes);
params['/BaseFont'] = PdfStream.string('/' + fontName);
params['/FontDescriptor'] = descriptor.ref();
charMin = 32;
charMax = 255;
for (int i = charMin; i <= charMax; i++) {
widthsObject.values
.add((glyphMetrics(i).advanceWidth * 1000.0).toInt().toString());
}
params['/FirstChar'] = PdfStream.intNum(charMin);
params['/LastChar'] = PdfStream.intNum(charMax);
params['/Widths'] = widthsObject.ref();
}
void _buildType0(Map<String, PdfStream> params) {
int charMin;
int charMax;
final TtfWriter ttfWriter = TtfWriter(font);
final Uint8List data = ttfWriter.withChars(unicodeCMap.cmap);
file.buf.putBytes(data);
file.params['/Length1'] = PdfStream.intNum(data.length);
final PdfStream descendantFont = PdfStream.dictionary(<String, PdfStream>{
'/Type': PdfStream.string('/Font'),
'/BaseFont': PdfStream.string('/' + fontName),
'/FontFile2': file.ref(),
'/FontDescriptor': descriptor.ref(),
'/W': PdfStream.array(<PdfStream>[
PdfStream.intNum(0),
widthsObject.ref(),
]),
'/CIDToGIDMap': PdfStream.string('/Identity'),
'/DW': PdfStream.string('1000'),
'/Subtype': PdfStream.string('/CIDFontType2'),
'/CIDSystemInfo': PdfStream.dictionary(<String, PdfStream>{
'/Supplement': PdfStream.intNum(0),
'/Registry': PdfStream()..putText('Adobe'),
'/Ordering': PdfStream()..putText('Identity-H'),
})
});
params['/BaseFont'] = PdfStream.string('/' + fontName);
params['/FontDescriptor'] = descriptor.ref();
if (font.unicode) {
if (params.containsKey('/Encoding')) {
params.remove('/Encoding');
}
params['/Encoding'] = PdfStream.string('/Identity-H');
params['/DescendantFonts'] = PdfStream()
..putArray(<PdfStream>[descendantFont]);
params['/ToUnicode'] = unicodeCMap.ref();
charMin = 0;
charMax = unicodeCMap.cmap.length - 1;
for (int i = charMin; i <= charMax; i++) {
... ... @@ -85,17 +122,17 @@ class PdfTtfFont extends PdfFont {
.toInt()
.toString());
}
} else {
charMin = 32;
charMax = 255;
for (int i = charMin; i <= charMax; i++) {
widthsObject.values
.add((glyphMetrics(i).advanceWidth * 1000.0).toInt().toString());
}
@override
void _prepare() {
super._prepare();
if (font.unicode) {
_buildType0(params);
} else {
_buildTrueType(params);
}
params['/FirstChar'] = PdfStream.intNum(charMin);
params['/LastChar'] = PdfStream.intNum(charMax);
params['/Widths'] = widthsObject.ref();
}
@override
... ... @@ -105,7 +142,8 @@ class PdfTtfFont extends PdfFont {
}
final Runes runes = text.runes;
final List<int> bytes = List<int>();
final PdfStream stream = PdfStream();
stream.putBytes(latin1.encode('<'));
for (int rune in runes) {
int char = unicodeCMap.cmap.indexOf(rune);
if (char == -1) {
... ... @@ -113,13 +151,10 @@ class PdfTtfFont extends PdfFont {
unicodeCMap.cmap.add(rune);
}
bytes.add(char);
stream.putBytes(latin1.encode(char.toRadixString(16).padLeft(4, '0')));
}
return PdfStream()
..putBytes(latin1.encode('('))
..putTextBytes(bytes)
..putBytes(latin1.encode(')'));
stream.putBytes(latin1.encode('>'));
return stream;
}
@override
... ...
... ... @@ -34,14 +34,14 @@ class PdfUnicodeCmap extends PdfObjectStream {
'/CMapName/Adobe-Identity-UCS def\n'
'/CMapType 2 def\n'
'1 begincodespacerange\n'
'<00> <FF>\n'
'<0000> <FFFF>\n'
'endcodespacerange\n'
'${cmap.length} beginbfchar\n');
for (int key = 0; key < cmap.length; key++) {
final int value = cmap[key];
buf.putString('<' +
key.toRadixString(16).toUpperCase().padLeft(2, '0') +
key.toRadixString(16).toUpperCase().padLeft(4, '0') +
'> <' +
value.toRadixString(16).toUpperCase().padLeft(4, '0') +
'>\n');
... ...