r15889 by pierremarc - First bits of right-to-left composition support

scribus-commit scribus-commit at lists.scribus.net
Wed Nov 17 14:01:35 CET 2010


Author: pierremarc
Date: Wed Nov 17 13:01:35 2010
New Revision: 15889

URL: http://scribus.info/websvn/listing.php?repname=Scribus&sc=1&rev=15889
Log:
First bits of right-to-left composition support

Modified:
    branches/ScribusOIF/scribus/langmgr.cpp
    branches/ScribusOIF/scribus/langmgr.h
    branches/ScribusOIF/scribus/sctextstruct.h
    branches/ScribusOIF/scribus/text/boxes.cpp
    branches/ScribusOIF/scribus/text/linelayouter.cpp
    branches/ScribusOIF/scribus/text/shaper.cpp
    branches/ScribusOIF/scribus/ui/smcstylewidget.cpp
    branches/ScribusOIF/scribus/ui/smtextstyles.cpp

Modified: branches/ScribusOIF/scribus/langmgr.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15889&path=/branches/ScribusOIF/scribus/langmgr.cpp
==============================================================================
--- branches/ScribusOIF/scribus/langmgr.cpp (original)
+++ branches/ScribusOIF/scribus/langmgr.cpp Wed Nov 17 13:01:35 2010
@@ -316,6 +316,9 @@
 	isoLang.insert(QString("za"), QString("zha"));
 	isoLang.insert(QString("zu"), QString("zul"));
 
+	RTLLangs << QString("ar");
+	RTLLangs << QString("he");
+
 }
 
 void LanguageManager::generateInstalledLangList()
@@ -339,6 +342,19 @@
 	}
 }
 
+const QStringList LanguageManager::getAllLangs(bool getTranslated)
+{
+	QStringList ret;
+	foreach(const langPair& lp, langList)
+	{
+		if(getTranslated)
+			ret << lp.second;
+		else
+			ret << lp.first;
+	}
+	return ret;
+}
+
 const QString LanguageManager::getLangFromAbbrev(QString langAbbrev, bool getTranslated)
 {
 	QMap<QString, langPair>::Iterator it;
@@ -492,6 +508,11 @@
 	return retSeq;
 }
 
+bool LanguageManager::isRightToLeft(const QString &langAbbr)
+{
+	return RTLLangs.contains(langAbbr);
+}
+
 LanguageManager::~LanguageManager()
 {
 	langList.clear();

Modified: branches/ScribusOIF/scribus/langmgr.h
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15889&path=/branches/ScribusOIF/scribus/langmgr.h
==============================================================================
--- branches/ScribusOIF/scribus/langmgr.h (original)
+++ branches/ScribusOIF/scribus/langmgr.h Wed Nov 17 13:01:35 2010
@@ -36,13 +36,14 @@
 class SCRIBUS_API LanguageManager
 {
 	static LanguageManager* m_instance;
-	LanguageManager() {};
+	LanguageManager(){}
 	~LanguageManager();
 	void init(bool generateInstalledList = true);
 	
 public:
 	static LanguageManager* instance();
-	
+
+	const QStringList getAllLangs(bool getTranslated=true);
 	const QString getLangFromAbbrev(QString, bool getTranslated=true);
 	const QString getAbbrevFromLang(QString, bool getFromTranslated=true, bool useInstalled=true);
 	const QString getLangFromTransLang(QString lang);
@@ -51,6 +52,8 @@
 	void fillInstalledStringList(QStringList *stringListToFill, bool addDefaults);
 	void printInstalledList();
 	QString numericSequence(QString seq);
+	bool isRightToLeft(const QString& langAbbr);
+
 	
 	void addHyphLang(const QString& lang, const QString& filename);
 	const QString getHyphFilename(const QString& lang, bool langIsAbbreviated = true);
@@ -61,6 +64,7 @@
 	QMap<QString, QString> installedLangList;
 	QMap<QString, QString> hyphLangList; // <lang abbreviated, dict filename>
 	QMap<QString, QString> isoLang; // <lang abbreviated, iso639-2 abbreviation>
+	QStringList RTLLangs;
 
 	void generateLangList();
 	void generateInstalledLangList();

Modified: branches/ScribusOIF/scribus/sctextstruct.h
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15889&path=/branches/ScribusOIF/scribus/sctextstruct.h
==============================================================================
--- branches/ScribusOIF/scribus/sctextstruct.h (original)
+++ branches/ScribusOIF/scribus/sctextstruct.h Wed Nov 17 13:01:35 2010
@@ -56,6 +56,7 @@
 	TextFlag_StartOfLine = 16,
 	TextFlag_ClusterStart = 32,
 	TextFlag_WordBoundary = 64,
+	TextFlag_RightToLeft = 128
 };
 
 Q_DECLARE_FLAGS(TextFlags, TextFlag)

Modified: branches/ScribusOIF/scribus/text/boxes.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15889&path=/branches/ScribusOIF/scribus/text/boxes.cpp
==============================================================================
--- branches/ScribusOIF/scribus/text/boxes.cpp (original)
+++ branches/ScribusOIF/scribus/text/boxes.cpp Wed Nov 17 13:01:35 2010
@@ -413,6 +413,7 @@
 void GlyphBox::render(ScPainter* p, const RenderOptions& renderOptions) const
 {
 	const CharStyle& style(m_glyphs->story()->charStyle(m_charStart));
+	const bool rtl(m_glyphs->story()->charAttributes(m_charStart).testFlag(TextFlag_RightToLeft));
 	p->save();
 	p->setPen(Qt::lightGray);
 	p->setFillMode(ScPainter::None);
@@ -420,7 +421,10 @@
 	p->restore();
 	p->save();
 	p->setAntialiasing(true);
-	p->translate(x(), y());
+	if(rtl)
+		p->translate(x() + width(), y());
+	else
+		p->translate(x(), y());
 	
 	QString color = style.fillColor();
 	QColor fillColor(Qt::transparent);
@@ -461,6 +465,8 @@
 		}
 		GlyphLayout* layout = cluster.glyphs();
 		uint glyph = layout->glyph;
+		if(rtl)
+			p->translate(-layout->xadvance, 0);
 //		qDebug() << "render pos"<< cluster.textPosition()<<"glyph" << glyph << "width" << layout->xadvance  << "font" << style.font().scName() << "@" << x() << y() ;
 		if ((renderOptions.showControls) && 
 			(glyph == style.font().char2CMap(QChar(' ')) || glyph >=  ScFace::CONTROL_GLYPHS))
@@ -513,8 +519,9 @@
 		 p->setFillMode(1);
 		 p->drawRect(glyphs.xoffset, glyphs.yoffset - (style.fontSize() / 10.0) * glyphs.scaleV , (style.fontSize() / 10.0) * glyphs.scaleH, (style.fontSize() / 10.0) * glyphs.scaleV);
 		 }
-		 */	
-		p->translate(layout->xadvance, 0);
+		 */
+		if(!rtl)
+			p->translate(layout->xadvance, 0);
 		if(m_glyphs->haveNext(cluster))
 			cluster = m_glyphs->next(cluster);
 		else

Modified: branches/ScribusOIF/scribus/text/linelayouter.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15889&path=/branches/ScribusOIF/scribus/text/linelayouter.cpp
==============================================================================
--- branches/ScribusOIF/scribus/text/linelayouter.cpp (original)
+++ branches/ScribusOIF/scribus/text/linelayouter.cpp Wed Nov 17 13:01:35 2010
@@ -34,6 +34,12 @@
 }
 
 // We start with the simpler implementation - pm
+// this method tries to return a result set containing 3 possible lines
+// one at first break before line is longer than available space
+// one at the break just after the line becomes lomger than available space
+// one more after the previous break
+// In first intention, the score is not intended to take in account the difference
+// between available space and line width, just the quality of the break.
 LineLayouterBase::ResultSet LineLayouter::layoutLine(int start, double lineWidth) const
 {
 	ResultSet ret;
@@ -43,21 +49,27 @@
 	double wordSpacing(m_layout->story()->charStyle(start).wordTracking());
 	QList<unsigned int> items;
 	double stackWidth(0.0);
+	double rtlStack(0.0);
+	bool rtl(false);
 	double currentClusterWidth(0.0);
 	unsigned int lastBreak(0);
 	double lastBreakWidth(0.0);
 	int resultCount(0);
 	for(unsigned int i(firstItem); i < itemCount; ++i)
 	{
-		stackWidth += gs->itemWidth(i);
 		items << i;
-		if(stackWidth >= (3.0 * lineWidth)) // weak
-			break;
 	}
-	stackWidth = 0.0;
 	foreach(unsigned int item, items)
 	{
 		Cluster cluster(gs->itemStart(item));
+		if(!rtl)
+			rtlStack = 0.0;
+		else if(!m_layout->story()->charAttributes(cluster.textPosition()).testFlag(TextFlag_RightToLeft))
+		{
+			stackWidth += rtlStack;
+			rtlStack = 0.0;
+		}
+		rtl = m_layout->story()->charAttributes(cluster.textPosition()).testFlag(TextFlag_RightToLeft);
 		while(true)
 		{
 			if(cluster.textPosition() < start)
@@ -79,24 +91,26 @@
 			currentClusterWidth = gs->clusterWidth(cluster) * wordSpacing;
 			if(0 == resultCount)
 			{
-				if((stackWidth + currentClusterWidth) > lineWidth)
+				if((stackWidth + rtlStack + currentClusterWidth) > lineWidth)
 				{
 					if(lastBreak > 0)
 					{
 						LineResult lr(lastBreakWidth, 0, lastBreak);
 						ret << lr;
+						resultCount = 1;
 					}
-					else
+					else if(m_layout->story()->charAttributes(cluster.textPosition()).testFlag(TextFlag_HyphenationPossible)
+						|| SpecialChars::isBreakingSpace(m_layout->story()->text(cluster.textPosition())))
 					{
-						LineResult lr(stackWidth + currentClusterWidth, 1, cluster.textPosition()); // overbox
+						LineResult lr(stackWidth + rtlStack + currentClusterWidth, 1, cluster.textPosition()); // overfullbox
 						ret << lr;
+						resultCount = 1;
 					}
 //					qDebug()<<"Inserting Line Result0"<<lr.width<<lr.endPos;
-					resultCount = 1;
 				}
 				else if(cluster.textPosition() + 1 == m_layout->story()->length())
 				{
-					LineResult lr(stackWidth + currentClusterWidth, 0, cluster.textPosition());
+					LineResult lr(stackWidth + rtlStack + currentClusterWidth, 0, cluster.textPosition());
 					ret << lr;
 //					qDebug()<<"Inserting Line Result1"<<lr.width<<lr.endPos;
 					resultCount = 2;
@@ -106,19 +120,22 @@
 					|| SpecialChars::isBreakingSpace(m_layout->story()->text(cluster.textPosition())))
 				{
 					lastBreak = cluster.textPosition();
-					lastBreakWidth = stackWidth + currentClusterWidth;
+					lastBreakWidth = stackWidth + rtlStack + currentClusterWidth;
 				}
 			}
 			else if(m_layout->story()->charAttributes(cluster.textPosition()).testFlag(TextFlag_HyphenationPossible)
 				|| SpecialChars::isBreakingSpace(m_layout->story()->text(cluster.textPosition())))
 			{
-				LineResult lr(stackWidth + currentClusterWidth, 1, cluster.textPosition());
+				LineResult lr(stackWidth + rtlStack + currentClusterWidth, 1, cluster.textPosition());
 				ret << lr;
 //				qDebug()<<"Inserting Line Result2"<<lr.width<<lr.endPos;
 				resultCount = 2;
 				break;
 			}
-			stackWidth += currentClusterWidth;
+			if(rtl)
+				rtlStack += currentClusterWidth;
+			else
+				stackWidth += currentClusterWidth;
 
 			if(gs->haveNext(cluster))
 				cluster = gs->next(cluster);

Modified: branches/ScribusOIF/scribus/text/shaper.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15889&path=/branches/ScribusOIF/scribus/text/shaper.cpp
==============================================================================
--- branches/ScribusOIF/scribus/text/shaper.cpp (original)
+++ branches/ScribusOIF/scribus/text/shaper.cpp Wed Nov 17 13:01:35 2010
@@ -22,6 +22,7 @@
 
 #include "text/glyphstore.h"
 #include "text/storytext.h"
+#include "langmgr.h"
 
 #include <QDebug>
 
@@ -35,29 +36,45 @@
 {
 	StoryText * story(const_cast<StoryText *>(m_layout->story()));
 	GlyphStore *gs(const_cast<GlyphStore*>(m_layout->storyGlyphs()));
+	LanguageManager * lm(LanguageManager::instance());
 
 	QList<uint> items;
 	// redo itemization for this run
 	CharStyle ref;
 	int itStart(start);
 	bool first(true);
+	bool rtl(false);
 	for(int cursor(start); cursor <= end; ++cursor )
 	{
 		if(first)
 		{
 			first = false;
-			ref = story->charStyle(cursor);
+			ref = story->charStyle(cursor) ;
+			rtl = lm->isRightToLeft(lm->getAbbrevFromLang(story->charStyle(cursor).language(), false, false));
+			if(rtl)
+				story->charAttributes(cursor) |= TextFlag_RightToLeft;
+			else
+				story->charAttributes(cursor) &= ~TextFlag_RightToLeft;
 		}
 		else
 		{
 			if((story->charStyle(cursor) != ref)
 				|| (cursor == end))
 			{
+				if(cursor != end)
+				{
+					ref = story->charStyle(cursor) ;
+					rtl = lm->isRightToLeft(lm->getAbbrevFromLang(story->charStyle(cursor).language(), false, false));
+				}
 				items << gs->addItem(itStart, (cursor) - itStart + 1);
-				qDebug()<<"AddItem"<<itStart<< (cursor - itStart + 1);
 				itStart = cursor + 1;
 			}
+			if(rtl)
+				story->charAttributes(cursor) |= TextFlag_RightToLeft;
+			else
+				story->charAttributes(cursor) &= ~TextFlag_RightToLeft;
 		}
+		qDebug()<<cursor<<story->charStyle(cursor).language()<<ref.language()<< rtl;
 	}
 
 	foreach(uint it, items)

Modified: branches/ScribusOIF/scribus/ui/smcstylewidget.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15889&path=/branches/ScribusOIF/scribus/ui/smcstylewidget.cpp
==============================================================================
--- branches/ScribusOIF/scribus/ui/smcstylewidget.cpp (original)
+++ branches/ScribusOIF/scribus/ui/smcstylewidget.cpp Wed Nov 17 13:01:35 2010
@@ -120,18 +120,23 @@
 
 void SMCStyleWidget::fillLangCombo(QMap<QString,QString> langMap)
 {
-	QStringList sortList;
-	QMap<QString,QString>::Iterator it;
-
-	langMap_ = langMap;
-
-	language_->clear();
-
-	for (it = langMap.begin(); it != langMap.end(); ++it)
-		sortList.push_back(it.value());
-
-	language_->addItems(sortQStringList(sortList));
-
+//	QStringList sortList;
+//	QMap<QString,QString>::Iterator it;
+
+	LanguageManager * lm( LanguageManager::instance() );
+	langMap_.clear();
+	foreach(const QString& tl, lm->getAllLangs())
+	{
+		langMap_.insert(lm->getLangFromTransLang(tl), tl);
+	}
+
+//	language_->clear();
+
+//	for (it = langMap.begin(); it != langMap.end(); ++it)
+//		sortList.push_back(it.value());
+
+//	language_->addItems(sortQStringList(sortList));
+	language_->addItems(lm->getAllLangs());
 	QListView *tmpView = dynamic_cast<QListView*>(language_->view()); Q_ASSERT(tmpView);
 	int tmpWidth = tmpView->sizeHintForColumn(0);
 	if (tmpWidth > 0)

Modified: branches/ScribusOIF/scribus/ui/smtextstyles.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15889&path=/branches/ScribusOIF/scribus/ui/smtextstyles.cpp
==============================================================================
--- branches/ScribusOIF/scribus/ui/smtextstyles.cpp (original)
+++ branches/ScribusOIF/scribus/ui/smtextstyles.cpp Wed Nov 17 13:01:35 2010
@@ -12,6 +12,7 @@
 #include "colorcombo.h"
 #include "commonstrings.h"
 #include "fontcombo.h"
+#include "langmgr.h"
 #include "ui/scmwmenumanager.h"
 #include "prefsmanager.h"
 #include "propertiespalette.h"
@@ -1201,14 +1202,15 @@
 			selection_[i]->charStyle().resetLanguage();
 	else
 	{
-		for (it = doc_->scMW()->LangTransl.begin(); it != doc_->scMW()->LangTransl.end(); ++it)
-		{
-			if (it.value() == pwidget_->cpage->language_->currentText())
-			{
-				language = it.key();
-				break;
-			}
-		}
+//		for (it = doc_->scMW()->LangTransl.begin(); it != doc_->scMW()->LangTransl.end(); ++it)
+//		{
+//			if (it.value() == pwidget_->cpage->language_->currentText())
+//			{
+//				language = it.key();
+//				break;
+//			}
+//		}
+		language = LanguageManager::instance()->getLangFromTransLang(pwidget_->cpage->language_->currentText());
 		for (int i = 0; i < selection_.count(); ++i)
 			selection_[i]->charStyle().setLanguage(language);
 	}
@@ -2119,14 +2121,15 @@
 			selection_[i]->resetLanguage();
 	else
 	{
-		for (it = doc_->scMW()->LangTransl.begin(); it != doc_->scMW()->LangTransl.end(); ++it)
-		{
-			if (it.value() == page_->language_->currentText())
-			{
-				language = it.key();
-				break;
-			}
-		}
+//		for (it = doc_->scMW()->LangTransl.begin(); it != doc_->scMW()->LangTransl.end(); ++it)
+//		{
+//			if (it.value() == page_->language_->currentText())
+//			{
+//				language = it.key();
+//				break;
+//			}
+//		}
+		language = LanguageManager::instance()->getLangFromTransLang(page_->language_->currentText());
 		for (int i = 0; i < selection_.count(); ++i)
 			selection_[i]->setLanguage(language);
 	}




More information about the scribus-commit mailing list