r15962 by pierremarc - Made many adjustments in boxes rendering and ICU output parsing to get correct arabic composition

scribus-commit scribus-commit at lists.scribus.net
Tue Nov 23 17:23:03 CET 2010


Author: pierremarc
Date: Tue Nov 23 16:23:03 2010
New Revision: 15962

URL: http://scribus.info/websvn/listing.php?repname=Scribus&sc=1&rev=15962
Log:
Made many adjustments in boxes rendering and ICU output parsing to get correct arabic composition

Modified:
    branches/ScribusOIF/resources/loremipsum/ar.xml
    branches/ScribusOIF/scribus/fonts/scface_ttf.cpp
    branches/ScribusOIF/scribus/fonts/scfontmetrics.cpp
    branches/ScribusOIF/scribus/text/boxes.cpp
    branches/ScribusOIF/scribus/text/glyphlayout.cpp
    branches/ScribusOIF/scribus/text/linelayouter.cpp

Modified: branches/ScribusOIF/resources/loremipsum/ar.xml
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15962&path=/branches/ScribusOIF/resources/loremipsum/ar.xml
==============================================================================
--- branches/ScribusOIF/resources/loremipsum/ar.xml (original)
+++ branches/ScribusOIF/resources/loremipsum/ar.xml Tue Nov 23 16:23:03 2010
@@ -5,6 +5,9 @@
 <author>Marek Moehling</author>
 <url>http://lorem-ipsum.info</url>
 
+<p>
+جعل شبكة الويب العالÙ
يّة عالÙ
يّة حقًّا
+</p>
 <p>
 تصفح الحربي، به، ٣٠, إذ الشتاء الÙ
برÙ
Ø© حدى. Ù
Ù† ولÙ
 Ù
رجع هزيÙ
Ø© وسÙ
ّيت, فقد عل الجنوب بقيادة. فعل بـ باحتلال وبالتحديد،, وحتى الÙ
عركة، Ø£Ù
 فصل, الفاشي الإقتصادي ان تلك. نفس Ù
شاركة اليابان، الإقتصادية عل, Ø£Ù
 بزوال تجهيز تعد, Ùˆ يتÙ
 خيار يعادل الأولية. و ساعة استراليا، حدة.
 </p>
@@ -39,4 +42,4 @@
 بين عن أراضي والعتاد للألÙ
ان, قصف Ù
ا Ù
كّن بÙ
حاولة. هُزÙ
 Ù
شقّة فعل Ø«Ù
, هو بعض بفرض بلاده يتعلّق. أهّل ألÙ
اني العصبة حتى Ù
ا, أدوات اكتوبر جزيرتي Ù
ع ولÙ
. تلك Ø«Ù
 كانتا والÙ
عدات والروسية, كل سقطت واقتصار أخذ.
 </p>
 
-</lorem>
+</lorem>

Modified: branches/ScribusOIF/scribus/fonts/scface_ttf.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15962&path=/branches/ScribusOIF/scribus/fonts/scface_ttf.cpp
==============================================================================
--- branches/ScribusOIF/scribus/fonts/scface_ttf.cpp (original)
+++ branches/ScribusOIF/scribus/fonts/scface_ttf.cpp Tue Nov 23 16:23:03 2010
@@ -744,6 +744,7 @@
 	const TextStore * story(gs->story());
 	LanguageManager * lm(LanguageManager::instance());
 	QString language(lm->getAbbrevFromLang(story->charStyle(gs->itemTextPosition(item)).language(), false, false));
+	bool isRTL(lm->isRightToLeft(language));
 	bool isAuto(story->charStyle(gs->itemTextPosition(item)).autoShape());
 	double fSize(story->charStyle(gs->itemTextPosition(item)).fontSize() /10.0);
 	int itemPos(gs->itemTextPosition(item));
@@ -767,7 +768,7 @@
 			++ci;
 		}
 		icuLE->reset();
-		int glAllocated = icuLE->layoutChars( ts, 0, sCount , sCount, false, 0, 0, err );
+		int glAllocated = icuLE->layoutChars( ts, 0, sCount , sCount, isRTL, 0, 0, err );
 
 		le_int32 gCount(icuLE->getGlyphCount());
 		LEGlyphID *glyphs    = new LEGlyphID[gCount];
@@ -776,43 +777,67 @@
 		icuLE->getGlyphs ( glyphs, err );
 		icuLE->getCharIndices ( indices, err );
 //		icuLE->getGlyphPositions ( positions, err );
-		float stackX ( 0.0 );
-		float stackY ( 0.0 );
+//		float stackX ( 0.0 );
+//		float stackY ( 0.0 );
+		float xShift(0.0);
+		float yShift(0.0);
 		QList<GlyphLayout> glList;
 		QList<le_int32> charList;
+		QList<bool> markList;
 		double sHeight((m_ascent - m_descent) * fSize);
-
+		double sFactor(fSize / m_uniEM);
 		float icuX(0);
 		float icuY(0);
 		float icuFwdX(0);
 		float icuFwdY(0);
 		for ( le_int32 gIdx ( 0 ); gIdx < gCount ; ++gIdx )
 		{
-			if(glyphs[gIdx] != 0xFFFF)
+			if((glyphs[gIdx] != 0xFFFF)
+				&& (glyphs[gIdx] != 0xFFFE))
 			{
 				icuLE->getGlyphPosition(gIdx, icuX, icuY, err);
 				le_int32 nextIdx(gIdx + 1);
 				while((glyphs[nextIdx] == 0xFFFF) && (nextIdx < gCount))
 					++nextIdx;
 				icuLE->getGlyphPosition(nextIdx, icuFwdX, icuFwdY, err);
-
+				icuX *= sFactor;
+				icuY *= sFactor;
+				icuFwdX *= sFactor;
+				icuFwdY *= sFactor;
 				if(err != LE_NO_ERROR)
 					continue;
+				QChar c(text.at(indices[gIdx]));
+				bool isDiacritic(c.isMark());
+				bool isCombining(indices[gIdx] == indices[nextIdx]);
 				GlyphLayout curGlyph;
 				curGlyph.glyph = glyphs[gIdx];
-//				curGlyph.xadvance = (positions[ ( gIdx + 1 ) * 2] * fSize / m_uniEM) - stackX;
-//				curGlyph.yoffset = ((stackY - positions[ ( ( gIdx + 1 ) * 2 ) + 1]) * fSize / m_uniEM) + sHeight;
 				curGlyph.xadvance = glyphWidth(curGlyph.glyph, fSize);
-				curGlyph.xoffset = stackX;
-				curGlyph.yoffset = (icuY - stackY) * fSize / m_uniEM;
+				curGlyph.xoffset = isRTL ? (icuFwdX - icuX) - curGlyph.xadvance : xShift;
+				curGlyph.yoffset = yShift;
 				curGlyph.yadvance = 0;
-				stackY = icuFwdY;
-				stackX = ((icuFwdX - icuX) * fSize / m_uniEM) - curGlyph.xadvance;
-//				stackX +=  curGlyph.xadvance;
-//				stackY = positions[ ( ( gIdx + 1 ) * 2 ) + 1];
-				glList << curGlyph;
-				charList << indices[gIdx];
-//				qDebug()<<"icu"<<text.at(indices[gIdx])<< itemPos + indices[gIdx] << curGlyph.glyph <<curGlyph.xadvance <<curGlyph.yoffset ;
+				xShift =  (icuFwdX - icuX) - curGlyph.xadvance;
+				yShift =  (icuFwdY - icuY) - sHeight;
+				if(isDiacritic || isCombining)
+					yShift -= sHeight - curGlyph.yoffset;
+//				stackY = icuFwdY;
+//				stackX = icuX;
+				if(isRTL)
+				{
+					glList.prepend( curGlyph );
+					charList.prepend(indices[gIdx]);
+					markList.prepend(isDiacritic);
+				}
+				else
+				{
+					glList << curGlyph;
+					charList << indices[gIdx];
+					markList << isDiacritic;
+				}
+				qDebug()<<"icu"<<indices[gIdx]
+						<< curGlyph.glyph
+						<< sHeight
+						<< icuY
+						<< icuFwdY ;
 			}
 		}
 		icuLE->reset();
@@ -827,19 +852,23 @@
 		{
 			const GlyphLayout& g(glList.at(i));
 			const le_int32& c(charList.at(i) + itemPos);
+			bool isCombining((i > 0)  && (c == charList.at(i-1) + itemPos));
 			curGlyph->glyph = g.glyph;
 			curGlyph->xadvance = g.xadvance;
 			curGlyph->xoffset = g.xoffset;
 			curGlyph->yadvance = g.yadvance;
 			curGlyph->yoffset = g.yoffset;
-			gs->markCluster(item, c , curGlyph);
-			const_cast<TextFlags&>(story->charAttributes(c)) |= TextFlag_ClusterStart;
+			if(!markList.at(i) && !isCombining)
+			{
+				gs->markCluster(item, c , curGlyph);
+				const_cast<TextFlags&>(story->charAttributes(c)) |= TextFlag_ClusterStart;
+			}
 			++curGlyph;
 		}
 
 
 	}
-	else // FIXME_OIF should be able to mix auto and "manual"
+	else // FIXME_OIF should be able to mix auto and "manual" - will be easier when using harfbuzz shaper
 	{
 		hb_face_t * face = hb_ft_face_create(ftFace(), releaseFaceForHB );
 		hb_font_t * font = hb_ft_font_create (ftFace(), releaseFaceForHB);

Modified: branches/ScribusOIF/scribus/fonts/scfontmetrics.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15962&path=/branches/ScribusOIF/scribus/fonts/scfontmetrics.cpp
==============================================================================
--- branches/ScribusOIF/scribus/fonts/scfontmetrics.cpp (original)
+++ branches/ScribusOIF/scribus/fonts/scfontmetrics.cpp Tue Nov 23 16:23:03 2010
@@ -203,7 +203,7 @@
 	QTransform ma;
 	ma.scale(0.01, -0.01);
 	pts.map(ma);
-	pts.translate(0, chs);
+//	pts.translate(0, chs);
 	pts2.putPoints(0, pts.size()-2, pts, 0);
 
 	return pts2;

Modified: branches/ScribusOIF/scribus/text/boxes.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15962&path=/branches/ScribusOIF/scribus/text/boxes.cpp
==============================================================================
--- branches/ScribusOIF/scribus/text/boxes.cpp (original)
+++ branches/ScribusOIF/scribus/text/boxes.cpp Tue Nov 23 16:23:03 2010
@@ -417,7 +417,8 @@
 	p->save();
 	p->setPen(Qt::lightGray);
 	p->setFillMode(ScPainter::None);
-	p->drawRect(x(), y()-m_ascent, width(), height());
+//	p->drawRect(x(), y()-m_ascent, width(), height());
+	p->drawLine(FPoint(x(), y()), FPoint(x() + width(), y()));
 	p->restore();
 	p->save();
 	p->setAntialiasing(true);
@@ -463,55 +464,66 @@
 			else
 				break;
 		}
-		GlyphLayout* layout = cluster.glyphs();
-		uint glyph = layout->glyph;
-		if(rtl)
-			p->translate(-(layout->xadvance + layout->xoffset), 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))
-		{
-			layout->renderControlChar(p, renderOptions, style);
-			if(m_glyphs->haveNext(cluster))
-				cluster = m_glyphs->next(cluster);
-			else
-				break;
-			continue;
-		}
-		else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode()) ||
+
+		uint gCount(m_glyphs->glyphCount(cluster));
+		// consume all the glyphs in the cluster
+		for(uint gIdx(0); gIdx < gCount; ++gIdx )
+		{
+			GlyphLayout* layout = cluster.glyphs() + gIdx;
+			uint glyph = layout->glyph;
+			if(rtl)
+			{
+				p->translate(- (layout->xoffset + 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))
+			{
+				layout->renderControlChar(p, renderOptions, style);
+				if(m_glyphs->haveNext(cluster))
+					cluster = m_glyphs->next(cluster);
+				else
+					break;
+				continue;
+			}
+			else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode()) ||
 				 glyph == (ScFace::CONTROL_GLYPHS + 32)) 
-			glyph = style.font().char2CMap(QChar(' '));
-		else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode()))
-			glyph = style.font().char2CMap(QChar('-'));
-		
-		if (glyph >= ScFace::CONTROL_GLYPHS || (style.effects() & ScStyle_SuppressSpace)) 
-		{
-//			qDebug() << "render GlyphBox: skipping" << glyph;
-			// all those are empty
-
-			if(m_glyphs->haveNext(cluster))
-				cluster = m_glyphs->next(cluster);
-			else
-				break;
-			continue;
-		}
-		//	if (style.font().canRender(QChar(glyph)))
-		{
-			// Do underlining first so you can get typographically correct
-			// underlines when drawing a white outline
-			if (((style.effects() & ScStyle_Underline) || ((style.effects() & ScStyle_UnderlineWords) && glyph != style.font().char2CMap(QChar(' ')))) && (style.strokeColor() != CommonStrings::None))
-			{
-				layout->renderUnderline(p, renderOptions, style);
-			}
-			
-			layout->renderOutlines(p, renderOptions, style);
-
-			if ((style.effects() & ScStyle_Strikethrough) && (style.strokeColor() != CommonStrings::None))
-			{
-				layout->renderStrikeThrough(p, renderOptions, style);
-			}
-		}
-		/*	else
+				glyph = style.font().char2CMap(QChar(' '));
+			else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode()))
+				glyph = style.font().char2CMap(QChar('-'));
+
+			if (glyph >= ScFace::CONTROL_GLYPHS || (style.effects() & ScStyle_SuppressSpace))
+			{
+				//			qDebug() << "render GlyphBox: skipping" << glyph;
+				// all those are empty
+
+				if(m_glyphs->haveNext(cluster))
+					cluster = m_glyphs->next(cluster);
+				else
+					break;
+				continue;
+			}
+			//	if (style.font().canRender(QChar(glyph)))
+			{
+				// Do underlining first so you can get typographically correct
+				// underlines when drawing a white outline
+				if (((style.effects() & ScStyle_Underline) || ((style.effects() & ScStyle_UnderlineWords) && glyph != style.font().char2CMap(QChar(' ')))) && (style.strokeColor() != CommonStrings::None))
+				{
+					layout->renderUnderline(p, renderOptions, style);
+				}
+				//			p->save();
+				//			p->setPen(Qt::lightGray);
+				//			p->setFillMode(ScPainter::None);
+				//			p->drawRect(0, -m_ascent, layout->xadvance , height());
+				//			p->restore();
+				layout->renderOutlines(p, renderOptions, style);
+
+				if ((style.effects() & ScStyle_Strikethrough) && (style.strokeColor() != CommonStrings::None))
+				{
+					layout->renderStrikeThrough(p, renderOptions, style);
+				}
+			}
+			/*	else
 		 {
 		 p->setLineWidth(1);
 		 p->setPen(red);
@@ -520,8 +532,9 @@
 		 p->drawRect(glyphs.xoffset, glyphs.yoffset - (style.fontSize() / 10.0) * glyphs.scaleV , (style.fontSize() / 10.0) * glyphs.scaleH, (style.fontSize() / 10.0) * glyphs.scaleV);
 		 }
 		 */
-		if(!rtl)
-			p->translate(layout->xadvance + layout->xoffset, 0);
+			if(!rtl)
+				p->translate(layout->xadvance + layout->xoffset, 0);
+		}
 		if(m_glyphs->haveNext(cluster))
 			cluster = m_glyphs->next(cluster);
 		else

Modified: branches/ScribusOIF/scribus/text/glyphlayout.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15962&path=/branches/ScribusOIF/scribus/text/glyphlayout.cpp
==============================================================================
--- branches/ScribusOIF/scribus/text/glyphlayout.cpp (original)
+++ branches/ScribusOIF/scribus/text/glyphlayout.cpp Tue Nov 23 16:23:03 2010
@@ -41,7 +41,10 @@
 			//				qDebug() << QString("glyph 0: (%1,%2) * %3 %4 + %5").arg(glyphs.xoffset).arg(glyphs.yoffset).arg(glyphs.scaleH).arg(glyphs.scaleV).arg(glyphs.xadvance));
 		}
 		p->save();
-		p->translate(xoffset, yoffset - ((fontSize / 10.0) * scaleV));
+		// As xoffset has an impact on line composition, it is applied independently of glyph drawing (see GlyphBox::render)
+		// FIXME - make it clear how yoffset should be presented to this method
+//		p->translate(/*xoffset*/ 0, yoffset - ((fontSize / 10.0) * scaleV));
+		p->translate(0, yoffset * scaleV);
 		if (renderOptions.reverse)
 		{
 			p->scale(-1, 1);

Modified: branches/ScribusOIF/scribus/text/linelayouter.cpp
URL: http://scribus.info/websvn/diff.php?repname=Scribus&rev=15962&path=/branches/ScribusOIF/scribus/text/linelayouter.cpp
==============================================================================
--- branches/ScribusOIF/scribus/text/linelayouter.cpp (original)
+++ branches/ScribusOIF/scribus/text/linelayouter.cpp Tue Nov 23 16:23:03 2010
@@ -55,6 +55,7 @@
 	unsigned int lastBreak(0);
 	double lastBreakWidth(0.0);
 	int resultCount(0);
+	int lastPos(start);
 	for(unsigned int i(firstItem); i < itemCount; ++i)
 	{
 		items << i;
@@ -72,6 +73,7 @@
 		rtl = m_layout->story()->charAttributes(cluster.textPosition()).testFlag(TextFlag_RightToLeft);
 		while(true)
 		{
+			lastPos = cluster.textPosition();
 			if(cluster.textPosition() < start)
 			{
 				if(gs->haveNext(cluster))
@@ -146,6 +148,11 @@
 			break;
 	}
 //qDebug()<<"Result len"<<ret.length();
+	if(ret.count() == 0)
+	{
+		LineResult lr(stackWidth + rtlStack, 0, lastPos);
+		ret << lr;
+	}
 	return ret;
 }
 



More information about the scribus-commit mailing list