Commit 81dd1e7
Convert horizontal lines to the new coordinate system This commit does also add code that removes objects without an area before exporting TTF fonts.
Changed files (12)
modifiedlibbirdfont/Font.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/ImportSvg.valamodifiedlibbirdfont/Line.valamodifiedlibbirdfont/OpenFontFormat/DirectoryTable.valamodifiedlibbirdfont/OpenFontFormat/GlyfData.valamodifiedlibbirdfont/OpenFontFormat/GlyfTable.valamodifiedlibbirdfont/OpenFontFormat/NameTable.valamodifiedlibbirdfont/OpenFontFormat/OpenFontFormatReader.valamodifiedlibbirdfont/OpenFontFormat/Os2Table.valamodifiedlibbirdfont/OpenFontFormat/load_font.cmodifiedlibbirdfont/Svg.vala
Diff
@@ -195,7 +195,7 @@ public class Font : GLib.Object { } public double get_height () {- double r = base_line - top_position;+ double r = top_position - base_line; return (r > 0) ? r : -r; } @@ -304,16 +304,16 @@ public class Font : GLib.Object { g.left_limit = -33; g.right_limit = 33; - p.add (-20, -top_position - 5);- p.add (20, -top_position - 5);- p.add (20, -base_line + 5);- p.add (-20, -base_line + 5);+ p.add (-20, top_position - 5);+ p.add (20, top_position - 5);+ p.add (20, base_line + 5);+ p.add (-20, base_line + 5); p.close (); - i.add (-15, -top_position - 10);- i.add (15, -top_position - 10);- i.add (15, -base_line + 10);- i.add (-15, -base_line + 10);+ i.add (-15, top_position - 10);+ i.add (15, top_position - 10);+ i.add (15, base_line + 10);+ i.add (-15, base_line + 10); i.reverse (); i.close (); @@ -1341,15 +1341,16 @@ public class Glyph : FontDisplay { public void draw_path (Context cr) { double left, baseline;+ Font font = BirdFont.get_current_font (); - baseline = get_line ("baseline").pos;+ baseline = font.base_line; left = get_line ("left").pos; if (!is_open ()) { cr.save (); cr.set_source_rgba (0, 0, 0, 1); - Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () + baseline);+ Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () - baseline); cr.restore (); }@@ -1358,7 +1359,7 @@ public class Glyph : FontDisplay { foreach (unowned Path p in path_list) { cr.save (); cr.set_source_rgba (Path.fill_color_r, Path.fill_color_g, Path.fill_color_b, Path.fill_color_a);- Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () + baseline);+ Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () - baseline); cr.restore (); } }@@ -1770,7 +1771,7 @@ public class Glyph : FontDisplay { current.append_unichar (glyph.unichar_code); pos = glyph_sequence.index_of (current.str); - baseline = glyph.get_line ("baseline").pos;+ baseline = font.base_line;; left = glyph.get_line ("left").pos; x = glyph.get_width ();@@ -1791,7 +1792,7 @@ public class Glyph : FontDisplay { || in_range (left + x + kern + juxtaposed.get_width (), box_x1, box_x2))) { marker_x = Glyph.xc () + left + x + kern - glyph.view_offset_x;- marker_y = Glyph.yc () + baseline - glyph.view_offset_y;+ marker_y = Glyph.yc () - baseline - glyph.view_offset_y; cr.save (); cr.scale (glyph.view_zoom, glyph.view_zoom);@@ -1823,7 +1824,7 @@ public class Glyph : FontDisplay { x -= kern; marker_x = Glyph.xc () + left + x;- marker_y = Glyph.yc () + baseline;+ marker_y = Glyph.yc () - baseline; if (!juxtaposed.is_empty () &&(in_range (left + x, box_x1, box_x2) || in_range (left + x + juxtaposed.get_width (), box_x1, box_x2))) {@@ -1840,15 +1841,15 @@ public class Glyph : FontDisplay { } void draw_background_glyph (WidgetAllocation allocation, Context cr) {- double left, baseline, current_baseline, current_left;+ double left, baseline, current_left; Glyph g;+ Font font = BirdFont.get_current_font (); - current_baseline = get_line ("baseline").pos; current_left = get_line ("left").pos; if (background_glyph != null) { g = (!) background_glyph;- baseline = get_line ("baseline").pos;+ baseline = font.base_line; left = g.get_line ("left").pos; cr.save (); cr.scale (view_zoom, view_zoom);@@ -1856,11 +1857,15 @@ public class Glyph : FontDisplay { cr.set_source_rgba (0.2, 0.2, 0.2, 0.5); Svg.draw_svg_path (cr, g.get_svg_data (), Glyph.xc () + left - (left - current_left) , - Glyph.yc () + baseline - (current_baseline - baseline));+ Glyph.yc () - baseline); cr.restore (); } }+ + public string get_hex () {+ return Font.to_hex_code (unichar_code);+ } } }@@ -730,12 +730,12 @@ public class ImportSvg { // move only y for (int i = 0; i < pi; i += 2) { p[i] += glyph.left_limit;- p[i+1] -= font.base_line;+ p[i+1] += font.base_line; } } else { for (int i = 0; i < pi; i += 2) { p[i] += glyph.left_limit;- p[i+1] -= font.top_position;+ p[i+1] += font.top_position; } } @@ -231,10 +231,7 @@ public class Line : GLib.Object { public void draw (Context cr, WidgetAllocation allocation) { Glyph g = MainWindow.get_current_glyph ();- double p, h, w;- double ivz = 1/g.view_zoom;- double size = (active) ? 8 : 5; if (!visible) return;@@ -103,7 +103,7 @@ public class DirectoryTable : Table { // since the most browsers uses the GPOS table // but Windows does not accept fonts without a kern table. - // FIXME tables.append (kern_table);+ tables.append (kern_table); tables.append (loca_table); tables.append (maxp_table);@@ -63,9 +63,7 @@ class GlyfData : GLib.Object { foreach (Path p in g.path_list) { q = p.get_quadratic_points (); - if (q.points.length () < 2) {- warning (@"A path in $(g.get_name ()) has less than three points, it will not be exported.");- } else {+ if (!is_empty (q)) { paths.append (q); } }@@ -77,6 +75,25 @@ class GlyfData : GLib.Object { process_bounding_box (); } + bool is_empty (Path p) {+ EditPoint? last = null;+ + if (unlikely (p.points.length () < 2)) {+ warning (@"A path in $(glyph.get_name ()) has less than three points, it will not be exported.");+ return true;+ }+ + foreach (EditPoint ep in p.points) {+ if (last != null && !ep.equals ((!) last)) {+ return false;+ }+ last = ep;+ }+ + warning (@"A path in $(glyph.get_name ()) ($(glyph.get_hex ())) has no area but $(p.points.length ()) points at $(p.get_first_point ().x),$(p.get_first_point ().y).");+ return true;+ }+ public uint16 get_end_point () { return end_point; }@@ -96,12 +113,12 @@ class GlyfData : GLib.Object { end_point = 0; foreach (Path quadratic in paths) {- if (quadratic.points.length () == 0) {+ if (unlikely (quadratic.points.length () == 0)) { warning (@"No points in path (before conversion $(quadratic.points.length ()))"); continue; } - if (quadratic.points.length () < 2) {+ if (unlikely (quadratic.points.length () < 2)) { warning ("A path contains less than three points, it will not be exported."); continue; }@@ -119,15 +136,15 @@ class GlyfData : GLib.Object { } end_points.append (end_point - 1); - if (end_point - 1 < last_end_point) {+ if (unlikely (end_point - 1 < last_end_point)) { warning (@"Next endpoint has bad value. (end_point - 1 < last_end_point) ($(end_point - 1) < $last_end_point)"); } last_end_point = end_point - 1; } - if (end_point == 0) {- warning ("End point is zero");+ if (unlikely (end_point == 0)) {+ warning (@"End point is zero for glyph $(glyph.get_name ())"); } } @@ -159,8 +176,8 @@ class GlyfData : GLib.Object { public static double tie_to_ttf_grid_y (Font font, double y) { double ttf_y;- ttf_y = rint (y * UNITS + font.base_line * UNITS);- return (ttf_y / UNITS) - font.base_line;+ ttf_y = rint (y * UNITS - font.base_line * UNITS);+ return (ttf_y / UNITS) + font.base_line; } void process_x () {@@ -194,18 +211,18 @@ class GlyfData : GLib.Object { foreach (Path p in paths) { foreach (EditPoint e in p.points) {- y = rint (e.y * UNITS - prev + font.base_line * UNITS);+ y = rint (e.y * UNITS - prev - font.base_line * UNITS); coordinate_y.append ((int16) y); - prev = rint (e.y * UNITS + font.base_line * UNITS);+ prev = rint (e.y * UNITS - font.base_line * UNITS); type = e.get_right_handle ().type; // off curve- y = rint (e.get_right_handle ().y () * UNITS - prev + font.base_line * UNITS);+ y = rint (e.get_right_handle ().y () * UNITS - prev - font.base_line * UNITS); coordinate_y.append ((int16) y); - prev = rint (e.get_right_handle ().y () * UNITS + font.base_line * UNITS);+ prev = rint (e.get_right_handle ().y () * UNITS - font.base_line * UNITS); } } }@@ -246,8 +263,13 @@ class GlyfData : GLib.Object { c += last; if ((flags.nth (i).data & Coordinate.ON_PATH) > 0) {- if (c < bounding_box_ymin) bounding_box_ymin = c;- if (c > bounding_box_ymax) bounding_box_ymax = c; + if (c < bounding_box_ymin) {+ bounding_box_ymin = c;+ }+ + if (c > bounding_box_ymax) {+ bounding_box_ymax = c;+ } } last = c;@@ -214,6 +214,11 @@ public class GlyfTable : Table { g.remove_empty_paths (); glyf_data = new GlyfData (g);+ + if (glyf_data.get_ncontours () == 0) {+ warning (@"No paths in $(g.get_name ()) ($(g.get_hex ())) can be exported.");+ }+ if (g.path_list.length () == 0 || glyf_data.paths.length () == 0) { // location_offsets will be equal to location_offset + 1 for // all empty glyphs@@ -132,23 +132,28 @@ public class NameTable : Table { printd (@"Name id: $(name_id.nth (i).data) platform: $(platform.nth (i).data) enc: $(encoding_id.nth (i).data) lang: $(lang.nth (i).data) len: $(strlen.nth (i).data) str: \"$(str.str)\"\n"); } }- + /** Create a valid PostScript name. */ public string validate_ps_name (string s) {+ return name_validation (s, false);+ }++ public string validate_name (string s) {+ return name_validation (s, true);+ }+ + public string name_validation (string s, bool allow_space) { string n; int ccount; unichar c; StringBuilder name = new StringBuilder (); n = s;- if (n.char_count () >= 28) {- n = truncate (n, 28);- }- ccount = n.char_count ();- for (int i = 0; i < ccount; i++) {+ // truncate strings longer than 28 characters+ for (int i = 0; i < ccount && i < 27; i++) { c = n.get_char (n.index_of_nth_char (i));- if (is_valid_ps_name_char (c)) {+ if (is_valid_ps_name_char (c) || (allow_space && c == ' ')) { name.append_unichar (c); } else { name.append_unichar ('_');@@ -156,7 +161,7 @@ public class NameTable : Table { } return name.str; - }+ } bool is_valid_ps_name_char (unichar c) { switch (c) {@@ -192,15 +197,6 @@ public class NameTable : Table { return false; } - string truncate (string s, int size) {- StringBuilder str = new StringBuilder ();- int cc = s.char_count ();- for (int i = 0; i < size && i < cc; i++) {- str.append_unichar (s.get_char (s.index_of_nth_char (i)));- }- return str.str;- }- public void process () throws GLib.Error { FontData fd = new FontData (); Font font = OpenFontFormatWriter.get_current_font ();@@ -216,22 +212,22 @@ public class NameTable : Table { text.append (font.copyright); type.append (COPYRIGHT_NOTICE); - text.append (validate_ps_name (font.name));+ text.append (validate_name (font.name)); type.append (FONT_NAME); - text.append (font.subfamily);+ text.append (validate_name (font.subfamily)); type.append (SUBFAMILY_NAME); - text.append (font.unique_identifier);+ text.append (validate_name (font.unique_identifier)); type.append (UNIQUE_IDENTIFIER); - text.append (validate_ps_name (font.full_name));+ text.append (validate_name (font.full_name)); type.append (FULL_FONT_NAME); text.append (font.version); type.append (VERSION); - text.append (validate_ps_name (font.postscript_name));+ text.append (validate_name (font.postscript_name)); type.append (POSTSCRIPT_NAME); text.append (font.description);@@ -240,7 +236,7 @@ public class NameTable : Table { text.append (validate_ps_name (font.name)); type.append (PREFERED_FAMILY); - text.append (font.subfamily);+ text.append (validate_name (font.subfamily)); type.append (PREFERED_SUB_FAMILY); num_records = (uint16) text.length ();@@ -128,11 +128,11 @@ public class OpenFontFormatReader : Object { f = BirdFont.get_current_font (); } - f.top_position = -get_ascender ();- f.top_limit = f.top_position - 5;- f.xheight_position = f.top_position - 5;- f.bottom_position = -get_descender ();- f.bottom_limit = f.bottom_position + 5; + f.top_position = get_ascender ();+ f.top_limit = f.top_position + 5;+ f.xheight_position = f.top_position + 5;+ f.bottom_position = get_descender ();+ f.bottom_limit = f.bottom_position - 5; } public double get_ascender () {@@ -111,7 +111,7 @@ public class Os2Table : Table { fd.add_u16 (ascender); // usWinAscent if (descender > 0) {- warning ("usWinDescent is unsigned.");+ warning (@"usWinDescent is unsigned, can not write $(-descender) to the field."); fd.add_u16 (0); } else { fd.add_u16 (-descender); // usWinDescent (not like sTypoDescender)@@ -585,7 +585,7 @@ int get_height (FT_Face face, guint unichar) { return 0; } - return (int) -face->glyph->metrics.height; + return (int) face->glyph->metrics.height; } /** Height of lower case letters. */@@ -614,7 +614,7 @@ int get_descender (FT_Face face) { FT_Get_Glyph (face->glyph, &glyph); FT_Glyph_Get_CBox (glyph, FT_GLYPH_BBOX_UNSCALED, &bbox); - return (int) -bbox.yMin; + return (int) bbox.yMin; } /** Append name table data to a gstring. */@@ -717,12 +717,12 @@ GString* get_bf_font (FT_Face face, char* file, int* err) { g_string_append_printf (bf, "<backup>%s</backup>\n", file); g_string_append_printf (bf, "<lines>\n");- g_string_append_printf (bf, "\t<top_limit>%f</top_limit>\n", -face->ascender * units);+ g_string_append_printf (bf, "\t<top_limit>%f</top_limit>\n", face->ascender * units); g_string_append_printf (bf, "\t<top_position>%f</top_position>\n", get_top (face) * units); g_string_append_printf (bf, "\t<x-height>%f</x-height>\n", get_xheight (face) * units); g_string_append_printf (bf, "\t<base_line>0</base_line>\n"); g_string_append_printf (bf, "\t<bottom_position>%f</bottom_position>\n", get_descender (face) * units);- g_string_append_printf (bf, "\t<bottom_limit>%f</bottom_limit>\n", -face->descender * units); + g_string_append_printf (bf, "\t<bottom_limit>%f</bottom_limit>\n", face->descender * units); g_string_append_printf (bf, "</lines>\n"); // glyph outlines@@ -102,7 +102,7 @@ class Svg { private static void add_abs_start (EditPoint ep, StringBuilder svg, Glyph g, bool to_glyph) { double left = g.left_limit;- double baseline = BirdFont.get_current_font ().base_line;+ double baseline = -BirdFont.get_current_font ().base_line; double height = BirdFont.get_current_font ().get_height (); svg.append_printf ("M");@@ -121,7 +121,7 @@ class Svg { } private static void add_abs_line_to (EditPoint start, EditPoint stop, StringBuilder svg, Glyph g, bool to_glyph) {- double baseline = BirdFont.get_current_font ().base_line;+ double baseline = -BirdFont.get_current_font ().base_line; double left = g.left_limit; double xa, ya, xb, yb;@@ -160,7 +160,7 @@ class Svg { private static void add_quadratic_abs_path (EditPoint start, EditPoint end, StringBuilder svg, Glyph g, bool to_glyph) { double left = g.left_limit;- double baseline = BirdFont.get_current_font ().base_line;+ double baseline = -BirdFont.get_current_font ().base_line; double height = BirdFont.get_current_font ().get_height (); // no probably not double xa, ya, xb, yb, xc, yc, xd, yd;@@ -193,7 +193,7 @@ class Svg { private static void add_cubic_abs_path (EditPoint start, EditPoint end, StringBuilder svg, Glyph g, bool to_glyph) { double left = g.left_limit;- double baseline = BirdFont.get_current_font ().base_line;+ double baseline = -BirdFont.get_current_font ().base_line; double height = BirdFont.get_current_font ().get_height (); // no probably not double xa, ya, xb, yb, xc, yc, xd, yd;