View Issue Details

IDProjectCategoryView StatusLast Update
0011374ScribusTypographypublic2017-10-28 10:09
Reportercezaryece Assigned To 
PrioritynormalSeverityminorReproducibilityN/A
Status newResolutionopen 
Product Version1.5.0svn 
Target VersionFixed in Version 
Summary0011374: [PATCH] typographic spaces
DescriptionTypographic spaces are additional spaces before or after some chars set in preferences.
Specially usable in French.
In Preferences and Doc Preferences user can define chars and value of additional space he want provided before/after of them. See attached pictures (sorry for Polish GUI).
Tagspatch, spacing
PatchYes

Activities

cezaryece

2013-01-15 15:04

developer  

addSpaces2.jpg (140,129 bytes)
addSpaces2.jpg (140,129 bytes)

JLuc

2013-01-15 15:58

developer   ~0029706

I've looked at the typography screencaptures. By chance the polish GUI only deals with allready english or french existing labels !

This new feature enables to add automaticaly some white space after or before ponctuation marks. Isn't ? I think Scribus can really do better with automatic typographic enhancements, and your patch tackles this issue.

I have not tested the patch but i have some questions :

Is it 50% or 7O% of "normal space" width ? of "n space" ? of "m space" ?
or of "normal glyph width" ?
Is it inserting a new space glyph, or is it just increasing width of actual
glyph, as a margin before and after (tracking distance) ?

I guess its a non breaking space.
But before a (, the space should be breakable (but not the space after).
and after a ), space should be breakable too, (but not the space before)
so as a consequence, it's necessary to specify whether space is breakable or not !

Beside : does it replaces or delete previously existing space if one is allready there ?
It should.

Is the feature launched automaticaly or is it called through a menu option ?
I think launching through menu might be better, because it should be possible to correct the results, and i dont see how it can be possible when its automatic.

When launched through menu option, user should be able to specify
"whole text", "linked text frame chaine", "selected frame" or "selection"
(as shortwords does).

It would be nice to be able to specify not only single glyph to be managed,
but a list of glyphs or whort words sharing the same typographic requisitess.
Example : !,?,;,: as is done with shortwords plugins. A list of glyph ... or words ! or regexp ?

This patch somehow competes a bit with shortwords isn't ?
I dont like the idea of having 2 separate plugins or features both to manage spaces and typography.

Shorwords does not have a nice UI : only a text file to set the parameters,
and shortwords only insert allways same non breaking space,

but shortwords accept lists of glyphs (it is quiker to specify lots of patterns)
and shorwords manages one different list for each langage.

cezaryece

2013-01-16 06:22

developer   ~0029707

Values means % of normal space for current font and are added to glyph.
Using should be smart as it is only glyph width modification and breaking rules does not apply here and does not touch any spaces or other chars near selected one.
Feature is a document preference and touch whole text in document for now.
There is possibility to provide string of chars with same values to add.

IMHO it is nothing related to ShortWords, as it does not providing any addition only change some normal spaces into non-breaking ones.

Feature was requested by French users as they always want to have a space before question marks (and other similar chars), but for example in Polish some very small distance is here also expected (by old typography school at least, but as I know only one very old and not used already application had such feature).

I know that it may be better to have full manual control of each glyph in text or separate values for languages. But IMHO it will slow down text layouting and should be provided when it will be optimised. So for now I propose it as document property.

cezaryece

2013-01-16 06:27

developer   ~0029708

And one small notice for team - this report is only notice that such feature is ready and I don`t force merging of it into trunk if team is not sure about it. It is scratch for future use.
But it will be merged into ScribusECE soon if someone want to test and use it (I want).

cezaryece

2013-01-16 09:37

developer  

typoSpace.jpg (95,084 bytes)
typoSpace.jpg (95,084 bytes)

cezaryece

2013-01-16 09:37

developer  

typographicSpaces.patch (35,218 bytes)
diff --git a/Scribus/scribus/pageitem.cpp b/Scribus/scribus/pageitem.cpp
index 17ce6a4..4edad69 100644
--- a/Scribus/scribus/pageitem.cpp
+++ b/Scribus/scribus/pageitem.cpp
@@ -2342,7 +2342,7 @@ void PageItem::SetQColor(QColor *tmp, QString farbe, double shad)
     sets xadvance to the advance width without kerning. If more than one glyph
     is generated, kerning is included in all but the last xadvance.
 */
-double PageItem::layoutGlyphs(const CharStyle& style, const QString& chars, GlyphLayout& layout)
+double PageItem::layoutGlyphs(const CharStyle& style, const QString& chars, GlyphLayout& layout, int addBefore, int addAfter)
 {
 	double retval = 0.0;
 	const ScFace font = style.font();
@@ -2366,8 +2366,15 @@ double PageItem::layoutGlyphs(const CharStyle& style, const QString& chars, Glyp
 		layout.glyph = font.char2CMap(chars[0].unicode());
 	}
 	double tracking = 0.0;
+	double before = 0.0;
+	double after = 0.0;
+	if (addBefore != 0)
+		before = font.glyphWidth(font.char2CMap(' '), style.fontSize() / 10) * addBefore/100.0;
+	if (addAfter != 0)
+		after = font.glyphWidth(font.char2CMap(' '), style.fontSize() / 10) * addAfter/100.0;
+	
 	if ( (style.effects() & ScStyle_StartOfLine) == 0)
-		tracking = style.fontSize() * style.tracking() / 10000.0;
+		tracking = style.fontSize() * style.tracking() / 10000.0 + before;
 
 	layout.xoffset = tracking;
 	layout.yoffset = 0;
@@ -2431,7 +2438,7 @@ double PageItem::layoutGlyphs(const CharStyle& style, const QString& chars, Glyp
 		layout.yadvance = font.glyphBBox(layout.glyph, style.fontSize() / 10).ascent * layout.scaleV;
 	}
 	if (layout.xadvance > 0)
-		layout.xadvance += tracking;
+		layout.xadvance += tracking + after;
 
 	if (chars.length() > 1) {
 		layout.grow();
diff --git a/Scribus/scribus/pageitem.h b/Scribus/scribus/pageitem.h
index 75a4fc5..1be4ac5 100644
--- a/Scribus/scribus/pageitem.h
+++ b/Scribus/scribus/pageitem.h
@@ -387,7 +387,7 @@ public: // Start public functions
 	/// Return current text properties (current char + paragraph properties)
 	void currentTextProps(ParagraphStyle& parStyle) const;
 	// deprecated:
-	double layoutGlyphs(const CharStyle& style, const QString& chars, GlyphLayout& layout);
+	double layoutGlyphs(const CharStyle& style, const QString& chars, GlyphLayout& layout, int addBefore =0, int addAfter = 0);
 	void SetQColor(QColor *tmp, QString farbe, double shad);
 	void drawGlyphs(ScPainter *p, const CharStyle& style, GlyphLayout& glyphs );
 	void DrawPolyL(QPainter *p, QPolygon pts);
diff --git a/Scribus/scribus/pageitem_pathtext.cpp b/Scribus/scribus/pageitem_pathtext.cpp
index 47ceef9..1b3bac9 100644
--- a/Scribus/scribus/pageitem_pathtext.cpp
+++ b/Scribus/scribus/pageitem_pathtext.cpp
@@ -214,7 +214,23 @@ void PageItem_PathText::DrawObj_Item(ScPainter *p, QRectF cullingArea)
 		if (a < itemRenderText.length()-1)
 			chstr += itemRenderText.text(a+1, 1);
 		hl->glyph.yadvance = 0;
-		layoutGlyphs(itemRenderText.charStyle(a), chstr, hl->glyph);
+		int before =0, after =0;
+		if (m_Doc->checkAddSpace(chstr[0], before, after))
+		{
+			if ((before != 0) && (a > firstInFrame()))
+			{
+				QChar ch = itemText.text(a-1);
+				if ((ch == chstr[0]) || ch.isSpace())
+					before = 0;
+			}
+			if ((after != 0) && (a < itemText.length()-1))
+			{
+				QChar ch = itemText.text(a+1);
+				if ((ch == chstr[0]) || ch.isSpace())
+					after = 0;
+			}
+		}
+		layoutGlyphs(itemRenderText.charStyle(a), chstr, hl->glyph), before, after;
 		hl->glyph.shrink();
 		if (hl->hasObject(m_Doc))
 			totalTextLen += (hl->getItem(m_Doc)->width() + hl->getItem(m_Doc)->lineWidth()) * hl->glyph.scaleH;
@@ -266,7 +282,23 @@ void PageItem_PathText::DrawObj_Item(ScPainter *p, QRectF cullingArea)
 		if (a < itemRenderText.length()-1)
 			chstr += itemRenderText.text(a+1, 1);
 		hl->glyph.yadvance = 0;
-		layoutGlyphs(itemRenderText.charStyle(a), chstr, hl->glyph);
+		int before =0, after =0;
+		if (m_Doc->checkAddSpace(chstr[0], before, after))
+		{
+			if ((before != 0) && (a > firstInFrame()))
+			{
+				QChar ch = itemText.text(a-1);
+				if ((ch == chstr[0]) || ch.isSpace())
+					before = 0;
+			}
+			if ((after != 0) && (a < itemText.length()-1))
+			{
+				QChar ch = itemText.text(a+1);
+				if ((ch == chstr[0]) || ch.isSpace())
+					after = 0;
+			}
+		}
+		layoutGlyphs(itemRenderText.charStyle(a), chstr, hl->glyph, before, after);
 		hl->glyph.shrink();                                                           // HACK
 		if (hl->hasObject(m_Doc))
 			dx = (hl->getItem(m_Doc)->width() + hl->getItem(m_Doc)->lineWidth()) * hl->glyph.scaleH / 2.0;
diff --git a/Scribus/scribus/pageitem_textframe.cpp b/Scribus/scribus/pageitem_textframe.cpp
index 7440a94..508aa67 100644
--- a/Scribus/scribus/pageitem_textframe.cpp
+++ b/Scribus/scribus/pageitem_textframe.cpp
@@ -1783,10 +1783,26 @@ void PageItem_TextFrame::layout()
 			else
 			{
 				kernVal = 0; // chs * charStyle.tracking() / 10000.0;
-				itemText.item(a)->setEffects(itemText.item(a)->effects() & ~ScStyle_StartOfLine);
+				hl->setEffects(hl->effects() & ~ScStyle_StartOfLine);
 			}
 			hl->glyph.yadvance = 0;
-			layoutGlyphs(*hl, chstr, hl->glyph);
+			int before =0, after =0;
+			if (m_Doc->checkAddSpace(chstr[0], before, after))
+			{
+				if ((before != 0) && (a > firstInFrame()))
+				{
+					QChar ch = itemText.text(a-1);
+					if ((ch == chstr[0]) || ch.isSpace())
+						before = 0;
+				}
+				if ((after != 0) && (a < itemText.length()-1))
+				{
+					QChar ch = itemText.text(a+1);
+					if ((ch == chstr[0]) || ch.isSpace())
+						after = 0;
+				}
+			}
+			layoutGlyphs(*hl, chstr, hl->glyph, before, after);
 			
 			// find out width, ascent and descent of char
 			if (HasObject)
diff --git a/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp b/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
index 960b9f3..73c0db3 100644
--- a/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
+++ b/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
@@ -1325,6 +1325,13 @@ bool Scribus150Format::loadFile(const QString & fileName, const FileFormat & /*
 				m_Doc->setCurCheckProfile(attrs.valueAsString("currentProfile"));
 			}
 		}
+		if (tagName == "AddSpace4Chars")
+		{
+			QString chars = attrs.valueAsString("Chars");
+			int before = attrs.valueAsInt("Before");
+			int after = attrs.valueAsInt("After");
+			m_Doc->typographicPrefs().addSpaceMap.insert(chars, qMakePair(before, after));
+		}
 		if (tagName == "CheckProfile")
 		{
 			success = readCheckProfile(m_Doc, attrs);
diff --git a/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp b/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
index 22ceea9..77e4edb 100644
--- a/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
+++ b/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
@@ -374,6 +374,13 @@ bool Scribus150Format::saveFile(const QString & fileName, const FileFormat & /*
 	docu.writeAttribute("calligrapicPenAngle", m_Doc->itemToolPrefs().calligrapicPenAngle);
 	docu.writeAttribute("calligrapicPenWidth", m_Doc->itemToolPrefs().calligrapicPenWidth);
 	docu.writeAttribute("calligrapicPenStyle", m_Doc->itemToolPrefs().calligrapicPenStyle);
+	foreach(QString chars, m_Doc->typographicPrefs().addSpaceMap.keys())
+	{
+		docu.writeEmptyElement("AddSpace4Chars");
+		docu.writeAttribute("Chars",chars);
+		docu.writeAttribute("Before",m_Doc->typographicPrefs().addSpaceMap.value(chars).first);
+		docu.writeAttribute("After",m_Doc->typographicPrefs().addSpaceMap.value(chars).second);
+	}
 
 	writeCheckerProfiles(docu);
 	writeJavascripts(docu);
diff --git a/Scribus/scribus/prefsmanager.cpp b/Scribus/scribus/prefsmanager.cpp
index f5e8855..0c4b6df 100644
--- a/Scribus/scribus/prefsmanager.cpp
+++ b/Scribus/scribus/prefsmanager.cpp
@@ -200,6 +200,7 @@ void PrefsManager::initDefaults()
 	appPrefs.typoPrefs.valueUnderlineWidth = -1;
 	appPrefs.typoPrefs.valueStrikeThruPos = -1;
 	appPrefs.typoPrefs.valueStrikeThruWidth = -1;
+//	appPrefs.typoPrefs.addSpaceMap.insert("?!)",qMakePair(80,0));
 	appPrefs.guidesPrefs.valueBaselineGrid = 14.4;
 	appPrefs.guidesPrefs.offsetBaselineGrid = 0.0;
 	appPrefs.uiPrefs.style = "";
@@ -1468,6 +1469,17 @@ bool PrefsManager::WritePref(QString ho)
 		dcTypography.setAttribute("StrikeThruWidth", appPrefs.typoPrefs.valueStrikeThruWidth);
 	else
 		dcTypography.setAttribute("StrikeThruWidth", appPrefs.typoPrefs.valueStrikeThruWidth / 10.0);
+	if (!appPrefs.typoPrefs.addSpaceMap.isEmpty())
+	{
+		for (QMap<QString, QPair<int, int> >::Iterator asIt = appPrefs.typoPrefs.addSpaceMap.begin(); asIt != appPrefs.typoPrefs.addSpaceMap.end(); ++asIt)
+		{
+			QDomElement aselm = docu.createElement("AddSpace4Chars");
+			aselm.setAttribute("Chars", asIt.key());
+			aselm.setAttribute("Before", asIt.value().first);
+			aselm.setAttribute("After", asIt.value().second);
+			dcTypography.appendChild(aselm);
+		}
+	}
 	elem.appendChild(dcTypography);
 
 	QDomElement dcItemTools=docu.createElement("ItemTools");
@@ -2069,6 +2081,20 @@ bool PrefsManager::ReadPref(QString ho)
 				appPrefs.typoPrefs.valueStrikeThruWidth = qRound(stw * 10);
 			else
 				appPrefs.typoPrefs.valueStrikeThruWidth = -1;
+			appPrefs.typoPrefs.addSpaceMap.clear();
+			QDomNode aselm = dc.firstChild();
+			while(!aselm.isNull())
+			{
+				QDomElement asElem = aselm.toElement();
+				if (asElem.tagName()=="AddSpace4Chars")
+				{
+					QString chars = asElem.attribute("Chars");
+					int before = asElem.attribute("Before").toInt();
+					int after = asElem.attribute("After").toInt();
+					appPrefs.typoPrefs.addSpaceMap.insert(chars, qMakePair(before, after));
+				}
+				aselm = aselm.nextSibling();
+			}
 		}
 
 
diff --git a/Scribus/scribus/prefsstructs.h b/Scribus/scribus/prefsstructs.h
index cc58c93..77687b2 100644
--- a/Scribus/scribus/prefsstructs.h
+++ b/Scribus/scribus/prefsstructs.h
@@ -72,6 +72,7 @@ struct TypoPrefs
 	int valueUnderlineWidth; //! Underline width
 	int valueStrikeThruPos; //! Strike-through displacement
 	int valueStrikeThruWidth; //! Strike-through line width
+	QMap<QString, QPair<int, int> > addSpaceMap; //! Additional space before chars
 
 	inline bool operator==(const TypoPrefs &other)
 	{
diff --git a/Scribus/scribus/scribusdoc.cpp b/Scribus/scribus/scribusdoc.cpp
index 641e1d0..7350b92 100644
--- a/Scribus/scribus/scribusdoc.cpp
+++ b/Scribus/scribus/scribusdoc.cpp
@@ -18634,3 +18634,19 @@ void ScribusDoc::ResetFormFields()
 	changed();
 	regionsChanged()->update(QRect());
 }
+
+bool ScribusDoc::checkAddSpace(QChar ch, int &before, int &after)
+{
+	bool addSpace = false;
+	foreach (QString str, typographicPrefs().addSpaceMap.keys())
+	{
+		if (str.contains(ch))
+		{
+			before = typographicPrefs().addSpaceMap.value(str).first;
+			after = typographicPrefs().addSpaceMap.value(str).second;
+			addSpace = true;
+			break;
+		}
+	}
+	return addSpace;
+}
diff --git a/Scribus/scribus/scribusdoc.h b/Scribus/scribus/scribusdoc.h
index 7bf4b8c..14e6425 100644
--- a/Scribus/scribus/scribusdoc.h
+++ b/Scribus/scribus/scribusdoc.h
@@ -1790,6 +1790,9 @@ public:
 	void SubmitForm();
 	void ImportData();
 	void ResetFormFields();
+	
+	//check if char should have additional space before or after
+	bool checkAddSpace(QChar ch, int &before, int &after);
 };
 
 Q_DECLARE_METATYPE(ScribusDoc*);
diff --git a/Scribus/scribus/ui/prefs_typography.cpp b/Scribus/scribus/ui/prefs_typography.cpp
index e442b55..f670e2b 100644
--- a/Scribus/scribus/ui/prefs_typography.cpp
+++ b/Scribus/scribus/ui/prefs_typography.cpp
@@ -14,6 +14,11 @@ Prefs_Typography::Prefs_Typography(QWidget* parent, ScribusDoc* doc)
 {
 	setupUi(this);
 	languageChange();
+
+	connect(spacesTable, SIGNAL(cellChanged(int,int)), this, SLOT(tableItemChanged()));
+	connect(addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
+	connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteEntry()));
+	connect(clearButton, SIGNAL(clicked()), this, SLOT(clearEntries()));
 }
 
 Prefs_Typography::~Prefs_Typography()
@@ -38,6 +43,93 @@ void Prefs_Typography::languageChange()
 	strikeoutLineWidthSpinBox->setToolTip( tr( "Line width expressed as a percentage of the font size" ) );
 	smallcapsScalingSpinBox->setToolTip( tr( "Relative size of the small caps font compared to the normal font" ) );
 	automaticLineSpacingSpinBox->setToolTip( tr( "Percentage increase over the font size for the line spacing" ) );
+	spacesTable->setToolTip("Add empty space before/after glyph as % of normal space width in current font");
+}
+
+void Prefs_Typography::updateTable()
+{
+	disconnect(spacesTable, SIGNAL(cellChanged(int,int)), this, SLOT(tableItemChanged()));
+	spacesTable->setRowCount(spacesMap.count());
+	int row=0;
+	foreach (QString chars, spacesMap.keys())
+	{
+		uint i=0;
+		//Chars
+		QTableWidgetItem *item1 = new QTableWidgetItem(chars);
+		item1->setText(chars);
+		spacesTable->setItem(row, i++, item1);
+		//Add before
+		QSpinBox *item2 = new QSpinBox();
+		item2->setMinimum(0);
+		item2->setMaximum(999);
+		item2->setValue(spacesMap.value(chars).first);
+		item2->setSuffix("%");
+		connect(item2, SIGNAL(valueChanged(int)), this, SLOT(tableItemChanged()));
+		spacesTable->setCellWidget(row, i++, item2);
+		//Add after
+		QSpinBox *item3 = new QSpinBox();
+		item3->setMinimum(0);
+		item3->setMaximum(999);
+		item3->setValue(spacesMap.value(chars).second);
+		item3->setSuffix("%");
+		connect(item3, SIGNAL(valueChanged(int)), this, SLOT(tableItemChanged()));
+		spacesTable->setCellWidget(row, i++, item3);
+
+		QTableWidgetItem *t=spacesTable->verticalHeaderItem(row);
+		if (t!=NULL)
+			t->setText(QString("%1").arg(row));
+		row++;
+	}
+	deleteButton->setEnabled(spacesMap.count()!=0);
+	clearButton->setEnabled(spacesMap.count()!=0);
+	connect(spacesTable, SIGNAL(cellChanged(int,int)), this, SLOT(tableItemChanged()));
+}
+
+void Prefs_Typography::tableItemChanged()
+{
+	spacesMap.clear();
+	for (int row=0; row < spacesTable->rowCount(); ++row)
+	{
+		QString chars = spacesTable->item(row, 0)->text();
+		QSpinBox* qspB=dynamic_cast<QSpinBox*>(spacesTable->cellWidget(row,1));
+		QSpinBox* qspA=dynamic_cast<QSpinBox*>(spacesTable->cellWidget(row,2));
+		if (qspB!=NULL && qspA!=NULL)
+			spacesMap.insert(chars, qMakePair(qspB->value(), qspA->value()));
+	}
+}
+
+void Prefs_Typography::addEntry()
+{
+	spacesMap.insert("<chars>", qMakePair(0,0));
+	updateTable();
+}
+
+void Prefs_Typography::deleteEntry()
+{
+	int currRow=spacesTable->currentRow();
+	bool found=false;
+	int count=0;
+	QMap<QString, QPair<int,int> >::Iterator it;
+	for(it = spacesMap.begin(); it!= spacesMap.end(); ++it)
+	{
+		if(count==currRow)
+		{
+			found=true;
+			break;
+		}
+		++count;
+	}
+	if (found)
+	{
+		spacesMap.erase(it);
+		updateTable();
+	}
+}
+
+void Prefs_Typography::clearEntries()
+{
+	spacesMap.clear();
+	updateTable();
 }
 
 void Prefs_Typography::restoreDefaults(struct ApplicationPrefs *prefsData)
@@ -52,6 +144,9 @@ void Prefs_Typography::restoreDefaults(struct ApplicationPrefs *prefsData)
 	strikeoutLineWidthSpinBox->setValue(prefsData->typoPrefs.valueStrikeThruWidth / 10.0);
 	smallcapsScalingSpinBox->setValue(prefsData->typoPrefs.valueSmallCaps);
 	automaticLineSpacingSpinBox->setValue(prefsData->typoPrefs.autoLineSpacing);
+	foreach(QString chars, prefsData->typoPrefs.addSpaceMap.keys())
+		spacesMap.insert(chars, prefsData->typoPrefs.addSpaceMap.value(chars));
+	updateTable();
 }
 
 void Prefs_Typography::saveGuiToPrefs(struct ApplicationPrefs *prefsData) const
@@ -66,5 +161,9 @@ void Prefs_Typography::saveGuiToPrefs(struct ApplicationPrefs *prefsData) const
 	prefsData->typoPrefs.valueStrikeThruWidth=strikeoutLineWidthSpinBox->value() * 10.0;
 	prefsData->typoPrefs.valueSmallCaps=smallcapsScalingSpinBox->value();
 	prefsData->typoPrefs.autoLineSpacing=automaticLineSpacingSpinBox->value();
+
+	prefsData->typoPrefs.addSpaceMap.clear();
+	foreach (QString chars, spacesMap.keys())
+		prefsData->typoPrefs.addSpaceMap.insert(chars, spacesMap.value(chars));
 }
 
diff --git a/Scribus/scribus/ui/prefs_typography.h b/Scribus/scribus/ui/prefs_typography.h
index 629c4af..ae5ea5f 100644
--- a/Scribus/scribus/ui/prefs_typography.h
+++ b/Scribus/scribus/ui/prefs_typography.h
@@ -26,6 +26,15 @@ class SCRIBUS_API Prefs_Typography : public Prefs_Pane, Ui::Prefs_Typography
 
 	public slots:
 		void languageChange();
+protected:
+	virtual void updateTable();
+protected slots:
+	virtual void tableItemChanged();
+	virtual void addEntry();
+	virtual void deleteEntry();
+	virtual void clearEntries();
+private:
+	QMap<QString, QPair<int,int> > spacesMap;
 };
 
 #endif // PREFS_TYPOGRAPHY_H
diff --git a/Scribus/scribus/ui/prefs_typographybase.ui b/Scribus/scribus/ui/prefs_typographybase.ui
index 8f59e4c..0fa1c67 100644
--- a/Scribus/scribus/ui/prefs_typographybase.ui
+++ b/Scribus/scribus/ui/prefs_typographybase.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>682</width>
-    <height>449</height>
+    <width>453</width>
+    <height>730</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -45,8 +45,8 @@
        <rect>
         <x>0</x>
         <y>0</y>
-        <width>639</width>
-        <height>782</height>
+        <width>431</width>
+        <height>673</height>
        </rect>
       </property>
       <layout class="QVBoxLayout" name="verticalLayout">
@@ -71,13 +71,7 @@
         </widget>
        </item>
        <item>
-        <layout class="QFormLayout" name="formLayout_3">
-         <property name="fieldGrowthPolicy">
-          <enum>QFormLayout::FieldsStayAtSizeHint</enum>
-         </property>
-         <property name="formAlignment">
-          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-         </property>
+        <layout class="QGridLayout" name="gridLayout">
          <item row="0" column="0">
           <widget class="QLabel" name="label_5">
            <property name="text">
@@ -85,17 +79,7 @@
            </property>
           </widget>
          </item>
-         <item row="0" column="1">
-          <widget class="QSpinBox" name="subscriptDisplacementSpinBox">
-           <property name="suffix">
-            <string> %</string>
-           </property>
-           <property name="maximum">
-            <number>100</number>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="1">
+         <item row="0" column="4">
           <widget class="QSpinBox" name="subscriptScalingSpinBox">
            <property name="suffix">
             <string> %</string>
@@ -108,13 +92,52 @@
            </property>
           </widget>
          </item>
-         <item row="1" column="0">
+         <item row="0" column="3">
           <widget class="QLabel" name="label_6">
            <property name="text">
             <string>Scaling:</string>
            </property>
           </widget>
          </item>
+         <item row="0" column="2">
+          <spacer name="horizontalSpacer">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeType">
+            <enum>QSizePolicy::Minimum</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item row="0" column="1">
+          <widget class="QSpinBox" name="subscriptDisplacementSpinBox">
+           <property name="suffix">
+            <string> %</string>
+           </property>
+           <property name="maximum">
+            <number>100</number>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="5">
+          <spacer name="horizontalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
         </layout>
        </item>
        <item>
@@ -123,7 +146,7 @@
           <enum>Qt::Vertical</enum>
          </property>
          <property name="sizeType">
-          <enum>QSizePolicy::Fixed</enum>
+          <enum>QSizePolicy::Expanding</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
@@ -154,50 +177,73 @@
         </widget>
        </item>
        <item>
-        <layout class="QFormLayout" name="formLayout_2">
-         <property name="fieldGrowthPolicy">
-          <enum>QFormLayout::FieldsStayAtSizeHint</enum>
-         </property>
-         <property name="formAlignment">
-          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-         </property>
-         <item row="0" column="0">
-          <widget class="QLabel" name="label_7">
-           <property name="text">
-            <string>Displacement:</string>
-           </property>
-          </widget>
-         </item>
-         <item row="0" column="1">
-          <widget class="QSpinBox" name="superscriptDisplacementSpinBox">
+        <layout class="QGridLayout" name="gridLayout_2">
+         <item row="0" column="4">
+          <widget class="QSpinBox" name="superscriptScalingSpinBox">
            <property name="suffix">
             <string> %</string>
            </property>
+           <property name="minimum">
+            <number>1</number>
+           </property>
            <property name="maximum">
             <number>100</number>
            </property>
           </widget>
          </item>
-         <item row="1" column="0">
+         <item row="0" column="2">
+          <spacer name="horizontalSpacer_3">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeType">
+            <enum>QSizePolicy::Maximum</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_7">
+           <property name="text">
+            <string>Displacement:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="3">
           <widget class="QLabel" name="label_8">
            <property name="text">
             <string>Scaling:</string>
            </property>
           </widget>
          </item>
-         <item row="1" column="1">
-          <widget class="QSpinBox" name="superscriptScalingSpinBox">
+         <item row="0" column="1">
+          <widget class="QSpinBox" name="superscriptDisplacementSpinBox">
            <property name="suffix">
             <string> %</string>
            </property>
-           <property name="minimum">
-            <number>1</number>
-           </property>
            <property name="maximum">
             <number>100</number>
            </property>
           </widget>
          </item>
+         <item row="0" column="5">
+          <spacer name="horizontalSpacer_4">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
         </layout>
        </item>
        <item>
@@ -206,7 +252,7 @@
           <enum>Qt::Vertical</enum>
          </property>
          <property name="sizeType">
-          <enum>QSizePolicy::Fixed</enum>
+          <enum>QSizePolicy::Expanding</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
@@ -237,29 +283,9 @@
         </widget>
        </item>
        <item>
-        <layout class="QFormLayout" name="formLayout">
-         <property name="fieldGrowthPolicy">
-          <enum>QFormLayout::FieldsStayAtSizeHint</enum>
-         </property>
-         <property name="formAlignment">
-          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-         </property>
-         <item row="0" column="0">
-          <widget class="QLabel" name="label_9">
-           <property name="text">
-            <string>Displacement:</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="0">
-          <widget class="QLabel" name="label_10">
-           <property name="text">
-            <string>Line Width:</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="1">
-          <widget class="QDoubleSpinBox" name="underlineLineWidthSpinBox">
+        <layout class="QGridLayout" name="gridLayout_3">
+         <item row="0" column="1">
+          <widget class="QDoubleSpinBox" name="underlineDisplacementSpinBox">
            <property name="wrapping">
             <bool>true</bool>
            </property>
@@ -277,8 +303,15 @@
            </property>
           </widget>
          </item>
-         <item row="0" column="1">
-          <widget class="QDoubleSpinBox" name="underlineDisplacementSpinBox">
+         <item row="0" column="3">
+          <widget class="QLabel" name="label_10">
+           <property name="text">
+            <string>Line Width:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="4">
+          <widget class="QDoubleSpinBox" name="underlineLineWidthSpinBox">
            <property name="wrapping">
             <bool>true</bool>
            </property>
@@ -296,6 +329,42 @@
            </property>
           </widget>
          </item>
+         <item row="0" column="2">
+          <spacer name="horizontalSpacer_5">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeType">
+            <enum>QSizePolicy::Maximum</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_9">
+           <property name="text">
+            <string>Displacement:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="5">
+          <spacer name="horizontalSpacer_6">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
         </layout>
        </item>
        <item>
@@ -304,7 +373,7 @@
           <enum>Qt::Vertical</enum>
          </property>
          <property name="sizeType">
-          <enum>QSizePolicy::Fixed</enum>
+          <enum>QSizePolicy::Expanding</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
@@ -335,22 +404,25 @@
         </widget>
        </item>
        <item>
-        <layout class="QFormLayout" name="formLayout_4">
-         <property name="fieldGrowthPolicy">
-          <enum>QFormLayout::FieldsStayAtSizeHint</enum>
-         </property>
-         <property name="formAlignment">
-          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-         </property>
-         <item row="0" column="0">
-          <widget class="QLabel" name="label_12">
-           <property name="text">
-            <string>Displacement:</string>
-           </property>
-          </widget>
+        <layout class="QGridLayout" name="gridLayout_4">
+         <item row="0" column="2">
+          <spacer name="horizontalSpacer_7">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeType">
+            <enum>QSizePolicy::Maximum</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
          </item>
-         <item row="0" column="1">
-          <widget class="QDoubleSpinBox" name="strikeoutDisplacementSpinBox">
+         <item row="0" column="4">
+          <widget class="QDoubleSpinBox" name="strikeoutLineWidthSpinBox">
            <property name="wrapping">
             <bool>true</bool>
            </property>
@@ -368,15 +440,22 @@
            </property>
           </widget>
          </item>
-         <item row="1" column="0">
+         <item row="0" column="3">
           <widget class="QLabel" name="label_13">
            <property name="text">
             <string>Line Width:</string>
            </property>
           </widget>
          </item>
-         <item row="1" column="1">
-          <widget class="QDoubleSpinBox" name="strikeoutLineWidthSpinBox">
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_12">
+           <property name="text">
+            <string>Displacement:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1">
+          <widget class="QDoubleSpinBox" name="strikeoutDisplacementSpinBox">
            <property name="wrapping">
             <bool>true</bool>
            </property>
@@ -394,6 +473,19 @@
            </property>
           </widget>
          </item>
+         <item row="0" column="5">
+          <spacer name="horizontalSpacer_8">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
         </layout>
        </item>
        <item>
@@ -402,7 +494,7 @@
           <enum>Qt::Vertical</enum>
          </property>
          <property name="sizeType">
-          <enum>QSizePolicy::Fixed</enum>
+          <enum>QSizePolicy::Expanding</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
@@ -465,7 +557,7 @@
           <enum>Qt::Vertical</enum>
          </property>
          <property name="sizeType">
-          <enum>QSizePolicy::Fixed</enum>
+          <enum>QSizePolicy::Expanding</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
@@ -533,7 +625,120 @@
          <property name="sizeHint" stdset="0">
           <size>
            <width>20</width>
-           <height>34</height>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="Line" name="line_8">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox">
+         <property name="font">
+          <font>
+           <weight>75</weight>
+           <bold>true</bold>
+          </font>
+         </property>
+         <property name="title">
+          <string>Additional Spaces for Chars</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <item>
+             <spacer name="spacer">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeType">
+               <enum>QSizePolicy::Expanding</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>192</width>
+                <height>21</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <widget class="QPushButton" name="addButton">
+              <property name="text">
+               <string>&amp;Add</string>
+              </property>
+              <property name="shortcut">
+               <string>Alt+A</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="deleteButton">
+              <property name="text">
+               <string>&amp;Delete</string>
+              </property>
+              <property name="shortcut">
+               <string>Alt+D</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="clearButton">
+              <property name="text">
+               <string>C&amp;lear</string>
+              </property>
+              <property name="shortcut">
+               <string>Alt+L</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="ScTableWidget" name="spacesTable">
+            <property name="alternatingRowColors">
+             <bool>false</bool>
+            </property>
+            <property name="rowCount">
+             <number>0</number>
+            </property>
+            <property name="columnCount">
+             <number>3</number>
+            </property>
+            <column>
+             <property name="text">
+              <string>Chars</string>
+             </property>
+            </column>
+            <column>
+             <property name="text">
+              <string>Add Before</string>
+             </property>
+            </column>
+            <column>
+             <property name="text">
+              <string>Add After</string>
+             </property>
+            </column>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_7">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
           </size>
          </property>
         </spacer>
@@ -544,6 +749,13 @@
    </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>ScTableWidget</class>
+   <extends>QTableWidget</extends>
+   <header>ui/sctablewidget.h</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections/>
 </ui>
typographicSpaces.patch (35,218 bytes)

JLuc

2013-01-16 15:05

developer   ~0029713

Last edited: 2013-01-16 17:45

View 2 revisions

This feature can have some real nice use in automatizing small space addition
but it can have bad effects if automation is badly controlled :
it should not teach bad habbits to the user (not teach him to never use spaces because this tool puts them nicely) and it must do nothing and not interfere in case the user has allready taken control and has taken the time and the pain to allready insert some special space before.

This new typo function provides very interesting fine tuning of spaces so it should overwrite basic existing normal spaces allready there, but it should not overwrite the manualy fine-tuned spaces like thin spaces or non breaking space or other special spaces that have been inserted by hand with conscious choice.

When typing "first question ? Second question?", the spaces resulting of this new treatment should be the same before the '?'.

jghali

2013-01-16 20:13

administrator   ~0029719

>> It should not overwrite the manualy fine-tuned spaces like thin spaces or non breaking space or other special spaces that have been inserted by hand with conscious choice

I agree 100% here.

cezaryece

2013-01-16 20:45

developer   ~0029721

JLuc, do you test this feature or your reports are based on wishfull thinking only?

JLuc

2013-01-17 13:15

developer   ~0029724

Last edited: 2013-01-23 09:53

View 5 revisions

I have not tested the patch yet.
My previous note is my conlusion following cezariece's explanations on irc and our discussion about it.

Think of it as a quality test check :

1- do the spaces before both '?' appear to be the same after feature has dealt with following input : "first question ? Second question?" (Answer should be YES. As a consequence : feature should test whether there is a space before or after, before acting)

2- do the writer require to omit correct spaces so as to benefit of feature (Answer should be NO so as not to teach bad habbits to the user. If 1- is OK, then 2- should be OK too)

3- do the feature keep special spaces and do nothing in cases and in place wher some special spaces have been inserted ? (should be YES. As a consequence : feature should test whether there is a special space before or after, before acting)

cezaryece

2013-01-23 10:27

developer   ~0029757

No spacing is added before/after char if before/after it is any space (recognized by Qt function QChar::isSpace(); I test that any spaces Scribus use are recognized properly).

Ad 1 - additional space will be added only to second '?'
Ad 2 - if rules require spaces (as char) then why anyone will expected additional spacing for chars?
Ad 3 - spaces are added to glyphs only and text is not touched (corrected) in any way, any char is added or deleted

JLuc

2013-10-18 11:09

developer   ~0030736

Last edited: 2013-10-18 12:00

View 6 revisions

So :

- no 'space' glyph is added to the text, but some width is added to the glyph (before and after it but "inside it"). The glyph is displayed (and exportedtoPDF) with that bigger width when required.

- glyph is made wider before or after only if there is no space before or after.

So the answers to my previous questions are :

1) yes or no, depending on whether the user has inserted a correct thin space before the first '?' : this features does not change the allready there spaces. So if the user has correctly inserted a thin space, then it will be OK. If the user has inserted a normal space, then it will appear wider than the space emulated by the widened glyph.

2) user has to either use special thin spaces OR to not use any spaces and leave the feature deal with them.

3) yes, as for normal spaces [ and also for non breaking spaces ; thin spaces ; non breaking thin spaces ; other spaces since isSpace is replaced with isWhiteChar in new commit http://www.git.scribus-ece.info/?p=ScribusECE;a=commit;h=a93898133397b172841c55a39be12414d7fb61b1].

Issue History

Date Modified Username Field Change
2013-01-15 15:03 cezaryece New Issue
2013-01-15 15:03 cezaryece File Added: typographicSpaces.patch
2013-01-15 15:04 cezaryece File Added: addSpaces1.jpg
2013-01-15 15:04 cezaryece File Added: addSpaces2.jpg
2013-01-15 15:58 JLuc Note Added: 0029706
2013-01-16 06:22 cezaryece Note Added: 0029707
2013-01-16 06:27 cezaryece Note Added: 0029708
2013-01-16 09:21 cezaryece File Deleted: addSpaces1.jpg
2013-01-16 09:22 cezaryece File Deleted: typographicSpaces.patch
2013-01-16 09:22 cezaryece File Added: typographicSpaces.patch
2013-01-16 09:37 cezaryece File Deleted: typographicSpaces.patch
2013-01-16 09:37 cezaryece File Added: typoSpace.jpg
2013-01-16 09:37 cezaryece File Added: typographicSpaces.patch
2013-01-16 15:05 JLuc Note Added: 0029713
2013-01-16 17:45 JLuc Note Edited: 0029713 View Revisions
2013-01-16 20:13 jghali Note Added: 0029719
2013-01-16 20:45 cezaryece Note Added: 0029721
2013-01-17 13:15 JLuc Note Added: 0029724
2013-01-23 09:51 JLuc Note Edited: 0029724 View Revisions
2013-01-23 09:52 JLuc Note Edited: 0029724 View Revisions
2013-01-23 09:52 JLuc Note Edited: 0029724 View Revisions
2013-01-23 09:53 JLuc Note Edited: 0029724 View Revisions
2013-01-23 10:27 cezaryece Note Added: 0029757
2013-10-18 11:09 JLuc Note Added: 0030736
2013-10-18 11:10 JLuc Note Edited: 0030736 View Revisions
2013-10-18 11:11 JLuc Note Edited: 0030736 View Revisions
2013-10-18 11:57 JLuc Note Edited: 0030736 View Revisions
2013-10-18 11:59 JLuc Note Edited: 0030736 View Revisions
2013-10-18 12:00 JLuc Note Edited: 0030736 View Revisions
2014-06-13 00:38 Kunda Tag Attached: patch
2014-10-24 23:00 Kunda Patch => Yes
2017-10-28 10:09 JLuc Tag Attached: spacing