Commit 0eae353
expand and connect unicode ranges
Changed files (5)
modifiedsrc/GlyphRange.valaaddedsrc/OpenFontFormatReader.valamodifiedsrc/OpenFontFormatWriter.valamodifiedsrc/TestSupplement.valaaddedsrc/UniRange.vala
Diff
@@ -26,8 +26,6 @@ class GlyphRange { unichar len = 0; - public bool is_fill_unicode = false;- public GlyphRange () { } @@ -80,7 +78,6 @@ class GlyphRange { } public void use_full_unicode_range () {- is_fill_unicode = true; add_range ('\0', (unichar) 0xA868FE00); } @@ -110,26 +107,74 @@ class GlyphRange { } public void add_range (unichar start, unichar stop) {+ unichar b, s; if (unique (start, stop)) {- insert_range(start, stop);+ append_range (start, stop); } else { - unichar b = start;- unichar s = b;- while (b < stop) {- if (unique (b, b)) {- b++;- } else {- if (s != b) {- insert_range(s, b - 1);+ // make sure this range does not overlap existing ranges+ b = start;+ s = b;+ if (!unique (b, b)) { + while (b < stop) {+ if (!unique (b, b)) {+ b++;+ } else {+ if (s != b) {+ add_range (b, stop);+ }+ + b++;+ s = b; }- - b++;- s = b; }+ } else {+ while (b < stop) {+ if (unique (b, b)) {+ b++;+ } else {+ if (s != b) {+ add_range (start, b - 1);+ }+ + b++;+ s = b;+ }+ } } }+ }+ + private void append_range (unichar start, unichar stop) {+ UniRange r;+ + StringBuilder s = new StringBuilder ();+ StringBuilder e = new StringBuilder ();+ s.append_unichar (start);+ e.append_unichar (stop); + r = insert_range (start, stop); // insert a unique range+ merge_range (r); // join connecting ranges+ }+ + private void merge_range (UniRange r) {+ foreach (UniRange u in ranges) {+ if (u == r) {+ continue;+ } + + if (u.start == r.stop + 1) {+ u.start = r.start;+ ranges.remove_all (r);+ merge_range (u);+ }+ + if (u.stop == r.start - 1) {+ u.stop = r.stop;+ ranges.remove_all (r);+ merge_range (u);+ }+ } } public string get_char (unichar index) {@@ -183,7 +228,7 @@ class GlyphRange { if (inside (stop, u.start, u.stop)) return false; if (inside (u.start, start, stop)) return false; if (inside (u.stop, start, stop)) return false;-+ } return true;@@ -193,18 +238,33 @@ class GlyphRange { return (u_start <= start <= u_stop); } - private void insert_range (unichar start, unichar stop) {+ private UniRange insert_range (unichar start, unichar stop) { if (unlikely (start > stop)) { warning ("start > stop");- return;+ stop = start; } UniRange ur = new UniRange (start, stop); len += ur.length (); index_start.append (len); ranges.append (ur);+ + return ur; } + public void print_all () {+ StringBuilder s;+ + stdout.printf ("Ranges:\n");+ foreach (UniRange u in ranges) {+ s = new StringBuilder ();+ s.append_unichar (u.start);+ s.append (" - ");+ s.append_unichar (u.stop);+ s.append ("\n");+ stdout.printf (s.str);+ }+ } } }new file mode 100644@@ -0,0 +1,127 @@+/*+ Copyright (C) 2012 Johan Mattsson++ This program is free software: you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation, either version 3 of the License, or+ (at your option) any later version.++ This program 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 General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program. If not, see <http://www.gnu.org/licenses/>.+*/++namespace Supplement {++[SimpleType]+[CCode (has_type_id = false)] // Vala bug+public struct Fixed : uint32 {++ public void @set (uint16 upper, uint16 lower) {+ uint32* p = &this;+ *p = (upper << 16) + lower;+ }++ public bool @equals (uint16 upper, uint16 lower) {+ uint32 t = (upper << 16) + lower;+ return (t == this); + }++ public string get_string () {+ uint a = this >> 16;+ return @"$(a).$(this - (a << 16))";+ }+}++[SimpleType]+[CCode (has_type_id = false)] // same as above+public struct F2Dot14 : uint32 {+}++errordomain BadFormat {+ PARSE+}++class OpenFontFormatReader : Object {+ + OtfInputStream dis;+ DirectoryTable directory_table;+ + public OpenFontFormatReader (string file_name) {+ try {+ parse (file_name);+ } catch (Error e) {+ stderr.printf (e.message);+ }+ }+ + void parse (string file_name) throws Error {+ File f = File.new_for_path (file_name);+ if (!f.query_exists ()) {+ throw new FileError.EXIST(@"OpenFontFormatReader: file does not exist. $((!) f.get_path ())");+ }+ + dis = new OtfInputStream (f.read ());+ + parse_index ();+ done ();+ }+ + void done () {+ IdleSource idle = new IdleSource ();++ idle.set_callback (() => {+ Font f = Supplement.get_current_font ();+ f.loading_finished_callback ();+ return false;+ });++ idle.attach (null); + }+ + void parse_index () throws Error {+ OffsetTable offset_table;+ + directory_table = new DirectoryTable ();+ + offset_table = new OffsetTable (directory_table);+ offset_table.parse (dis);+ + directory_table = new DirectoryTable ();+ directory_table.set_offset_table (offset_table);+ directory_table.parse (dis);+ + set_limits ();+ }++ public void set_limits () {+ IdleSource idle = new IdleSource ();++ idle.set_callback (() => {+ Font f = Supplement.get_current_font ();+ + f.base_line = 0;+ f.top_position = -get_ascender ();+ f.top_limit = f.top_position - 5;+ f.bottom_position = -get_descender ();+ f.bottom_limit = f.bottom_position + 5; ++ return false;+ });++ idle.attach (null);+ }++ public double get_ascender () {+ return directory_table.hhea_table.get_ascender ();+ }+ + public double get_descender () {+ return directory_table.hhea_table.get_descender ();+ }}++}@@ -1403,6 +1403,8 @@ class CmapSubtableWindowsUnicode : CmapSubtable { } } + glyph_range.print_all (); + ranges = glyph_range.get_ranges (); seg_count = (uint16) ranges.length () + 1; seg_count_2 = seg_count * 2; @@ -33,6 +33,7 @@ class TestCases { public List<Test> test_cases; public TestCases () { + add (test_glyph_ranges, "Glyph ranges"); add (test_glyph_table, "Glyph table"); add (test_active_edit_point, "Active edit point"); add (test_hex, "Unicode hex values"); @@ -45,6 +46,23 @@ class TestCases { add (test_save_backup, "Save backup"); } + public static void test_glyph_ranges () { + GlyphRange gr = new GlyphRange (); + + gr.add_range ('b', 'c'); + gr.add_single ('d'); + gr.add_range ('e', 'h'); + gr.add_range ('k', 'm'); + gr.add_range ('o', 'u'); + gr.add_range ('a', 'd'); + gr.add_range ('f', 'z'); + gr.add_range ('b', 'd'); + + return_if_fail (gr.length () == 'z' - 'a' + 1); + return_if_fail (gr.get_ranges ().length () == 1); + return_if_fail (gr.get_ranges ().first ().data.length () == 'z' - 'a' + 1); + } + public static void test_glyph_table () { GlyphTable table = new GlyphTable (); List<GlyphCollection> gc = new List<GlyphCollection> (); new file mode 100644@@ -0,0 +1,47 @@+/*+ Copyright (C) 2012 Johan Mattsson++ This program is free software: you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation, either version 3 of the License, or+ (at your option) any later version.++ This program 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 General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program. If not, see <http://www.gnu.org/licenses/>.+*/++namespace Supplement { + class UniRange : GLib.Object {+ + public unichar start;+ public unichar stop;+ + public UniRange (unichar start, unichar stop) {+ this.start = start;+ this.stop = stop;+ }+ + public unichar length () {+ return stop - start + 1;+ }++ public unichar get_char (unichar index) {+ unichar result = start + index;+ + if (unlikely (index < 0)) {+ warning ("Index is negative in UniRange.");+ }+ + if (unlikely (!(start <= result <= stop))) {+ warning ("Index out of range in UniRange (%u <= %u <= %u) (index: %u)\n", start, result, stop, index);+ }+ + return result;+ }+ }+}