diff -Nru birdfont-2.30.0/birdfont/GtkWindow.vala birdfont-2.32.0/birdfont/GtkWindow.vala --- birdfont-2.30.0/birdfont/GtkWindow.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/birdfont/GtkWindow.vala 2022-05-25 16:55:10.000000000 +0000 @@ -81,12 +81,7 @@ uri = Preview.get_uri (); html = Preview.get_html_with_absolute_paths (); - try { - html_canvas.load_html (html, uri); - } catch (Error e) { - warning (e.message); - warning ("Failed to load html into canvas."); - } + html_canvas.load_html (html, uri); // show the webview when loading has finished html_box.set_visible (true); @@ -331,16 +326,16 @@ } else { if ((flags & FileChooser.DIRECTORY) > 0) { if ((flags & FileChooser.LOAD) > 0) { - fn = show_file_chooser (title, FileChooserAction.SELECT_FOLDER, Stock.OPEN); + fn = show_file_chooser (title, FileChooserAction.SELECT_FOLDER, t_("Open")); } else if ((flags & FileChooser.SAVE) > 0) { - fn = show_file_chooser (title, FileChooserAction.SELECT_FOLDER, Stock.SAVE); + fn = show_file_chooser (title, FileChooserAction.SELECT_FOLDER, t_("Save")); } else { warning ("Open or save is not set."); } } else if ((flags & FileChooser.LOAD) > 0) { - fn = show_file_chooser (title, FileChooserAction.OPEN, Stock.OPEN); + fn = show_file_chooser (title, FileChooserAction.OPEN, t_("Open")); } else if ((flags & FileChooser.SAVE) > 0) { - fn = show_file_chooser (title, FileChooserAction.SAVE, Stock.SAVE); + fn = show_file_chooser (title, FileChooserAction.SAVE, t_("Save")); } else { warning ("Unknown type"); } @@ -351,7 +346,7 @@ public string? show_file_chooser (string title, FileChooserAction action, string label) { string? fn = null; - FileChooserDialog file_chooser = new FileChooserDialog (title, this, action, Stock.CANCEL, ResponseType.CANCEL, label, ResponseType.ACCEPT); + FileChooserDialog file_chooser = new FileChooserDialog (title, this, action, t_("Cancel"), ResponseType.CANCEL, label, ResponseType.ACCEPT); Font font = BirdFont.get_current_font (); int i; string last_folder; @@ -415,7 +410,7 @@ background_task = t; try { - bg = Thread.create (this.background_thread, true); + bg = new Thread.try ("bg", this.background_thread); } catch (GLib.Error e) { warning (e.message); } @@ -425,7 +420,7 @@ unowned Thread bg; try { - bg = Thread.create (t.perform_task, true); + bg = new Thread.try ("bg", t.perform_task); } catch (GLib.Error e) { warning (e.message); } @@ -444,7 +439,7 @@ MenuTab.start_background_thread (); try { - export_thread = Thread.create (this.export_thread, true); + export_thread = new Thread.try ("export_thread", this.export_thread); } catch (GLib.Error e) { warning (e.message); } @@ -460,7 +455,11 @@ idle.set_callback (() => { Notify.Notification export_notification; export_notification = new Notify.Notification ("BirdFont", t_("Your fonts have been exported."), null); - export_notification.show (); + try { + export_notification.show (); + } catch (GLib.Error e) { + warning (e.message); + } return false; }); idle.attach (null); @@ -475,7 +474,7 @@ MenuTab.start_background_thread (); try { - thread = Thread.create (this.loading_thread, true); + thread = new Thread.try ("thread", this.loading_thread); } catch (GLib.Error e) { warning (e.message); } @@ -495,7 +494,7 @@ MenuTab.start_background_thread (); try { - thread = Thread.create (this.saving_thread, true); + thread = new Thread.try ("thread", this.saving_thread); } catch (GLib.Error e) { warning (e.message); } @@ -514,7 +513,7 @@ MenuTab.start_background_thread (); try { - thread = Thread.create (this.background_image_thread, true); + thread = new Thread.try ("thread", this.background_image_thread); } catch (GLib.Error e) { warning (e.message); } @@ -576,9 +575,9 @@ draw.connect ((t, e)=> { Gtk.Allocation alloc; - Context cr; + Context cr = e; - cr = cairo_create ((!) get_window ()); + //cr = cairo_create ((!) get_window ()); get_allocation (out alloc); tabbar.draw (cr, alloc.width, alloc.height); @@ -642,7 +641,8 @@ Gtk.Allocation allocation; get_allocation (out allocation); - Context cw = cairo_create((!) get_window()); + Context cw = e; + //cw = cairo_create((!) get_window()); Toolbox.allocation_width = allocation.width; Toolbox.allocation_height = allocation.height; tb.draw (allocation.width, allocation.height, cw); @@ -705,7 +705,8 @@ alloc.x = allocation.x; alloc.y = allocation.y; - Context cw = cairo_create ((!) get_window()); + Context cw = e; + //cw = cairo_create ((!) get_window()); Surface s = new Surface.similar (cw.get_target (), Cairo.Content.COLOR_ALPHA, alloc.width, alloc.height); Context c = new Context (s); diff -Nru birdfont-2.30.0/birdfont-test/TestRunner.vala birdfont-2.32.0/birdfont-test/TestRunner.vala --- birdfont-2.30.0/birdfont-test/TestRunner.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/birdfont-test/TestRunner.vala 2022-05-25 16:55:10.000000000 +0000 @@ -221,7 +221,7 @@ MenuTab.start_background_thread (); try { - bg = Thread.create (t.perform_task, true); + bg = new Thread.try ("bg", t.perform_task); } catch (GLib.Error e) { warning (e.message); } @@ -231,7 +231,7 @@ unowned Thread bg; try { - bg = Thread.create (t.perform_task, true); + bg = new Thread.try ("bg", t.perform_task); } catch (GLib.Error e) { warning (e.message); } diff -Nru birdfont-2.30.0/debian/changelog birdfont-2.32.0/debian/changelog --- birdfont-2.30.0/debian/changelog 2022-02-15 10:39:57.000000000 +0000 +++ birdfont-2.32.0/debian/changelog 2022-05-28 10:15:30.000000000 +0000 @@ -1,3 +1,13 @@ +birdfont (2.32.0-1) unstable; urgency=medium + + * New upstream release + * debian/copyright + - update copyright year + * debian/control + - Set Standards-Version: 4.6.1 with no changes + + -- Hideki Yamane Sat, 28 May 2022 19:15:30 +0900 + birdfont (2.30.0-1) unstable; urgency=medium * New upstream release diff -Nru birdfont-2.30.0/debian/control birdfont-2.32.0/debian/control --- birdfont-2.30.0/debian/control 2022-02-15 10:39:57.000000000 +0000 +++ birdfont-2.32.0/debian/control 2022-05-28 10:15:30.000000000 +0000 @@ -7,7 +7,7 @@ libglib2.0-dev, libgtk-3-dev, libgee-0.8-dev, libnotify-dev, libwebkit2gtk-4.0-dev, libsqlite3-dev, libxmlbird-dev, python3-pkg-resources -Standards-Version: 4.6.0 +Standards-Version: 4.6.1 Homepage: https://birdfont.org/ Vcs-Git: https://salsa.debian.org/fonts-team/birdfont.git Vcs-Browser: https://salsa.debian.org/fonts-team/birdfont diff -Nru birdfont-2.30.0/debian/copyright birdfont-2.32.0/debian/copyright --- birdfont-2.30.0/debian/copyright 2022-02-15 10:39:57.000000000 +0000 +++ birdfont-2.32.0/debian/copyright 2022-05-28 10:15:30.000000000 +0000 @@ -3,7 +3,7 @@ Source: https://birdfont.org/releases/ Files: * -Copyright: 2012-2021 Johan Mattsson +Copyright: 2012-2022 Johan Mattsson License: GPL-3+ Files: resources/linux/birdfont.appdata.xml @@ -130,7 +130,7 @@ License: GPL-3+ Files: debian/* -Copyright: 2012-2021 Hideki Yamane +Copyright: 2012-2022 Hideki Yamane License: GPL-3+ License: GPL-3+ diff -Nru birdfont-2.30.0/fixed-kerning-example/build.sh birdfont-2.32.0/fixed-kerning-example/build.sh --- birdfont-2.30.0/fixed-kerning-example/build.sh 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/build.sh 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,2 @@ +#!/bin/sh +gcc *.c -o kerning-example -lm diff -Nru birdfont-2.30.0/fixed-kerning-example/clean.sh birdfont-2.32.0/fixed-kerning-example/clean.sh --- birdfont-2.30.0/fixed-kerning-example/clean.sh 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/clean.sh 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,2 @@ +#!/bin/sh +rm -f kerning-example fixedkerningtable.test basic.test diff -Nru birdfont-2.30.0/fixed-kerning-example/fk.c birdfont-2.32.0/fixed-kerning-example/fk.c --- birdfont-2.30.0/fixed-kerning-example/fk.c 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/fk.c 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,181 @@ +/* + * This is example code. Using this code in any project with any license is permitted. + * Author: Johan Mattsson + */ +#include +#include +#include +#include +#include +#include + +#include "fk.h" + +uint8_t* fk_get_subtable_entries(uint8_t* otf_table, size_t table_size, size_t* subtable_size); + +double fk_fixed_to_double (Fixed16_16 val) { + return val / 65536.0; +} + +uint16_t fk_get_uint16 (uint8_t* otf_table, size_t table_size, size_t index) { + if (index + 1 >= table_size) { + fprintf(stderr, "Index out of bounds: %zu Buffer size: %zu.\n", index, table_size); + return 0; + } + + uint16_t val = otf_table[index + 1] << 8; + val |= otf_table[index]; + return val; +} + +uint32_t fk_get_uint32 (uint8_t* otf_table, size_t table_size, size_t index) { + if (index + 3 >= table_size) { + fprintf(stderr, "Index out of bounds: %zu Buffer size: %zu.\n", index, table_size); + return 0; + } + + uint32_t val = fk_get_uint16 (otf_table, table_size, index) << 16; + val |= fk_get_uint16 (otf_table, table_size, index + 2); + + return val; +} + +void fk_write_u8 (FILE* file, uint8_t val) { + fwrite(&val, 1, sizeof(uint8_t), file); +} + +void fk_write_u16 (FILE* file, uint16_t val) { + fk_write_u8 (file, (uint8_t) ((val & 0x00FF) >> (8 * 0))); + fk_write_u8 (file, (uint8_t) ((val & 0xFF00) >> (8 * 1))); +} + +void fk_write_u32 (FILE* file, uint32_t val) { + uint16_t s = (uint16_t) (val >> 16); + + fk_write_u16 (file, (val & 0xFFFF0000) >> 16); + fk_write_u16 (file, val & 0x0000FFFF); +} + +uint32_t fk_get_int32 (uint8_t* otf_table, size_t table_size, size_t index) { + return (uint32_t) fk_get_uint32 (otf_table, table_size, index); +} + +/* +* This function ensures that we have data for the fixed kerning table. +* The get_fixed_kerning assumes that has_fixed_kerning has been used to +* check if we have a valid subtable with kerning entries. +*/ +bool fk_has_fixed_kerning (uint8_t* otf_table, size_t table_size) { + if (otf_table == NULL) { + fprintf(stderr, "No table for fixed kerning.\n"); + return false; + } + + if (table_size <= FIXED_KERNING_HEADER_SIZE) { + // No data in table + return false; + } + + if (table_size % 4 != 0) { + fprintf(stderr, "Bad padding in fixed kerning table, size: %zu.\n", table_size); + return false; + } + + uint16_t version_upper = fk_get_uint16(otf_table, table_size, 0); + uint16_t version_lower = fk_get_uint16(otf_table, table_size, 2); + + if (version_upper != 1 || version_lower != 0) { + fprintf(stderr,"Bad version of fixed kerning table. Expecting 1.0 got %d.%d\n", version_upper, version_lower); + return false; + } + + uint32_t entries = fk_get_num_kerning_pairs (otf_table, table_size); + size_t subtable_size = table_size - FIXED_KERNING_HEADER_SIZE; + size_t expected_subtable_size = entries * 3 * sizeof(uint32_t); + + if (subtable_size != expected_subtable_size) { + fprintf(stderr,"Bad subtable size in fixed kerning table. Size %zu bytes expecting %zu bytes (added entries: %d).\n", subtable_size, expected_subtable_size, entries); + return false; + } + + return true; +} + +Fixed16_16 fk_get_fixed_kerning (uint8_t* otf_table, size_t table_size, uint32_t first_glyph_index, uint32_t second_glyph_index) { + uint32_t entries = fk_get_num_kerning_pairs(otf_table, table_size); + size_t subtable_size = 0; + uint8_t* subtable = fk_get_subtable_entries(otf_table, table_size, &subtable_size); + + int lower = 0; + int upper = entries; + const int second_gid_offset = sizeof(uint32_t); // offset from start of an kerning entry to the second glyph + const int kerning_offset = 2 * sizeof(uint32_t); // offset from start of an kerning entry to the kerning value + + uint64_t gid1 = first_glyph_index; + uint64_t gid2 = second_glyph_index; + uint64_t search_key = (gid1 << 32) | gid2; + + while (lower <= upper) { + size_t middle = lower + (upper - lower) / 2; + size_t index = middle; + + size_t row_index = index * 3 * sizeof(uint32_t); + uint64_t pair_key = fk_get_uint32 (subtable, subtable_size, row_index); + pair_key <<= 32; + pair_key |= fk_get_uint32 (subtable, subtable_size, row_index + second_gid_offset); + + if (pair_key == search_key) { + return (Fixed16_16) fk_get_uint32 (subtable, subtable_size, row_index + kerning_offset); + } + + if (pair_key < search_key) { + lower = middle + 1; + } else { + upper = middle - 1; + } + } + + return 0; +} + +uint8_t* fk_get_subtable_entries(uint8_t* otf_table, size_t table_size, size_t* subtable_size) { + if (table_size <= FIXED_KERNING_HEADER_SIZE) { + *subtable_size = 0; + return NULL; + } + + *subtable_size = table_size - FIXED_KERNING_HEADER_SIZE; + + return otf_table + FIXED_KERNING_HEADER_SIZE; +} + +uint32_t fk_get_num_kerning_pairs (uint8_t* otf_table, size_t table_size) { + if (table_size < FIXED_KERNING_HEADER_SIZE) { + printf("Kerning table is too short."); + return 0; + } + + return fk_get_uint32 (otf_table, table_size, 4); +} + +void fk_get_fixed_kerning_by_index (uint8_t* otf_table, size_t table_size, size_t index, uint32_t* first_glyph_index, uint32_t* second_glyph_index, Fixed16_16* kerning) { + uint32_t num_pairs = fk_get_num_kerning_pairs (otf_table, table_size); + size_t subtable_size = 0; + uint8_t* subtable = fk_get_subtable_entries (otf_table, table_size, &subtable_size); + + index *= FIXED_KERNING_ENTRY_SIZE; + + if (index + FIXED_KERNING_ENTRY_SIZE > subtable_size) { + fprintf (stderr, "Index out of bounds in fixed kerning table, index: %zu subtable size: %zu, item size: %ld\n", index, subtable_size, FIXED_KERNING_ENTRY_SIZE); + *first_glyph_index = 0; + *second_glyph_index = 0; + *kerning = 0; + return; + } + + *first_glyph_index = fk_get_uint32 (subtable, subtable_size, index); + *second_glyph_index = fk_get_uint32 (subtable, subtable_size, index + sizeof(uint32_t)); + + int32_t fixed_kerning = fk_get_int32 (subtable, subtable_size, index + 2 * sizeof(uint32_t)); + *kerning = fixed_kerning; +} diff -Nru birdfont-2.30.0/fixed-kerning-example/fk-example.birdfont birdfont-2.32.0/fixed-kerning-example/fk-example.birdfont --- birdfont-2.30.0/fixed-kerning-example/fk-example.birdfont 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/fk-example.birdfont 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,100 @@ + + +3.22 + + +FK-example +FK-example +Regular +false +false +FK-example +FK-example +Version 1.0 + +SIL Open Font License +SIL Open Font License +http://scripts.sil.org/OFL +400 +1024 + + + + +Bird + +-10 +3.5 +false +false +false + + + 78 + 72 + 56 + 0 + -20 + -21 + 10 + + + + + + + + +FK-example +FK-example Mac +true +true +false +false +false +false +false +true + + + +100 +5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Binary files /tmp/tmp6esk415k/p4LssQNduq/birdfont-2.30.0/fixed-kerning-example/FK-example Mac.otf and /tmp/tmp6esk415k/CqgTo9j6cB/birdfont-2.32.0/fixed-kerning-example/FK-example Mac.otf differ Binary files /tmp/tmp6esk415k/p4LssQNduq/birdfont-2.30.0/fixed-kerning-example/FK-example Mac.ttf and /tmp/tmp6esk415k/CqgTo9j6cB/birdfont-2.32.0/fixed-kerning-example/FK-example Mac.ttf differ Binary files /tmp/tmp6esk415k/p4LssQNduq/birdfont-2.30.0/fixed-kerning-example/FK-example.otf and /tmp/tmp6esk415k/CqgTo9j6cB/birdfont-2.32.0/fixed-kerning-example/FK-example.otf differ Binary files /tmp/tmp6esk415k/p4LssQNduq/birdfont-2.30.0/fixed-kerning-example/FK-example.ttf and /tmp/tmp6esk415k/CqgTo9j6cB/birdfont-2.32.0/fixed-kerning-example/FK-example.ttf differ diff -Nru birdfont-2.30.0/fixed-kerning-example/fk-font-editor.c birdfont-2.32.0/fixed-kerning-example/fk-font-editor.c --- birdfont-2.30.0/fixed-kerning-example/fk-font-editor.c 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/fk-font-editor.c 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * This is example code. Using this code in any project with any license is permitted. + * Author: Johan Mattsson + */ +#include +#include +#include +#include +#include +#include + +#include "fk.h" + +void fk_write_fixed_kerning_table_header (FILE* file, uint32_t num_kerning_pairs) { + uint16_t version_upper = 1; + uint16_t version_lower = 0; + uint16_t pairs = num_kerning_pairs; + + fk_write_u16 (file, version_upper); + fk_write_u16 (file, version_lower); + fk_write_u32 (file, pairs); +} + +Fixed16_16 fk_double_to_fixed (double v) { + int32_t val; + int32_t mant; + + val = (int32_t) floor (v); + mant = (int32_t) floor (0x10000 * (v - val)); + val = (val << 16) | mant; + + return val; +} + +void fk_write_fixed_kerning_entry (FILE* file, uint32_t glyph_index_first, uint32_t glyph_index_second, double kerning) { + int32_t fixed_kerning; + + if (kerning > INT16_MAX || kerning < INT16_MIN) { + fprintf(stderr, "Kerning is out of bounds.\n"); + kerning = 0; + } + + fixed_kerning = fk_double_to_fixed (kerning); + + fk_write_u32 (file, glyph_index_first); + fk_write_u32 (file, glyph_index_second); + fk_write_u32 (file, fixed_kerning); +} diff -Nru birdfont-2.30.0/fixed-kerning-example/fk-font-editor.h birdfont-2.32.0/fixed-kerning-example/fk-font-editor.h --- birdfont-2.30.0/fixed-kerning-example/fk-font-editor.h 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/fk-font-editor.h 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,14 @@ +/* + * This is example code. Using this code in any project with any license is permitted. + * Author: Johan Mattsson + */ +#ifndef FILE_FK_FONT_EDITOR +#define FILE_FK_FONT_EDITOR + +#include +#include "fk.h" + +void fk_write_fixed_kerning_table_header (FILE* file, uint32_t num_kerning_pairs); +void fk_write_fixed_kerning_entry (FILE* file, uint32_t glyh_index_first, uint32_t glyh_index_second, double kerning); + +#endif diff -Nru birdfont-2.30.0/fixed-kerning-example/fk.h birdfont-2.32.0/fixed-kerning-example/fk.h --- birdfont-2.30.0/fixed-kerning-example/fk.h 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/fk.h 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,50 @@ +/* + * This is example code. Using this code in any project with any license is permitted. + * Author: Johan Mattsson + */ +#ifndef FILE_FK_H +#define FILE_FK_H + +#include +#include +#include +#include + +typedef int32_t Fixed16_16; + +#define FIXED_KERNING_HEADER_SIZE 8 +#define FIXED_KERNING_ENTRY_SIZE (3 * sizeof (uint32_t)) + +/* Convert fixed 16.16 values to double. */ +double fk_fixed_to_double (Fixed16_16 val); + +Fixed16_16 fk_double_to_fixed (double v); + +/* + * All parser functions assumes that this function has been used to check if + * the table is valid and we have kerning pairs in the subtable. + */ +bool fk_has_fixed_kerning (uint8_t* otf_table, size_t table_size); + +uint32_t fk_get_num_kerning_pairs (uint8_t* otf_table, size_t table_size); + +/* + * A function that makes it possible iterate over all kerning pairs in the + * table from 0 to fk_get_num_kerning_pairs. + */ +void fk_get_fixed_kerning_by_index (uint8_t* otf_table, size_t table_size, size_t index, uint32_t* first_glyph_index, uint32_t* second_glyph_index, Fixed16_16* kerning); + +/* + * Get kerning for two gids, (glyph ID). The Fixed 16.16 value can be converted + * to a floating point value with the with the function fixed_to_double. + */ +Fixed16_16 fk_get_fixed_kerning (uint8_t* otf_table, size_t table_size, uint32_t first_glyph_index, uint32_t second_glyph_index); + +uint32_t fk_get_uint32 (uint8_t* otf_table, size_t table_size, size_t index); +uint16_t fk_get_uint16 (uint8_t* otf_table, size_t table_size, size_t index); + +void fk_write_u8 (FILE* file, uint8_t val); +void fk_write_u16 (FILE* file, uint16_t val); +void fk_write_u32 (FILE* file, uint32_t val); + +#endif diff -Nru birdfont-2.30.0/fixed-kerning-example/fk-test.c birdfont-2.32.0/fixed-kerning-example/fk-test.c --- birdfont-2.30.0/fixed-kerning-example/fk-test.c 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/fk-test.c 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,189 @@ +/* + * This is example code. Using this code in any project with any license is permitted. + * Author: Johan Mattsson + */ +#include +#include "fk.h" +#include "fk-font-editor.h" + +uint8_t* read_content (const char* file_name, size_t* buffer_size) { + FILE* file; + file = fopen (file_name, "rb"); + assert(file); + + fseek (file, 0, SEEK_END); + size_t size = ftell (file); + *buffer_size = size; + rewind (file); + + uint8_t* table_buffer = (uint8_t*) malloc(size); + assert (table_buffer); + + fread (table_buffer, size, sizeof (uint8_t), file); + fclose (file); + + return table_buffer; +} + +int test_write () { + FILE* file; + uint32_t num_pairs = 10; + + file = fopen ("fixedkerningtable.test", "wb"); + + fk_write_fixed_kerning_table_header (file, num_pairs); + + for (uint32_t i = 0; i < num_pairs; i++) { + uint32_t gid1 = i; + uint32_t gid2 = i; + double kerning = -0.2; + + gid1 = 0x45678abc; + gid2 = 0x6EEEEEE2 + i; + + // all entries needs to be sorted on gid1 and gid2. + fk_write_fixed_kerning_entry (file, gid1, gid2, kerning); + } + + fclose (file); + return 0; +} + +void test_datatypes () { + FILE* file; + file = fopen ("basic.test", "wb"); + + fk_write_u16 (file, 0x1234); + fk_write_u32 (file, 0x567abcde); + + fclose (file); + + uint8_t* table_buffer = NULL; + size_t buffer_size; + table_buffer = read_content ("basic.test", &buffer_size); + + assert (fk_get_uint16 (table_buffer, buffer_size, 0) == 0x1234); + assert (fk_get_uint32 (table_buffer, buffer_size, 2) == 0x567abcde); + + free (table_buffer); +} + +void test_fixed_conversion () { + Fixed16_16 f; + double d; + + int32_t x = 0xffffcccc; + assert (x == 0xffffcccc); + + f = fk_double_to_fixed (-0.2); + assert (f == 0xffffcccc); + + f = fk_double_to_fixed (-0.1); + assert (f == 0xffffe666); + + d = fk_fixed_to_double (0xffffcccc); + assert ((int) (d * 1000) == -200); + + d = fk_fixed_to_double (0xffffe666); + assert ((int) (d * 1000) == -100); +} + +void test_read_all () { + FILE* file; + uint8_t* table_buffer = NULL; + size_t buffer_size; + uint32_t num_pairs; + + table_buffer = read_content ("fixedkerningtable.test", &buffer_size); + + bool has_data = fk_has_fixed_kerning (table_buffer, buffer_size); + assert (has_data); + + num_pairs = fk_get_num_kerning_pairs(table_buffer, buffer_size); + assert (num_pairs > 0); + + printf ("Table size : %zu\n", buffer_size); + printf ("List all kerning pairs in table. Number of pairs: %d\n", num_pairs); + + for (uint32_t i = 0; i < num_pairs; i++) { + uint32_t gid1 = 0; + uint32_t gid2 = 0; + Fixed16_16 kern = 0; + + fk_get_fixed_kerning_by_index (table_buffer, buffer_size, i, &gid1, &gid2, &kern); + + Fixed16_16 fixed_kerning; + fixed_kerning = fk_get_fixed_kerning (table_buffer, buffer_size, gid1, gid2); + double kerning = fk_fixed_to_double (fixed_kerning); + + printf ("Kerning for gid1: %d and gid2: %d, kerning %4.4f, (raw fixed: %d)\n", gid1, gid2, kerning, fixed_kerning); + assert (kern == fixed_kerning); + } + + printf ("Total pairs %d\n\n", num_pairs); + + free (table_buffer); +} + +void test_order () { + uint8_t* table_buffer = NULL; + size_t buffer_size; + uint32_t num_pairs; + + table_buffer = read_content ("fixedkerningtable.test", &buffer_size); + + bool has_data = fk_has_fixed_kerning (table_buffer, buffer_size); + assert (has_data); + + num_pairs = fk_get_num_kerning_pairs(table_buffer, buffer_size); + assert (num_pairs > 0); + + uint32_t read_index = FIXED_KERNING_HEADER_SIZE; + + uint32_t last_gid1 = 0; + uint32_t last_gid2 = 0; + + for (uint32_t i = 0; i < num_pairs; i++) { + uint32_t gid1 = fk_get_uint32 (table_buffer, buffer_size, read_index); + read_index += sizeof (uint32_t); + + uint32_t gid2 = fk_get_uint32 (table_buffer, buffer_size, read_index); + read_index += sizeof (uint32_t); + + Fixed16_16 kern = fk_get_uint32 (table_buffer, buffer_size, read_index); + read_index += sizeof (uint32_t); + + double kerning = fk_fixed_to_double (kern); + + printf ("Row: %d gid1: %x, gid2 %x, kerning: %.4f (raw kerning %d)\n", i, gid1, gid2, kerning, kern); + + bool is_sorted = false; + + if (gid1 != last_gid1) { + is_sorted = gid1 >= last_gid1; + last_gid2 = 0; + } else { + is_sorted = gid2 >= last_gid2; + } + + last_gid1 = gid1; + last_gid2 = gid2; + + assert (is_sorted); + assert (gid1 == 0x45678abc); + assert (gid2 == 0x6EEEEEE2 + i); + } + + printf ("Total pairs %d\n\n", num_pairs); + + free (table_buffer); +} + +int main () { + test_fixed_conversion (); + test_datatypes (); + test_write (); + test_read_all (); + test_order (); + return 0; +} diff -Nru birdfont-2.30.0/fixed-kerning-example/otf-fk-documentation.html birdfont-2.32.0/fixed-kerning-example/otf-fk-documentation.html --- birdfont-2.30.0/fixed-kerning-example/otf-fk-documentation.html 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/otf-fk-documentation.html 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,181 @@ + + +Fixed Point Kerning Table in OpenType fonts + + + + + + + + + + +
+ +

Fixed Point Kerning Table (FK, Version 1.0)

+The FK table is a simple and efficient solution that makes it possible to store +kerning information with a high accuracy in OpenType fonts. + +

Names

+The table name for horizontal kerning is "FK" and the table name for vertical +kerning is "FKV". The name should be padded up to four bytes with space in the +TTF and OTF lists of tables (just like the CFF table). Name: FK space space + +

Table

+
+uint16 version_upper = 1;
+uint16 version_lower = 0;
+uint32 num_kerning_pair_entries;
+KerningEntry[]
+
+KerningEntry
+uint32 first_glyph_index
+uint32 second_glyph_index
+fixed16_16 kerning
+
+ +

Padding up to four bytes will not be needed because the table already is aligned.

+ +

The type fixed16_16 is a fixed point value (16.16) that uses 32 bits, similar to the 255 type in the CFF table.

+ +

All kerning entries needs to be sorted on the first and second glyph ID (GID).

+
+ +
+ +

Example data

+
+
+
+   
+   
+   
+   
+
+
+
+   
+   
+   
+   
+
+
+
+   
+   
+   
+   
+
+
+
+   
+   
+   
+   
+
+
+
+    
+
+
+
+   
+   
+   
+   
+
+
+
+   
+   
+   
+   
+
+
+
+   
+   
+   
+   
+
+
+
+    
+
+
+
+   
+   
+   
+   
+
+
+
+   
+   
+   
+   
+
+
+
+   
+   
+   
+   
+
+
TypeHexDecimalDescription
USHORT0x00011Major verison
USHORT0x00000Minor version
ULONG0x000000022Number of kerning pairs
ULONG0x000000077First GID of the pair (left in LTR languages)
ULONG0x000000088Second GID of the pair (right in LTR languages)
Fixed0xffffcccc-0.2Kerning for this pair
ULONG0x0000000A10First GID of the second pair (left in LTR languages)
ULONG0x0000000F15Second GID of second the pair (right in LTR languages)
Fixed0xffffe666-0.1Kerning for this pair
+
+ +
+ + diff -Nru birdfont-2.30.0/fixed-kerning-example/README.txt birdfont-2.32.0/fixed-kerning-example/README.txt --- birdfont-2.30.0/fixed-kerning-example/README.txt 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/README.txt 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,20 @@ +The FK Table (version 1.0) + +This is a reference implementation of a new kerning table that stores fixed +point 16.16 values. The idea is to get better precision for kerning of OTF +and TTF fonts. The goal is also to create a solution that is is simple and fast. + +The code is small and hopefully easy to understand. The parser needs around 200 +lines of code and around 40 more lines are needed to add support for writing +the table. + +All code related to the FK feature in this folder is example code. Copy and +paste of this code into any project with any license is permitted. + +An OTF parser only needs fk.c and fk.h. A font editor might also use +fk-font-editor.c and fk-font-editor.h. The file fk-test.c provides an +example of how the code could be used. + +Regards +Johan Mattsson +johan.mattsson.m@gmail.com diff -Nru birdfont-2.30.0/fixed-kerning-example/run.sh birdfont-2.32.0/fixed-kerning-example/run.sh --- birdfont-2.30.0/fixed-kerning-example/run.sh 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/fixed-kerning-example/run.sh 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,2 @@ +#!/bin/sh +./kerning-example diff -Nru birdfont-2.30.0/libbirdfont/BirdFontFile.vala birdfont-2.32.0/libbirdfont/BirdFontFile.vala --- birdfont-2.30.0/libbirdfont/BirdFontFile.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/BirdFontFile.vala 2022-05-25 16:55:10.000000000 +0000 @@ -24,12 +24,12 @@ Font font; public const int FORMAT_MAJOR = 2; - public const int FORMAT_MINOR = 3; + public const int FORMAT_MINOR = 4; public const int MIN_FORMAT_MAJOR = 0; public const int MIN_FORMAT_MINOR = 0; - public bool has_svg_glyphs = false; + //public bool has_svg_glyphs = false; Gee.ArrayList written_images = new Gee.ArrayList (); @@ -390,6 +390,7 @@ os.put_string (@"$(Markup.escape_text (font.license))\n"); os.put_string (@"$(Markup.escape_text (font.license_url))\n"); os.put_string (@"$(font.weight)\n"); + os.put_string (@"$(round(font.italic_angle))\n"); os.put_string (@"$(font.units_per_em)\n"); os.put_string (@"$(Markup.escape_text (font.trademark))\n"); os.put_string (@"$(Markup.escape_text (font.manufacturer))\n"); @@ -852,6 +853,10 @@ font.weight = int.parse (t.get_content ()); } + if (t.get_name () == "italic_angle") { + font.italic_angle = double.parse (t.get_content ()); + } + if (t.get_name () == "units_per_em") { font.units_per_em = int.parse (t.get_content ()); } @@ -914,7 +919,7 @@ } font.format_major = int.parse (v[0]); - font.format_major = int.parse (v[1]); + font.format_minor = int.parse (v[1]); } public void parse_images (Tag tag) { diff -Nru birdfont-2.30.0/libbirdfont/BirdFont.vala birdfont-2.32.0/libbirdfont/BirdFont.vala --- birdfont-2.30.0/libbirdfont/BirdFont.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/BirdFont.vala 2022-05-25 16:55:10.000000000 +0000 @@ -294,7 +294,7 @@ #endif } - public static void load_font_from_command_line () { + public void load_font_from_command_line () { string file = args.get_file (); if (file != "") { RecentFiles.load_font (file); diff -Nru birdfont-2.30.0/libbirdfont/DescriptionDisplay.vala birdfont-2.32.0/libbirdfont/DescriptionDisplay.vala --- birdfont-2.30.0/libbirdfont/DescriptionDisplay.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/DescriptionDisplay.vala 2022-05-25 16:55:10.000000000 +0000 @@ -24,6 +24,7 @@ CheckBox bold; CheckBox italic; TextArea weight; + TextArea italic_angle; TextArea full_name; TextArea unique_id; TextArea version; @@ -50,6 +51,7 @@ name = new LineTextArea (label_size); style = new LineTextArea (label_size); weight = new LineTextArea (label_size); + italic_angle = new LineTextArea (label_size); full_name = new LineTextArea (label_size); unique_id = new LineTextArea (label_size); version = new LineTextArea (label_size); @@ -125,6 +127,21 @@ }); widgets.add (weight); focus_ring.add (weight); + + /* + Italic angle in counter-clockwise degrees from the vertical. Zero + for upright text, negative for text that leans to the right (forward). + */ + + widgets.add (new Text (t_("Italic angle, use negative values for text that leans to the right."), label_size, label_margin)); + italic_angle.margin_bottom = margin; + italic_angle.set_text (Doubles.round (font.italic_angle)); + italic_angle.text_changed.connect ((t) => { + font.set_italic_angle (t); + font.touch (); + }); + widgets.add (italic_angle); + focus_ring.add (italic_angle); widgets.add (new Text (t_("Full Name (Name and Style)"), label_size, label_margin)); full_name.margin_bottom = margin; diff -Nru birdfont-2.30.0/libbirdfont/Doubles.vala birdfont-2.32.0/libbirdfont/Doubles.vala --- birdfont-2.30.0/libbirdfont/Doubles.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/Doubles.vala 2022-05-25 16:55:10.000000000 +0000 @@ -155,15 +155,36 @@ public string get_string (int i) { return round (get_double (i)); } - - public static string round (double p) { - string v = p.to_string (); + + public static string round (double p, int decimals = 5) { + string v = ""; char[] c = new char [501]; - v = p.format (c, "%3.5f"); + v = p.format (c, @"%.$(decimals)f"); + v = v.replace (",", "."); if (v.index_of ("e") != -1) { - return "0.0"; + v = "0.0"; + } + + if (v.index_of ("-") == 0 && double.parse (v) == -0) { + v = "0"; + } + + return remove_last_zeros (v); + } + + public static string remove_last_zeros (string value) { + string v = value; + + if (v.index_of (".") != -1) { + while (v.has_suffix ("0")) { + v = v.substring (0, v.length - "0".length); + } + + if (v.has_suffix (".")) { + v = v.substring (0, v.length - ".".length); + } } return v; diff -Nru birdfont-2.30.0/libbirdfont/EmptyTab.vala birdfont-2.32.0/libbirdfont/EmptyTab.vala --- birdfont-2.30.0/libbirdfont/EmptyTab.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/EmptyTab.vala 2022-05-25 16:55:10.000000000 +0000 @@ -34,6 +34,11 @@ return label; } + public override void selected_canvas () { + MainWindow.hide_scrollbar (); + GlyphCanvas.redraw (); + } + public override void draw (WidgetAllocation allocation, Context cr) { cr.save (); Theme.color (cr, "Default Background"); diff -Nru birdfont-2.30.0/libbirdfont/ExportTool.vala birdfont-2.32.0/libbirdfont/ExportTool.vala --- birdfont-2.30.0/libbirdfont/ExportTool.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/ExportTool.vala 2022-05-25 16:55:10.000000000 +0000 @@ -459,7 +459,11 @@ } string html_data; - FileUtils.get_contents ((!) template.get_path (), out html_data); + try { + FileUtils.get_contents ((!) template.get_path (), out html_data); + } catch (FileError e) { + warning (e.message); + } string name; #if MAC @@ -631,7 +635,7 @@ critical (@"$(e.message)"); } } - + /* static bool can_write (File folder) { File test = get_child (folder, "text.tmp"); bool writable = false; @@ -648,6 +652,7 @@ return writable; } + */ } } diff -Nru birdfont-2.30.0/libbirdfont/Font.vala birdfont-2.32.0/libbirdfont/Font.vala --- birdfont-2.30.0/libbirdfont/Font.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/Font.vala 2022-05-25 16:55:10.000000000 +0000 @@ -87,6 +87,7 @@ public bool bold = false; public bool italic = false; public int weight = 400; + public double italic_angle = 0; public bool initialised = true; @@ -294,6 +295,10 @@ } } + public void set_italic_angle (string a) { + italic_angle = double.parse (a); + } + public string get_weight () { return @"$weight"; } diff -Nru birdfont-2.30.0/libbirdfont/OpenFontFormat/DirectoryTable.vala birdfont-2.32.0/libbirdfont/OpenFontFormat/DirectoryTable.vala --- birdfont-2.30.0/libbirdfont/OpenFontFormat/DirectoryTable.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OpenFontFormat/DirectoryTable.vala 2022-05-25 16:55:10.000000000 +0000 @@ -19,6 +19,7 @@ public CmapTable cmap_table; public CvtTable cvt_table; + public FkTable fk_table; public GaspTable gasp_table; public GdefTable gdef_table; public GlyfTable glyf_table; @@ -57,6 +58,7 @@ name_table = new NameTable (); os_2_table = new Os2Table (glyf_table, hmtx_table, hhea_table); post_table = new PostTable (glyf_table); + fk_table = new FkTable (glyf_table, kern_table); id = "Directory table"; @@ -96,6 +98,8 @@ if (tables.size == 0) { tables.add (offset_table); tables.add (this); + + tables.add (fk_table); tables.add (gpos_table); tables.add (gsub_table); @@ -154,8 +158,13 @@ length = dis.read_ulong (); printd (@"$(tag.str) \toffset: $offset \tlength: $length \tchecksum: $checksum.\n"); - - if (tag.str == "cvt") { + + if (tag.str == "FK ") { + fk_table.id = tag.str; + fk_table.checksum = checksum; + fk_table.offset = offset; + fk_table.length = length; + } else if (tag.str == "cvt") { cvt_table.id = tag.str; cvt_table.checksum = checksum; cvt_table.offset = offset; @@ -262,8 +271,20 @@ if (kern_table.has_data ()) { cvt_table.parse (dis); } + + if (fk_table.has_data ()) { + fk_table.parse (dis); + } } - + + public void parse_fk_table (FontData dis) throws Error { + if (fk_table.has_data ()) { + fk_table.parse (dis); + } else { + warning ("Fk table is empty."); + } + } + public void parse_kern_table (FontData dis) throws Error { if (kern_table.has_data ()) { kern_table.parse (dis); @@ -352,7 +373,12 @@ warning ("kern_table has invalid checksum"); valid = false; } - + + if (fk_table.has_data () && !fk_table.validate (dis)) { + warning ("fk_table has invalid checksum"); + valid = false; + } + if (!gpos_table.validate (dis)) { warning (@"gpos_table has invalid checksum"); diff -Nru birdfont-2.30.0/libbirdfont/OpenFontFormat/FkKern.vala birdfont-2.32.0/libbirdfont/OpenFontFormat/FkKern.vala --- birdfont-2.30.0/libbirdfont/OpenFontFormat/FkKern.vala 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OpenFontFormat/FkKern.vala 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,45 @@ +/* + Copyright (C) 2022 Johan Mattsson + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. +*/ + +namespace BirdFont { + +public class FkKern : GLib.Object { + public int left; + public int right; + public double kerning; + + public FkKern (int l, int r, double k) { + if (l < 0) { + warning ("Negative gid (left)"); + } + + if (r < 0) { + warning ("Negative gid (right)"); + } + + left = l; + right = r; + kerning = k; + } + + public FkKern copy () { + return new FkKern (left, right, kerning); + } + + public string to_string () { + return @"left: $left, right: $right, kerning: $kerning"; + } +} + +} diff -Nru birdfont-2.30.0/libbirdfont/OpenFontFormat/FkTable.vala birdfont-2.32.0/libbirdfont/OpenFontFormat/FkTable.vala --- birdfont-2.30.0/libbirdfont/OpenFontFormat/FkTable.vala 1970-01-01 00:00:00.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OpenFontFormat/FkTable.vala 2022-05-25 16:55:10.000000000 +0000 @@ -0,0 +1,150 @@ +/* + Copyright (C) 2022 Johan Mattsson + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. +*/ + +namespace BirdFont { + +public class FkTable : OtfTable { + GlyfTable glyf_table; + KernTable kern_table; + + public FkTable (GlyfTable glyf_table, KernTable kern_table) { + this.glyf_table = glyf_table; + this.kern_table = kern_table; + id = "FK "; + } + + public static int32 to_fixed (double d) { + int32 val = (int32) Math.floor (d); + int32 mant = (int32) Math.floor (0x10000 * (d - val)); + val = (val << 16) | mant; + return val; + } + + public static double from_fixed (int32 val) { + return val / 65536.0; + } + + public override void parse (FontData dis) throws GLib.Error { + uint16 version_upper; + uint16 version_lower; + + uint32 n_pairs; + + dis.seek (offset); + + version_upper = dis.read_ushort (); + version_lower = dis.read_ushort (); + + if (!(version_upper == 1 && version_lower == 0)) { + warning (@"Expecting version 1.0. Found version: $version_upper.$version_lower"); + return; + } + + n_pairs = dis.read_ulong (); + + printd (@"Pairs in fk table $n_pairs\n"); + + uint32 gid1 = -1; + uint32 gid2 = -1; + int32 k = -1; + double kerning = -1; + + for (uint32 i = 0; i < n_pairs; i++) { + gid1 = dis.read_ulong (); + gid2 = dis.read_ulong (); + k = dis.read_int32 (); + kerning = from_fixed (k); + kern_table.fk_kerning.add (new FkKern ((int) gid1, (int) gid2, kerning)); + } + + if (dis.get_read_pos () != dis.length_with_padding ()) { + warning (@"Data left in fk table. Read pos $(dis.get_read_pos ()), length: $(dis.length_with_padding ())"); + } + } + + public void process () throws GLib.Error { + FontData fd = new FontData (); + KerningClasses classes = BirdFont.get_current_font ().get_kerning_classes (); + + fd.add_ushort (1); // version upper + fd.add_ushort (0); // version lower + + write_kerning_pairs(fd); + + fd.pad (); + this.font_data = fd; + } + + public void write_kerning_pairs (FontData fd) throws GLib.Error { + KerningClasses classes = BirdFont.get_current_font ().get_kerning_classes (); + Gee.ArrayList pairs = new Gee.ArrayList (); + + classes.each_pair ((g1, g2, kerning) => { + int gid1 = glyf_table.get_gid (g1); + int gid2 = glyf_table.get_gid (g2); + + if (gid1 == -1) { + warning (@"Glyph id not found for $g1"); + return; + } + + if (gid2 == -1) { + warning (@"Glyph not found for $g2"); + return; + } + + pairs.add (new FkKern ((int) gid1, (int) gid2, kerning)); + }); + + pairs.sort ((a, b) => { + FkKern first = (FkKern) a; + FkKern next = (FkKern) b; + + if (first.left == next.left) { + return first.right - next.right; + } + + return first.left - next.left; + }); + + uint32 num_pairs = (uint32) pairs.size; + fd.add_ulong (num_pairs); + + foreach (FkKern k in pairs) { + write_pair (fd, k.left, k.right, k.kerning); + } + } + + public void write_pair (FontData fd, int gid1, int gid2, double kerning) throws GLib.Error { + if (gid1 < 0) { + warning (@"Negative gid1."); + throw new FileError.FAILED (@"gid1 is $gid1"); + } + + if (gid2 < 0) { + warning (@"Negative gid2."); + throw new FileError.FAILED (@"gid2 is $gid2"); + } + + int32 fixed_kerning = to_fixed (kerning * HeadTable.UNITS); + + fd.add_ulong ((uint) gid1); // left gid + fd.add_ulong ((uint) gid2); // right gid + fd.add_long (fixed_kerning); // kerning + } +} + + +} + diff -Nru birdfont-2.30.0/libbirdfont/OpenFontFormat/FontData.vala birdfont-2.32.0/libbirdfont/OpenFontFormat/FontData.vala --- birdfont-2.30.0/libbirdfont/OpenFontFormat/FontData.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OpenFontFormat/FontData.vala 2022-05-25 16:55:10.000000000 +0000 @@ -195,6 +195,15 @@ return f; } + public int32 read_int32 () { + int32 f; + f = read () << 8 * 3; + f += read () << 8 * 2; + f += read () << 8 * 1; + f += read () << 8 * 0; + return f; + } + public uint64 read_uint64 () { uint64 f; f = (uint64) read () << 8 * 7; @@ -278,7 +287,18 @@ public void add_ulong (uint32 d) throws Error { add_u32 (d); } + + public void add_long (int32 d) throws Error { + add_32 (d); + } + + public void add_32 (int32 i) throws GLib.Error { + uint32 s = (uint16) (i >> 16); + add_u16 ((uint16) s); + add_u16 ((uint16) (i - (s << 16))); + } + public void add_byte (uint8 b) throws Error { add (b); } @@ -609,7 +629,18 @@ add (fd.read ()); } } - + + public static int32 to_fixed (double d) { + int32 val = (int32) Math.floor (d); + int32 mant = (int32) Math.floor (0x10000 * (d - val)); + val = (val << 16) | mant; + return val; + } + + public static double from_fixed (int32 val) { + return val / 65536.0; + } + public void dump () { for (uint32 i = 0; i < length_with_padding (); i++) { stdout.printf ("%x " , table_data[i]); diff -Nru birdfont-2.30.0/libbirdfont/OpenFontFormat/KernTable.vala birdfont-2.32.0/libbirdfont/OpenFontFormat/KernTable.vala --- birdfont-2.30.0/libbirdfont/OpenFontFormat/KernTable.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OpenFontFormat/KernTable.vala 2022-05-25 16:55:10.000000000 +0000 @@ -27,7 +27,9 @@ KernList pairs; // Only used for loading pairs - public Gee.ArrayList kerning = new Gee.ArrayList (); // TODO: replace with the KernList + public Gee.ArrayList kerning = new Gee.ArrayList (); + public Gee.ArrayList fk_kerning = new Gee.ArrayList (); // Also only used for loading pairs + public uint kerning_pairs = 0; public KernTable (GlyfTable gt) { diff -Nru birdfont-2.30.0/libbirdfont/OpenFontFormat/load_font.c birdfont-2.32.0/libbirdfont/OpenFontFormat/load_font.c --- birdfont-2.30.0/libbirdfont/OpenFontFormat/load_font.c 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OpenFontFormat/load_font.c 2022-05-25 16:55:10.000000000 +0000 @@ -131,7 +131,7 @@ int j; guint prev_is_curve; guint first_is_curve = FALSE; - guint first_normal_off_curve = FALSE; + //guint first_normal_off_curve = FALSE; double x = 0; double y = 0; FT_Vector* p; @@ -172,7 +172,7 @@ // first point is of curve but it is not part of a double curve if (len > 2 && is_quadratic (flags[0]) && !is_quadratic (flags[1])) { - first_normal_off_curve = TRUE; + //first_normal_off_curve = TRUE; } while (i < len) { @@ -380,19 +380,19 @@ gchar coordinate_buffer[80]; gchar* coordinate = (gchar*) &coordinate_buffer; double units = get_units (units_per_em); - guint prev_is_curve; - int points_length; + //guint prev_is_curve; + //int points_length; if (length == 0) { return bf; } - points_length = length; + //points_length = length; - gboolean last_to_first = FALSE; + //gboolean last_to_first = FALSE; - int last_x = 0; - int last_y = 0; + //int last_x = 0; + //int last_y = 0; create_contour (unicode, points, flags, &length, &new_points, &new_flags, err); @@ -454,8 +454,8 @@ g_ascii_formatd (coordinate, 80, "%f", y2); g_string_append (contour, coordinate); - last_x = new_points[i+2].x; - last_y = new_points[i+2].y; + //last_x = new_points[i+2].x; + //last_y = new_points[i+2].y; i += 3; } else if (is_double_curve (new_flags[i])) { @@ -491,8 +491,8 @@ g_ascii_formatd (coordinate, 80, "%f", y2); g_string_append (contour, coordinate); - last_x = new_points[i+2].x; - last_y = new_points[i+2].y; + //last_x = new_points[i+2].x; + //last_y = new_points[i+2].y; i += 3; } else if (is_quadratic (new_flags[i])) { @@ -518,8 +518,8 @@ g_ascii_formatd (coordinate, 80, "%f", y1); g_string_append (contour, coordinate); - last_x = new_points[i + 1].x; - last_y = new_points[i + 1].y; + //last_x = new_points[i + 1].x; + //last_y = new_points[i + 1].y; i += 2; } else if (is_line (new_flags[i])) { @@ -537,8 +537,8 @@ i += 1; - last_x = new_points[i].x; - last_y = new_points[i].y; + //last_x = new_points[i].x; + //last_y = new_points[i].y; } else { contour = g_string_new (""); g_warning ("Can't parse outline.\n"); @@ -560,7 +560,7 @@ GString* get_bf_path (guint unicode, FT_Face face, double units_per_em, int* err) { GString* bf = g_string_new (""); GString* contour; - FT_Error error; + //FT_Error error; int i; int start; int end; @@ -593,7 +593,7 @@ return NULL; } - gchar* short_path = file; + gchar* short_path = (gchar *)file; error = FT_New_Face (library, short_path, 0, &face); @@ -807,7 +807,7 @@ GError* error = NULL; if (name_table_data->encoding_id == 0) { // mac roman - utf8_str = g_convert (name_table_data->string, name_table_data->string_len, "utf-8", "macintosh", &read, &written, &error); + utf8_str = g_convert ((const gchar *)name_table_data->string, name_table_data->string_len, "utf-8", "macintosh", &read, &written, &error); if (error == NULL) { g_string_append (str, g_markup_escape_text (utf8_str, -1)); @@ -817,7 +817,7 @@ g_error_free (error); } } else if (name_table_data->encoding_id == 1) { // windows unicode - utf8_str = g_convert (name_table_data->string, name_table_data->string_len, "utf-8", "ucs-2be", &read, &written, &error); + utf8_str = g_convert ((const gchar *)name_table_data->string, name_table_data->string_len, "utf-8", "ucs-2be", &read, &written, &error); if (error == NULL) { g_string_append (str, g_markup_escape_text (utf8_str, -1)); @@ -867,10 +867,10 @@ * @param err error code * @return xml representation of a bf font */ -GString* get_bf_font (FT_Face face, char* file, int* err) { +GString* get_bf_font (FT_Face face, const char* file, int* err) { GString* bf = g_string_new (""); GString* bf_data; - gchar* kerning; + //gchar* kerning; GString* glyph; FT_Error error; FT_Long i; @@ -1052,7 +1052,8 @@ g_string_append_printf (bf, "\n"); g_string_append_printf (bf, "\t\n", 0.0, face->glyph->metrics.horiAdvance * units); - bf_data = get_bf_path (charcode, face, units_per_em, err); + //bf_data = get_bf_path (charcode, face, units_per_em, err); + bf_data = get_bf_path (' ', face, units_per_em, err); g_string_append (bf, bf_data->str); g_string_append (bf, "\t\n"); @@ -1101,7 +1102,7 @@ } if (!has_unicode_value) { - g_warning ("Ignoring glyph without a Unicode value, %d. (condition: %d)", + g_warning ("Ignoring glyph without a Unicode value, %ld. (condition: %d)", i, has_unicode_value); break; } @@ -1158,8 +1159,8 @@ FT_Library library; FT_Face face; int error; - FT_Glyph glyph; - FT_UInt glyph_index; + //FT_Glyph glyph; + //FT_UInt glyph_index; error = FT_Init_FreeType (&library); if (error != OK) { @@ -1186,7 +1187,7 @@ // not tested the new code. gchar* short_path = calloc ((2048 + 1), sizeof(gchar)); - short_path = file; + short_path = (gchar *)file; error = FT_New_Face (library, short_path, 0, &face); if (error) { @@ -1244,13 +1245,13 @@ FT_Library library = NULL; FT_Face face = NULL; int error; - FreeTypeFontFace* font; + FreeTypeFontFace* font = NULL; error = FT_Init_FreeType (&library); if (error != OK) { g_warning ("Freetype init error %d.\n", error); - return NULL; + return FALSE; } gchar* short_path = calloc ((2048 + 1), sizeof(gchar)); @@ -1267,7 +1268,7 @@ g_warning ("Can't open file %s", file); g_warning ("Short path: %s", short_path); - return NULL; + return FALSE; } if (font == NULL || font->face == NULL || font->library == NULL) { @@ -1280,7 +1281,7 @@ } gulong* get_all_unicode_points_in_font (const gchar* file) { - FT_ULong* charcodes = NULL; + //FT_ULong* charcodes = NULL; FT_Library library; FT_Face face; @@ -1322,7 +1323,7 @@ } gboolean error_in_result = FALSE; - gint gindex = 0; + FT_UInt gindex = 0; FT_ULong charcode; gint num_glyphs = 0; @@ -1371,4 +1372,4 @@ FT_Done_FreeType (library); return result; -} \ No newline at end of file +} diff -Nru birdfont-2.30.0/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala birdfont-2.32.0/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala --- birdfont-2.30.0/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala 2022-05-25 16:55:10.000000000 +0000 @@ -109,7 +109,11 @@ public void parse_head_table () throws Error { directory_table.parse_head_table (font_data); } - + + public void parse_fk_table () throws Error { + directory_table.parse_fk_table (font_data); + } + public void set_limits () { Font f = OpenFontFormatWriter.font; @@ -144,6 +148,7 @@ reader.parse_kern_table (); reader.parse_cmap_table (); reader.parse_head_table (); + reader.parse_fk_table (); kern_table = reader.directory_table.kern_table; cmap_table = reader.directory_table.cmap_table; @@ -152,33 +157,48 @@ npairs = kern_table.kerning.size; units_per_em = HeadTable.units_per_em; - + foreach (Kern k in kern_table.kerning) { left = cmap_table.get_char (k.left); right = cmap_table.get_char (k.right); kerning = 100 * (k.kerning / units_per_em); - if (left <= 0x1F || right <= 0x1F) { - warning ("Ignoring kerning of control character."); - } else { - if (@"$kerning" != "0") { - bf_kerning.append ("\n"); - } - } + add_kerning (bf_kerning, left, right, kerning); + } + + foreach (FkKern k in kern_table.fk_kerning) { + left = cmap_table.get_char (k.left); + right = cmap_table.get_char (k.right); + kerning = 100 * (k.kerning / units_per_em); + + add_kerning (bf_kerning, left, right, kerning); } + + printd (@"FK kerning pairs: $(kern_table.fk_kerning.size)\n"); } catch (GLib.Error e) { warning (@"Failed to parse font. $(e.message)"); } return bf_kerning.str; } + + static void add_kerning (StringBuilder bf_kerning, unichar left, unichar right, double kerning) { + if (left <= 0x1F || right <= 0x1F) { + warning ("Ignoring kerning of control character."); + } else { + if (@"$kerning" != "0") { + bf_kerning.append ("\n"); + } + } + } } -} + +} \ No newline at end of file diff -Nru birdfont-2.30.0/libbirdfont/OpenFontFormat/PostTable.vala birdfont-2.32.0/libbirdfont/OpenFontFormat/PostTable.vala --- birdfont-2.30.0/libbirdfont/OpenFontFormat/PostTable.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OpenFontFormat/PostTable.vala 2022-05-25 16:55:10.000000000 +0000 @@ -1078,7 +1078,20 @@ StringBuilder name; fd.add_fixed (0x00020000); // Version - fd.add_fixed (0x00000000); // italicAngle + + Font font = OpenFontFormatWriter.get_current_font (); + + if (!font.italic) { + if (font.italic_angle != 0) { + printd ("Italic angle set to $(font.italic_angle) but the italic checkbox is not ticked."); + } + + fd.add_fixed (0x00000000); // italicAngle + } else { + int angle = FontData.to_fixed (font.italic_angle); + fd.add_32 (angle); + } + fd.add_short (-2); // underlinePosition fd.add_short (1); // underlineThickness diff -Nru birdfont-2.30.0/libbirdfont/OverView.vala birdfont-2.32.0/libbirdfont/OverView.vala --- birdfont-2.30.0/libbirdfont/OverView.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/OverView.vala 2022-05-25 16:55:10.000000000 +0000 @@ -1422,15 +1422,15 @@ private bool at_bottom () { Font f; double t = rows * items_per_row + first_visible; - + if (all_available) { f = BirdFont.get_current_font (); - return t >= f.length (); + return t >= f.length () + 2 * items_per_row; } - return t >= glyph_range.length (); + return t >= glyph_range.length () + 2 * items_per_row; } - + public void set_current_glyph_range (GlyphRange range) { GlyphRange? current = glyph_range; string c; @@ -1471,7 +1471,7 @@ this.unref (); } - public override void update_scrollbar () { + public double update_scrollbar () { Font f; double nrows = 0; double pos = 0; @@ -1484,23 +1484,36 @@ } else { if (all_available) { f = BirdFont.get_current_font (); - nrows = Math.floor ((f.length ()) / rows); + nrows = Math.ceil ((f.length ()) / (double) rows); size = f.length (); } else { - nrows = Math.floor ((glyph_range.length ()) / rows); + nrows = Math.ceil ((glyph_range.length ()) / (double) rows); size = glyph_range.length (); } if (nrows <= 0) { nrows = 1; } - - visible_rows = allocation.height / OverViewItem.height; + + visible_rows = allocation.height / (OverViewItem.height + OverViewItem.margin); scroll_size = visible_rows / nrows; MainWindow.set_scrollbar_size (scroll_size); - pos = first_visible / (nrows * items_per_row - visible_rows * items_per_row); + pos = first_visible / (size - visible_rows * items_per_row); + + if (pos > 1) { + pos = 1; + } + MainWindow.set_scrollbar_position (pos); + + if (at_bottom () && first_visible == 0) { + MainWindow.hide_scrollbar (); + } else { + MainWindow.show_scrollbar (); + } } + + return pos; } /** Display one entry from the Unicode Character Database. */ diff -Nru birdfont-2.30.0/libbirdfont/Renderer/fontconfig.c birdfont-2.32.0/libbirdfont/Renderer/fontconfig.c --- birdfont-2.30.0/libbirdfont/Renderer/fontconfig.c 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/Renderer/fontconfig.c 2022-05-25 16:55:10.000000000 +0000 @@ -111,7 +111,7 @@ } path = NULL; - name = font_name; + name = (FcChar8*) font_name; search_pattern = FcPatternCreate (); FcPatternAddString (search_pattern, FC_FAMILY, name); diff -Nru birdfont-2.30.0/libbirdfont/Renderer/Text.vala birdfont-2.32.0/libbirdfont/Renderer/Text.vala --- birdfont-2.30.0/libbirdfont/Renderer/Text.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/Renderer/Text.vala 2022-05-25 16:55:10.000000000 +0000 @@ -389,7 +389,7 @@ // double x = margin_left * ratio; double x = 0; - double py = cc_y; + //double py = cc_y; double w = get_sidebearing_extent () * screen_scale + x + margin_left + 1; diff -Nru birdfont-2.30.0/libbirdfont/ResizeTool.vala birdfont-2.32.0/libbirdfont/ResizeTool.vala --- birdfont-2.30.0/libbirdfont/ResizeTool.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/ResizeTool.vala 2022-05-25 16:55:10.000000000 +0000 @@ -479,7 +479,7 @@ objects_resized (selection_box_width, selection_box_height); } - + /* void get_selection_min (out double x, out double y) { Glyph glyph = MainWindow.get_current_glyph (); x = double.MAX; @@ -494,7 +494,7 @@ } } } - + */ bool can_resize (double x, double y) { Glyph glyph = MainWindow.get_current_glyph (); double h, w; diff -Nru birdfont-2.30.0/libbirdfont/SearchPaths.vala birdfont-2.32.0/libbirdfont/SearchPaths.vala --- birdfont-2.30.0/libbirdfont/SearchPaths.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/SearchPaths.vala 2022-05-25 16:55:10.000000000 +0000 @@ -37,8 +37,13 @@ resources = (is_null (resources_folder)) ? "" : resources_folder; - string? current_program = GLib.FileUtils.read_link ("/proc/self/exe"); - + string? current_program; + try { + current_program = GLib.FileUtils.read_link ("/proc/self/exe"); + } catch (Error e) { + warning (e.message); + current_program = null; + } if (current_program != null) { string program = (!) current_program; int separator = program.last_index_of ("/"); diff -Nru birdfont-2.30.0/libbirdfont/StrokeTool.vala birdfont-2.32.0/libbirdfont/StrokeTool.vala --- birdfont-2.30.0/libbirdfont/StrokeTool.vala 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/libbirdfont/StrokeTool.vala 2022-05-25 16:55:10.000000000 +0000 @@ -1451,7 +1451,7 @@ return intersections; } - + /* bool split_corner (PathList pl) { EditPoint p1, p2; EditPoint a1, a2; @@ -1513,7 +1513,8 @@ return false; } - + */ + /* bool split_segment (Path p, EditPoint first, EditPoint next, EditPoint p1, EditPoint p2, out PathList result) { double ix, iy; bool intersection; @@ -1534,7 +1535,7 @@ return intersection; } - + */ PathList get_parts_self (Path path, PathList? paths = null) { PathList pl; PathList r; @@ -1899,6 +1900,7 @@ } // indside becomes outside in some paths + /* void remove_points_in_stroke (PathList pl) { PathList r; @@ -1910,7 +1912,8 @@ } } } - + */ + /* bool remove_points_in_stroke_for_path (Path p, PathList pl, out PathList result) { EditPoint start_ep; EditPoint start_next; @@ -1950,7 +1953,8 @@ return false; } - + */ + /* bool merge_segments (PathList pl, Path path1, EditPoint start1, EditPoint stop1, EditPoint start2, EditPoint stop2, @@ -2022,7 +2026,7 @@ return false; } - + */ void reset_intersections (Path p) { foreach (EditPoint ep in p.points) { ep.flags &= ~EditPoint.INTERSECTION; @@ -2032,7 +2036,7 @@ } p.remove_points_on_points (); } - + /* bool add_merge_intersection_point (Path path1, Path path2, EditPoint first, EditPoint next) { double ix, iy; bool intersection; @@ -2058,7 +2062,7 @@ return intersection; } - + */ bool is_inside_of_path (PointSelection ps, PathList pl, out Path outline) { outline = new Path (); foreach (Path p in pl.paths) { diff -Nru birdfont-2.30.0/NEWS birdfont-2.32.0/NEWS --- birdfont-2.30.0/NEWS 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/NEWS 2022-05-25 16:55:10.000000000 +0000 @@ -1,3 +1,9 @@ +birdfont (2.32.0) stable; + + * Store italic angle in font metadata + + -- Johan Mattsson Wed May 25 18:54:28 CEST 2022 + birdfont (2.30.0) stable; * Smaller .birdfont files diff -Nru birdfont-2.30.0/README.md birdfont-2.32.0/README.md --- birdfont-2.30.0/README.md 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/README.md 2022-05-25 16:55:10.000000000 +0000 @@ -8,7 +8,6 @@ Author: Johan Mattsson and others see AUTHORS for full attribution. License: GNU GPL v3 Webpage: https://birdfont.org - Bugtracker: https://birdfont.org/bugtracker/my_view_page.php ## Building from Source diff -Nru birdfont-2.30.0/scripts/version.py birdfont-2.32.0/scripts/version.py --- birdfont-2.30.0/scripts/version.py 2022-02-10 17:50:09.000000000 +0000 +++ birdfont-2.32.0/scripts/version.py 2022-05-25 16:55:10.000000000 +0000 @@ -13,7 +13,7 @@ Lesser General Public License for more details. """ -VERSION = '2.30.0' +VERSION = '2.32.0' SO_VERSION_MAJOR = '36' SO_VERSION_MINOR = '0' SO_VERSION = SO_VERSION_MAJOR + '.' + SO_VERSION_MINOR