[fondue-commits] [SCM] Fondue Font Editor branch, master, updated. 27cf9e647f964aa8405f8f640064c8a4bf67a88f

Eugeniy Meshcheryakov eugen at debian.org
Fri Aug 31 20:12:47 UTC 2007


The branch, master has been updated
       via  27cf9e647f964aa8405f8f640064c8a4bf67a88f (commit)
      from  4d21308791bbc7e5a917cda8941a114d9c4e9c68 (commit)


- Shortlog ------------------------------------------------------------
27cf9e6 generate type 4 and (if needed) type 12 cmaps

Summary of changes:
 nongui/ttfwriter.cxx |  103 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 92 insertions(+), 11 deletions(-)
-----------------------------------------------------------------------
Details of changes:

commit 27cf9e647f964aa8405f8f640064c8a4bf67a88f
Author: Eugeniy Meshcheryakov <eugen at debian.org>
Date:   Fri Aug 31 22:12:36 2007 +0200

    generate type 4 and (if needed) type 12 cmaps

diff --git a/nongui/ttfwriter.cxx b/nongui/ttfwriter.cxx
index 266142f..5ed9752 100644
--- a/nongui/ttfwriter.cxx
+++ b/nongui/ttfwriter.cxx
@@ -472,35 +472,116 @@ bool TTFWriter::writeHead()
 	return ret;
 }
 
+struct TTUnicodeRange {
+	unsigned first;
+	unsigned last;
+	quint16 glyph;
+};
+
 bool TTFWriter::writeCmap()
 {
 	// XXX TODO writes minimal cmap
+	QList<TTUnicodeRange> ranges;
+	unsigned nBMP = 0; // number of ranges in BMP, at least partly
+	bool hasNonBMP = false; // if true, font needs additional type 12 cmap
+	bool has0xFFFF = false;
+	if (encodedGlyphsCount) {
+		TTUnicodeRange range;
+		range.first = range.last = sortedGlyphs.at(1)->unicode();
+		range.glyph = 1;
+		if (range.first < 0x10000)
+			nBMP++;
+
+		for (int i = 2; i <= encodedGlyphsCount; i++) {
+			unsigned u = sortedGlyphs.at(i)->unicode();
+			if (u == 0xFFFF)
+				has0xFFFF = true;
+			if (u == range.last + 1)
+				range.last += 1;
+			else {
+				ranges << range;
+				range.first = range.last = u;
+				range.glyph = i;
+				if (range.first < 0x10000)
+					nBMP++;
+			}
+		}
+		ranges << range;
+		if (range.last > 0xFFFF)
+			hasNonBMP = true;
+	}
+
 	QByteArray tbl;
 	QBuffer buffer(&tbl);
 	buffer.open(QBuffer::WriteOnly);
 
+	quint16 nSubtables = hasNonBMP? 2 : 1;
+	quint16 type4SegCount = has0xFFFF ? nBMP : nBMP + 1;
+	quint32 type4CmapOffset = 4 /* header */ + 8 * nSubtables /* subtables */;
+	quint16 type4Length = 16 /* fixed part of type4 cmap */ + 8 * type4SegCount;
+	quint32 type12CmapOffset = type4CmapOffset + type4Length;
+
+	quint16 type4SearchRange = 2 * maxPowerOfTwo(type4SegCount);
+	quint16 type4EntrySelector = integerLog2(type4SearchRange / 2);
+	quint16 type4RangeShift = 2 * type4SegCount - type4SearchRange;
+
 	bool ret = true;
 	// Table header
 	ret = ret && writeBigEndian(&buffer, (quint16)0); // Version
-	ret = ret && writeBigEndian(&buffer, (quint16)1); // FIXME Number of subtables
+	ret = ret && writeBigEndian(&buffer, (quint16)nSubtables); // FIXME Number of subtables
 	
 	// Subtables
 	ret = ret && writeBigEndian(&buffer, (quint16)3); // Platform ID, 3 - MS
 	ret = ret && writeBigEndian(&buffer, (quint16)1); // Encoding ID, 1 - Unicode
-	ret = ret && writeBigEndian(&buffer, (quint32)12); // FIXME offset of cmap
+	ret = ret && writeBigEndian(&buffer, (quint32)type4CmapOffset); // Offset of cmap
+	if (hasNonBMP) {
+		ret = ret && writeBigEndian(&buffer, (quint16)3); // Platform ID, 3 - MS
+		ret = ret && writeBigEndian(&buffer, (quint16)10); // Encoding ID, 10 - UCS-4
+		ret = ret && writeBigEndian(&buffer, (quint32)type12CmapOffset); // Offset of cmap
+	}
 	// Type 4 cmap
 	ret = ret && writeBigEndian(&buffer, (quint16)4); // cmap format
-	ret = ret && writeBigEndian(&buffer, (quint16)24); // FIXME Length
+	ret = ret && writeBigEndian(&buffer, (quint16)type4Length); // Length
 	ret = ret && writeBigEndian(&buffer, (quint16)0); // Language
-	ret = ret && writeBigEndian(&buffer, (quint16)2); // FIXME 2 * SegCount
-	ret = ret && writeBigEndian(&buffer, (quint16)4); // FIXME Search range
-	ret = ret && writeBigEndian(&buffer, (quint16)1); // FIXME Entry selector
-	ret = ret && writeBigEndian(&buffer, (quint16)0); // FIXME Range shift
-	ret = ret && writeBigEndian(&buffer, (quint16)0xFFFF); // End code
+	ret = ret && writeBigEndian(&buffer, (quint16)(2 * type4SegCount)); // 2 * SegCount
+	ret = ret && writeBigEndian(&buffer, (quint16)type4SearchRange); // Search range
+	ret = ret && writeBigEndian(&buffer, (quint16)type4EntrySelector); // Entry selector
+	ret = ret && writeBigEndian(&buffer, (quint16)type4RangeShift); // Range shift
+	// End codes
+	for (unsigned i = 0; i < nBMP; i++)
+		ret = ret && writeBigEndian(&buffer, 
+				(quint16)(ranges.at(i).last > 0xFFFF ? 0xFFFF : ranges.at(i).last));
+	if (!has0xFFFF)
+		ret = ret && writeBigEndian(&buffer, (quint16)0xFFFF);
 	ret = ret && writeBigEndian(&buffer, (quint16)0); // Reserved
-	ret = ret && writeBigEndian(&buffer, (quint16)0xFFFF); // Start code
-	ret = ret && writeBigEndian(&buffer, (quint16)1); // FIXME ID delta
-	ret = ret && writeBigEndian(&buffer, (quint16)0); // FIXME ID range offset
+	// Start Codes
+	for (unsigned i = 0; i < nBMP; i++)
+		ret = ret && writeBigEndian(&buffer, (quint16)ranges.at(i).first);
+	if (!has0xFFFF)
+		ret = ret && writeBigEndian(&buffer, (quint16)0xFFFF);
+	// ID Delta
+	for (unsigned i = 0; i < nBMP; i++)
+		ret = ret && writeBigEndian(&buffer, (quint16)(ranges.at(i).glyph - ranges.at(i).first));
+	if (!has0xFFFF)
+		ret = ret && writeBigEndian(&buffer, (quint16)1);
+	for (unsigned i = 0; i < type4SegCount; i++)
+		ret = ret && writeBigEndian(&buffer, (quint16)0); // ID range offset
+	if (ret)
+		Q_ASSERT(buffer.pos() == type4CmapOffset + type4Length); // FIXME remove or check for overflows
+
+	if (hasNonBMP) {
+		// type 12 cmap
+		ret = ret && writeBigEndian(&buffer, (quint32)0x000C0000); // Format, 12.0
+		ret = ret && writeBigEndian(&buffer, (quint32)(ranges.size() * 12 + 16)); // Length
+		ret = ret && writeBigEndian(&buffer, (quint32)0); // Language, 0 - don't care
+		ret = ret && writeBigEndian(&buffer, (quint32)ranges.size()); // Number of groups
+		foreach (const TTUnicodeRange &r, ranges) {
+			ret = ret && writeBigEndian(&buffer, (quint32)r.first);
+			ret = ret && writeBigEndian(&buffer, (quint32)r.last);
+			ret = ret && writeBigEndian(&buffer, (quint32)r.glyph);
+		}
+	}
+
 	buffer.close();
 	if (ret)
 		appendTable(makeTag('c', 'm', 'a', 'p'), tbl);

-- 
Fondue Font Editor



More information about the fondue-commits mailing list