kreativekorp / bitsnpicas

Bits'N'Picas - Bitmap & Emoji Font Creation & Conversion Tools
339 stars 23 forks source link

BDF to TTF conversion isn't idempotent #35

Open sunaku opened 1 year ago

sunaku commented 1 year ago

Hello,

TTF files converted from BDF files are always slightly different (in terms of their binary file contents; not in terms of actual appearance / font rendering) each time they are converted. Specifically, byte offsets 50-51 (represented by the 0x40 line in the hexdump below) as well as bytes in the offset range 160-192 (represented by the 0xb0-0xc0 lines in the hexdump below) vary each time I do the conversion (as follows) using the latest Bits'N'Picas built from the Git master branch at commit 6eb4d3b5e7983d9e99906bf26561ca32d6b36c30.

Could the conversion be made idempotent, so that a given BDF file always produces the same TTF output? (stable checksum)

Thanks for your consideration.

java -jar bitsnpicas/main/java/BitsNPicas/BitsNPicas.jar convertbitmap -f ttf -o ttf/TamzenForPowerline10x20r.ttf bdf/TamzenForPowerline10x20r.bdf

image

diff --git a/ttf/Tamzen10x20r.ttf b/ttf/Tamzen10x20r.ttf
index 71b654a..dff6a2c 100644
--- a/ttf/Tamzen10x20r.ttf
+++ b/ttf/Tamzen10x20r.ttf
@@ -2,15 +2,15 @@
 00000010  98 52 67 3a 00 00 01 28  00 00 00 64 63 6d 61 70  |.Rg:...(...dcmap|
 00000020  06 fe 06 7b 00 00 04 88  00 00 00 cc 67 6c 79 66  |...{........glyf|
 00000030  30 1d 56 05 00 00 08 54  00 00 66 70 68 65 61 64  |0.V....T..fphead|
-00000040  23 39 f8 f5 00 00 00 ac  00 00 00 36 68 68 65 61  |#9.........6hhea|
+00000040  23 39 f9 1f 00 00 00 ac  00 00 00 36 68 68 65 61  |#9.........6hhea|
 00000050  09 62 02 50 00 00 00 e4  00 00 00 24 68 6d 74 78  |.b.P.......$hmtx|
 00000060  e6 30 56 b8 00 00 01 8c  00 00 02 fc 6c 6f 63 61  |.0V.........loca|
 00000070  00 25 34 24 00 00 05 54  00 00 03 00 6d 61 78 70  |.%4$...T....maxp|
 00000080  01 24 01 92 00 00 01 08  00 00 00 20 6e 61 6d 65  |.$......... name|
 00000090  cd 53 84 6c 00 00 6e c4  00 00 03 b1 70 6f 73 74  |.S.l..n.....post|
 000000a0  a3 80 d5 9b 00 00 72 78  00 00 02 17 00 01 00 00  |......rx........|
-000000b0  00 01 1c 29 fc e7 f5 ad  5f 0f 3c f5 00 03 07 d0  |...)...._.<.....|
-000000c0  00 00 00 00 e0 1e 4a 69  00 00 00 00 e0 1e 4a 69  |......Ji......Ji|
+000000b0  00 01 1c 29 fc e7 f5 59  5f 0f 3c f5 00 03 07 d0  |...)...Y_.<.....|
+000000c0  00 00 00 00 e0 1e 4a 7e  00 00 00 00 e0 1e 4a 7e  |......J~......J~|
 000000d0  00 00 fd a8 03 e8 05 78  00 00 00 14 00 00 00 01  |.......x........|
 000000e0  00 00 00 00 00 01 00 00  05 78 fd a8 00 00 03 e8  |.........x......|
 000000f0  00 00 00 00 03 e8 00 01  00 00 00 00 00 00 00 00  |................|
sunaku commented 1 year ago

In the meantime, I'm working around this issue by hacking makeHeadTable() in the TTFBitmapFontExporter class as follows:

diff --git a/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporter/TTFBitmapFontExporter.java b/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporter/TTFBitmapFontExporter.java
index bdf6669..9d05c2f 100755
--- a/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporter/TTFBitmapFontExporter.java
+++ b/main/java/BitsNPicas/src/com/kreative/bitsnpicas/exporter/TTFBitmapFontExporter.java
@@ -242,8 +242,8 @@ public class TTFBitmapFontExporter implements BitmapFontExporter {
        headTable.setFontRevisionDouble(fontVersion);
        headTable.flags = HeadTable.FLAGS_Y_VALUE_OF_ZERO_SPECIFIES_BASELINE | HeadTable.FLAGS_MINIMUM_X_VALUE_IS_LEFT_SIDE_BEARING;
        headTable.unitsPerEm = (bf.getEmAscent() + bf.getEmDescent()) * ysize;
-       headTable.setDateCreatedCalendar(now);
-       headTable.setDateModifiedCalendar(now);
        headTable.xMin = a.bbx1;
        headTable.yMin = a.bby1;
        headTable.xMax = a.bbx2;
sunaku commented 1 year ago

I'm thinking of adding either a new -nt flag that disables timestamps entirely (like the hack in my previous comment above) or two new -ct and -mt options that let the user specify the creation and modification times respectively on the command line.

Which would you prefer? :nerd_face: I'll submit a pull request accordingly.