summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Jeanmougin <marc@jeanmougin.fr>2017-02-05 19:24:08 +0000
committerMarc Jeanmougin <marcjeanmougin@free.fr>2017-02-05 19:24:08 +0000
commit6947ff531840b67cafd4c7931e6b7bb9ceaf7d70 (patch)
treee648223cc925b2fbe62b7063262eed68f3463541
parentadd missing header (diff)
downloadinkscape-6947ff531840b67cafd4c7931e6b7bb9ceaf7d70.tar.gz
inkscape-6947ff531840b67cafd4c7931e6b7bb9ceaf7d70.zip
forward-port from 0.92.x the line height conversion from <.92 to >=.92
Code written by su_v in python as an extension, ported to c++ by Mc, some fixes added by bryce. http://bazaar.launchpad.net/~inkscape.dev/inkscape/0.92.x/revision/15338 http://bazaar.launchpad.net/~inkscape.dev/inkscape/0.92.x/revision/15339 http://bazaar.launchpad.net/~inkscape.dev/inkscape/0.92.x/revision/15350 http://bazaar.launchpad.net/~inkscape.dev/inkscape/0.92.x/revision/15351 Option to disable it is called --no-convert-text-baseline-spacing The terminology "convert" is chosen as a jargon word to be used for all such legacy file conversions. The "--no-XXX" naming style is adopted from the convention used by other software such as GIMP. (bzr r15481)
-rw-r--r--inkscape.pod10
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/document.cpp14
-rw-r--r--src/document.h18
-rw-r--r--src/file-update.cpp173
-rw-r--r--src/file.h3
-rw-r--r--src/main.cpp9
7 files changed, 224 insertions, 4 deletions
diff --git a/inkscape.pod b/inkscape.pod
index 451e690f8..a8369f28a 100644
--- a/inkscape.pod
+++ b/inkscape.pod
@@ -63,6 +63,7 @@ options:
-z, --without-gui
--vacuum-defs
+ --no-convert-text-baseline-spacing
--g-fatal-warnings
@@ -342,6 +343,15 @@ Remove all unused items from the <lt>defs<gt> section of the SVG file. If this
option is invoked in conjunction with --export-plain-svg, only the exported file
will be affected. If it is used alone, the specified file will be modified in place.
+=item B<--no-convert-text-baseline-spacing>
+
+Do not automatically fix text baselines in legacy (pre-0.92) files on
+opening. Inkscape 0.92 adopts the CSS standard definition for the
+'line-height' property, which differs from past versions. By default,
+the line height values in files created prior to Inkscape 0.92 will be
+adjusted on loading to preserve the intended text layout. This command
+line option will skip that adjustment.
+
=item B<-z>, B<--without-gui>
Do not open the GUI (on Unix, do not use X server); only process the files from console.
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 47aa02ef1..bb45ffa4a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -200,6 +200,7 @@ set(inkscape_SRC
event-log.cpp
extract-uri.cpp
file.cpp
+ file-update.cpp
filter-chemistry.cpp
filter-enums.cpp
gc-anchored.cpp
diff --git a/src/document.cpp b/src/document.cpp
index 57208582a..b69508751 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -49,6 +49,7 @@
#include "display/drawing.h"
#include "document-private.h"
#include "document-undo.h"
+#include "file.h"
#include "id-clash.h"
#include "inkscape.h"
#include "inkscape-version.h"
@@ -71,7 +72,7 @@ using Inkscape::Util::unit_table;
// since we want it to happen when there are no more updates.
#define SP_DOCUMENT_REROUTING_PRIORITY (G_PRIORITY_HIGH_IDLE - 1)
-
+bool sp_no_convert_text_baseline_spacing = false;
static gint sp_document_idle_handler(gpointer data);
static gint sp_document_rerouting_handler(gpointer data);
@@ -452,6 +453,17 @@ SPDocument *SPDocument::createDoc(Inkscape::XML::Document *rdoc,
));
document->oldSignalsConnected = true;
+ /** Fix baseline spacing (pre-92 files) **/
+ if ( (!sp_no_convert_text_baseline_spacing)
+ && sp_version_inside_range( document->root->version.inkscape, 0, 1, 0, 92 ) ) {
+ sp_file_convert_text_baseline_spacing(document);
+ }
+
+ /** Fix font names in legacy documents (pre-92 files) **/
+ if ( sp_version_inside_range( document->root->version.inkscape, 0, 1, 0, 92 ) ) {
+ sp_file_convert_font_name(document);
+ }
+
return document;
}
diff --git a/src/document.h b/src/document.h
index 49bde1897..142eb5000 100644
--- a/src/document.h
+++ b/src/document.h
@@ -30,6 +30,24 @@
#include <set>
#include <deque>
+// This variable is introduced with 0.92.1
+// with the introduction of automatic fix
+// for files detected to have been created
+// with previous versions to have a similar
+// look in 0.92+.
+extern bool sp_no_convert_text_baseline_spacing;
+
+
+
+// This variable is introduced with 0.92.1
+// with the introduction of automatic fix
+// for files detected to have been created
+// with previous versions to have a similar
+// look in 0.92+.
+extern bool sp_do_not_fix_pre_92;
+
+
+
namespace Avoid {
class Router;
}
diff --git a/src/file-update.cpp b/src/file-update.cpp
new file mode 100644
index 000000000..40a8bc834
--- /dev/null
+++ b/src/file-update.cpp
@@ -0,0 +1,173 @@
+/**
+ * @file-update
+ * Operations to bump files from the pre-0.92 era into the 0.92+ era
+ * (90dpi vs 96dpi, line height problems, and related bugs)
+ */
+/* Authors:
+ * Tavmjong Bah
+ * Marc Jeanmougin
+ * su_v
+ */
+#include "file.h"
+#include "sp-root.h"
+#include "sp-text.h"
+#include "sp-tspan.h"
+#include "sp-flowdiv.h"
+#include "sp-flowtext.h"
+#include "sp-object.h"
+#include "sp-item.h"
+#include "style.h"
+#include "document.h"
+#include <string>
+#include "text-editing.h"
+
+using namespace std;
+
+bool is_line(SPObject *i)
+{
+ if (!(i->getAttribute("sodipodi:role")))
+ return false;
+ return !strcmp(i->getAttribute("sodipodi:role"), "line");
+}
+
+
+void fix_blank_line(SPObject *o)
+{
+ if (SP_IS_TEXT(o))
+ ((SPText *)o)->rebuildLayout();
+ else if (SP_IS_FLOWTEXT(o))
+ ((SPFlowtext *)o)->rebuildLayout();
+
+ SPIFontSize fontsize = o->style->font_size;
+ SPILengthOrNormal lineheight = o->style->line_height;
+ vector<SPObject *> cl = o->childList(false);
+ bool beginning = true;
+ for (vector<SPObject *>::const_iterator ci = cl.begin(); ci != cl.end(); ++ci) {
+ SPObject *i = *ci;
+ if ((SP_IS_TSPAN(i) && is_line(i)) || SP_IS_FLOWPARA(i) || SP_IS_FLOWDIV(i)) {
+ if (sp_text_get_length((SPItem *)i) <= 1) { // empty line
+ Inkscape::Text::Layout::iterator pos = te_get_layout((SPItem*)(o))->charIndexToIterator(
+ ((SP_IS_FLOWPARA(i) || SP_IS_FLOWDIV(i))?0:((ci==cl.begin())?0:1)) + sp_text_get_length_upto(o,i) );
+ sp_te_insert((SPItem *)o, pos, "\u00a0"); //"\u00a0"
+ gchar *l = g_strdup_printf("%f", lineheight.value);
+ gchar *f = g_strdup_printf("%f", fontsize.value);
+ i->style->line_height.readIfUnset(l);
+ if (!beginning)
+ i->style->font_size.read(f);
+ else
+ i->style->font_size.readIfUnset(f);
+ g_free(l);
+ g_free(f);
+ } else {
+ beginning = false;
+ fontsize = i->style->font_size;
+ lineheight = o->style->line_height;
+ }
+ }
+ }
+}
+
+void fix_line_spacing(SPObject *o)
+{
+ SPILengthOrNormal lineheight = o->style->line_height;
+ bool inner = false;
+ vector<SPObject *> cl = o->childList(false);
+ for (vector<SPObject *>::const_iterator ci = cl.begin(); ci != cl.end(); ++ci) {
+ SPObject *i = *ci;
+ if ((SP_IS_TSPAN(i) && is_line(i)) || SP_IS_FLOWPARA(i) || SP_IS_FLOWDIV(i)) {
+ // if no line-height attribute, set it
+ gchar *l = g_strdup_printf("%f", lineheight.value);
+ i->style->line_height.readIfUnset(l);
+ g_free(l);
+ }
+ inner = true;
+ }
+ if (inner) {
+ if (SP_IS_TEXT(o)) {
+ o->style->line_height.read("0.00%");
+ } else {
+ o->style->line_height.read("0.01%");
+ }
+ }
+}
+
+void fix_font_name(SPObject *o)
+{
+ vector<SPObject *> cl = o->childList(false);
+ for (vector<SPObject *>::const_iterator ci = cl.begin(); ci != cl.end(); ++ci)
+ fix_font_name(*ci);
+ string prev = o->style->font_family.value ? o->style->font_family.value : o->style->font_family.value_default;
+ if (prev == "Sans")
+ o->style->font_family.read("sans-serif");
+ else if (prev == "Serif")
+ o->style->font_family.read("serif");
+ else if (prev == "Monospace")
+ o->style->font_family.read("monospace");
+}
+
+
+void fix_font_size(SPObject *o)
+{
+ SPIFontSize fontsize = o->style->font_size;
+ if (!fontsize.set)
+ return;
+ bool inner = false;
+ vector<SPObject *> cl = o->childList(false);
+ for (vector<SPObject *>::const_iterator ci = cl.begin(); ci != cl.end(); ++ci) {
+ SPObject *i = *ci;
+ fix_font_size(i);
+ if ((SP_IS_TSPAN(i) && is_line(i)) || SP_IS_FLOWPARA(i) || SP_IS_FLOWDIV(i)) {
+ inner = true;
+ gchar *s = g_strdup_printf("%f", fontsize.value);
+ if (fontsize.set)
+ i->style->font_size.readIfUnset(s);
+ g_free(s);
+ }
+ }
+ if (inner && (SP_IS_TEXT(o) || SP_IS_FLOWTEXT(o)))
+ o->style->font_size.clear();
+}
+
+
+
+// helper function
+void sp_file_text_run_recursive(void (*f)(SPObject *), SPObject *o)
+{
+ if (SP_IS_TEXT(o) || SP_IS_FLOWTEXT(o))
+ f(o);
+ else {
+ vector<SPObject *> cl = o->childList(false);
+ for (vector<SPObject *>::const_iterator ci = cl.begin(); ci != cl.end(); ++ci)
+ sp_file_text_run_recursive(f, *ci);
+ }
+}
+
+void fix_update(SPObject *o) {
+ o->style->write();
+ o->updateRepr();
+}
+
+void sp_file_convert_text_baseline_spacing(SPDocument *doc)
+{
+ sp_file_text_run_recursive(fix_blank_line, doc->getRoot());
+ sp_file_text_run_recursive(fix_line_spacing, doc->getRoot());
+ sp_file_text_run_recursive(fix_font_size, doc->getRoot());
+ sp_file_text_run_recursive(fix_update, doc->getRoot());
+}
+
+void sp_file_convert_font_name(SPDocument *doc)
+{
+ sp_file_text_run_recursive(fix_font_name, doc->getRoot());
+ sp_file_text_run_recursive(fix_update, doc->getRoot());
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/file.h b/src/file.h
index 4ffbc8ec0..2fc4ea910 100644
--- a/src/file.h
+++ b/src/file.h
@@ -203,7 +203,8 @@ void sp_file_print (Gtk::Window& parentWindow);
* clean unused defs out of file
*/
void sp_file_vacuum (SPDocument *doc);
-
+void sp_file_convert_text_baseline_spacing(SPDocument *doc);
+void sp_file_convert_font_name(SPDocument *doc);
#endif // SEEN_SP_FILE_H
diff --git a/src/main.cpp b/src/main.cpp
index 605c1207e..47cf43456 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -166,6 +166,7 @@ enum {
SP_ARG_SHELL,
SP_ARG_VERSION,
SP_ARG_VACUUM_DEFS,
+ SP_ARG_NO_CONVERT_TEXT_BASELINE_SPACING,
#ifdef WITH_DBUS
SP_ARG_DBUS_LISTEN,
SP_ARG_DBUS_NAME,
@@ -235,7 +236,6 @@ static gchar *sp_xverbs_yaml_utf8 = NULL;
static gchar *sp_xverbs_yaml = NULL;
#endif // WITH_YAML
-
/**
* Reset variables to default values.
*/
@@ -274,6 +274,7 @@ static void resetCommandlineGlobals() {
sp_query_all = FALSE;
sp_query_id = NULL;
sp_vacuum_defs = FALSE;
+ sp_no_convert_text_baseline_spacing = FALSE;
#ifdef WITH_DBUS
sp_dbus_listen = FALSE;
sp_dbus_name = NULL;
@@ -525,6 +526,11 @@ struct poptOption options[] = {
N_("Start Inkscape in interactive shell mode."),
NULL},
+ {"no-convert-text-baseline-spacing", 0,
+ POPT_ARG_NONE, &sp_no_convert_text_baseline_spacing, SP_ARG_NO_CONVERT_TEXT_BASELINE_SPACING,
+ N_("Do not fix legacy (pre-0.92) files' text baseline spacing on opening."),
+ NULL},
+
POPT_AUTOHELP POPT_TABLEEND
};
@@ -1636,7 +1642,6 @@ static int sp_do_export_png(SPDocument *doc)
return retcode;
}
-
/**
* Perform a PDF/PS/EPS export
*