Commit 3191744
Merge branch 'master' of /home/johan/birdfont-android/../birdfont
Changed files (21)
modifiedbirdfont/GtkWindow.valamodifiedbirdfont/Main.valamodifiedconfiguremodifieddodo.pymodifiedinstall.pymodifiedlibbirdfont/Argument.valamodifiedlibbirdfont/BirdFont.valamodifiedlibbirdfont/BirdFontFile.valamodifiedlibbirdfont/BirdFontPart.valamodifiedlibbirdfont/CharDatabase.valamodifiedlibbirdfont/CharDatabaseParser.valaaddedlibbirdfont/FallbackFont.valamodifiedlibbirdfont/OpenFontFormat/CodePageBits.valamodifiedlibbirdfont/Path.valamodifiedlibbirdfont/StrokeTool.valamodifiedlibbirdfont/TestCases.valamodifiedlibbirdgems/fit_cubic.caddedresources/codepages.sqliteaddedresources/ucd.sqlitemodifiedscripts/build.pyaddedsqlite3.vapi
Diff
@@ -179,7 +179,7 @@ public class GtkWindow : Gtk.Window, NativeWindow { add (vbox); try {- set_icon_from_file ((!) Icons.find_icon ("birdfont_window_icon.png").get_path ());+ set_icon_from_file ((!) SearchPaths.find_file (null, "birdfont_window_icon.png").get_path ()); } catch (GLib.Error e) { warning (e.message); }@@ -23,7 +23,6 @@ public static int main (string[] arg) { string file; BirdFont.BirdFont birdfont; - Icons.use_high_resolution (true); birdfont = new BirdFont.BirdFont (); birdfont.init (arg, null); Gtk.init (ref arg);@@ -36,50 +35,8 @@ public static int main (string[] arg) { birdfont.load_font_from_command_line (); - load_ucd (); Gtk.main ();- return 0; } -/** Load descriptions from the unicode character database in a - * background thread.- */-void load_ucd () { - CharDatabaseParser db;- unowned Thread<CharDatabaseParser> db_thread;- Mutex database_mutex = new Mutex ();- Cond main_loop_idle = new Cond ();- bool in_idle = false;- - try {- db = new CharDatabaseParser ();- db_thread = Thread.create<CharDatabaseParser> (db.load, false);- - // wait until main loop is done- db.sync.connect (() => {- database_mutex.lock ();- IdleSource idle = new IdleSource ();- in_idle = false;- - idle.set_callback (() => {- database_mutex.lock ();- in_idle = true;- main_loop_idle.broadcast ();- database_mutex.unlock ();- return false;- });- idle.attach (null);- - while (!in_idle) {- main_loop_idle.wait (database_mutex);- }- - database_mutex.unlock ();- });- } catch (GLib.Error e) {- warning (e.message);- }-}- @@ -71,15 +71,16 @@ def configure (gtk, libbgee, posixvala): 'gtk+-3.0', 'webkitgtk-3.0', 'libsoup-2.4',- 'libnotify'+ 'libnotify',+ 'sqlite3' ] else: libs = [ 'gdk-pixbuf-2.0', 'gio-2.0', 'glib-2.0', + 'sqlite' ]- for lib in libs: if not test_library_version (lib):@@ -44,6 +44,7 @@ DOIT_CONFIG = { # external Vala libs LIBS = [+ 'sqlite3', 'glib-2.0', 'gio-2.0', 'cairo',@@ -105,6 +105,8 @@ install ('resources/key_bindings.xml', '/share/birdfont', 644) install ('resources/roboto.bf', '/share/birdfont', 644) install ('resources/linux/birdfont_window_icon.png', '/share/birdfont', 644) install ('resources/linux/birdfont.desktop', '/share/applications', 644)+install ('resources/ucd.sqlite', '/share/birdfont', 644)+install ('resources/codepages.sqlite', '/share/birdfont', 644) install ('resources/linux/256x256/birdfont.png', '/share/icons/hicolor/256x256/apps', 644) install ('resources/linux/128x128/birdfont.png', '/share/icons/hicolor/128x128/apps', 644)@@ -1,5 +1,5 @@ /*- Copyright (C) 2012 Johan Mattsson+ Copyright (C) 2012 2015 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 @@ -16,18 +16,18 @@ namespace BirdFont { public class Argument : GLib.Object { - List<string> args;+ Gee.ArrayList<string> args; public Argument (string line) {- args = new List<string> ();+ args = new Gee.ArrayList<string> (); set_argument (line); } public Argument.command_line (string[] arg) { - args = new List<string> ();+ args = new Gee.ArrayList<string> (); foreach (string a in arg) {- args.append (a);+ args.add (a); } } @@ -35,8 +35,9 @@ public class Argument : GLib.Object { public int validate () { string prev = ""; int i = 0;- foreach (string a in args) {- + string[] p;+ + foreach (string a in args) { if (a == "") { continue; }@@ -55,6 +56,11 @@ public class Argument : GLib.Object { continue; } + if (a.index_of ("=") > -1) {+ p = a.split ("=");+ a = p[0];+ }+ // a single character, like -t if (!a.has_prefix ("--") && a.has_prefix ("-")) { a = expand_param (a);@@ -71,8 +77,9 @@ public class Argument : GLib.Object { a == "--mac" || a == "--android" || a == "--log" ||- a == "--no-ucd" ||- a == "--windows") {+ a == "--windows" ||+ a == "--parse-ucd" ||+ a == "--codepages") { prev = a; i++; continue;@@ -96,8 +103,8 @@ public class Argument : GLib.Object { public string get_file () { string f = ""; - if (args.length () >= 2) {- f = args.nth (1).data;+ if (args.size >= 2) {+ f = args.get (1); } if (f.has_prefix ("-")) {@@ -108,7 +115,7 @@ public class Argument : GLib.Object { } public void print_all () {- print (@"$(args.length ()) arguments:\n");+ print (@"$(args.size) arguments:\n"); foreach (string p in args) { print (@"$p\n");@@ -124,7 +131,9 @@ public class Argument : GLib.Object { int i = 0; string? n; string p;-+ string v = "";+ string[] pm;+ if (param.substring (0, 1) != "-") { warning (@"parameters must begin with \"-\" got $param"); return null;@@ -132,10 +141,22 @@ public class Argument : GLib.Object { foreach (string s in args) { + if (s.index_of ("=") > -1) {+ pm = s.split ("=");+ + if (pm.length > 1) {+ v = pm[1];+ }+ + s = pm[0];+ }+ // this is content not a parameter - if (s.substring (0, 1) != "-") continue;+ if (s.substring (0, 1) != "-") {+ continue;+ } - // we might need to expand -t to test fo instance+ // we might need to expand -t to test for instance if (s.substring (0, 2) != "--") { p = expand_param (s); } else { @@ -143,20 +164,24 @@ public class Argument : GLib.Object { } if (param == p) {- if (i + 2 >= args.length ()) {+ if (v != "") {+ return v;+ }+ + if (i + 2 >= args.size) { return ""; } - n = args.nth (i + 2).data;+ n = args.get (i + 2); if (n == null) { return ""; } - if (args.nth (i + 2).data.substring (0, 1) == "-") {+ if (args.get (i + 2).substring (0, 1) == "-") { return ""; } - return args.nth (i + 2).data;+ return args.get (i + 2); } i++;@@ -184,10 +209,14 @@ public class Argument : GLib.Object { private string expand_param (string? param) { if (param == null) return ""; var p = (!) param;++ if (p.get_char (0) != '-') {+ return "";+ } - if (p.length == 0) return "";- if (p.get_char (0) != '-') return "";- if (p.char_count () != 2) return "";+ if (p.char_count () != 2) {+ return "";+ } switch (p.get_char (1)) { case 'c':@@ -235,17 +264,17 @@ public class Argument : GLib.Object { n = arg.substring (i, a - i + 1); } - args.append (n);+ args.add (n); i += n.char_count () + 1; } while (i < arg.char_count ()); } public void print_help () - requires (args.length () > 0)+ requires (args.size > 0) { stdout.printf (t_("Usage") + ": ");- stdout.printf (args.nth (0).data);+ stdout.printf (args.get (0)); stdout.printf (" [" + t_("FILE") + "] [" + t_("OPTION") + " ...]\n"); print_padded ("-a, --android", t_("enable Android customizations"));@@ -398,7 +398,9 @@ public class BirdFont { string theme; int default_theme_version; string theme_version;- + CharDatabaseParser parser;+ CodePageBits codepage_bits;+ args = new Argument.command_line (arg); #if ANDROID@@ -524,6 +526,16 @@ public class BirdFont { if (TestBirdFont.get_singleton ().test_cases_to_run != "All") { TestBirdFont.run_tests (); }+ + if (has_argument ("--parse-ucd")) {+ parser = new CharDatabaseParser ();+ parser.regenerate_database ();+ }++ if (has_argument ("--codepages")) {+ codepage_bits = new CodePageBits ();+ codepage_bits.generate_codepage_database ();+ } } public static Argument get_arguments () {@@ -377,12 +377,12 @@ class BirdFontFile : GLib.Object { write_glyph_collection_start (gc, os); write_selected (gc, os); foreach (Glyph g in gc.get_version_list ().glyphs) {- write_glyph (g, gc, os);+ write_glyph (g, os); } write_glyph_collection_end (os); } - public void write_glyph (Glyph g, GlyphCollection gc, DataOutputStream os) throws GLib.Error {+ public void write_glyph (Glyph g, DataOutputStream os) throws GLib.Error { string data; os.put_string (@"\t<glyph id=\"$(g.version_id)\" left=\"$(double_to_string (g.left_limit))\" right=\"$(double_to_string (g.right_limit))\">\n");@@ -390,7 +390,10 @@ class BirdFontFile : GLib.Object { data = get_point_data (p); if (data != "") { os.put_string (@"\t\t<path ");- os.put_string (@"stroke=\"$(double_to_string (p.stroke))\" ");+ + if (p.stroke != 0) {+ os.put_string (@"stroke=\"$(double_to_string (p.stroke))\" ");+ } if (p.line_cap != LineCap.BUTT) { if (p.line_cap == LineCap.ROUND) {@@ -265,7 +265,7 @@ public class BirdFontPart : GLib.Object{ os = create_file (@"$(file_name).bfp", "glyphs", dir_name); bf.write_root_tag (os); bf.write_glyph_collection_start (gc, os);- bf.write_glyph (g, gc, os);+ bf.write_glyph (g, os); bf.write_glyph_collection_end (os); bf.write_closing_root_tag (os); os.close ();@@ -1,5 +1,5 @@ /*- Copyright (C) 2012 Johan Mattsson+ Copyright (C) 2012 2015 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 @@ -13,32 +13,47 @@ */ using Gee;+using Sqlite; namespace BirdFont { public class CharDatabase {- - public static HashMap<string, string> entries;- public static HashMultiMap<string, string> index;- public static GlyphRange full_unicode_range;- public static bool database_is_loaded = false;++ public static unowned Database db;+ public static Database? database = null; public CharDatabase () {- entries = new HashMap<string, string> ();- index = new HashMultiMap<string, string> ();- + File f;+ full_unicode_range = new GlyphRange ();+ f = get_database_file ();+ open_database () ;+ }+ + public static void open_database () {+ File f = get_database_file ();+ int rc = Database.open ((!) f.get_path (), out database);++ db = (!) database;++ if (rc != Sqlite.OK) {+ stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ());+ }+ }+ + public static File get_database_file () {+ return SearchPaths.find_file (null, "ucd.sqlite"); } public static GlyphRange search (string s) { GlyphRange result = new GlyphRange (); GlyphRange ucd_result = new GlyphRange ();+ int rc, cols;+ Statement statement;+ string select; unichar c; - return_val_if_fail (!is_null (index), result); - return_val_if_fail (result.get_length () == 0, result);- if (s.has_prefix ("U+") || s.has_prefix ("u+")) { c = Font.to_unichar (s.down ()); @@ -46,23 +61,49 @@ public class CharDatabase { result.add_single (c); } }- + if (s.char_count () == 1) {- result.add_single (s.get_char ()); - }- - foreach (string i in index.get (s)) {- c = Font.to_unichar ("U+" + i.down ());- ucd_result.add_single (c);+ result.add_single (s.get_char (0)); }++ select = "SELECT unicode FROM Words "+ + "WHERE word = '" + s.replace ("'", "''") + "';";+ + rc = db.prepare_v2 (select, select.length, out statement, null); - try {- if (ucd_result.get_length () > 0) {- ucd_result.sort ();- result.parse_ranges (ucd_result.get_all_ranges ());+ if (rc == Sqlite.OK) {+ cols = statement.column_count();+ + if (cols != 1) {+ warning ("Expecting one column.");+ return result; }- } catch (MarkupError e) {- warning (e.message);++ while (true) {+ rc = statement.step ();+ + if (rc == Sqlite.DONE) {+ break;+ } else if (rc == Sqlite.ROW) {+ c = (unichar) statement.column_int64 (0);+ ucd_result.add_single (c);+ } else {+ warning ("Error: %d, %s\n", rc, db.errmsg ());+ break;+ }+ }+ + try {+ if (ucd_result.get_length () > 0) {+ ucd_result.sort ();+ result.parse_ranges (ucd_result.get_all_ranges ());+ }+ } catch (MarkupError e) {+ warning (e.message);+ }+ + } else {+ warning ("SQL error: %d, %s\n", rc, db.errmsg ()); } return result;@@ -95,35 +136,45 @@ public class CharDatabase { return false; } - /** Convert from the U+xx form to the unicode database hex value. */ - static string to_database_hex (unichar c) {- string hex_char = Font.to_hex (c).replace ("U+", "");-- if (hex_char.char_count () == 2) {- hex_char = "00" + hex_char;- }- - if (hex_char.char_count () == 6 && hex_char.has_prefix ("0")) {- hex_char = hex_char.substring (1);- }- - hex_char = hex_char.up (); - return hex_char;- }- public static string get_unicode_database_entry (unichar c) {- string description;- string? d;+ string description = "";+ int rc, cols;+ Statement statement;+ string select = "SELECT description FROM Description "+ + @"WHERE unicode = $((int64) c)"; - d = entries.get (to_database_hex (c));+ rc = db.prepare_v2 (select, select.length, out statement, null); - if (d == null) {- description = Font.to_hex (c).replace ("U+", "") + "\tUNICODE CHARACTER";+ if (rc == Sqlite.OK) {+ cols = statement.column_count();+ + if (cols != 1) {+ warning ("Expecting one column.");+ return description;+ }++ while (true) {+ rc = statement.step ();+ + if (rc == Sqlite.DONE) {+ break;+ } else if (rc == Sqlite.ROW) {+ description = statement.column_text (0);+ } else {+ printerr ("Error: %d, %s\n", rc, db.errmsg ());+ break;+ }+ }+ } else {- description = (!) d;+ printerr ("SQL error: %d, %s\n", rc, db.errmsg ());+ }+ + if (description == "") {+ description = Font.to_hex (c).replace ("U+", "") + "\tUNICODE CHARACTER"; } - return description; + return description; } public static void get_full_unicode (GlyphRange glyph_range) {@@ -1,5 +1,5 @@ /*- Copyright (C) 2013 Johan Mattsson+ Copyright (C) 2013 2015 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 @@ -13,18 +13,120 @@ */ using Gee;+using Sqlite; namespace BirdFont { public class CharDatabaseParser : GLib.Object {+ public static unowned Database db;+ public static Database? database = null; - public signal void sync ();- GlyphRange utf8 = new GlyphRange (); public CharDatabaseParser () { } + public File get_database_file () {+ string? fn = BirdFont.get_argument ("--parse-ucd");+ + if (fn != null && ((!) fn) != "") {+ return File.new_for_path ((!) fn);+ }+ + return File.new_for_path ("ucd.sqlite");+ }+ + public void regenerate_database () {+ File f = get_database_file ();+ + stdout.printf ("Generating sqlite database in: %s\n", (!) f.get_path ());+ + try {+ if (f.query_exists ()) {+ f.delete ();+ }+ + open_database ();+ create_tables ();+ parse_all_entries ();+ } catch (GLib.Error e) {+ warning (e.message);+ }+ }+ + public void open_database () {+ File f = get_database_file ();+ int rc = Database.open ((!) f.get_path (), out database);++ db = (!) database;++ if (rc != Sqlite.OK) {+ stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ());+ }+ }+ + public void create_tables () {+ int ec;+ string? errmsg;+ string description_table = """+ CREATE TABLE Description (+ unicode INTEGER PRIMARY KEY NOT NULL,+ description TEXT NOT NULL+ );+ """;++ ec = db.exec (description_table, null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }++ string index_table = """+ CREATE TABLE Words (+ unicode INTEGER NOT NULL,+ word TEXT NOT NULL+ );+ """;++ ec = db.exec (index_table, null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }++ string create_index = "CREATE INDEX word_index ON Words (word);";++ ec = db.exec (create_index, null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }+ }++ public void insert_lookup (int64 character, string word) {+ string? errmsg;+ string query = """+ INSERT INTO Words (unicode, word)+ VALUES (""" + @"$((int64) character)" + """, '""" + word.replace ("'", "''") + "');";+ int ec = db.exec (query, null, out errmsg);+ if (ec != Sqlite.OK) {+ stderr.printf (query);+ warning ("Error: %s\n", (!) errmsg);+ }+ }+ + public void insert_entry (int64 character, string description) {+ string? errmsg;+ string query = """+ INSERT INTO Description (unicode, description)+ VALUES (""" + @"$((int64) character)" + """, '""" + description.replace ("'", "''") + "');";+ + int ec = db.exec (query, null, out errmsg);+ + if (ec != Sqlite.OK) {+ stderr.printf (query);+ warning ("Error: %s\n", (!) errmsg);+ warning (@"Can't insert description to: $(character)");+ }+ }+ private void add_entry (string data) { string[] e; string[] r;@@ -61,13 +163,8 @@ public class CharDatabaseParser : GLib.Object { unicode_hex = e[0].up (); ch = Font.to_unichar ("U+" + unicode_hex.down ());- - Idle.add (() => {- CharDatabase.entries.set (unicode_hex, data);- return false;- });- sync ();- + stdout.printf ("Adding " + (!) ch.to_string () + "\n");+ insert_entry ((int64) ch, data); utf8.add_single (ch); foreach (string s in e) {@@ -76,11 +173,7 @@ public class CharDatabaseParser : GLib.Object { d = t.split (" "); foreach (string token in d) { if (token != "") {- Idle.add (() => {- CharDatabase.index.set (token, unicode_hex);- return false;- });- sync ();+ insert_lookup ((int64)ch, token); } } }@@ -94,14 +187,17 @@ public class CharDatabaseParser : GLib.Object { string data; string description = ""; File file;+ int ec;+ string? errmsg;+ uint64 transaction_number = 0;+ + file = get_unicode_database (); - if (BirdFont.has_argument ("--no-ucd")) {- warning ("Not loading UCD.");- return;+ ec = db.exec ("BEGIN TRANSACTION", null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg); }-- file = get_unicode_database ();- + try { fin = file.read (); din = new DataInputStream (fin);@@ -119,6 +215,23 @@ public class CharDatabaseParser : GLib.Object { } else { if (description.index_of ("<not a character>") == -1) { add_entry (description);+ transaction_number++;+ + if (transaction_number >= 1000) {+ print ("Write to database\n");+ + ec = db.exec ("END TRANSACTION", null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ } ++ ec = db.exec ("BEGIN TRANSACTION", null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }+ + transaction_number = 0; + } } break; } @@ -139,23 +252,16 @@ public class CharDatabaseParser : GLib.Object { warning (e.message); warning ("In %s", (!) get_unicode_database ().get_path ()); }- }- - public CharDatabaseParser load () {- parse_all_entries (); - IdleSource idle = new IdleSource ();- idle.set_callback (() => {- CharDatabase.full_unicode_range = utf8;- CharDatabase.database_is_loaded = true;- return false;- });- idle.attach (null);- - return this;+ ec = db.exec ("END TRANSACTION", null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }+ + stdout.printf ("Done"); } - static File get_unicode_database () {+ File get_unicode_database () { return SearchPaths.get_char_database (); } }new file mode 100644@@ -0,0 +1,121 @@+/*+ Copyright (C) 2015 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.+*/++using Gee;+using Sqlite;++namespace BirdFont {++public class FallbackFont : GLib.Object {+ public static unowned Database db;+ public static Database? database = null;++ public FallbackFont () { + }++ public File get_database_file () {+ return SearchPaths.find_file (null, "fallback-font.sqlite");+ }+ + public File get_new_database_file () {+ string? fn = BirdFont.get_argument ("--fallback-font");+ + if (fn != null && ((!) fn) != "") {+ return File.new_for_path ((!) fn);+ }+ + return File.new_for_path ("fallback-font.sqlite");+ }+ + public void generate_fallback_font () {+ File f = get_new_database_file ();+ string? fonts = BirdFont.get_argument ("--fonts");+ string fallback;+ + if (fonts == null) {+ stderr.printf ("Add a list of fonts to use as fallback to the \"--fonts\" argument.\n");+ stderr.printf ("Separate each font file with \":\"\n");+ return;+ }+ + fallback = (!) fonts;+ + stdout.printf ("Generating fallback font: %s\n", (!) f.get_path ());+ + try {+ if (f.query_exists ()) {+ f.delete ();+ }+ + open_database (f);+ create_tables ();+ + foreach (string font in fallback.split (":")) {+ add_font (font);+ } + } catch (GLib.Error e) {+ warning (e.message);+ }+ + }++ public void add_font (string font_file) {+ Font font;+ Glyph g;+ BirdFontFile bf;+ File single_glyph_font;+ + font = new Font ();+ single_glyph_font = File.new_for_path ("/tmp/fallback_glyph.bf");+ + font.set_file (font_file);+ if (!font.load ()) {+ stderr.printf ("Failed to load font: " + font_file);+ return;+ }+ + for (int i = 0; i < font.length (); i++) {+ g = (!) font.get_glyph_indice (i);+ bf = new BirdFontFile (font);+ }+ }++ public void open_database (File db_file) {+ int rc = Database.open ((!) db_file.get_path (), out database);++ db = (!) database;++ if (rc != Sqlite.OK) {+ stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ());+ }+ }++ public void create_tables () {+ int ec;+ string? errmsg;+ string create_font_table = """+ CREATE TABLE FallbackFont (+ unicode INTEGER PRIMARY KEY NOT NULL,+ font_data TEXT NOT NULL+ );+ """;+ + ec = db.exec (create_font_table, null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }+ }+}++}@@ -1,5 +1,5 @@ /*- Copyright (C) 2014 Johan Mattsson+ Copyright (C) 2014 2015 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 @@ -12,28 +12,32 @@ Lesser General Public License for more details. */ +using Sqlite;+ namespace BirdFont { public class CodePageBits : GLib.Object { /** The first characters in all code pages. */ PageBit default_range;- - static bool has_codepages = false; static Gee.ArrayList<PageBit> codepages; - - public CodePageBits () {- default_range = new PageBit (-1, "null-");+ static Gee.ArrayList<string> all_characters; ++ public static unowned Database db;+ public static Database? database = null; - if (!has_codepages) {- codepages = new Gee.ArrayList<PageBit> ();- create_codepage_list ();- has_codepages = true;+ public CodePageBits () {+ if (database == null) {+ open_database (get_database_file ()); } }++ public File get_database_file () {+ return SearchPaths.find_file (null, "codepages.sqlite");+ } public void get_pages (Font font, out uint32 p0, out uint32 p1) {- uint32 indice;+ uint32 indice, a0, a1; GlyphCollection? gl; GlyphCollection g; @@ -43,46 +47,52 @@ public class CodePageBits : GLib.Object { for (indice = 0; (gl = font.get_glyph_collection_indice (indice)) != null; indice++) { g = (!) gl; - if (default_range.has_char (g.get_unicode_character ())) {- set_bit (0, ref p0, ref p1);- } else {- set_bits_for_glyph (g, ref p0, ref p1);- }- }- }-- void set_bits_for_glyph (GlyphCollection g, ref uint32 p0, ref uint32 p1) {- Gee.ArrayList<int> bits;- - if (!g.is_unassigned ()) {- bits = get_bits (g.get_unicode_character ());- - foreach (int bit in bits) {- set_bit (bit, ref p0, ref p1);+ if (!g.is_unassigned ()) {+ get_bits (g.get_unicode_character (), out a0, out a1);+ p0 |= a0;+ p1 |= a1; } } } - public Gee.ArrayList<int> get_bits (unichar c) {- Gee.ArrayList<int> bits = new Gee.ArrayList<int> ();- foreach (PageBit pb in codepages) {- if (pb.has_char (c)) {- bits.add (pb.bit); + public void get_bits (unichar ch, out uint p0, out uint p1) {+ int rc, cols;+ Statement statement;+ int64 c = (int64) ch;+ string select = "SELECT codepages1, codepages2 FROM CodePages "+ + "WHERE unicode = " + @"$c" + ";";+ + p0 = 0; + p1 = 0;+ + rc = db.prepare_v2 (select, select.length, out statement, null);+ + if (rc == Sqlite.OK) {+ cols = statement.column_count();+ + if (cols != 2) {+ warning ("Expecting two columns.");+ return; }- }- return bits;- } - void set_bit (int bit, ref uint32 p0, ref uint32 p1) {- const int length = 32;- - if (bit < length) {- p0 |= 1 << bit;+ while (true) {+ rc = statement.step ();+ + if (rc == Sqlite.DONE) {+ break;+ } else if (rc == Sqlite.ROW) {+ p0 = (uint) statement.column_int64 (0);+ p1 = (uint) statement.column_int64 (1);+ } else {+ printerr ("Error: %d, %s\n", rc, db.errmsg ());+ break;+ }+ } } else {- p1 |= 1 << (bit - length);+ warning ("Database error: %s", db.errmsg ()); } }-+ void create_codepage_list () { // TODO: Add ASMO // Windows-1252@@ -149,11 +159,157 @@ public class CodePageBits : GLib.Object { create_codepage (63, "- ß-â ä-ï Ä-Ç É ö-÷ ñ-ô ù-ü ÿ Ö Ü -£ ¥ ₧ ƒ Ñ ¿ ⌐ ª-¬ º-½ ▐-▓ │ ┤ ┐ └ ┴ ┬ ├ ─ ┼ ═-╬ ┘ ┌ █ ▄ ▌ ▀ α Γ π Σ σ-τ µ Φ Θ Ω δ-ε ∞ φ ∩ ≡ °-² ≤-≥ ⌠-⌡ ≈ ∙-√ · ⁿ ■"); } - void create_codepage (int bit, string ranges) {- PageBit b = new PageBit (bit, ranges);+ void create_codepage (int bit, string characters) {+ string c;+ PageBit b = new PageBit (bit, characters); codepages.add (b);+ + for (int i = 0; i < b.ranges.length (); i++) {+ c = b.ranges.get_char (i);+ if (all_characters.index_of (c) == -1) {+ all_characters.add (c);+ }+ }+ }+ + File get_new_database_file () {+ string? fn = BirdFont.get_argument ("--codepages");+ + if (fn != null && ((!) fn) != "") {+ return File.new_for_path ((!) fn);+ }+ + return File.new_for_path ("codepages.sqlite");+ }+ + public void generate_codepage_database () {+ File f = get_new_database_file ();++ stdout.printf ("Generating codepage database: %s\n", (!) f.get_path ());++ try {+ if (f.query_exists ()) {+ f.delete ();+ }+ + open_database (f);+ create_tables ();+ + default_range = new PageBit (-1, "null-");+ codepages = new Gee.ArrayList<PageBit> ();+ all_characters = new Gee.ArrayList<string> ();+ create_codepage_list ();+ + write_database ();+ } catch (GLib.Error e) {+ warning (e.message);+ }+ + stdout.printf ("Done\n");+ }++ void write_database () {+ unichar ch;+ uint32 pages1, pages2;+ string? errmsg;+ + int ec = db.exec ("BEGIN TRANSACTION", null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }+ + foreach (string c in all_characters) {+ ch = c.get_char (0);+ get_pages_for_character (ch, out pages1, out pages2);+ insert_codepage_for_character ((int64) ch, pages1, pages2);+ }+ + ec = db.exec ("END TRANSACTION", null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }+ }++ void insert_codepage_for_character (int64 character, uint32 codepages1, uint32 codepages2) {+ string? errmsg;+ string query = """+ INSERT INTO CodePages (unicode, codepages1, codepages2)+ VALUES (""" + @"$((int64) character)" + ", " + @"$(codepages1), " + @"$(codepages2)" + ");";+ int ec = db.exec (query, null, out errmsg);+ if (ec != Sqlite.OK) {+ stderr.printf (query);+ warning ("Error: %s\n", (!) errmsg);+ }+ }+ + void open_database (File db_file) {+ int rc = Database.open ((!) db_file.get_path (), out database);++ db = (!) database;++ if (rc != Sqlite.OK) {+ stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ());+ }+ }++ void create_tables () {+ int ec;+ string? errmsg;+ string create_font_table = """+ CREATE TABLE CodePages (+ unicode INTEGER PRIMARY KEY NOT NULL,+ codepages1 INTEGER NOT NULL,+ codepages2 INTEGER NOT NULL+ );+ """;+ + ec = db.exec (create_font_table, null, out errmsg);+ if (ec != Sqlite.OK) {+ warning ("Error: %s\n", (!) errmsg);+ }+ }++ void get_pages_for_character (unichar character, out uint32 p0, out uint32 p1) {+ p0 = 0;+ p1 = 0;+ + if (default_range.has_char (character)) {+ set_bit (0, ref p0, ref p1);+ } else {+ set_bits_for_character (character, ref p0, ref p1);+ } } + void set_bits_for_character (unichar c, ref uint32 p0, ref uint32 p1) {+ Gee.ArrayList<int> bits;+ + bits = get_code_page_bits (c);+ + foreach (int bit in bits) {+ set_bit (bit, ref p0, ref p1);+ }+ }+ + Gee.ArrayList<int> get_code_page_bits (unichar c) {+ Gee.ArrayList<int> bits = new Gee.ArrayList<int> ();+ foreach (PageBit pb in codepages) {+ if (pb.has_char (c)) {+ bits.add (pb.bit); + }+ }+ return bits;+ }+ + void set_bit (int bit, ref uint32 p0, ref uint32 p1) {+ const int length = 32;+ + if (bit < length) {+ p0 |= 1 << bit;+ } else {+ p1 |= 1 << (bit - length);+ }+ }+ private class PageBit : GLib.Object { public GlyphRange ranges; public int bit;@@ -1290,7 +1290,7 @@ public class Path { ep.get_left_handle ().set_point_type (PointType.LINE_DOUBLE_CURVE); ep.type = PointType.DOUBLE_CURVE; } else {- warning ("Point types: $right and $left in insert_new_point_on_path");+ warning (@"Point types: $right and $left in insert_new_point_on_path"); } ep.get_left_handle ().parent = ep;@@ -71,20 +71,6 @@ public class StrokeTool : Tool { convert_stroke = false; } - public PathList merge_selected_paths () {- PathList n = new PathList ();- Glyph g = MainWindow.get_current_glyph ();- - foreach (Path p in g.active_paths) {- if (p.stroke == 0) {- n.add (p);- }- }- - n = merge (n);- return n;- }- public static PathList get_stroke_fast (Path path, double thickness) { PathList o; Path stroke;@@ -114,7 +100,21 @@ public class StrokeTool : Tool { return m; }- ++ public PathList merge_selected_paths () {+ PathList n = new PathList ();+ Glyph g = MainWindow.get_current_glyph ();+ + foreach (Path p in g.active_paths) {+ if (p.stroke == 0) {+ n.add (p);+ }+ }+ + n = merge (n);+ return n;+ }+ static Path simplify_stroke (Path p) { Path simplified = new Path (); Path segment, added_segment;@@ -272,7 +272,7 @@ public class StrokeTool : Tool { PathList r = new PathList (); foreach (Path p in pl.paths) {- if (p.points.size > 22) {+ if (p.points.size > 7) { r.add (p); } else if (!has_new_corner (p)) { r.add (p);@@ -84,20 +84,25 @@ class TestCases { public static void test_codepages () { CodePageBits pages = new CodePageBits ();+ uint32 p0, p1; - if (pages.get_bits ('ó').size == 0) {+ pages.get_bits ('ó', out p0, out p1);+ if (p0 == 0 && p1 == 0) { warning ("Codepage for Hungarian is not set."); } - if (pages.get_bits ('ö').size == 0) {+ pages.get_bits ('ö', out p0, out p1);+ if (p0 == 0 && p1 == 0) { warning ("Codepage for Swedish is not set."); } - if (pages.get_bits ('ツ').size == 0) {+ pages.get_bits ('ツ', out p0, out p1);+ if (p0 == 0 && p1 == 0) { warning ("Codepage for Japanese is not set."); } - if (pages.get_bits ('马').size == 0) {+ pages.get_bits ('马', out p0, out p1);+ if (p0 == 0 && p1 == 0) { warning ("Codepage for Chinese is not set."); } }@@ -69,7 +69,7 @@ void fit_bezier_curve_to_line ( Point2* points; int npoints; - if (npoints % 2 != 0) {+ if (lines_size % 2 != 0) { fprintf (stderr, "Odd number of coordinates in fit_bezier_curve_to_line."); return; }new file mode 100644Binary files /dev/null and b/resources/codepages.sqlite differnew file mode 100644Binary files /dev/null and b/resources/ucd.sqlite differ@@ -49,6 +49,7 @@ def libbirdfont(prefix, cc, cflags, ldflags, valac, valaflags, library, nonNull --pkg cairo \ --pkg libbirdxml \ --pkg libbirdgems \+ --pkg sqlite3 \ """) #copy c sources @@ -61,6 +62,7 @@ def libbirdfont(prefix, cc, cflags, ldflags, valac, valaflags, library, nonNull -c build/libbirdfont/*.c \ -fPIC \ -D 'GETTEXT_PACKAGE="birdfont"' \+ $(pkg-config --cflags sqlite) \ $(pkg-config --cflags """ + config.GEE + """) \ $(pkg-config --cflags gio-2.0) \ $(pkg-config --cflags cairo) \@@ -78,6 +80,7 @@ def libbirdfont(prefix, cc, cflags, ldflags, valac, valaflags, library, nonNull -shared \ """ + sonameparam + """ \ build/libbirdfont/*.o \+ $(pkg-config --libs sqlite) \ $(freetype-config --libs) \ $(pkg-config --libs """ + config.GEE + """) \ $(pkg-config --libs gio-2.0) \new file mode 100644@@ -0,0 +1,457 @@+/* sqlite3.vala+ *+ * Copyright (C) 2007 Jürg Billeter+ *+ * 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 2.1 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.++ * You should have received a copy of the GNU Lesser General Public+ * License along with this library; if not, write to the Free Software+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA+ *+ * Author:+ * Jürg Billeter <j@bitron.ch>+ */++[CCode (lower_case_cprefix = "sqlite3_", cheader_filename = "sqlite3.h")]+namespace Sqlite {+ /* Database Connection Handle */+ [Compact]+ [CCode (free_function = "sqlite3_close", cname = "sqlite3", cprefix = "sqlite3_")]+ public class Database {+ public int busy_timeout (int ms);+ public int changes ();+ [CCode (cname = "sqlite3_exec")]+ public int _exec (string sql, Callback? callback = null, [CCode (type = "char**")] out unowned string errmsg = null);+ [CCode (cname = "_sqlite3_exec")]+ public int exec (string sql, Callback? callback = null, out string errmsg = null) {+ unowned string sqlite_errmsg;+ var ec = this._exec (sql, callback, out sqlite_errmsg);+ if (&errmsg != null) {+ errmsg = sqlite_errmsg;+ }+ Sqlite.Memory.free ((void*) sqlite_errmsg);+ return ec;+ }+ public int extended_result_codes (int onoff);+ public int get_autocommit ();+ public void interrupt ();+ public int64 last_insert_rowid ();+ public int limit (Sqlite.Limit id, int new_val);+ public int total_changes ();+ public int complete (string sql);+ [CCode (cname = "sqlite3_get_table")]+ public int _get_table (string sql, [CCode (array_length = false)] out unowned string[] resultp, out int nrow, out int ncolumn, [CCode (type = "char**")] out unowned string? errmsg = null);+ private static void free_table ([CCode (array_length = false)] string[] result);+ [CCode (cname = "_sqlite3_get_table")]+ public int get_table (string sql, out string[] resultp, out int nrow, out int ncolumn, out string? errmsg = null) {+ unowned string? sqlite_errmsg;+ unowned string[] sqlite_resultp;++ var ec = this._get_table (sql, out sqlite_resultp, out nrow, out ncolumn, out sqlite_errmsg);++ resultp = new string[(nrow + 1) * ncolumn];+ for (var entry = 0 ; entry < resultp.length ; entry++ ) {+ resultp[entry] = sqlite_resultp[entry];+ }+ Sqlite.Database.free_table (sqlite_resultp);++ if (&errmsg != null) {+ errmsg = sqlite_errmsg;+ }+ Sqlite.Memory.free ((void*) sqlite_errmsg);+ return ec;+ }+ public static int open (string filename, out Database db);+ public static int open_v2 (string filename, out Database db, int flags = OPEN_READWRITE | OPEN_CREATE, string? zVfs = null);+ public int errcode ();+ public unowned string errmsg ();+ public unowned Sqlite.Statement next_stmt (Sqlite.Statement? current);+ public int prepare (string sql, int n_bytes, out Statement stmt, out unowned string tail = null);+ public int prepare_v2 (string sql, int n_bytes, out Statement stmt, out unowned string tail = null);+ public int set_authorizer (AuthorizeCallback? auth);+ [CCode (cname = "sqlite3_db_status")]+ public int status (Sqlite.DatabaseStatus op, out int pCurrent, out int pHighwater, int resetFlag = 0);+ public int table_column_metadata (string db_name, string table_name, string column_name, out string? data_type, out string? collation_sequence, out int? not_null, out int? primary_key, out int? auto_increment);+ public void trace (TraceCallback? xtrace);+ public void profile (ProfileCallback? xprofile);+ public void progress_handler (int n_opcodes, Sqlite.ProgressCallback? progress_handler);+ public void commit_hook (CommitCallback? commit_hook);+ public void rollback_hook (RollbackCallback? rollback_hook);+ public void update_hook (UpdateCallback? update_hook);+ public int create_function (string zFunctionName, int nArg, int eTextRep, void * user_data, UserFuncCallback? xFunc, UserFuncCallback? xStep, UserFuncFinishCallback? xFinal);+ public int create_function_v2 (string zFunctionName, int nArg, int eTextRep, void * user_data, UserFuncCallback? xFunc, UserFuncCallback? xStep, UserFuncFinishCallback? xFinal, GLib.DestroyNotify? destroy = null);+ public int create_collation (string zName, int eTextRep, [CCode (delegate_target_pos = 2.9, type = "int (*)(void *, int, const void *, int, const void *)")] CompareCallback xCompare);++ public int wal_autocheckpoint (int N);+ public int wal_checkpoint (string zDb);+ public void* wal_hook (WALHookCallback cb, string db_name, int page_count);+ }++ [CCode (instance_pos = 0)]+ public delegate int AuthorizeCallback (Sqlite.Action action, string? p1, string? p2, string db_name, string? responsible);+ [CCode (instance_pos = 0)]+ public delegate void TraceCallback (string message);+ [CCode (instance_pos = 0)]+ public delegate void ProfileCallback (string sql, uint64 time);+ public delegate int ProgressCallback ();+ public delegate int CommitCallback ();+ public delegate void RollbackCallback ();+ [CCode (has_target = false)]+ public delegate void UserFuncCallback (Sqlite.Context context, [CCode (array_length_pos = 1.1)] Sqlite.Value[] values);+ [CCode (has_target = false)]+ public delegate void UserFuncFinishCallback (Sqlite.Context context);+ [CCode (instance_pos = 0)]+ public delegate void UpdateCallback (Sqlite.Action action, string dbname, string table, int64 rowid);+ [CCode (instance_pos = 0)]+ public delegate int CompareCallback (int alen, void* a, int blen, void* b);+ [CCode (instance_pos = 0)]+ public delegate int WALHookCallback (Sqlite.Database db, string dbname, int pages);++ public unowned string? compileoption_get (int n);+ public int compileoption_used (string option_name);+ public static int complete (string sql);+ [CCode (sentinel = "")]+ public static int config (Sqlite.Config op, ...);+ public unowned string libversion ();+ public int libversion_number ();+ [PrintfFormat]+ public void log (int error_code, string format, ...);+ public unowned string sourceid ();+ public static int status (Sqlite.Status op, out int pCurrent, out int pHighwater, int resetFlag = 0);+ public static int threadsafe ();++ [CCode (cname = "SQLITE_VERSION")]+ public const string VERSION;+ [CCode (cname = "SQLITE_VERSION_NUMBER")]+ public const int VERSION_NUMBER;+ [CCode (cname = "SQLITE_SOURCE_ID")]+ public const string SOURCE_ID;++ /* Dynamically Typed Value Object */+ [Compact]+ [CCode (cname = "sqlite3_value")]+ public class Value {+ [CCode (cname = "sqlite3_value_blob")]+ public void* to_blob ();+ [CCode (cname = "sqlite3_value_bytes")]+ public int to_bytes ();+ [CCode (cname = "sqlite3_value_double")]+ public double to_double ();+ [CCode (cname = "sqlite3_value_int")]+ public int to_int ();+ [CCode (cname = "sqlite3_value_int64")]+ public int64 to_int64 ();+ [CCode (cname = "sqlite3_value_text")]+ public unowned string to_text ();+ [CCode (cname = "sqlite3_value_type")]+ public int to_type ();+ [CCode (cname = "sqlite3_value_numeric_type")]+ public int to_numeric_type ();+ }++ [CCode (cname = "sqlite3_callback", instance_pos = 0)]+ public delegate int Callback (int n_columns, [CCode (array_length = false)] string[] values, [CCode (array_length = false)] string[] column_names);++ [CCode (cname = "SQLITE_OK")]+ public const int OK;+ [CCode (cname = "SQLITE_ERROR")]+ public const int ERROR;+ [CCode (cname = "SQLITE_INTERNAL")]+ public const int INTERNAL;+ [CCode (cname = "SQLITE_PERM")]+ public const int PERM;+ [CCode (cname = "SQLITE_ABORT")]+ public const int ABORT;+ [CCode (cname = "SQLITE_BUSY")]+ public const int BUSY;+ [CCode (cname = "SQLITE_LOCKED")]+ public const int LOCKED;+ [CCode (cname = "SQLITE_NOMEM")]+ public const int NOMEM;+ [CCode (cname = "SQLITE_READONLY")]+ public const int READONLY;+ [CCode (cname = "SQLITE_INTERRUPT")]+ public const int INTERRUPT;+ [CCode (cname = "SQLITE_IOERR")]+ public const int IOERR;+ [CCode (cname = "SQLITE_CORRUPT")]+ public const int CORRUPT;+ [CCode (cname = "SQLITE_NOTFOUND")]+ public const int NOTFOUND;+ [CCode (cname = "SQLITE_FULL")]+ public const int FULL;+ [CCode (cname = "SQLITE_CANTOPEN")]+ public const int CANTOPEN;+ [CCode (cname = "SQLITE_PROTOCOL")]+ public const int PROTOCOL;+ [CCode (cname = "SQLITE_EMPTY")]+ public const int EMPTY;+ [CCode (cname = "SQLITE_SCHEMA")]+ public const int SCHEMA;+ [CCode (cname = "SQLITE_TOOBIG")]+ public const int TOOBIG;+ [CCode (cname = "SQLITE_CONSTRAINT")]+ public const int CONSTRAINT;+ [CCode (cname = "SQLITE_MISMATCH")]+ public const int MISMATCH;+ [CCode (cname = "SQLITE_MISUSE")]+ public const int MISUSE;+ [CCode (cname = "SQLITE_NOLFS")]+ public const int NOLFS;+ [CCode (cname = "SQLITE_AUTH")]+ public const int AUTH;+ [CCode (cname = "SQLITE_FORMAT")]+ public const int FORMAT;+ [CCode (cname = "SQLITE_RANGE")]+ public const int RANGE;+ [CCode (cname = "SQLITE_NOTADB")]+ public const int NOTADB;+ [CCode (cname = "SQLITE_ROW")]+ public const int ROW;+ [CCode (cname = "SQLITE_DONE")]+ public const int DONE;+ [CCode (cname = "SQLITE_OPEN_READONLY")]+ public const int OPEN_READONLY;+ [CCode (cname = "SQLITE_OPEN_READWRITE")]+ public const int OPEN_READWRITE;+ [CCode (cname = "SQLITE_OPEN_CREATE")]+ public const int OPEN_CREATE;+ [CCode (cname = "SQLITE_INTEGER")]+ public const int INTEGER;+ [CCode (cname = "SQLITE_FLOAT")]+ public const int FLOAT;+ [CCode (cname = "SQLITE_BLOB")]+ public const int BLOB;+ [CCode (cname = "SQLITE_NULL")]+ public const int NULL;+ [CCode (cname = "SQLITE3_TEXT")]+ public const int TEXT;+ [CCode (cname = "SQLITE_MUTEX_FAST")]+ public const int MUTEX_FAST;+ [CCode (cname = "SQLITE_MUTEX_RECURSIVE")]+ public const int MUTEX_RECURSIVE;+ [CCode (cname = "SQLITE_UTF8")]+ public const int UTF8;+ [CCode (cname = "SQLITE_UTF16LE")]+ public const int UTF16LE;+ [CCode (cname = "SQLITE_UTF16BE")]+ public const int UTF16BE;+ [CCode (cname = "SQLITE_UTF16")]+ public const int UTF16;+ [CCode (cname = "SQLITE_ANY")]+ public const int ANY;+ [CCode (cname = "SQLITE_UTF16_ALIGNED")]+ public const int UTF16_ALIGNED;++ [CCode (cname = "int", cprefix = "SQLITE_", has_type_id = false)]+ public enum Action {+ CREATE_INDEX,+ CREATE_TABLE,+ CREATE_TEMP_INDEX,+ CREATE_TEMP_TABLE,+ CREATE_TEMP_TRIGGER,+ CREATE_TEMP_VIEW,+ CREATE_TRIGGER,+ CREATE_VIEW,+ DELETE,+ DROP_INDEX,+ DROP_TABLE,+ DROP_TEMP_INDEX,+ DROP_TEMP_TABLE,+ DROP_TEMP_TRIGGER,+ DROP_TEMP_VIEW,+ DROP_TRIGGER,+ DROP_VIEW,+ INSERT,+ PRAGMA,+ READ,+ SELECT,+ TRANSACTION,+ UPDATE,+ ATTACH,+ DETACH,+ ALTER_TABLE,+ REINDEX,+ ANALYZE,+ CREATE_VTABLE,+ DROP_VTABLE,+ FUNCTION,+ SAVEPOINT,+ COPY+ }++ [CCode (cname = "int", cprefix = "SQLITE_CONFIG_", has_type_id = false)]+ public enum Config {+ SINGLETHREAD,+ MULTITHREAD,+ SERIALIZED,+ MALLOC,+ GETMALLOC,+ SCRATCH,+ PAGECACHE,+ HEAP,+ MEMSTATUS,+ MUTEX,+ GETMUTEX,+ LOOKASIDE,+ PCACHE,+ GETPCACHE,+ LOG,+ }++ [CCode (cname = "int", cprefix = "SQLITE_DBSTATUS_", has_type_id = false)]+ public enum DatabaseStatus {+ LOOKASIDE_USED+ }++ [CCode (cname = "int", cprefix = "SQLITE_LIMIT_", has_type_id = false)]+ public enum Limit {+ LENGTH,+ SQL_LENGTH,+ COLUMN,+ EXPR_DEPTH,+ COMPOUND_SELECT,+ VDBE_OP,+ FUNCTION_ARG,+ ATTACHED,+ LIKE_PATTERN_LENGTH,+ VARIABLE_NUMBER,+ TRIGGER_DEPTH+ }++ [CCode (cname = "int", cprefix = "SQLITE_STMTSTATUS_", has_type_id = false)]+ public enum StatementStatus {+ FULLSCAN_STEP,+ SORT+ }++ [CCode (cname = "int", cprefix = "SQLITE_STATUS_", has_type_id = false)]+ public enum Status {+ MEMORY_USED,+ PAGECACHE_USED,+ PAGECACHE_OVERFLOW,+ SCRATCH_USED,+ SCRATCH_OVERFLOW,+ MALLOC_SIZE,+ PARSER_STACK,+ PAGECACHE_SIZE,+ SCRATCH_SIZE+ }++ /* SQL Statement Object */+ [Compact]+ [CCode (free_function = "sqlite3_finalize", cname = "sqlite3_stmt", cprefix = "sqlite3_")]+ public class Statement {+ public int bind_parameter_count ();+ public int bind_parameter_index (string name);+ public unowned string bind_parameter_name (int index);+ public int clear_bindings ();+ public int column_count ();+ public int data_count ();+ public unowned Database db_handle ();+ public int reset ();+ [CCode (cname = "sqlite3_stmt_status")]+ public int status (Sqlite.StatementStatus op, int resetFlg = 0);+ public int step ();+ public int bind_blob (int index, void* value, int n, GLib.DestroyNotify? destroy_notify = null);+ public int bind_double (int index, double value);+ public int bind_int (int index, int value);+ public int bind_int64 (int index, int64 value);+ public int bind_null (int index);+ [CCode (cname = "sqlite3_bind_text")]+ public int _bind_text (int index, string value, int n = -1, GLib.DestroyNotify? destroy_notify = null);+ public int bind_text (int index, owned string value, int n = -1, GLib.DestroyNotify destroy_notify = GLib.g_free);+ public int bind_value (int index, Value value);+ public int bind_zeroblob (int index, int n);+ public void* column_blob (int col);+ public int column_bytes (int col);+ public double column_double (int col);+ public int column_int (int col);+ public int64 column_int64 (int col);+ public unowned string column_text (int col);+ public int column_type (int col);+ public unowned Value column_value (int col);+ public unowned string column_name (int index);+ public unowned string column_database_name (int col);+ public unowned string column_table_name (int col);+ public unowned string column_origin_name (int col);+ public unowned string sql ();+ }++ namespace Memory {+ [CCode (cname = "sqlite3_malloc")]+ public static void* malloc (int n_bytes);+ [CCode (cname = "sqlite3_realloc")]+ public static void* realloc (void* mem, int n_bytes);+ [CCode (cname = "sqlite3_free")]+ public static void free (void* mem);+ [CCode (cname = "sqlite3_release_memory")]+ public static int release (int bytes);+ [CCode (cname = "sqlite3_memory_used")]+ public static int64 used ();+ [CCode (cname = "sqlite3_memory_highwater")]+ public static int64 highwater (int reset = 0);+ [Deprecated (since = "3.7.2", replacement = "Sqlite.Memory.soft_heap_limit64")]+ [CCode (cname = "sqlite3_soft_heap_limit")]+ public static void soft_heap_limit (int limit);+ [CCode (cname = "sqlite3_soft_heap_limit64")]+ public static int64 soft_heap_limit64 (int64 limit = -1);+ }++ [Compact]+ [CCode (cname = "sqlite3_mutex")]+ public class Mutex {+ [CCode (cname = "sqlite3_mutex_alloc")]+ public Mutex (int mutex_type = MUTEX_RECURSIVE);+ public void enter ();+ public int held ();+ public int notheld ();+ public int @try ();+ public void leave ();+ }++ [Compact, CCode (cname = "sqlite3_context", cprefix = "sqlite3_")]+ public class Context {+ public void result_blob (owned uint8[] data, GLib.DestroyNotify? destroy_notify = GLib.g_free);+ public void result_double (double value);+ public void result_error (string value, int error_code);+ public void result_error_toobig ();+ public void result_error_nomem ();+ public void result_error_code (int error_code);+ public void result_int (int value);+ public void result_int64 (int64 value);+ public void result_null ();+ public void result_text (owned string value, int length = -1, GLib.DestroyNotify? destroy_notify = GLib.g_free);+ public void result_value (Sqlite.Value value);+ public void result_zeroblob (int n);++ [CCode (simple_generics = true)]+ public unowned T user_data<T> ();+ [CCode (simple_generics = true)]+ public void set_auxdata<T> (int N, owned T data);+ [CCode (simple_generics = true)]+ public unowned T get_auxdata<T> (int N);+ [CCode (cname = "sqlite3_context_db_handle")]+ public unowned Database db_handle ();+ [CCode (cname = "sqlite3_aggregate_context")]+ public void * aggregate (int n_bytes);+ }++ [Compact, CCode (cname = "sqlite3_backup", free_function = "sqlite3_backup_finish", cprefix = "sqlite3_backup_")]+ public class Backup {+ [CCode (cname = "sqlite3_backup_init")]+ public Backup (Database dest, string dest_name, Database source, string source_name);+ public int step (int nPage);+ public int remaining ();+ public int pagecount ();+ }+}+