r21107 by craig -

scribus-commit scribus-commit at lists.scribus.net
Wed Mar 23 20:21:36 UTC 2016


Author: craig
Date: Wed Mar 23 20:21:36 2016
New Revision: 21107

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=21107
Log:
Big thanks to HOST-Oman and the team. Commit Boxes diff to SVN. Celebrate

Modified:
    trunk/Scribus/AUTHORS
    trunk/Scribus/scribus/canvas.cpp
    trunk/Scribus/scribus/canvasmode.cpp
    trunk/Scribus/scribus/pageitem.cpp
    trunk/Scribus/scribus/pageitem.h
    trunk/Scribus/scribus/pageitem_pathtext.cpp
    trunk/Scribus/scribus/pageitem_textframe.cpp
    trunk/Scribus/scribus/pageitem_textframe.h
    trunk/Scribus/scribus/pdflib_core.cpp
    trunk/Scribus/scribus/pdflib_core.h
    trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.cpp
    trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.h
    trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.cpp
    trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.h
    trunk/Scribus/scribus/pslib.cpp
    trunk/Scribus/scribus/pslib.h
    trunk/Scribus/scribus/scpageoutput.cpp
    trunk/Scribus/scribus/scpageoutput.h
    trunk/Scribus/scribus/scpainter.cpp
    trunk/Scribus/scribus/scpainter.h
    trunk/Scribus/scribus/scribusdoc.cpp
    trunk/Scribus/scribus/scribusview.cpp
    trunk/Scribus/scribus/sctextstruct.cpp
    trunk/Scribus/scribus/sctextstruct.h
    trunk/Scribus/scribus/text/CMakeLists.txt
    trunk/Scribus/scribus/text/storytext.cpp
    trunk/Scribus/scribus/text/storytext.h
    trunk/Scribus/scribus/text/textlayout.cpp
    trunk/Scribus/scribus/text/textlayout.h

Modified: trunk/Scribus/AUTHORS
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/AUTHORS
==============================================================================
--- trunk/Scribus/AUTHORS	(original)
+++ trunk/Scribus/AUTHORS	Wed Mar 23 20:21:36 2016
@@ -71,6 +71,20 @@
 Giovanni Mugnai musical777 at gmail.com
 
 
+Refactoring text layout code and the new boxes model, Oman House of Open Source
+Technology team:
+
+Anood Almuharbi anood.almuharbi at gmail.com
+Asma ALbahanta as.bahanta at gmail.com
+Dawood Albadi daawood.albadi at gmail.com
+Ibrahim Alrashdi ibrahimalrashdi745 at gmail.com
+Ibtisam Nasser ibtisammabsali at gmail.com
+Khaled Hosny khaledhosny at eglug.org
+Noseeba noseeba1 at gmail.com
+Shamsa Hamed shamsahamed59 at gmail.com
+Sheikha sheikha443 at gmail.com
+
+
 Official Documentation:
 
 Peter Linnell plinnell at scribus.net

Modified: trunk/Scribus/scribus/canvas.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/canvas.cpp
==============================================================================
--- trunk/Scribus/scribus/canvas.cpp	(original)
+++ trunk/Scribus/scribus/canvas.cpp	Wed Mar 23 20:21:36 2016
@@ -2061,6 +2061,7 @@
 void Canvas::DrawPageIndicatorSub(ScPainter *p, ScPage *page)
 {
 	p->save();
+	int fm = p->fillMode();
 	p->setAntialiasing(false);
 	p->translate(page->xOffset(), page->yOffset());
 	double lineWidth = 1.0 / m_viewMode.scale;
@@ -2072,6 +2073,7 @@
 	p->setPen(PrefsManager::instance()->appPrefs.displayPrefs.pageBorderColor, 1 / m_viewMode.scale, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
 	p->drawRect(0, 0, pageWidth, pageHeight);
 	p->setAntialiasing(true);
+	p->setFillMode(fm);
 	p->restore();
 }
 

Modified: trunk/Scribus/scribus/canvasmode.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/canvasmode.cpp
==============================================================================
--- trunk/Scribus/scribus/canvasmode.cpp	(original)
+++ trunk/Scribus/scribus/canvasmode.cpp	Wed Mar 23 20:21:36 2016
@@ -1016,141 +1016,21 @@
 
 void CanvasMode::commonDrawTextCursor(QPainter* p, PageItem_TextFrame* textframe, const QPointF& offset)
 {
-	double dx, dy, dy1;
+	QLineF cursor;
 	QPen cPen ( Qt::black, 0.9 , Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin );
 
 	// normalize Current Position
 	textframe->itemText.normalizeCursorPosition();
 	int textCursorPos ( textframe->itemText.cursorPosition() );
-
-	if ( textframe->lastInFrame() >= textframe->itemText.length()
-		 || textframe->itemText.length() == 0 )
-	{
-		dx = textframe->textToFrameDistLeft();
-		dy = textframe->textToFrameDistTop();
-		dy1 = textframe->textToFrameDistTop() + (textframe->itemText.defaultStyle().charStyle().fontSize() / 10.0);
-
-		cPen.setColor ( ScColorEngine::getRGBColor ( m_doc->PageColors[textframe->itemText.defaultStyle().charStyle().fillColor() ], m_doc ) );
-	}
-	else if ( textCursorPos > textframe->lastInFrame() )
-	{
-		// Happens often when typing directly into frame.
-		// And the cursor curses nothing, vertigo.
-		textCursorPos = qMax(0, textframe->lastInFrame());
-		QChar textCursorChar = textframe->itemText.text(textCursorPos);
-		if (textCursorChar == SpecialChars::PARSEP || textCursorChar == SpecialChars::LINEBREAK)
-		{
-			// The cursor must be moved to the beginning of the next line
-			FRect bbox = textframe->textLayout.boundingBox ( textCursorPos );
-			double lineSpacing(textframe->itemText.paragraphStyle(textCursorPos).lineSpacing());
-
-			// take care if cursor is not in first column
-			int curCol(1);
-			double ccPos(textframe->textLayout.boundingBox ( textCursorPos ).x());
-			double leftOffset(textframe->textToFrameDistLeft());
-			for(int ci(1); ci <= textframe->columns(); ++ci)
-			{
-				double cLeft(((ci-1) * textframe->columnWidth()) + ((ci -1) * textframe->columnGap()) + leftOffset);
-				double cRight((ci * textframe->columnWidth()) + ((ci -1) * textframe->columnGap()) + leftOffset);
-				if((cLeft <= ccPos) && (ccPos <= cRight))
-				{
-					curCol = ci;
-					break;
-				}
-			}
-			dx = (textframe->columnWidth() * (curCol - 1)) + (textframe->columnGap() * (curCol - 1))  + leftOffset;
-			dy = bbox.y();
-
-			if ( bbox.height() <= 2 )
-				dy1 = bbox.y() + textframe->itemText.charStyle ( textCursorPos ).fontSize() / 30.0;
-			else
-				dy1 = bbox.y() + bbox.height();
-
-			dy  += lineSpacing;
-			dy1 += lineSpacing;
-		}
-		else if (textCursorChar == SpecialChars::COLBREAK)
-		{
-			// A bit tricky :)
-			// We want to position the cursor at the beginning of the next column, if any.
-			// At first we need to know in which column the cursor is.
-			int curCol(1);
-			double ccPos(textframe->textLayout.boundingBox ( textCursorPos ).x());
-			double leftOffset(textframe->textToFrameDistLeft());
-			for(int ci(1); ci <= textframe->columns(); ++ci)
-			{
-				double cLeft(((ci-1) * textframe->columnWidth()) + ((ci -1) * textframe->columnGap()) + leftOffset);
-				double cRight((ci * textframe->columnWidth()) + ((ci -1) * textframe->columnGap()) + leftOffset);
-				if((cLeft <= ccPos) && (ccPos <= cRight))
-				{
-					curCol = ci;
-					break;
-				}
-			}
-			if(textframe->columns() > curCol)
-			{
-				dx = (textframe->columnWidth() * curCol) + (textframe->columnGap() * curCol)  + leftOffset;
-				dy = textframe->textToFrameDistTop();
-				dy1 = textframe->textToFrameDistTop() + textframe->textLayout.boundingBox ( textCursorPos ).height();
-			}
-			else // there is no column after the current column
-			{
-				FRect bbox = textframe->textLayout.boundingBox ( textCursorPos );
-				dx = bbox.x();
-				dy = bbox.y();
-                dx += textframe->itemText.getGlyphs(textCursorPos)->wide();
-				if ( bbox.height() <= 2 )
-					dy1 = bbox.y() + textframe->itemText.charStyle ( textCursorPos ).fontSize() / 30.0;
-				else
-					dy1 = bbox.y() + bbox.height();
-			}
-		}
-		else
-		{
-			FRect bbox = textframe->textLayout.boundingBox ( textCursorPos );
-			dx = bbox.x();
-			dy = bbox.y();
-            dx += textframe->itemText.getGlyphs(textCursorPos)->wide();
-			if ( bbox.height() <= 2 )
-				dy1 = bbox.y() + textframe->itemText.charStyle ( textCursorPos ).fontSize() / 30.0;
-			else
-				dy1 = bbox.y() + bbox.height();
-
-		}
-		cPen.setColor ( ScColorEngine::getRGBColor ( m_doc->PageColors[textframe->itemText.charStyle ( textCursorPos ).fillColor() ], m_doc ) );
-	}
-	else
-	{
-		FRect bbox = textframe->textLayout.boundingBox ( textCursorPos );
-		dx = bbox.x();
-		dy = bbox.y();
-		if ( bbox.height() <= 2 )
-			dy1 = bbox.y() + textframe->itemText.charStyle ( textCursorPos ).fontSize() / 30.0;
-		else
-			dy1 = bbox.y() + bbox.height();
-
-		cPen.setColor ( ScColorEngine::getRGBColor ( m_doc->PageColors[textframe->itemText.charStyle ( textCursorPos ).fillColor() ], m_doc ) );
-	}
-	//handle Right to Left writing
-	if (textframe->imageFlippedH())
-		dx = textframe->width() - dx;
-	if (textframe->imageFlippedV())
-	{
-		dy  = textframe->height() - dy;
-		dy1 = textframe->height() - dy1;
-	}
+	cursor = textframe->textLayout.positionToPoint(textCursorPos);
+
+	cPen.setColor(ScColorEngine::getRGBColor(m_doc->PageColors[textframe->itemText.charStyle(textCursorPos).fillColor()], m_doc));
+
 	p->save();
 	p->setTransform(textframe->getTransform(), true);
 	p->setPen ( cPen );
 	p->setRenderHint ( QPainter::Antialiasing, true );
-	// avoid displaying the cursor on the frameborder
-	dx = qMax ( ( cPen.widthF() / 2.0 ), dx );
-
-	dy =  qMin ( qMax ( dy,0.0 ) , textframe->height() );
-	dy1 = qMin ( qMax ( dy1,0.0 ), textframe->height() );
-
-	p->drawLine ( QLineF ( dx,dy,dx,dy1 ).translated(offset) );
-
+	p->drawLine(cursor.translated(offset));
 	p->restore();
 }
 

Modified: trunk/Scribus/scribus/pageitem.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pageitem.cpp
==============================================================================
--- trunk/Scribus/scribus/pageitem.cpp	(original)
+++ trunk/Scribus/scribus/pageitem.cpp	Wed Mar 23 20:21:36 2016
@@ -2549,7 +2549,7 @@
 
 /**
     layout glyphs translates the chars into a number of glyphs, applying the Charstyle
-    'style'. The following fields are set in layout: glyph, more, scaleH, scaleV, xoffset, yoffset, xadvance.
+    'style'. The following fields are set in layout: glyph, scaleH, scaleV, xoffset, yoffset, xadvance.
     If the DropCap-bit in style.effects is set and yadvance is > 0, scaleH/V, x/yoffset and xadvance
     are modified to scale the glyphs to this height.
     Otherwise yadvance is set to the max ascender of all generated glyphs.
@@ -2557,9 +2557,9 @@
     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, LayoutFlags flags, GlyphLayout& layout)
-{
-	double retval = 0.0;
+GlyphLayout PageItem::layoutGlyphs(const CharStyle& style, const QString& chars, LayoutFlags flags)
+{
+	GlyphLayout gl;
 	const ScFace font = style.font();
 	double asce = font.ascent(style.fontSize() / 10.0);
 	int chst = style.effects() & ScStyle_UserStyles;
@@ -2578,36 +2578,34 @@
 	}
 	else */
 	{
-		layout.glyph = font.char2CMap(chars[0].unicode());
+		gl.glyph = font.char2CMap(chars[0].unicode());
 	}
 	double tracking = 0.0;
 	if ( (flags & ScLayout_StartOfLine) == 0)
 		tracking = style.fontSize() * style.tracking() / 10000.0;
 
-	layout.xoffset = tracking;
-	layout.yoffset = 0;
+	gl.xoffset = tracking;
+	gl.yoffset = 0;
 	if (chst != ScStyle_Default)
 	{
 		if (chst & ScStyle_Superscript)
 		{
-			retval -= asce * m_Doc->typographicPrefs().valueSuperScript / 100.0;
-			layout.yoffset -= asce * m_Doc->typographicPrefs().valueSuperScript / 100.0;
-			layout.scaleV = layout.scaleH = qMax(m_Doc->typographicPrefs().scalingSuperScript / 100.0, 10.0 / style.fontSize());
+			gl.yoffset -= asce * m_Doc->typographicPrefs().valueSuperScript / 100.0;
+			gl.scaleV = gl.scaleH = qMax(m_Doc->typographicPrefs().scalingSuperScript / 100.0, 10.0 / style.fontSize());
 		}
 		else if (chst & ScStyle_Subscript)
 		{
-			retval += asce * m_Doc->typographicPrefs().valueSubScript / 100.0;
-			layout.yoffset += asce * m_Doc->typographicPrefs().valueSubScript / 100.0;
-			layout.scaleV = layout.scaleH = qMax(m_Doc->typographicPrefs().scalingSubScript / 100.0, 10.0 / style.fontSize());
+			gl.yoffset += asce * m_Doc->typographicPrefs().valueSubScript / 100.0;
+			gl.scaleV = gl.scaleH = qMax(m_Doc->typographicPrefs().scalingSubScript / 100.0, 10.0 / style.fontSize());
 		}
 		else {
-			layout.scaleV = layout.scaleH = 1.0;
-		}
-		layout.scaleH *= style.scaleH() / 1000.0;
-		layout.scaleV *= style.scaleV() / 1000.0;
+			gl.scaleV = gl.scaleH = 1.0;
+		}
+		gl.scaleH *= style.scaleH() / 1000.0;
+		gl.scaleV *= style.scaleV() / 1000.0;
 		if (chst & ScStyle_AllCaps)
 		{
-			layout.glyph = font.char2CMap(chars[0].toUpper().unicode());
+			gl.glyph = font.char2CMap(chars[0].toUpper().unicode());
 		}
 		if (chst & ScStyle_SmallCaps)
 		{
@@ -2615,15 +2613,15 @@
 			QChar uc = chars[0].toUpper();
 			if (uc != chars[0])
 			{
-				layout.glyph = font.char2CMap(chars[0].toUpper().unicode());
-				layout.scaleV *= smallcapsScale;
-				layout.scaleH *= smallcapsScale;
+				gl.glyph = font.char2CMap(chars[0].toUpper().unicode());
+				gl.scaleV *= smallcapsScale;
+				gl.scaleH *= smallcapsScale;
 			}
 		}
 	}
 	else {
-		layout.scaleH = style.scaleH() / 1000.0;
-		layout.scaleV = style.scaleV() / 1000.0;
+		gl.scaleH = style.scaleH() / 1000.0;
+		gl.scaleV = style.scaleV() / 1000.0;
 	}	
 	
 /*	if (layout.glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode())) {
@@ -2642,311 +2640,13 @@
 	}
 	else */
 	{
-		layout.xadvance = font.glyphWidth(layout.glyph, style.fontSize() / 10) * layout.scaleH;
-		layout.yadvance = font.glyphBBox(layout.glyph, style.fontSize() / 10).ascent * layout.scaleV;
-	}
-	if (layout.xadvance > 0)
-		layout.xadvance += tracking;
-
-	if (chars.length() > 1) {
-		layout.grow();
-		layoutGlyphs(style, chars.mid(1), ScLayout_None, *layout.more);
-		layout.xadvance += font.glyphKerning(layout.glyph, layout.more->glyph, style.fontSize() / 10) * layout.scaleH;
-		if (layout.more->yadvance > layout.yadvance)
-			layout.yadvance = layout.more->yadvance;
-	}
-	else {
-		layout.shrink();
-	}
-	return retval;
-}
-
-void PageItem::drawGlyphs(ScPainter *p, const CharStyle& style, LayoutFlags flags, GlyphLayout& glyphs)
-{
-	uint glyph = glyphs.glyph;
-	const ScFace font = style.font();
-	if ((m_Doc->guidesPrefs().showControls) &&
-		(glyph == font.char2CMap(QChar(' ')) || glyph >=  ScFace::CONTROL_GLYPHS))
-	{
-		bool stroke = false;
-		if (glyph >=  ScFace::CONTROL_GLYPHS)
-			glyph -= ScFace::CONTROL_GLYPHS;
-		else
-			glyph = 32;
-		QTransform chma, chma4, chma5;
-		FPointArray points;
-		if (glyph == SpecialChars::TAB.unicode())
-		{
-			points = m_Doc->symTab.copy();
-			chma4.translate(glyphs.xoffset + glyphs.xadvance - ((style.fontSize() / 10.0) * glyphs.scaleH * 0.7), glyphs.yoffset - ((style.fontSize() / 10.0) * glyphs.scaleV * 0.5));
-		}
-		else if (glyph == SpecialChars::COLBREAK.unicode())
-		{
-			points = m_Doc->symNewCol.copy();
-			chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.6));
-		}
-		else if (glyph == SpecialChars::FRAMEBREAK.unicode())
-		{
-			points = m_Doc->symNewFrame.copy();
-			chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.6));
-		}
-		else if (glyph == SpecialChars::PARSEP.unicode())
-		{
-			points = m_Doc->symReturn.copy();
-			chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.8));
-		}
-		else if (glyph == SpecialChars::LINEBREAK.unicode())
-		{
-			points = m_Doc->symNewLine.copy();
-			chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.4));
-		}
-		else if (glyph == SpecialChars::NBSPACE.unicode() ||
-				 glyph == 32)
-		{
-			stroke = (glyph == 32);
-			points = m_Doc->symNonBreak.copy();
-			chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV * 0.4));
-		}
-		else if (glyph == SpecialChars::NBHYPHEN.unicode())
-		{
-			points = font.glyphOutline(font.char2CMap(QChar('-')), style.fontSize() / 100);
-			chma4.translate(glyphs.xoffset, glyphs.yoffset-((style.fontSize() / 10.0) * glyphs.scaleV));
-		}
-		else if (glyph == SpecialChars::SHYPHEN.unicode())
-		{
-			points.resize(0);
-			points.addQuadPoint(0, -10, 0, -10, 0, -6, 0, -6);
-			stroke = true;
-		}
-		else if (glyph == SpecialChars::OBJECT.unicode())
-		{
-			//for showing marks entries as control chars
-			points.resize(0);
-			points.addQuadPoint(0, -8, 1, -8, 0, -6, 1, -6);
-			stroke = true;
-		}
-		else // ???
-		{
-			points.resize(0);
-			points.addQuadPoint(0, -10, 0, -10, 0, -9, 0, -9);			
-			points.addQuadPoint(0, -9, 0, -9, 1, -9, 1, -9);			
-			points.addQuadPoint(1, -9, 1, -9, 1, -10, 1, -10);			
-			points.addQuadPoint(1, -10, 1, -10, 0, -10, 0, -10);			
-		}
-		chma.scale(glyphs.scaleH * style.fontSize() / 100.0, glyphs.scaleV * style.fontSize() / 100.0);
-		points.map(chma * chma4);
-		p->setupPolygon(&points, true);
-		QColor oldBrush = p->brush();
-		p->setBrush( (flags & ScLayout_SuppressSpace) ? Qt::green
-					: PrefsManager::instance()->appPrefs.displayPrefs.controlCharColor);
-		if (stroke)
-		{
-			QColor tmp = p->pen();
-			p->setPen(p->brush(), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-			p->setLineWidth(style.fontSize() * glyphs.scaleV / 200.0);
-			p->strokePath();
-			p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-		}
-		else
-		{
-			p->setFillMode(1);
-			p->fillPath();
-		}
-		p->setBrush(oldBrush);
-		if (glyphs.more)
-		{
-			p->translate(glyphs.xadvance, 0);
-			drawGlyphs(p, style, ScLayout_None, *glyphs.more);
-		}			
-		return;
-	}
-	else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode()) ||
-			 glyph == (ScFace::CONTROL_GLYPHS + 32)) 
-		glyph = font.char2CMap(QChar(' '));
-	else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode()))
-		glyph = font.char2CMap(QChar('-'));
-	
-	if (glyph >= ScFace::CONTROL_GLYPHS || (style.effects() & ScLayout_SuppressSpace)) {
-//		qDebug("drawGlyphs: skipping %d", glyph);
-		// all those are empty
-		if (glyphs.more)
-		{
-			p->translate(glyphs.xadvance, 0);
-			drawGlyphs(p, style, ScLayout_None, *glyphs.more);
-		}			
-		return;
-	}
-//	if (font.canRender(QChar(glyph)))
-	{
-		FPointArray gly = font.glyphOutline(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 != font.char2CMap(QChar(' ')))) && (style.strokeColor() != CommonStrings::None))
-		{
-			double st, lw;
-			if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1))
-			{
-				if (style.underlineOffset() != -1)
-					st = (style.underlineOffset() / 1000.0) * (font.descent(style.fontSize() / 10.0));
-				else
-					st = font.underlinePos(style.fontSize() / 10.0);
-				if (style.underlineWidth() != -1)
-					lw = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0);
-				else
-					lw = qMax(font.strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				st = font.underlinePos(style.fontSize() / 10.0);
-				lw = qMax(font.strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			if (style.baselineOffset() != 0)
-				st += (style.fontSize() / 10.0) * glyphs.scaleV * (style.baselineOffset() / 1000.0);
-			QColor tmpC = p->pen();
-			int oldStrokeMode = p->strokeMode();
-			p->setPen(p->brush());
-			p->setLineWidth(lw);
-			p->setStrokeMode(1);
-			if (style.effects() & ScStyle_Subscript)
-				p->drawLine(FPoint(glyphs.xoffset, glyphs.yoffset - st), FPoint(glyphs.xoffset + glyphs.xadvance, glyphs.yoffset - st));
-			else
-				p->drawLine(FPoint(glyphs.xoffset, -st), FPoint(glyphs.xoffset + glyphs.xadvance, -st));
-			p->setStrokeMode(oldStrokeMode);
-			p->setPen(tmpC);
-		}
-		if (gly.size() > 3)
-		{
-			if (glyph == 0)
-			{
-//				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(glyphs.xoffset, glyphs.yoffset - ((style.fontSize() / 10.0) * glyphs.scaleV));
-			if (m_isReversed)
-			{
-				p->scale(-1, 1);
-				p->translate(-glyphs.xadvance, 0);
-			}
-			if (style.baselineOffset() != 0)
-				p->translate(0, -(style.fontSize() / 10.0) * (style.baselineOffset() / 1000.0));
-			double glxSc = glyphs.scaleH * style.fontSize() / 100.00;
-			double glySc = glyphs.scaleV * style.fontSize() / 100.0;
-			p->scale(glxSc, glySc);
-//			p->setFillMode(1);
-			bool fr = p->fillRule();
-			p->setFillRule(false);
-//			double	a = gly.point(0).x();
-//			double	b = gly.point(0).y();
-//			double	c = gly.point(3).x();
-//			double	d = gly.point(3).y();
-//			qDebug() << QString("drawglyphs: %1 (%2,%3) (%4,%5) scaled %6,%7 trans %8,%9")
-//				   .arg(gly.size()).arg(a).arg(b).arg(c).arg(d)
-//				   .arg(p->worldMatrix().m11()).arg(p->worldMatrix().m22()).arg(p->worldMatrix().dx()).arg(p->worldMatrix().dy());
-			p->setupPolygon(&gly, true);
-			if (m_Doc->layerOutline(LayerID))
-			{
-				p->save();
-				p->setPen(m_Doc->layerMarker(LayerID), 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-				p->setFillMode(ScPainter::None);
-				p->setBrushOpacity(1.0);
-				p->setPenOpacity(1.0);
-				p->strokePath();
-				p->restore();
-				p->setFillRule(fr);
-				p->restore();
-				if (glyphs.more)
-				{
-					p->translate(glyphs.xadvance, 0);
-					drawGlyphs(p, style, ScLayout_None, *glyphs.more);
-				}
-				return;
-			}
-			if (glyph == 0)
-			{
-				p->setPen(PrefsManager::instance()->appPrefs.displayPrefs.controlCharColor, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-				p->setLineWidth(style.fontSize() * glyphs.scaleV * style.outlineWidth() * 2 / 10000.0);
-				p->strokePath();
-			}
-			else if ((font.isStroked()) && (style.strokeColor() != CommonStrings::None) && ((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) != 0))
-			{
-				QColor tmp = p->brush();
-				p->setStrokeMode(1);
-				p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-				p->setLineWidth(style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0);
-				p->strokePath();
-			}
-			else
-			{
-				if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None))
-				{
-					p->save();
-					p->translate((style.fontSize() * glyphs.scaleH * style.shadowXOffset() / 10000.0) / glxSc, -(style.fontSize() * glyphs.scaleV * style.shadowYOffset() / 10000.0) / glySc);
-					QColor tmp = p->brush();
-					p->setBrush(p->pen());
-					p->setupPolygon(&gly, true);
-					p->fillPath();
-					p->setBrush(tmp);
-					p->restore();
-					p->setupPolygon(&gly, true);
-				}
-				if (style.fillColor() != CommonStrings::None)
-					p->fillPath();
-				if ((style.effects() & ScStyle_Outline) && (style.strokeColor() != CommonStrings::None) && ((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) != 0))
-				{
-					p->setStrokeMode(1);
-					p->setLineWidth((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) / glySc);
-					p->strokePath();
-				}
-			}
-			p->setFillRule(fr);
-			p->restore();
-		}
-		else {
-//			qDebug() << "drawGlyphs: empty glyph" << glyph;
-		}
-		if ((style.effects() & ScStyle_Strikethrough) && (style.strokeColor() != CommonStrings::None))
-		{
-			double st, lw;
-			if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1))
-			{
-				if (style.strikethruOffset() != -1)
-					st = (style.strikethruOffset() / 1000.0) * (font.ascent(style.fontSize() / 10.0));
-				else
-					st = font.strikeoutPos(style.fontSize() / 10.0);
-				if (style.strikethruWidth() != -1)
-					lw = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0);
-				else
-					lw = qMax(font.strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				st = font.strikeoutPos(style.fontSize() / 10.0);
-				lw = qMax(font.strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			if (style.baselineOffset() != 0)
-				st += (style.fontSize() / 10.0) * glyphs.scaleV * (style.baselineOffset() / 1000.0);
-			int oldStrokeMode = p->strokeMode();
-			p->setPen(p->brush());
-			p->setLineWidth(lw);
-			p->setStrokeMode(1);
-			p->drawLine(FPoint(glyphs.xoffset, glyphs.yoffset - st), FPoint(glyphs.xoffset + glyphs.xadvance, glyphs.yoffset - st));
-			p->setStrokeMode(oldStrokeMode);
-		}
-	}
-/*	else
-	{
-		p->setLineWidth(1);
-		p->setPen(red);
-		p->setBrush(red);
-		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);
-	}
-	*/	
-	if (glyphs.more)
-	{
-		p->translate(glyphs.xadvance, 0);
-		drawGlyphs(p, style, ScLayout_None, *glyphs.more);
-	}
+		gl.xadvance = font.glyphWidth(gl.glyph, style.fontSize() / 10);
+		gl.yadvance = font.glyphBBox(gl.glyph, style.fontSize() / 10).ascent;
+	}
+	if (gl.xadvance > 0)
+		gl.xadvance += tracking;
+
+	return gl;
 }
 
 void PageItem::DrawPolyL(QPainter *p, QPolygon pts)

Modified: trunk/Scribus/scribus/pageitem.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pageitem.h
==============================================================================
--- trunk/Scribus/scribus/pageitem.h	(original)
+++ trunk/Scribus/scribus/pageitem.h	Wed Mar 23 20:21:36 2016
@@ -415,9 +415,8 @@
 	/// Return current text properties (current char + paragraph properties)
 	void currentTextProps(ParagraphStyle& parStyle) const;
 	// deprecated:
-	double layoutGlyphs(const CharStyle& style, const QString& chars, LayoutFlags flags, GlyphLayout& layout);
+	GlyphLayout layoutGlyphs(const CharStyle& style, const QString& chars, LayoutFlags flags);
 	void SetQColor(QColor *tmp, QString farbe, double shad);
-	void drawGlyphs(ScPainter *p, const CharStyle& style, LayoutFlags flags, GlyphLayout& glyphs );
 	void DrawPolyL(QPainter *p, QPolygon pts);
 	QString ExpandToken(uint base);
 	const FPointArray shape() const { return PoLine; }

Modified: trunk/Scribus/scribus/pageitem_pathtext.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pageitem_pathtext.cpp
==============================================================================
--- trunk/Scribus/scribus/pageitem_pathtext.cpp	(original)
+++ trunk/Scribus/scribus/pageitem_pathtext.cpp	Wed Mar 23 20:21:36 2016
@@ -46,6 +46,9 @@
 #include "undostate.h"
 #include "util.h"
 #include "util_math.h"
+#include "text/boxes.h"
+#include "text/textlayoutpainter.h"
+#include "text/screenpainter.h"
 
 using namespace std;
 
@@ -79,18 +82,8 @@
 	double dx;
 	FPoint point = FPoint(0, 0);
 	FPoint tangent = FPoint(0, 0);
-	QColor tmp;
 	CurX = m_textDistanceMargins.left();
-	QString cachedStroke = "";
-	QString cachedFill = "";
-	double cachedFillShade = -1;
-	double cachedStrokeShade = -1;
-	QString actStroke = "";
-	QString actFill = "";
-	double actFillShade = -1;
-	double actStrokeShade = -1;
-	QColor cachedFillQ;
-	QColor cachedStrokeQ;
+
 	if (!m_Doc->layerOutline(LayerID))
 	{
 		if (PoShow)
@@ -202,7 +195,6 @@
 	double wordExtra = 0;
 	for (a = firstChar; a < itemRenderText.length(); ++a)
 	{
-		GlyphLayout* glyphs = itemRenderText.getGlyphs(a);
 		chstr = itemRenderText.text(a, 1);
 		if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
 			|| chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK)
@@ -211,13 +203,11 @@
 			spaceCount++;
 		if (a < itemRenderText.length()-1)
 			chstr += itemRenderText.text(a+1, 1);
-		glyphs->yadvance = 0;
-		layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a), *glyphs);
-		glyphs->shrink();
+		GlyphLayout glyphs = layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a));
 		if (itemRenderText.hasObject(a))
-			totalTextLen += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH;
-		else
-			totalTextLen += glyphs->wide()+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0;
+			totalTextLen += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH;
+		else
+			totalTextLen += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0;
 	}
 	for (int segs = 0; segs < PoLine.size()-3; segs += 4)
 	{
@@ -252,10 +242,10 @@
 	QList<QPainterPath> pathList = decomposePath(guidePath);
 	QPainterPath currPath = pathList[0];
 	int currPathIndex = 0;
+	PathLineBox* linebox = new PathLineBox();
 	for (a = firstChar; a < itemRenderText.length(); ++a)
 	{
 		CurY = 0;
-		GlyphLayout* glyphs = itemRenderText.getGlyphs(a);
 		PathData* pdata = & (textLayout.point(a));
 		chstr = itemRenderText.text(a,1);
 		if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
@@ -263,15 +253,16 @@
 			continue;
 		if (a < itemRenderText.length()-1)
 			chstr += itemRenderText.text(a+1, 1);
-		glyphs->yadvance = 0;
-		layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a), *glyphs);
-		glyphs->shrink();                                                           // HACK
+
+		GlyphLayout glyphs = layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a));
+		GlyphRun run(&itemRenderText.charStyle(a), itemRenderText.flags(a), a, a, itemRenderText.object(a));
+		run.glyphs().append(glyphs);
+
 		if (itemRenderText.hasObject(a))
-			dx = (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH / 2.0;
-		else
-			dx = glyphs->wide() / 2.0;
+			dx = (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH / 2.0;
+		else
+			dx = glyphs.xadvance / 2.0;
 		CurX += dx;
-
 		double currPerc = currPath.percentAtLength(CurX);
 		if (currPerc >= 0.9999999)
 		{
@@ -293,7 +284,7 @@
 		QPointF currPoint = currPath.pointAtPercent(currPerc);
 		tangent = FPoint(cos(currAngle * M_PI / 180.0), sin(currAngle * M_PI / 180.0));
 		point = FPoint(currPoint.x(), currPoint.y());
-		glyphs->xoffset = 0;
+		glyphs.xoffset = 0;
 		pdata->PtransX = point.x();
 		pdata->PtransY = point.y();
 		pdata->PRot    = currAngle * M_PI / 180.0;
@@ -315,62 +306,55 @@
 			else
 				trafo *= QTransform( a, 4 * a, 0, -1, point.x(), point.y() );
 		}
-		QTransform sca = p->worldMatrix();
-		trafo *= sca;
-		p->save();
-		QTransform savWM = p->worldMatrix();
-		p->setWorldMatrix(trafo);
-		if (!m_Doc->RePos)
-		{
-			actFill = itemRenderText.charStyle(a).fillColor();
-			actFillShade = itemRenderText.charStyle(a).fillShade();
-			if (actFill != CommonStrings::None)
-			{
-				p->setFillMode(ScPainter::Solid);
-				if ((cachedFillShade != actFillShade) || (cachedFill != actFill))
-				{
-					SetQColor(&tmp, actFill, actFillShade);
-					p->setBrush(tmp);
-					cachedFillQ = tmp;
-					cachedFill = actFill;
-					cachedFillShade = actFillShade;
-				}
-				else
-					p->setBrush(cachedFillQ);
-			}
-			else
-				p->setFillMode(ScPainter::None);
-			actStroke = itemRenderText.charStyle(a).strokeColor();
-			actStrokeShade = itemRenderText.charStyle(a).strokeShade();
-			if (actStroke != CommonStrings::None)
-			{
-				if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke))
-				{
-					SetQColor(&tmp, actStroke, actStrokeShade);
-					p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-					cachedStrokeQ = tmp;
-					cachedStroke = actStroke;
-					cachedStrokeShade = actStrokeShade;
-				}
-				else
-					p->setPen(cachedStrokeQ, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-			}
-			p->translate(0.0, BaseOffs);
-			if (itemRenderText.hasObject(a))
-				DrawObj_Embedded(p, cullingArea, itemRenderText.charStyle(a), itemRenderText.object(a));
-			else
-				drawGlyphs(p, itemRenderText.charStyle(a), itemRenderText.flags(a), *glyphs);
-		}
-		p->setWorldMatrix(savWM);
-		p->restore();
+
+
+		const CharStyle& cStyle(run.style());
+		double scaleV = cStyle.scaleV() / 1000.0;
+		double offset = (cStyle.fontSize() / 10) * (cStyle.baselineOffset() / 1000.0);
+		double ascent = cStyle.font().ascent(cStyle.fontSize()/10.00) * scaleV + offset;
+		double descent = cStyle.font().descent(cStyle.fontSize()/10.00) * scaleV - offset;
+		linebox->setAscent(ascent);
+		linebox->setDescent(descent);
+		Box* box;
+		if (itemRenderText.hasObject(a))
+		{
+			box = new ObjectBox(run);
+			box->setAscent(run.object()->height() - run.object()->lineWidth());
+			box->setDescent(0);
+		}
+		else
+		{
+			box = new GlyphBox(run);
+			box->setAscent(linebox->ascent());
+			box->setDescent(linebox->descent());
+		}
+
+		box->setMatrix(trafo);
+		linebox->addBox(box);
+
+
 		MaxChars = a+1;
 		CurX -= dx;
 		if (itemRenderText.hasObject(a))
-			CurX += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH + extraOffset;
+			CurX += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH + extraOffset;
 		else if (chstr[0] == SpecialChars::BLANK)
-			CurX += glyphs->wide()+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0 + wordExtra + extraOffset;
-		else
-			CurX += glyphs->wide()+itemRenderText.charStyle(a).fontSize() *itemRenderText.charStyle(a).tracking() / 10000.0 + extraOffset;
+			CurX += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0 + wordExtra + extraOffset;
+		else
+			CurX += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() *itemRenderText.charStyle(a).tracking() / 10000.0 + extraOffset;
+	}
+
+	textLayout.addColumn(0, 0);
+	textLayout.appendLine(linebox);
+
+	if (!m_Doc->RePos)
+	{
+		int fm = p->fillMode();
+		p->setFillMode(1);
+		p->save();
+		ScreenPainter painter(p, this);
+		textLayout.render(&painter);
+		p->setFillMode(fm);
+		p->restore();
 	}
 }
 

Modified: trunk/Scribus/scribus/pageitem_textframe.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pageitem_textframe.cpp
==============================================================================
--- trunk/Scribus/scribus/pageitem_textframe.cpp	(original)
+++ trunk/Scribus/scribus/pageitem_textframe.cpp	Wed Mar 23 20:21:36 2016
@@ -55,6 +55,8 @@
 #include "scribusview.h"
 #include "scribusstructs.h"
 #include "selection.h"
+#include "text/boxes.h"
+#include "text/screenpainter.h"
 #include "ui/guidemanager.h"
 #include "ui/marksmanager.h"
 #include "undomanager.h"
@@ -346,7 +348,7 @@
 	stream << "scaleV"   << "\t";
 	stream << "\n";
 
-	for (int zc = line.firstItem; zc < line.lastItem; ++zc)
+	for (int zc = line.firstChar; zc < line.lastChar; ++zc)
 	{
 		const ScText* item = itemText.item(zc);
 
@@ -388,46 +390,6 @@
 }
 */
 
-/**
- Clones the tab fill char as often as necssary after all distances are known
- */
-static void fillInTabLeaders(StoryText & itemText, LineSpec & curLine)
-{
-	// fill in tab leaders
-	double xPos = curLine.x;
-	for (int ti= curLine.firstItem; ti <= curLine.lastItem; ++ti)
-	{
-		GlyphLayout* glyphs = itemText.getGlyphs(ti);
-		if (itemText.text(ti) == SpecialChars::TAB)
-		{
-			GlyphLayout * tglyph = glyphs->more;
-
-			if (!tglyph)
-				continue;
-
-			const CharStyle & charStyle(itemText.charStyle(ti));
-			double wt   = charStyle.font().glyphWidth(tglyph->glyph, charStyle.fontSize() * tglyph->scaleV / 10.0);
-			double len  = glyphs->xadvance;
-			int count   = static_cast<int>(len / wt);
-			double sPos = -len;
-			tglyph->xoffset = sPos;
-//			qDebug() << QString("tab leaders: %1 %2 width=%3 count=%4").arg(sPos).arg(curLine.y).arg(wt).arg(count);
-			for (int cx = 1; cx < count; ++cx)
-			{
-				// clone fillchar
-				tglyph->grow();
-				*(tglyph->more) = *tglyph;
-				tglyph->more->more = NULL;
-				tglyph = tglyph->more;
-				tglyph->xoffset =  sPos + wt * cx;
-			}
-		}
-		xPos += glyphs->wide();
-	}
-}
-
-
-
 enum TabStatus {
 	TabNONE    = 0,
 	TabLEFT    = TabNONE,
@@ -442,19 +404,36 @@
 fields which describe what type of tab is currently active
  */
 struct TabControl {
-	bool   active;
-	int    status;
-	int    charIndex;
-	double xPos;
-	QChar  fillChar;
+	bool         active;
+	int          status;
+	double       xPos;
+	QChar        fillChar;
+	GlyphLayout* tabGlyph;
+};
+
+struct LineSpec
+{
+	qreal x;
+	qreal y;
+	qreal width;
+	qreal ascent;
+	qreal descent;
+	qreal colLeft;
+
+	int firstRun;
+	int lastRun;
+	qreal naturalWidth;
+	bool isFirstLine;
+	qreal height;
 };
 
 /**
 fields which describe how the current line is placed into the frame
- */
+*/
 struct LineControl {
 	LineSpec line;
-	int      itemsInLine;
+	QList<GlyphRun>& glyphRuns;
+	bool     isEmpty;
 	int      hyphenCount;
 	double   colWidth;
 	double   colGap;
@@ -472,8 +451,8 @@
 	double   leftIndent;
 	double   rightMargin;
 	double   mustLineEnd;
-	int      restartIndex;  //index of char where line computing should be restarted
-	int      restartRowIndex;  //index of char where row of text is started
+	int      restartIndex;  //index of glyph run where line computing should be restarted
+	int      restartRowIndex;  //index of glyph run where row of text is started
 	double   restartX; //starting X position of line if must be restarted
 	double   rowDesc;
 
@@ -487,38 +466,36 @@
 
 	double   maxShrink;
 	double   maxStretch;
-
+	ScribusDoc *doc;
 
 	/// remember frame dimensions and offsets
-	void init(double w, double h, const MarginStruct& extra, double lCorr)
+	LineControl(double w, double h, const MarginStruct& extra, double lCorr, ScribusDoc* d, QList<GlyphRun>& runs, double colwidth, double colgap)
+		: glyphRuns(runs)
+		, hasDropCap(false)
+		, doc(d)
 	{
 		insets = extra;
 		lineCorr = lCorr;
 		frameWidth = w;
 		frameHeight = h;
-		hasDropCap = false;
-	}
-
-	/// start at column 0
-	void initColumns(double width, double gap)
-	{
 		column = 0;
-		colWidth = width;
-		colGap = gap;
+		colWidth = colwidth;
+		colGap = colgap;
+		hyphenCount = 0;
 	}
 
 	/// move position to next column
-	void nextColumn(double asce = 0.0)
+	void nextColumn(TextLayout &textLayout)
 	{
 		startOfCol = true;
 		colLeft = (colWidth + colGap) * column + insets.left() + lineCorr;
+		textLayout.addColumn(colLeft, colWidth);
 		//now colRight is REAL column right edge
 		colRight = colLeft + colWidth;
 		if (legacy)
 			colRight += lineCorr;
 		xPos = colLeft;
-		yPos = asce + insets.top() + lineCorr;
-		line.colLeft = colLeft;
+		yPos = insets.top() + lineCorr;
 	}
 
 	bool isEndOfCol(double morespace = 0)
@@ -529,19 +506,18 @@
 	/**
 		init fields for a new line at current position
 	 */
-	void startLine(int first)
-	{
-		itemsInLine = 0;
+	void startLine(int firstRun)
+	{
+		isEmpty = true;
 		line.x = xPos;
 		line.y = yPos;
-		line.firstItem = first;
-		line.lastItem = 0;
+		line.firstRun = firstRun;
+		line.lastRun = 0;
 		line.ascent = 0.0;
 		line.descent = 0.0;
 		line.width = 0.0;
 		line.naturalWidth = 0.0;
 		line.colLeft = colLeft;
-		line.isFirstLine = false;
 		breakIndex = -1;
 		breakXPos = 0.0;
 		maxShrink = 0.0;
@@ -586,18 +562,17 @@
 		breakXPos = pos;
 		breakIndex = index;
 	}
-	
+
 	/// called when a mandatory break is found
-	void breakLine(const StoryText& itemText, const ParagraphStyle& style, FirstLineOffsetPolicy offsetPolicy, int last)
+	void breakLine(const ParagraphStyle& style, FirstLineOffsetPolicy offsetPolicy, int last)
 	{
 		breakIndex = last;
 		breakXPos  = line.x;
-		for (int j = line.firstItem; j <= last; ++j)
-			if ( !itemText.hasFlag(j, ScLayout_SuppressSpace) )
-				breakXPos += itemText.getGlyphs(j)->wide();
+		for (int i = line.firstRun; i <= breakIndex; i++)
+			breakXPos += glyphRuns.at(i).width();
 		// #8194, #8717 : update line ascent and descent with sensible values
 		// so that endOfLine() returns correct result
-		updateHeightMetrics(itemText);
+		updateHeightMetrics();
 		// #9060 : update line offset too
 	//	updateLineOffset(itemText, style, offsetPolicy);
 	}
@@ -605,7 +580,7 @@
 	/// use the last remembered break to set line width and itemrange
 	void finishLine(double endX)
 	{
-		line.lastItem = breakIndex;
+		line.lastRun = breakIndex;
 		line.naturalWidth = breakXPos - line.x;
 		line.width = endX - line.x;
 		maxShrink = maxStretch = 0;
@@ -620,7 +595,7 @@
 		startLine(restartRowIndex);
 		addLeftIndent = true;
 		afterOverflow = false;
-		return restartRowIndex -1;
+		return restartRowIndex - 1;
 	}
 
 	int restartLine(bool recalcY, bool add)
@@ -630,7 +605,7 @@
 		xPos = restartX;
 		startLine(restartIndex);
 		afterOverflow = false;
-		return restartIndex -1;
+		return restartIndex - 1;
 	}
 
 	bool isEndOfLine(double moreSpace = 0)
@@ -732,147 +707,29 @@
 		return qMin(EndX2, maxX);
 	}
 
-	double getLineAscent(const StoryText& itemText)
-	{
-		double result = 0;
-		QChar firstChar = itemText.text (line.firstItem);
-		if ((firstChar == SpecialChars::PAGENUMBER) || (firstChar == SpecialChars::PAGECOUNT))
-			firstChar = '8';
-		PageItem *obj = itemText.object (line.firstItem);
-		const CharStyle& fcStyle(itemText.charStyle(line.firstItem));
-		if ((firstChar == SpecialChars::PARSEP) || (firstChar == SpecialChars::LINEBREAK))
-			result = fcStyle.font().ascent(fcStyle.fontSize() / 10.0);
-		else if (obj)
-			result = qMax(result, (obj->height() + obj->lineWidth()) * (fcStyle.scaleV() / 1000.0));
-		else
-			result = fcStyle.font().realCharAscent(firstChar, fcStyle.fontSize() / 10.0);
-		for (int zc = 0; zc < itemsInLine; ++zc)
-		{
-			QChar ch = itemText.text(line.firstItem + zc);
-			if ((ch == SpecialChars::PAGENUMBER) || (ch == SpecialChars::PAGECOUNT))
-				ch = '8'; // should have highest ascender even in oldstyle
-			const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc));
-			if ((ch == SpecialChars::TAB) || (ch == QChar(10))
-				|| SpecialChars::isBreak (ch, true) || (ch == SpecialChars::NBHYPHEN) || (ch.isSpace()))
-				continue;
-			double asce;
-			PageItem *obj = itemText.object (line.firstItem + zc);
-			if (obj)
-				asce = obj->height() + obj->lineWidth() * (cStyle.scaleV() / 1000.0);
-			else
-				asce = cStyle.font().realCharAscent(ch, cStyle.fontSize() / 10.0);
-			//	qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result);
-			result = qMax(result, asce);
-		}
-		return result;
-	}
-
-	double getLineDescent(const StoryText& itemText)
-	{
-		double result = 0;
-		QChar  firstChar = itemText.text(line.firstItem);
-		if ((firstChar == SpecialChars::PAGENUMBER) || (firstChar == SpecialChars::PAGECOUNT))
-			firstChar = '8';
-		const CharStyle& fcStyle(itemText.charStyle(line.firstItem));
-		if ((firstChar == SpecialChars::PARSEP) || (firstChar == SpecialChars::LINEBREAK))
-			result = fcStyle.font().descent(fcStyle.fontSize() / 10.0);
-		else if (itemText.object(line.firstItem))
-			result = 0.0;
-		else
-			result = fcStyle.font().realCharDescent(firstChar, fcStyle.fontSize() / 10.0);
-		for (int zc = 0; zc < itemsInLine; ++zc)
-		{
-			QChar ch = itemText.text(line.firstItem + zc);
-			if ((ch == SpecialChars::PAGENUMBER) || (ch == SpecialChars::PAGECOUNT))
-				ch = '8'; // should have highest ascender even in oldstyle
-			const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc));
-			if ((ch == SpecialChars::TAB) || (ch == QChar(10))
-				|| SpecialChars::isBreak (ch, true) || (ch == SpecialChars::NBHYPHEN) || (ch.isSpace()))
-				continue;
-			double desc;
-			if (itemText.object(line.firstItem + zc))
-				desc = 0.0;
-			else
-				desc = cStyle.font().realCharDescent(ch, cStyle.fontSize() / 10.0);
-			//	qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result);
-			result = qMax(result, desc);
-		}
-		return result;
-	}
-
-	double getLineHeight(const StoryText& itemText)
-	{
-		double result = 0;
-		const CharStyle& firstStyle(itemText.charStyle(line.firstItem));
-		PageItem *obj = itemText.object (line.firstItem);
-		if (obj)
-			result = qMax(result, (obj->height() + obj->lineWidth()) * (firstStyle.scaleV() / 1000.0));
-		else
-			result = firstStyle.font().height(firstStyle.fontSize() / 10.0);
-		for (int zc = 0; zc < itemsInLine; ++zc)
-		{
-			QChar ch = itemText.text(line.firstItem+zc);
-			if ((ch == SpecialChars::TAB) || (ch == QChar(10))
-				|| SpecialChars::isBreak (ch, true) || (ch == SpecialChars::NBHYPHEN) || (ch.isSpace()))
-				continue;
-			const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc));
-			PageItem *obj = itemText.object (line.firstItem + zc);
-			double asce;
-			if (obj)
-				asce = (obj->height() + obj->lineWidth()) * (cStyle.scaleV() / 1000.0);
-			else
-				asce = cStyle.font().height (cStyle.fontSize() / 10.0);
-			//	qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result);
-			result = qMax(result, asce);
-		}
-		return result;
-	}
-
-	void updateHeightMetrics(const StoryText& itemText)
-	{
-		double asce, desc, hei;
-		line.ascent  = 0;
-		line.descent = 0;
-		line.height = 0;
-		for (int zc = 0; zc < itemsInLine; ++zc)
-		{
-			QChar ch = itemText.text(line.firstItem+zc);
-			if ((ch == SpecialChars::TAB) || (ch == QChar(10))
-				|| SpecialChars::isBreak (ch, true) || (ch == SpecialChars::NBHYPHEN) || (ch.isSpace()))
-				continue;
-			const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc));
-			double scaleV = cStyle.scaleV() / 1000.0;
-			double offset = (cStyle.fontSize() / 10) * (cStyle.baselineOffset() / 1000.0);
-
-			if (itemText.object(line.firstItem+zc) != 0)
-			{
-				asce = (itemText.object(line.firstItem+zc)->height() + itemText.object(line.firstItem+zc)->lineWidth()) * scaleV + offset;
-				desc = 0.0;
-				hei = asce;
-			}
-			else //if ((itemText.flags(current.line.firstItem+zc) & ScLayout_DropCap) == 0)
-			{
-				asce = cStyle.font().realCharAscent(ch, cStyle.fontSize() / 10.0) * scaleV + offset;
-				desc = cStyle.font().realCharDescent(ch, cStyle.fontSize() / 10.0) * scaleV - offset;
-				hei = cStyle.font().height(cStyle.fontSize() / 10.0) * scaleV;
-			}
-			//	qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result);
-			line.ascent  = qMax(line.ascent, asce);
-			line.descent = qMax(line.descent, desc);
-			line.height = qMax(line.height, hei);
-		}
+	void updateHeightMetrics()
+	{
+		line.ascent = line.descent = 0;
+		// Can happen when inserting a new line at end of text, WTF!
+		if (line.firstRun >= glyphRuns.length())
+			return;
+		const CharStyle& cStyle(glyphRuns.at(line.firstRun).style());
+		double scaleV = cStyle.scaleV() / 1000.0;
+		double offset = (cStyle.fontSize() / 10) * (cStyle.baselineOffset() / 1000.0);
+		line.ascent = cStyle.font().ascent(cStyle.fontSize()/10.00) * scaleV + offset;
+		line.descent = cStyle.font().descent(cStyle.fontSize()/10.00) * scaleV - offset;
 	}
 
 // yPos should not be changed when all line is already calculated - at new y position there can be overflow!!!
 // edit: can't happen as it should only move upwards, and this is covered by the calculations done.
 //void updateLineOffset(const StoryText& itemText, const ParagraphStyle& style, FirstLineOffsetPolicy offsetPolicy)
 //{
-//	if (itemsInLine <= 0)
+//	if (charsInLine <= 0)
 //		return;
 //	if ((!hasDropCap) && (startOfCol) && (style.lineSpacingMode() != ParagraphStyle::BaselineGridLineSpacing))
 //	{
 //		//FIXME: use glyphs, not chars
-//		double firstasce = itemText.charStyle(line.firstItem).font().ascent(itemText.charStyle(line.firstItem).fontSize() / 10.0);
+//		double firstasce = itemText.charStyle(line.firstChar).font().ascent(itemText.charStyle(line.firstChar).fontSize() / 10.0);
 //		double adj (0.0);
 //		double currasce (this->getLineAscent(itemText));
 //		if (offsetPolicy == FLOPRealGlyphHeight)
@@ -893,16 +750,50 @@
 //	}
 //	else if ((!startOfCol) && (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing))
 //	{
-//		QChar ch = itemText.text(line.firstItem);
+//		QChar ch = itemText.text(line.firstChar);
 //		double firstasce = style.lineSpacing();
 //		double currasce  = getLineHeight(itemText);
 //		double adj = firstasce - currasce;
-//		qDebug() << QString("move2 line %1.. down by %2").arg(current.line.firstItem).arg(-adj);
+//		qDebug() << QString("move2 line %1.. down by %2").arg(current.line.firstChar).arg(-adj);
 //		line.ascent = currasce;
 //		line.y -= adj;
 //		yPos -= adj;
 //	}
 //}
+
+	LineBox* createLineBox()
+	{
+		LineBox* result = new LineBox();
+		result->moveTo(line.x - colLeft, line.y);
+		result->setWidth(line.width);
+		result->setAscent(line.ascent);
+		result->setDescent(line.descent);
+
+		for (int i = line.firstRun; i <= line.lastRun; ++i)
+		{
+			addBox(result, glyphRuns.at(i));
+		}
+
+		return result;
+	}
+
+	void addBox(LineBox *lineBox, const GlyphRun& run)
+	{
+		Box* result;
+		if (run.object())
+		{
+			result = new ObjectBox(run);
+			result->setAscent(run.object()->height() - run.object()->lineWidth());
+			result->setDescent(0);
+		}
+		else
+		{
+			result = new GlyphBox(run);
+			result->setAscent(lineBox->ascent());
+			result->setDescent(lineBox->descent());
+		}
+		lineBox->addBox(result);
+	}
 
 private:
 	double frameWidth;
@@ -910,6 +801,34 @@
 	MarginStruct insets;
 	double lineCorr;
 };
+
+/**
+ Clones the tab fill char as often as necssary after all distances are known
+ */
+static void fillInTabLeaders(LineControl & current)
+{
+	// fill in tab leaders
+	for(int i = current.line.firstRun; i <= current.line.lastRun; i++)
+	{
+		GlyphRun& glyphRun = current.glyphRuns[i];
+		CharStyle charStyle(glyphRun.style());
+		if (glyphRun.hasFlag(ScLayout_TabLeaders))
+		{
+			GlyphLayout tglyph = glyphRun.glyphs().last();
+			double width = glyphRun.width();
+			double wt = charStyle.font().glyphWidth(tglyph.glyph, charStyle.fontSize() * tglyph.scaleV / 10.0);
+			int count = static_cast<int>(width / wt);
+			glyphRun.glyphs().clear();
+			for(int cx = 0; cx < count; ++cx)
+			{
+				GlyphLayout more = tglyph;
+				more.xadvance = width / count;
+				glyphRun.glyphs().append(more);
+			}
+		}
+	}
+}
+
 
 static bool checkCJK(QChar ch) {
 	unsigned int code = ch.unicode();
@@ -957,10 +876,6 @@
 	return true;
 }
 
-static bool implicitSpace(QChar f, QChar s) {
-	return checkCJK(f) && checkCJK(s);
-}
-
 static bool implicitBreak(QChar f, QChar s) {
 	if (checkCJK(f) && checkCJK(s)) {
 		return allowedCJKBreakAfter(f) && allowedCJKBreakBefore(s);
@@ -969,7 +884,7 @@
 }
 
 /// called when line length is known and line is to be justified
-static void justifyLine(StoryText& itemText, LineSpec& line)
+static void justifyLine(const ParagraphStyle& style, LineControl& curr)
 {
 
 	double glyphNatural = 0;
@@ -979,24 +894,21 @@
 	int spaceInsertion = 0;
 	double imSpace = -1;
 
-	const ParagraphStyle& style(itemText.paragraphStyle(line.firstItem));
-
-	// measure natural widths for glyphs and spaces
-	for (int sof = line.firstItem; sof <= line.lastItem; ++sof)
-	{
-		GlyphLayout* glyph = itemText.getGlyphs(sof);
-		QChar ch = itemText.text(sof);
-		if (!SpecialChars::isExpandingSpace(ch))
-		{
-			glyphNatural += glyph->wide();
-		}
-		else if ( !itemText.hasFlag(sof, ScLayout_SuppressSpace) )
-		{
-			spaceNatural += glyph->wide();
-			if (imSpace < 0.0 || imSpace > glyph->wide())
-				imSpace = glyph->wide();
-		}
-		if (sof != line.firstItem && implicitSpace(itemText.text(sof - 1), ch)) {
+	for (int i = curr.line.firstRun; i <= curr.line.lastRun; ++i)
+	{
+		GlyphRun glyphrun = curr.glyphRuns[i];
+		if (!glyphrun.hasFlag(ScLayout_ExpandingSpace))
+		{
+			glyphNatural += glyphrun.width();
+		}
+		else if ( !glyphrun.hasFlag(ScLayout_SuppressSpace) )
+		{
+			spaceNatural += glyphrun.width();
+			if (imSpace < 0.0 || imSpace > glyphrun.width())
+				imSpace = glyphrun.width();
+		}
+		if (i != curr.line.firstRun && glyphrun.hasFlag(ScLayout_ImplicitSpace))
+		{
 			spaceInsertion += 1;
 		}
 	}
@@ -1005,23 +917,23 @@
 
 	// decision: prio 1: stretch glyph;  prio 2: insert spaces;  prio 3: stretch spaces
 
-	if (line.width < spaceNatural + glyphNatural * style.minGlyphExtension() && spaceNatural > 0)
+	if (curr.line.width < spaceNatural + glyphNatural * style.minGlyphExtension() && spaceNatural > 0)
 	{
 		glyphExtension = style.minGlyphExtension() - 1;
-		spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural  - 1;
+		spaceExtension = (curr.line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural  - 1;
 		imSpace = 0;
 	}
-	else if (line.width < spaceNatural + glyphNatural * style.maxGlyphExtension() && glyphNatural > 0)
+	else if (curr.line.width < spaceNatural + glyphNatural * style.maxGlyphExtension() && glyphNatural > 0)
 	{
 		spaceExtension = 0;
-		glyphExtension = (line.width - spaceNatural) / glyphNatural  - 1;
+		glyphExtension = (curr.line.width - spaceNatural) / glyphNatural  - 1;
 		imSpace = 0;
 	}
 	else
 	{
 		glyphExtension = style.maxGlyphExtension() - 1;
 		if (spaceInsertion) {
-			double remaining = line.width - glyphNatural * (1 + glyphExtension) - spaceNatural;
+			double remaining = curr.line.width - glyphNatural * (1 + glyphExtension) - spaceNatural;
 			if (imSpace > 0) {
 				if (remaining / spaceInsertion < imSpace) {
 					imSpace = remaining / spaceInsertion;
@@ -1036,7 +948,7 @@
 			}
 		} else {
 			if (spaceNatural > 0)
-				spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural  - 1;
+				spaceExtension = (curr.line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural  - 1;
 			else
 				spaceExtension = 0;
 		}
@@ -1051,47 +963,51 @@
 		   .arg(style.minWordTracking()).arg(style.minGlyphExtension());
 	*/
 
-	int startItem = line.firstItem;
-	if (itemText.hasFlag(startItem, ScLayout_DropCap))
+	int startItem = curr.line.firstRun;
+	if (curr.glyphRuns[startItem].hasFlag(ScLayout_DropCap))
 		startItem++;
 	// distribute whitespace on spaces and glyphs
-	for (int yof = startItem; yof <= line.lastItem; ++yof)
-	{
-		GlyphLayout* glyph = itemText.getGlyphs(yof);
-		QChar ch = itemText.text(yof);
-		double wide = glyph->wide();
-		if (!SpecialChars::isExpandingSpace(ch))
-		{
-			glyph->last()->xadvance += wide * glyphExtension;
-			while (glyph)
-			{
-				glyph->xoffset *= glyphScale;
-				glyph->scaleH *= glyphScale;
-				glyph = glyph->more;
-			}
-		}
-		else if (!itemText.hasFlag(yof, ScLayout_SuppressSpace))
-		{
-			glyph->last()->xadvance += wide * spaceExtension;
-		}
-		if (yof != line.firstItem && implicitSpace(itemText.text(yof - 1), ch)) {
-			itemText.getGlyphs(yof - 1)->last()->xadvance += imSpace;
+
+	for (int i = startItem; i <= curr.line.lastRun; ++i)
+	{
+		GlyphRun& glyphrun = curr.glyphRuns[i];
+		if (i != curr.line.firstRun && glyphrun.hasFlag(ScLayout_ImplicitSpace))
+		{
+			GlyphRun& lastRun = curr.glyphRuns[i-1];
+			lastRun.glyphs().last().xadvance += imSpace;
+		}
+		double wide = glyphrun.width();
+		if (!glyphrun.hasFlag(ScLayout_ExpandingSpace))
+		{
+			for (int j = 0; j < glyphrun.glyphs().count(); ++j)
+			{
+				GlyphLayout& glyph = glyphrun.glyphs()[j];
+				glyph.xadvance += wide * glyphExtension;
+				glyph.xoffset *= glyphScale;
+				glyph.scaleH *= glyphScale;
+			}
+		}
+		else if (!glyphrun.hasFlag(ScLayout_SuppressSpace))
+		{
+			GlyphLayout& glyph = glyphrun.glyphs().last();
+			glyph.xadvance += wide * spaceExtension;
+
 		}
 	}
 }
 
 
 /// called when linelength is known and line is not justified
-static void indentLine(StoryText& itemText, LineSpec& line, double leftIndent)
+static void indentLine(const ParagraphStyle& style, LineControl& curr, double leftIndent)
 {
-	if (line.naturalWidth > line.width)
-	{
-		justifyLine(itemText, line);
+	if (curr.line.naturalWidth > curr.line.width)
+	{
+		justifyLine(style, curr);
 	}
 	if (leftIndent > 0)
 	{
-		line.x += leftIndent;
-		line.width -= leftIndent;
+		curr.line.x += leftIndent;
+		curr.line.width -= leftIndent;
 	}
 }
 
@@ -1099,8 +1015,8 @@
 ///// calculate how much the first char should stick out to the left
 //static double opticalLeftMargin(const StoryText& itemText, const LineSpec& line)
 //{
-//	int b = line.firstItem;
-//	while (b < line.lastItem && (itemText.flags(b)) & ScLayout_SuppressSpace))
+//	int b = line.firstChar;
+//	while (b < line.lastChar && (itemText.flags(b) & ScLayout_SuppressSpace))
 //		   ++b;
 //
 //	double chs = itemText.charStyle(b).fontSize() * (itemText.charStyle(b).scaleH() / 1000.0);
@@ -1135,19 +1051,20 @@
 //}
 
 /// calculate how much the last char should stick out to the right
-static double opticalRightMargin(const StoryText& itemText, const LineSpec& line)
+static double opticalRightMargin(const StoryText& itemText, const QList<GlyphRun> runs, const LineSpec& line)
 {
-	int b = line.lastItem;
-	while (b > line.firstItem &&
-		   (SpecialChars::isBreakingSpace(itemText.text(b)) || SpecialChars::isBreak(itemText.text(b)))
+	int b = line.lastRun;
+	while (b > line.firstRun &&
+		   (SpecialChars::isBreakingSpace(itemText.text(runs[b].firstChar())) ||
+			SpecialChars::isBreak(itemText.text(runs[b].firstChar())))
 		   )
 		--b;
-	if (b >= line.firstItem)
-	{
-		const CharStyle& chStyle(itemText.charStyle(b));
+	if (b >= line.firstRun)
+	{
+		const CharStyle& chStyle(runs[b].style());
 		double chs = chStyle.fontSize() * (chStyle.scaleH() / 1000.0);
-		QChar chr = itemText.hasFlag(b, ScLayout_SoftHyphenVisible) ?
-			QChar('-') : itemText.text(b);
+		QChar chr = runs[b].hasFlag(ScLayout_SoftHyphenVisible) ?
+			QChar('-') : itemText.text(runs[b].firstChar());
 		double rightCorr = chStyle.font().realCharWidth(chr, chs / 10.0);
 		if (QString("-,.`´'~").indexOf(chr) >= 0
 			|| chr == QChar(0x2018)
@@ -1309,6 +1226,154 @@
 	}
 }
 
+QList<GlyphRun> PageItem_TextFrame::shapeText()
+{
+	// maps expanded characters to itemText tokens.
+	QMap<int, int> textMap;
+	QString text;
+	for (int i = firstInFrame(); i < itemText.length(); ++i)
+	{
+		Mark* mark = itemText.mark(i);
+		if (itemText.hasMark(i))
+		{
+			mark->OwnPage = OwnPage;
+			//itemPtr and itemName set to this frame only if mark type is different than MARK2ItemType
+			if (!mark->isType(MARK2ItemType))
+			{
+				mark->setItemPtr(this);
+				mark->setItemName(itemName());
+			}
+
+			//anchors and indexes has no visible inserts in text
+			if (mark->isType(MARKAnchorType) || mark->isType(MARKIndexType))
+				continue;
+
+			//set note marker charstyle
+			if (mark->isNoteType())
+			{
+				TextNote* note = mark->getNotePtr();
+				if (note == NULL)
+					continue;
+				mark->setItemPtr(this);
+				NotesStyle* nStyle = note->notesStyle();
+				Q_ASSERT(nStyle != NULL);
+				QString chsName = nStyle->marksChStyle();
+				CharStyle currStyle(itemText.charStyle(i));
+				if (!chsName.isEmpty())
+				{
+					CharStyle marksStyle(m_Doc->charStyle(chsName));
+					if (!currStyle.equiv(marksStyle))
+					{
+						currStyle.setParent(chsName);
+						itemText.applyCharStyle(i, 1, currStyle);
+					}
+				}
+
+				StyleFlag s(itemText.charStyle(i).effects());
+				if (mark->isType(MARKNoteMasterType))
+				{
+					if (nStyle->isSuperscriptInMaster())
+						s |= ScStyle_Superscript;
+					else
+						s &= ~ScStyle_Superscript;
+				}
+				else
+				{
+					if (nStyle->isSuperscriptInNote())
+						s |= ScStyle_Superscript;
+					else
+						s &= ~ScStyle_Superscript;
+				}
+				if (s != itemText.charStyle(i).effects())
+				{
+					CharStyle haveSuperscript;
+					haveSuperscript.setFeatures(s.featureList());
+					itemText.applyCharStyle(i, 1, haveSuperscript);
+				}
+			}
+		}
+
+		bool bullet = false;
+		if (i == 0 || itemText.text(i - 1) == SpecialChars::PARSEP)
+		{
+			ParagraphStyle style = itemText.paragraphStyle(i);
+			if (style.hasBullet() || style.hasNum())
+			{
+				bullet = true;
+				if (mark == NULL || !mark->isType(MARKBullNumType))
+				{
+					itemText.insertMark(new BulNumMark(), i);
+					i--;
+					continue;
+				}
+				if (style.hasBullet())
+					mark->setString(style.bulletStr());
+				else if (style.hasNum() && mark->getString().isEmpty())
+				{
+					mark->setString("?");
+					m_Doc->flag_Renumber = true;
+				}
+			}
+		}
+
+		if (!bullet && mark && mark->isType(MARKBullNumType))
+		{
+			itemText.removeChars(i, 1);
+			i--;
+			continue;
+		}
+
+		QString str = ExpandToken(i);
+		if (str.isEmpty())
+			str = SpecialChars::ZWNBSPACE;
+
+		for (int j = 0; j < str.length(); j++)
+			textMap.insert(text.length() + j, i);
+
+		text.append(str);
+	}
+
+	QList<GlyphRun> glyphRuns;
+	glyphRuns.reserve(text.length());
+	for (int i = 0; i < text.length(); i++)
+	{
+		const QChar ch(text.at(i));
+		int a = textMap.value(i);
+
+		GlyphRun run(&itemText.charStyle(a), itemText.flags(a), a, a, itemText.object(a));
+		if (SpecialChars::isExpandingSpace(ch))
+			run.setFlag(ScLayout_ExpandingSpace);
+
+		GlyphLayout gl = layoutGlyphs(run.style(), QString(ch), itemText.flags(a));
+
+		if (!glyphRuns.isEmpty())
+		{
+			GlyphLayout& last = glyphRuns.last().glyphs().last();
+			last.xadvance += run.style().font().glyphKerning(last.glyph, gl.glyph, run.style().fontSize() / 10) * last.scaleH;
+		}
+
+		//show control characters for marks
+		if (itemText.hasMark(a))
+		{
+			GlyphLayout control;
+			control.glyph = SpecialChars::OBJECT.unicode() + ScFace::CONTROL_GLYPHS;
+			run.glyphs().append(control);
+		}
+
+		if (SpecialChars::isExpandingSpace(ch))
+			gl.xadvance *= run.style().wordTracking();
+
+		if (itemText.hasObject(a))
+			gl.xadvance = itemText.object(a)->width() + itemText.object(a)->lineWidth();
+
+		run.glyphs().append(gl);
+
+		glyphRuns.append(run);
+	}
+
+	return glyphRuns;
+}
+
 void PageItem_TextFrame::layout()
 {
 // 	qDebug()<<"==Layout==" << itemName() ;
@@ -1342,10 +1407,7 @@
 	QPoint pt1, pt2;
 	QRect pt;
 	double chs, chsd = 0;
-	double EndX, OFs, wide, kernVal;
-	QString chstr;
-	QChar currentCh;
-	GlyphLayout* glyphs;
+	double EndX, OFs;
 	ParagraphStyle style;
 	int opticalMargins = ParagraphStyle::OM_None;
 
@@ -1356,7 +1418,7 @@
 	TabControl tabs;
 	tabs.active    = false;     // RTab
 	tabs.status    = TabNONE;   // TabCode
-	tabs.charIndex = -1;        // StartRT
+	tabs.tabGlyph  = 0;         // was int charIndex ~ StartRT
 	tabs.xPos      = 0;         // RTabX
 
 	QList<ParagraphStyle::TabRecord> tTabValues;
@@ -1378,14 +1440,6 @@
 	if (lineColor() != CommonStrings::None)
 		lineCorr = m_lineWidth / 2.0;
 
-	// TODO: refactor this into PageItem
-	MarginStruct savedTextDistanceMargins(m_textDistanceMargins);
-
-	LineControl current;
-	current.init(m_width, m_height, m_textDistanceMargins, lineCorr);
-	current.initColumns(columnWidth(), ColGap);
-	current.hyphenCount = 0;
-
 	//hold Y position of last computed line of text (with glyphs descent)
 	//for moving next line if glyphs are higher than that
 	double lastLineY = 0;
@@ -1456,7 +1510,11 @@
 			m_availableRegion = matrix.map(m_availableRegion);
 		}
 
-		current.nextColumn();
+		QList<GlyphRun> glyphRuns = shapeText();
+
+		LineControl current(m_width, m_height, m_textDistanceMargins, lineCorr, m_Doc, glyphRuns, columnWidth(), ColGap);
+		current.nextColumn(textLayout);
+
 		lastLineY = m_textDistanceMargins.top();
 
 		//automatic line spacing factor (calculated once)
@@ -1486,13 +1544,13 @@
 			desc = -itemText.defaultStyle().charStyle().font().descent(itemText.defaultStyle().charStyle().fontSize() / 10.0);
 			current.yPos = itemText.defaultStyle().lineSpacing() + m_textDistanceMargins.top() + lineCorr - desc;
 		}
-		current.startLine(firstInFrame());
+		current.startLine(0);
 
 		outs = false;
 		OFs = 0;
 		MaxChars = 0;
 		double realEnd = 0;
-		current.restartIndex = current.restartRowIndex = firstInFrame();
+		current.restartIndex = current.restartRowIndex = 0;
 		current.afterOverflow = false;
 		current.addLine = false;
 		current.recalculateY = true;
@@ -1513,81 +1571,35 @@
 		int regionMinY = 0, regionMaxY= 0;
 
 		double autoLeftIndent = 0.0;
-
-		for (int a = firstInFrame(); a < itLen; ++a)
-		{
-			currentCh = itemText.text(a);
-			glyphs = itemText.getGlyphs(a);
+		for (int i = 0; i < glyphRuns.length(); ++i)
+		{
+			if (glyphRuns[i].glyphs().isEmpty())
+				continue;
+
+			int a = glyphRuns[i].firstChar();
 			bool HasObject = itemText.hasObject(a);
-			PageItem* currentObject = HasObject? itemText.object(a): NULL;
+			PageItem* currentObject = itemText.object(a);
 			bool HasMark = itemText.hasMark(a);
-			Mark* mark = itemText.mark(a);
+
+			if (itemText.charStyle(a).effects() & ScStyle_UnderlineWords)
+			{
+				CharStyle tmp(itemText.charStyle(a));
+				StyleFlag effects = tmp.effects();
+				if (!itemText.text(a).isSpace())
+					effects |= ScStyle_Underline;
+				effects &= ~ScStyle_UnderlineWords;
+				tmp.setFeatures(effects.featureList());
+				itemText.applyCharStyle(a, 1, tmp);
+			}
 
 			if (HasMark)
 			{
-				//show control characters for marks
-				glyphs->glyph = SpecialChars::OBJECT.unicode() + ScFace::CONTROL_GLYPHS;
-
-				mark->OwnPage = OwnPage;
-				//itemPtr and itemName set to this frame only if mark type is different than MARK2ItemType
-				if (!mark->isType(MARK2ItemType))
-				{
-					mark->setItemPtr(this);
-					mark->setItemName(itemName());
-				}
-				//anchors and indexes has no visible inserts in text
-				if (mark->isType(MARKAnchorType) || mark->isType(MARKIndexType))
-				{
-					glyphs->shrink();
-					continue;
-				}
+				Mark* mark = itemText.mark(a);
 				//store mark pointer and position in text
 				if (mark->isType(MARKNoteMasterType))
 					noteMarksPosMap.insert(a, mark);
-				//set note marker charstyle
-				if (mark->isNoteType())
-				{
-					TextNote* note = mark->getNotePtr();
-					if (note == NULL)
-						continue;
-					mark->setItemPtr(this);
-					NotesStyle* nStyle = note->notesStyle();
-						Q_ASSERT(nStyle != NULL);
-					QString chsName = nStyle->marksChStyle();
-					CharStyle currStyle(itemText.charStyle(a));
-					if (!chsName.isEmpty())
-					{
-						CharStyle marksStyle(m_Doc->charStyle(chsName));
-						if (!currStyle.equiv(marksStyle))
-						{
-							currStyle.setParent(chsName);
-							itemText.applyCharStyle(a, 1, currStyle);
-						}
-					}
-
-					StyleFlag s(itemText.charStyle(a).effects());
-					if (mark->isType(MARKNoteMasterType))
-					{
-						if (nStyle->isSuperscriptInMaster())
-							s |= ScStyle_Superscript;
-						else
-							s &= ~ScStyle_Superscript;
-					}
-					else
-					{
-						if (nStyle->isSuperscriptInNote())
-							s |= ScStyle_Superscript;
-						else
-							s &= ~ScStyle_Superscript;
-					}
-					if (s != itemText.charStyle(a).effects())
-					{
-						CharStyle haveSuperscript;
-						haveSuperscript.setFeatures(s.featureList());
-						itemText.applyCharStyle(a, 1, haveSuperscript);
-					}
-				}
-			}
+			}
+
 			BulNumMode = false;
 			if (a==0 || itemText.text(a-1) == SpecialChars::PARSEP)
 			{
@@ -1596,37 +1608,13 @@
 				if (style.hasBullet() || style.hasNum())
 				{
 					BulNumMode = true;
-					if (mark == NULL || !mark->isType(MARKBullNumType))
-					{
-						BulNumMark* bnMark = new BulNumMark();
-						itemText.insertMark(bnMark,a);
-						a--;
-						itLen = itemText.length();
-						continue;
-					}
-					if (style.hasBullet())
-						mark->setString(style.bulletStr());
-					else if (style.hasNum())
-					{
-						if (mark->getString().isEmpty())
-						{
-							mark->setString("?");
-							m_Doc->flag_Renumber = true;
-						}
-					}
-				}
-			}
-			if (!BulNumMode && mark && mark->isType(MARKBullNumType))
-			{
-				itemText.removeChars(a,1);
-				a--;
-				itLen = itemText.length();
-				continue;
-			}
-			if (current.itemsInLine == 0)
+				}
+			}
+
+			if (current.isEmpty)
 				opticalMargins = style.opticalMargins();
 			//-->#13490
-			if (isNoteFrame() && !mark)
+			if (isNoteFrame() && !HasMark)
 			{
 				StyleFlag s(itemText.charStyle(a).effects());
 				s &= ~ScStyle_Superscript;
@@ -1636,12 +1624,8 @@
 			}
 			//--<#13490
 			CharStyle charStyle = ((itemText.text(a) != SpecialChars::PARSEP) ? itemText.charStyle(a) : style.charStyle());
-			chstr = ExpandToken(a);
-			int chstrLen = chstr.length();
-			if (chstr.isEmpty())
-				chstr = SpecialChars::ZWNBSPACE;
-
-			curStat = SpecialChars::getCJKAttr(currentCh);
+
+			curStat = SpecialChars::getCJKAttr(itemText.text(a));
 			//set style for paragraph effects
 			if (a == 0 || itemText.text(a-1) == SpecialChars::PARSEP)
 			{
@@ -1678,7 +1662,7 @@
 			{
 				if (a == 0 || itemText.text(a-1) == SpecialChars::PARSEP)
 				{
-					if (currentCh != SpecialChars::PARSEP)
+					if (itemText.text(a) != SpecialChars::PARSEP)
 					{
 						DropCmode = style.hasDropCap();
 						if (DropCmode)
@@ -1692,20 +1676,20 @@
 
 			const ScFace font = charStyle.font();
 
-			itemText.clearFlag(a, ScLayout_DropCap);
-			itemText.clearFlag(a, ScLayout_SoftHyphenVisible);
+			glyphRuns[i].clearFlag(ScLayout_DropCap);
+			glyphRuns[i].clearFlag(ScLayout_SoftHyphenVisible);
 
 			// No space at begin of line,
 			if (legacy)
 			{
 				// unless at begin of par (eeks)
-				if ( (current.itemsInLine == 0) && (SpecialChars::isBreakingSpace(currentCh))
+				if ( (current.isEmpty) && (SpecialChars::isBreakingSpace(itemText.text(a)))
 					 && (a > 0 && ! SpecialChars::isBreak(itemText.text(a-1)))
 					 && ! (a > 0 && SpecialChars::isBreakingSpace(itemText.text(a-1))
-						   && (!itemText.hasFlag(a-1, ScLayout_SuppressSpace))))
-				{
-					itemText.setFlag(a, ScLayout_SuppressSpace);
-					glyphs->xadvance = 0;
+						   && (!glyphRuns[i - 1].hasFlag(ScLayout_SuppressSpace))))
+				{
+					glyphRuns[i].setFlag(ScLayout_SuppressSpace);
+					glyphRuns[i].glyphs().first().xadvance = 0;
 					continue;
 				}
 				else
@@ -1713,16 +1697,16 @@
 			}
 			else // from 134 on use NBSPACE for this effect
 			{
-				if ( current.itemsInLine == 0 && (SpecialChars::isBreakingSpace(currentCh) || currentCh.isSpace()))
-				{
-					itemText.setFlag(a, ScLayout_SuppressSpace);
-					glyphs->xadvance = 0;
+				if ( current.isEmpty && (SpecialChars::isBreakingSpace(itemText.text(a)) || itemText.text(a).isSpace()))
+				{
+					glyphRuns[i].setFlag(ScLayout_SuppressSpace);
+					glyphRuns[i].glyphs()[0].xadvance = 0;
 					continue;
 				}
 				else
 					itemText.clearFlag(a, ScLayout_SuppressSpace);
 			}
-			if (current.itemsInLine == 0)
+			if (current.isEmpty)
 			{
 				if (style.rightMargin() == 0)
 				{
@@ -1745,7 +1729,7 @@
 					if (!current.afterOverflow && current.recalculateY && !current.startOfCol)
 						current.yPos += style.gapBefore();
 					DropCapDrop = 0;
-					if (chstr[0] != SpecialChars::PARSEP)
+					if (itemText.text(a) != SpecialChars::PARSEP)
 						DropCmode = style.hasDropCap();
 					else
 						DropCmode = false;
@@ -1770,10 +1754,10 @@
 				//text height, width, ascent and descent should be calculated for whole text provided by ScText in current position
 				//and that may be more than one char (variable text for example)
 				double realCharHeight = 0.0, realCharAscent = 0.0;
-				for (int i = 0; i < chstrLen; ++i)
-				{
-					realCharHeight = qMax(realCharHeight, font.realCharHeight(chstr[i], 1));
-					realCharAscent = qMax(realCharAscent, font.realCharAscent(chstr[i], 1));
+				foreach (GlyphLayout gl, glyphRuns[i].glyphs()) {
+					GlyphMetrics gm = font.glyphBBox(gl.glyph);
+					realCharHeight = qMax(realCharHeight, gm.ascent + gm.descent);
+					realCharAscent = qMax(realCharAscent, gm.ascent);
 				}
 				double fontAscent = font.ascent(style.charStyle().fontSize() / 10.0);
 				if (realCharHeight == 0.0)
@@ -1782,8 +1766,8 @@
 					realCharAscent = fontAscent;
 				chsd = (10 * ((DropCapDrop + fontAscent) / realCharHeight));
 				chs  = (10 * ((DropCapDrop + fontAscent) / realCharAscent));
-				itemText.setFlag(a, ScLayout_DropCap);
-				glyphs->yoffset -= DropCapDrop;
+				glyphRuns[i].setFlag(ScLayout_DropCap);
+				glyphRuns[i].glyphs().first().yoffset += DropCapDrop;
 				if (HasObject)
 				{
 					chs = qRound((currentObject->height() + currentObject->lineWidth()) * 10);
@@ -1797,113 +1781,92 @@
 				else
 					chs = charStyle.fontSize();
 			}
-			// set StartOfLine (and find tracking?)
-			if (current.itemsInLine == 0)
-			{
-				itemText.setFlag(a, ScLayout_StartOfLine);
-				kernVal = 0;
+			// set StartOfLine
+			if (current.isEmpty)
+			{
+				glyphRuns[i].setFlag(ScLayout_StartOfLine);
 			}
 			else
 			{
-				kernVal = 0; // chs * charStyle.tracking() / 10000.0;
-				itemText.clearFlag(a, ScLayout_StartOfLine);
-			}
-			glyphs->yadvance = 0;
-			layoutGlyphs(charStyle, chstr, itemText.flags(a), *glyphs);
-
-			// find out width, ascent and descent of char
-			if (HasObject)
-			{
-				wide = currentObject->width() + currentObject->lineWidth();
-				glyphs->xadvance = wide * glyphs->scaleH;
-			}
-			else
-			{
-				wide = glyphs->wide();
-				// apply kerning
-				if (a+1 < itemText.length())
-				{
-					uint glyph2 = font.char2CMap(itemText.text(a+1));
-					double kern = font.glyphKerning(glyphs->last()->glyph, glyph2, chs / 10.0) * glyphs->scaleH;
-					wide += kern;
-					glyphs->last()->xadvance += kern;
-					// change xadvance, xoffset according to JIS X4051
-					int nextStat = SpecialChars::getCJKAttr(itemText.text(a+1));
-					int prevStat;
-					if (curStat != 0)
-					{	// current char is CJK
-						if (nextStat == 0 && !SpecialChars::isBreakingSpace(itemText.text(a+1))){
-							switch(curStat & SpecialChars::CJK_CHAR_MASK){
-							case SpecialChars::CJK_KANJI:
-							case SpecialChars::CJK_KANA:
-							case SpecialChars::CJK_NOTOP:
-								kern = charStyle.fontSize() / 10 / 4;
-								wide += kern;
-								glyphs->last()->xadvance += kern;
-							}
-						} else {	// next char is CJK, too
-							switch(curStat & SpecialChars::CJK_CHAR_MASK){
+				glyphRuns[i].clearFlag(ScLayout_StartOfLine);
+			}
+//			glyphs->yadvance = 0;
+
+			GlyphLayout& firstGlyph = glyphRuns[i].glyphs().first();
+			GlyphLayout& lastGlyph = glyphRuns[i].glyphs().last();
+
+			// apply cjk kerning
+			//TODO: cjk spacing and kerning should be done in layoutGlyphs!
+			if (i + 1 < glyphRuns.length())
+			{
+				GlyphRun nextRun = glyphRuns[i + 1];
+				// change xadvance, xoffset according to JIS X4051
+				int nextStat = SpecialChars::getCJKAttr(itemText.text(nextRun.firstChar()));
+				if (curStat != 0)
+				{	// current char is CJK
+					if (nextStat == 0 && !SpecialChars::isBreakingSpace(itemText.text(nextRun.firstChar()))){
+						switch(curStat & SpecialChars::CJK_CHAR_MASK){
+						case SpecialChars::CJK_KANJI:
+						case SpecialChars::CJK_KANA:
+						case SpecialChars::CJK_NOTOP:
+							lastGlyph.xadvance += charStyle.fontSize() / 10 / 4;
+						}
+					} else {	// next char is CJK, too
+						switch(curStat & SpecialChars::CJK_CHAR_MASK){
+						case SpecialChars::CJK_FENCE_END:
+							switch(nextStat & SpecialChars::CJK_CHAR_MASK){
+							case SpecialChars::CJK_FENCE_BEGIN:
 							case SpecialChars::CJK_FENCE_END:
-								switch(nextStat & SpecialChars::CJK_CHAR_MASK){
-								case SpecialChars::CJK_FENCE_BEGIN:
-								case SpecialChars::CJK_FENCE_END:
-								case SpecialChars::CJK_COMMA:
-								case SpecialChars::CJK_PERIOD:
-								case SpecialChars::CJK_MIDPOINT:
-									kern = -charStyle.fontSize() / 10 / 2;
-									wide += kern;
-									glyphs->last()->xadvance += kern;
-								}
-								break;
 							case SpecialChars::CJK_COMMA:
 							case SpecialChars::CJK_PERIOD:
-								switch(nextStat & SpecialChars::CJK_CHAR_MASK){
-								case SpecialChars::CJK_FENCE_BEGIN:
-								case SpecialChars::CJK_FENCE_END:
-									kern = -charStyle.fontSize() / 10 / 2;
-									wide += kern;
-									glyphs->last()->xadvance += kern;
-								}
-								break;
 							case SpecialChars::CJK_MIDPOINT:
-								switch(nextStat & SpecialChars::CJK_CHAR_MASK){
-								case SpecialChars::CJK_FENCE_BEGIN:
-									kern = -charStyle.fontSize() / 10 / 2;
-									wide += kern;
-									glyphs->last()->xadvance += kern;
-								}
-								break;
+								lastGlyph.xadvance -= charStyle.fontSize() / 10 / 2;
+							}
+							break;
+						case SpecialChars::CJK_COMMA:
+						case SpecialChars::CJK_PERIOD:
+							switch(nextStat & SpecialChars::CJK_CHAR_MASK){
 							case SpecialChars::CJK_FENCE_BEGIN:
-								if (a == current.line.firstItem){ // first char of the line
-									prevStat = SpecialChars::CJK_FENCE_BEGIN;
-								} else {
-									prevStat = SpecialChars::getCJKAttr(itemText.text(a-1)) & SpecialChars::CJK_CHAR_MASK;
-								}
-								if (prevStat == SpecialChars::CJK_FENCE_BEGIN){
-									kern = -charStyle.fontSize() / 10 / 2;
-									wide += kern;
-									glyphs->last()->xadvance += kern;
-									glyphs->last()->xoffset += kern;
-								}
-								break;
+							case SpecialChars::CJK_FENCE_END:
+								lastGlyph.xadvance -= charStyle.fontSize() / 10 / 2;;
 							}
-
+							break;
+						case SpecialChars::CJK_MIDPOINT:
+							switch(nextStat & SpecialChars::CJK_CHAR_MASK){
+							case SpecialChars::CJK_FENCE_BEGIN:
+								lastGlyph.xadvance -= charStyle.fontSize() / 10 / 2;
+							}
+							break;
+						case SpecialChars::CJK_FENCE_BEGIN:
+							int prevStat = 0;
+							if (i == current.line.firstRun){ // first char of the line
+								prevStat = SpecialChars::CJK_FENCE_BEGIN;
+							} else if (i != 0) {
+								prevStat = SpecialChars::getCJKAttr(itemText.text(glyphRuns[i - 1].lastChar())) & SpecialChars::CJK_CHAR_MASK;
+							}
+							if (prevStat == SpecialChars::CJK_FENCE_BEGIN){
+								lastGlyph.xadvance -= charStyle.fontSize() / 10 / 2;
+								lastGlyph.xoffset -= charStyle.fontSize() / 10 / 2;
+							}
+							break;
 						}
-					} else {	// current char is not CJK
-						if (nextStat != 0 && !SpecialChars::isBreakingSpace(currentCh)){
-							switch(nextStat & SpecialChars::CJK_CHAR_MASK){
-							case SpecialChars::CJK_KANJI:
-							case SpecialChars::CJK_KANA:
-							case SpecialChars::CJK_NOTOP:
-								// use the size of the current char instead of the next one
-								kern = charStyle.fontSize() / 10 / 4;
-								wide += kern;
-								glyphs->last()->xadvance += kern;
-							}
+					}
+				} else {	// current char is not CJK
+					if (nextStat != 0 && !SpecialChars::isBreakingSpace(itemText.text(glyphRuns[i].lastChar()))){
+						switch(nextStat & SpecialChars::CJK_CHAR_MASK){
+						case SpecialChars::CJK_KANJI:
+						case SpecialChars::CJK_KANA:
+						case SpecialChars::CJK_NOTOP:
+							// use the size of the current char instead of the next one
+							lastGlyph.xadvance += charStyle.fontSize() / 10 / 4;
 						}
 					}
 				}
 			}
+
+			// find out width, ascent and descent of char
+			double wide = glyphRuns[i].width();
+
 			if (DropCmode)
 			{
 				// drop caps are wider...
@@ -1912,22 +1875,23 @@
 					double itemHeight = currentObject->height() + currentObject->lineWidth();
 					if (itemHeight == 0)
 						itemHeight = font.height(style.charStyle().fontSize() / 10.0);
-					wide = currentObject->width() + currentObject->lineWidth();
 					asce = currentObject->height() + currentObject->lineWidth();
 					realAsce = calculateLineSpacing (style, this) * DropLines;
-					glyphs->scaleH /= glyphs->scaleV;
-					glyphs->scaleV = (realAsce / itemHeight);
-					glyphs->scaleH *= glyphs->scaleV;
+					firstGlyph.scaleH /= firstGlyph.scaleV;
+					firstGlyph.scaleV = (realAsce / itemHeight);
+					firstGlyph.scaleH *= firstGlyph.scaleV;
 				}
 				else
 				{
 					double realCharHeight = 0.0;
 					wide = 0.0; realAsce = 0.0;
-					for (int i = 0; i < chstrLen; ++i)
-					{
-						realCharHeight = qMax(realCharHeight, font.realCharHeight(chstr[i], charStyle.fontSize() / 10.0));
-						realAsce = qMax(realAsce, font.realCharHeight(chstr[i], chsd / 10.0));
-						wide += font.realCharWidth(chstr[i], chsd / 10.0);
+					foreach (GlyphLayout gl, glyphRuns[i].glyphs()) {
+						GlyphMetrics gm;
+						gm = font.glyphBBox(gl.glyph, charStyle.fontSize() / 10.0);
+						realCharHeight = qMax(realCharHeight, gm.ascent + gm.descent);
+						gm = font.glyphBBox(gl.glyph, chsd / 10.0);
+						realAsce = qMax(realAsce, gm.ascent + gm.descent);
+						wide += gm.width;
 					}
 					wide = (wide* scaleH) + (1 - scaleH);
 					realAsce = realAsce  * scaleV + offset;
@@ -1935,37 +1899,33 @@
 						realCharHeight = font.height(style.charStyle().fontSize() / 10.0);
 					asce = font.ascent(hlcsize10);
 					// qDebug() QString("dropcaps pre: chsd=%1 realCharHeight = %2 chstr=%3").arg(chsd).arg(asce).arg(chstr2[0]);
-					glyphs->scaleH /= glyphs->scaleV;
-					glyphs->scaleV = (realAsce / realCharHeight);
-					glyphs->scaleH *= glyphs->scaleV;
-					glyphs->xoffset -= 0.5; //drop caps are always to far from column left edge
-				}
-				glyphs->xadvance = wide;
+					firstGlyph.scaleH /= firstGlyph.scaleV;
+					firstGlyph.scaleV = (realAsce / realCharHeight);
+					firstGlyph.scaleH *= firstGlyph.scaleV;
+					firstGlyph.xoffset -= 0.5; //drop caps are always to far from column left edge
+				}
+				firstGlyph.xadvance = wide / firstGlyph.scaleH;
 				desc = realDesc = 0;
 			}
 			else // !DropCMode
 			{
-				if (SpecialChars::isExpandingSpace(currentCh))
-				{
-					double wordtracking = charStyle.wordTracking();
-					glyphs->xadvance *= wordtracking;
-					wide *= wordtracking;
-				}
 				// find ascent / descent
 				if (HasObject)
 					desc = realDesc = 0;
 				else
 				{
-					for (int i = 0; i < chstrLen; ++i)
+					if (itemText.text(a) != SpecialChars::OBJECT)
 					{
-						if (chstr[i] == SpecialChars::OBJECT)
-							continue;
-						realDesc = qMax(realDesc, font.realCharDescent(chstr[i], hlcsize10));
-						realAsce = font.realCharAscent(chstr[i], hlcsize10);
-					}
+						foreach (GlyphLayout gl, glyphRuns[i].glyphs()) {
+							GlyphMetrics gm = font.glyphBBox(gl.glyph, hlcsize10);
+							realDesc = qMax(realDesc, gm.descent);
+							realAsce = gm.ascent;
+						}
+					}
+
 					realDesc =  realDesc * scaleV - offset;
 					desc = -font.descent(hlcsize10);
-					current.rememberShrinkStretch(currentCh, wide, style);
+					current.rememberShrinkStretch(itemText.text(a), wide, style);
 				}
 				if (HasObject)
 				{
@@ -1979,15 +1939,15 @@
 						realAsce = asce * scaleV + offset;
 					else
 					{
-						for (int i = 0; i < chstrLen; ++i)
-							realAsce = qMax(realAsce, font.realCharAscent(chstr[i], hlcsize10) * scaleV + offset);
+						foreach (GlyphLayout gl, glyphRuns[i].glyphs())
+							realAsce = qMax(realAsce, font.glyphBBox(gl.glyph, hlcsize10).ascent * scaleV + offset);
 					}
 				}
 			}
 //			if (BulNumMode)
 //				hl->glyph.last()->xadvance += style.parEffectOffset();
 			//check for Y position at beginning of line
-			if (current.itemsInLine == 0 && !current.afterOverflow)
+			if (current.isEmpty && !current.afterOverflow)
 			{
 				if (current.recalculateY)
 				{
@@ -1996,7 +1956,7 @@
 					{
 						lastLineY = qMax(lastLineY, m_textDistanceMargins.top() + lineCorr);
 						//fix for proper rendering first empty line (only with PARSEP)
-						if (chstr[0] == SpecialChars::PARSEP)
+						if (itemText.text(a) == SpecialChars::PARSEP)
 							current.yPos += style.lineSpacing();
 						if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing || FlopBaseline)
 						{
@@ -2101,7 +2061,7 @@
 				regionMaxY = static_cast<int>(floor(current.yPos + desc));
 			}
 
-			if (current.itemsInLine == 0 && !current.afterOverflow)
+			if (current.isEmpty && !current.afterOverflow)
 			{
 				//start a new line
 				goNoRoom = false;
@@ -2219,25 +2179,27 @@
 				}
 				if (newColumn)
 				{
-					current.nextColumn();
+					current.nextColumn(textLayout);
 					current.mustLineEnd = current.colRight;
 					current.restartX = current.xPos;
 					lastLineY = current.yPos;
 					current.rowDesc = 0;
-					a--;
+					i--;
 					current.recalculateY = true;
 					current.addLeftIndent = true;
 					continue;
 				}
 				current.line.x = current.restartX = current.xPos;
 				current.line.y = current.yPos;
+				if (glyphRuns[current.line.firstRun].hasFlag(ScLayout_DropCap))
+					current.line.y -= DropCapDrop;
 			}
 
 			//check if line must start at new Y position due to current glyph height or previous line descent
-			if (!SpecialChars::isBreak(currentCh, true)
-				&& !SpecialChars::isBreakingSpace(currentCh)
-				&& !SpecialChars::isExpandingSpace(currentCh)
-				&& currentCh != SpecialChars::TAB)
+			if (!SpecialChars::isBreak(itemText.text(a), true)
+				&& !SpecialChars::isBreakingSpace(itemText.text(a))
+				&& !SpecialChars::isExpandingSpace(itemText.text(a))
+				&& itemText.text(a) != SpecialChars::TAB)
 			{
 				double diff = 0;
 				if (current.startOfCol || DropCmode)
@@ -2247,7 +2209,7 @@
 					if (HasObject)
 						diff = (currentObject->height() + currentObject->lineWidth()) * scaleV + offset - (current.yPos - lastLineY);
 					else
-						diff = font.realCharAscent(QChar('l'), hlcsize10) * scaleV + offset - (current.yPos - lastLineY);
+						diff = font.capHeight(hlcsize10) * scaleV + offset - (current.yPos - lastLineY);
 				}
 				else
 				{
@@ -2290,21 +2252,21 @@
 							maxDY = 0;
 						}
 					}
-					a = current.restartRow(false);
+					i = current.restartRow(false);
 					continue;
 				}
 			}
 			// right tab stuff
 			if (tabs.active)
 			{
-				if (((currentCh == '.') && (tabs.status == TabPOINT)) || ((currentCh == ',') && (tabs.status == TabCOMMA)) || (currentCh == SpecialChars::TAB))
+				if (((itemText.text(a) == '.') && (tabs.status == TabPOINT)) || ((itemText.text(a) == ',') && (tabs.status == TabCOMMA)) || (itemText.text(a) == SpecialChars::TAB))
 				{
 					tabs.active = false;
 					tabs.status = TabNONE;
 				}
 			}
 			// tab positioning
-			if (currentCh == SpecialChars::TAB)
+			if (itemText.text(a) == SpecialChars::TAB)
 			{
 				wide = 1;
 				if (tabs.active)
@@ -2342,23 +2304,19 @@
 						}
 
 						// remember fill char
-						if (!tabs.fillChar.isNull()) {
-							glyphs->growWithTabLayout();
-							TabLayout * tglyph = dynamic_cast<TabLayout*>(glyphs->more);
-							if (tglyph)
-							{
-								tglyph->fillChar = tabs.fillChar;
-								tglyph->glyph    = font.char2CMap(tabs.fillChar);
-								tglyph->yoffset  = glyphs->yoffset;
-								tglyph->scaleV   = tglyph->scaleH = chs / charStyle.fontSize();
-								tglyph->xadvance = 0;
-							}
+						if (!tabs.fillChar.isNull())
+						{
+								glyphRuns[i].setFlag(ScLayout_TabLeaders);
+								GlyphLayout tglyph;
+								tglyph.glyph	= font.char2CMap(tabs.fillChar);
+								tglyph.yoffset  = firstGlyph.yoffset;
+								tglyph.scaleV   = tglyph.scaleH = chs / charStyle.fontSize();
+								tglyph.xadvance = 0;
+								glyphRuns[i].glyphs().append(tglyph);
 						}
 					}
-					current.xPos -= (legacy ? 1.0 : 0.0);
-					glyphs->xadvance = current.xPos + wide + kernVal - tabs.xPos;
-//					wide = current.xPos - RTabX;
-					tabs.charIndex = a;
+					firstGlyph.xadvance = current.xPos + wide - tabs.xPos;
+					tabs.tabGlyph = &firstGlyph;
 				}
 			}
 
@@ -2366,20 +2324,20 @@
 			if (DropCmode)
 			{
 				double yoffset = 0.0;
-				for (int i = 0; i < chstrLen; ++i)
-					yoffset = qMax(yoffset, font.realCharHeight(chstr[i], chsd / 10.0) - font.realCharAscent(chstr[i], chsd / 10.0));
-				glyphs->yoffset -= yoffset;
+				foreach (GlyphLayout gl, glyphRuns[i].glyphs())
+					yoffset = qMax(yoffset, font.glyphBBox(gl.glyph, chsd / 10.0).descent);
+				firstGlyph.yoffset -= yoffset;
 			}
 			// remember x pos
 			double breakPos = current.xPos;
 
 			if (!tabs.active) // normal case
 			{
-				current.xPos += wide+kernVal;
+				current.xPos += wide;
 			}
 			else if (tabs.active && tabs.status == TabCENTER) 	// center tab
 			{
-				current.xPos += (wide+kernVal) / 2;
+				current.xPos += wide / 2;
 				current.xPos = qMax(current.xPos, current.colLeft);
 			}
 			else // other tabs.active
@@ -2387,17 +2345,17 @@
 				current.xPos = qMax(current.xPos, current.colLeft);
 			}
 			// remember possible break
-			if ( (SpecialChars::isBreakingSpace(currentCh) || currentCh == SpecialChars::TAB))
+			if ( (SpecialChars::isBreakingSpace(itemText.text(a)) || itemText.text(a) == SpecialChars::TAB))
 			{
 				if ( a == firstInFrame() || !SpecialChars::isBreakingSpace(itemText.text(a-1)) )
 				{
-					current.rememberBreak(a, breakPos, style.rightMargin());
+					current.rememberBreak(i, breakPos, style.rightMargin());
 				}
 			}
 			if  (HasObject)
-				current.rememberBreak(a, breakPos, style.rightMargin());
+				current.rememberBreak(i, breakPos, style.rightMargin());
 			// CJK break
-			if (a > current.line.firstItem)
+			if (i > current.line.firstRun)
 			{ // not the first char
 				if ((lastStat == 0) && (curStat == 0))
 				{	// both non-CJK
@@ -2406,7 +2364,7 @@
 					// non-CJK char does not have CJK_NOBREAK_AFTER/CJK_NOBREAK_BEFORE
 					if ((lastStat & SpecialChars::CJK_NOBREAK_AFTER) == 0 &&
 							(curStat & SpecialChars::CJK_NOBREAK_BEFORE) == 0){
-						current.rememberBreak(a-1, breakPos, style.rightMargin());
+						current.rememberBreak(i-1, breakPos, style.rightMargin());
 					}
 				}
 
@@ -2423,17 +2381,18 @@
 			double overflowWidth = 0.0;
 			double hyphWidth = 0.0;
 			bool inOverflow = false;
-			if (itemText.hasFlag(a,ScLayout_HyphenationPossible) || currentCh == SpecialChars::SHYPHEN)
+			if (glyphRuns[i].hasFlag(ScLayout_HyphenationPossible) || itemText.text(a) == SpecialChars::SHYPHEN)
 				hyphWidth = font.charWidth('-', hlcsize10) * (charStyle.scaleH() / 1000.0);
-			if ((current.isEndOfLine(style.rightMargin() + hyphWidth)) || current.isEndOfCol(realDesc) || SpecialChars::isBreak(currentCh, Cols > 1) || (current.xPos - current.maxShrink + hyphWidth) >= current.mustLineEnd)
-			{
+			if ((current.isEndOfLine(style.rightMargin() + hyphWidth)) || current.isEndOfCol(realDesc) || SpecialChars::isBreak(itemText.text(a), Cols > 1) || (current.xPos - current.maxShrink + hyphWidth) >= current.mustLineEnd)
+			{
+
 				//end of row reached - right column, end of column, break char or line must end
-				if (current.itemsInLine == 0 && !current.afterOverflow && !SpecialChars::isBreak(currentCh, Cols > 1))
+				if (current.isEmpty && !current.afterOverflow && !SpecialChars::isBreak(itemText.text(a), Cols > 1))
 				{
 					//no glyphs in line, so start new row
-					if (SpecialChars::isBreak(currentCh, Cols > 1))
-						current.restartRowIndex = a +1;
-					a = current.restartRow(true);
+					if (SpecialChars::isBreak(itemText.text(a), Cols > 1))
+						current.restartRowIndex = i + 1;
+					i = current.restartRow(true);
 					inOverflow = false;
 					outs = false;
 					continue;
@@ -2442,13 +2401,14 @@
 				if (current.breakIndex < 0)
 				{
 					//force break
-					if (!SpecialChars::isBreak(currentCh, Cols > 1))
+					if (!SpecialChars::isBreak(itemText.text(a), Cols > 1))
 					{
 						//force line end at previouse glyph
-						a--;
+						i--;
+						a = glyphRuns[i].firstChar();
 						current.mustLineEnd = current.line.x;
 					}
-					current.breakLine(itemText, style, firstLineOffset(),a);
+					current.breakLine(style, firstLineOffset(), i);
 				}
 				if (!current.addLine && !current.lastInRowLine && current.afterOverflow)
 				{
@@ -2457,7 +2417,7 @@
 					//if we have some text here - insert text WITHOUT right margin
 					//if there is no place for text - insert text WITH right margin and end line
 					current.lastInRowLine = false;
-					if (current.line.firstItem == current.restartIndex)
+					if (current.line.firstRun == current.restartIndex)
 						current.lastInRowLine = true;
 					if (current.hasDropCap && DropLinesCount == 0 && current.restartIndex == current.restartRowIndex)
 					{
@@ -2465,12 +2425,13 @@
 						maxDX = 0;
 						current.yPos = maxDY;
 					}
-					a = current.restartLine(false,true);
+					i = current.restartLine(false,true);
 					outs = false;
 					inOverflow = false;
 					continue;
 				}
 				outs = true;
+
 				current.addLine = true;
 				current.lastInRowLine = true;
 				current.rightMargin = style.rightMargin();
@@ -2480,7 +2441,7 @@
 			else
 			{
 				int charStart, charEnd;
-				if (current.itemsInLine == 0)
+				if (current.isEmpty)
 				{
 					charStart = static_cast<int>(floor(current.line.x));
 					charEnd = static_cast<int>(ceil(current.xPos));
@@ -2491,10 +2452,10 @@
 					charEnd = static_cast<int>(ceil(current.xPos - current.maxShrink));
 				}
 				if (legacy &&
-						(((currentCh == '-' || itemText.hasFlag(a, ScLayout_HyphenationPossible)) && (current.hyphenCount < m_Doc->hyphConsecutiveLines() || m_Doc->hyphConsecutiveLines() == 0))
-						 || currentCh == SpecialChars::SHYPHEN))
-				{
-					if (itemText.hasFlag(a, ScLayout_HyphenationPossible) || currentCh == SpecialChars::SHYPHEN)
+						(((itemText.text(a) == '-' || glyphRuns[i].hasFlag(ScLayout_HyphenationPossible)) && (current.hyphenCount < m_Doc->hyphConsecutiveLines() || m_Doc->hyphConsecutiveLines() == 0))
+						 || itemText.text(a) == SpecialChars::SHYPHEN))
+				{
+					if (glyphRuns[i].hasFlag(ScLayout_HyphenationPossible) || itemText.text(a) == SpecialChars::SHYPHEN)
 					{
 						pt1 = QPoint(charStart,  regionMinY);
 						pt2 = QPoint(static_cast<int>(charEnd + hyphWidth), regionMaxY -1);
@@ -2505,7 +2466,7 @@
 						pt2 = QPoint(charEnd, regionMaxY -1);
 					}
 				}
-				else if (!legacy && SpecialChars::isBreakingSpace(currentCh))
+				else if (!legacy && SpecialChars::isBreakingSpace(itemText.text(a)))
 				{
 					pt1 = QPoint(static_cast<int>(qMax(floor(breakPos - current.maxShrink - (style.minGlyphExtension() * wide)),0.0)), regionMinY);
 					pt2 = QPoint(charEnd, regionMaxY -1);
@@ -2536,11 +2497,11 @@
 				}
 				if (outs)
 				{
-					if (current.itemsInLine == 0)
+					if (current.isEmpty)
 					{
 						current.line.x = current.xPos = realEnd;
-						a--;
-						current.startLine(a+1);
+						i--;
+						current.startLine(i+1);
 						if (!current.wasFirstInRow)
 							current.addLeftIndent = true;
 						if (current.hasDropCap && DropLinesCount == 0 && !current.afterOverflow)
@@ -2554,8 +2515,9 @@
 					}
 					if (current.breakIndex < 0)
 					{
-						a--;
-						current.breakLine(itemText, style, firstLineOffset(), a);
+						i--;
+						a = glyphRuns[i].firstChar();
+						current.breakLine(style, firstLineOffset(), i);
 					}
 					//check if after overflow text can be placed
 					overflowWidth = realEnd - (current.xPos - current.maxShrink);
@@ -2577,7 +2539,7 @@
 									current.lastInRowLine = true;
 									current.mustLineEnd = current.line.x;
 								}
-								else if (current.line.firstItem == current.restartIndex)
+								else if (current.line.firstRun == current.restartIndex)
 									current.lastInRowLine = true;
 							}
 							else
@@ -2587,7 +2549,7 @@
 								current.hasDropCap = false;
 								maxDX = 0;
 							}
-							a = current.restartLine(false, true);
+							i = current.restartLine(false, true);
 							inOverflow = false;
 							outs = false;
 							continue;
@@ -2604,13 +2566,13 @@
 			}
 
 			// hyphenation
-			if ((itemText.hasFlag(a, ScLayout_HyphenationPossible)
-				  || currentCh == '-'
-				  || currentCh == SpecialChars::SHYPHEN)
-				 && (!outs) && !itemText.text(a-1).isSpace() )
+			if ((glyphRuns[i].hasFlag(ScLayout_HyphenationPossible)
+				  || itemText.text(a) == '-'
+				  || itemText.text(a) == SpecialChars::SHYPHEN)
+				 && (!outs) && !itemText.text(glyphRuns[i - 1].lastChar()).isSpace() )
 			{
 				breakPos = current.xPos;
-				if (currentCh != '-')
+				if (itemText.text(a) != '-')
 				{
 					breakPos += hyphWidth;
 				}
@@ -2622,22 +2584,22 @@
 
 				if (legacy || (breakPos - rightHang < current.colRight - style.rightMargin()))
 				{
-					if ((current.hyphenCount < m_Doc->hyphConsecutiveLines()) || (m_Doc->hyphConsecutiveLines() == 0) || currentCh == SpecialChars::SHYPHEN)
+					if ((current.hyphenCount < m_Doc->hyphConsecutiveLines()) || (m_Doc->hyphConsecutiveLines() == 0) || itemText.text(a) == SpecialChars::SHYPHEN)
 					{
-						current.rememberBreak(a, breakPos, style.rightMargin() + hyphWidth);
-					}
-				}
-			}
-
-			if ((currentCh == SpecialChars::FRAMEBREAK) && (a < itemText.length()-1))
+						current.rememberBreak(i, breakPos, style.rightMargin() + hyphWidth);
+					}
+				}
+			}
+
+			if ((itemText.text(a) == SpecialChars::FRAMEBREAK) && (a < itemText.length()-1))
 				goNoRoom = true;
-			if ((currentCh == SpecialChars::COLBREAK) && (Cols > 1))
+			if ((itemText.text(a) == SpecialChars::COLBREAK) && (Cols > 1))
 				goNextColumn = true;
 
 			if (a != firstInFrame() && implicitBreak(itemText.text(a - 1), itemText.text(a)))
-				current.rememberBreak(a - 1, breakPos);
-
-			++current.itemsInLine;
+				current.rememberBreak(i -1, breakPos);
+
+			current.isEmpty = (i - current.line.firstRun + 1) == 0;
 
 			if (tabs.active)
 			{
@@ -2645,10 +2607,10 @@
 				if (tabs.status == TabCENTER)
 					cen = 2;
 
-				double newTabAdvance = itemText.getGlyphs(tabs.charIndex)->xadvance - (wide+kernVal) / cen;
+				double newTabAdvance = tabs.tabGlyph->xadvance - wide / cen;
 
 				if (newTabAdvance >= 0) {
-					itemText.getGlyphs(tabs.charIndex)->xadvance = newTabAdvance;
+					tabs.tabGlyph->xadvance = newTabAdvance;
 				}
 				else {
 					tabs.active = false;
@@ -2658,7 +2620,7 @@
 			if ((DropCmode || BulNumMode) && !outs)
 			{
 				current.xPos += style.parEffectOffset();
-				glyphs->last()->xadvance += style.parEffectOffset();
+				lastGlyph.xadvance += style.parEffectOffset();
 				if (DropCmode)
 				{
 					DropCmode = false;
@@ -2678,17 +2640,17 @@
 			{
 				tabs.active = false;
 				tabs.status = TabNONE;
-				if (SpecialChars::isBreak(currentCh, Cols > 1))
+				if (SpecialChars::isBreak(itemText.text(a), Cols > 1))
 				{
 					// find end of line
-					current.breakLine(itemText, style, firstLineOffset(), a);
+					current.breakLine(style, firstLineOffset(), i);
 					EndX = current.endOfLine(m_availableRegion, style.rightMargin(), regionMinY, regionMaxY);
 					current.finishLine(EndX);
 					//addLine = true;
 					assert(current.addLine);
 					//current.startOfCol = false;
 					//addLeftIndent = true;
-					if (currentCh == SpecialChars::PARSEP)
+					if (itemText.text(a) == SpecialChars::PARSEP)
 					{
 						maxDX = 0;
 						if (current.hasDropCap)
@@ -2702,7 +2664,7 @@
 //					if (style.alignment() != 0)
 					{
 						if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
-							current.line.width += opticalRightMargin(itemText, current.line);
+							current.line.width += opticalRightMargin(itemText, glyphRuns, current.line);
 
 						OFs = 0;
 						if (style.alignment() == ParagraphStyle::Rightaligned)
@@ -2714,22 +2676,22 @@
 
 						if (style.alignment() == ParagraphStyle::Extended
 							|| (style.alignment() == ParagraphStyle::Justified
-								&&  (currentCh == SpecialChars::LINEBREAK ||
-									 currentCh == SpecialChars::FRAMEBREAK ||
-									 currentCh == SpecialChars::COLBREAK)
-								&&  !itemText.text(current.line.lastItem - 1).isSpace()))
+								&&  (itemText.text(a) == SpecialChars::LINEBREAK ||
+									 itemText.text(a) == SpecialChars::FRAMEBREAK ||
+									 itemText.text(a) == SpecialChars::COLBREAK)
+								&&  !itemText.text(glyphRuns[current.line.lastRun - 1].lastChar()).isSpace()))
 						{
-							justifyLine(itemText, current.line);
+							justifyLine(style, current);
 						}
 						else
 						{
 							if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
-								current.line.naturalWidth += opticalRightMargin(itemText, current.line);
+								current.line.naturalWidth += opticalRightMargin(itemText, glyphRuns, current.line);
 							double optiWidth = current.colRight - style.rightMargin() - style.lineSpacing()/2.0 - current.line.x;
 							if (current.line.naturalWidth > optiWidth)
 								current.line.width = qMax(current.line.width - current.maxShrink, optiWidth);
 							// simple offset
-							indentLine(itemText, current.line, OFs);
+							indentLine(style, current, OFs);
 						}
 						current.xPos = current.colRight;
 					}
@@ -2737,11 +2699,14 @@
 				else // outs -- last char went outside the columns (or into flow-around shape)
 				{
 					if (current.breakIndex >= 0)
-						a = current.breakIndex;
-					assert( a >= 0 );
-					assert( a < itemText.length() );
-					glyphs = itemText.getGlyphs(a);
-					current.itemsInLine = a - current.line.firstItem + 1;
+					{
+						i = current.breakIndex;
+						a = glyphRuns[i].firstChar();
+					}
+					assert( i >= 0 );
+					assert( i < glyphRuns.length() );
+					//glyphs = itemText.getGlyphs(a);
+					current.isEmpty = (i - current.line.firstRun + 1) == 0;
 					if (current.addLine)
 					{
 						// go back to last break position
@@ -2752,40 +2717,44 @@
 							style.setLineSpacing(m_Doc->guidesPrefs().valueBaselineGrid);
 
 						if (itemText.text(a) == ' ') {
-							itemText.setFlag(a, ScLayout_SuppressSpace);
-							glyphs->xadvance = 0;
+							glyphRuns[i].setFlag(ScLayout_SuppressSpace);
+							glyphRuns[i].glyphs()[0].xadvance = 0;
 						}
 
-						current.updateHeightMetrics(itemText);
+						current.updateHeightMetrics();
 						//current.updateLineOffset(itemText, style, firstLineOffset());
 						//current.xPos = current.breakXPos;
 						EndX = current.endOfLine(m_availableRegion, current.rightMargin, regionMinY, regionMaxY);
 						current.finishLine(EndX);
 
 						hyphWidth = 0.0;
-						if (itemText.hasFlag(a, ScLayout_HyphenationPossible) || itemText.text(a) == SpecialChars::SHYPHEN)
+						if (glyphRuns[i].hasFlag(ScLayout_HyphenationPossible) || itemText.text(a) == SpecialChars::SHYPHEN)
 						{
 							// insert hyphen
 							if (current.lastInRowLine)
 								//increase hyphen count only for hyphens a the end of text row, omit hyphens before overflow
 								current.hyphenCount++;
-							itemText.setFlag(a, ScLayout_SoftHyphenVisible);
-							glyphs->grow();
-							glyphs->more->glyph = font.char2CMap(QChar('-'));
-							glyphs->more->xadvance = font.charWidth('-', itemText.charStyle(a).fontSize() / 10.0) * scaleH; //FIX ME - hyphen is not rendered with proper width - check yhis with large glyphs horizontal scaling eg. 20%
-							hyphWidth = glyphs->more->xadvance;
+							glyphRuns[i].setFlag(ScLayout_SoftHyphenVisible);
+							GlyphLayout hyphen;
+							hyphen.glyph = font.char2CMap(QChar('-'));
+							hyphen.xadvance = font.glyphBBox(hyphen.glyph, itemText.charStyle(a).fontSize() / 10.0).width;
+							hyphWidth = hyphen.xadvance * scaleH;
+							glyphRuns[i].glyphs().append(hyphen);
 						}
 						else
 						{
 							if (itemText.text(a) != '-')
 								current.hyphenCount = 0;
-							itemText.clearFlag(a, ScLayout_SoftHyphenVisible);
-							glyphs->shrink();
+							if (glyphRuns[i].hasFlag(ScLayout_SoftHyphenVisible))
+							{
+								glyphRuns[i].clearFlag(ScLayout_SoftHyphenVisible);
+								glyphRuns[i].glyphs().removeLast();
+							}
 						}
 
 						// Justification
 						if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
-							current.line.width += opticalRightMargin(itemText, current.line);
+							current.line.width += opticalRightMargin(itemText, glyphRuns, current.line);
 						// #12565: Right alignment of hyphens
 						// The additional character width has already been taken into account
 						// above via the line break position, so it's not necessary to increase
@@ -2805,12 +2774,12 @@
 							OFs = (current.line.width - current.line.naturalWidth) / 2;
 
 						if ((style.alignment() == ParagraphStyle::Justified) || (style.alignment() == ParagraphStyle::Extended))
-							justifyLine(itemText, current.line);
+							justifyLine(style, current);
 						else
 						{
 							if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
-								current.line.naturalWidth += opticalRightMargin(itemText, current.line);
-							indentLine(itemText, current.line, OFs);
+								current.line.naturalWidth += opticalRightMargin(itemText, glyphRuns, current.line);
+							indentLine(style, current, OFs);
 						}
 						current.xPos = current.line.x + current.line.width;
 					}
@@ -2833,10 +2802,10 @@
 				if (current.isEndOfCol(desc))
 				{
 					//check if really line extends bottom margin
-					current.updateHeightMetrics(itemText);
+					current.updateHeightMetrics();
 					if (current.isEndOfCol(current.line.descent))
 					{
-						if (current.itemsInLine == 0 || current.column+1 == Cols)
+						if (current.isEmpty || current.column+1 == Cols)
 						{
 							goNoRoom = true;
 							MaxChars = a + 1;
@@ -2849,22 +2818,23 @@
 				}
 				else
 					setMaxY(maxYDesc);
-				if (current.line.firstItem <= current.line.lastItem && current.itemsInLine > 0)
+				if (current.line.firstRun <= current.line.lastRun && !current.isEmpty)
 				{
 					if (current.addLine && current.breakIndex >= 0)
 					{
-						if (itemText.charStyle(current.line.firstItem).effects() & ScLayout_DropCap)
+						if (glyphRuns[current.line.firstRun].style().effects() & ScLayout_DropCap)
 						{
 							// put line back to top
 							current.line.y -= DropCapDrop;
-							itemText.getGlyphs(current.line.firstItem)->yoffset += DropCapDrop;
+							glyphRuns[current.line.firstRun].glyphs().first().yoffset += DropCapDrop;
 						}
-						fillInTabLeaders(itemText, current.line);
+						fillInTabLeaders(current);
 						//if right margin is set we temporally save line, not append it
-						textLayout.appendLine(current.line);
+						textLayout.appendLine(current.createLineBox());
 						setMaxY(maxYDesc);
-						current.restartIndex = current.line.lastItem +1;
-						a = current.restartIndex -1;
+						current.restartIndex = current.line.lastRun + 1;
+						i = current.line.lastRun;
+						a = glyphRuns[i].firstChar();
 						current.rowDesc = qMax(current.rowDesc,current.yPos + current.line.descent);
 						if (!current.lastInRowLine)
 						{
@@ -2879,7 +2849,7 @@
 					else if (!inOverflow && !current.afterOverflow && current.lastInRowLine)
 					{
 						current.yPos++;
-						a = current.restartLine(true, true);
+						i = current.restartLine(true, true);
 						inOverflow = false;
 						outs = false;
 						current.mustLineEnd = current.colRight;
@@ -2930,7 +2900,8 @@
 				outs = false;
 				current.addLine = false;
 				current.lastInRowLine = false;
-				current.startLine(a+1);
+				// WTF does i+1 mean here, what if i is the last run we have!
+				current.startLine(i+1);
 				if (goNoRoom)
 				{
 					goNoRoom = false;
@@ -2945,7 +2916,7 @@
 					{
 						if (firstLineOffset() == FLOPRealGlyphHeight)
 							asce = 0;
-						current.nextColumn();
+						current.nextColumn(textLayout);
 						current.mustLineEnd = current.colRight;
 						current.addLeftIndent = true;
 						lastLineY = m_textDistanceMargins.top();
@@ -2961,23 +2932,23 @@
 					}
 				}
 			}
-			if (a == itemText.length() -1)
+			if (i == glyphRuns.length() - 1)
 			{
 				if (!current.afterOverflow || current.addLine)
 				{
 					current.addLine = true;
 					current.lastInRowLine = true;
-					current.breakLine(itemText, style, firstLineOffset(),a);
+					current.breakLine(style, firstLineOffset(), i);
 				}
 				if (current.afterOverflow && !current.addLine)
 				{
-					if (current.restartIndex < current.line.firstItem)
+					if (current.restartIndex < current.line.firstRun)
 					{
-						a = current.restartLine(false,true);
+						i = current.restartLine(false,true);
 						continue;
 					}
 					else
-						current.breakLine(itemText, style, firstLineOffset(),a);
+						current.breakLine(style, firstLineOffset(), i);
 				}
 			}
 		}
@@ -2988,10 +2959,11 @@
 		}
 // end of itemText
 // now place the last line
-		if (current.itemsInLine > 0 )
+		if (!current.isEmpty)
 		{
 			int a = itemText.length()-1;
-			current.breakLine(itemText, style, firstLineOffset(), a);
+			int i = glyphRuns.length() - 1;
+			current.breakLine(style, firstLineOffset(), i);
 
 			if (current.startOfCol)
 			{
@@ -3029,7 +3001,7 @@
 			current.finishLine(EndX);
 
 			if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
-				current.line.width += opticalRightMargin(itemText, current.line);
+				current.line.width += opticalRightMargin(itemText, glyphRuns, current.line);
 
 			OFs = 0;
 			if (style.alignment() == ParagraphStyle::Rightaligned)
@@ -3043,27 +3015,27 @@
 					&&  (itemText.text(a) == SpecialChars::LINEBREAK ||
 						 itemText.text(a) == SpecialChars::FRAMEBREAK ||
 						 itemText.text(a) == SpecialChars::COLBREAK)
-					&&  !itemText.text(current.line.firstItem + current.itemsInLine-1).isSpace()))
-			{
-				justifyLine(itemText, current.line);
+					&&  !itemText.text(a).isSpace()))
+			{
+				justifyLine(style, current);
 			}
 			else
 			{
 				if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
-					current.line.naturalWidth += opticalRightMargin(itemText, current.line);
-				indentLine(itemText, current.line, OFs);
-			}
-			if ( itemText.charStyle(current.line.firstItem).effects() & ScLayout_DropCap )
+					current.line.naturalWidth += opticalRightMargin(itemText, glyphRuns, current.line);
+				indentLine(style, current, OFs);
+			}
+			if (glyphRuns[current.line.firstRun].style().effects() & ScLayout_DropCap)
 			{
 				// put line back to top
 				current.line.y -= DropCapDrop;
-				itemText.getGlyphs(current.line.firstItem)->yoffset += DropCapDrop;
-			}
-			fillInTabLeaders(itemText, current.line);
+				glyphRuns[current.line.firstRun].glyphs().first().yoffset += DropCapDrop;
+			}
+			fillInTabLeaders(current);
 			current.startOfCol = false;
 			goNextColumn = false;
 
-			textLayout.appendLine(current.line);
+			textLayout.appendLine(current.createLineBox());
 			setMaxY(maxYDesc);
 			current.startOfCol = false;
 
@@ -3077,20 +3049,12 @@
 	MaxChars = itemText.length();
 	if ((verticalAlign > 0) && (NextBox == NULL))
 	{
-		int vertAlign = verticalAlign;
-		double topDist = m_textDistanceMargins.top();
-		double hAdjust = 0;
-		if (verticalAlign == 1)
-			hAdjust = (height() - (m_textDistanceMargins.bottom() + lineCorr) - maxY) / 2.0;
-		else if (verticalAlign == 2)
-			hAdjust = (height() - (m_textDistanceMargins.bottom() + lineCorr) - maxY);
+		double hAdjust = height() - textLayout.box()->naturalHeight();
 		if (hAdjust > 0)
 		{
-			m_textDistanceMargins.setTop(topDist + hAdjust);
-			verticalAlign = 0;
-			layout();
-			m_textDistanceMargins.setTop(topDist);
-			verticalAlign = vertAlign;
+			if (verticalAlign == 1)
+				hAdjust /= 2;
+			textLayout.box()->moveBy(0, hAdjust);
 		}
 	}
 	invalid = false;
@@ -3220,20 +3184,6 @@
 	if (m_Doc->RePos)
 		return;
 	QTransform pf2;
-	QPoint pt1, pt2;
-	double wide;
-	QString cachedStroke = "";
-	QString cachedFill = "";
-	double cachedFillShade = -1;
-	double cachedStrokeShade = -1;
-	QString actStroke = "";
-	QString actFill = "";
-	double actFillShade = -1;
-	double actStrokeShade = -1;
-	QColor cachedFillQ;
-	QColor cachedStrokeQ;
-	//	QValueList<ParagraphStyle::TabRecord> tTabValues;
-	double desc, asce;
 	//	tTabValues.clear();
 	p->save(); //SA1
 
@@ -3696,326 +3646,16 @@
 		}
 		assert( firstInFrame() >= 0 );
 		assert( lastInFrame() < itemText.length() );
-		LineSpec ls;
-
-		uint llp = 0;
-		while (llp < textLayout.lines())
-		{
-			ls = textLayout.line(llp++);
-			const ParagraphStyle& LineStyle = itemText.paragraphStyle(ls.firstItem);
-			if (LineStyle.backgroundColor() != CommonStrings::None)
-			{
-				QColor tmp;
-				SetQColor(&tmp, LineStyle.backgroundColor(), LineStyle.backgroundShade());
-				double y0 = ls.y;
-				double y2 = ls.y;
-				double ascent = ls.ascent;
-				double descent = ls.descent;
-				double rMarg = LineStyle.rightMargin();
-				double lMarg = ls.colLeft;
-				double adjX = 0;
-				if (LineStyle.firstIndent() <= 0)
-					adjX += LineStyle.leftMargin() + LineStyle.firstIndent();
-				while (llp < textLayout.lines())
-				{
-					ls = textLayout.line(llp);
-					if ((ls.colLeft > lMarg) || (itemText.paragraphStyle(ls.firstItem) != LineStyle))
-					{
-						if (y2 == 0)
-							y2 = y0;
-						break;
-					}
-					if (itemText.text(ls.lastItem) == SpecialChars::PARSEP)
-					{
-						y2 = ls.y;
-						descent = ls.descent;
-						if ((llp + 1) < textLayout.lines())
-						{
-							if ((textLayout.line(llp + 1).lastItem - textLayout.line(llp + 1).firstItem) > 0)
-								descent += LineStyle.lineSpacing() - (ls.descent + textLayout.line(llp + 1).ascent);
-						}
-						llp++;
-						break;
-					}
-					y2 = ls.y;
-					descent = ls.descent;
-					if ((llp + 1) < textLayout.lines())
-						descent += LineStyle.lineSpacing() - (ls.descent + textLayout.line(llp + 1).ascent);
-					llp++;
-				}
-				p->save();
-				p->setupPolygon(&PoLine);
-				p->setClipPath();
-				p->setAntialiasing(false);
-				p->setFillMode(1);
-				p->setStrokeMode(0);
-				p->setBrush(tmp);
-				p->drawRect(lMarg + adjX, y0 - ascent, columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent);
-				p->setAntialiasing(true);
-				p->restore();
-			}
-		}
-		for (uint ll=0; ll < textLayout.lines(); ++ll)
-		{
-			ls = textLayout.line(ll);
-			double CurX = ls.x;
-			// Draw text selection rectangles
-			QRectF selectedFrame;
-			QList<QRectF> sFList;
-			bool previousWasObject(false);
-			double selX = ls.x;
-			GlyphLayout* glyphs = 0;
-			int last = qMin(ls.lastItem, itemText.length() - 1);
-			for (int as = ls.firstItem; as <= last; ++as)
-			{
-				bool selecteds = itemText.selected(as);
-				glyphs = itemText.getGlyphs(as);
-				bool HasObject = itemText.hasObject(as);
-				Mark* mark = itemText.mark(as);
-				if (mark != NULL && (mark->isType(MARKAnchorType) || mark->isType(MARKIndexType)))
-					continue;
-				if (selecteds)
-				{
-					const CharStyle& charStyleS(itemText.charStyle(as));
-					if (((as > ls.firstItem) && (charStyleS != itemText.charStyle(as-1)))
-						|| ((!selectedFrame.isNull()) && HasObject)
-						|| previousWasObject)
-					{
-						sFList << selectedFrame;
-						selectedFrame = QRectF();
-						previousWasObject = false;
-					}
-					if ((m_isSelected || (NextBox != 0 || BackBox != 0))
-						&& (m_Doc->appMode == modeEdit || m_Doc->appMode == modeEditTable))
-					{
-						double xcoZli = selX + glyphs->xoffset;
-						// ugly hack to make selection correct, as xoffset is used to
-						// remove left-half of CJK lparen , which is blank.
-						if (glyphs->xoffset)
-						{
-							int attr = SpecialChars::getCJKAttr(itemText.text(as)) & SpecialChars::CJK_CHAR_MASK;
-							if (attr == SpecialChars::CJK_FENCE_BEGIN)
-							{
-								xcoZli -= glyphs->xoffset;
-							}
-						}
-						const ScFace font = charStyleS.font();
-						double fontSize = charStyleS.fontSize() / 10.0;
-						desc = - font.descent(fontSize);
-						asce = font.ascent(fontSize);
-						wide = glyphs->wide();
-						QRectF scr;
-						if (HasObject)
-						{
-							PageItem* obj = itemText.object(as);
-							double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH;
-							double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV;
-							scr = QRectF(xcoZli, ls.y - hh, ww , hh);
-							previousWasObject = true;
-						}
-						else
-							scr = QRectF(xcoZli, ls.y + glyphs->yoffset - asce * glyphs->scaleV, wide , (asce+desc) * (glyphs->scaleV));
-						selectedFrame |=  scr;
-					}
-				}
-				// Unneeded now that glyph xadvance is set appropriately for inline objects by layout() - JG
-				/*if ((hls->ch == SpecialChars::OBJECT) && (hls->embedded.hasItem()))
-					selX += (hls->embedded.getItem()->gWidth + hls->embedded.getItem()->lineWidth()) * hls->glyph.scaleH;
-				else*/
-				selX += glyphs->wide();
-			}
-			if (!selectedFrame.isNull())
-				sFList << selectedFrame;
-			p->save();//SA3
-			p->setFillMode(1);
-			p->setBrush(qApp->palette().color(QPalette::Active, QPalette::Highlight));
-			p->setLineWidth(0);
-			// TODO - I dunno why but scpainter does not accept
-			// to actually set the pen to 0? As a wa,
-			// we set its color same as brush: "à malin, malin et demi!".
-			p->setPen(qApp->palette().color(QPalette::Active, QPalette::Highlight));
-			for(int sfc(0);sfc < sFList.count();++sfc)
-				p->drawRect(sFList[sfc].x(), sFList[sfc].y(), sFList[sfc].width(), sFList[sfc].height());
-			p->restore();//RE3
-			//	End of selection
-
-			QColor tmp;
-			double CurXB = ls.x;
-			QRectF scrG;
-			QString oldBack;
-			double oldShade = 100;
-			for (int a = ls.firstItem; a <= last; ++a)
-			{
-				glyphs = itemText.getGlyphs(a);
-				const CharStyle& charStyle(itemText.charStyle(a));
-				if (charStyle.backColor() != CommonStrings::None)
-				{
-					SetQColor(&tmp, charStyle.backColor(), charStyle.backShade());
-					const ParagraphStyle& LineStyle = itemText.paragraphStyle(ls.firstItem);
-					double y1 = ls.y;
-					double hl = ls.height;
-					if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-						hl = doc()->guidesPrefs().valueBaselineGrid;
-					else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
-						hl = LineStyle.lineSpacing();
-					if (ls.isFirstLine)
-					{
-						if (textLayout.lines() == 1)
-							hl = ls.ascent + ls.descent;
-						if (LineStyle.hasDropCap() && (a == ls.firstItem))
-							hl *= LineStyle.dropCapLines();
-						if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-							y1 -= LineStyle.lineSpacing();
-						else if (firstLineOffset() == FLOPRealGlyphHeight || firstLineOffset() == FLOPFontAscent)
-							y1 -= ls.ascent;
-						else
-							y1 -= LineStyle.lineSpacing();
-					}
-					else
-						y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0;
-					QRectF scr;
-					if (itemText.hasObject(a))
-					{
-						PageItem* obj = itemText.object(a);
-						double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH;
-						double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV;
-						scr = QRectF(CurXB, ls.y - hh, ww , hh);
-					}
-					else
-						scr = QRectF(CurXB, y1, glyphs->wide(), hl);
-					if ((oldBack.isEmpty()) || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade())))
-						scrG |= scr;
-					else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade()))
-					{
-						p->save();
-						p->setFillMode(1);
-						p->setStrokeMode(0);
-						SetQColor(&tmp, oldBack, oldShade);
-						p->setBrush(tmp);
-						p->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height());
-						p->restore();
-						scrG = scr;
-					}
-					oldBack = charStyle.backColor();
-					oldShade = charStyle.backShade();
-				}
-				else
-				{
-					oldBack.clear();
-					oldShade = 100;
-					if (!scrG.isNull())
-					{
-						p->save();
-						p->setFillMode(1);
-						p->setStrokeMode(0);
-						p->setBrush(tmp);
-						p->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height());
-						p->restore();
-					}
-					scrG = QRectF();
-				}
-				CurXB += glyphs->wide();
-			}
-			if (!scrG.isNull())
-			{
-				p->save();
-				p->setFillMode(1);
-				p->setStrokeMode(0);
-				p->setBrush(tmp);
-				p->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height());
-				p->restore();
-			}
-			for (int a = ls.firstItem; a <= last; ++a)
-			{
-				glyphs = itemText.getGlyphs(a);
-				const CharStyle& charStyle(itemText.charStyle(a));
-				bool selected = itemText.selected(a);
-				actFill = charStyle.fillColor();
-				actFillShade = charStyle.fillShade();
-				if (actFill != CommonStrings::None)
-				{
-					p->setFillMode(ScPainter::Solid);
-					if ((cachedFillShade != actFillShade) || (cachedFill != actFill))
-					{
-						SetQColor(&tmp, actFill, actFillShade);
-						p->setBrush(tmp);
-						cachedFillQ = tmp;
-						cachedFill = actFill;
-						cachedFillShade = actFillShade;
-					}
-					else
-						p->setBrush(cachedFillQ);
-				}
-				else
-					p->setFillMode(ScPainter::None);
-
-				const ScFace font = charStyle.font();
-				double fontSize = charStyle.fontSize() / 10.0;
-				desc = - font.descent(fontSize);
-				asce = font.ascent(fontSize);
-				if (((selected && m_isSelected) || ((NextBox != 0 || BackBox != 0) && selected)) && (m_Doc->appMode == modeEdit || m_Doc->appMode == modeEditTable))
-				{
-					// set text color to highlight if its selected
-					p->setBrush(qApp->palette().color(QPalette::Active, QPalette::HighlightedText));
-				}
-
-				actStroke = charStyle.strokeColor();
-				actStrokeShade = charStyle.strokeShade();
-				if (actStroke != CommonStrings::None)
-				{
-					if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke))
-					{
-						SetQColor(&tmp, actStroke, actStrokeShade);
-						p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-						cachedStrokeQ = tmp;
-						cachedStroke = actStroke;
-						cachedStrokeShade = actStrokeShade;
-					}
-					else
-						p->setPen(cachedStrokeQ, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-				}
-				// paint glyphs
-				QRectF scrGl;
-				if (itemText.hasObject(a))
-				{
-					PageItem* obj = itemText.object(a);
-					double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH;
-					double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV;
-					scrGl = QRectF(CurX, ls.y + glyphs->yoffset, ww , -hh).normalized();
-					previousWasObject = true;
-				}
-				else
-					scrGl = QRectF(CurX + glyphs->xoffset, ls.y + glyphs->yoffset - asce * glyphs->scaleV, glyphs->xadvance+1 , (asce+desc) * (glyphs->scaleV));
-				if (isEmbedded || cullingArea.intersects(pf2.mapRect(scrGl)))
-				{
-					p->save();//SA4
-					p->translate(CurX, ls.y);
-					if (itemText.hasObject(a))
-						DrawObj_Embedded(p, cullingArea, charStyle, itemText.object(a));
-					else
-					{
-						//control chars for marks
-						if (m_Doc->guidesPrefs().showControls && itemText.hasMark(a) && (glyphs->glyph != SpecialChars::OBJECT))
-						{
-							GlyphLayout markGlyph;
-							layoutGlyphs(charStyle, SpecialChars::OBJECT, ScLayout_None, markGlyph);
-							drawGlyphs(p, charStyle, ScLayout_None, markGlyph);
-						}
-						drawGlyphs(p, charStyle, itemText.flags(a), *glyphs);
-					}
-					p->restore();//RE4
-				}
-				// Unneeded now that glyph xadvance is set appropriately for inline objects by layout() - JG
-				/*if ((hl->ch == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
-					CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) * hl->glyph.scaleH;
-				else*/
-				CurX += glyphs->wide();
-			}
-		}
-	//	else {
-	//		//		qDebug("skipping textframe: len=%d", itemText.count());
-	//	}
-		//	pf2.end();
+
+		int fm = p->fillMode();
+		int sm = p->strokeMode();
+		p->setFillMode(1);
+		p->setStrokeMode(1);
+		ScreenPainter painter(p, this);
+		textLayout.renderBackground(&painter);
+		textLayout.render(&painter, this);
+		p->setFillMode(fm);
+		p->setStrokeMode(sm);
 	}
 	m_textDistanceMargins=savedTextDistanceMargins;
 	p->restore();//RE1
@@ -4489,7 +4129,7 @@
 					ExpandSel(1, oldPos);
 				}
 				else
-					if ((textLayout.lines() > 0) && (oldPos >= textLayout.line(textLayout.lines()-1).firstItem) && (itemText.cursorPosition() >= lastInFrame()) && (NextBox != 0))
+					if ((textLayout.lines() > 0) && (oldPos >= textLayout.line(textLayout.lines()-1)->firstChar()) && (itemText.cursorPosition() >= lastInFrame()) && (NextBox != 0))
 					{
 						if (NextBox->frameDisplays(itemText.cursorPosition()))
 						{
@@ -4540,7 +4180,7 @@
 					ExpandSel(-1, oldPos);
 				}
 				else
-					if ((textLayout.lines() > 0) && (oldPos <= textLayout.line(0).lastItem) && (itemText.cursorPosition()  == firstInFrame()) && (BackBox != 0))
+					if ((textLayout.lines() > 0) && (oldPos <= textLayout.line(0)->lastChar()) && (itemText.cursorPosition()  == firstInFrame()) && (BackBox != 0))
 					{
 						view->Deselect(true);
 						// TODO position at the right place in previous frame
@@ -6254,58 +5894,33 @@
 
 void PageItem_TextFrame::setTextFrameHeight()
 {
-	//ugly hack increasing min frame`s haeight against strange glyph painting if it is too close of bottom
-	double hackValue = 0.5;
-
 	if (textLayout.lines() <= 0)
 		return;
-	const LineSpec& firstLine = textLayout.line(0);
-	const LineSpec& lastLine  = textLayout.line(textLayout.lines() -1);
-
-	double y1 = firstLine.y /*- firstLine.ascent*/;
-	double y2 = lastLine.y  + lastLine.descent;
-
-	const ParagraphStyle& firstLineStyle = itemText.paragraphStyle(firstLine.firstItem);
-	if (firstLineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-		y1 -= firstLineStyle.lineSpacing();
-	else if (firstLineOffset() == FLOPRealGlyphHeight || firstLineOffset() == FLOPFontAscent)
-		y1 -= firstLine.ascent;
-	else
-		y1 -= firstLineStyle.lineSpacing();
-
-	double newHeight = ceil(y2) + m_textDistanceMargins.bottom() + hackValue;
+
 	if (NextBox == 0) // Vertical alignment is not used inside a text chain
 	{
-		if (verticalAlign == 1)
-			newHeight -= floor(y1);
-		else if (verticalAlign == 2)
-			newHeight = m_height - floor(y1);
-	}
-
-	UndoTransaction undoTransaction;
-	if (UndoManager::undoEnabled() && (verticalAlign != 0))
-	{
-		QString unitSuffix = unitGetStrFromIndex(m_Doc->unitIndex());
-		int unitPrecision  = unitGetPrecisionFromIndex(m_Doc->unitIndex());
-		double unitRatio   = m_Doc->unitRatio();
-		QString owString  = QString::number(oldWidth * unitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString ohString  = QString::number(oldHeight * unitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString nwString  = QString::number(m_width * unitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString nhString  = QString::number(m_height * unitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString tooltip   = QString(Um::ResizeFromTo).arg(owString).arg(ohString).arg(nwString).arg(nhString);
-		undoTransaction = undoManager->beginTransaction(Um::Selection, Um::ITextFrame, Um::Resize, tooltip, Um::IResize);
-	}
-
-	if (verticalAlign != 0)
-	{
-		double newX = m_xPos + floor(y1) * cos(-m_rotation * M_PI / 180 - M_PI / 2);
-		double newY = m_yPos - floor(y1) * sin(-m_rotation * M_PI / 180 - M_PI / 2);
-		setXYPos(newX, newY);
-	}
-	setHeight(newHeight);
-
-	if (undoTransaction)
-		undoTransaction.commit();
+		textLayout.box()->moveTo(textLayout.box()->x(), 0);
+		double newHeight = textLayout.box()->naturalHeight();
+
+		UndoTransaction undoTransaction;
+		if (UndoManager::undoEnabled())
+		{
+			QString unitSuffix = unitGetStrFromIndex(m_Doc->unitIndex());
+			int unitPrecision  = unitGetPrecisionFromIndex(m_Doc->unitIndex());
+			double unitRatio   = m_Doc->unitRatio();
+			QString owString  = QString::number(oldWidth * unitRatio, 'f', unitPrecision) + " " + unitSuffix;
+			QString ohString  = QString::number(oldHeight * unitRatio, 'f', unitPrecision) + " " + unitSuffix;
+			QString nwString  = QString::number(m_width * unitRatio, 'f', unitPrecision) + " " + unitSuffix;
+			QString nhString  = QString::number(m_height * unitRatio, 'f', unitPrecision) + " " + unitSuffix;
+			QString tooltip   = QString(Um::ResizeFromTo).arg(owString).arg(ohString).arg(nwString).arg(nhString);
+			undoTransaction = undoManager->beginTransaction(Um::Selection, Um::ITextFrame, Um::Resize, tooltip, Um::IResize);
+		}
+
+		setHeight(newHeight);
+
+		if (undoTransaction)
+			undoTransaction.commit();
+	}
 
 	updateClip();
 	invalid = true;

Modified: trunk/Scribus/scribus/pageitem_textframe.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pageitem_textframe.h
==============================================================================
--- trunk/Scribus/scribus/pageitem_textframe.h	(original)
+++ trunk/Scribus/scribus/pageitem_textframe.h	Wed Mar 23 20:21:36 2016
@@ -159,6 +159,9 @@
 
 public:
 	void setTextFrameHeight();
+
+private:
+	QList<GlyphRun> shapeText();
 };
 
 #endif

Modified: trunk/Scribus/scribus/pdflib_core.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pdflib_core.cpp
==============================================================================
--- trunk/Scribus/scribus/pdflib_core.cpp	(original)
+++ trunk/Scribus/scribus/pdflib_core.cpp	Wed Mar 23 20:21:36 2016
@@ -71,6 +71,7 @@
 #include "sccolor.h"
 #include "sccolorengine.h"
 #include "scfonts.h"
+#include "text/textlayoutpainter.h"
 #include "fonts/cff.h"
 #include "fonts/sfnt.h"
 #include "scpage.h"
@@ -87,6 +88,7 @@
 #include "util_formats.h"
 #include "util_math.h"
 #include "util_ghostscript.h"
+#include "text/boxes.h"
 
 #ifdef HAVE_OSG
 	#include "third_party/prc/exportPRC.h"
@@ -103,6 +105,376 @@
 #undef GetObject
 #endif
 
+static inline QByteArray FToStr(double c)
+{
+	double v = c;
+	if (fabs(c) < 0.0000001)
+		v = 0.0;
+	return QByteArray::number(v, 'f', 5);
+}
+
+class PdfPainter: public TextLayoutPainter
+{
+	QByteArray m_glyphBuffer;
+	QByteArray m_pathBuffer;
+	PageItem* m_item;
+	QMap<QString, PdfFont>  m_UsedFontsP;
+	PDFLibCore *m_pdf;
+	uint m_PNr;
+	const ScPage* m_page;
+
+	QByteArray transformToStr(QTransform tr)
+	{
+		return FToStr(tr.m11()) + " " + FToStr(-tr.m12()) + " " + FToStr(-tr.m21()) + " " + FToStr(tr.m22()) + " " + FToStr(tr.dx()) + " " + FToStr(-tr.dy());
+	}
+
+public:
+	PdfPainter(PageItem *ite, PDFLibCore *pdf, uint num, const ScPage* pag) :
+		m_glyphBuffer(),
+		m_pathBuffer(),
+		m_item(ite),
+		m_pdf(pdf),
+		m_PNr(num),
+		m_page(pag)
+	{}
+
+	~PdfPainter() {}
+
+	void drawGlyph(const GlyphLayout gl)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		PdfFont pdfFont = m_pdf->UsedFontsP[font().replacementName()];
+		QByteArray StrokeColor;
+		QByteArray FillColor;
+		QTransform transform = matrix();
+
+		if (strokeColor().color != CommonStrings::None)
+			StrokeColor = m_pdf->putColor(strokeColor().color, strokeColor().shade, false);
+		if (fillColor().color != CommonStrings::None)
+			FillColor = m_pdf->putColor(fillColor().color, fillColor().shade, true);
+
+		if (pdfFont.method == Use_XForm)
+		{
+			if (!FillColor.isEmpty())
+				m_pathBuffer += FillColor;
+
+			m_pathBuffer += "q\n";
+			m_glyphBuffer += FToStr(fontSize()) + " 0 0 " + FToStr(fontSize()) + " " + FToStr(x()) + " " + FToStr(y()) + " cm\n";
+
+			if (gl.scaleV != 1.0)
+				m_pathBuffer += "1 0 0 1 0 " + FToStr(((fontSize() - fontSize() * gl.scaleV) / fontSize()) * -1) + " cm\n";
+
+			transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1));
+			m_glyphBuffer += transformToStr(transform) + " cm\n";
+
+			if (!FillColor.isEmpty())
+				m_pathBuffer += pdfFont.name + Pdf::toPdf(gl.glyph) + " Do\n";
+			m_pathBuffer += "Q\n";
+		}
+		else
+		{
+			uint gid = gl.glyph;
+			uint fontNr = 65535;
+
+			switch (pdfFont.encoding)
+			{
+			case  Encode_256:
+				gid = pdfFont.glyphmap[gid];
+				fontNr = gid / 256;
+				gid = gid % 256;
+				break;
+			case Encode_224:
+				fontNr = gid / 224;
+				gid = gid % 224 + 32;
+				break;
+			case Encode_Subset:
+				gid = pdfFont.glyphmap[gid];
+				break;
+			case Encode_IdentityH:
+				break;
+			}
+
+			if (fontNr == 65535)
+				m_glyphBuffer += pdfFont.name + " " + FToStr(fontSize()) + " Tf\n";
+			else
+				m_glyphBuffer += pdfFont.name + "S" + Pdf::toPdf(fontNr) + " " + FToStr(fontSize()) + " Tf\n";
+
+			if (!StrokeColor.isEmpty())
+				m_glyphBuffer += StrokeColor;
+
+			if (!FillColor.isEmpty())
+				m_glyphBuffer += FillColor;
+
+			m_glyphBuffer += "0 Tr\n";
+
+			transform.translate(x(), y());
+			transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1));
+			m_glyphBuffer += transformToStr(transform) + " Tm\n";
+
+
+			if (pdfFont.method != Use_Type3 || !FillColor.isEmpty())
+			{
+				switch (pdfFont.encoding)
+				{
+				case Encode_224:
+				case Encode_256:
+					m_glyphBuffer += Pdf::toHexString8(gid) + " Tj\n";
+					break;
+				case Encode_IdentityH:
+				default:
+					m_glyphBuffer += Pdf::toHexString16(gid) + " Tj\n";
+					break;
+				}
+			}
+		}
+	}
+
+	void drawGlyphOutline(const GlyphLayout gl, bool fill)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		PdfFont pdfFont = m_pdf->UsedFontsP[font().replacementName()];
+		QByteArray StrokeColor;
+		QByteArray FillColor;
+		QTransform transform = matrix();
+
+		if (strokeColor().color != CommonStrings::None)
+			StrokeColor = m_pdf->putColor(strokeColor().color, strokeColor().shade, false);
+		if (fill && fillColor().color != CommonStrings::None)
+			FillColor = m_pdf->putColor(fillColor().color, fillColor().shade, true);
+
+		if (pdfFont.method == Use_XForm)
+		{
+			if (!StrokeColor.isEmpty())
+			{
+				m_pathBuffer += FToStr(strokeWidth()) + " w\n[] 0 d\n0 J\n0 j\n";
+				m_pathBuffer += StrokeColor;
+			}
+
+			if (!FillColor.isEmpty())
+				m_pathBuffer += FillColor;
+
+			m_pathBuffer += "q\n";
+			m_glyphBuffer += FToStr(fontSize()) + " 0 0 " + FToStr(fontSize()) + " " + FToStr(x()) + " " + FToStr(y()) + " cm\n";
+
+			if (gl.scaleV != 1.0)
+				m_pathBuffer += "1 0 0 1 0 " + FToStr(((fontSize() - fontSize() * (gl.scaleV)) / fontSize()) * -1) + " cm\n";
+
+			transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1));
+			m_pathBuffer += transformToStr(transform) + " cm\n";
+
+			if (!FillColor.isEmpty())
+				m_pathBuffer += pdfFont.name + Pdf::toPdf(gl.glyph) + " Do\n";
+
+			FPointArray outline = font().glyphOutline(gl.glyph);
+			QTransform mat;
+			mat.scale(0.1, 0.1);
+			outline.map(mat);
+			bool nPath = true;
+			FPoint np;
+			if (outline.size() > 3)
+			{
+				for (int poi = 0; poi < outline.size() - 3; poi += 4)
+				{
+					if (outline.isMarker(poi))
+					{
+						m_pathBuffer += "h\n";
+						nPath = true;
+						continue;
+					}
+
+					if (nPath)
+					{
+						np = outline.point(poi);
+						m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " m\n";
+						nPath = false;
+					}
+
+					np = outline.point(poi + 1);
+					m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " ";
+					np = outline.point(poi + 3);
+					m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " ";
+					np = outline.point(poi + 2);
+					m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " c\n";
+				}
+			}
+			m_pathBuffer += "h s\n";
+			m_pathBuffer += "Q\n";
+		}
+		else
+		{
+			if (!StrokeColor.isEmpty())
+				m_pathBuffer += StrokeColor;
+
+			uint gid = gl.glyph;
+			uint fontNr = 65535;
+			switch (pdfFont.encoding)
+			{
+			case  Encode_256:
+				gid = pdfFont.glyphmap[gid];
+				fontNr = gid / 256;
+				gid = gid % 256;
+				break;
+			case Encode_224:
+				fontNr = gid / 224;
+				gid = gid % 224 + 32;
+				break;
+			case Encode_Subset:
+				gid = pdfFont.glyphmap[gid];
+				break;
+			case Encode_IdentityH:
+				break;
+			}
+
+			if (fontNr == 65535)
+				m_glyphBuffer += pdfFont.name + " " + FToStr(fontSize()) + " Tf\n";
+			else
+				m_glyphBuffer += pdfFont.name + "S" + Pdf::toPdf(fontNr) + " " + FToStr(fontSize()) + " Tf\n";
+
+			if (!StrokeColor.isEmpty())
+				m_glyphBuffer += StrokeColor;
+
+			if (!FillColor.isEmpty())
+				m_glyphBuffer += FillColor;
+
+			if (pdfFont.method == Use_Type3 && !StrokeColor.isEmpty())
+			{
+				m_pathBuffer += "q\n";
+				m_pathBuffer += FToStr(strokeWidth()) + " w\n[] 0 d\n0 J\n0 j\n";
+
+				transform.scale(fontSize(), fontSize());
+				transform.translate(x(), y());
+				if (gl.scaleV != 1.0)
+					transform.translate(0, ((fontSize() - fontSize() * gl.scaleV) / fontSize()) * -1);
+				transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1));
+				m_pathBuffer += transformToStr(transform) + " cm\n";
+
+				/* paint outline */
+				FPointArray outline = font().glyphOutline(gl.glyph);
+				QTransform mat;
+				mat.scale(0.1, 0.1);
+				outline.map(mat);
+				bool nPath = true;
+				FPoint np;
+				if (outline.size() > 3)
+				{
+					for (int poi = 0; poi < outline.size() - 3; poi += 4)
+					{
+						if (outline.isMarker(poi))
+						{
+							m_pathBuffer += "h\n";
+							nPath = true;
+							continue;
+						}
+
+						if (nPath)
+						{
+							np = outline.point(poi);
+							m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " m\n";
+							nPath = false;
+						}
+
+						np = outline.point(poi + 1);
+						m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " ";
+						np = outline.point(poi + 3);
+						m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " ";
+						np = outline.point(poi + 2);
+						m_pathBuffer += FToStr(np.x()) + " " + FToStr(-np.y()) + " c\n";
+					}
+				}
+				m_pathBuffer += "h s\n";
+				m_pathBuffer += "Q\n";
+			}
+			else
+			{
+				m_glyphBuffer += FToStr(strokeWidth()) + " w ";
+				if (fill)
+					m_glyphBuffer += "2 Tr\n";
+				else
+					m_glyphBuffer += "1 Tr\n";
+			}
+
+			transform.translate(x(), y());
+			transform.scale(qMax(gl.scaleH, 0.1), qMax(gl.scaleV, 0.1));
+			m_glyphBuffer += transformToStr(transform) + " Tm\n";
+
+			if (pdfFont.method != Use_Type3 || !FillColor.isEmpty())
+			{
+				switch (pdfFont.encoding)
+				{
+				case Encode_224:
+				case Encode_256:
+					m_glyphBuffer += Pdf::toHexString8(gid) + " Tj\n";
+					break;
+				case Encode_IdentityH:
+				default:
+					m_glyphBuffer += Pdf::toHexString16(gid) + " Tj\n";
+					break;
+				}
+			}
+		}
+	}
+
+	void drawLine(QPointF start, QPointF end)
+	{
+		QTransform transform = matrix();
+		transform.translate(x(), y());
+		m_pathBuffer += "q\n";
+		m_pathBuffer += transformToStr(transform) + " cm\n";
+		m_pathBuffer += m_pdf->putColor(strokeColor().color, strokeColor().shade, false);
+		m_pathBuffer += FToStr(strokeWidth())+" w\n";
+		m_pathBuffer += FToStr(start.x()) + " " + FToStr(-start.y()) + " m\n";
+		m_pathBuffer += FToStr(end.x()) + " " + FToStr(-end.y()) + " l\n";
+		m_pathBuffer += "S\n";
+		m_pathBuffer += "Q\n";
+	}
+
+	QByteArray getBuffer()
+	{
+		return "BT\n" + m_glyphBuffer + "ET\n" + m_pathBuffer;
+	}
+
+	void drawRect(QRectF rect)
+	{
+		QTransform transform = matrix();
+//		transform.translate(x(), y());
+		double rectX = x() + rect.x();
+		double rectY = -y() - rect.y();
+		m_glyphBuffer += "q\n";
+		m_glyphBuffer += transformToStr(transform) + " cm\n";
+		m_glyphBuffer += "n\n";
+		m_glyphBuffer += m_pdf->putColor(fillColor().color, fillColor().shade, true);
+		m_glyphBuffer += m_pdf->putColor(strokeColor().color, strokeColor().shade, false);
+		m_glyphBuffer += FToStr(rectX) + " " + FToStr(rectY) + " m\n";
+		m_glyphBuffer += FToStr(rectX + rect.width()) + " " + FToStr(rectY) + " l\n";
+		m_glyphBuffer += FToStr(rectX + rect.width()) + " " + FToStr(rectY - rect.height()) + " l\n";
+		m_glyphBuffer += FToStr(rectX) + " " + FToStr(rectY - rect.height()) + " l\n";
+		m_glyphBuffer += "h\nf\n";
+		m_glyphBuffer += "Q\n";
+	}
+
+	void drawObject(PageItem* embedded)
+	{
+		m_glyphBuffer += "ET\n"+m_pathBuffer;
+		m_pathBuffer = "";
+
+		m_pathBuffer += "q\n";
+		m_pathBuffer += FToStr(scaleH()) + " 0 0 " + FToStr(scaleV()) + " " + FToStr(x()) + " " + FToStr(-y()) + " cm\n";
+
+		QByteArray output;
+		if (!m_pdf->PDF_ProcessItem(output, embedded, m_page, m_PNr, true))
+			return;
+		m_pathBuffer += output;
+		m_pathBuffer += "Q\n";
+		m_glyphBuffer += m_pathBuffer+"\n";
+		m_pathBuffer = "";
+
+		m_glyphBuffer += "BT\n";
+	}
+};
 
 PDFLibCore::PDFLibCore(ScribusDoc & docu)
 	: QObject(&docu),
@@ -170,13 +542,6 @@
 	delete progressDialog;
 }
 
-static inline QByteArray FToStr(double c)
-{
-	double v = c;
-	if (fabs(c) < 0.0000001)
-		v = 0.0;
-	return QByteArray::number(v, 'f', 5);
-};
 
 bool PDFLibCore::PDF_IsPDFX()
 {
@@ -5380,853 +5745,10 @@
 // Return a PDF substring representing a PageItem's text
 QByteArray PDFLibCore::setTextSt(PageItem *ite, uint PNr, const ScPage* pag)
 {
-	int tabCc = 0;
-	int savedOwnPage = ite->OwnPage;
-	double tabDist = ite->textToFrameDistLeft();
-	QByteArray tmp(""), tmp2("");
-	QList<ParagraphStyle::TabRecord> tTabValues;
-	ite->OwnPage = PNr;
-	ite->layout();
-	ite->OwnPage = savedOwnPage;
-	if (ite->lineColor() != CommonStrings::None)
-		tabDist += ite->lineWidth() / 2.0;
-	// Loop over each character (!) in the pageItem...
-	if (ite->itemType() == PageItem::TextFrame)
-	{
-		PathData straightPath;
-		straightPath.PtransX = 0;
-		straightPath.PtransY = 0;
-		straightPath.PRot = 0;
-		straightPath.PDx = 0;
-		tmp += "BT\n";
-		uint llp = 0;
-		while (llp < ite->textLayout.lines())
-		{
-			LineSpec ls = ite->textLayout.line(llp++);
-			const ParagraphStyle& LineStyle = ite->itemText.paragraphStyle(ls.firstItem);
-			if (LineStyle.backgroundColor() != CommonStrings::None)
-			{
-				double y0 = ls.y;
-				double y2 = ls.y;
-				double ascent = ls.ascent;
-				double descent = ls.descent;
-				double rMarg = LineStyle.rightMargin();
-				double lMarg = ls.colLeft;
-				double adjX = 0;
-				if (LineStyle.firstIndent() <= 0)
-					adjX += LineStyle.leftMargin() + LineStyle.firstIndent();
-				while (llp < ite->textLayout.lines())
-				{
-					ls = ite->textLayout.line(llp);
-					if ((ls.colLeft > lMarg) || (ite->itemText.paragraphStyle(ls.firstItem) != LineStyle))
-					{
-						if (y2 == 0)
-							y2 = y0;
-						break;
-					}
-					if (ite->itemText.text(ls.lastItem) == SpecialChars::PARSEP)
-					{
-						y2 = ls.y;
-						descent = ls.descent;
-						if ((llp + 1) < ite->textLayout.lines())
-						{
-							if ((ite->textLayout.line(llp + 1).lastItem - ite->textLayout.line(llp + 1).firstItem) > 0)
-								descent += LineStyle.lineSpacing() - (ls.descent + ite->textLayout.line(llp + 1).ascent);
-						}
-						llp++;
-						break;
-					}
-					y2 = ls.y;
-					descent = ls.descent;
-					if ((llp + 1) < ite->textLayout.lines())
-						descent += LineStyle.lineSpacing() - (ls.descent + ite->textLayout.line(llp + 1).ascent);
-					llp++;
-				}
-				QRectF scr(lMarg + adjX, y0 - ascent, ite->asTextFrame()->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent);
-				tmp += "q\n";
-				tmp += "n\n";
-				tmp += SetPathAndClip(ite);
-				tmp += putColor(LineStyle.backgroundColor(), LineStyle.backgroundShade(), true);
-				tmp += FToStr(scr.x())     +" "+FToStr(-scr.y())+" m\n";
-				tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y())+" l\n";
-				tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y() - scr.height())+" l\n";
-				tmp += FToStr(scr.x())+" "+FToStr(-scr.y() - scr.height())+" l\n";
-				tmp += "h\nf\n";
-				tmp += "Q\n";
-			}
-		}
-		for (uint ll=0; ll < ite->textLayout.lines(); ++ll)
-		{
-			LineSpec ls = ite->textLayout.line(ll);
-			tabDist = ls.x;
-			double CurX = ls.x;
-			double CurXB = ls.x;
-			int last = qMin(ls.lastItem, ite->itemText.length() - 1);
-			QRectF scr;
-			QString oldBack = "";
-			double oldShade = 100;
-			QByteArray colorB = "";
-			for (int a = ls.firstItem; a <= last; ++a)
-			{
-				const GlyphLayout* glyphs(ite->itemText.getGlyphs(a));
-				const CharStyle& charStyle(ite->itemText.charStyle(a));
-				if (charStyle.backColor() != CommonStrings::None)
-				{
-					colorB = putColor(charStyle.backColor(), charStyle.backShade(), true);
-				// This code is for rendering character background color.
-					const ParagraphStyle& LineStyle = ite->itemText.paragraphStyle(ls.firstItem);
-					double y1 = ls.y;
-					double hl = ls.height;
-					if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-						hl = doc.guidesPrefs().valueBaselineGrid;
-					else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
-						hl = LineStyle.lineSpacing();
-					if (ls.isFirstLine)
-					{
-						if (ite->textLayout.lines() == 1)
-							hl = ls.ascent + ls.descent;
-						if (LineStyle.hasDropCap() && (a == ls.firstItem))
-							hl *= LineStyle.dropCapLines();
-						if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-							y1 -= LineStyle.lineSpacing();
-						else if (ite->firstLineOffset() == FLOPRealGlyphHeight || ite->firstLineOffset() == FLOPFontAscent)
-							y1 -= ls.ascent;
-						else
-							y1 -= LineStyle.lineSpacing();
-					}
-					else
-						y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0;
-					QRectF scrG;
-					if (ite->itemText.hasObject(a))
-					{
-						PageItem* obj = ite->itemText.object(a);
-						double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH;
-						double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV;
-						scrG = QRectF(CurXB, ls.y - hh, ww , hh);
-					}
-					else
-						scrG = QRectF(CurXB, y1, glyphs->wide(), hl);
-					if ((oldBack == "") || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade())))
-						scr |= scrG;
-					else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade()))
-					{
-						tmp += "q\n";
-						tmp += "n\n";
-						tmp += putColor(oldBack, oldShade, true);
-						tmp += FToStr(scr.x())     +" "+FToStr(-scr.y())+" m\n";
-						tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y())+" l\n";
-						tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y() - scr.height())+" l\n";
-						tmp += FToStr(scr.x())+" "+FToStr(-scr.y() - scr.height())+" l\n";
-						tmp += "h\nf\n";
-						tmp += "Q\n";
-						scr = scrG;
-					}
-					oldBack = charStyle.backColor();
-					oldShade = charStyle.backShade();
-				}
-				else
-				{
-					if (!scr.isNull())
-					{
-						tmp += "q\n";
-						tmp += colorB;
-						tmp += FToStr(scr.x())     +" "+FToStr(-scr.y())+" m\n";
-						tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y())+" l\n";
-						tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y() - scr.height())+" l\n";
-						tmp += FToStr(scr.x())+" "+FToStr(-scr.y() - scr.height())+" l\n";
-						tmp += "h\nf\n";
-						tmp += "Q\n";
-					}
-					oldBack = "";
-					oldShade = 100;
-					scr = QRectF();
-				}
-				CurXB += glyphs->wide();
-			}
-			if (!scr.isNull())
-			{
-				tmp += "q\n";
-				tmp += colorB;
-				tmp += FToStr(scr.x())     +" "+FToStr(-scr.y())+" m\n";
-				tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y())+" l\n";
-				tmp += FToStr(scr.x() + scr.width())+" "+FToStr(-scr.y() - scr.height())+" l\n";
-				tmp += FToStr(scr.x())+" "+FToStr(-scr.y() - scr.height())+" l\n";
-				tmp += "h\nf\n";
-				tmp += "Q\n";
-			}
-			for (int d = ls.firstItem; d <= ls.lastItem; ++d)
-			{
-				GlyphLayout* glyphs = ite->itemText.getGlyphs(d);
-				PathData* pdata = &straightPath;
-				const QChar ch = ite->itemText.text(d);
-				const CharStyle& chstyle(ite->itemText.charStyle(d));
-				const ParagraphStyle& pstyle(ite->itemText.paragraphStyle(d));
-				if (SpecialChars::isBreak(ch, true) || (ch == QChar(10)))
-					continue;
-				if (ite->itemText.hasFlag(d, ScLayout_SuppressSpace))
-					continue;
-				tTabValues = pstyle.tabValues();
-				if (ite->itemText.hasFlag(d, ScLayout_StartOfLine))
-					tabCc = 0;
-				if ((ch == SpecialChars::TAB) && (tTabValues.count() != 0))
-				{
-					QChar tabFillChar;
-					const TabLayout* tabLayout = dynamic_cast<const TabLayout*>(glyphs->more);
-					if (tabLayout)
-						tabFillChar = tabLayout->fillChar;
-					if (!tabFillChar.isNull())
-					{
-						GlyphLayout gl2;
-						CharStyle cl2(chstyle);
-						const GlyphLayout * const gl = glyphs->more;
-						double scale = gl ? gl->scaleV : 1.0;
-						double wt    = chstyle.font().charWidth(tabFillChar, chstyle.fontSize() * scale / 10.0);
-						double len   = glyphs->xadvance;
-						int coun     = static_cast<int>(len / wt);
-						// #6728 : update code according to fillInTabLeaders() and PageItem::layout() - JG
-						double sPos  = 0.0 /*CurX - len + chstyle.fontSize() / 10.0 * 0.7 + 1*/;
-						//hl2.ch = tTabValues[tabCc].tabFillChar;
-						cl2.setTracking(0);
-						cl2.setScaleH(1000);
-						cl2.setScaleV(1000);
-						gl2.glyph   = chstyle.font().char2CMap(tabFillChar);
-						gl2.yoffset = glyphs->yoffset;
-						for (int cx = 0; cx < coun; ++cx)
-						{
-							gl2.xoffset =  sPos + wt * cx;
-							if ((chstyle.effects() & ScStyle_Shadowed) && (chstyle.strokeColor() != CommonStrings::None))
-							{
-								GlyphLayout gl3;
-								CharStyle cl3(cl2);
-								//<< HACK to fix Bug #8446
-								cl3.setEffects(cl3.effects() & (~(ScStyle_Outline)));
-								//>>
-								gl3.glyph = gl2.glyph;
-								cl3.setFillColor(cl2.strokeColor());
-								cl3.setFillShade(cl2.strokeShade());
-								gl3.yoffset = gl2.yoffset - (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0);
-								gl3.xoffset = gl2.xoffset + (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0);
-								setTextCh(ite, PNr, CurX, ls.y, d, tmp, tmp2, cl3, &gl3, pdata, pstyle, pag);
-							}
-							setTextCh(ite, PNr, CurX, ls.y, d, tmp, tmp2, cl2, &gl2, pdata, pstyle, pag);
-						}
-					}
-					tabCc++;
-				}
-				if (ch == SpecialChars::TAB)
-				{
-					CurX += glyphs->wide();
-					continue;
-				}
-				if ((chstyle.effects() & ScStyle_Shadowed) && (chstyle.strokeColor() != CommonStrings::None))
-				{
-					GlyphLayout gl2(*glyphs);
-					gl2.glyph = glyphs->glyph;
-					const GlyphLayout *gl1 = glyphs;
-					GlyphLayout* glx = &gl2;
-					while (gl1->more)
-					{
-						glx->more = new GlyphLayout(*gl1->more);
-						glx->more->yoffset -= (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0);
-						glx->more->xoffset += (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0);
-						glx->more->more = NULL;
-						gl1 = gl1->more;
-						glx = glx->more;
-					}
-					CharStyle cl2(chstyle);
-					//<< HACK to fix Bug #8446
-					cl2.setEffects(cl2.effects() & (~(ScStyle_Outline)));
-					//>>
-					cl2.setFillColor(chstyle.strokeColor());
-					cl2.setFillShade(chstyle.strokeShade());
-					gl2.xadvance = glyphs->xadvance;
-					gl2.yadvance = glyphs->yadvance;
-					gl2.yoffset = glyphs->yoffset - (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0);
-					gl2.xoffset = glyphs->xoffset + (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0);
-					gl2.scaleH = glyphs->scaleH;
-					gl2.scaleV = glyphs->scaleV;
-					setTextCh(ite, PNr, CurX, ls.y, d, tmp, tmp2, cl2, &gl2, pdata, pstyle, pag);
-					gl2.shrink();
-				}
-				setTextCh(ite, PNr, CurX, ls.y, d, tmp, tmp2, chstyle, glyphs, pdata, pstyle, pag);
-				// Unneeded now that glyph xadvance is set appropriately for inline objects by PageItem_TextFrame::layout() - JG
-				/*if (hl->ch == SpecialChars::OBJECT)
-				{
-					InlineFrame& embedded(const_cast<InlineFrame&>(hl->embedded));
-					CurX += (embedded.getItem()->gWidth + embedded.getItem()->lineWidth()) * hl->glyph.scaleH;
-				}
-				else*/
-				CurX += glyphs->wide();
-				tabDist = CurX;
-			}
-		}
-	}
-	else
-	{
-		ite->OwnPage = PNr;
-		ite->asPathText()->layout();
-		ite->OwnPage = savedOwnPage;
-		double CurX = 0;
-		for (int d = 0; d < ite->maxCharsInFrame(); ++d)
-		{
-			GlyphLayout* glyphs = ite->asPathText()->itemRenderText.getGlyphs(d);
-			PathData* pdata = &ite->textLayout.point(d);
-			const QChar ch = ite->asPathText()->itemRenderText.text(d);
-			const CharStyle& chstyle(ite->asPathText()->itemRenderText.charStyle(d));
-			const ParagraphStyle& pstyle(ite->asPathText()->itemRenderText.paragraphStyle(d));
-			if (SpecialChars::isBreak(ch, true) || (ch == QChar(10)))
-				continue;
-			if (ite->asPathText()->itemRenderText.hasFlag(d,  ScLayout_SuppressSpace))
-				continue;
-			tTabValues = pstyle.tabValues();
-			if (ite->asPathText()->itemRenderText.hasFlag(d,  ScLayout_StartOfLine))
-				tabCc = 0;
-			if ((ch == SpecialChars::TAB) && (tTabValues.count() != 0))
-			{
-				if ((tabCc < tTabValues.count()) && (!tTabValues[tabCc].tabFillChar.isNull()))
-				{
-					GlyphLayout gl2;
-					CharStyle cl2(chstyle);
-					double wt = chstyle.font().charWidth(tTabValues[tabCc].tabFillChar, chstyle.fontSize());
-					int coun = static_cast<int>((CurX+ glyphs->xoffset - tabDist) / wt);
-					// #6728 : update code according to fillInTabLeaders() and PageItem::layout() - JG
-					double sPos = 0.0 /* CurX+hl->glyph.xoffset - (CurX+hl->glyph.xoffset - tabDist) + 1 */;
-					gl2.glyph = chstyle.font().char2CMap(tTabValues[tabCc].tabFillChar);
-					cl2.setTracking(0);
-					cl2.setScaleH(1000);
-					cl2.setScaleV(1000);
-					gl2.yoffset = glyphs->yoffset;
-					for (int cx = 0; cx < coun; ++cx)
-					{
-						glyphs->xoffset =  sPos + wt * cx;
-						if ((chstyle.effects() & ScStyle_Shadowed) && (chstyle.strokeColor() != CommonStrings::None))
-						{
-							GlyphLayout gl3;
-							CharStyle cl3(cl2);
-							//<< HACK to fix Bug #8446
-							cl3.setEffects(cl3.effects() & (~(ScStyle_Outline)));
-							//>>
-							gl3.glyph = gl2.glyph;
-							cl3.setFillColor(cl2.strokeColor());
-							cl3.setFillShade(cl2.strokeShade());
-							gl3.yoffset = gl2.yoffset - (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0);
-							gl3.xoffset = gl2.xoffset + (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0);
-							setTextCh(ite, PNr, 0, 0, d, tmp, tmp2, cl3, &gl3, pdata, pstyle, pag);
-						}
-						setTextCh(ite, PNr, 0, 0, d, tmp, tmp2, cl2, &gl2, pdata, pstyle, pag);
-					}
-					tabCc++;
-				}
-				else
-				{
-					tabCc++;
-				}
-			}
-			if (ch == SpecialChars::TAB)
-			{
-				CurX += glyphs->wide();
-				continue;
-			}
-			if ((chstyle.effects() & ScStyle_Shadowed) && (chstyle.strokeColor() != CommonStrings::None))
-			{
-				GlyphLayout gl2;
-				gl2.glyph = glyphs->glyph;
-				CharStyle cl2(chstyle);
-				//<< HACK to fix Bug #8446
-				cl2.setEffects(cl2.effects() & (~(ScStyle_Outline)));
-				//>>
-				cl2.setFillColor(chstyle.strokeColor());
-				cl2.setFillShade(chstyle.strokeShade());
-				gl2.yoffset = glyphs->yoffset - (chstyle.fontSize() * chstyle.shadowYOffset() / 10000.0);
-				gl2.xoffset = glyphs->xoffset + (chstyle.fontSize() * chstyle.shadowXOffset() / 10000.0);
-				gl2.scaleH = glyphs->scaleH;
-				gl2.scaleV = glyphs->scaleV;
-				setTextCh(ite, PNr, 0, 0, d, tmp, tmp2, cl2, &gl2, pdata, pstyle, pag);
-			}
-			setTextCh(ite, PNr, 0, 0, d, tmp, tmp2, chstyle, glyphs, pdata, pstyle, pag);
-			CurX += glyphs->wide();
-			tabDist = CurX;
-		}
-	}
-	if (ite->itemType() == PageItem::TextFrame)
-		tmp += "ET\n"+tmp2;
-	return tmp;
-}
-
-bool PDFLibCore::setTextCh(PageItem *ite, uint PNr, double x, double y, uint d, QByteArray &tmp, QByteArray &tmp2, const CharStyle& style, GlyphLayout *glyphs, PathData* pdata, const ParagraphStyle& pstyle, const ScPage* pag)
-{
-	QByteArray output;
-	QByteArray FillColor = "";
-	QByteArray StrokeColor = "";
-	if (ite->asPathText())
-	{
-		tmp += "q\n";
-		QPointF tangt = QPointF( cos(pdata->PRot), sin(pdata->PRot) );
-		QTransform trafo = QTransform( 1, 0, 0, -1, -pdata->PDx, 0 );
-		if (ite->textPathFlipped)
-			trafo *= QTransform(1, 0, 0, -1, 0, 0);
-		if (ite->textPathType == 0)
-			trafo *= QTransform( tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata->PtransX, -pdata->PtransY );
-		else if (ite->textPathType == 1)
-			trafo *= QTransform(1, 0, 0, -1, pdata->PtransX, -pdata->PtransY );
-		else if (ite->textPathType == 2)
-		{
-			double a = 1;
-			double b = -1;
-			if (tangt.x() < 0)
-			{
-				a = -1;
-				b = 1;
-			}
-			if (fabs(tangt.x()) > 0.1)
-				trafo *= QTransform( a, (tangt.y() / tangt.x()) * b, 0, -1, pdata->PtransX, -pdata->PtransY ); // ID's Skew mode
-			else
-				trafo *= QTransform( a, 6 * b, 0, -1, pdata->PtransX, -pdata->PtransY );
-		}
-		tmp += FToStr(trafo.m11())+" "+FToStr(trafo.m12())+" "+FToStr(trafo.m21())+" "+FToStr(trafo.m22())+" "+FToStr(trafo.dx())+" "+FToStr(trafo.dy())+" cm\n";
-		if (ite->BaseOffs != 0)
-			tmp += "1 0 0 1 0 "+ FToStr( -ite->BaseOffs)+" cm\n";
-		if (glyphs->xoffset != 0.0 || glyphs->yoffset != 0.0)
-			tmp += "1 0 0 1 " + FToStr( glyphs->xoffset)+ " " + FToStr( -glyphs->yoffset)+" cm\n";
-		if (ite->itemText.text(d) != SpecialChars::OBJECT)
-			tmp += "BT\n";
-	}
-	QChar chstr = ite->itemText.text(d);
-	double tsz = style.fontSize();
-
-/*	if (hl->effects() & ScStyle_DropCap)
-	{
-		if (pstyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-			tsz = qRound(10 * ((doc.typographicSettings.valueBaseGrid * (pstyle.dropCapLines()-1)+(hl->font().ascent(pstyle.charStyle().fontSize() / 10.0))) / (hl->font().realCharHeight(chstr, 10))));
-		else
-		{
-			if (pstyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
-				tsz = qRound(10 * ((pstyle.lineSpacing() *  (pstyle.dropCapLines()-1)+(hl->font().ascent(pstyle.charStyle().fontSize() / 10.0))) / (hl->font().realCharHeight(chstr, 10))));
-			else
-			{
-				double currasce = hl->font().height(pstyle.charStyle().fontSize());
-				tsz = qRound(10 * ((currasce * (pstyle.dropCapLines()-1)+(hl->font().ascent(pstyle.charStyle().fontSize() / 10.0))) / hl->font().realCharHeight(chstr, 10)));
-			}
-		}
-	}
-	*/
-	if (ite->itemText.hasObject(d))
-	{
-		if (!ite->asPathText())
-		{
-			tmp += "ET\n"+tmp2;
-			tmp2 = "";
-		}
-		PageItem* embedded = ite->itemText.object(d);
-		tmp2 += "q\n";
-		if (ite->asPathText())
-			tmp2 +=  FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr((embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0)+embedded->gHeight * (style.baselineOffset() / 1000.0))+" cm\n";
-		else
-		{
-			if (d == 0 || ite->itemText.text(d-1) == SpecialChars::PARSEP)
-			{
-				if ((style.baselineOffset() != 0) && (!pstyle.hasDropCap()))
-					tmp2 +=  FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(x + glyphs->xoffset + embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr(-y- glyphs->yoffset + (embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0)+embedded->height() * (style.baselineOffset() / 1000.0))+" cm\n";
-				else
-					tmp2 +=  FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(x+ glyphs->xoffset + embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr(-y- glyphs->yoffset + (embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0))+" cm\n";
-			}
-			else
-			{
-				if (style.baselineOffset() != 0)
-					tmp2 +=  FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(x+ glyphs->xoffset + embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr(-y- glyphs->yoffset + (embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0)+embedded->height() * (style.baselineOffset() / 1000.0))+" cm\n";
-				else
-					tmp2 +=  FToStr(style.scaleH() / 1000.0)+" 0 0 "+FToStr(style.scaleV() / 1000.0)+" "+FToStr(x+ glyphs->xoffset + embedded->gXpos * (style.scaleH() / 1000.0))+" "+FToStr(-y- glyphs->yoffset + (embedded->height() * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0))+" cm\n";
-			}
-		}
-		if (!PDF_ProcessItem(output, embedded, pag, PNr, true))
-			return false;
-		tmp2 +=output;
-		tmp2 += "Q\n";
-		tmp += tmp2+"\n";
-		tmp2 = "";
-		if (ite->asPathText())
-			tmp += "Q\n";
-		else
-			tmp += "BT\n";
-		return true;
-	}
-
-	PdfFont pdfFont = UsedFontsP[style.font().replacementName()];
-	uint glyph = glyphs->glyph;
-
-	if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode()) ||
-		glyph == (ScFace::CONTROL_GLYPHS + 32))
-	{
-		glyph = style.font().char2CMap(QChar(' '));
-		chstr = ' ';
-	}
-	else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode()))
-	{
-		glyph = style.font().char2CMap(QChar('-'));
-		chstr = '-';
-	}
-
-	if (glyph < ScFace::CONTROL_GLYPHS)
-	{
-		if (style.strokeColor() != CommonStrings::None)
-		{
-			StrokeColor = "";
-			StrokeColor += putColor(style.strokeColor(), style.strokeShade(), false);
-		}
-		if (style.fillColor() != CommonStrings::None)
-		{
-			FillColor = "";
-			FillColor += putColor(style.fillColor(), style.fillShade(), true);
-		}
-		if (((style.effects() & ScStyle_Underline) && (chstr != SpecialChars::PARSEP))  || ((style.effects() & ScStyle_UnderlineWords) && (!chstr.isSpace())))
-		{
-			//		double Ulen = style.font().charWidth(chstr, style.fontSize()) * (hl->glyph.scaleH);
-			double Ulen = glyphs->xadvance;
-			double Upos, Uwid;
-			if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1))
-			{
-				if (style.underlineOffset() != -1)
-					Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0));
-				else
-					Upos = style.font().underlinePos(style.fontSize() / 10.0);
-				if (style.underlineWidth() != -1)
-					Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0);
-				else
-					Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				Upos = style.font().underlinePos(style.fontSize() / 10.0);
-				Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			if (style.baselineOffset() != 0)
-				Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-			if (style.fillColor() != CommonStrings::None)
-				tmp2 += putColor(style.fillColor(), style.fillShade(), false);
-			tmp2 += FToStr(Uwid)+" w\n";
-			if (ite->itemType() == PageItem::PathText)
-			{
-				if (style.effects() & ScStyle_Subscript)
-				{
-					tmp2 += FToStr(x+ glyphs->xoffset)     +" "+FToStr(-y+Upos)+" m\n";
-					tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y+Upos)+" l\n";
-				}
-				else
-				{
-					tmp2 += FToStr(x+ glyphs->xoffset)     +" "+FToStr(-y+ glyphs->yoffset+Upos)+" m\n";
-					tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y+ glyphs->yoffset+Upos)+" l\n";
-				}
-			}
-			else
-			{
-				if (style.effects() & ScStyle_Subscript)
-				{
-					tmp2 += FToStr(x+ glyphs->xoffset)     +" "+FToStr(-y- glyphs->yoffset+Upos)+" m\n";
-					tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y- glyphs->yoffset+Upos)+" l\n";
-				}
-				else
-				{
-					tmp2 += FToStr(x+ glyphs->xoffset)     +" "+FToStr(-y+Upos)+" m\n";
-					tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y+Upos)+" l\n";
-				}
-			}
-			tmp2 += "S\n";
-		}
-		
-		if (pdfFont.method == Use_XForm)
-		{
-			if (glyph != style.font().char2CMap(QChar(' ')))
-			{
-				if ((style.strokeColor() != CommonStrings::None) && (style.effects() & ScStyle_Outline))
-				{
-					tmp2 += FToStr((tsz * style.outlineWidth() / 1000.0) / tsz)+" w\n[] 0 d\n0 J\n0 j\n";
-					tmp2 += StrokeColor;
-				}
-				if (style.fillColor() != CommonStrings::None)
-					tmp2 += FillColor;
-				tmp2 += "q\n";
-				// #see 8257 : transform is already computed at beginning of the function
-				/*if (ite->itemType() == PageItem::PathText)
-				{
-					QPointF tangt = QPointF( cos(hl->PRot), sin(hl->PRot) );
-					QTransform trafo = QTransform( 1, 0, 0, -1, -hl->PDx, 0 );
-					if (ite->textPathFlipped)
-						trafo *= QTransform(1, 0, 0, -1, 0, 0);
-					if (ite->textPathType == 0)
-						trafo *= QTransform(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), hl->PtransX, -hl->PtransY);
-					else if (ite->textPathType == 1)
-						trafo *= QTransform(1, 0, 0, -1, hl->PtransX, -hl->PtransY );
-					tmp2 += FToStr(trafo.m11())+" "+FToStr(trafo.m12())+" "+FToStr(trafo.m21())+" "+FToStr(trafo.m22())+" "+FToStr(trafo.dx())+" "+FToStr(trafo.dy())+" cm\n";
-				}*/
-				if (!ite->asPathText())
-				{
-					if (ite->reversed())
-					{
-						double wid = style.font().charWidth(chstr, style.fontSize()) * (glyphs->scaleH);
-						tmp2 += "1 0 0 1 "+FToStr(x+ glyphs->xoffset)+" "+FToStr((y+ glyphs->yoffset - (tsz / 10.0)) * -1 + ((tsz / 10.0) * (style.baselineOffset() / 1000.0)))+" cm\n";
-						tmp2 += "-1 0 0 1 0 0 cm\n";
-						tmp2 += "1 0 0 1 "+FToStr(-wid)+" 0 cm\n";
-						tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" 0 0 cm\n";
-					}
-					else
-					{
-						tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" "+FToStr(x+ glyphs->xoffset)+" "+FToStr((y+ glyphs->yoffset - (tsz / 10.0)) * -1 + ((tsz / 10.0) * (style.baselineOffset() / 1000.0)))+" cm\n";
-					}
-				}
-				else
-				{
-				//	if (ite->BaseOffs != 0)
-				//		tmp2 += "1 0 0 1 0 "+FToStr( -ite->BaseOffs)+" cm\n";
-					tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" 0 "+FToStr(tsz / 10.0)+" cm\n";
-				}
-				if (glyphs->scaleV != 1.0)
-					tmp2 += "1 0 0 1 0 "+FToStr( (((tsz / 10.0) - (tsz / 10.0) * (glyphs->scaleV)) / (tsz / 10.0)) * -1)+" cm\n";
-				tmp2 += FToStr(qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1))+" 0 0 cm\n";
-				if (style.fillColor() != CommonStrings::None)
-				    tmp2 += pdfFont.name + Pdf::toPdf(glyph)+" Do\n";
-				
-				if (style.effects() & ScStyle_Outline)
-				{
-					FPointArray gly = style.font().glyphOutline(glyph);
-					QTransform mat;
-					mat.scale(0.1, 0.1);
-					gly.map(mat);
-					bool nPath = true;
-					FPoint np;
-					if (gly.size() > 3)
-					{
-						for (int poi=0; poi<gly.size()-3; poi += 4)
-						{
-							if (gly.isMarker(poi))
-							{
-								tmp2 += "h\n";
-								nPath = true;
-								continue;
-							}
-							if (nPath)
-							{
-								np = gly.point(poi);
-								tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" m\n";
-								nPath = false;
-							}
-							np = gly.point(poi+1);
-							tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" ";
-							np = gly.point(poi+3);
-							tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" ";
-							np = gly.point(poi+2);
-							tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" c\n";
-						}
-					}
-					tmp2 += "h s\n";
-				}
-				tmp2 += "Q\n";
-			}
-		}
-		else
-		{
-			if (style.strokeColor() != CommonStrings::None)
-			{
-				if ((style.effects() & ScStyle_Underline) || (style.effects() & ScStyle_Strikethrough) || (style.effects() & ScStyle_Outline))
-					tmp2 += StrokeColor;
-			}
-			if (style.fillColor() != CommonStrings::None)
-			{
-				if ((style.effects() & ScStyle_Underline) || (style.effects() & ScStyle_Strikethrough))
-					tmp2 += FillColor;
-			}
-			if (glyph != style.font().char2CMap(QChar(' ')))
-			{
-				uint gid = glyphs->glyph;
-				uint fontNr = 65535;
-				switch (pdfFont.encoding)
-				{
-					case  Encode_256:
-						gid = pdfFont.glyphmap[gid];
-						fontNr = gid / 256;
-						gid = gid % 256;
-						break;
-					case Encode_224:
-						fontNr = gid / 224;
-						gid = gid % 224 + 32;
-						break;
-					case Encode_Subset:
-						gid = pdfFont.glyphmap[gid];
-						break;
-					case Encode_IdentityH:
-						break;
-				}
-				if (fontNr == 65535)
-					tmp+= pdfFont.name + " " + FToStr(tsz / 10.0)+" Tf\n";
-				else
-					tmp += pdfFont.name+"S"+Pdf::toPdf(fontNr) + " "+FToStr(tsz / 10.0)+" Tf\n";
-				if (style.strokeColor() != CommonStrings::None)
-					tmp += StrokeColor;
-				if (style.fillColor() != CommonStrings::None)
-					tmp += FillColor;
-				if (pdfFont.method == Use_Type3 && (style.effects() & ScStyle_Outline) && (style.strokeColor() != CommonStrings::None))
-				{
-					tmp2 += "q\n";
-					tmp2 += FToStr((tsz * style.outlineWidth() / 1000.0) / tsz)+" w\n[] 0 d\n0 J\n0 j\n";
-					// #see 8257 : transform is already computed at beginning of the function
-					/*if (ite->itemType() == PageItem::PathText)
-					{
-						QPointF tangt = QPointF( cos(hl->PRot), sin(hl->PRot) );
-						QTransform trafo = QTransform( 1, 0, 0, -1, -hl->PDx, 0 );
-						if (ite->textPathFlipped)
-							trafo *= QTransform(1, 0, 0, -1, 0, 0);
-						if (ite->textPathType == 0)
-							trafo *= QTransform(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), hl->PtransX, -hl->PtransY);
-						else if (ite->textPathType == 1)
-							trafo *= QTransform(1, 0, 0, -1, hl->PtransX, -hl->PtransY );
-						tmp2 += FToStr(trafo.m11())+" "+FToStr(trafo.m12())+" "+FToStr(trafo.m21())+" "+FToStr(trafo.m22())+" "+FToStr(trafo.dx())+" "+FToStr(trafo.dy())+" cm\n";
-					}*/
-					if (!ite->asPathText())
-					{
-						if (ite->reversed())
-						{
-							double wid = style.font().charWidth(chstr, style.fontSize()) * (glyphs->scaleH);
-							tmp2 += "1 0 0 1 "+FToStr(x+ glyphs->xoffset)+" "+FToStr((y+ glyphs->yoffset - (tsz / 10.0)) * -1 + ((tsz / 10.0) * (style.baselineOffset() / 1000.0)))+" cm\n";
-							tmp2 += "-1 0 0 1 0 0 cm\n";
-							tmp2 += "1 0 0 1 "+FToStr(-wid)+" 0 cm\n";
-							tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" 0 0 cm\n";
-						}
-						else
-						{
-							tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" "+FToStr(x+ glyphs->xoffset)+" "+FToStr((y+ glyphs->yoffset - (tsz / 10.0)) * -1 + ((tsz / 10.0) * (style.baselineOffset() / 1000.0)))+" cm\n";
-						}
-					}
-					else
-					{
-						tmp2 += FToStr(tsz / 10.0)+" 0 0 "+FToStr(tsz / 10.0)+" 0 "+FToStr(tsz / 10.0)+" cm\n";
-					}
-					if (glyphs->scaleV != 1.0)
-						tmp2 += "1 0 0 1 0 "+FToStr( (((tsz / 10.0) - (tsz / 10.0) * (glyphs->scaleV)) / (tsz / 10.0)) * -1)+" cm\n";
-					tmp2 += FToStr(qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1))+" 0 0 cm\n";
-					/* paint outline */
-					FPointArray gly = style.font().glyphOutline(glyph);
-					QTransform mat;
-					mat.scale(0.1, 0.1);
-					gly.map(mat);
-					bool nPath = true;
-					FPoint np;
-					if (gly.size() > 3)
-					{
-						for (int poi=0; poi<gly.size()-3; poi += 4)
-						{
-							if (gly.isMarker(poi))
-							{
-								tmp2 += "h\n";
-								nPath = true;
-								continue;
-							}
-							if (nPath)
-							{
-								np = gly.point(poi);
-								tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" m\n";
-								nPath = false;
-							}
-							np = gly.point(poi+1);
-							tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" ";
-							np = gly.point(poi+3);
-							tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" ";
-							np = gly.point(poi+2);
-							tmp2 += FToStr(np.x())+" "+FToStr(-np.y())+" c\n";
-						}
-					}
-					tmp2 += "h s\n";
-					tmp2 += "Q\n";
-				}
-				else
-				{
-					if (style.effects() & ScStyle_Outline)
-						tmp += FToStr(tsz * style.outlineWidth() / 10000.0) + (style.fillColor() != CommonStrings::None ? " w 2 Tr\n" : " w 1 Tr\n");
-					else
-						tmp += "0 Tr\n";
-				}
-				if (!ite->asPathText())
-				{
-					if (ite->reversed())
-					{
-						double wtr = glyphs->xadvance;
-						tmp +=  FToStr(-qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1)) +" "+FToStr(x+ glyphs->xoffset+wtr)+" "+FToStr(-y- glyphs->yoffset+(style.fontSize() / 10.0) * (style.baselineOffset() / 1000.0))+" Tm\n";
-					}
-					else
-						tmp +=  FToStr(qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1))+" "+FToStr(x+ glyphs->xoffset)+" "+FToStr(-y- glyphs->yoffset+(style.fontSize() / 10.0) * (style.baselineOffset() / 1000.0))+" Tm\n";
-				}
-				else
-				{
-					tmp += FToStr(qMax(glyphs->scaleH, 0.1))+" 0 0 "+FToStr(qMax(glyphs->scaleV, 0.1))+" 0 0 Tm\n";
-				}
-				if (pdfFont.method != Use_Type3 || style.fillColor() != CommonStrings::None)
-				{
-					switch (pdfFont.encoding)
-					{
-						case Encode_224:
-						case Encode_256:
-							tmp += Pdf::toHexString8(gid) + " Tj\n";
-							break;
-						case Encode_IdentityH:
-						default:
-							tmp += Pdf::toHexString16(gid) + " Tj\n";
-							break;
-					}
-				}
-			}
-		}
-		if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP))
-		{
-			//		double Ulen = style.font().charWidth(chstr, style.fontSize()) * (hl->glyph.scaleH);
-			double Ulen = glyphs->xadvance;
-			double Upos, Uwid;
-			if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1))
-			{
-				if (style.strikethruOffset() != -1)
-					Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0));
-				else
-					Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-				if (style.strikethruWidth() != -1)
-					Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0);
-				else
-					Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-				Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			if (style.baselineOffset() != 0)
-				Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-			if (style.fillColor() != CommonStrings::None)
-				tmp2 += putColor(style.fillColor(), style.fillShade(), false);
-			tmp2 += FToStr(Uwid)+" w\n";
-			if (ite->itemType() == PageItem::PathText)
-			{
-				tmp2 += FToStr(x+ glyphs->xoffset)     +" "+FToStr(-y+Upos)+" m\n";
-				tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y+Upos)+" l\n";
-			}
-			else
-			{
-				tmp2 += FToStr(x+ glyphs->xoffset)     +" "+FToStr(-y- glyphs->yoffset+Upos)+" m\n";
-				tmp2 += FToStr(x+ glyphs->xoffset+Ulen)+" "+FToStr(-y- glyphs->yoffset+Upos)+" l\n";
-			}
-			tmp2 += "S\n";
-		}
-		if (ite->asPathText())
-		{
-			tmp += "ET\n"+tmp2+"Q\n";
-			tmp2 = "";
-		}
-	}
-	if (glyphs->more) {
-//		// ugly hack until setTextCh interface is changed
-//		ScText hl2(*hl);
-//		hl2.glyph = *(hl->glyph.more);
-		if (!setTextCh(ite, PNr, x + glyphs->xadvance, y, d, tmp, tmp2, style, glyphs->more, pdata, pstyle, pag))
-			return false;
-//		// don't let hl2's destructor delete these!
-//		hl2.glyph.more = 0;
-	}
-	return true;
+	PdfPainter p(ite, this, PNr, pag);
+	ite->textLayout.renderBackground(&p);
+	ite->textLayout.render(&p);
+	return p.getBuffer();
 }
 
 QByteArray PDFLibCore::SetColor(const QString& farbe, double Shade)

Modified: trunk/Scribus/scribus/pdflib_core.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pdflib_core.h
==============================================================================
--- trunk/Scribus/scribus/pdflib_core.h	(original)
+++ trunk/Scribus/scribus/pdflib_core.h	Wed Mar 23 20:21:36 2016
@@ -43,6 +43,8 @@
 
 #include "pdfwriter.h"
 
+class PdfPainter;
+
 /**
  * PDFLibCore provides Scribus's implementation of PDF export functionality.
  *
@@ -58,6 +60,8 @@
 class PDFLibCore : public QObject
 {
 	Q_OBJECT
+
+friend class PdfPainter;
 
 public:
 	explicit PDFLibCore(ScribusDoc & docu);
@@ -171,7 +175,6 @@
     QByteArray Write_FormXObject(QByteArray &data, PageItem *controlItem = 0);
 	QByteArray Write_TransparencyGroup(double trans, int blend, QByteArray &data, PageItem *controlItem = 0);
 	QByteArray setTextSt(PageItem *ite, uint PNr, const ScPage* pag);
-	bool    setTextCh(PageItem *ite, uint PNr, double x, double y, uint d,  QByteArray &tmp, QByteArray &tmp2, const CharStyle& cstyle, GlyphLayout *glyphs, PathData* pdata, const ParagraphStyle& pstyle, const ScPage* pag);
 	void    getBleeds(const ScPage* page, double &left, double &right);
 	void    getBleeds(const ScPage* page, double &left, double &right, double &bottom, double& top);
 

Modified: trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.cpp
==============================================================================
--- trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.cpp	(original)
+++ trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.cpp	Wed Mar 23 20:21:36 2016
@@ -55,6 +55,9 @@
 #include "sccolorengine.h"
 #include "util_formats.h"
 #include "util_math.h"
+#include "text/textlayout.h"
+#include "text/textlayoutpainter.h"
+#include "text/boxes.h"
 
 int svgexplugin_getPluginAPIVersion()
 {
@@ -368,10 +371,8 @@
 			ob = processImageItem(Item, trans, fill, stroke);
 			break;
 		case PageItem::TextFrame:
+		case PageItem::PathText:
 			ob = processTextItem(Item, trans, fill, stroke);
-			break;
-		case PageItem::PathText:
-			ob = processPathTextItem(Item, trans, stroke);
 			break;
 		case PageItem::Symbol:
 			ob = processSymbolItem(Item, trans);
@@ -1144,6 +1145,97 @@
 	return ob;
 }
 
+class SvgPainter: public TextLayoutPainter
+{
+	QDomElement m_elem;
+	SVGExPlug *m_svg;
+	QString m_trans;
+
+public:
+	SvgPainter(QString trans, SVGExPlug *svg, QDomElement &elem)
+		: m_elem(elem)
+		, m_svg(svg)
+		, m_trans(trans)
+	{}
+
+	void drawGlyph(const GlyphLayout gl)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		QTransform transform = matrix();
+		transform.translate(x(), y() - (fontSize() * gl.scaleV));
+		transform.scale(gl.scaleH * fontSize() / 10.0, gl.scaleV * fontSize() / 10.0);
+
+		QDomElement glyph = m_svg->docu.createElement("use");
+		glyph.setAttribute("xlink:href", "#" + m_svg->handleGlyph(gl.glyph, font()));
+		glyph.setAttribute("transform", m_svg->MatrixToStr(transform));
+		QString fill = "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";";
+		QString stroke = "stroke:none;";
+		glyph.setAttribute("style", fill + stroke);
+		m_elem.appendChild(glyph);
+	}
+
+	void drawGlyphOutline(const GlyphLayout gl, bool hasFill)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		QTransform transform = matrix();
+		transform.translate(x(), y() - (fontSize() * gl.scaleV));
+		transform.scale(gl.scaleH * fontSize() / 10.0, gl.scaleV * fontSize() / 10.0);
+		QDomElement glyph = m_svg->docu.createElement("use");
+		glyph.setAttribute("xlink:href", "#" + m_svg->handleGlyph(gl.glyph, font()));
+		glyph.setAttribute("transform", m_svg->MatrixToStr(transform));
+		QString fill = "fill:none;";
+		if (hasFill)
+			fill = "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";";
+		QString stroke ="stroke:" + m_svg->SetColor(strokeColor().color, strokeColor().shade) + ";";
+		stroke += " stroke-width:" + m_svg->FToStr(strokeWidth()) + ";";
+		glyph.setAttribute("style", fill + stroke);
+		m_elem.appendChild(glyph);
+	}
+
+	void drawLine(QPointF start, QPointF end)
+	{
+		QTransform transform = matrix();
+		transform.translate(x(), y());
+		QDomElement path = m_svg-> docu.createElement("path");
+		path.setAttribute("d", QString("M %1 %2 L%3 %4").arg(start.x()).arg(start.y()).arg(end.x()).arg(end.y()));
+		QString stroke = "stroke:none;";
+		if (fillColor().color != CommonStrings::None)
+		{
+			stroke = "stroke:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";";
+			stroke += " stroke-width:" + m_svg->FToStr(strokeWidth()) + ";";
+		}
+		path.setAttribute("style", "fill:none;" + stroke);
+		path.setAttribute("transform", m_svg->MatrixToStr(transform));
+		m_elem.appendChild(path);
+	}
+
+	void drawRect(QRectF rect)
+	{
+		QTransform transform = matrix();
+		transform.translate(x(), y());
+		QString paS = QString("M %1 %2 ").arg(rect.x()).arg(rect.y());
+		paS += QString("L %1 %2 ").arg(rect.x() + rect.width()).arg(rect.y());
+		paS += QString("L %1 %2 ").arg(rect.x() + rect.width()).arg(rect.y() + rect.height());
+		paS += QString("L %1 %2 ").arg(rect.x()).arg(rect.y() + rect.height());
+		paS += "Z";
+		QDomElement path = m_svg-> docu.createElement("path");
+		path.setAttribute("d", paS);
+		path.setAttribute("transform", m_svg->MatrixToStr(transform));
+		path.setAttribute("style", "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";" + "stroke:none;");
+		m_elem.appendChild(path);
+	}
+
+	void drawObject(PageItem* item)
+	{
+		QDomElement layerGroup = m_svg->processInlineItem(item, m_trans, scaleH(), scaleV());
+		m_elem.appendChild(layerGroup);
+	}
+};
+
 QDomElement SVGExPlug::processTextItem(PageItem *Item, QString trans, QString fill, QString stroke)
 {
 	QDomElement ob;
@@ -1168,14 +1260,6 @@
 		}
 	}
 	bool bFound = false;
-	for (uint ll=0; ll < Item->textLayout.lines(); ++ll)
-	{
-		if (Item->itemText.paragraphStyle(Item->textLayout.line(ll).firstItem).backgroundColor() != CommonStrings::None)
-		{
-			bFound = true;
-			break;
-		}
-	}
 	if (bFound)
 	{
 		QDomElement cl;
@@ -1188,633 +1272,13 @@
 		if (!ob2.isNull())
 			ob.setAttribute("clip-path", "url(#" + ob2.attribute("id") + ")");
 	}
-	double x, y, wide;
-	QString chstr;
-	uint llp = 0;
-	while (llp < Item->textLayout.lines())
-	{
-		LineSpec ls = Item->textLayout.line(llp++);
-		const ParagraphStyle& LineStyle = Item->itemText.paragraphStyle(ls.firstItem);
-		if (LineStyle.backgroundColor() != CommonStrings::None)
-		{
-			double y0 = ls.y;
-			double y2 = 0;
-			double ascent = ls.ascent;
-			double descent = ls.descent;
-			double rMarg = LineStyle.rightMargin();
-			double lMarg = ls.colLeft;
-			double adjX = 0;
-			if (LineStyle.firstIndent() <= 0)
-				adjX += LineStyle.leftMargin() + LineStyle.firstIndent();
-			while (llp < Item->textLayout.lines())
-			{
-				ls = Item->textLayout.line(llp);
-				if ((ls.colLeft > lMarg) || (Item->itemText.paragraphStyle(ls.firstItem) != LineStyle))
-				{
-					if (y2 == 0)
-						y2 = y0;
-					break;
-				}
-				if (Item->itemText.text(ls.lastItem) == SpecialChars::PARSEP)
-				{
-					y2 = ls.y;
-					descent = ls.descent;
-					if ((llp + 1) < Item->textLayout.lines())
-					{
-						if ((Item->textLayout.line(llp + 1).lastItem - Item->textLayout.line(llp + 1).firstItem) > 0)
-							descent += LineStyle.lineSpacing() - (ls.descent + Item->textLayout.line(llp + 1).ascent);
-					}
-					llp++;
-					break;
-				}
-				y2 = ls.y;
-				descent = ls.descent;
-				if ((llp + 1) < Item->textLayout.lines())
-					descent += LineStyle.lineSpacing() - (ls.descent + Item->textLayout.line(llp + 1).ascent);
-				llp++;
-			}
-			QRectF scr(lMarg + adjX, y0 - ascent, Item->asTextFrame()->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent);
-			QString paS = QString("M %1 %2 ").arg(scr.x()).arg(scr.y());
-			paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y());
-			paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y() + scr.height());
-			paS += QString("L %1 %2 ").arg(scr.x()).arg(scr.y() + scr.height());
-			paS += "Z";
-			QDomElement glyS = docu.createElement("path");
-			glyS.setAttribute("d", paS);
-			glyS.setAttribute("style", "fill:"+SetColor(LineStyle.backgroundColor(), LineStyle.backgroundShade())+";" + "stroke:none;");
-			ob.appendChild(glyS);
-		}
-	}
-	for (uint ll=0; ll < Item->textLayout.lines(); ++ll)
-	{
-		LineSpec ls = Item->textLayout.line(ll);
-		double CurX = ls.x;
-
-		double CurXB = ls.x;
-		int last = qMin(ls.lastItem, Item->itemText.length() - 1);
-		QRectF scr;
-		QString oldBack = "";
-		double oldShade = 100;
-		QString colorB = "";
-		for (int a = ls.firstItem; a <= last; ++a)
-		{
-			const GlyphLayout* glyphs(Item->itemText.getGlyphs(a));
-			const CharStyle& charStyle(Item->itemText.charStyle(a));
-			if (charStyle.backColor() != CommonStrings::None)
-			{
-			// This code is for rendering character background color.
-				colorB = SetColor(charStyle.backColor(), charStyle.backShade());
-				const ParagraphStyle& LineStyle = Item->itemText.paragraphStyle(ls.firstItem);
-				double y1 = ls.y;
-				double hl = ls.height;
-				if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-					hl = m_Doc->guidesPrefs().valueBaselineGrid;
-				else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
-					hl = LineStyle.lineSpacing();
-				if (ls.isFirstLine)
-				{
-					if (Item->textLayout.lines() == 1)
-						hl = ls.ascent + ls.descent;
-					if (LineStyle.hasDropCap() && (a == ls.firstItem))
-						hl *= LineStyle.dropCapLines();
-					if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-						y1 -= LineStyle.lineSpacing();
-					else if (Item->firstLineOffset() == FLOPRealGlyphHeight || Item->firstLineOffset() == FLOPFontAscent)
-						y1 -= ls.ascent;
-					else
-						y1 -= LineStyle.lineSpacing();
-				}
-				else
-					y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0;
-				QRectF scrG;
-				if (Item->itemText.hasObject(a))
-				{
-					PageItem* obj = Item->itemText.object(a);
-					double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH;
-					double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV;
-					scrG = QRectF(CurXB, ls.y - hh, ww , hh);
-				}
-				else
-					scrG = QRectF(CurXB, y1, glyphs->wide(), hl);
-				if ((oldBack == "") || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade())))
-					scr |= scrG;
-				else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade()))
-				{
-					QString paS = QString("M %1 %2 ").arg(scr.x()).arg(scr.y());
-					paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y());
-					paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y() + scr.height());
-					paS += QString("L %1 %2 ").arg(scr.x()).arg(scr.y() + scr.height());
-					paS += "Z";
-					QDomElement glyS = docu.createElement("path");
-					glyS.setAttribute("d", paS);
-					glyS.setAttribute("style", "fill:"+SetColor(oldBack, oldShade)+";" + "stroke:none;");
-					ob.appendChild(glyS);
-					scr = scrG;
-				}
-				oldBack = charStyle.backColor();
-				oldShade = charStyle.backShade();
-				// end background code
-			}
-			else
-			{
-				if (!scr.isNull())
-				{
-					QString paS = QString("M %1 %2 ").arg(scr.x()).arg(scr.y());
-					paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y());
-					paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y() + scr.height());
-					paS += QString("L %1 %2 ").arg(scr.x()).arg(scr.y() + scr.height());
-					paS += "Z";
-					QDomElement glyS = docu.createElement("path");
-					glyS.setAttribute("d", paS);
-					glyS.setAttribute("style", "fill:"+colorB+";" + "stroke:none;");
-					ob.appendChild(glyS);
-				}
-				oldBack = "";
-				oldShade = 100;
-				scr = QRectF();
-			}
-			CurXB += glyphs->wide();
-		}
-		if (!scr.isNull())
-		{
-			QString paS = QString("M %1 %2 ").arg(scr.x()).arg(scr.y());
-			paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y());
-			paS += QString("L %1 %2 ").arg(scr.x() + scr.width()).arg(scr.y() + scr.height());
-			paS += QString("L %1 %2 ").arg(scr.x()).arg(scr.y() + scr.height());
-			paS += "Z";
-			QDomElement glyS = docu.createElement("path");
-			glyS.setAttribute("d", paS);
-			glyS.setAttribute("style", "fill:"+colorB+";" + "stroke:none;");
-			ob.appendChild(glyS);
-		}
-
-		for (int a = ls.firstItem; a <= ls.lastItem; ++a)
-		{
-			x = 0.0;
-			y = 0.0;
-			//ScText * hl = Item->itemText.item_p(a);
-			const CharStyle& charStyle(Item->itemText.charStyle(a));
-            const GlyphLayout* glyphs = Item->itemText.getGlyphs(a);
-            PageItem* embItem = Item->itemText.hasObject(a)? Item->itemText.object(a) : NULL;
-            LayoutFlags flags = Item->itemText.flags(a);
-            
-			chstr = Item->itemText.text(a,1);
-			if ((chstr == QChar(13)) || (chstr == QChar(29)))
-			{
-				if (chstr == QChar(29))
-					CurX += glyphs->wide();
-				continue;
-			}
-			if (chstr == QChar(30))
-			{
-				chstr = Item->ExpandToken(a);
-				if (chstr == QChar(32))
-				{
-					CurX += glyphs->wide();
-					continue;
-				}
-			}
-			double chs = charStyle.fontSize();
-			if (charStyle.effects() & ScStyle_SmallCaps)
-			{
-				if (chstr.toUpper() != chstr)
-				{
-					chs = qMax(static_cast<int>(charStyle.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1);
-					chstr = chstr.toUpper();
-				}
-			}
-			else if (charStyle.effects() & ScStyle_AllCaps)
-				chstr = chstr.toUpper();
-			uint chr = chstr[0].unicode();
-			QTransform chma, chma2, chma3, chma4, chma6;
-			QTransform trafo = QTransform( 1, 0, 0, 1, CurX, ls.y );
-			if (Item->rotation() != 0)
-			{
-				QTransform sca;
-				sca.translate(-Item->xPos(), -Item->yPos());
-				trafo *= sca;
-			}
-			chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0);
-			if (Item->reversed())
-			{
-				if (a < Item->itemText.length()-1)
-					wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), Item->itemText.text(a+1));
-				else
-					wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize());
-				chma3.scale(-1, 1);
-				chma3.translate(-wide, 0);
-			}
-			chma4.translate(0, Item->BaseOffs - (charStyle.fontSize() / 10.0) * glyphs->scaleV);
-			if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript | ScLayout_DropCap))
-				chma6.translate(0, glyphs->yoffset);
-			if (charStyle.baselineOffset() != 0)
-				chma6.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0));
-			QTransform finalMat = chma * chma2 * chma3 * chma4 * chma6 * trafo;
-			if (Item->rotation() != 0)
-			{
-				QTransform sca;
-				sca.translate(Item->xPos(), Item->yPos());
-				finalMat *= sca;
-			}
-			if (embItem != NULL)
-			{
-				ob.appendChild(processInlineItem(CurX + glyphs->xoffset, ls.y + glyphs->yoffset, finalMat, embItem, charStyle, false, trans));
-				CurX += (embItem->width() + embItem->lineWidth()) * glyphs->scaleH;
-			}
-			else
-			{
-				QString glName;
-				if (chstr > QChar(32))
-					glName = handleGlyph(chr, charStyle);
-				if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None) && (chstr > QChar(32)))
-				{
-					QTransform sha = finalMat;
-					QTransform shad;
-					shad.translate(charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0, -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0);
-					sha *= shad;
-					QDomElement ob2 = docu.createElement("use");
-					ob2.setAttribute("xlink:href", "#" + glName);
-					ob2.setAttribute("transform", MatrixToStr(sha));
-					ob2.setAttribute("style", "fill:"+SetColor(charStyle.strokeColor(), charStyle.strokeShade())+";" + "stroke:none;");
-					ob.appendChild(ob2);
-				}
-				
-				if (((charStyle.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr[0]))
-					|| ((charStyle.effects() & ScStyle_UnderlineWords) && !chstr[0].isSpace() && !SpecialChars::isBreak(chstr[0])))
-				{
-					x = CurX;
-					y = ls.y;
-					double Ulen = glyphs->xadvance;
-					double Upos, lw, kern;
-					if (flags & ScLayout_StartOfLine)
-						kern = 0;
-					else
-						kern = charStyle.fontSize() * charStyle.tracking() / 10000.0;
-					if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1))
-					{
-						if (charStyle.underlineOffset() != -1)
-							Upos = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0));
-						else
-							Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-						if (charStyle.underlineWidth() != -1)
-							lw = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-						else
-							lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-					}
-					else
-					{
-						Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-						lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-					}
-					if (charStyle.baselineOffset() != 0)
-						Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-					QDomElement ob6 = docu.createElement("path");
-					if (charStyle.effects() & ScStyle_Subscript)
-						ob6.setAttribute("d", QString("M %1 %2 L%3 %4").arg(x + glyphs->xoffset-kern).arg(y + glyphs->yoffset - Upos).arg(x + glyphs->xoffset+Ulen).arg(y + glyphs->yoffset - Upos));
-					else
-						ob6.setAttribute("d", QString("M %1 %2 L%3 %4").arg(x + glyphs->xoffset-kern).arg(y - Upos).arg(x + glyphs->xoffset+Ulen).arg(y - Upos));
-					QString sT = "stroke:none;";
-					if (charStyle.fillColor() != CommonStrings::None)
-					{
-						sT = "stroke:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";";
-						sT += " stroke-width:"+FToStr(lw)+";";
-					}
-					ob6.setAttribute("style", "fill:none;" + sT);
-					ob.appendChild(ob6);
-				}
-				if (chstr > QChar(32))
-				{
-					QDomElement ob3 = docu.createElement("use");
-					ob3.setAttribute("xlink:href", "#" + glName);
-					ob3.setAttribute("transform", MatrixToStr(finalMat));
-					QString fT = "fill:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";";
-					QString sT = "stroke:none;";
-					if (charStyle.effects() & ScStyle_Outline)
-					{
-						sT = "stroke:"+SetColor(charStyle.strokeColor(), charStyle.strokeShade())+";";
-						sT += " stroke-width:"+FToStr(chs * charStyle.outlineWidth() / 10000.0)+";";
-					}
-					ob3.setAttribute("style", fT + sT);
-					ob.appendChild(ob3);
-				}
-				if (charStyle.effects() & ScStyle_Strikethrough)
-				{
-					x = CurX;
-					y = ls.y;
-					double Ulen = glyphs->xadvance;
-					double Upos, lw, kern;
-					if (flags & ScLayout_StartOfLine)
-						kern = 0;
-					else
-						kern = charStyle.fontSize() * charStyle.tracking() / 10000.0;
-					if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1))
-					{
-						if (charStyle.strikethruOffset() != -1)
-							Upos = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0));
-						else
-							Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-						if (charStyle.strikethruWidth() != -1)
-							lw = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-						else
-							lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-					}
-					else
-					{
-						Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-						lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-					}
-					if (charStyle.baselineOffset() != 0)
-						Upos += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0);
-					QDomElement ob7 = docu.createElement("path");
-					ob7.setAttribute("d", QString("M %1 %2 L%3 %4").arg(x + glyphs->xoffset-kern).arg(y + glyphs->yoffset - Upos).arg(x + glyphs->xoffset+Ulen).arg(y + glyphs->yoffset - Upos));
-					QString sT = "stroke:none;";
-					if (charStyle.fillColor() != CommonStrings::None)
-					{
-						sT = "stroke:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";";
-						sT += " stroke-width:"+FToStr(lw)+";";
-					}
-					ob7.setAttribute("style", "fill:none;" + sT);
-					ob.appendChild(ob7);
-				}
-				CurX += glyphs->wide();
-			}
-		}
-	}
-	if (Item->NamedLStyle.isEmpty())
-	{
-		QDomElement ob4 = docu.createElement("path");
-		ob4.setAttribute("d", SetClipPath(&Item->PoLine, true));
-		ob4.setAttribute("style", "fill:none; "+stroke);
-		if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
-			ob4.appendChild(processSymbolStroke(Item, trans));
-		ob.appendChild(ob4);
-	}
-	else
-	{
-		multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
-		for (int it = ml.size()-1; it > -1; it--)
-		{
-			if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
-			{
-				QDomElement ob5 = docu.createElement("path");
-				ob5.setAttribute("d", SetClipPath(&Item->PoLine, true));
-				ob5.setAttribute("style", "fill:none; "+GetMultiStroke(&ml[it], Item));
-				ob.appendChild(ob5);
-			}
-		}
-	}
+	SvgPainter p(trans, this, ob);
+	Item->textLayout.renderBackground(&p);
+	Item->textLayout.render(&p);
 	return ob;
 }
 
-QDomElement SVGExPlug::processPathTextItem(PageItem *Item, QString trans, QString stroke)
-{
-	QDomElement ob;
-	ob = docu.createElement("g");
-	ob.setAttribute("transform", trans);
-	if (Item->PoShow)
-	{
-		if (Item->NamedLStyle.isEmpty())
-		{
-			QDomElement ob4 = docu.createElement("path");
-			ob4.setAttribute("d", SetClipPath(&Item->PoLine, false));
-			ob4.setAttribute("style", "fill:none; "+stroke);
-			ob.appendChild(ob4);
-		}
-		else
-		{
-			multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
-			for (int it = ml.size()-1; it > -1; it--)
-			{
-				if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
-				{
-					QDomElement ob5 = docu.createElement("path");
-					ob5.setAttribute("d", SetClipPath(&Item->PoLine, false));
-					ob5.setAttribute("style", "fill:none; "+GetMultiStroke(&ml[it], Item));
-					ob.appendChild(ob5);
-				}
-			}
-		}
-	}
-	double wide;
-	QString chstr;
-	for (int a = 0; a < Item->asPathText()->itemRenderText.length(); ++a)
-	{
-		//ScText *hl = Item->asPathText()->itemRenderText.item_p(a);
-		const CharStyle& charStyle(Item->asPathText()->itemRenderText.charStyle(a));
-		const GlyphLayout* glyphs = Item->asPathText()->itemRenderText.getGlyphs(a);
-        const PathData* pdata = &(Item->textLayout.point(a));
-        PageItem* embItem = Item->itemText.hasObject(a)? Item->itemText.object(a) : NULL;
-        LayoutFlags flags = Item->itemText.flags(a);
-        
-		chstr = Item->asPathText()->itemRenderText.text(a,1);
-        if ((chstr == QChar(13)) || (chstr == QChar(29)))
-			continue;
-		if (chstr == QChar(30))
-		{
-			chstr = Item->ExpandToken(a);
-			if (chstr == QChar(32))
-				continue;
-		}
-		double chs = charStyle.fontSize();
-		if (charStyle.effects() & ScStyle_SmallCaps)
-		{
-			if (chstr.toUpper() != chstr)
-			{
-				chs = qMax(static_cast<int>(charStyle.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1);
-				chstr = chstr.toUpper();
-			}
-		}
-		else if (charStyle.effects() & ScStyle_AllCaps)
-			chstr = chstr.toUpper();
-		uint chr = chstr[0].unicode();
-        
-		QPointF tangt = QPointF( cos(pdata->PRot), sin(pdata->PRot) );
-		QTransform chma, chma2, chma3, chma4, chma6;
-		QTransform trafo = QTransform( 1, 0, 0, -1, -pdata->PDx, 0 );
-		if (Item->textPathFlipped)
-			trafo *= QTransform(1, 0, 0, -1, 0, 0);
-		if (Item->textPathType == 0)
-			trafo *= QTransform( tangt.x(), tangt.y(), tangt.y(), -tangt.x(), pdata->PtransX, pdata->PtransY );
-		else if (Item->textPathType == 1)
-			trafo *= QTransform(1, 0, 0, -1, pdata->PtransX, pdata->PtransY );
-		else if (Item->textPathType == 2)
-		{
-			double a = 1;
-			double b = -1;
-			if (tangt.x() < 0)
-			{
-				a = -1;
-				b = 1;
-			}
-			if (fabs(tangt.x()) > 0.1)
-				trafo *= QTransform( a, (tangt.y() / tangt.x()) * b, 0, -1, pdata->PtransX, pdata->PtransY ); // ID's Skew mode
-			else
-				trafo *= QTransform( a, 6 * b, 0, -1, pdata->PtransX, pdata->PtransY );
-		}
-		if (embItem != NULL)
-		{
-			QTransform finalMat = chma * chma2 * chma3 * chma4 * chma6 * trafo;
-			ob.appendChild(processInlineItem(0, 0, finalMat, embItem, charStyle, true, trans));
-		}
-		else
-		{
-			if (Item->rotation() != 0)
-			{
-				QTransform sca;
-				sca.translate(-Item->xPos(), -Item->yPos());
-				trafo *= sca;
-			}
-			chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0);
-			if (Item->reversed())
-			{
-				if (a < Item->itemText.length()-1)
-					wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), Item->itemText.text(a+1));
-				else
-					wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize());
-				chma3.scale(-1, 1);
-				chma3.translate(-wide, 0);
-			}
-			chma4.translate(0, Item->BaseOffs - (charStyle.fontSize() / 10.0) * glyphs->scaleV);
-			if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript | ScLayout_DropCap))
-				chma6.translate(0, glyphs->yoffset);
-			if (charStyle.baselineOffset() != 0)
-				chma6.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0));
-			QTransform finalMat = chma * chma2 * chma3 * chma4 * chma6 * trafo;
-			if (Item->rotation() != 0)
-			{
-				QTransform sca;
-				sca.translate(Item->xPos(), Item->yPos());
-				finalMat *= sca;
-			}
-
-			if (((charStyle.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr[0]))
-				|| ((charStyle.effects() & ScStyle_UnderlineWords) && !chstr[0].isSpace() && !SpecialChars::isBreak(chstr[0])))
-			{
-				QTransform stro = chma2 * chma3 * chma6 * trafo;
-				if (Item->rotation() != 0)
-				{
-					QTransform sca;
-					sca.translate(Item->xPos(), Item->yPos());
-					stro *= sca;
-				}
-				double Ulen = glyphs->xadvance;
-				double Upos, Uwid, kern;
-				if (flags & ScLayout_StartOfLine)
-					kern = 0;
-				else
-					kern = charStyle.fontSize() * charStyle.tracking() / 10000.0;
-				if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1))
-				{
-					if (charStyle.underlineOffset() != -1)
-						Upos = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0));
-					else
-						Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-					if (charStyle.underlineWidth() != -1)
-						Uwid = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-					else
-						Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-				}
-				else
-				{
-					Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-					Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-				}
-				if (charStyle.baselineOffset() != 0)
-					Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-				QDomElement ob8 = docu.createElement("path");
-				ob8.setAttribute("transform", MatrixToStr(stro));
-				if (charStyle.effects() & ScStyle_Subscript)
-					ob8.setAttribute("d", QString("M %1 %2 L%3 %4").arg(glyphs->xoffset-kern).arg(-Upos).arg(glyphs->xoffset+Ulen).arg(-Upos));
-				else
-					ob8.setAttribute("d", QString("M %1 %2 L%3 %4").arg(glyphs->xoffset-kern).arg(-(Upos + glyphs->yoffset)).arg(glyphs->xoffset+Ulen).arg(-(Upos + glyphs->yoffset)));
-				QString sT = "stroke:none;";
-				if (charStyle.fillColor() != CommonStrings::None)
-				{
-					sT = "stroke:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";";
-					sT += " stroke-width:"+FToStr(Uwid)+";";
-				}
-				ob8.setAttribute("style", "fill:none;" + sT);
-				ob.appendChild(ob8);
-			}
-			if (chstr > QChar(32))
-			{
-				QString glName = handleGlyph(chr, charStyle);
-				if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None))
-				{
-					QTransform sha = finalMat;
-					QTransform shad;
-					shad.translate(charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0, -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0);
-					sha *= shad;
-					QDomElement ob2 = docu.createElement("use");
-					ob2.setAttribute("xlink:href", "#" + glName);
-					ob2.setAttribute("transform", MatrixToStr(sha));
-					ob2.setAttribute("style", "fill:"+SetColor(charStyle.strokeColor(), charStyle.strokeShade())+";" + "stroke:none;");
-					ob.appendChild(ob2);
-				}
-				QDomElement ob1 = docu.createElement("use");
-				ob1.setAttribute("xlink:href", "#" + glName);
-				ob1.setAttribute("transform", MatrixToStr(finalMat));
-				QString fT = "fill:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";";
-				QString sT = "stroke:none;";
-				if (charStyle.effects() & ScStyle_Outline)
-				{
-					sT = "stroke:"+SetColor(charStyle.strokeColor(), charStyle.strokeShade())+";";
-					sT += " stroke-width:"+FToStr(chs * charStyle.outlineWidth() / 10000.0)+";";
-				}
-				ob1.setAttribute("style", fT + sT);
-				ob.appendChild(ob1);
-			}
-			if (charStyle.effects() & ScStyle_Strikethrough)
-			{
-				QTransform stro = chma2 * chma3 * chma6 * trafo;
-				if (Item->rotation() != 0)
-				{
-					QTransform sca;
-					sca.translate(Item->xPos(), Item->yPos());
-					stro *= sca;
-				}
-				double Ulen = glyphs->xadvance;
-				double Upos, Uwid, kern;
-				if (flags & ScLayout_StartOfLine)
-					kern = 0;
-				else
-					kern = charStyle.fontSize() * charStyle.tracking() / 10000.0;
-				if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1))
-				{
-					if (charStyle.strikethruOffset() != -1)
-						Upos = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0));
-					else
-						Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-					if (charStyle.strikethruWidth() != -1)
-						Uwid = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-					else
-						Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-				}
-				else
-				{
-					Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-					Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-				}
-				if (charStyle.baselineOffset() != 0)
-					Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-				QDomElement ob7 = docu.createElement("path");
-				ob7.setAttribute("transform", MatrixToStr(stro));
-				ob7.setAttribute("d", QString("M %1 %2 L%3 %4").arg(glyphs->xoffset-kern).arg(-Upos).arg(glyphs->xoffset+Ulen).arg(-Upos));
-				QString sT = "stroke:none;";
-				if (charStyle.fillColor() != CommonStrings::None)
-				{
-					sT = "stroke:"+SetColor(charStyle.fillColor(), charStyle.fillShade())+";";
-					sT += " stroke-width:"+FToStr(Uwid)+";";
-				}
-				ob7.setAttribute("style", "fill:none;" + sT);
-				ob.appendChild(ob7);
-			}
-		}
-	}
-	return ob;
-}
-
-QDomElement SVGExPlug::processInlineItem(double xpos, double ypos, QTransform &finalMat, PageItem* embItem, const CharStyle & charStyle, bool pathT, QString trans)
+QDomElement SVGExPlug::processInlineItem(PageItem* embItem, QString trans, double scaleH, double scaleV)
 {
 	QList<PageItem*> emG;
 	if (embItem->isGroup())
@@ -1823,8 +1287,6 @@
 		emG.append(embItem);
 
 	QDomElement layerGroup = docu.createElement("g");
-	if (pathT)
-		layerGroup.setAttribute("transform", MatrixToStr(finalMat));
 	for (int em = 0; em < emG.count(); ++em)
 	{
 		PageItem* embedded = emG.at(em);
@@ -1853,10 +1315,8 @@
 				obE = processImageItem(embedded, trans, fill, stroke);
 				break;
 			case PageItem::TextFrame:
+			case PageItem::PathText:
 				obE = processTextItem(embedded, trans, fill, stroke);
-				break;
-			case PageItem::PathText:
-				obE = processPathTextItem(embedded, trans, stroke);
 				break;
 			case PageItem::Symbol:
 				obE = processSymbolItem(embedded, trans);
@@ -1865,13 +1325,10 @@
 				break;
 		}
 		QTransform mm;
-		mm.translate(xpos + embedded->gXpos * (charStyle.scaleH() / 1000.0), (ypos - (embedded->gHeight * (charStyle.scaleV() / 1000.0)) + embedded->gYpos * (charStyle.scaleV() / 1000.0)));
-		if (charStyle.baselineOffset() != 0)
-			mm.translate(0, embedded->gHeight * (charStyle.baselineOffset() / 1000.0));
-		if (charStyle.scaleH() != 1000)
-			mm.scale(charStyle.scaleH() / 1000.0, 1);
-		if (charStyle.scaleV() != 1000)
-			mm.scale(1, charStyle.scaleV() / 1000.0);
+		if (scaleH != 1.0)
+			mm.scale(scaleH, 1);
+		if (scaleV != 1.0)
+			mm.scale(1, scaleV);
 		mm.rotate(embedded->rotation());
 		obE.setAttribute("transform", MatrixToStr(mm));
 		layerGroup.appendChild(obE);
@@ -1879,15 +1336,12 @@
 	return layerGroup;
 }
 
-QString SVGExPlug::handleGlyph(uint chr, const CharStyle& cStyle)
-{
-	if (chr == 32)
-		return "SPACE";
-	QString glName = QString("Gl%1%2").arg(cStyle.font().psName().simplified().replace(QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )).arg(chr);
+QString SVGExPlug::handleGlyph(uint gid, const ScFace font)
+{
+	QString glName = QString("Gl%1%2").arg(font.psName().simplified().replace(QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )).arg(gid);
 	if (glyphNames.contains(glName))
 		return glName;
-	uint gl = cStyle.font().char2CMap(chr);
-	FPointArray pts = cStyle.font().glyphOutline(gl);
+	FPointArray pts = font.glyphOutline(gid);
 	QDomElement ob = docu.createElement("path");
 	ob.setAttribute("d", SetClipPath(&pts, true));
 	ob.setAttribute("id", glName);

Modified: trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.h
==============================================================================
--- trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.h	(original)
+++ trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.h	Wed Mar 23 20:21:36 2016
@@ -58,7 +58,8 @@
 
 class SVGExPlug : public QObject
 {
-    Q_OBJECT
+	Q_OBJECT
+	friend class SvgPainter;
 
 public:
 	/*!
@@ -90,9 +91,8 @@
 	QDomElement processLineItem(PageItem *Item, QString trans, QString stroke);
 	QDomElement processImageItem(PageItem *Item, QString trans, QString fill, QString stroke);
 	QDomElement processTextItem(PageItem *Item, QString trans, QString fill, QString stroke);
-	QDomElement processPathTextItem(PageItem *Item, QString trans, QString stroke);
-	QDomElement processInlineItem(double xpos, double ypos, QTransform &finalMat, PageItem* embItem, const CharStyle& cStyle, bool pathT, QString trans);
-	QString handleGlyph(uint chr, const CharStyle& cStyle);
+	QDomElement processInlineItem(PageItem* embItem, QString trans, double scaleH, double scaleV);
+	QString handleGlyph(uint gid, const ScFace font);
 	QDomElement processArrows(PageItem *Item, QDomElement line, QString trans);
 	QString handleMask(PageItem *Item, double xOffset, double yOffset);
 	QString getFillStyle(PageItem *Item);

Modified: trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.cpp
==============================================================================
--- trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.cpp	(original)
+++ trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.cpp	Wed Mar 23 20:21:36 2016
@@ -51,6 +51,7 @@
 #include "scribusview.h"
 #include "sctextstruct.h"
 #include "tableutils.h"
+#include "text/textlayoutpainter.h"
 #include "util.h"
 #include "ui/customfdialog.h"
 #include "ui/guidemanager.h"
@@ -59,6 +60,7 @@
 #include "util_formats.h"
 #include "util_math.h"
 #include "third_party/zip/scribus_zip.h"
+#include "text/boxes.h"
 
 int xpsexplugin_getPluginAPIVersion()
 {
@@ -435,17 +437,12 @@
 			else
 				processImageItem(xOffset, yOffset, Item, parentElem, rel_root);
 			break;
+		case PageItem::PathText:
 		case PageItem::TextFrame:
 			if (checkForFallback(Item))
 				handleImageFallBack(Item, parentElem, rel_root);
 			else
 				processTextItem(xOffset, yOffset, Item, parentElem, rel_root);
-			break;
-		case PageItem::PathText:
-			if (checkForFallback(Item))
-				handleImageFallBack(Item, parentElem, rel_root);
-			else
-				processPathTextItem(xOffset, yOffset, Item, parentElem, rel_root);
 			break;
 		case PageItem::Table:
 			if (checkForFallback(Item))
@@ -804,6 +801,121 @@
 	return;
 }
 
+class XPSPainter: public TextLayoutPainter
+{
+	PageItem *m_item;
+	QDomElement m_group;
+	XPSExPlug *m_xps;
+	QMap<QString, QString> &m_fontMap;
+	QDomElement &m_relRoot;
+
+public:
+	XPSPainter(PageItem *item, QDomElement &group, XPSExPlug *xps, QMap<QString, QString> &XPSfontMap, QDomElement &rel_root):
+		m_item(item),
+		m_group(group),
+		m_xps(xps),
+		m_fontMap(XPSfontMap),
+		m_relRoot(rel_root)
+	{ }
+
+	void drawGlyph(const GlyphLayout gl)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		if (!m_fontMap.contains(font().replacementName()))
+			m_fontMap.insert(font().replacementName(), m_xps->embedFont(font(), m_relRoot));
+
+		QTransform transform = matrix();
+		QDomElement glyph = m_xps->p_docu.createElement("Glyphs");
+		double size = fontSize() * qMax(gl.scaleV, gl.scaleH) * m_xps->conversionFactor;
+		glyph.setAttribute("RenderTransform", m_xps->MatrixToStr(transform, m_xps->conversionFactor));
+		glyph.setAttribute("BidiLevel", "0");
+		glyph.setAttribute("StyleSimulations", "None");
+		glyph.setAttribute("FontRenderingEmSize", m_xps->FToStr(size));
+		glyph.setAttribute("FontUri", m_fontMap[font().replacementName()]);
+		glyph.setAttribute("Fill", m_xps->SetColor(fillColor().color,fillColor().shade, 0));
+		glyph.setAttribute("OriginX", m_xps->FToStr(x() * m_xps->conversionFactor));
+		glyph.setAttribute("OriginY", m_xps->FToStr(y() * m_xps->conversionFactor));
+		glyph.setAttribute("Indices", QString::number(gl.glyph));
+
+		m_group.appendChild(glyph);
+	}
+
+	void drawGlyphOutline(const GlyphLayout gl, bool fill)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		FPointArray outline = font().glyphOutline(gl.glyph);
+		if (outline.size() >= 4)
+		{
+			QTransform transform = matrix();
+			transform.scale((fontSize() * gl.scaleH) / 10.0, (fontSize() * gl.scaleV) / 10.0);
+			outline.map(transform);
+			outline.translate(0, -fontSize() * gl.scaleV);
+			outline.translate(x(), y());
+			outline.scale(m_xps->conversionFactor, m_xps->conversionFactor);
+			QString pathData = m_xps->SetClipPath(&outline, true);
+			QDomElement glyph = m_xps->p_docu.createElement("Path");
+			glyph.setAttribute("Data", pathData);
+			if (!fill)
+				glyph.setAttribute("Fill", m_xps->SetColor("None", fillColor().shade, 0));
+			else
+				glyph.setAttribute("Fill", m_xps->SetColor(fillColor().color, fillColor().shade, 0));
+			glyph.setAttribute("StrokeThickness", m_xps->FToStr(strokeWidth() * m_xps->conversionFactor));
+			glyph.setAttribute("Stroke", m_xps->SetColor(strokeColor().color, strokeColor().shade, 0));
+			m_group.appendChild(glyph);
+		}
+	}
+
+	void drawLine(QPointF start, QPointF end)
+	{
+		QTransform transform = matrix();
+		QDomElement path = m_xps->p_docu.createElement("Path");
+		path.setAttribute("RenderTransform", m_xps->MatrixToStr(transform, m_xps->conversionFactor));
+		path.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((x() + start.x()) * m_xps->conversionFactor).arg((y() + end.y()) * m_xps->conversionFactor).arg((x() + start.x() + end.x()) * m_xps->conversionFactor).arg((y() + end.y()) * m_xps->conversionFactor));
+		path.setAttribute("Stroke", m_xps->SetColor(strokeColor().color, strokeColor().shade, 0));
+		path.setAttribute("StrokeThickness", m_xps->FToStr(strokeWidth() * m_xps->conversionFactor));
+		m_group.appendChild(path);
+	}
+
+	void drawRect(QRectF rect)
+	{
+		QTransform transform = matrix();
+		double rx = (x() + rect.x()) * m_xps->conversionFactor;
+		double ry = (y() + rect.y()) * m_xps->conversionFactor;
+		double rw = rx + rect.width() * m_xps->conversionFactor;
+		double rh = ry + rect.height() * m_xps->conversionFactor;
+		QString paS = QString("M%1,%2 ").arg(rx).arg(ry);
+		paS += QString("L%1,%2 ").arg(rw).arg(ry);
+		paS += QString("L%1,%2 ").arg(rw).arg(rh);
+		paS += QString("L%1,%2 ").arg(rx).arg(rh);
+		paS += "Z";
+		QDomElement path = m_xps->p_docu.createElement("Path");
+		path.setAttribute("RenderTransform", m_xps->MatrixToStr(transform, m_xps->conversionFactor));
+		path.setAttribute("Data", paS);
+		path.setAttribute("Fill", m_xps->SetColor(fillColor().color, fillColor().shade, 0));
+		path.setAttribute("StrokeThickness", m_xps->FToStr(strokeWidth() * m_xps->conversionFactor));
+		path.setAttribute("Stroke", m_xps->SetColor(strokeColor().color, strokeColor().shade, 0));
+		m_group.appendChild(path);
+	}
+
+	void drawObject(PageItem* item)
+	{
+		QDomElement canvas = m_xps->p_docu.createElement("Canvas");
+		QTransform matrix = QTransform();
+		matrix.translate(x() * m_xps->conversionFactor, (y() - (item->height() * (scaleV() / 1000.0))) * m_xps->conversionFactor);
+		if (scaleH() != 1.0)
+			matrix.scale(scaleH(), 1);
+		if (scaleV() != 1.0)
+			matrix.scale(1, scaleV());
+		canvas.setAttribute("RenderTransform", m_xps->MatrixToStr(matrix));
+		m_xps->writeItemOnPage(item->gXpos, item->gYpos, item, canvas, m_relRoot);
+		m_group.appendChild(canvas);
+	}
+};
+
 void XPSExPlug::processTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
 {
 	if (Item->isAnnotation())
@@ -879,756 +991,11 @@
 			grp.appendChild(ob);
 		}
 	}
-	bool bFound = false;
-	for (uint ll=0; ll < Item->textLayout.lines(); ++ll)
-	{
-		if (Item->itemText.paragraphStyle(Item->textLayout.line(ll).firstItem).backgroundColor() != CommonStrings::None)
-		{
-			bFound = true;
-			break;
-		}
-	}
-	if (bFound)
-	{
-		FPointArray path = Item->PoLine.copy();
-		path.scale(conversionFactor, conversionFactor);
-		SetClipAttr(grp, &path, Item->fillRule);
-	}
-	uint llp = 0;
-	while (llp < Item->textLayout.lines())
-	{
-		LineSpec ls = Item->textLayout.line(llp++);
-		const ParagraphStyle& LineStyle = Item->itemText.paragraphStyle(ls.firstItem);
-		if (LineStyle.backgroundColor() != CommonStrings::None)
-		{
-			double y0 = ls.y;
-			double y2 = ls.y;
-			double ascent = ls.ascent;
-			double descent = ls.descent;
-			double rMarg = LineStyle.rightMargin();
-			double lMarg = ls.colLeft;
-			double adjX = 0;
-			if (LineStyle.firstIndent() <= 0)
-				adjX += LineStyle.leftMargin() + LineStyle.firstIndent();
-			while (llp < Item->textLayout.lines())
-			{
-				ls = Item->textLayout.line(llp);
-				if ((ls.colLeft > lMarg) || (Item->itemText.paragraphStyle(ls.firstItem) != LineStyle))
-				{
-					if (y2 == 0)
-						y2 = y0;
-					break;
-				}
-				if (Item->itemText.text(ls.lastItem) == SpecialChars::PARSEP)
-				{
-					y2 = ls.y;
-					descent = ls.descent;
-					if ((llp + 1) < Item->textLayout.lines())
-					{
-						if ((Item->textLayout.line(llp + 1).lastItem - Item->textLayout.line(llp + 1).firstItem) > 0)
-							descent += LineStyle.lineSpacing() - (ls.descent + Item->textLayout.line(llp + 1).ascent);
-					}
-					llp++;
-					break;
-				}
-				y2 = ls.y;
-				descent = ls.descent;
-				if ((llp + 1) < Item->textLayout.lines())
-					descent += LineStyle.lineSpacing() - (ls.descent + Item->textLayout.line(llp + 1).ascent);
-				llp++;
-			}
-			QRectF scr(lMarg + adjX, y0 - ascent, Item->asTextFrame()->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent);
-			QString paS = QString("M%1,%2 ").arg(scr.x() * conversionFactor).arg(scr.y() * conversionFactor);
-			paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg(scr.y() * conversionFactor);
-			paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor);
-			paS += QString("L%1,%2 ").arg(scr.x() * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor);
-			paS += "Z";
-			QDomElement glyS = p_docu.createElement("Path");
-			glyS.setAttribute("Data", paS);
-			glyS.setAttribute("Fill", SetColor(LineStyle.backgroundColor(), LineStyle.backgroundShade(), 0));
-			grp.appendChild(glyS);
-		}
-	}
-	for (uint ll=0; ll < Item->textLayout.lines(); ++ll)
-	{
-		LineSpec ls = Item->textLayout.line(ll);
-		QList<txtRunItem> current_run;
-		QList<QList<txtRunItem> > textRuns;
-		QList<txtRunItem> specialText;
-		double CurX = ls.x;
-
-		double CurXB = ls.x;
-		int last = qMin(ls.lastItem, Item->itemText.length() - 1);
-		QRectF scr;
-		QString oldBack = "";
-		double oldShade = 100;
-		QString colorB = "";
-		for (int a = ls.firstItem; a <= last; ++a)
-		{
-			const GlyphLayout* glyphs(Item->itemText.getGlyphs(a));
-			const CharStyle& charStyle(Item->itemText.charStyle(a));
-			if (charStyle.backColor() != CommonStrings::None)
-			{
-			// This code is for rendering character background color.
-				colorB = SetColor(charStyle.backColor(), charStyle.backShade(), 0);
-				const ParagraphStyle& LineStyle = Item->itemText.paragraphStyle(ls.firstItem);
-				double y1 = ls.y;
-				double hl = ls.height;
-				if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-					hl = m_Doc->guidesPrefs().valueBaselineGrid;
-				else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
-					hl = LineStyle.lineSpacing();
-				if (ls.isFirstLine)
-				{
-					if (Item->textLayout.lines() == 1)
-						hl = ls.ascent + ls.descent;
-					if (LineStyle.hasDropCap() && (a == ls.firstItem))
-						hl *= LineStyle.dropCapLines();
-					if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-						y1 -= LineStyle.lineSpacing();
-					else if (Item->firstLineOffset() == FLOPRealGlyphHeight || Item->firstLineOffset() == FLOPFontAscent)
-						y1 -= ls.ascent;
-					else
-						y1 -= LineStyle.lineSpacing();
-				}
-				else
-					y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0;
-				QRectF scrG;
-				if (Item->itemText.hasObject(a))
-				{
-					PageItem* obj = Item->itemText.object(a);
-					double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH;
-					double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV;
-					scrG = QRectF(CurXB, ls.y - hh, ww , hh);
-				}
-				else
-					scrG = QRectF(CurXB, y1, glyphs->wide(), hl);
-				if ((oldBack == "") || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade())))
-					scr |= scrG;
-				else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade()))
-				{
-					QString paS = QString("M%1,%2 ").arg(scr.x() * conversionFactor).arg(scr.y() * conversionFactor);
-					paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg(scr.y() * conversionFactor);
-					paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor);
-					paS += QString("L%1,%2 ").arg(scr.x() * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor);
-					paS += "Z";
-					QDomElement glyS = p_docu.createElement("Path");
-					glyS.setAttribute("Data", paS);
-					glyS.setAttribute("Fill", SetColor(oldBack, oldShade, 0));
-					grp.appendChild(glyS);
-					scr = scrG;
-				}
-				oldBack = charStyle.backColor();
-				oldShade = charStyle.backShade();
-			}
-			else
-			{
-				if (!scr.isNull())
-				{
-					QString paS = QString("M%1,%2 ").arg(scr.x() * conversionFactor).arg(scr.y() * conversionFactor);
-					paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg(scr.y() * conversionFactor);
-					paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor);
-					paS += QString("L%1,%2 ").arg(scr.x() * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor);
-					paS += "Z";
-					QDomElement glyS = p_docu.createElement("Path");
-					glyS.setAttribute("Data", paS);
-					glyS.setAttribute("Fill", colorB);
-					grp.appendChild(glyS);
-				}
-				oldBack = "";
-				oldShade = 100;
-				scr = QRectF();
-			}
-			CurXB += glyphs->wide();
-		}
-		if (!scr.isNull())
-		{
-			QString paS = QString("M%1,%2 ").arg(scr.x() * conversionFactor).arg(scr.y() * conversionFactor);
-			paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg(scr.y() * conversionFactor);
-			paS += QString("L%1,%2 ").arg((scr.x() + scr.width()) * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor);
-			paS += QString("L%1,%2 ").arg(scr.x() * conversionFactor).arg((scr.y() + scr.height()) * conversionFactor);
-			paS += "Z";
-			QDomElement glyS = p_docu.createElement("Path");
-			glyS.setAttribute("Data", paS);
-			glyS.setAttribute("Fill", colorB);
-			grp.appendChild(glyS);
-		}
-
-		for (int a = ls.firstItem; a <= ls.lastItem; ++a)
-		{
-			//ScText *hl = Item->itemText.item_p(a);
-			QChar chr = Item->itemText.text(a);
-			CharStyle charStyle = Item->itemText.charStyle(a);
-			GlyphLayout* glyphs = Item->itemText.getGlyphs(a);
-			LayoutFlags flags = Item->itemText.flags(a);
-			const ScFace* font = &charStyle.font();
-			txtRunItem txItem;
-			txItem.chr = chr;
-			txItem.glyphs = glyphs;
-			txItem.style = charStyle;
-			txItem.index = a;
-			txItem.CurX = CurX;
-			txItem.embItem = Item->itemText.hasObject(a)? Item->itemText.object(a) : NULL;
-			if (!((font->type() == ScFace::TTF) || (font->type() == ScFace::OTF)))
-			{
-				specialText.append(txItem);
-				textRuns.append(current_run);
-				current_run.clear();
-				CurX += txItem.glyphs->wide();
-				continue;
-			}
-			if (SpecialChars::isBreak(chr, true) || (chr == QChar(10)))
-			{
-				continue;
-			}
-			if (flags & ScLayout_SuppressSpace)
-			{
-				continue;
-			}
-			if ((chr == SpecialChars::OLD_NBSPACE) || (chr == SpecialChars::OBJECT) || (charStyle.effects() & ScStyle_UserStyles))
-			{
-				specialText.append(txItem);
-				textRuns.append(current_run);
-				current_run.clear();
-				CurX += txItem.glyphs->wide();
-				continue;
-			}
-			QString guidFont;
-			if (!xps_fontMap.contains(font->replacementName()))
-			{
-				guidFont = embedFont(font, rel_root);
-				xps_fontMap.insert(font->replacementName(), guidFont);
-			}
-			else
-				guidFont = xps_fontMap[font->replacementName()];
-			if (current_run.isEmpty())
-				current_run.append(txItem);
-			else
-			{
-				txtRunItem txItemL = current_run.last();
-				double chl = (txItemL.style.fontSize() / 10.0) * qMax(txItemL.glyphs->scaleV, txItemL.glyphs->scaleH) * conversionFactor;
-				const ScFace* fontL = &txItemL.style.font();
-				QString guidFontL = xps_fontMap[fontL->replacementName()];
-				StyleFlag old_sty = txItemL.style.effects();
-				int old_shade = txItemL.style.fillShade();
-				QString old_fill = txItemL.style.fillColor();
-				double chs = (charStyle.fontSize() / 10.0) * qMax(glyphs->scaleV, glyphs->scaleH) * conversionFactor;
-				if ((chs != chl) || (guidFont != guidFontL) || (charStyle.effects() != old_sty) || (charStyle.fillColor() != old_fill) || (charStyle.fillShade() != old_shade))
-				{
-					textRuns.append(current_run);
-					current_run.clear();
-				}
-				current_run.append(txItem);
-			}
-			CurX += txItem.glyphs->wide();
-		}
-		textRuns.append(current_run);
-		for (int txr = 0; txr < textRuns.count(); txr++)
-		{
-			QString uniString = "";
-			QString indString = "";
-			current_run = textRuns[txr];
-			if (current_run.isEmpty())
-				continue;
-			double StartX = current_run[0].CurX;
-			CurX = current_run[0].CurX;
-			double chs = (current_run[0].style.fontSize() / 10.0) * qMax(current_run[0].glyphs->scaleV, current_run[0].glyphs->scaleH) * conversionFactor;
-			for (int cr = 0; cr < current_run.count(); cr++)
-			{
-				txtRunItem txItem = current_run[cr];
-				if ((txItem.chr == SpecialChars::PAGENUMBER) || (txItem.chr == SpecialChars::PAGECOUNT))
-				{
-					QString exString = Item->ExpandToken(txItem.index);
-					for (int ex = 0; ex < exString.count(); ex++)
-					{
-						indString += ";";
-					}
-					uniString += exString;
-				}
-				else if ((SpecialChars::isBreakingSpace(txItem.chr)) || (SpecialChars::isExpandingSpace(txItem.chr)) || (txItem.chr.isSpace()))
-				{
-					indString += QString(",%1;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100);
-					uniString += " ";
-				}
-				else
-				{
-					uniString += txItem.chr;
-					if ((txItem.glyphs->xoffset != 0) || (txItem.glyphs->yoffset != 0))
-						indString += QString(",%1,%2,%3;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100).arg((txItem.glyphs->xoffset * conversionFactor) / chs * 100).arg((-txItem.glyphs->yoffset * conversionFactor) / chs * 100);
-					else
-						indString += QString(",%1;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100);
-				}
-				CurX += txItem.glyphs->wide();
-			}
-			if (!indString.isEmpty())
-				indString.chop(1);
-			QDomElement gly = p_docu.createElement("Glyphs");
-			gly.setAttribute("BidiLevel", "0");
-			gly.setAttribute("StyleSimulations", "None");
-			gly.setAttribute("FontRenderingEmSize", FToStr(chs));
-			const ScFace* fontL = &current_run[0].style.font();
-			gly.setAttribute("FontUri", xps_fontMap[fontL->replacementName()]);
-			gly.setAttribute("Fill", SetColor(current_run[0].style.fillColor(), current_run[0].style.fillShade(), 0));
-			gly.setAttribute("UnicodeString", uniString);
-			if (current_run.count() == 1)
-			{
-				gly.setAttribute("OriginX", FToStr((StartX + current_run[0].glyphs->xoffset) * conversionFactor));
-				gly.setAttribute("OriginY", FToStr((ls.y + current_run[0].glyphs->yoffset) * conversionFactor));
-			}
-			else
-			{
-				gly.setAttribute("OriginX", FToStr(StartX * conversionFactor));
-				gly.setAttribute("OriginY", FToStr(ls.y * conversionFactor));
-				gly.setAttribute("Indices", indString);
-			}
-			grp.appendChild(gly);
-		}
-		for (int cr = 0; cr < specialText.count(); cr++)
-		{
-			txtRunItem txItem = specialText[cr];
-			CurX = txItem.CurX;
-			if (txItem.chr == SpecialChars::OBJECT)
-			{
-				if (txItem.embItem != NULL)
-				{
-					QDomElement obO = p_docu.createElement("Canvas");
-					QTransform mm;
-					mm.translate(CurX * conversionFactor, (ls.y - (txItem.embItem->height() * (txItem.style.scaleV() / 1000.0))) * conversionFactor);
-					if (txItem.style.baselineOffset() != 0)
-						mm.translate(0, (txItem.style.baselineOffset() / 1000.0) * conversionFactor);
-					if (txItem.style.scaleH() != 1000)
-						mm.scale(txItem.style.scaleH() / 1000.0, 1);
-					if (txItem.style.scaleV() != 1000)
-						mm.scale(1, txItem.style.scaleV() / 1000.0);
-					obO.setAttribute("RenderTransform", MatrixToStr(mm));
-					QList<PageItem*> emG;
-					if (txItem.embItem->isGroup())
-						emG = txItem.embItem->getItemList();
-					else
-						emG.append(txItem.embItem);
-					for (int em = 0; em < emG.count(); ++em)
-					{
-						PageItem* embed = emG.at(em);
-						writeItemOnPage(embed->gXpos, embed->gYpos, embed, obO, rel_root);
-					}
-					grp.appendChild(obO);
-				}
-				continue;
-			}
-			QString chstr = txItem.chr;
-			if ((txItem.chr == SpecialChars::PAGENUMBER) || (txItem.chr == SpecialChars::PAGECOUNT))
-				chstr = Item->ExpandToken(txItem.index);
-			double chs = txItem.style.fontSize();
-			if (txItem.style.effects() & ScStyle_SmallCaps)
-			{
-				if (chstr.toUpper() != chstr)
-				{
-					chs = qMax(static_cast<int>(txItem.style.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1);
-					chstr = chstr.toUpper();
-				}
-			}
-			else if (txItem.style.effects() & ScStyle_AllCaps)
-				chstr = chstr.toUpper();
-			for (int cx = 0; cx < chstr.count(); cx++)
-			{
-				FPointArray pts;
-				QChar chstrex = chstr[cx];
-				uint chr = chstrex.unicode();
-				QTransform chma;
-				uint gl = txItem.style.font().char2CMap(chr);
-				if (!chstrex.isSpace())
-				{
-					pts = txItem.style.font().glyphOutline(gl);
-					if (pts.size() < 4)
-						continue;
-					chma = QTransform();
-					chma.scale(txItem.glyphs->scaleH * txItem.style.fontSize() / 100.00, txItem.glyphs->scaleV * txItem.style.fontSize() / 100.0);
-					pts.map(chma);
-					if (txItem.style.effects() & (ScStyle_Subscript | ScStyle_Superscript))
-						pts.translate(0, -(chs / 10.0 * txItem.glyphs->scaleV));
-					else
-						pts.translate(0, -(chs / 10.0));
-					pts.translate(CurX, ls.y);
-					// Fix for drop caps ???
-					if (ls.isFirstLine && Item->itemText.paragraphStyle(ls.firstItem).hasDropCap() && (txItem.index == ls.firstItem))
-						pts.translate(0, -ls.ascent);
-					if (txItem.style.effects() & (ScStyle_Subscript | ScStyle_Superscript))
-						pts.translate(0, txItem.glyphs->yoffset);
-					if ((txItem.style.effects() & ScStyle_Shadowed) && (txItem.style.strokeColor() != CommonStrings::None))
-					{
-						FPointArray ptsS = pts.copy();
-						ptsS.translate(txItem.style.fontSize() * txItem.style.shadowXOffset() / 10000.0, -txItem.style.fontSize() * txItem.style.shadowYOffset() / 10000.0);
-						ptsS.scale(conversionFactor, conversionFactor);
-						QString paS = SetClipPath(&ptsS, true);
-						QDomElement glyS = p_docu.createElement("Path");
-						glyS.setAttribute("Data", paS);
-						glyS.setAttribute("Fill", SetColor(txItem.style.strokeColor(), txItem.style.strokeShade(), 0));
-						grp.appendChild(glyS);
-					}
-					pts.scale(conversionFactor, conversionFactor);
-					QString pa = SetClipPath(&pts, true);
-					QDomElement gly = p_docu.createElement("Path");
-					gly.setAttribute("Data", pa);
-					gly.setAttribute("Fill", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0));
-					if (txItem.style.effects() & ScStyle_Outline)
-					{
-						gly.setAttribute("StrokeThickness", FToStr((chs * txItem.style.outlineWidth() / 10000.0) * conversionFactor));
-						gly.setAttribute("Stroke", SetColor(txItem.style.strokeColor(), txItem.style.strokeShade(), 0));
-					}
-					grp.appendChild(gly);
-				}
-				if ((txItem.style.effects() & ScStyle_Underline) || ((txItem.style.effects() & ScStyle_UnderlineWords)  && chstr.toUInt() != txItem.style.font().char2CMap(QChar(' '))))
-				{
-					double st, lw;
-					if ((txItem.style.underlineOffset() != -1) || (txItem.style.underlineWidth() != -1))
-					{
-						if (txItem.style.underlineOffset() != -1)
-							st = (txItem.style.underlineOffset() / 1000.0) * (txItem.style.font().descent(txItem.style.fontSize() / 10.0));
-						else
-							st = txItem.style.font().underlinePos(txItem.style.fontSize() / 10.0);
-						if (txItem.style.underlineWidth() != -1)
-							lw = (txItem.style.underlineWidth() / 1000.0) * (txItem.style.fontSize() / 10.0);
-						else
-							lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0);
-					}
-					else
-					{
-						st = txItem.style.font().underlinePos(txItem.style.fontSize() / 10.0);
-						lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0);
-					}
-					if (txItem.style.baselineOffset() != 0)
-						st += (txItem.style.fontSize() / 10.0) * txItem.glyphs->scaleV * (txItem.style.baselineOffset() / 1000.0);
-					QDomElement gly = p_docu.createElement("Path");
-					if (txItem.style.effects() & ScStyle_Subscript)
-						gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y + txItem.glyphs->yoffset - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y + txItem.glyphs->yoffset - st) * conversionFactor));
-					else
-						gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y - st) * conversionFactor));
-					gly.setAttribute("Stroke", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0));
-					gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor));
-					grp.appendChild(gly);
-				}
-				if (txItem.style.effects() & ScStyle_Strikethrough)
-				{
-					double st, lw;
-					if ((txItem.style.strikethruOffset() != -1) || (txItem.style.strikethruWidth() != -1))
-					{
-						if (txItem.style.strikethruOffset() != -1)
-							st = (txItem.style.strikethruOffset() / 1000.0) * (txItem.style.font().ascent(txItem.style.fontSize() / 10.0));
-						else
-							st = txItem.style.font().strikeoutPos(txItem.style.fontSize() / 10.0);
-						if (txItem.style.strikethruWidth() != -1)
-							lw = (txItem.style.strikethruWidth() / 1000.0) * (txItem.style.fontSize() / 10.0);
-						else
-							lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0);
-					}
-					else
-					{
-						st = txItem.style.font().strikeoutPos(txItem.style.fontSize() / 10.0);
-						lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0);
-					}
-					if (txItem.style.baselineOffset() != 0)
-						st += (txItem.style.fontSize() / 10.0) * txItem.glyphs->scaleV * (txItem.style.baselineOffset() / 1000.0);
-					QDomElement gly = p_docu.createElement("Path");
-					gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y - st) * conversionFactor));
-					gly.setAttribute("Stroke", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0));
-					gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor));
-					grp.appendChild(gly);
-				}
-			}
-		}
-	}
+
 	parentElem.appendChild(grp);
-	if ((Item->GrTypeStroke != 0) || (Item->lineColor() != CommonStrings::None) || !Item->NamedLStyle.isEmpty())
-	{
-		if (Item->NamedLStyle.isEmpty())
-		{
-			if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
-			{
-				processSymbolStroke(xOffset, yOffset, Item, parentElem, rel_root);
-			}
-			else
-			{
-				QDomElement ob3 = p_docu.createElement("Path");
-				ob3.setAttribute("Data", pa);
-				getStrokeStyle(Item, ob3, rel_root, xOffset, yOffset);
-				ob3.setAttribute("RenderTransform", MatrixToStr(mpl));
-				parentElem.appendChild(ob3);
-			}
-		}
-		else
-		{
-			QDomElement grp2 = p_docu.createElement("Canvas");
-			multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
-			for (int it = ml.size()-1; it > -1; it--)
-			{
-				if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
-				{
-					QDomElement ob3 = p_docu.createElement("Path");
-					ob3.setAttribute("Data", pa);
-					GetMultiStroke(&ml[it], ob3);
-					grp2.appendChild(ob3);
-				}
-			}
-			if (Item->lineTransparency() != 0)
-				grp2.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
-			grp2.setAttribute("RenderTransform", MatrixToStr(mpl));
-			parentElem.appendChild(grp2);
-		}
-	}
-}
-
-void XPSExPlug::processPathTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
-{
-	QDomElement grp = p_docu.createElement("Canvas");
-	QTransform mpx;
-	mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
-	if ((Item->rotation() != 0.0) || Item->imageFlippedH() || Item->imageFlippedV())
-	{
-		mpx.rotate(Item->rotation());
-		if (Item->imageFlippedH())
-		{
-			mpx.translate(Item->width() * conversionFactor, 0);
-			mpx.scale(-1, 1);
-		}
-		if (Item->imageFlippedV())
-		{
-			mpx.translate(0, Item->height() * conversionFactor);
-			mpx.scale(1, -1);
-		}
-	}
-	grp.setAttribute("RenderTransform", MatrixToStr(mpx));
-	if ((Item->PoShow) && (Item->lineColor() != CommonStrings::None))
-	{
-		QDomElement ob = p_docu.createElement("Path");
-		FPointArray path = Item->PoLine.copy();
-		path.scale(conversionFactor, conversionFactor);
-		QString pa = SetClipPath(&path, false);
-		ob.setAttribute("Data", pa);
-		if (Item->NamedLStyle.isEmpty())
-		{
-			if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
-			{
-				processSymbolStroke(xOffset, yOffset, Item, parentElem, rel_root);
-			}
-			else
-			{
-				getStrokeStyle(Item, ob, rel_root, xOffset, yOffset);
-				grp.appendChild(ob);
-			}
-		}
-		else
-		{
-			QDomElement grp2 = p_docu.createElement("Canvas");
-			multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
-			for (int it = ml.size()-1; it > -1; it--)
-			{
-				if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
-				{
-					QDomElement ob3 = p_docu.createElement("Path");
-					ob3.setAttribute("Data", pa);
-					GetMultiStroke(&ml[it], ob3);
-					grp2.appendChild(ob3);
-				}
-			}
-			if (Item->lineTransparency() != 0)
-				grp2.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
-			grp.appendChild(grp2);
-		}
-	}
-	QString chstr;
-	for (int a = 0; a < Item->asPathText()->itemRenderText.length(); ++a)
-	{
-		//ScText *hl = Item->asPathText()->itemRenderText.item_p(a);
-		const CharStyle& charStyle(Item->asPathText()->itemRenderText.charStyle(a));
-		const PathData* pdata = &(Item->asPathText()->textLayout.point(a));
-		const GlyphLayout* glyphs = Item->asPathText()->itemRenderText.getGlyphs(a);
-		PageItem* embItem = Item->asPathText()->itemRenderText.hasObject(a)?
-		                    Item->asPathText()->itemRenderText.object(a) : NULL;
-		
-		chstr = Item->asPathText()->itemRenderText.text(a,1);
-		if ((chstr == QChar(13)) || (chstr == QChar(29)))
-			continue;
-		if (chstr == QChar(30))
-		{
-			chstr = Item->ExpandToken(a);
-			if (chstr == QChar(32))
-				continue;
-		}
-		double chs = charStyle.fontSize();
-		if (charStyle.effects() & ScStyle_SmallCaps)
-		{
-			if (chstr.toUpper() != chstr)
-			{
-				chs = qMax(static_cast<int>(charStyle.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1);
-				chstr = chstr.toUpper();
-			}
-		}
-		else if (charStyle.effects() & ScStyle_AllCaps)
-			chstr = chstr.toUpper();
-		uint chr = chstr[0].unicode();
-		QPointF tangt = QPointF( cos(pdata->PRot), sin(pdata->PRot) );
-		QTransform trafo = QTransform( 1, 0, 0, -1, -pdata->PDx * conversionFactor, 0 );
-		if (Item->textPathFlipped)
-			trafo *= QTransform(1, 0, 0, -1, 0, 0);
-		if (Item->textPathType == 0)
-			trafo *= QTransform( tangt.x(), tangt.y(), tangt.y(), -tangt.x(), pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor );
-		else if (Item->textPathType == 1)
-			trafo *= QTransform(1, 0, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor );
-		else if (Item->textPathType == 2)
-		{
-			double a = 1;
-			if (tangt.x() < 0)
-				a = -1;
-			if (fabs(tangt.x()) > 0.1)
-				trafo *= QTransform( a, (tangt.y() / tangt.x()) * a, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor ); // ID's Skew mode
-			else
-				trafo *= QTransform( a, 4 * a, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor );
-		}
-		if (charStyle.baselineOffset() != 0)
-			trafo.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0));
-		trafo.translate(0, Item->BaseOffs);
-		QTransform finalMat = trafo;
-		if (chr == SpecialChars::OBJECT)
-		{
-			if (embItem != NULL)
-			{
-				QDomElement obO = p_docu.createElement("Canvas");
-				QTransform mm = finalMat;
-				mm.translate(0, (-(embItem->height() * (charStyle.scaleV() / 1000.0))) * conversionFactor);
-				if (charStyle.scaleH() != 1000)
-					mm.scale(charStyle.scaleH() / 1000.0, 1);
-				if (charStyle.scaleV() != 1000)
-					mm.scale(1, charStyle.scaleV() / 1000.0);
-				obO.setAttribute("RenderTransform", MatrixToStr(mm));
-				QList<PageItem*> emG;
-				if (embItem->isGroup())
-					emG = embItem->getItemList();
-				else
-					emG.append(embItem);
-				for (int em = 0; em < emG.count(); ++em)
-				{
-					PageItem* embed = emG.at(em);
-					writeItemOnPage(embed->gXpos, embed->gYpos, embed, obO, rel_root);
-				}
-				grp.appendChild(obO);
-			}
-			continue;
-		}
-		finalMat.scale(conversionFactor, conversionFactor);
-		FPointArray pts;
-		QTransform chma;
-		uint gl = charStyle.font().char2CMap(chr);
-		pts = charStyle.font().glyphOutline(gl);
-		if (pts.size() < 4)
-			continue;
-		chma = QTransform();
-		chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0);
-		pts.map(chma);
-		if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript))
-			pts.translate(0, -(chs / 10.0 * glyphs->scaleV));
-		else
-			pts.translate(0, -(chs / 10.0));
-		if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript))
-			pts.translate(0, glyphs->yoffset);
-		if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None))
-		{
-			FPointArray ptsS = pts.copy();
-			ptsS.translate(charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0, -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0);
-			ptsS.map(finalMat);
-			QString paS = SetClipPath(&ptsS, true);
-			QDomElement glyS = p_docu.createElement("Path");
-			glyS.setAttribute("Data", paS);
-			glyS.setAttribute("Fill", SetColor(charStyle.strokeColor(), charStyle.strokeShade(), 0));
-			grp.appendChild(glyS);
-		}
-		pts.map(finalMat);
-		QString pa = SetClipPath(&pts, true);
-		QDomElement gly = p_docu.createElement("Path");
-		gly.setAttribute("Data", pa);
-		gly.setAttribute("Fill", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0));
-		if (charStyle.effects() & ScStyle_Outline)
-		{
-			gly.setAttribute("StrokeThickness", FToStr((chs * charStyle.outlineWidth() / 10000.0) * conversionFactor));
-			gly.setAttribute("Stroke", SetColor(charStyle.strokeColor(), charStyle.strokeShade(), 0));
-		}
-		grp.appendChild(gly);
-		if ((charStyle.effects() & ScStyle_Underline) || ((charStyle.effects() & ScStyle_UnderlineWords)  && chstr.toUInt() != charStyle.font().char2CMap(QChar(' '))))
-		{
-			double st, lw;
-			if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1))
-			{
-				if (charStyle.underlineOffset() != -1)
-					st = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0));
-				else
-					st = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-				if (charStyle.underlineWidth() != -1)
-					lw = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-				else
-					lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				st = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-				lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-			}
-			if (charStyle.baselineOffset() != 0)
-				st += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0);
-			FPointArray ptsS;
-			ptsS.svgInit();
-			if (charStyle.effects() & ScStyle_Subscript)
-			{
-				ptsS.svgMoveTo(glyphs->xoffset, glyphs->yoffset - st);
-				ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, glyphs->yoffset - st);
-			}
-			else
-			{
-				ptsS.svgMoveTo(glyphs->xoffset, -st);
-				ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, -st);
-			}
-			ptsS.map(finalMat);
-			QString paS = SetClipPath(&ptsS, true);
-			QDomElement gly = p_docu.createElement("Path");
-			gly.setAttribute("Data", paS);
-			gly.setAttribute("Stroke", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0));
-			gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor));
-			grp.appendChild(gly);
-		}
-		if (charStyle.effects() & ScStyle_Strikethrough)
-		{
-			double st, lw;
-			if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1))
-			{
-				if (charStyle.strikethruOffset() != -1)
-					st = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0));
-				else
-					st = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-				if (charStyle.strikethruWidth() != -1)
-					lw = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-				else
-					lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				st = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-				lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-			}
-			if (charStyle.baselineOffset() != 0)
-				st += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0);
-			FPointArray ptsS;
-			ptsS.svgInit();
-			ptsS.svgMoveTo(glyphs->xoffset, -st);
-			ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, -st);
-			ptsS.map(finalMat);
-			QString paS = SetClipPath(&ptsS, true);
-			QDomElement gly = p_docu.createElement("Path");
-			gly.setAttribute("Data", paS);
-			gly.setAttribute("Stroke", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0));
-			gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor));
-			grp.appendChild(gly);
-		}
-	}
-	parentElem.appendChild(grp);
-	return;
+	XPSPainter p(Item, grp, this, xps_fontMap, rel_root);
+	Item->textLayout.renderBackground(&p);
+	Item->textLayout.render(&p);
 }
 
 void XPSExPlug::processSymbolItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
@@ -2274,10 +1641,10 @@
 	}
 }
 
-QString XPSExPlug::embedFont(const ScFace *font, QDomElement &rel_root)
+QString XPSExPlug::embedFont(const ScFace font, QDomElement &rel_root)
 {
 	QByteArray fontData;
-	loadRawText(font->fontFilePath(), fontData);
+	loadRawText(font.fontFilePath(), fontData);
 	QUuid id = QUuid::createUuid();
 	QString guidString = id.toString();
 	guidString = guidString.toUpper();
@@ -3084,6 +2451,12 @@
 	return cc.setNum(c);
 }
 
+QString XPSExPlug::MatrixToStr(QTransform &mat, double factor)
+{
+	QString cc("%1, %2, %3, %4, %5, %6");
+	return  cc.arg(mat.m11()).arg(mat.m12()).arg(mat.m21()).arg(mat.m22()).arg(mat.dx() * factor).arg(mat.dy() * factor);
+}
+
 QString XPSExPlug::MatrixToStr(QTransform &mat)
 {
 	QString cc("%1, %2, %3, %4, %5, %6");

Modified: trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.h
==============================================================================
--- trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.h	(original)
+++ trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.h	Wed Mar 23 20:21:36 2016
@@ -58,8 +58,9 @@
 
 class XPSExPlug : public QObject
 {
-    Q_OBJECT
+	Q_OBJECT
 
+	friend class XPSPainter;
 public:
 	/*!
 	\author Franz Schmid
@@ -81,7 +82,6 @@
 	void processLineItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root);
 	void processImageItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root);
 	void processTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root);
-	void processPathTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root);
 	void processSymbolItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root);
 	void processTableItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root);
 	void paintBorder(const TableBorder &border, const QPointF &start, const QPointF &end, const QPointF &startOffsetFactors, const QPointF &endOffsetFactors, QDomElement &ob);
@@ -89,7 +89,7 @@
 	void processSymbolStroke(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root);
 	void processArrows(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root);
 	void drawArrow(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, FPointArray &arrow);
-	QString embedFont(const ScFace *font, QDomElement &rel_root);
+	QString embedFont(const ScFace font, QDomElement &rel_root);
 	void GetMultiStroke(struct SingleLine *sl, QDomElement &parentElem);
 	void getStrokeStyle(PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, double xOffset, double yOffset, bool forArrow = false);
 	void getFillStyle(PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, double xOffset, double yOffset, bool withTransparency = true);
@@ -104,6 +104,7 @@
 	QString FToStr(double c);
 	QString IToStr(int c);
 	QString MatrixToStr(QTransform &mat);
+	QString MatrixToStr(QTransform &mat, double factor);
 	int hex2int(char hex);
 	bool checkForFallback(PageItem *Item);
 	ScribusDoc* m_Doc;

Modified: trunk/Scribus/scribus/pslib.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pslib.cpp
==============================================================================
--- trunk/Scribus/scribus/pslib.cpp	(original)
+++ trunk/Scribus/scribus/pslib.cpp	Wed Mar 23 20:21:36 2016
@@ -55,12 +55,157 @@
 #include "scstreamfilter_ascii85.h"
 #include "scstreamfilter_flate.h"
 #include "tableutils.h"
+#include "text/textlayoutpainter.h"
 #include "ui/multiprogressdialog.h"
 #include "util.h"
 #include "util_formats.h"
 #include "util_math.h"
+#include "text/boxes.h"
 
 using namespace TableUtils;
+
+class PSPainter:public TextLayoutPainter
+{
+	ScribusDoc* m_Doc;
+	uint m_argh;
+	ScPage* m_page;
+	bool m_sep;
+	bool m_farb;
+	bool m_master;
+	PSLib* m_ps;
+
+	void applyTransform()
+	{
+		if (matrix() != QTransform())
+		{
+			m_ps->PutStream(m_ps->MatrixToStr(1.0, 0.0, 0.0, -1.0, x(), 0.0) + "\n");
+			m_ps->PutStream(m_ps->MatrixToStr(matrix().m11(), -matrix().m12(), matrix().m21(), -matrix().m22(), matrix().dx(), -matrix().dy()) + "\n");
+			m_ps->PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n");
+		}
+	}
+
+public:
+	PSPainter(ScribusDoc* Doc, uint argh, ScPage* page, bool sep, bool farb, bool master, PSLib* ps):
+		m_Doc(Doc),
+		m_argh(argh),
+		m_page(page),
+		m_sep(sep),
+		m_farb(farb),
+		m_master(master),
+		m_ps(ps)
+	{}
+
+	void drawGlyph(const GlyphLayout gl);
+	void drawGlyphOutline(const GlyphLayout gl, bool fill);
+	void drawLine(QPointF start, QPointF end);
+	void drawRect(QRectF rect);
+	void drawObject(PageItem* item);
+};
+
+void PSPainter::drawGlyph(const GlyphLayout gl)
+{
+	if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+		return;
+
+	m_ps->PS_save();
+	applyTransform();
+	m_ps->PS_translate(x(), -(y() - fontSize()));
+	if (gl.scaleH != 1.0)
+		m_ps->PS_scale(gl.scaleH, 1);
+	if (gl.scaleV != 1.0)
+	{
+		m_ps->PS_translate(0, -(fontSize() - fontSize() * gl.scaleV));
+		m_ps->PS_scale(1, gl.scaleV);
+	}
+	if (fillColor().color != CommonStrings::None)
+		m_ps->putColorNoDraw(fillColor().color, fillColor().shade);
+	m_ps->PS_showSub(gl.glyph, m_ps->FontSubsetMap[font().scName()], fontSize(), false);
+	m_ps->PS_restore();
+}
+
+void PSPainter::drawGlyphOutline(const GlyphLayout gl, bool fill)
+{
+	if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+		return;
+
+	int h, s, v, k;
+	QVector<double> dum;
+	dum.clear();
+	m_ps->PS_save();
+	applyTransform();
+	if (strokeColor().color != CommonStrings::None)
+	{
+		m_ps->PS_setlinewidth(strokeWidth());
+		m_ps->PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
+		m_ps->PS_setdash(Qt::SolidLine, 0, dum);
+		m_ps->PS_translate(x(), -(y() - fontSize()));
+		FPointArray gly = font().glyphOutline(gl.glyph);
+		QTransform chma;
+		chma.scale((fontSize() * gl.scaleH) / 10.0, (fontSize() * gl.scaleV) / 10.0);
+		gly.map(chma);
+		m_ps->PS_translate(0, -(fontSize() - fontSize() * gl.scaleV));
+		m_ps->SetColor(strokeColor().color, strokeColor().shade, &h, &s, &v, &k);
+		m_ps->PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+		m_ps->SetClipPath(&gly, true);
+		m_ps->PS_closepath();
+		m_ps->putColor(strokeColor().color, strokeColor().shade, false);
+
+		if (gl.scaleH != 1.0 || gl.scaleV != 1.0)
+			m_ps->PS_scale(gl.scaleH, gl.scaleV);
+		if (fill)
+			m_ps->putColorNoDraw(fillColor().color, fillColor().shade);
+		m_ps->PS_showSub(gl.glyph, m_ps->FontSubsetMap[font().scName()], fontSize(), false);
+	}
+	m_ps->PS_restore();
+}
+
+void PSPainter::drawRect(QRectF rect)
+{
+	int h, s, v, k;
+	m_ps->PS_save();
+	applyTransform();
+	m_ps->PS_moveto(x() + rect.x(), -y() - rect.y());
+	m_ps->PS_lineto(x() + rect.x() + rect.width(), -y() - rect.y());
+	m_ps->PS_lineto(x() + rect.x() + rect.width(), -y() - rect.y() - rect.height());
+	m_ps->PS_lineto(x() + rect.x(), -y() - rect.y() - rect.height());
+	m_ps->PS_closepath();
+	m_ps->SetColor(fillColor().color, fillColor().shade, &h, &s, &v, &k);
+	m_ps->PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+	m_ps->putColor(fillColor().color, fillColor().shade, true);
+	m_ps->PS_restore();
+}
+
+void PSPainter::drawLine(QPointF start, QPointF end)
+{
+	int h, s, v, k ;
+	QVector<double> dum;
+	dum.clear();
+	m_ps->PS_save();
+	applyTransform();
+	if (fillColor().color != CommonStrings::None)
+	{
+		m_ps->PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
+		m_ps->PS_setdash(Qt::SolidLine, 0, dum);
+		m_ps->SetColor(fillColor().color,fillColor().shade, &h, &s, &v, &k);
+		m_ps->PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+	}
+	m_ps->PS_setlinewidth(strokeWidth());
+	m_ps->PS_moveto(x() + start.x(), -y() - start.y());
+	m_ps->PS_lineto(x() + end.x(), -y() - end.y());
+	m_ps->putColor(fillColor().color, fillColor().shade, false);
+	m_ps->PS_restore();
+}
+
+void PSPainter::drawObject(PageItem* item)
+{
+	m_ps->PS_save();
+	m_ps->PS_translate(x(), -y());
+	applyTransform();
+	if (scaleH() != 1 || scaleV() != 1)
+		m_ps->PS_scale(scaleH(), scaleV());
+	m_ps->ProcessItem(m_Doc, m_page, item, m_argh, m_sep, m_farb, m_master, true);
+	m_ps->PS_restore();
+}
 
 PSLib::PSLib(PrintOptions &options, bool psart, SCFonts &AllFonts, QMap<QString, QMap<uint, FPointArray> > DocFonts, ColorList DocColors, bool pdf, bool spot)
 {
@@ -555,7 +700,7 @@
 	PutStream("%%Page: " + IToStr(Seiten) + " " + IToStr(Seiten) + "\n");
 	PutStream("%%PageOrientation: ");
 // when creating EPS files determine the orientation from the bounding box
-  	if (!psExport)
+	if (!psExport)
 	{
 		if ((pg->width() - Ma->left() - Ma->right()) <= (pg->height() - Ma->bottom() - Ma->top()))
 			PutStream("Portrait\n");
@@ -1665,14 +1810,8 @@
 
 bool PSLib::ProcessItem(ScribusDoc* Doc, ScPage* a, PageItem* c, uint PNr, bool sep, bool farb, bool master, bool embedded, bool useTemplate)
 {
-	double tsz;
 	int h, s, v, k;
-	int d;
-	int savedOwnPage;
-	//ScText *hl;
 	QVector<double> dum;
-	QChar chstr;
-	QString tmps;
 	if (c->printEnabled())
 	{
 		fillRule = true;
@@ -2156,401 +2295,7 @@
 					PS_restore();
 				}
 			}
-			savedOwnPage = c->OwnPage;
-			c->OwnPage = PNr-1;
-			c->asPathText()->layout();
-			c->OwnPage = savedOwnPage;
-			for (d = 0; d < c->maxCharsInFrame(); ++d)
-			{
-                // hl = c->asPathText()->itemRenderText.item_p(d);
-				chstr = c->asPathText()->itemRenderText.text(d);
-				if ((chstr == QChar(13)) || (chstr == QChar(30)) || (chstr == QChar(9)) || (chstr == QChar(28)))
-					continue;
-                
-                const CharStyle & style(c->asPathText()->itemRenderText.charStyle(d));
-				const PathData& pdata(c->textLayout.point(d));
-                const GlyphLayout* glyphs(c->asPathText()->itemRenderText.getGlyphs(d));
-                PageItem* embItem = c->asPathText()->itemRenderText.hasObject(d)?
-                                          c->asPathText()->itemRenderText.object(d) : NULL;
-                
-				QPointF tangt = QPointF( cos(pdata.PRot), sin(pdata.PRot) );
-				tsz = style.fontSize();
-				if (chstr == QChar(29))
-					chstr = ' ';
-				if (chstr == QChar(0xA0))
-					chstr = ' ';
-				if (style.effects() & ScStyle_AllCaps)
-				{
-					if (chstr.toUpper() != chstr)
-						chstr = chstr.toUpper();
-				}
-				if (style.effects() & ScStyle_SmallCaps)
-				{
-					if (chstr.toUpper() != chstr)
-					{
-						tsz = style.fontSize() * Doc->typographicPrefs().valueSmallCaps / 100;
-						chstr = chstr.toUpper();
-					}
-				}
-				if (style.effects() & ScStyle_Superscript)
-					tsz = style.fontSize() * Doc->typographicPrefs().scalingSuperScript / 100;
-				if (style.effects() & ScStyle_Subscript)
-					tsz = style.fontSize() * Doc->typographicPrefs().scalingSubScript / 100;
-				if (style.fillColor() != CommonStrings::None)
-				{
-					SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-					PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-				}
-				if (embItem != NULL)
-				{
-					PS_save();
-					PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n");
-					if (c->textPathFlipped)
-					{
-						PutStream("[1 0 0 -1 0 0]\n");
-						PutStream("[0 0 0  0 0 0] concatmatrix\n"); //???????
-					}
-					if (c->textPathType == 0)
-						PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n");
-					else if (c->textPathType == 1)
-						PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-					else if (c->textPathType == 2)
-					{
-						double a = 1;
-						double b = -1;
-						if (tangt.x()< 0)
-						{
-							a = -1;
-							b = 1;
-						}
-						if (fabs(tangt.x()) > 0.1)
-							PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-						else
-							PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-					}
-					PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n");
-//					PS_translate(0, (tsz / 10.0));
-					if (c->BaseOffs != 0)
-						PS_translate(0, -c->BaseOffs);
-					if (style.scaleH() != 1000)
-						PS_scale(style.scaleH() / 1000.0, 1);
-					QList<PageItem*> emG;
-                    if (embItem->isGroup())
-                        emG = embItem->getItemList();
-                    else
-                        emG.append(embItem);
-					for (int em = 0; em < emG.count(); ++em)
-					{
-						PageItem* embedded = emG.at(em);
-						PS_save();
-						PS_translate(embedded->gXpos * (style.scaleH() / 1000.0), ((embedded->gHeight * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0)));
-						if (style.baselineOffset() != 0)
-							PS_translate(0, embedded->gHeight * (style.baselineOffset() / 1000.0));
-						if (style.scaleH() != 1000)
-							PS_scale(style.scaleH() / 1000.0, 1);
-						if (style.scaleV() != 1000)
-							PS_scale(1, style.scaleV() / 1000.0);
-						ProcessItem(Doc, a, embedded, PNr, sep, farb, master, true);
-						PS_restore();
-					}
-					PS_restore();
-					continue;
-				}
-				/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */
-				if (FontSubsetMap.contains(style.font().scName()))
-				{
-//					uint chr = chstr.unicode();
-					uint chr = style.font().char2CMap(chstr);
-					if (style.font().canRender(chstr))
-					{
-						PS_save();
-						if (style.fillColor() != CommonStrings::None)
-						{
-							PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n");
-							if (c->textPathFlipped)
-							{
-								PutStream("[1.0 0.0 0.0 -1.0 0.0 0.0]\n");
-								PutStream("[0.0 0.0 0.0  0.0 0.0 0.0] concatmatrix\n");
-							}
-							if (c->textPathType == 0)
-								PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n");
-							else if (c->textPathType == 1)
-								PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-							else if (c->textPathType == 2)
-							{
-								double a = 1;
-								double b = -1;
-								if (tangt.x() < 0)
-								{
-									a = -1;
-									b = 1;
-								}
-								if (fabs(tangt.x()) > 0.1)
-									PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-								else
-									PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-							}
-							PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n");
-							PS_translate(0, (tsz / 10.0));
-							if (c->BaseOffs != 0)
-								PS_translate(0, -c->BaseOffs);
-							if (glyphs->xoffset !=0 || glyphs->yoffset != 0)
-								PS_translate(glyphs->xoffset, -glyphs->yoffset);
-							if (style.scaleH() != 1000)
-								PS_scale(style.scaleH() / 1000.0, 1);
-							if (((style.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13)))  
-								|| ((style.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr)))
-							{
-								PS_save();
-								PS_translate(0, -(tsz / 10.0));
-								double Ulen = glyphs->xadvance;
-								double Upos, Uwid;
-								if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1))
-								{
-									if (style.underlineOffset() != -1)
-										Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0));
-									else
-										Upos = style.font().underlinePos(style.fontSize() / 10.0);
-									if (style.underlineWidth() != -1)
-										Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0);
-									else
-										Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-								}
-								else
-								{
-									Upos = style.font().underlinePos(style.fontSize() / 10.0);
-									Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-								}
-								if (style.baselineOffset() != 0)
-									Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-								if (style.fillColor() != CommonStrings::None)
-								{
-									SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-									PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-								}
-								PS_setlinewidth(Uwid);
-								if (style.effects() & ScStyle_Subscript)
-								{
-									PS_moveto(glyphs->xoffset     , Upos);
-									PS_lineto(glyphs->xoffset+Ulen, Upos);
-								}
-								else
-								{
-									PS_moveto(glyphs->xoffset     , glyphs->yoffset+Upos);
-									PS_lineto(glyphs->xoffset+Ulen, glyphs->yoffset+Upos);
-								}
-								putColor(style.fillColor(), style.fillShade(), false);
-								PS_restore();
-							}
-							if (chstr != ' ')
-							{
-								if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None))
-								{
-									PS_save();
-									PS_translate(style.fontSize() * style.shadowXOffset() / 10000.0, style.fontSize() * style.shadowYOffset() / 10000.0);
-									putColorNoDraw(style.strokeColor(), style.strokeShade());
-									PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, false);
-									PS_restore();
-								}
-								putColorNoDraw(style.fillColor(), style.fillShade());
-								PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, false);
-								if ((style.effects() & ScStyle_Outline))
-								{
-									if ((style.strokeColor() != CommonStrings::None) && ((tsz * style.outlineWidth() / 10000.0) != 0))
-									{
-										PS_save();
-										PS_setlinewidth(tsz * style.outlineWidth() / 10000.0);
-										putColorNoDraw(style.strokeColor(), style.strokeShade());
-										PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, true);
-										PS_restore();
-									}
-								}
-							}
-							if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP))
-							{
-								PS_save();
-								PS_translate(0, -(tsz / 10.0));
-								double Ulen = glyphs->xadvance;
-								double Upos, Uwid;
-								if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1))
-								{
-									if (style.strikethruOffset() != -1)
-										Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0));
-									else
-										Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-									if (style.strikethruWidth() != -1)
-										Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0);
-									else
-										Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-								}
-								else
-								{
-									Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-									Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-								}
-								if (style.baselineOffset() != 0)
-									Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-								if (style.fillColor() != CommonStrings::None)
-								{
-									SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-									PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-								}
-								PS_setlinewidth(Uwid);
-								PS_moveto(glyphs->xoffset     , Upos);
-								PS_lineto(glyphs->xoffset+Ulen, Upos);
-								putColor(style.fillColor(), style.fillShade(), false);
-								PS_restore();
-							}
-						}
-						PS_restore();
-					}
-				}
-				else
-				{
-					uint glyph = glyphs->glyph;
-					PS_selectfont(style.font().replacementName(), tsz / 10.0);
-					PS_save();
-					PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n");
-					if (c->textPathFlipped)
-					{
-						PutStream("[1.0 0.0 0.0 -1.0 0.0 0.0]\n");
-						PutStream("[0.0 0.0 0.0  0.0 0.0 0.0] concatmatrix\n");
-					}
-					if (c->textPathType == 0)
-						PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n");
-					else if (c->textPathType == 1)
-						PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-					else if (c->textPathType == 2)
-					{
-						double a = 1;
-						double b = -1;
-						if (tangt.x() < 0)
-						{
-							a = -1;
-							b = 1;
-						}
-						if (fabs(tangt.x()) > 0.1)
-							PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-						else
-							PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-					}
-					PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n");
-					if (c->BaseOffs != 0)
-						PS_translate(0, -c->BaseOffs);
-					if (glyphs->xoffset !=0 || glyphs->yoffset != 0)
-						PS_translate(glyphs->xoffset, -glyphs->yoffset);
-					if (((style.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13)))  
-						|| ((style.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr)))
-					{
-						PS_save();
-						double Ulen = glyphs->xadvance;
-						double Upos, Uwid;
-						if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1))
-						{
-							if (style.underlineOffset() != -1)
-								Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0));
-							else
-								Upos = style.font().underlinePos(style.fontSize() / 10.0);
-							if (style.underlineWidth() != -1)
-								Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0);
-							else
-								Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-						}
-						else
-						{
-							Upos = style.font().underlinePos(style.fontSize() / 10.0);
-							Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-						}
-						if (style.baselineOffset() != 0)
-							Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-						if (style.fillColor() != CommonStrings::None)
-						{
-							SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-							PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-						}
-						PS_setlinewidth(Uwid);
-						if (style.effects() & ScStyle_Subscript)
-						{
-							PS_moveto(glyphs->xoffset     , Upos);
-							PS_lineto(glyphs->xoffset+Ulen, Upos);
-						}
-						else
-						{
-							PS_moveto(glyphs->xoffset     , glyphs->yoffset+Upos);
-							PS_lineto(glyphs->xoffset+Ulen, glyphs->yoffset+Upos);
-						}
-						putColor(style.fillColor(), style.fillShade(), false);
-						PS_restore();
-					}
-					if (chstr != ' ')
-					{
-						if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None))
-						{
-							PS_save();
-							PS_translate(style.fontSize() * style.shadowXOffset() / 10000.0, style.fontSize() * style.shadowYOffset() / 10000.0);
-							PS_show_xyG(style.font().replacementName(), glyph, 0, 0, style.strokeColor(), style.strokeShade());
-							PS_restore();
-						}
-						PS_show_xyG(style.font().replacementName(), glyph, 0, 0, style.fillColor(), style.fillShade());
-						if ((style.effects() & ScStyle_Outline))
-						{
-							if ((style.strokeColor() != CommonStrings::None) && ((tsz * style.outlineWidth() / 10000.0) != 0))
-							{
-								uint gl = style.font().char2CMap(chstr);
-								FPointArray gly = style.font().glyphOutline(gl);
-								QTransform chma;
-								chma.scale(tsz / 100.0, tsz / 100.0);
-								gly.map(chma);
-								PS_save();
-								PS_setlinewidth(tsz * style.outlineWidth() / 10000.0);
-								PS_translate(0,  tsz / 10.0);
-								SetColor(style.strokeColor(), style.strokeShade(), &h, &s, &v, &k);
-								PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-								SetClipPath(&gly);
-								PS_closepath();
-								putColor(style.strokeColor(), style.strokeShade(), false);
-								PS_restore();
-							}
-						}
-					}
-					if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP))
-					{
-						PS_save();
-						double Ulen = glyphs->xadvance;
-						double Upos, Uwid;
-						if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1))
-						{
-							if (style.strikethruOffset() != -1)
-								Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0));
-							else
-								Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-							if (style.strikethruWidth() != -1)
-								Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0);
-							else
-								Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-						}
-						else
-						{
-							Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-							Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-						}
-						if (style.baselineOffset() != 0)
-							Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-						if (style.fillColor() != CommonStrings::None)
-						if (style.fillColor() != CommonStrings::None)
-						{
-							SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-							PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-						}
-						PS_setlinewidth(Uwid);
-						PS_moveto(glyphs->xoffset     , Upos);
-						PS_lineto(glyphs->xoffset+Ulen, Upos);
-						putColor(style.fillColor(), style.fillShade(), false);
-						PS_restore();
-					}
-					PS_restore();
-				}
-			}
+			setTextSt(Doc, c, PNr-1, a, sep, farb, master);
 			break;
 		case PageItem::Symbol:
 			if (m_Doc->docPatterns.contains(c->pattern()))
@@ -3221,10 +2966,6 @@
 			}
 			else if (ite->asPathText())
 			{
-				double tsz;
-				int d;
-				//ScText *hl;
-				QChar chstr;
 				PS_save();
 				PS_translate(ite->xPos() - mPage->xOffset(), mPage->height() - (ite->yPos() - mPage->yOffset()));
 				if (ite->PoShow)
@@ -3270,400 +3011,7 @@
 						PS_restore();
 					}
 				}
-				int savedOwnPage = ite->OwnPage;
-				ite->OwnPage = PNr;
-				ite->asPathText()->layout();
-				ite->OwnPage = savedOwnPage;
-				for (d = 0; d < ite->maxCharsInFrame(); ++d)
-				{
-                    //hl = ite->asPathText()->itemRenderText.item_p(d);
-					chstr = ite->asPathText()->itemRenderText.text(d);
-					const CharStyle & style(ite->asPathText()->itemRenderText.charStyle(d));
-					if ((chstr == QChar(13)) || (chstr == QChar(30)) || (chstr == QChar(9)) || (chstr == QChar(28)))
-						continue;
-                    const PathData& pdata(ite->textLayout.point(d));
-                    const GlyphLayout* glyphs(ite->asPathText()->itemRenderText.getGlyphs(d));
-                    PageItem* embItem = ite->asPathText()->itemRenderText.hasObject(d)?
-                                              ite->asPathText()->itemRenderText.object(d) : NULL;
-                    
-					QPointF tangt = QPointF( cos(pdata.PRot), sin(pdata.PRot) );
-					tsz = style.fontSize();
-					if (chstr == QChar(29))
-						chstr = ' ';
-					if (chstr == QChar(0xA0))
-						chstr = ' ';
-					if (style.effects() & ScStyle_AllCaps)
-					{
-						if (chstr.toUpper() != chstr)
-							chstr = chstr.toUpper();
-					}
-					if (style.effects() & ScStyle_SmallCaps)
-					{
-						if (chstr.toUpper() != chstr)
-						{
-							tsz = style.fontSize() * Doc->typographicPrefs().valueSmallCaps / 100;
-							chstr = chstr.toUpper();
-						}
-					}
-					if (style.effects() & ScStyle_Superscript)
-						tsz = style.fontSize() * Doc->typographicPrefs().scalingSuperScript / 100;
-					if (style.effects() & ScStyle_Subscript)
-						tsz = style.fontSize() * Doc->typographicPrefs().scalingSubScript / 100;
-					if (style.fillColor() != CommonStrings::None)
-					{
-						SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-						PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-					}
-					if (embItem != NULL)
-					{
-						PS_save();
-						PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n");
-						if (ite->textPathFlipped)
-						{
-							PutStream("[1 0 0 -1 0 0]\n");
-							PutStream("[0 0 0  0 0 0] concatmatrix\n"); //???????
-						}
-						if (ite->textPathType == 0)
-							PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n");
-						else if (ite->textPathType == 1)
-							PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-						else if (ite->textPathType == 2)
-						{
-							double a = 1;
-							double b = -1;
-							if (tangt.x()< 0)
-							{
-								a = -1;
-								b = 1;
-							}
-							if (fabs(tangt.x()) > 0.1)
-								PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-							else
-								PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-						}
-						PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n");
-	//					PS_translate(0, (tsz / 10.0));
-						if (ite->BaseOffs != 0)
-							PS_translate(0, -ite->BaseOffs);
-						if (style.scaleH() != 1000)
-							PS_scale(style.scaleH() / 1000.0, 1);
-						QList<PageItem*> emG;
-                        if (embItem->isGroup())
-                            emG = embItem->getItemList();
-                        else
-                            emG.append(embItem);
-                        for (int em = 0; em < emG.count(); ++em)
-						{
-							PageItem* embedded = emG.at(em);
-							PS_save();
-							PS_translate(embedded->gXpos * (style.scaleH() / 1000.0), ((embedded->gHeight * (style.scaleV() / 1000.0)) - embedded->gYpos * (style.scaleV() / 1000.0)));
-							if (style.baselineOffset() != 0)
-								PS_translate(0, embedded->gHeight * (style.baselineOffset() / 1000.0));
-							if (style.scaleH() != 1000)
-								PS_scale(style.scaleH() / 1000.0, 1);
-							if (style.scaleV() != 1000)
-								PS_scale(1, style.scaleV() / 1000.0);
-							ProcessItem(Doc, mPage, embedded, PNr, sep, farb, true, true);
-							PS_restore();
-						}
-						PS_restore();
-						continue;
-					}
-					/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */
-					if (FontSubsetMap.contains(style.font().scName()))
-					{
-	//					uint chr = chstr.unicode();
-						uint chr = style.font().char2CMap(chstr);
-						if (style.font().canRender(chstr))
-						{
-							PS_save();
-							if (style.fillColor() != CommonStrings::None)
-							{
-								PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n");
-								if (ite->textPathFlipped)
-								{
-									PutStream("[1.0 0.0 0.0 -1.0 0.0 0.0]\n");
-									PutStream("[0.0 0.0 0.0  0.0 0.0 0.0] concatmatrix\n");
-								}
-								if (ite->textPathType == 0)
-									PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n");
-								else if (ite->textPathType == 1)
-									PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-								else if (ite->textPathType == 2)
-								{
-									double a = 1;
-									double b = -1;
-									if (tangt.x() < 0)
-									{
-										a = -1;
-										b = 1;
-									}
-									if (fabs(tangt.x()) > 0.1)
-										PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-									else
-										PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-								}
-								PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n");
-								PS_translate(0, (tsz / 10.0));
-								if (ite->BaseOffs != 0)
-									PS_translate(0, -ite->BaseOffs);
-								if (glyphs->xoffset !=0 || glyphs->yoffset != 0)
-									PS_translate(glyphs->xoffset, -glyphs->yoffset);
-								if (style.scaleH() != 1000)
-									PS_scale(style.scaleH() / 1000.0, 1);
-								if (((style.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13)))
-									|| ((style.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr)))
-								{
-									PS_save();
-									PS_translate(0, -(tsz / 10.0));
-									double Ulen = glyphs->xadvance;
-									double Upos, Uwid;
-									if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1))
-									{
-										if (style.underlineOffset() != -1)
-											Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0));
-										else
-											Upos = style.font().underlinePos(style.fontSize() / 10.0);
-										if (style.underlineWidth() != -1)
-											Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0);
-										else
-											Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-									}
-									else
-									{
-										Upos = style.font().underlinePos(style.fontSize() / 10.0);
-										Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-									}
-									if (style.baselineOffset() != 0)
-										Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-									if (style.fillColor() != CommonStrings::None)
-									{
-										SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-										PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-									}
-									PS_setlinewidth(Uwid);
-									if (style.effects() & ScStyle_Subscript)
-									{
-										PS_moveto(glyphs->xoffset     , Upos);
-										PS_lineto(glyphs->xoffset+Ulen, Upos);
-									}
-									else
-									{
-										PS_moveto(glyphs->xoffset     , glyphs->yoffset+Upos);
-										PS_lineto(glyphs->xoffset+Ulen, glyphs->yoffset+Upos);
-									}
-									putColor(style.fillColor(), style.fillShade(), false);
-									PS_restore();
-								}
-								if (chstr != ' ')
-								{
-									if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None))
-									{
-										PS_save();
-										PS_translate(style.fontSize() * style.shadowXOffset() / 10000.0, style.fontSize() * style.shadowYOffset() / 10000.0);
-										putColorNoDraw(style.strokeColor(), style.strokeShade());
-										PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, false);
-										PS_restore();
-									}
-									putColorNoDraw(style.fillColor(), style.fillShade());
-									PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, false);
-									if ((style.effects() & ScStyle_Outline))
-									{
-										if ((style.strokeColor() != CommonStrings::None) && ((tsz * style.outlineWidth() / 10000.0) != 0))
-										{
-											PS_save();
-											PS_setlinewidth(tsz * style.outlineWidth() / 10000.0);
-											putColorNoDraw(style.strokeColor(), style.strokeShade());
-											PS_showSub(chr, FontSubsetMap[style.font().scName()], tsz / 10.0, true);
-											PS_restore();
-										}
-									}
-								}
-								if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP))
-								{
-									PS_save();
-									PS_translate(0, -(tsz / 10.0));
-									double Ulen = glyphs->xadvance;
-									double Upos, Uwid;
-									if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1))
-									{
-										if (style.strikethruOffset() != -1)
-											Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0));
-										else
-											Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-										if (style.strikethruWidth() != -1)
-											Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0);
-										else
-											Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-									}
-									else
-									{
-										Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-										Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-									}
-									if (style.baselineOffset() != 0)
-										Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-									if (style.fillColor() != CommonStrings::None)
-									{
-										SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-										PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-									}
-									PS_setlinewidth(Uwid);
-									PS_moveto(glyphs->xoffset     , Upos);
-									PS_lineto(glyphs->xoffset+Ulen, Upos);
-									putColor(style.fillColor(), style.fillShade(), false);
-									PS_restore();
-								}
-							}
-							PS_restore();
-						}
-					}
-					else
-					{
-						uint glyph = glyphs->glyph;
-						PS_selectfont(style.font().replacementName(), tsz / 10.0);
-						PS_save();
-						PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, -pdata.PDx, 0.0) + "\n");
-						if (ite->textPathFlipped)
-						{
-							PutStream("[1.0 0.0 0.0 -1.0 0.0 0.0]\n");
-							PutStream("[0.0 0.0 0.0  0.0 0.0 0.0] concatmatrix\n");
-						}
-						if (ite->textPathType == 0)
-							PutStream( MatrixToStr(tangt.x(), -tangt.y(), -tangt.y(), -tangt.x(), pdata.PtransX, -pdata.PtransY) + "\n");
-						else if (ite->textPathType == 1)
-							PutStream( MatrixToStr(1.0, 0.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-						else if (ite->textPathType == 2)
-						{
-							double a = 1;
-							double b = -1;
-							if (tangt.x() < 0)
-							{
-								a = -1;
-								b = 1;
-							}
-							if (fabs(tangt.x()) > 0.1)
-								PutStream( MatrixToStr(a, (tangt.y() / tangt.x()) * b, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-							else
-								PutStream( MatrixToStr(a, 4.0, 0.0, -1.0, pdata.PtransX, -pdata.PtransY) + "\n");
-						}
-						PutStream("[0.0 0.0 0.0 0.0 0.0 0.0] concatmatrix\nconcat\n");
-						if (ite->BaseOffs != 0)
-							PS_translate(0, -ite->BaseOffs);
-						if (glyphs->xoffset !=0 || glyphs->yoffset != 0)
-							PS_translate(glyphs->xoffset, -glyphs->yoffset);
-						if (((style.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13)))
-							|| ((style.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr)))
-						{
-							PS_save();
-							double Ulen = glyphs->xadvance;
-							double Upos, Uwid;
-							if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1))
-							{
-								if (style.underlineOffset() != -1)
-									Upos = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0));
-								else
-									Upos = style.font().underlinePos(style.fontSize() / 10.0);
-								if (style.underlineWidth() != -1)
-									Uwid = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0);
-								else
-									Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-							}
-							else
-							{
-								Upos = style.font().underlinePos(style.fontSize() / 10.0);
-								Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-							}
-							if (style.baselineOffset() != 0)
-								Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-							if (style.fillColor() != CommonStrings::None)
-							{
-								SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-								PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-							}
-							PS_setlinewidth(Uwid);
-							if (style.effects() & ScStyle_Subscript)
-							{
-								PS_moveto(glyphs->xoffset     , Upos);
-								PS_lineto(glyphs->xoffset+Ulen, Upos);
-							}
-							else
-							{
-								PS_moveto(glyphs->xoffset     , glyphs->yoffset+Upos);
-								PS_lineto(glyphs->xoffset+Ulen, glyphs->yoffset+Upos);
-							}
-							putColor(style.fillColor(), style.fillShade(), false);
-							PS_restore();
-						}
-						if (chstr != ' ')
-						{
-							if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None))
-							{
-								PS_save();
-								PS_translate(style.fontSize() * style.shadowXOffset() / 10000.0, style.fontSize() * style.shadowYOffset() / 10000.0);
-								PS_show_xyG(style.font().replacementName(), glyph, 0, 0, style.strokeColor(), style.strokeShade());
-								PS_restore();
-							}
-							PS_show_xyG(style.font().replacementName(), glyph, 0, 0, style.fillColor(), style.fillShade());
-							if ((style.effects() & ScStyle_Outline))
-							{
-								if ((style.strokeColor() != CommonStrings::None) && ((tsz * style.outlineWidth() / 10000.0) != 0))
-								{
-									uint gl = style.font().char2CMap(chstr);
-									FPointArray gly = style.font().glyphOutline(gl);
-									QTransform chma;
-									chma.scale(tsz / 100.0, tsz / 100.0);
-									gly.map(chma);
-									PS_save();
-									PS_setlinewidth(tsz * style.outlineWidth() / 10000.0);
-									PS_translate(0,  tsz / 10.0);
-									SetColor(style.strokeColor(), style.strokeShade(), &h, &s, &v, &k);
-									PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-									SetClipPath(&gly);
-									PS_closepath();
-									putColor(style.strokeColor(), style.strokeShade(), false);
-									PS_restore();
-								}
-							}
-						}
-						if ((style.effects() & ScStyle_Strikethrough) && (chstr != SpecialChars::PARSEP))
-						{
-							PS_save();
-							double Ulen = glyphs->xadvance;
-							double Upos, Uwid;
-							if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1))
-							{
-								if (style.strikethruOffset() != -1)
-									Upos = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0));
-								else
-									Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-								if (style.strikethruWidth() != -1)
-									Uwid = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0);
-								else
-									Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-							}
-							else
-							{
-								Upos = style.font().strikeoutPos(style.fontSize() / 10.0);
-								Uwid = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-							}
-							if (style.baselineOffset() != 0)
-								Upos += (style.fontSize() / 10.0) * glyphs->scaleV * (style.baselineOffset() / 1000.0);
-							if (style.fillColor() != CommonStrings::None)
-							if (style.fillColor() != CommonStrings::None)
-							{
-								SetColor(style.fillColor(), style.fillShade(), &h, &s, &v, &k);
-								PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-							}
-							PS_setlinewidth(Uwid);
-							PS_moveto(glyphs->xoffset     , Upos);
-							PS_lineto(glyphs->xoffset+Ulen, Upos);
-							putColor(style.fillColor(), style.fillShade(), false);
-							PS_restore();
-						}
-						PS_restore();
-					}
-				}
+				setTextSt(Doc, ite, PNr, mPage, sep, farb, true);
 				PS_restore();
 			}
 			if (!success)
@@ -5056,571 +4404,9 @@
  */
 void PSLib::setTextSt(ScribusDoc* Doc, PageItem* ite, uint argh, ScPage* pg, bool sep, bool farb, bool master)
 {
-//	qDebug() << QString("pslib setTextSt: ownPage=%1 pageNr=%2 OnMasterPage=%3;").arg(ite->OwnPage).arg(pg->pageNr()).arg(ite->OnMasterPage);
-	int tabCc = 0;
-	int savedOwnPage = ite->OwnPage;
-	double tabDist = ite->textToFrameDistLeft();
-	QList<ParagraphStyle::TabRecord> tTabValues;
-
-	ite->OwnPage = argh;
-	ite->layout();
-	ite->OwnPage = savedOwnPage;
-	if (ite->lineColor() != CommonStrings::None)
-		tabDist += ite->lineWidth() / 2.0;
-
-	uint llp = 0;
-	while (llp < ite->textLayout.lines())
-	{
-		LineSpec ls = ite->textLayout.line(llp++);
-		const ParagraphStyle& LineStyle = ite->itemText.paragraphStyle(ls.firstItem);
-		if (LineStyle.backgroundColor() != CommonStrings::None)
-		{
-			double y0 = ls.y;
-			double y2 = ls.y;
-			double ascent = ls.ascent;
-			double descent = ls.descent;
-			double rMarg = LineStyle.rightMargin();
-			double lMarg = ls.colLeft;
-			double adjX = 0;
-			if (LineStyle.firstIndent() <= 0)
-				adjX += LineStyle.leftMargin() + LineStyle.firstIndent();
-			while (llp < ite->textLayout.lines())
-			{
-				ls = ite->textLayout.line(llp);
-				if ((ls.colLeft > lMarg) || (ite->itemText.paragraphStyle(ls.firstItem) != LineStyle))
-				{
-					if (y2 == 0)
-						y2 = y0;
-					break;
-				}
-				if (ite->itemText.text(ls.lastItem) == SpecialChars::PARSEP)
-				{
-					y2 = ls.y;
-					descent = ls.descent;
-					if ((llp + 1) < ite->textLayout.lines())
-					{
-						if ((ite->textLayout.line(llp + 1).lastItem - ite->textLayout.line(llp + 1).firstItem) > 0)
-							descent += LineStyle.lineSpacing() - (ls.descent + ite->textLayout.line(llp + 1).ascent);
-					}
-					llp++;
-					break;
-				}
-				y2 = ls.y;
-				descent = ls.descent;
-				if ((llp + 1) < ite->textLayout.lines())
-					descent += LineStyle.lineSpacing() - (ls.descent + ite->textLayout.line(llp + 1).ascent);
-				llp++;
-			}
-			QRectF scr(lMarg + adjX, y0 - ascent, ite->asTextFrame()->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent);
-			PS_save();
-			SetPathAndClip(ite->PoLine, true);
-			int h, s, v, k;
-			SetColor(LineStyle.backgroundColor(), LineStyle.backgroundShade(), &h, &s, &v, &k);
-			PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-			PS_moveto(scr.x(), -scr.y());
-			PS_lineto(scr.x() + scr.width(), -scr.y());
-			PS_lineto(scr.x() + scr.width(), -scr.y() - scr.height());
-			PS_lineto(scr.x(), -scr.y() - scr.height());
-			PS_closepath();
-			putColor(LineStyle.backgroundColor(), LineStyle.backgroundShade(), true);
-			PS_restore();
-		}
-	}
-
-	for (uint ll=0; ll < ite->textLayout.lines(); ++ll)
-	{
-		LineSpec ls = ite->textLayout.line(ll);
-		tabDist = ls.x;
-		double CurX = ls.x;
-		double CurXB = ls.x;
-		QRectF scrG;
-		QString oldBack = "";
-		double oldShade = 100;
-		int last = qMin(ls.lastItem, ite->itemText.length() - 1);
-		for (int a = ls.firstItem; a <= last; ++a)
-		{
-			const GlyphLayout* glyphs(ite->itemText.getGlyphs(a));
-			const CharStyle& charStyle(ite->itemText.charStyle(a));
-			if (charStyle.backColor() != CommonStrings::None)
-			{
-			// This code is for rendering character background color.
-				int h, s, v, k;
-				SetColor(charStyle.backColor(), charStyle.backShade(), &h, &s, &v, &k);
-				PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-				const ParagraphStyle& LineStyle = ite->itemText.paragraphStyle(ls.firstItem);
-				double y1 = ls.y;
-				double hl = ls.height;
-				if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-					hl = Doc->guidesPrefs().valueBaselineGrid;
-				else if (LineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
-					hl = LineStyle.lineSpacing();
-				if (ls.isFirstLine)
-				{
-					if (ite->textLayout.lines() == 1)
-						hl = ls.ascent + ls.descent;
-					if (LineStyle.hasDropCap() && (a == ls.firstItem))
-						hl *= LineStyle.dropCapLines();
-					if (LineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-						y1 -= LineStyle.lineSpacing();
-					else if (ite->firstLineOffset() == FLOPRealGlyphHeight || ite->firstLineOffset() == FLOPFontAscent)
-						y1 -= ls.ascent;
-					else
-						y1 -= LineStyle.lineSpacing();
-				}
-				else
-					y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0;
-				QRectF scr;
-				if (ite->itemText.hasObject(a))
-				{
-					PageItem* obj = ite->itemText.object(a);
-					double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH;
-					double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV;
-					scr = QRectF(CurXB, ls.y - hh, ww , hh);
-				}
-				else
-					scr = QRectF(CurXB, y1, glyphs->wide(), hl);
-				if ((oldBack == "") || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade())))
-					scrG |= scr;
-				else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade()))
-				{
-					PS_save();
-					PS_moveto(scrG.x(), -scrG.y());
-					PS_lineto(scrG.x() + scrG.width(), -scrG.y());
-					PS_lineto(scrG.x() + scrG.width(), -scrG.y() - scrG.height());
-					PS_lineto(scrG.x(), -scrG.y() - scrG.height());
-					PS_closepath();
-					SetColor(oldBack, oldShade, &h, &s, &v, &k);
-					PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-					putColor(oldBack, oldShade, true);
-					PS_restore();
-					scrG = scr;
-				}
-				oldBack = charStyle.backColor();
-				oldShade = charStyle.backShade();
-			}
-			else
-			{
-				if (!scrG.isNull())
-				{
-					PS_save();
-					PS_moveto(scrG.x(), -scrG.y());
-					PS_lineto(scrG.x() + scrG.width(), -scrG.y());
-					PS_lineto(scrG.x() + scrG.width(), -scrG.y() - scrG.height());
-					PS_lineto(scrG.x(), -scrG.y() - scrG.height());
-					PS_closepath();
-					putColor(oldBack, oldShade, true);
-					PS_restore();
-				}
-				oldBack = "";
-				oldShade = 100;
-				scrG = QRectF();
-			}
-			CurXB += glyphs->wide();
-		}
-		if (!scrG.isNull())
-		{
-			PS_save();
-			PS_moveto(scrG.x(), -scrG.y());
-			PS_lineto(scrG.x() + scrG.width(), -scrG.y());
-			PS_lineto(scrG.x() + scrG.width(), -scrG.y() - scrG.height());
-			PS_lineto(scrG.x(), -scrG.y() - scrG.height());
-			PS_closepath();
-			putColor(oldBack, oldShade, true);
-			PS_restore();
-		}
-
-		for (int d = ls.firstItem; d <= ls.lastItem; ++d)
-		{
-            //ScText *hl = ite->itemText.item_p(d);
-            QChar chr = ite->itemText.text(d);
-			const CharStyle & cstyle(ite->itemText.charStyle(d));
-			const ParagraphStyle& pstyle(ite->itemText.paragraphStyle(d));
-			const GlyphLayout* glyphs(ite->itemText.getGlyphs(d));
-            LayoutFlags flags = ite->itemText.flags(d);
-            
-//			if ((hl->ch == QChar(13)) || (hl->ch == QChar(10)) || (hl->ch == QChar(28)) || (hl->ch == QChar(27)) || (hl->ch == QChar(26)))
-//				continue;
-			if (flags & ScLayout_SuppressSpace)
-				continue;
-			tTabValues = pstyle.tabValues();
-			if (flags & ScLayout_StartOfLine)
-				tabCc = 0;
-			if ((chr == SpecialChars::TAB) && (tTabValues.count() != 0))
-			{
-				QChar tabFillChar;
-				const TabLayout* tabLayout = dynamic_cast<const TabLayout*>(glyphs->more);
-				if (tabLayout)
-					tabFillChar = tabLayout->fillChar;
-				if (!tabFillChar.isNull())
-				{
-					//ScText hl2;
-					//static_cast<CharStyle&>(hl2) = static_cast<const CharStyle&>(*hl);
-					const GlyphLayout * const gl = glyphs->more;
-					double scale = gl ? gl->scaleV : 1.0;
-					double wt    = cstyle.font().charWidth(tabFillChar, cstyle.fontSize() * scale / 10.0);
-					double len   = glyphs->xadvance;
-					int coun     = static_cast<int>(len / wt);
-					// JG - #6728 : update code according to fillInTabLeaders() and PageItem::layout()
-					double sPos  = 0.0 /*CurX - len + cstyle.fontSize() / 10.0 * 0.7 + 1*/;
-					//hl2.ch = tabFillChar;
-					//hl2.setTracking(0);
-					//hl2.setScaleH(1000);
-					//hl2.setScaleV(1000);
-					//hl2.glyph.glyph   = cstyle.font().char2CMap(tabFillChar);
-					//hl2.glyph.yoffset = glyphs->yoffset;
-                    
-                    GlyphLayout gl2 = *gl;
-                    gl2.glyph   = cstyle.font().char2CMap(tabFillChar);
-                    gl2.yoffset = glyphs->yoffset;
-                    
-                    CharStyle shadow(cstyle);
-                    shadow.setFillColor(cstyle.strokeColor());
-                    
-					for (int cx = 0; cx < coun; ++cx)
-					{
-						gl2.xoffset =  sPos + wt * cx;
-						if ((cstyle.effects() & ScStyle_Shadowed) && (cstyle.strokeColor() != CommonStrings::None))
-						{
-							//ScText hl3;
-							//static_cast<CharStyle&>(hl3) = static_cast<const CharStyle&>(hl2);
-							//hl3.ch = hl2.ch;
-							//hl3.glyph.glyph = hl2.glyph.glyph;
-							//hl3.setFillColor(hl2.strokeColor());
-							//hl3.glyph.yoffset = hl2.glyph.yoffset - (hl2.fontSize() * hl2.shadowYOffset() / 10000.0);
-							//hl3.glyph.xoffset = hl2.glyph.xoffset + (hl2.fontSize() * hl2.shadowXOffset() / 10000.0);
-							GlyphLayout gl3 = gl2;
-                            gl3.yoffset = gl2.yoffset - (cstyle.fontSize() * cstyle.shadowYOffset() / 10000.0);
-							gl3.xoffset = gl2.xoffset + (cstyle.fontSize() * cstyle.shadowXOffset() / 10000.0);
-							setTextCh(Doc, ite, CurX, ls.y, argh, d, tabFillChar, &gl3, shadow, pstyle, pg, sep, farb, master);
-						}
-						setTextCh(Doc, ite, CurX, ls.y, argh, d, tabFillChar, &gl2, cstyle, pstyle, pg, sep, farb, master);
-					}
-				}
-				tabCc++;
-			}
-			if (chr == SpecialChars::TAB) {
-				CurX += glyphs->wide();
-				continue;
-			}
-			if ((cstyle.effects() & ScStyle_Shadowed) && (cstyle.strokeColor() != CommonStrings::None))
-			{
-				const GlyphLayout *gl1 = glyphs;
-				GlyphLayout* gl2 = new GlyphLayout(*gl1);
-				GlyphLayout* gl3 = gl2; 
-				while (gl1->more)
-				{
-					gl2->more = new GlyphLayout(*gl1->more);
-					gl2->more->yoffset -= (cstyle.fontSize() * cstyle.shadowYOffset() / 10000.0);
-					gl2->more->xoffset += (cstyle.fontSize() * cstyle.shadowXOffset() / 10000.0);
-					gl2->more->more = NULL;
-					gl1 = gl1->more;
-					gl2 = gl2->more;
-				}
-				CharStyle shadowed(cstyle);
-				shadowed.setFillColor(cstyle.strokeColor());
-				shadowed.setFillShade(cstyle.strokeShade());
-				gl2->xadvance = glyphs->xadvance;
-				gl2->yadvance = glyphs->yadvance;
-				gl2->yoffset = glyphs->yoffset - (cstyle.fontSize() * cstyle.shadowYOffset() / 10000.0);
-				gl2->xoffset = glyphs->xoffset + (cstyle.fontSize() * cstyle.shadowXOffset() / 10000.0);
-				gl2->scaleH = glyphs->scaleH;
-				gl2->scaleV = glyphs->scaleV;
-				
-				setTextCh(Doc, ite, CurX, ls.y, argh, d, chr, gl2, shadowed, pstyle, pg, sep, farb, master);
-				
-				while (gl3->more) {
-					GlyphLayout* more = gl3->more;
-					gl3->more = gl3->more->more;
-					delete more;
-				}
-				delete gl3;
-			}
-			setTextCh(Doc, ite, CurX, ls.y, argh, d, chr, glyphs, cstyle, pstyle, pg, sep, farb, master);
-			// Unneeded now that glyph xadvance is set appropriately for inline objects by PageItem_TextFrame::layout() - JG
-			/*if (hl->ch == SpecialChars::OBJECT)
-			{
-				InlineFrame& embedded(const_cast<InlineFrame&>(hl->embedded));
-				CurX += (embedded.getItem()->gWidth + embedded.getItem()->lineWidth()) * glyphs->scaleH;
-			}
-			else*/
-			CurX += glyphs->wide();
-			tabDist = CurX;
-		}
-	}
-}
-
-void PSLib::setTextCh(ScribusDoc* Doc, PageItem* ite, double x, double y, uint argh, uint doh, QChar chstr, const GlyphLayout* glyphs, const CharStyle& cstyle, const ParagraphStyle& pstyle, ScPage* pg, bool sep, bool farb, bool master)
-{
-	//QChar chstr = hl->ch;
-	//const CharStyle & cstyle(*hl);
-	//const GlyphLayout* glyphs(&(hl->glyph));
-	uint glyph = glyphs->glyph;
-
-	int h, s, v, k;
-	double tsz;
-	double wideR = 0.0;
-	QVector<double> dum;
-	dum.clear();
-
-	tsz = cstyle.fontSize();
-
-/*	if (cstyle.effects() & ScStyle_DropCap)
-	{
-//		QString chstr; // dummy, FIXME: replace by glyph
-		if (pstyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-			tsz = qRound(10 * ((Doc->typographicSettings.valueBaseGrid *  (pstyle.dropCapLines()-1)+(cstyle.font().ascent(pstyle.charStyle().fontSize() / 10.0))) / (cstyle.font().realCharHeight(chstr, 10))));
-		else
-		{
-			if (pstyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
-				tsz = qRound(10 * ((pstyle.lineSpacing() *  (pstyle.dropCapLines()-1)+(cstyle.font().ascent(pstyle.charStyle().fontSize() / 10.0))) / (cstyle.font().realCharHeight(chstr, 10))));
-			else
-			{
-				double currasce = cstyle.font().height(pstyle.charStyle().fontSize());
-				tsz = qRound(10 * ((currasce * (pstyle.dropCapLines()-1)+(cstyle.font().ascent(pstyle.charStyle().fontSize() / 10.0))) / cstyle.font().realCharHeight(chstr, 10)));
-			}
-		}
-	}
-	*/
-	if (ite->itemText.hasObject(doh-1))
-	{
-		PageItem* embedded = ite->itemText.object(doh-1);
-		PS_save();
-		PS_translate(x + glyphs->xoffset + embedded->gXpos * (cstyle.scaleH() / 1000.0), (y + glyphs->yoffset - (embedded->gHeight * (cstyle.scaleV() / 1000.0)) + embedded->gYpos * (cstyle.scaleV() / 1000.0)) * -1);
-		if (doh == 0 || ite->itemText.text(doh-1) == SpecialChars::PARSEP)
-		{
-			if ((cstyle.baselineOffset() != 0) && (!pstyle.hasDropCap()))
-				PS_translate(0, embedded->gHeight * (cstyle.baselineOffset() / 1000.0));
-		}
-		else
-		{
-			if (cstyle.baselineOffset() != 0)
-				PS_translate(0, embedded->gHeight * (cstyle.baselineOffset() / 1000.0));
-		}
-		if (cstyle.scaleH() != 1000)
-			PS_scale(cstyle.scaleH() / 1000.0, 1);
-		if (cstyle.scaleV() != 1000)
-			PS_scale(1, cstyle.scaleV() / 1000.0);
-		ProcessItem(Doc, pg, embedded, argh, sep, farb, master, true);
-		PS_restore();
-		return;
-	}
-
-	if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode()) ||
-		glyph == (ScFace::CONTROL_GLYPHS + 32)) 
-	{
-		glyph = cstyle.font().char2CMap(QChar(' '));
-		chstr = ' ';
-	}
-	else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode()))
-	{
-		glyph = cstyle.font().char2CMap(QChar('-'));
-		chstr = '-';
-	}
-	
-	if (glyph < ScFace::CONTROL_GLYPHS)
-	{
-		if (((cstyle.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstr)) //FIXME && (chstr != QChar(13)))  
-			|| ((cstyle.effects() & ScStyle_UnderlineWords) && !chstr.isSpace() && !SpecialChars::isBreak(chstr)))
-		{
-	//		double Ulen = cstyle.font().glyphWidth(glyph, cstyle.fontSize()) * glyphs->scaleH;
-			double Ulen = glyphs->xadvance;
-			double Upos, lw;
-			if ((cstyle.underlineOffset() != -1) || (cstyle.underlineWidth() != -1))
-			{
-				if (cstyle.underlineOffset() != -1)
-					Upos = (cstyle.underlineOffset() / 1000.0) * (cstyle.font().descent(cstyle.fontSize() / 10.0));
-				else
-					Upos = cstyle.font().underlinePos(cstyle.fontSize() / 10.0);
-				if (cstyle.underlineWidth() != -1)
-					lw = (cstyle.underlineWidth() / 1000.0) * (cstyle.fontSize() / 10.0);
-				else
-					lw = qMax(cstyle.font().strokeWidth(cstyle.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				Upos = cstyle.font().underlinePos(cstyle.fontSize() / 10.0);
-				lw = qMax(cstyle.font().strokeWidth(cstyle.fontSize() / 10.0), 1.0);
-			}
-			if (cstyle.baselineOffset() != 0)
-				Upos += (cstyle.fontSize() / 10.0) * glyphs->scaleV * (cstyle.baselineOffset() / 1000.0);
-			if (cstyle.fillColor() != CommonStrings::None)
-			{
-				PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
-				PS_setdash(Qt::SolidLine, 0, dum);
-				SetColor(cstyle.fillColor(), cstyle.fillShade(), &h, &s, &v, &k);
-				PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-			}
-			PS_setlinewidth(lw);
-			if (cstyle.effects() & ScStyle_Subscript)
-			{
-				PS_moveto(x + glyphs->xoffset     , -y - glyphs->yoffset+Upos);
-				PS_lineto(x + glyphs->xoffset+Ulen, -y - glyphs->yoffset+Upos);
-			}
-			else
-			{
-				PS_moveto(x + glyphs->xoffset     , -y + Upos);
-				PS_lineto(x + glyphs->xoffset+Ulen, -y + Upos);
-			}
-			putColor(cstyle.fillColor(), cstyle.fillShade(), false);
-		}
-		/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */
-		if (FontSubsetMap.contains(cstyle.font().scName()))
-		{
-			if (glyph != 0 && glyph != cstyle.font().char2CMap(QChar(' ')) && (!SpecialChars::isBreak(chstr)))
-			{
-				PS_save();
-				if (ite->reversed())
-				{
-					PS_translate(x + glyphs->xoffset, (y + glyphs->yoffset - (tsz / 10.0)) * -1);
-					PS_scale(-1, 1);
-					PS_translate(-glyphs->xadvance, 0);
-				}
-				else
-					PS_translate(x + glyphs->xoffset, (y + glyphs->yoffset - (cstyle.fontSize() / 10.0)) * -1);
-				if (cstyle.baselineOffset() != 0)
-					PS_translate(0, (cstyle.fontSize() / 10.0) * (cstyle.baselineOffset() / 1000.0));
-				if (glyphs->scaleH != 1.0)
-					PS_scale(glyphs->scaleH, 1);
-				if (glyphs->scaleV != 1.0)
-				{
-					PS_translate(0, -((tsz / 10.0) - (tsz / 10.0) * (glyphs->scaleV)));
-					PS_scale(1, glyphs->scaleV);
-				}
-				if (cstyle.fillColor() != CommonStrings::None)
-				{
-					putColorNoDraw(cstyle.fillColor(), cstyle.fillShade());
-					PS_showSub(glyph, FontSubsetMap[cstyle.font().scName()], tsz / 10.0, false);
-				}
-				PS_restore();
-			}
-		}
-		else if (glyph != 0)
-		{
-			PS_selectfont(cstyle.font().replacementName(), tsz / 10.0);
-			PS_save();
-			PS_translate(x + glyphs->xoffset, -y - glyphs->yoffset);
-			if (ite->reversed())
-			{
-				PS_scale(-1, 1);
-				PS_translate(glyphs->xadvance, 0);
-			}
-			if (cstyle.baselineOffset() != 0)
-				PS_translate(0, (cstyle.fontSize() / 10.0) * (cstyle.baselineOffset() / 1000.0));
-			if (glyphs->scaleH != 1.0 || glyphs->scaleV != 1.0)
-				PS_scale(glyphs->scaleH, glyphs->scaleV);
-			if (cstyle.fillColor() != CommonStrings::None)
-			{
-				PS_show_xyG(cstyle.font().replacementName(), glyph, 0, 0, cstyle.fillColor(), cstyle.fillShade());
-			}
-			PS_restore();
-		}
-		if ((cstyle.effects() & ScStyle_Outline) || glyph == 0)//&& (chstr != QChar(13)))
-		{
-//		if (cstyle.font().canRender(chstr))
-			{
-				FPointArray gly = cstyle.font().glyphOutline(glyph);
-				QTransform chma, chma2, chma3;
-				chma.scale(tsz / 100.0, tsz / 100.0);
-				chma2.scale(glyphs->scaleH, glyphs->scaleV);
-				if (cstyle.baselineOffset() != 0)
-					chma3.translate(0, -(cstyle.fontSize() / 10.0) * (cstyle.baselineOffset() / 1000.0));
-				gly.map(chma * chma2 * chma3);
-				if (ite->reversed())
-				{
-					chma = QTransform();
-					chma.scale(-1, 1);
-					chma.translate(wideR, 0);
-					gly.map(chma);
-				}
-				if ((cstyle.strokeColor() != CommonStrings::None) && ((tsz * cstyle.outlineWidth() / 10000.0) != 0))
-				{
-					PS_save();
-					PS_setlinewidth(tsz * cstyle.outlineWidth() / 10000.0);
-					PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
-					PS_setdash(Qt::SolidLine, 0, dum);
-					PS_translate(x + glyphs->xoffset, (y + glyphs->yoffset - (tsz / 10.0)) * -1);
-					PS_translate(0, -((tsz / 10.0) - (tsz / 10.0) * glyphs->scaleV));
-					SetColor(cstyle.strokeColor(), cstyle.strokeShade(), &h, &s, &v, &k);
-					PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-					SetClipPath(&gly);
-					PS_closepath();
-					putColor(cstyle.strokeColor(), cstyle.strokeShade(), false);
-					PS_restore();
-				}
-			}
-		}
-		if ((cstyle.effects() & ScStyle_Strikethrough))//&& (chstr != QChar(13)))
-		{
-			//		double Ulen = cstyle.font().glyphWidth(glyph, cstyle.fontSize()) * glyphs->scaleH;
-			double Ulen = glyphs->xadvance;
-			double Upos, lw;
-			if ((cstyle.strikethruOffset() != -1) || (cstyle.strikethruWidth() != -1))
-			{
-				if (cstyle.strikethruOffset() != -1)
-					Upos = (cstyle.strikethruOffset() / 1000.0) * (cstyle.font().ascent(cstyle.fontSize() / 10.0));
-				else
-					Upos = cstyle.font().strikeoutPos(cstyle.fontSize() / 10.0);
-				if (cstyle.strikethruWidth() != -1)
-					lw = (cstyle.strikethruWidth() / 1000.0) * (cstyle.fontSize() / 10.0);
-				else
-					lw = qMax(cstyle.font().strokeWidth(cstyle.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				Upos = cstyle.font().strikeoutPos(cstyle.fontSize() / 10.0);
-				lw = qMax(cstyle.font().strokeWidth(cstyle.fontSize() / 10.0), 1.0);
-			}
-			if (cstyle.baselineOffset() != 0)
-				Upos += (cstyle.fontSize() / 10.0) * glyphs->scaleV * (cstyle.baselineOffset() / 1000.0);
-			if (cstyle.fillColor() != CommonStrings::None)
-			{
-				PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
-				PS_setdash(Qt::SolidLine, 0, dum);
-				SetColor(cstyle.fillColor(), cstyle.fillShade(), &h, &s, &v, &k);
-				PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-			}
-			PS_setlinewidth(lw);
-			PS_moveto(x + glyphs->xoffset     , -y-glyphs->yoffset+Upos);
-			PS_lineto(x + glyphs->xoffset+Ulen, -y-glyphs->yoffset+Upos);
-			putColor(cstyle.fillColor(), cstyle.fillShade(), false);
-		}
-	}
-	if (glyphs->more) {
-		//// ugly hack until setTextCh interface is changed
-		//ScText hl2(*hl);
-		//hl2.glyph = *glyphs->more;
-		setTextCh(Doc, ite, x + glyphs->xadvance, y, argh, doh, chstr, glyphs->more, cstyle, pstyle, pg, sep, farb, master);
-		//// don't let hl2's destructor delete these!
-		//hl2.glyph.more = 0;
-	}
-/*	if (cstyle.effects() & ScStyle_SoftHyphenVisible)
-	{
-		int chs = cstyle.fontSize();
-//		double wide = cstyle.font().charWidth(chstr, chs) * (cstyle.scaleH() / 1000.0);
-//		chstr = '-';
-//		if (cstyle.font().canRender(chstr))
-		{
-			FPointArray gly = cstyle.font().glyphOutline(glyph);
-			QTransform chma;
-			chma.scale(tsz / 100.0, tsz / 100.0);
-			gly.map(chma);
-			chma = QTransform();
-			chma.scale(glyphs->scaleH, glyphs->scaleV);
-			gly.map(chma);
-			if (cstyle.fillColor() != CommonStrings::None)
-			{
-				PS_save();
-				PS_newpath();
-				PS_translate(x + glyphs->xoffset + glyphs->xadvance, (y + glyphs->yoffset - (tsz / 10.0)) * -1);
-				SetColor(cstyle.fillColor(), cstyle.fillShade(), &h, &s, &v, &k);
-				PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
-				SetClipPath(&gly);
-				PS_closepath();
-				putColor(cstyle.fillColor(), cstyle.fillShade(), true);
-				PS_restore();
-			}
-		}
-	}*/
+	PSPainter p(Doc, argh, pg, sep, farb, master, this);
+	ite->textLayout.renderBackground(&p);
+	ite->textLayout.render(&p);
 }
 
 void PSLib::putColor(const QString& colorName, double shade, bool fill)

Modified: trunk/Scribus/scribus/pslib.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/pslib.h
==============================================================================
--- trunk/Scribus/scribus/pslib.h	(original)
+++ trunk/Scribus/scribus/pslib.h	Wed Mar 23 20:21:36 2016
@@ -45,6 +45,7 @@
 class MultiProgressDialog;
 class ScImage;
 class ScLayer;
+class PSPainter;
 
 /**
   *@author Franz Schmid
@@ -54,6 +55,9 @@
 class SCRIBUS_API PSLib : public QObject
 {
 	Q_OBJECT
+
+	friend class PSPainter;
+
 	public:
 
 		typedef enum
@@ -140,7 +144,6 @@
 		virtual void SetColor(const QString& color, double shade, int *h, int *s, int *v, int *k);
 		virtual void SetColor(const ScColor& color, double shade, int *h, int *s, int *v, int *k);
 		virtual void setTextSt(ScribusDoc* Doc, PageItem* ite, uint a, ScPage* pg, bool sep, bool farb, bool master);
-		virtual void setTextCh(ScribusDoc* Doc, PageItem* ite, double x, double y, uint a, uint d, QChar chstr, const GlyphLayout* glyphs, const CharStyle& cstyle, const ParagraphStyle& pstyle, ScPage* pg, bool sep, bool farb, bool master);
 		bool psExport;
 
 	private:

Modified: trunk/Scribus/scribus/scpageoutput.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/scpageoutput.cpp
==============================================================================
--- trunk/Scribus/scribus/scpageoutput.cpp	(original)
+++ trunk/Scribus/scribus/scpageoutput.cpp	Wed Mar 23 20:21:36 2016
@@ -10,7 +10,7 @@
 #include <QPointF>
 #include <QRectF>
 #include <QStack>
-
+#include <pageitem_textframe.h>
 #include "cmsettings.h"
 #include "collapsedtablepainterex.h"
 #include "commonstrings.h"
@@ -31,11 +31,13 @@
 #include "scimage.h"
 #include "scpage.h"
 #include "scpattern.h"
+#include "text/textlayoutpainter.h"
 
 #include "scribusdoc.h"
 #include "util.h"
 #include "util_formats.h"
 #include "util_math.h"
+#include "text/boxes.h"
 
 
 MarksOptions::MarksOptions(void)
@@ -506,167 +508,6 @@
 	painter->restore();
 }
 
-void ScPageOutput::drawGlyphs(PageItem* item, ScPainterExBase *painter, const CharStyle& style, GlyphLayout& glyphs, QRect clip)
-{
-	uint glyph = glyphs.glyph;
-	if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode())) // NBSPACE
-		glyph = style.font().char2CMap(QChar(' '));
-	else if (glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode())) // NBHYPHEN
-		glyph = style.font().char2CMap(QChar('-'));
-	
-	if (glyph >= ScFace::CONTROL_GLYPHS)
-	{
-		if (glyphs.more)
-		{
-			painter->translate(glyphs.xadvance, 0);
-			drawGlyphs(item, painter, style, *glyphs.more, clip);
-		}
-		return;
-	}
-	
-	//if (style.font().canRender(QChar(glyph)))
-	{
-		QTransform chma, chma2, chma3, chma4, chma5, chma6;
-		chma.scale(glyphs.scaleH * style.fontSize() / 100.00, glyphs.scaleV * style.fontSize() / 100.0);
-		FPointArray gly = style.font().glyphOutline(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(' ')))))
-		{
-			double st, lw;
-			if ((style.underlineOffset() != -1) || (style.underlineWidth() != -1))
-			{
-				if (style.underlineOffset() != -1)
-					st = (style.underlineOffset() / 1000.0) * (style.font().descent(style.fontSize() / 10.0));
-				else
-					st = style.font().underlinePos(style.fontSize() / 10.0);
-				if (style.underlineWidth() != -1)
-					lw = (style.underlineWidth() / 1000.0) * (style.fontSize() / 10.0);
-				else
-					lw = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				st = style.font().underlinePos(style.fontSize() / 10.0);
-				lw = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			if (style.baselineOffset() != 0)
-				st += (style.fontSize() / 10.0) * glyphs.scaleV * (style.baselineOffset() / 1000.0);
-			ScColorShade tmpPen = painter->pen();
-			int tmpStrokeMode = painter->strokeMode();
-			painter->setPen(painter->brush());
-			painter->setLineWidth(lw);
-			painter->setStrokeMode(1);
-			if (style.effects() & ScStyle_Subscript)
-				painter->drawLine(FPoint(glyphs.xoffset, glyphs.yoffset - st), FPoint(glyphs.xoffset + glyphs.xadvance, glyphs.yoffset - st));
-			else
-				painter->drawLine(FPoint(glyphs.xoffset, -st), FPoint(glyphs.xoffset + glyphs.xadvance, -st));
-			painter->setStrokeMode(tmpStrokeMode);
-			painter->setPen(tmpPen);
-		}
-		if (gly.size() > 3)
-		{
-			painter->save();
-			painter->translate(glyphs.xoffset, glyphs.yoffset - ((style.fontSize() / 10.0) * glyphs.scaleV));
-			if (item->reversed())
-			{
-				painter->scale(-1, 1);
-				painter->translate(-glyphs.xadvance, 0);
-			}
-			if (style.baselineOffset() != 0)
-				painter->translate(0, -(style.fontSize() / 10.0) * (style.baselineOffset() / 1000.0));
-			double glxSc = glyphs.scaleH * style.fontSize() / 100.00;
-			double glySc = glyphs.scaleV * style.fontSize() / 100.0;
-			painter->scale(glxSc, glySc);
-			painter->setFillMode(ScPainterExBase::Solid);
-			bool fr = painter->fillRule();
-			painter->setFillRule(false);
-			painter->setupPolygon(&gly, true);
-			if (glyph == 0)
-			{
-				ScColorShade tmp(PrefsManager::instance()->appPrefs.displayPrefs.controlCharColor, 100);
-				painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-				painter->setLineWidth(style.fontSize() * glyphs.scaleV * style.outlineWidth() * 2 / 10000.0);
-				painter->strokePath();
-			}
-			else if ((style.font().isStroked()) && ((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) != 0))
-			{
-				ScColorShade tmp = painter->brush();
-				painter->setStrokeMode(1);
-				painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-				painter->setLineWidth(style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0);
-				painter->strokePath();
-			}
-			else
-			{
-				if ((style.effects() & ScStyle_Shadowed) && (style.strokeColor() != CommonStrings::None))
-				{
-					painter->save();
-					painter->translate((style.fontSize() * glyphs.scaleH * style.shadowXOffset() / 10000.0) / glxSc, -(style.fontSize() * glyphs.scaleV * style.shadowYOffset() / 10000.0) / glySc);
-					ScColorShade tmp = painter->brush();
-					painter->setBrush(painter->pen());
-					painter->setupPolygon(&gly, true);
-					fillPath(item, painter, clip);
-					painter->setBrush(tmp);
-					painter->restore();
-					painter->setupPolygon(&gly, true);
-				}
-				if (style.fillColor() != CommonStrings::None)
-					fillPath(item, painter, clip);
-				if ((style.effects() & ScStyle_Outline) && (style.strokeColor() != CommonStrings::None) && ((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) != 0))
-				{
-					painter->setStrokeMode(1);
-					painter->setLineWidth((style.fontSize() * glyphs.scaleV * style.outlineWidth() / 10000.0) / glySc);
-					painter->strokePath();
-				}
-			}
-			painter->setFillRule(fr);
-			painter->restore();
-		}
-		if (style.effects() & ScStyle_Strikethrough)
-		{
-			double st, lw;
-			if ((style.strikethruOffset() != -1) || (style.strikethruWidth() != -1))
-			{
-				if (style.strikethruOffset() != -1)
-					st = (style.strikethruOffset() / 1000.0) * (style.font().ascent(style.fontSize() / 10.0));
-				else
-					st = style.font().strikeoutPos(style.fontSize() / 10.0);
-				if (style.strikethruWidth() != -1)
-					lw = (style.strikethruWidth() / 1000.0) * (style.fontSize() / 10.0);
-				else
-					lw = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			else
-			{
-				st = style.font().strikeoutPos(style.fontSize() / 10.0);
-				lw = qMax(style.font().strokeWidth(style.fontSize() / 10.0), 1.0);
-			}
-			if (style.baselineOffset() != 0)
-				st += (style.fontSize() / 10.0) * glyphs.scaleV * (style.baselineOffset() / 1000.0);
-			int tmpStrokeMode = painter->strokeMode();
-			painter->setPen(painter->brush());
-			painter->setLineWidth(lw);
-			painter->setStrokeMode(1);
-			painter->drawLine(FPoint(glyphs.xoffset, glyphs.yoffset - st), FPoint(glyphs.xoffset + glyphs.xadvance, glyphs.yoffset - st));
-			painter->setStrokeMode(tmpStrokeMode);
-		}
-	}
-	/*else
-	{
-		painter->setLineWidth(1);
-		painter->setPen(ScColorShade(Qt::red, 100));
-		painter->setBrush(ScColorShade(Qt::red, 100));
-		painter->setFillMode(1);
-		painter->drawRect(glyphs.xoffset, glyphs.yoffset - (style.fontSize() / 10.0) * glyphs.scaleV , (style.fontSize() / 10.0) * glyphs.scaleH, (style.fontSize() / 10.0) * glyphs.scaleV);
-	}*/
-	if (glyphs.more)
-	{
-		painter->translate(glyphs.xadvance, 0);
-		drawGlyphs(item, painter, style, *glyphs.more, clip);
-	}
-}
-
 void ScPageOutput::drawItem_Embedded( PageItem* item, ScPainterExBase *p, QRect clip, const CharStyle& style, PageItem* cembedded)
 {
 	if (!cembedded)
@@ -1080,185 +921,185 @@
 	}
 }
 
+class ScpageoutputPainter: public TextLayoutPainter
+{
+private:
+	PageItem* m_item;
+	ScPainterExBase* m_painter;
+	ScPageOutput* m_scpage;
+
+	void setupState()
+	{
+		m_painter->setLineWidth(strokeWidth());
+		ScColorShade fill(m_item->doc()->PageColors[fillColor().color], qRound(fillColor().shade));
+		m_painter->setBrush(fill);
+		ScColorShade stroke(m_item->doc()->PageColors[strokeColor().color], qRound(strokeColor().shade));
+		m_painter->setPen(stroke);
+		if (matrix() != QTransform())
+		{
+			m_painter->setWorldMatrix(matrix() * m_painter->worldMatrix());
+		}
+	}
+
+public:
+	ScpageoutputPainter(PageItem* item, ScPainterExBase* painter, ScPageOutput* scpage)
+		: m_item(item)
+		, m_painter(painter)
+		, m_scpage(scpage)
+	{}
+
+	void translate(double xp, double yp)
+	{
+		TextLayoutPainter::translate(xp, yp);
+		m_painter->translate(xp, yp);
+	}
+
+	void save()
+	{
+		TextLayoutPainter::save();
+		m_painter->save();
+	}
+
+	void restore()
+	{
+		TextLayoutPainter::restore();
+		m_painter->restore();
+	}
+
+	void setScale(double h, double v)
+	{
+		TextLayoutPainter::setScale(h, v);
+		m_painter->scale(h, v);
+	}
+
+	void drawGlyph(const GlyphLayout gl)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		m_painter->save();
+		bool fr = m_painter->fillRule();
+		int fm = m_painter->fillMode();
+
+		m_painter->setFillRule(false);
+		m_painter->setFillMode(1);
+
+		setupState();
+		m_painter->translate(0, -(fontSize() * gl.scaleV));
+		FPointArray outline = font().glyphOutline(gl.glyph);
+		double scaleH = gl.scaleH * fontSize() / 10.0;
+		double scaleV = gl.scaleV * fontSize() / 10.0;
+		m_painter->scale(scaleH, scaleV);
+		m_painter->setupPolygon(&outline, true);
+		if (outline.size() > 3)
+			m_painter->fillPath();
+
+		m_painter->setFillMode(fm);
+		m_painter->setFillRule(fr);
+		m_painter->restore();
+	}
+
+	void drawGlyphOutline(const GlyphLayout gl, bool fill)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		m_painter->save();
+		bool fr = m_painter->fillRule();
+		m_painter->setFillRule(false);
+
+		setupState();
+		m_painter->translate(0, -(fontSize() * gl.scaleV));
+
+		FPointArray outline = font().glyphOutline(gl.glyph);
+		double scaleH = gl.scaleH * fontSize() / 10.0;
+		double scaleV = gl.scaleV * fontSize() / 10.0;
+		m_painter->scale(scaleH, scaleV);
+		m_painter->setupPolygon(&outline, true);
+		if (outline.size() > 3)
+		{
+			m_painter->setLineWidth(strokeWidth());
+			m_painter->strokePath();
+		}
+
+		m_painter->setFillRule(fr);
+		m_painter->restore();
+
+		if (fill)
+			drawGlyph(gl);
+	}
+
+	void drawLine(QPointF start, QPointF end)
+	{
+		m_painter->save();
+		setupState();
+		m_painter->drawLine(start, end);
+		m_painter->restore();
+	}
+
+	void drawRect(QRectF rect)
+	{
+		m_painter->save();
+		setupState();
+		m_painter->setFillMode(1);
+		m_painter->setStrokeMode(1);
+		m_painter->drawRect(rect.x(), rect.y(), rect.width(), rect.height());
+		m_painter->restore();
+	}
+
+	void drawObject(PageItem* embedded)
+	{
+		QRect cullingArea;
+		if (!embedded)
+			return;
+		if (!m_item->m_Doc->DoDrawing)
+			return;
+
+		m_painter->save();
+		double pws = embedded->m_lineWidth;
+
+		embedded->Dirty = m_item->Dirty;
+		embedded->invalid = true;
+		m_scpage->drawItem_Pre(embedded, m_painter);
+
+		switch(embedded->itemType())
+		{
+		case PageItem::ImageFrame:
+		case PageItem::TextFrame:
+		case PageItem::LatexFrame:
+		case PageItem::OSGFrame:
+		case PageItem::Polygon:
+		case PageItem::PathText:
+		case PageItem::Symbol:
+		case PageItem::Group:
+		case PageItem::RegularPolygon:
+		case PageItem::Arc:
+		case PageItem::Table:
+			m_scpage->drawItem(embedded, m_painter, cullingArea);
+			break;
+		case PageItem::Line:
+		case PageItem::PolyLine:
+		case PageItem::Spiral:
+			embedded->m_lineWidth = pws * qMin(scaleH(), scaleV());
+			m_scpage->drawItem(embedded, m_painter, cullingArea);
+			break;
+		default:
+			break;
+		}
+
+		embedded->m_lineWidth = pws * qMin(scaleH(), scaleV());
+		m_scpage->drawItem_Post(embedded, m_painter);
+		embedded->m_lineWidth = pws;
+		m_painter->restore();
+	}
+};
+
+
 void ScPageOutput::drawItem_PathText( PageItem_PathText* item, ScPainterExBase* painter, QRect clip )
 {
-	QString chstr;
-	//ScText *hl;
-	FPoint point = FPoint(0, 0);
-	FPoint tangent = FPoint(0, 0);
-	double CurX = item->textToFrameDistLeft(); // item->CurX = item->textToFrameDistLeft()
-	QString actFill, actStroke;
-	double actFillShade, actStrokeShade, dx;
-	StoryText& itemText = item->itemText;
-	if (item->pathTextShowFrame())
-	{
-		painter->setupPolygon(&item->PoLine, false);
-		if (item->NamedLStyle.isEmpty())
-		{
-			if (item->lineColor() != CommonStrings::None)
-				painter->strokePath();
-		}
-		else
-		{
-			multiLine ml = m_doc->MLineStyles[item->NamedLStyle];
-			for (int it = ml.size() - 1; it > -1; it--)
-			{
-				const SingleLine& sl = ml[it];
-				if ((sl.Color != CommonStrings::None) && (sl.Width != 0))
-				{
-					ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
-					painter->setPen(tmp, sl.Width,  static_cast<Qt::PenStyle>(sl.Dash), 
-							 static_cast<Qt::PenCapStyle>(sl.LineEnd), 
-							 static_cast<Qt::PenJoinStyle>(sl.LineJoin));
-					painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
-				}
-			}
-		}
-	}
-	double totalTextLen = 0.0;
-	double totalCurveLen = 0.0;
-	double extraOffset = 0.0;
-	if (itemText.length() != 0)
-	{
-        CurX += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
-		totalTextLen += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
-	}
-	for (int a = 0; a < itemText.length(); ++a)
-	{
-        GlyphLayout* glyphs = itemText.getGlyphs(a);
-        chstr =itemText.text(a,1);
-		if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
-			|| chstr[0] == SpecialChars::TAB || chstr == SpecialChars::LINEBREAK)
-			continue;
-		if (a < itemText.length()-1)
-			chstr += itemText.text(a+1, 1);
-        glyphs->yadvance = 0;
-        item->layoutGlyphs(itemText.charStyle(a), chstr, itemText.flags(a), *glyphs);
-        glyphs->shrink();
-        if (item->itemText.hasObject(a))
-            totalTextLen += (item->itemText.object(a)->width() + item->itemText.object(a)->lineWidth()) * glyphs->scaleH;
-		else
-            totalTextLen += glyphs->wide()+itemText.charStyle(a).fontSize() * itemText.charStyle(a).tracking() / 10000.0;
-	}
-	for (int segs = 0; segs < item->PoLine.size()-3; segs += 4)
-	{
-		totalCurveLen += item->PoLine.lenPathSeg(segs);
-	}
-	if ((itemText.defaultStyle().alignment() != 0) && (totalCurveLen >= totalTextLen + item->textToFrameDistLeft()))
-	{
-		if (itemText.defaultStyle().alignment() == 2)
-		{
-			CurX = totalCurveLen  - totalTextLen;
-			CurX -= item->textToFrameDistLeft();
-		}
-		if (itemText.defaultStyle().alignment() == 1)
-			CurX = (totalCurveLen - totalTextLen) / 2.0;
-		if ((itemText.defaultStyle().alignment() == 3) || (itemText.defaultStyle().alignment() == 4))
-			extraOffset = (totalCurveLen - item->textToFrameDistLeft()  - totalTextLen) / static_cast<double>(itemText.length());
-	}
-
-	QPainterPath guidePath = item->PoLine.toQPainterPath(false);
-	QList<QPainterPath> pathList = decomposePath(guidePath);
-	QPainterPath currPath = pathList[0];
-	int currPathIndex = 0;
-	for (int a = item->firstInFrame(); a < itemText.length(); ++a)
-	{
-        GlyphLayout* glyphs = itemText.getGlyphs(a);
-        PathData* pdata = &(item->textLayout.point(a));
-        
-        chstr = itemText.text(a,1);
-		if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
-			|| chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK)
-			continue;
-		if (a < itemText.length()-1)
-			chstr += itemText.text(a+1, 1);
-        glyphs->yadvance = 0;
-        item->layoutGlyphs(itemText.charStyle(a), chstr, itemText.flags(a), *glyphs);
-        glyphs->shrink();                                                           // HACK
-		// Unneeded now that glyph xadvance is set appropriately for inline objects by PageItem_TextFrame::layout() - JG
-		/*if (hl->hasObject())
-			dx = (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) * hl->glyph.scaleH / 2.0;
-		else*/
-        dx = glyphs->wide() / 2.0;
-
-		CurX += dx;
-
-		double currPerc = currPath.percentAtLength(CurX);
-		if (currPerc >= 0.9999999)
-		{
-			currPathIndex++;
-			if (currPathIndex == pathList.count())
-				break;
-			currPath = pathList[currPathIndex];
-			CurX = dx;
-			currPerc = currPath.percentAtLength(CurX);
-		}
-		double currAngle = currPath.angleAtPercent(currPerc);
-		if (currAngle <= 180.0)
-			currAngle *= -1.0;
-		else
-			currAngle = 360.0 - currAngle;
-		QPointF currPoint = currPath.pointAtPercent(currPerc);
-		tangent = FPoint(cos(currAngle * M_PI / 180.0), sin(currAngle * M_PI / 180.0));
-		point = FPoint(currPoint.x(), currPoint.y());
-
-        //hl = itemText.item_p(a);
-        glyphs->xoffset = 0;
-		pdata->PtransX = point.x();
-		pdata->PtransY = point.y();
-		pdata->PRot    = currAngle * M_PI / 180.0;
-		pdata->PDx     = dx;
-		QTransform trafo = QTransform( 1, 0, 0, -1, -dx, 0 );
-		if (item->textPathFlipped)
-			trafo *= QTransform(1, 0, 0, -1, 0, 0);
-		if (item->textPathType == 0)
-			trafo *= QTransform( tangent.x(), tangent.y(), tangent.y(), -tangent.x(), point.x(), point.y() ); // ID's Rainbow mode
-		else if (item->textPathType == 1)
-			trafo *= QTransform( 1, 0, 0, -1, point.x(), point.y() ); // ID's Stair Step mode
-		else if (item->textPathType == 2)
-		{
-			double a = 1;
-			if (tangent.x() < 0)
-				a = -1;
-			if (fabs(tangent.x()) > 0.1)
-				trafo *= QTransform( a, (tangent.y() / tangent.x()) * a, 0, -1, point.x(), point.y() ); // ID's Skew mode
-			else
-				trafo *= QTransform( a, 4 * a, 0, -1, point.x(), point.y() );
-		}
-		QTransform sca = painter->worldMatrix();
-		trafo *= sca;
-		painter->save();
-		QTransform savWM = painter->worldMatrix();
-		painter->setWorldMatrix(trafo);
-
-		actFill = itemText.charStyle(a).fillColor();
-		actFillShade = itemText.charStyle(a).fillShade();
-		if (actFill != CommonStrings::None)
-		{
-			ScColorShade tmp(m_doc->PageColors[actFill], qRound(actFillShade));
-			painter->setBrush(tmp);
-		}
-		actStroke = itemText.charStyle(a).strokeColor();
-		actStrokeShade = itemText.charStyle(a).strokeShade();
-		if (actStroke != CommonStrings::None)
-		{
-			ScColorShade tmp(m_doc->PageColors[actStroke], qRound(actStrokeShade));
-			painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-		}
-		painter->translate(0.0, item->pathTextBaseOffset());
-        if (itemText.hasObject(a))
-            drawItem_Embedded(itemText.object(a), painter, clip, itemText.charStyle(a), itemText.object(a));
-		else
-            drawGlyphs(item, painter, itemText.charStyle(a), *glyphs, clip);
-
-		painter->setWorldMatrix(savWM);
-		painter->restore();
-		CurX -= dx;
-        if (itemText.hasObject(a))
-            CurX += (itemText.object(a)->width() + itemText.object(a)->lineWidth()) * glyphs->scaleH;
-		else
-            CurX += glyphs->wide()+itemText.charStyle(a).fontSize() * itemText.charStyle(a).tracking() / 10000.0 + extraOffset;
-	}
+	ScpageoutputPainter p(item, painter, this);
+	item->textLayout.renderBackground(&p);
+	item->textLayout.render(&p);
 }
 
 void ScPageOutput::drawItem_Polygon ( PageItem_Polygon* item , ScPainterExBase* painter, QRect clip )
@@ -1610,251 +1451,9 @@
 
 void ScPageOutput::drawItem_TextFrame( PageItem_TextFrame* item, ScPainterExBase* painter, QRect cullingArea )
 {
-	QTransform wm;
-	QPoint pt1, pt2;
-	FPoint ColBound;
-	QRegion cm;
-	int a;
-	double desc, asce;
-	
-	painter->save();
-	if (!item->isEmbedded)
-		wm.translate(item->xPos(), item->yPos());
-	wm.rotate(item->rotation());
-
-	if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
-	{
-		painter->setupPolygon(&item->PoLine);
-		fillPath(item, painter, cullingArea);
-	}
-	if ((item->isAnnotation()) && (item->annotation().Type() == Annotation::Button) && (!item->Pfile.isEmpty()) && (item->imageIsAvailable) && (item->imageVisible()) && (item->annotation().UseIcons()))
-	{
-		painter->save();
-		painter->setupPolygon(&item->PoLine);
-		painter->setClipPath();
-		painter->scale(item->imageXScale(), item->imageYScale());
-		painter->translate(static_cast<int>(item->imageXOffset() * item->imageXScale()), static_cast<int>(item->imageYOffset()  * item->imageYScale()));
-		if (!item->pixm.qImage().isNull())
-			painter->drawImage(&item->pixm, ScPainterExBase::rgbImages);
-		painter->restore();
-	}
-	if ((item->itemText.length() != 0))
-	{
-		if (item->imageFlippedH())
-		{
-			painter->translate(item->width(), 0);
-			painter->scale(-1, 1);
-			wm.translate(item->width(), 0);
-			wm.scale(-1, 1);
-		}
-		if (item->imageFlippedV())
-		{
-			painter->translate(0, item->height());
-			painter->scale(1, -1);
-			wm.translate(0, item->height());
-			wm.scale(1, -1);
-		}
-
-		uint llp = 0;
-		LineSpec ls;
-		while (llp < item->textLayout.lines())
-		{
-			ls = item->textLayout.line(llp++);
-			const ParagraphStyle& LineStyle = item->itemText.paragraphStyle(ls.firstItem);
-			if (LineStyle.backgroundColor() != CommonStrings::None)
-			{
-				ScColorShade colorShade;
-				colorShade.color = m_doc->PageColors[LineStyle.backgroundColor()];
-				colorShade.shade = LineStyle.backgroundShade();
-				double y0 = ls.y;
-				double y2 = ls.y;
-				double ascent = ls.ascent;
-				double descent = ls.descent;
-				double rMarg = LineStyle.rightMargin();
-				double lMarg = ls.colLeft;
-				double adjX = 0;
-				if (LineStyle.firstIndent() <= 0)
-					adjX += LineStyle.leftMargin() + LineStyle.firstIndent();
-				while (llp < item->textLayout.lines())
-				{
-					ls = item->textLayout.line(llp);
-					if ((ls.colLeft > lMarg) || (item->itemText.paragraphStyle(ls.firstItem) != LineStyle))
-					{
-						if (y2 == 0)
-							y2 = y0;
-						break;
-					}
-					if (item->itemText.text(ls.lastItem) == SpecialChars::PARSEP)
-					{
-						y2 = ls.y;
-						descent = ls.descent;
-						if ((llp + 1) < item->textLayout.lines())
-						{
-							if ((item->textLayout.line(llp + 1).lastItem - item->textLayout.line(llp + 1).firstItem) > 0)
-								descent += LineStyle.lineSpacing() - (ls.descent + item->textLayout.line(llp + 1).ascent);
-						}
-						llp++;
-						break;
-					}
-					y2 = ls.y;
-					descent = ls.descent;
-					if ((llp + 1) < item->textLayout.lines())
-						descent += LineStyle.lineSpacing() - (ls.descent + item->textLayout.line(llp + 1).ascent);
-					llp++;
-				}
-				painter->save();
-				painter->setupPolygon(&item->PoLine);
-				painter->setClipPath();
-				painter->setFillMode(1);
-				painter->setStrokeMode(0);
-				painter->setBrush(colorShade);
-				painter->drawRect(lMarg + adjX, y0 - ascent, item->columnWidth() - adjX - rMarg, y2 - y0 + descent + ascent);
-				painter->restore();
-			}
-		}
-
-		for (uint ll=0; ll < item->textLayout.lines(); ++ll)
-		{
-			const LineSpec& ls = item->textLayout.line(ll);
-			double CurX = ls.x;
-
-			// Draw text background
-			ScColorShade tmpShade;
-			double curXB = ls.x;
-			QRectF scrG;
-			QString oldBack;
-			double oldShade = 100;
-			for (a = ls.firstItem; a <= ls.lastItem; ++a)
-			{
-				GlyphLayout* glyphs = item->itemText.getGlyphs(a);
-				const CharStyle& charStyle(item->itemText.charStyle(a));
-				if (charStyle.backColor() != CommonStrings::None)
-				{
-					tmpShade.color = m_doc->PageColors[charStyle.backColor()];
-					tmpShade.shade = charStyle.backShade();
-					const ParagraphStyle& lineStyle = item->itemText.paragraphStyle(ls.firstItem);
-					double y1 = ls.y;
-					double hl = ls.height;
-					if (lineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-						hl = m_doc->guidesPrefs().valueBaselineGrid;
-					else if (lineStyle.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
-						hl = lineStyle.lineSpacing();
-					if (ls.isFirstLine)
-					{
-						if (item->textLayout.lines() == 1)
-							hl = ls.ascent + ls.descent;
-						if (lineStyle.hasDropCap() && (a == ls.firstItem))
-							hl *= lineStyle.dropCapLines();
-						if (lineStyle.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
-							y1 -= lineStyle.lineSpacing();
-						else if (item->firstLineOffset() == FLOPRealGlyphHeight || item->firstLineOffset() == FLOPFontAscent)
-							y1 -= ls.ascent;
-						else
-							y1 -= lineStyle.lineSpacing();
-					}
-					else
-						y1 -= ls.ascent + (hl - (ls.ascent + ls.descent)) / 2.0;
-					QRectF scr;
-					if (item->itemText.hasObject(a))
-					{
-						PageItem* obj = item->itemText.object(a);
-						double ww = (obj->width() + obj->lineWidth()) * glyphs->scaleH;
-						double hh = (obj->height() + obj->lineWidth()) * glyphs->scaleV;
-						scr = QRectF(curXB, ls.y - hh, ww , hh);
-					}
-					else
-						scr = QRectF(curXB, y1, glyphs->wide(), hl);
-					if ((oldBack.isEmpty()) || ((oldBack == charStyle.backColor()) && (oldShade == charStyle.backShade())))
-						scrG |= scr;
-					else if ((oldBack != charStyle.backColor()) || (oldShade != charStyle.backShade()))
-					{
-						tmpShade.color = m_doc->PageColors[oldBack];
-						tmpShade.shade = oldShade;
-						painter->save();
-						painter->setFillMode(1);
-						painter->setStrokeMode(0);
-						painter->setBrush(tmpShade);
-						painter->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height());
-						painter->restore();
-						scrG = scr;
-					}
-					oldBack = charStyle.backColor();
-					oldShade = charStyle.backShade();
-				}
-				else
-				{
-					oldBack.clear();
-					oldShade = 100;
-					if (!scrG.isNull())
-					{
-						painter->save();
-						painter->setFillMode(1);
-						painter->setStrokeMode(0);
-						painter->setBrush(tmpShade);
-						painter->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height());
-						painter->restore();
-					}
-					scrG = QRectF();
-				}
-				curXB += glyphs->wide();
-			}
-			if (!scrG.isNull())
-			{
-				painter->save();
-				painter->setFillMode(1);
-				painter->setStrokeMode(0);
-				painter->setBrush(tmpShade);
-				painter->drawRect(scrG.x(), scrG.y(), scrG.width(), scrG.height());
-				painter->restore();
-			}
-
-			// Draw text
-			for (a = ls.firstItem; a <= ls.lastItem; ++a)
-			{
-				GlyphLayout* glyphs = item->itemText.getGlyphs(a);
-				const CharStyle& charStyle  = item->itemText.charStyle(a);
-
-				if (charStyle.fillColor() != CommonStrings::None)
-				{
-					ScColorShade tmp(m_doc->PageColors[charStyle.fillColor()], (int) charStyle.fillShade());
-					painter->setBrush(tmp);
-				}
-				if (charStyle.strokeColor() != CommonStrings::None)
-				{
-					ScColorShade tmp(m_doc->PageColors[charStyle.strokeColor()], (int) charStyle.strokeShade());
-					painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-				}
-
-				//if (!m_doc->RePos)
-				{
-					//double xcoZli = CurX + glyphs->xoffset;
-					desc = - charStyle.font().descent(charStyle.fontSize() / 10.0);
-					asce = charStyle.font().ascent(charStyle.fontSize() / 10.0);
-					if (charStyle.strokeColor() != CommonStrings::None)
-					{
-						ScColorShade tmp(m_doc->PageColors[charStyle.strokeColor()], (int) charStyle.strokeShade());
-						painter->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
-					}
-					if (item->isEmbedded || cullingArea.intersects(wm.mapRect(QRect(qRound(CurX + glyphs->xoffset),qRound(ls.y + glyphs->yoffset-asce), qRound(glyphs->xadvance+1), qRound(asce+desc)))))
-					{
-						painter->save();
-						painter->translate(CurX, ls.y);
-						if (item->itemText.hasObject(a))
-							drawItem_Embedded(item, painter, cullingArea, charStyle, item->itemText.object(a));
-						else
-							drawGlyphs(item, painter, charStyle, *glyphs, cullingArea);
-						painter->restore();
-					}
-					// Unneeded now that glyph xadvance is set appropriately for inline objects by PageItem_TextFrame::layout() - JG
-					/*if (hl->hasObject())
-						CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth());
-					else*/
-					CurX += glyphs->wide();
-				}
-			}
-		}
-	}
-	painter->restore();
+	ScpageoutputPainter p(item, painter, this);
+	item->textLayout.renderBackground(&p);
+	item->textLayout.render(&p);
 }
 
 void ScPageOutput::drawArrow(ScPainterExBase* painter, PageItem* item, QTransform &arrowTrans, int arrowIndex)

Modified: trunk/Scribus/scribus/scpageoutput.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/scpageoutput.h
==============================================================================
--- trunk/Scribus/scribus/scpageoutput.h	(original)
+++ trunk/Scribus/scribus/scpageoutput.h	Wed Mar 23 20:21:36 2016
@@ -53,6 +53,8 @@
 
 class SCRIBUS_API ScPageOutput
 {
+	friend class ScpageoutputPainter;
+
 public:
 	ScPageOutput(ScribusDoc* doc, bool reloadImages = false, int resolution = 72, bool useProfiles = false);
 	virtual ~ScPageOutput() { }
@@ -82,7 +84,6 @@
 	virtual void drawItem_Pre( PageItem* item, ScPainterExBase* painter );
 	virtual void drawItem_Post( PageItem* item, ScPainterExBase* painter );
 
-	virtual void drawGlyphs(PageItem* item, ScPainterExBase *painter, const CharStyle& style, GlyphLayout& glyphs, QRect clip);
 	virtual void drawItem_Embedded( PageItem* item, ScPainterExBase *p, QRect clip, const CharStyle& style, PageItem* cembedded);
 	virtual void drawPattern(PageItem* item, ScPainterExBase* painter, QRect clip);
 	virtual void drawStrokePattern(PageItem* item, ScPainterExBase* painter, const QPainterPath& path);

Modified: trunk/Scribus/scribus/scpainter.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/scpainter.cpp
==============================================================================
--- trunk/Scribus/scribus/scpainter.cpp	(original)
+++ trunk/Scribus/scribus/scpainter.cpp	Wed Mar 23 20:21:36 2016
@@ -181,6 +181,11 @@
 		m_image->fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) );
 }
 
+cairo_t *ScPainter::context()
+{
+	return m_cr;
+}
+
 const QTransform ScPainter::worldMatrix()
 {
 	cairo_matrix_t matrix;
@@ -424,6 +429,11 @@
 	return m_fill;
 }
 
+double ScPainter::brushOpacity()
+{
+	return m_fill_trans;
+}
+
 void ScPainter::setPen( const QColor &c )
 {
 	m_stroke = c;
@@ -493,6 +503,11 @@
 	cairo_restore( m_cr );
 	if (!m_zoomStack.isEmpty())
 		m_zoomFactor = m_zoomStack.pop();
+}
+
+int ScPainter::blendModeFill()
+{
+	return m_blendModeFill;
 }
 
 void ScPainter::setRasterOp(int blendMode)
@@ -1932,6 +1947,7 @@
 
 void ScPainter::drawText(QRectF area, QString text, bool filled, int align)
 {
+	// FIXME HOST: This uses Cairo "Toy text API" which does not support complex text layout.
 	cairo_text_extents_t extents;
 	cairo_font_extents_t extentsF;
 	double x;

Modified: trunk/Scribus/scribus/scpainter.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/scpainter.h
==============================================================================
--- trunk/Scribus/scribus/scpainter.h	(original)
+++ trunk/Scribus/scribus/scpainter.h	Wed Mar 23 20:21:36 2016
@@ -19,6 +19,7 @@
 #include <QPointF>
 #include "scribusapi.h"
 #include "scconfig.h"
+#include "sctextstruct.h"
 #include "fpoint.h"
 #include "fpointarray.h"
 #include "vgradient.h"
@@ -43,6 +44,7 @@
 	virtual void end();
 	void clear();
 	virtual void clear( const QColor & );
+	virtual cairo_t* context();
 
 	// matrix manipulation
 	virtual void setWorldMatrix( const QTransform & );
@@ -66,6 +68,7 @@
 	virtual bool fillRule() { return m_fillRule; }
 	virtual void setFillMode( int fill );
 	virtual int  fillMode() { return m_fillMode; }
+	virtual int  maskMode() { return m_maskMode; }
 	virtual void setStrokeMode( int stroke );
 	virtual int  strokeMode() { return m_strokeMode; }
 	virtual void setGradient( VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc, double scale, double skew);
@@ -109,6 +112,7 @@
 	// pen + brush
 	virtual QColor pen();
 	virtual QColor brush();
+	virtual double brushOpacity();
 	virtual void setPen( const QColor & );
 	virtual void setPen( const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo );
 	virtual void setPenOpacity( double op );
@@ -123,6 +127,7 @@
 	// stack management
 	virtual void save();
 	virtual void restore();
+	virtual int blendModeFill();
 
 
 	virtual void setRasterOp( int blendMode );

Modified: trunk/Scribus/scribus/scribusdoc.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/scribusdoc.cpp
==============================================================================
--- trunk/Scribus/scribus/scribusdoc.cpp	(original)
+++ trunk/Scribus/scribus/scribusdoc.cpp	Wed Mar 23 20:21:36 2016
@@ -42,6 +42,7 @@
 
 #include "actionmanager.h"
 #include "appmodes.h"
+#include "text/boxes.h"
 #include "canvas.h"
 #include "colorblind.h"
 #include "commonstrings.h"
@@ -95,6 +96,7 @@
 #include "selection.h"
 #include "serializer.h"
 #include "tableborder.h"
+#include "text/textlayoutpainter.h"
 #include "ui/hruler.h"
 #include "ui/layers.h"
 #include "ui/mark2item.h"
@@ -4497,181 +4499,45 @@
 	}
 }
 
+// a special painter that does not actually paint anything,
+// but collects the glyphs used in the frame.
+class UsedGlyphsPainter: public TextLayoutPainter
+{
+public:
+	UsedGlyphsPainter(QMap<QString, QMap<uint, FPointArray> > & Really)
+		: m_really(Really)
+	{}
+
+	void drawGlyph(const GlyphLayout gl)
+	{
+		if (gl.glyph >= ScFace::CONTROL_GLYPHS)
+			return;
+
+		if (!font().replacementName().isEmpty())
+		{
+			FPointArray outline(font().glyphOutline(gl.glyph));
+			m_really[font().replacementName()].insert(gl.glyph, outline);
+		}
+	}
+
+	void drawGlyphOutline(const GlyphLayout gl, bool) { drawGlyph(gl); }
+
+	// we don't need this one
+	void drawLine(QPointF, QPointF) {}
+	void drawRect(QRectF) {}
+	void drawObject(PageItem*) {}
+
+private:
+	QMap<QString, QMap<uint, FPointArray> > & m_really;
+};
 
 void ScribusDoc::checkItemForFonts(PageItem *it, QMap<QString, QMap<uint, FPointArray> > & Really, uint lc)
 {
 	if (!it->isTextFrame() && !it->isPathText())
 		return;
 
-	FPointArray gly;
-	QChar chstr;
-
-	int start = it->isTextFrame() ? it->firstInFrame() : 0;
-	int stop  = it->isTextFrame() ? it->lastInFrame() + 1 : it->itemText.length();
-	for (int e = start; e < stop; ++e)
-	{
-		const ScFace* font = &it->itemText.charStyle(e).font();
-		if (it->itemText.hasMark(e))
-		{
-			QString mrkStr = it->itemText.mark(e)->getString();
-			for (int i=0;i<mrkStr.length(); ++i)
-			{
-				if (font->canRender(mrkStr[i].unicode()))
-				{
-					uint gl = font->char2CMap(mrkStr[i]);
-					FPointArray gly(font->glyphOutline(gl));
-					if (!font->replacementName().isEmpty())
-						Really[font->replacementName()].insert(gl, gly);
-				}
-			}
-		}
-		if (! Really.contains(font->replacementName()) )
-		{
-			if (!font->replacementName().isEmpty())
-				Really.insert(font->replacementName(), QMap<uint, FPointArray>());
-		}
-		uint chr = it->itemText.text(e).unicode();
-		if ((chr == 13) || (chr == 32) || ((chr >= 26) && (chr <= 29)))
-			continue;
-		if (chr == 9)
-		{
-			for (int t1 = 0; t1 < it->itemText.paragraphStyle(e).tabValues().count(); t1++)
-			{
-				if (it->itemText.paragraphStyle(e).tabValues()[t1].tabFillChar.isNull())
-					continue;
-				chstr = it->itemText.paragraphStyle(e).tabValues()[t1].tabFillChar;
-				if ((it->itemText.charStyle(e).effects() & ScStyle_SmallCaps) || (it->itemText.charStyle(e).effects() & ScStyle_AllCaps))
-				{
-					if (chstr.toUpper() != chstr)
-						chstr = chstr.toUpper();
-				}
-				chr = chstr.unicode();
-				uint gl = font->char2CMap(chstr);
-				gly = font->glyphOutline(gl);
-				if (!font->replacementName().isEmpty())
-					Really[font->replacementName()].insert(gl, gly);
-			}
-			for (int t1 = 0; t1 < it->itemText.defaultStyle().tabValues().count(); t1++)
-			{
-				if (it->itemText.defaultStyle().tabValues()[t1].tabFillChar.isNull())
-					continue;
-				chstr = it->itemText.defaultStyle().tabValues()[t1].tabFillChar;
-				if ((it->itemText.charStyle(e).effects() & ScStyle_SmallCaps) || (it->itemText.charStyle(e).effects() & ScStyle_AllCaps))
-				{
-					if (chstr.toUpper() != chstr)
-						chstr = chstr.toUpper();
-				}
-				chr = chstr.unicode();
-				uint gl = font->char2CMap(chstr);
-				gly = font->glyphOutline(gl);
-				if (!font->replacementName().isEmpty())
-					Really[font->replacementName()].insert(gl, gly);
-			}
-			continue;
-		}
-		if ((chr == 30) || (chr == 23))
-		{
-			//Our page number collection string
-			QString pageNumberText(QString::null);
-			if (chr == 30)
-			{//ch == SpecialChars::PAGENUMBER
-				if (e > 0 && it->itemText.text(e-1) == SpecialChars::PAGENUMBER)
-					pageNumberText=SpecialChars::ZWNBSPACE;
-				else if (lc!=0) //If not on a master page just get the page number for the page and the text
-				{
-					pageNumberText = QString("%1").arg(getSectionPageNumberForPageIndex(it->OwnPage),
-									getSectionPageNumberWidthForPageIndex(it->OwnPage),
-									getSectionPageNumberFillCharForPageIndex(it->OwnPage));
-				}
-				else
-				{
-					//Else, for a page number in a text frame on a master page we must scan
-					//all pages to see which ones use this page and get their page numbers.
-					//We only add each character of the pages' page number text if its nothing
-					//already in the pageNumberText variable. No need to add glyphs twice.
-					QString newText;
-					uint docPageCount=DocPages.count();
-					for (uint a = 0; a < docPageCount; ++a)
-					{
-						if (DocPages.at(a)->MPageNam == it->OnMasterPage)
-						{
-							newText = QString("%1").arg(getSectionPageNumberForPageIndex(a),
-											getSectionPageNumberWidthForPageIndex(a),
-											getSectionPageNumberFillCharForPageIndex(a));
-							for (int nti=0;nti<newText.length();++nti)
-								if (pageNumberText.indexOf(newText[nti])==-1)
-									pageNumberText+=newText[nti];
-						}
-					}
-				}
-			}
-			else
-			{//ch == SpecialChars::PAGECOUNT
-				if (lc!=0)
-				{
-					int key = getSectionKeyForPageIndex(it->OwnPage);
-					if (key == -1)
-						pageNumberText = "";
-					else
-						pageNumberText = QString("%1").arg(getStringFromSequence(m_docPrefsData.docSectionMap[key].type, m_docPrefsData.docSectionMap[key].toindex - m_docPrefsData.docSectionMap[key].fromindex + 1));
-				}
-				else
-				{
-					QString newText;
-					uint docPageCount=DocPages.count();
-					for (uint a = 0; a < docPageCount; ++a)
-					{
-						if (DocPages.at(a)->MPageNam == it->OnMasterPage)
-						{
-							int key = getSectionKeyForPageIndex(a);
-							if (key == -1)
-								newText = "";
-							else
-								newText = QString("%1").arg(getStringFromSequence(m_docPrefsData.docSectionMap[key].type, m_docPrefsData.docSectionMap[key].toindex - m_docPrefsData.docSectionMap[key].fromindex + 1));
-							for (int nti=0;nti<newText.length();++nti)
-								if (pageNumberText.indexOf(newText[nti])==-1)
-									pageNumberText+=newText[nti];
-						}
-					}
-				}
-			}
-			//Now scan and add any glyphs used in page numbers
-			for (int pnti=0;pnti<pageNumberText.length(); ++pnti)
-			{
-				uint chr = pageNumberText[pnti].unicode();
-				if (font->canRender(chr))
-				{
-					uint gl = font->char2CMap(pageNumberText[pnti]);
-					FPointArray gly(font->glyphOutline(gl));
-					if (!font->replacementName().isEmpty())
-						Really[font->replacementName()].insert(gl, gly);
-				}
-			}
-			continue;
-		}
-
-		if (it->itemText.hasFlag(e, ScLayout_SoftHyphenVisible))
-		{
-			uint gl = it->itemText.charStyle(e).font().char2CMap(QChar('-'));
-			FPointArray gly(it->itemText.charStyle(e).font().glyphOutline(gl));
-			if (!it->itemText.charStyle(e).font().replacementName().isEmpty())
-				Really[it->itemText.charStyle(e).font().replacementName()].insert(gl, gly);
-		}
-		if ((it->itemText.charStyle(e).effects() & ScStyle_SmallCaps) || (it->itemText.charStyle(e).effects() & ScStyle_AllCaps))
-		{
-			chstr = it->itemText.text(e);
-			if (chstr.toUpper() != chstr)
-				chstr = chstr.toUpper();
-			chr = chstr.unicode();
-		}
-		if (it->itemText.charStyle(e).font().canRender(chr))
-		{
-			uint gl = it->itemText.charStyle(e).font().char2CMap(chr);
-			gly = it->itemText.charStyle(e).font().glyphOutline(gl);
-			if (!it->itemText.charStyle(e).font().replacementName().isEmpty())
-				Really[it->itemText.charStyle(e).font().replacementName()].insert(gl, gly);
-		}
-	}
+	UsedGlyphsPainter p(Really);
+	it->textLayout.render(&p);
 }
 
 

Modified: trunk/Scribus/scribus/scribusview.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/scribusview.cpp
==============================================================================
--- trunk/Scribus/scribus/scribusview.cpp	(original)
+++ trunk/Scribus/scribus/scribusview.cpp	Wed Mar 23 20:21:36 2016
@@ -80,6 +80,7 @@
 #include "hyphenator.h"
 #include "iconmanager.h"
 #include "loadsaveplugin.h"
+#include "text/textlayoutpainter.h"
 #include "pageitem.h"
 #include "pageitem_group.h"
 #include "pageitem_imageframe.h"
@@ -1651,8 +1652,14 @@
 			point.setX(textFrame->width() - point.x());
 		if (textFrame->imageFlippedV())
 			point.setY(textFrame->height() - point.y());
-		textFrame->itemText.setCursorPosition(textFrame->itemText.length() == 0 ? 0 :
-			textFrame->textLayout.screenToPosition(point));
+		if (textFrame->itemText.length() == 0)
+			textFrame->itemText.setCursorPosition(0);
+		else
+		{
+			int result = textFrame->textLayout.pointToPosition(point.toQPointF());
+			if (result >= 0)
+				textFrame->itemText.setCursorPosition(result);
+		}
 
 		if (textFrame->itemText.length() > 0)
 		{
@@ -2998,6 +3005,91 @@
 	}
 }
 
+// FIXME: the following code is untested, but it should give an idea for
+// anyone who wants to fix and knows how to test it.
+class TextToPathPainter: public TextLayoutPainter
+{
+	ScribusView* m_view;
+	PageItem* m_item;
+	QList<PageItem*> m_group;
+	int m_counter;
+
+public:
+	TextToPathPainter(ScribusView* view, PageItem* item)
+		: m_view(view)
+		, m_item(item)
+		, m_counter(0)
+	{}
+
+	void drawGlyph(const GlyphLayout gl)
+	{
+
+		FPointArray outline = font().glyphOutline(gl.glyph);
+		if (outline.size() < 4)
+			return;
+		QTransform transform = matrix();
+		transform.scale(x(), y());
+		outline.map(transform);
+		uint z = m_view->Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, m_item->xPos(), m_item->yPos(), m_item->width(), m_item->height(), m_item->lineWidth(), m_item->lineColor(), m_item->fillColor());
+		PageItem* item = m_view->Doc->Items->at(z);
+		m_view->undoManager->setUndoEnabled(false);
+		item->setTextFlowMode(m_item->textFlowMode());
+		item->setSizeLocked(m_item->sizeLocked());
+		item->setLocked(m_item->locked());
+		item->NamedLStyle = m_item->NamedLStyle;
+		item->setItemName(m_item->itemName() + "+U" + QString::number(m_counter++));
+		item->PoLine = outline.copy();
+		if (!m_item->asPathText())
+			item->setRotation(m_item->rotation());
+		item->setFillColor(fillColor().color);
+		item->setFillShade(fillColor().shade);
+		item->setLineWidth(strokeWidth());
+		m_view->Doc->adjustItemSize(item);
+		item->ContourLine = item->PoLine.copy();
+		item->ClipEdited = true;
+		item->FrameType = 3;
+		item->OldB2 = item->width();
+		item->OldH2 = item->height();
+		m_view->Doc->setRedrawBounding(item);
+		m_view->undoManager->setUndoEnabled(true);
+		m_group.append(m_view->Doc->Items->takeAt(z));
+	}
+	void drawGlyphOutline(const GlyphLayout gl, bool fill)
+	{
+		drawGlyph(gl);
+	}
+	void drawLine(QPointF start, QPointF end)
+	{
+		QTransform transform = matrix();
+		transform.translate(x(), y());
+		uint z = m_view->Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, m_item->xPos(), m_item->yPos(), m_item->width(), m_item->height(), m_item->lineWidth(), m_item->lineColor(), m_item->fillColor());
+		PageItem* item = m_view->Doc->Items->at(z);
+		m_view->undoManager->setUndoEnabled(false);
+		item->setTextFlowMode(m_item->textFlowMode());
+		item->setSizeLocked(m_item->sizeLocked());
+		item->setLocked(m_item->locked());
+		item->NamedLStyle = m_item->NamedLStyle;
+		item->setItemName(m_item->itemName() + "+U" + QString::number(m_counter++));
+		item->PoLine.resize(0);
+		item->PoLine.addQuadPoint(FPoint(start), FPoint(start), FPoint(end), FPoint(end));
+		item->PoLine.map(transform);
+		item->setLineColor(fillColor().color);
+		item->setLineShade(fillColor().shade);
+		item->setLineWidth(strokeWidth());
+		m_view->Doc->adjustItemSize(item);
+		item->ContourLine = item->PoLine.copy();
+		item->ClipEdited = true;
+		item->FrameType = 3;
+		item->OldB2 = item->width();
+		item->OldH2 = item->height();
+		m_view->Doc->setRedrawBounding(item);
+		m_view->undoManager->setUndoEnabled(true);
+		m_group.append(m_view->Doc->Items->takeAt(z));
+	}
+	void drawRect(QRectF rect) {}
+	void drawObject(PageItem* item) {}
+};
+
 void ScribusView::TextToPath()
 {
 	if (Doc->appMode == modeEditClip)
@@ -3048,642 +3140,9 @@
 				++offset;
 				continue;
 			}
-//			newGroupedItems.clear();
-			FPointArray pts;
-			double x=0.0, y=0.0, wide=0.0;
-			QString chstr, ccounter;
-			QChar chstrex;
-			PageItem* bb;
-
-			if (currItem->asPathText())
-			{
-				for (int a = 0; a < currItem->asPathText()->itemRenderText.length(); ++a)
-				{
-					pts.resize(0);
-					x = 0.0;
-					y = 0.0;
-					//ScText * hl = currItem->asPathText()->itemRenderText.item_p(a);
-					const CharStyle& charStyle(currItem->asPathText()->itemRenderText.charStyle(a));
-					const PathData& pdata(currItem->textLayout.point(a));
-					const GlyphLayout* glyphs = currItem->asPathText()->itemRenderText.getGlyphs(a);
-					LayoutFlags flags = currItem->asPathText()->itemRenderText.flags(a);
-					
-					chstr = currItem->asPathText()->itemRenderText.text(a,1);
-					if ((chstr == SpecialChars::PARSEP) || (chstr == SpecialChars::OLD_NBSPACE))
-						continue;
-					if (chstr == SpecialChars::OBJECT)
-					{
-						continue;
-					}
-					if (chstr == SpecialChars::PAGENUMBER)
-						chstr = currItem->ExpandToken(a);
-					double chs = charStyle.fontSize();
-					if (charStyle.effects() & ScStyle_SmallCaps)
-					{
-						if (chstr[0].toUpper() != chstr[0])
-						{
-							chs = qMax(static_cast<int>(charStyle.fontSize() * Doc->typographicPrefs().valueSmallCaps / 100), 1);
-							chstr = chstr[0].toUpper();
-						}
-					}
-					else if (charStyle.effects() & ScStyle_AllCaps)
-						chstr = chstr[0].toUpper();
-	//					double csi = static_cast<double>(chs) / 100.0;
-					uint chr = chstr[0].unicode();
-					QPointF tangt = QPointF( cos(pdata.PRot), sin(pdata.PRot) );
-					QTransform chma, chma2, chma3, chma4, chma6;
-					QTransform trafo = QTransform( 1, 0, 0, -1, -pdata.PDx, 0 );
-					if (currItem->textPathFlipped)
-						trafo *= QTransform(1, 0, 0, -1, 0, 0);
-					if (currItem->textPathType == 0)
-						trafo *= QTransform( tangt.x(), tangt.y(), tangt.y(), -tangt.x(), pdata.PtransX, pdata.PtransY );
-					else if (currItem->textPathType == 1)
-						trafo *= QTransform(1, 0, 0, -1, pdata.PtransX, pdata.PtransY );
-					else if (currItem->textPathType == 2)
-					{
-						double a = 1;
-						double b = -1;
-						if (tangt.x() < 0)
-						{
-							a = -1;
-							b = 1;
-						}
-						if (fabs(tangt.x()) > 0.1)
-							trafo *= QTransform( a, (tangt.y() / tangt.x()) * b, 0, -1, pdata.PtransX, pdata.PtransY ); // ID's Skew mode
-						else
-							trafo *= QTransform( a, 6 * b, 0, -1, pdata.PtransX, pdata.PtransY );
-					}
-					//trafo *= QTransform( hl->PtransX, hl->PtransY, hl->PtransY, -hl->PtransX, glyphs->xoffset, glyphs->yoffset);
-					if (currItem->rotation() != 0)
-					{
-						QTransform sca;
-						sca.translate(-currItem->xPos(), -currItem->yPos());
-						sca.rotate(currItem->rotation());
-						trafo *= sca;
-					}
-					chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0);
-					if (currItem->reversed())
-					{
-						if (a < currItem->asPathText()->itemRenderText.length()-1)
-							wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), currItem->asPathText()->itemRenderText.text(a+1));
-						else
-							wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize());
-						chma3.scale(-1, 1);
-						chma3.translate(-wide, 0);
-					}
-					chma4.translate(0, currItem->BaseOffs - (charStyle.fontSize() / 10.0) * glyphs->scaleV);
-					if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript))
-						chma6.translate(0, glyphs->yoffset);
-					if (charStyle.baselineOffset() != 0)
-						chma6.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0));
-					uint gl = charStyle.font().char2CMap(chr);
-					QTransform finalMat = QTransform(chma * chma2 * chma3 * chma4 * chma6 * trafo);
-					if (currItem->rotation() != 0)
-					{
-						QTransform sca;
-						sca.translate(currItem->xPos(), currItem->yPos());
-						pts.map(sca);
-					}
-					QChar chstc = chstr[0];
-					if (((charStyle.effects() & ScStyle_Underline) && !SpecialChars::isBreak(chstc))
-						|| ((charStyle.effects() & ScStyle_UnderlineWords) && !chstc.isSpace() && !SpecialChars::isBreak(chstc)))
-					{
-						QTransform stro = QTransform(chma2 * chma3 * chma6 * trafo);
-						if (currItem->rotation() != 0)
-						{
-							QTransform sca;
-							sca.translate(currItem->xPos(), currItem->yPos());
-							stro *= sca;
-						}
-						double Ulen = glyphs->xadvance;
-						double Upos, Uwid, kern;
-						if (flags & ScLayout_StartOfLine)
-							kern = 0;
-						else
-							kern = charStyle.fontSize() * charStyle.tracking() / 10000.0;
-						if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1))
-						{
-							if (charStyle.underlineOffset() != -1)
-								Upos = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0));
-							else
-								Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-							if (charStyle.underlineWidth() != -1)
-								Uwid = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-							else
-								Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-						}
-						else
-						{
-							Upos = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-							Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-						}
-						if (charStyle.baselineOffset() != 0)
-							Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-						uint z = Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor());
-						bb = Doc->Items->at(z);
-						undoManager->setUndoEnabled(false);
-						bb->setTextFlowMode(currItem->textFlowMode());
-						bb->setSizeLocked(currItem->sizeLocked());
-						bb->setLocked(currItem->locked());
-						bb->NamedLStyle = currItem->NamedLStyle;
-						bb->setItemName(currItem->itemName()+"+U"+ccounter.setNum(a));
-						FPoint start, stop;
-						if (charStyle.effects() & ScStyle_Subscript)
-						{
-							start = FPoint(glyphs->xoffset-kern, -Upos);
-							stop = FPoint(glyphs->xoffset+Ulen, -Upos);
-						}
-						else
-						{
-							start = FPoint(glyphs->xoffset-kern, -(Upos + glyphs->yoffset));
-							stop = FPoint(glyphs->xoffset+Ulen, -(Upos + glyphs->yoffset));
-						}
-						bb->PoLine.resize(0);
-						bb->PoLine.addQuadPoint(start, start, stop, stop);
-						bb->PoLine.map(stro);
-						bb->setLineColor(charStyle.fillColor());
-						bb->setLineShade(charStyle.fillShade());
-						bb->setLineWidth(Uwid);
-						Doc->adjustItemSize(bb);
-						bb->ContourLine = bb->PoLine.copy();
-						bb->ClipEdited = true;
-						bb->FrameType = 3;
-						bb->OldB2 = bb->width();
-						bb->OldH2 = bb->height();
-						Doc->setRedrawBounding(bb);
-						undoManager->setUndoEnabled(true);
-						newGroupedItems.append(Doc->Items->takeAt(z));
-					}
-					if ((chstr.length() > 0) && (!chstr.at(0).isSpace()))
-					{
-						pts = charStyle.font().glyphOutline(gl);
-						if (pts.size() < 4)
-							continue;
-						if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None))
-						{
-							double glxTr = charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0;
-							double glyTr = -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0;
-							uint z = Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor());
-							bb = Doc->Items->at(z);
-							undoManager->setUndoEnabled(false);
-							bb->setTextFlowMode(currItem->textFlowMode());
-							bb->setSizeLocked(currItem->sizeLocked());
-							bb->setLocked(currItem->locked());
-							bb->NamedLStyle = currItem->NamedLStyle;
-							bb->setItemName(currItem->itemName()+"+Sh"+ccounter.setNum(a));
-							bb->PoLine = pts.copy();
-							QTransform shmap;
-							shmap.translate(glxTr, glyTr);
-							bb->PoLine.map(finalMat * shmap);
-							bb->setFillColor(charStyle.strokeColor());
-							bb->setFillShade(charStyle.strokeShade());
-							if (currItem->asPathText()->itemRenderText.charStyle(a).effects() & ScStyle_Outline)
-							{
-								bb->setLineColor(charStyle.strokeColor());
-								bb->setLineShade(charStyle.strokeShade());
-							}
-							else
-							{
-								bb->setLineColor(CommonStrings::None);
-								bb->setLineShade(100);
-							}
-							bb->setLineWidth(chs * charStyle.outlineWidth() / 10000.0);
-							Doc->adjustItemSize(bb);
-							bb->ContourLine = bb->PoLine.copy();
-							bb->ClipEdited = true;
-							bb->FrameType = 3;
-							bb->OldB2 = bb->width();
-							bb->OldH2 = bb->height();
-							Doc->setRedrawBounding(bb);
-							undoManager->setUndoEnabled(true);
-							newGroupedItems.append(Doc->Items->takeAt(z));
-						}
-						pts.map(finalMat);
-						uint z = Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor());
-						bb = Doc->Items->at(z);
-						//bb->setTextFlowsAroundFrame(currItem->textFlowsAroundFrame());
-						//bb->setTextFlowUsesBoundingBox(currItem->textFlowUsesBoundingBox());
-						undoManager->setUndoEnabled(false);
-						bb->setTextFlowMode(currItem->textFlowMode());
-						bb->setSizeLocked(currItem->sizeLocked());
-						bb->setLocked(currItem->locked());
-						bb->NamedLStyle = currItem->NamedLStyle;
-						bb->setItemName(currItem->itemName()+"+"+ccounter.setNum(a));
-						bb->PoLine = pts.copy();
-						if (!currItem->asPathText())
-							bb->setRotation(currItem->rotation());
-						bb->setFillColor(charStyle.fillColor());
-						bb->setFillShade(charStyle.fillShade());
-						if (currItem->asPathText()->itemRenderText.charStyle(a).effects() & ScStyle_Outline)
-						{
-							bb->setLineColor(charStyle.strokeColor());
-							bb->setLineShade(charStyle.strokeShade());
-						}
-						else
-						{
-							bb->setLineColor(CommonStrings::None);
-							bb->setLineShade(100);
-						}
-						bb->setLineWidth(chs * charStyle.outlineWidth() / 10000.0);
-						Doc->adjustItemSize(bb);
-						bb->ContourLine = bb->PoLine.copy();
-						bb->ClipEdited = true;
-						bb->FrameType = 3;
-						bb->OldB2 = bb->width();
-						bb->OldH2 = bb->height();
-						Doc->setRedrawBounding(bb);
-						undoManager->setUndoEnabled(true);
-						newGroupedItems.append(Doc->Items->takeAt(z));
-					}
-					if (charStyle.effects() & ScStyle_Strikethrough)
-					{
-						QTransform stro = QTransform(chma2 * chma3 * chma6 * trafo);
-						if (currItem->rotation() != 0)
-						{
-							QTransform sca;
-							sca.translate(currItem->xPos(), currItem->yPos());
-							stro *= sca;
-						}
-						double Ulen = glyphs->xadvance;
-						double Upos, Uwid, kern;
-						if (flags & ScLayout_StartOfLine)
-							kern = 0;
-						else
-							kern = charStyle.fontSize() * charStyle.tracking() / 10000.0;
-						if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1))
-						{
-							if (charStyle.strikethruOffset() != -1)
-								Upos = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0));
-							else
-								Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-							if (charStyle.strikethruWidth() != -1)
-								Uwid = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-							else
-								Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-						}
-						else
-						{
-							Upos = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-							Uwid = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-						}
-						if (charStyle.baselineOffset() != 0)
-							Upos += (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-						uint z = Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor());
-						bb = Doc->Items->at(z);
-						undoManager->setUndoEnabled(false);
-						bb->setTextFlowMode(currItem->textFlowMode());
-						bb->setSizeLocked(currItem->sizeLocked());
-						bb->setLocked(currItem->locked());
-						bb->NamedLStyle = currItem->NamedLStyle;
-						bb->setItemName(currItem->itemName()+"+S"+ccounter.setNum(a));
-						FPoint start = FPoint(glyphs->xoffset-kern, -Upos);
-						FPoint stop = FPoint(glyphs->xoffset+Ulen, -Upos);
-						bb->PoLine.resize(0);
-						bb->PoLine.addQuadPoint(start, start, stop, stop);
-						bb->PoLine.map(stro);
-						bb->setLineColor(charStyle.fillColor());
-						bb->setLineShade(charStyle.fillShade());
-						bb->setLineWidth(Uwid);
-						Doc->adjustItemSize(bb);
-						bb->ContourLine = bb->PoLine.copy();
-						bb->ClipEdited = true;
-						bb->FrameType = 3;
-						bb->OldB2 = bb->width();
-						bb->OldH2 = bb->height();
-						Doc->setRedrawBounding(bb);
-						bb->setItemName(currItem->itemName()+"+S"+ccounter.setNum(a));
-						undoManager->setUndoEnabled(true);
-						newGroupedItems.append(Doc->Items->takeAt(z));
-					}
-				}
-			}
-			else
-			{
-				for (uint ll=0; ll < currItem->textLayout.lines(); ++ll)
-				{
-					LineSpec ls = currItem->textLayout.line(ll);
-					double CurX = ls.x;
-					for (int a = ls.firstItem; a <= ls.lastItem; ++a)
-					{
-						pts.resize(0);
-						x = 0.0;
-						y = 0.0;
-						GlyphLayout* glyphs = currItem->itemText.getGlyphs(a);
-						const CharStyle& charStyle(currItem->itemText.charStyle(a));
-
-						chstr = currItem->itemText.text(a,1);
-						if ((chstr == SpecialChars::PARSEP) || (chstr == SpecialChars::OLD_NBSPACE))
-						{
-							if (chstr == SpecialChars::OLD_NBSPACE)
-								CurX += glyphs->wide();
-							continue;
-						}
-						if (chstr == SpecialChars::OBJECT)
-						{
-							if (currItem->itemText.hasObject(a))
-							{
-								ScriXmlDoc ss;
-								Selection tempSelection(this, false);
-								tempSelection.addItem(currItem->itemText.object(a), true);
-								QString dataS = ss.WriteElem(Doc, &tempSelection);
-								emit LoadElem(dataS, currItem->xPos(), currItem->yPos(), false, true, Doc, this);
-								bb = Doc->Items->last();
-								int z = Doc->Items->indexOf(bb);
-								bb->setTextFlowMode(currItem->textFlowMode());
-								bb->setSizeLocked(currItem->sizeLocked());
-								bb->setLocked(currItem->locked());
-								bb->setItemName(currItem->itemName()+"+"+ccounter.setNum(a));
-								bb->setRotation(currItem->rotation());
-								double textX = CurX + glyphs->xoffset;
-								double textY = ls.y - bb->height();
-								if (charStyle.baselineOffset() != 0)
-									textY -= (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-								if (currItem->imageFlippedH())
-									textX = currItem->width() - textX - wide;
-								if (currItem->imageFlippedV())
-									textY = currItem->height() - textY + y - (bb->height() - y);
-								FPoint npo(textX, textY, 0.0, 0.0, currItem->rotation(), 1.0, 1.0);
-								bb->setXYPos(currItem->xPos() + npo.x(), currItem->yPos() + npo.y(), false);
-								Doc->setRedrawBounding(bb);
-								newGroupedItems.append(Doc->Items->takeAt(z));
-							}
-							CurX += glyphs->wide();
-							continue;
-						}
-						if (chstr == SpecialChars::PAGENUMBER)
-							chstr = currItem->ExpandToken(a);
-						for (int cx = 0; cx < chstr.count(); cx++)
-						{
-							chstrex = chstr[cx];
-							double chs = charStyle.fontSize();
-							if (currItem->itemText.charStyle(a).effects() & ScStyle_SmallCaps)
-							{
-								if (chstrex.toUpper() != chstrex)
-								{
-									chs = qMax(static_cast<int>(chs * Doc->typographicPrefs().valueSmallCaps / 100), 1);
-									chstrex = chstrex.toUpper();
-								}
-							}
-							else if (currItem->itemText.charStyle(a).effects() &  ScStyle_AllCaps)
-								chstrex = chstrex.toUpper();
-							double csi = static_cast<double>(chs) / 100.0;
-							uint chr = chstrex.unicode();
-							QTransform chma, chma6;
-							uint gl = charStyle.font().char2CMap(chr);
-							FPoint origin = charStyle.font().glyphOrigin(gl);
-							x = origin.x() * csi * glyphs->scaleH;
-							y = origin.y() * csi * glyphs->scaleV;
-							if ((charStyle.effects() & ScStyle_Underline) || ((charStyle.effects() & ScStyle_UnderlineWords)  && chstr.toUInt() != charStyle.font().char2CMap(QChar(' '))))
-						{
-								double st, lw;
-								if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1))
-								{
-									if (charStyle.underlineOffset() != -1)
-										st = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0));
-									else
-										st = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-									if (charStyle.underlineWidth() != -1)
-										lw = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-									else
-										lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-								}
-								else
-								{
-									st = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
-									lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-								}
-								if (charStyle.baselineOffset() != 0)
-									st += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0);
-								uint z = Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor());
-								bb = Doc->Items->at(z);
-								undoManager->setUndoEnabled(false);
-								bb->setTextFlowMode(currItem->textFlowMode());
-								bb->setSizeLocked(currItem->sizeLocked());
-								bb->setLocked(currItem->locked());
-								bb->NamedLStyle = currItem->NamedLStyle;
-								bb->setItemName(currItem->itemName()+"+U"+ccounter.setNum(a));
-								bb->setRotation(currItem->rotation());
-								bb->PoLine.addQuadPoint(FPoint(0, 0), FPoint(0, 0), FPoint(glyphs->xadvance, 0), FPoint(glyphs->xadvance, 0));
-								bb->setLineColor(charStyle.fillColor());
-								bb->setLineShade(charStyle.fillShade());
-								bb->setLineWidth(lw);
-								FPoint tp2(getMinClipF(&bb->PoLine));
-								bb->PoLine.translate(-tp2.x(), -tp2.y());
-								FPoint tp(getMaxClipF(&bb->PoLine));
-								bb->setWidthHeight(tp.x(), tp.y());
-								bb->Clip = FlattenPath(bb->PoLine, bb->Segments);
-								double textX = CurX;
-								double textY = ls.y - st;  // + glyphs->yoffset;
-								if (charStyle.effects() & ScStyle_Subscript)
-									textY += glyphs->yoffset;
-								if (charStyle.baselineOffset() != 0)
-									textY -= (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-								if (a < currItem->itemText.length()-1)
-									wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), currItem->itemText.text(a+1));
-								else
-									wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize());
-								if (currItem->imageFlippedH())
-									textX = currItem->width() - textX - bb->width() - x;
-								if (currItem->imageFlippedV())
-									textY = currItem->height() - textY + y - (bb->height() - y);
-								FPoint npo(textX, textY, 0.0, 0.0, currItem->rotation(), 1.0, 1.0);
-								bb->moveBy(npo.x(),npo.y());
-								bb->ContourLine = bb->PoLine.copy();
-								bb->ClipEdited = true;
-								bb->FrameType = 3;
-								bb->OldB2 = bb->width();
-								bb->OldH2 = bb->height();
-								Doc->setRedrawBounding(bb);
-								undoManager->setUndoEnabled(true);
-								newGroupedItems.append(Doc->Items->takeAt(z));
-							}
-							if (!chstrex.isSpace())
-							{
-								pts = charStyle.font().glyphOutline(gl);
-								if (pts.size() < 4)
-									continue;
-								chma = QTransform();
-								chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0);
-								pts.map(chma);
-								chma = QTransform();
-								if (currItem->imageFlippedH() && (!currItem->reversed()))
-									chma.scale(-1, 1);
-								if (currItem->imageFlippedV())
-									chma.scale(1, -1);
-								undoManager->setUndoEnabled(false);
-								pts.map(chma);
-								if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None))
-								{
-									double glxTr = charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0;
-									double glyTr = -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0;
-									uint z = Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, currItem->xPos() + glxTr, currItem->yPos() + glyTr, currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor());
-									bb = Doc->Items->at(z);
-									undoManager->setUndoEnabled(false);
-									bb->setTextFlowMode(currItem->textFlowMode());
-									bb->setSizeLocked(currItem->sizeLocked());
-									bb->setLocked(currItem->locked());
-									bb->NamedLStyle = currItem->NamedLStyle;
-									bb->setItemName(currItem->itemName()+"+Sh"+ccounter.setNum(a));
-									bb->PoLine = pts.copy();
-									bb->setRotation(currItem->rotation());
-									bb->setFillColor(charStyle.strokeColor());
-									bb->setFillShade(charStyle.strokeShade());
-									bb->setLineColor(CommonStrings::None);
-									bb->setLineShade(100);
-									bb->setLineWidth(chs * charStyle.outlineWidth() / 10000.0);
-									FPoint tp2(getMinClipF(&bb->PoLine));
-									bb->PoLine.translate(-tp2.x(), -tp2.y());
-									FPoint tp(getMaxClipF(&bb->PoLine));
-									bb->setWidthHeight(tp.x(), tp.y());
-									bb->Clip = FlattenPath(bb->PoLine, bb->Segments);
-									double textX = CurX + glyphs->xoffset;
-									double textY = ls.y;  // + glyphs->yoffset;
-									if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript))
-										textY += glyphs->yoffset;
-									chma6 = QTransform();
-									if (charStyle.baselineOffset() != 0)
-										textY -= (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-									if (a < currItem->itemText.length()-1)
-										wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), currItem->itemText.text(a+1));
-									else
-										wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize());
-									if (currItem->imageFlippedH())
-										textX = currItem->width() - textX - bb->width() - x;
-									if (currItem->imageFlippedV())
-										textY = currItem->height() - textY + y - (bb->height() - y);
-									FPoint npo(textX+x, textY-y, 0.0, 0.0, currItem->rotation(), 1.0, 1.0);
-									bb->moveBy(npo.x(),npo.y());
-									bb->ContourLine = bb->PoLine.copy();
-									bb->ClipEdited = true;
-									bb->FrameType = 3;
-									bb->OldB2 = bb->width();
-									bb->OldH2 = bb->height();
-									Doc->setRedrawBounding(bb);
-									undoManager->setUndoEnabled(true);
-									newGroupedItems.append(Doc->Items->takeAt(z));
-								}
-								uint z = Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor());
-								bb = Doc->Items->at(z);
-								//bb->setTextFlowsAroundFrame(currItem->textFlowsAroundFrame());
-								//bb->setTextFlowUsesBoundingBox(currItem->textFlowUsesBoundingBox());
-								bb->setTextFlowMode(currItem->textFlowMode());
-								bb->setSizeLocked(currItem->sizeLocked());
-								bb->setLocked(currItem->locked());
-								bb->NamedLStyle = currItem->NamedLStyle;
-								bb->setItemName(currItem->itemName()+"+"+ccounter.setNum(a));
-								bb->PoLine = pts.copy();
-								bb->setRotation(currItem->rotation());
-								bb->setFillColor(charStyle.fillColor());
-								bb->setFillShade(charStyle.fillShade());
-								if (currItem->itemText.charStyle(a).effects() & ScStyle_Outline)
-								{
-									bb->setLineColor(charStyle.strokeColor());
-									bb->setLineShade(charStyle.strokeShade());
-								}
-								else
-								{
-									bb->setLineColor(CommonStrings::None);
-									bb->setLineShade(100);
-								}
-								bb->setLineWidth(chs * charStyle.outlineWidth() / 10000.0);
-								FPoint tp2(getMinClipF(&bb->PoLine));
-								bb->PoLine.translate(-tp2.x(), -tp2.y());
-								FPoint tp(getMaxClipF(&bb->PoLine));
-								bb->setWidthHeight(tp.x(), tp.y());
-								bb->Clip = FlattenPath(bb->PoLine, bb->Segments);
-								double textX = CurX + glyphs->xoffset;
-								double textY = ls.y;  // + glyphs->yoffset;
-								if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript))
-									textY += glyphs->yoffset;
-								chma6 = QTransform();
-								if (charStyle.baselineOffset() != 0)
-									textY -= (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-								if (a < currItem->itemText.length()-1)
-									wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), currItem->itemText.text(a+1));
-								else
-									wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize());
-								if (currItem->imageFlippedH())
-									textX = currItem->width() - textX - bb->width() - x;
-								if (currItem->imageFlippedV())
-									textY = currItem->height() - textY + y - (bb->height() - y);
-								FPoint npo(textX+x, textY-y, 0.0, 0.0, currItem->rotation(), 1.0, 1.0);
-								bb->moveBy(npo.x(),npo.y());
-								bb->ContourLine = bb->PoLine.copy();
-								bb->ClipEdited = true;
-								bb->FrameType = 3;
-								bb->OldB2 = bb->width();
-								bb->OldH2 = bb->height();
-								Doc->setRedrawBounding(bb);
-								undoManager->setUndoEnabled(true);
-								newGroupedItems.append(Doc->Items->takeAt(z));
-							}
-							if (charStyle.effects() & ScStyle_Strikethrough)
-							{
-								double st, lw;
-								if ((charStyle.strikethruOffset() != -1) || (charStyle.strikethruWidth() != -1))
-								{
-									if (charStyle.strikethruOffset() != -1)
-										st = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0));
-									else
-										st = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-									if (charStyle.strikethruWidth() != -1)
-										lw = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
-									else
-										lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-								}
-								else
-								{
-									st = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
-									lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
-								}
-								if (charStyle.baselineOffset() != 0)
-									st += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0);
-								uint z = Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), currItem->lineColor(), currItem->fillColor());
-								bb = Doc->Items->at(z);
-								undoManager->setUndoEnabled(false);
-								bb->setTextFlowMode(currItem->textFlowMode());
-								bb->setSizeLocked(currItem->sizeLocked());
-								bb->setLocked(currItem->locked());
-								bb->NamedLStyle = currItem->NamedLStyle;
-								bb->setItemName(currItem->itemName()+"+S"+ccounter.setNum(a));
-								bb->setRotation(currItem->rotation());
-								bb->PoLine.addQuadPoint(FPoint(0, 0), FPoint(0, 0), FPoint(glyphs->xadvance, 0), FPoint(glyphs->xadvance, 0));
-								bb->setLineColor(charStyle.fillColor());
-								bb->setLineShade(charStyle.fillShade());
-								bb->setLineWidth(lw);
-								FPoint tp2(getMinClipF(&bb->PoLine));
-								bb->PoLine.translate(-tp2.x(), -tp2.y());
-								FPoint tp(getMaxClipF(&bb->PoLine));
-								bb->setWidthHeight(tp.x(), tp.y());
-								bb->Clip = FlattenPath(bb->PoLine, bb->Segments);
-								double textX = CurX;
-								double textY = ls.y - st + glyphs->yoffset;
-								if (charStyle.baselineOffset() != 0)
-									textY -= (charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0);
-								if (a < currItem->itemText.length()-1)
-									wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize(), currItem->itemText.text(a+1));
-								else
-									wide = charStyle.font().charWidth(chstr[0], charStyle.fontSize());
-								if (currItem->imageFlippedH())
-									textX = currItem->width() - textX - bb->width() - x;
-								if (currItem->imageFlippedV())
-									textY = currItem->height() - textY + y - (bb->height() - y);
-								FPoint npo(textX, textY, 0.0, 0.0, currItem->rotation(), 1.0, 1.0);
-								bb->moveBy(npo.x(),npo.y());
-								bb->ContourLine = bb->PoLine.copy();
-								bb->ClipEdited = true;
-								bb->FrameType = 3;
-								bb->OldB2 = bb->width();
-								bb->OldH2 = bb->height();
-								Doc->setRedrawBounding(bb);
-								undoManager->setUndoEnabled(true);
-								newGroupedItems.append(Doc->Items->takeAt(z));
-							}
-							CurX += glyphs->wide();
-						}
-					}
-				}
-			}
+
+			TextToPathPainter p(this, currItem);
+			currItem->textLayout.render(&p);
 			if ((currItem->asPathText()) && (currItem->PoShow))
 			{
 				uint z = Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), CommonStrings::None, currItem->lineColor());

Modified: trunk/Scribus/scribus/sctextstruct.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/sctextstruct.cpp
==============================================================================
--- trunk/Scribus/scribus/sctextstruct.cpp	(original)
+++ trunk/Scribus/scribus/sctextstruct.cpp	Wed Mar 23 20:21:36 2016
@@ -13,22 +13,19 @@
 #include "pageitem.h"
 #include "scribusdoc.h"
 
-void GlyphLayout::growWithTabLayout()
+
+qreal GlyphRun::width() const
 {
-	if (more)
-		shrink();
-	more = new TabLayout();
+	qreal width = 0;
+	foreach (const GlyphLayout gl, m_glyphs)
+	{
+		width += gl.xadvance * gl.scaleH;
+	}
+	return width;
 }
 
 ScText::~ScText() 
 {
-	// delete the linked list if present
-	GlyphLayout * more = glyph.more;
-	while (more) {
-		glyph.more = glyph.more->more;
-		delete more;
-		more = glyph.more;
-	}
 	if (parstyle)
 		delete parstyle;
 	parstyle = NULL;

Modified: trunk/Scribus/scribus/sctextstruct.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/sctextstruct.h
==============================================================================
--- trunk/Scribus/scribus/sctextstruct.h	(original)
+++ trunk/Scribus/scribus/sctextstruct.h	Wed Mar 23 20:21:36 2016
@@ -39,17 +39,21 @@
 // from charstlye.h ScStyleFlags
 enum LayoutFlags {
 	ScLayout_None          = 0,
+	ScLayout_BulletNum     = 1,       // new: marks list layout glyphs
+	ScLayout_FixedSpace    = 2,       // new: marks a fixed space
+	ScLayout_ExpandingSpace= 4,       // new: marks an expanding space
+	ScLayout_ImplicitSpace = 8,       // new: marks an implicit space
+	ScLayout_TabLeaders    = 16,      // new: marks a tab with fillchar
 	ScLayout_HyphenationPossible=128, //Hyphenation possible here (Soft Hyphen)
 	ScLayout_DropCap       = 2048,
-	ScLayout_SuppressSpace = 4096,//internal use in PageItem (Suppresses spaces when in Block alignment)
-	ScLayout_SoftHyphenVisible=8192, //Soft Hyphen visible at line end
-	ScLayout_StartOfLine   = 16384
+	ScLayout_SuppressSpace = 4096,    //internal use in PageItem (Suppresses spaces when in Block alignment)
+	ScLayout_SoftHyphenVisible=8192,  //Soft Hyphen visible at line end
+	ScLayout_StartOfLine   = 16384    //set for start of line
 };
 
 
 /**
  * This struct stores a positioned glyph. This is the result of the layout process.
- * If a char gets translated to more than one glyph, a linked list is built.
  */
 struct SCRIBUS_API GlyphLayout {
 	float xadvance;
@@ -59,50 +63,42 @@
 	double scaleV;
 	double scaleH;
 	uint glyph;
-	GlyphLayout* more;
 	
 	GlyphLayout() : xadvance(0.0f), yadvance(0.0f), xoffset(0.0f), yoffset(0.0f),
-		scaleV(1.0), scaleH(1.0), glyph(0), more(NULL) 
+		scaleV(1.0), scaleH(1.0), glyph(0) //, more(NULL)
 	{ }
-	GlyphLayout(const GlyphLayout& o) : xadvance(o.xadvance), yadvance(o.yadvance), xoffset(o.xoffset), yoffset(o.yoffset),
-		scaleV(o.scaleH), scaleH(o.scaleV), glyph(o.glyph), more(NULL)
-	{ }
-	virtual ~GlyphLayout()
-	{ }
-	double wide() const 
-	{ 
-		double ret = 0; 
-		for(const GlyphLayout* p=this; p; p=p->more) 
-			ret += p->xadvance; 
-		return ret; 
-	}
-	GlyphLayout* last() 
-	{ 
-		if (more) 
-			return more->last();
-		else 
-			return this;
-	}
-	void shrink()
-	{
-		if (more) {
-			more->shrink();
-			delete more;
-			more = NULL;
-		}
-	}
-	void grow()
-	{
-		if (!more) {
-			more = new GlyphLayout();
-		}
-	}
-	virtual void growWithTabLayout();
 };
 
-struct SCRIBUS_API TabLayout : public GlyphLayout
+
+class GlyphRun
 {
-	QChar fillChar;
+	const CharStyle* m_style;
+	LayoutFlags m_flags;
+	QList<GlyphLayout> m_glyphs;
+	int m_firstChar;
+	int m_lastChar;
+	PageItem* m_object;
+
+public:
+	GlyphRun(const CharStyle* style, LayoutFlags flags, int first, int last, PageItem* o)
+		: m_style(style)
+		, m_flags(flags)
+		, m_firstChar(first)
+		, m_lastChar(last)
+		, m_object(o)
+	{}
+
+	const CharStyle&         style()  const { return *m_style; }
+	bool       hasFlag(LayoutFlags f) const { return (m_flags & f) == f; }
+	void       setFlag(LayoutFlags f)       { m_flags = static_cast<LayoutFlags>(m_flags | f); }
+	void     clearFlag(LayoutFlags f)       { m_flags = static_cast<LayoutFlags>(m_flags & ~f); }
+
+	QList<GlyphLayout>&      glyphs()       { return m_glyphs; }
+	const QList<GlyphLayout> glyphs() const { return m_glyphs; }
+	int firstChar()					const	{ return m_firstChar; }
+	int lastChar()					const	{ return m_lastChar; }
+	qreal width() const;
+	PageItem* object()				const	{ return m_object; }
 };
 
 
@@ -110,28 +106,18 @@
 {
 public:
 	ParagraphStyle* parstyle; // only for parseps
-	GlyphLayout glyph;
 	int embedded;
 	Mark* mark;
 	QChar ch;
-	ScText() : 
+	ScText() :
 		CharStyle(),
-		parstyle(NULL), glyph(), 
+		parstyle(NULL),
 		embedded(0), mark(NULL), ch() {}
-	ScText(const ScText& other) : 
+	ScText(const ScText& other) :
 		CharStyle(other),
-		parstyle(NULL), glyph(other.glyph), 
+		parstyle(NULL),
 		embedded(other.embedded), mark(NULL), ch(other.ch)
 	{
-		glyph.more = NULL;
-		GlyphLayout *layout = &glyph;
-		const GlyphLayout *otherLayout = &other.glyph;
-		while (otherLayout->more)
-		{
-			layout->more = new GlyphLayout(*otherLayout->more);
-			layout       = layout->more;
-			otherLayout  = otherLayout->more;
-		}
 		if (other.parstyle)
 			parstyle = new ParagraphStyle(*other.parstyle);
 		if (other.mark)

Modified: trunk/Scribus/scribus/text/CMakeLists.txt
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/text/CMakeLists.txt
==============================================================================
--- trunk/Scribus/scribus/text/CMakeLists.txt	(original)
+++ trunk/Scribus/scribus/text/CMakeLists.txt	Wed Mar 23 20:21:36 2016
@@ -2,21 +2,26 @@
 	${CMAKE_SOURCE_DIR}
 	${CMAKE_SOURCE_DIR}/scribus
 	${FREETYPE_INCLUDE_DIRS}
+	${CAIRO_INCLUDE_DIRS}
 )
 
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_FPIC}")
 
 SET(SCRIBUS_TEXT_MOC_CLASSES
 	storytext.h
+	boxes.h
 )
 
 SET(SCRIBUS_TEXT_LIB_SOURCES
 	specialchars.cpp
 	storytext.cpp
 	textlayout.cpp
+	textlayoutpainter.cpp
+	screenpainter.cpp
 	sctext_shared.cpp
 	fsize.cpp
 	frect.cpp
+	boxes.cpp
 )
 
 QT5_WRAP_CPP(SCRIBUS_TEXT_MOC_SOURCES ${SCRIBUS_TEXT_MOC_CLASSES})

Modified: trunk/Scribus/scribus/text/storytext.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/text/storytext.cpp
==============================================================================
--- trunk/Scribus/scribus/text/storytext.cpp	(original)
+++ trunk/Scribus/scribus/text/storytext.cpp	Wed Mar 23 20:21:36 2016
@@ -710,32 +710,6 @@
 	}
 
 	return result;
-}
-
-
-GlyphLayout* StoryText::getGlyphs(int pos)
-{
-    if (pos < 0)
-        pos += length();
-
-    assert(pos >= 0);
-    assert(pos < length());
-	// WTF ?! removing this assert as it gives crashes when Scale goes below 51 %
-//	assert((this->d->at(pos)->glyph).scaleH > 0.5);
-	return &(this->d->at(pos)->glyph);
-}
-
-const GlyphLayout* StoryText::getGlyphs(int pos) const
-{
-    if (pos < 0)
-        pos += length();
-
-    assert(pos >= 0);
-    assert(pos < length());
-
-	// WTF ?! removing this assert as it gives crashes when Scale goes below 51 %
-//	assert( (const_cast<StoryText *>(this)->d->at(pos)->glyph).scaleH > 0.5);
-	return &(const_cast<StoryText *>(this)->d->at(pos)->glyph);
 }
 
 QChar StoryText::text() const

Modified: trunk/Scribus/scribus/text/storytext.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/text/storytext.h
==============================================================================
--- trunk/Scribus/scribus/text/storytext.h	(original)
+++ trunk/Scribus/scribus/text/storytext.h	Wed Mar 23 20:21:36 2016
@@ -231,8 +231,6 @@
 
 // layout helpers
 
-    GlyphLayout* getGlyphs(int pos);
-    const GlyphLayout* getGlyphs(int pos) const;
 	LayoutFlags flags(int pos) const;
 	bool hasFlag(int pos, LayoutFlags flag) const;
 	void setFlag(int pos, LayoutFlags flag);

Modified: trunk/Scribus/scribus/text/textlayout.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/text/textlayout.cpp
==============================================================================
--- trunk/Scribus/scribus/text/textlayout.cpp	(original)
+++ trunk/Scribus/scribus/text/textlayout.cpp	Wed Mar 23 20:21:36 2016
@@ -23,6 +23,8 @@
 #include "specialchars.h"
 #include "storytext.h"
 #include "textlayout.h"
+#include "textlayoutpainter.h"
+#include "boxes.h"
 
 
 
@@ -32,22 +34,49 @@
 	m_story = text;
 	m_frame = frame;
 
-	m_firstInFrame = 0;
-	m_lastInFrame = -1;
 	m_validLayout = false;
 	m_magicX = 0.0;
 	m_lastMagicPos = -1;
-}
-
+
+	m_box = new GroupBox(Box::D_Horizontal);
+}
+
+TextLayout::~TextLayout()
+{
+	delete m_box;
+}
 
 uint TextLayout::lines() const
 {
-	return m_lines.count();
-}
-
-const LineSpec& TextLayout::line(uint i) const
-{
-	return m_lines[i];
+	uint count = 0;
+	foreach (const Box *box, m_box->boxes())
+	{
+		count += box->boxes().count();
+	}
+	return count;
+}
+
+const LineBox* TextLayout::line(uint i) const
+{
+	uint count = 0;
+	foreach (const Box *box, m_box->boxes())
+	{
+		if (i < count + box->boxes().count())
+			return dynamic_cast<const LineBox*>(box->boxes()[i - count]);
+		count += box->boxes().count();
+	}
+	assert(false);
+	return NULL;
+}
+
+const Box* TextLayout::box() const
+{
+	return m_box;
+}
+
+Box* TextLayout::box()
+{
+	return m_box;
 }
 
 const PathData& TextLayout::point(int pos) const
@@ -63,45 +92,73 @@
 }
 
 
-void TextLayout::appendLine(const LineSpec& ls)
-	{ 
-		assert( ls.firstItem >= 0 );
-		assert( ls.firstItem < story()->length() );
-		assert( ls.lastItem >= 0 && ls.firstItem - ls.lastItem < 1 );
-		assert( ls.lastItem < story()->length() );
-		m_lines.append(ls);
-		if (m_lastInFrame < m_firstInFrame) {
-			m_firstInFrame = ls.firstItem;
-			m_lastInFrame = ls.lastItem;
-		}
-		else {
-			m_firstInFrame = qMin(m_firstInFrame, ls.firstItem);
-			m_lastInFrame = qMax(m_lastInFrame, ls.lastItem);
-		}
-	}
+void TextLayout::appendLine(LineBox* ls)
+{
+	assert( ls->firstChar() >= 0 );
+	assert( ls->firstChar() < story()->length() );
+	assert( ls->lastChar() < story()->length() );
+
+	// HACK: the ascent set by PageItem_TextFrame::layout()
+	// is useless, we reset it again based on the y position
+	ls->setAscent(ls->y() - m_box->boxes().last()->naturalHeight());
+	dynamic_cast<GroupBox*>(m_box->boxes().last())->addBox(ls);
+}
 
 // Remove the last line from the list. Used when we need to backtrack on the layouting.
 void TextLayout::removeLastLine ()
 {
-	if (m_lines.isEmpty()) return;
-	LineSpec last = m_lines.takeLast ();
-	if (m_lines.isEmpty()) {
-		clear();
-		return;
-	}
-	// fix lastFrameItem
-	if (m_lastInFrame != last.lastItem) return;
-	m_lastInFrame = m_lines.last().lastItem;
-}
-
-
+	m_box->removeBox(m_box->boxes().count() - 1);
+}
+
+void TextLayout::render(TextLayoutPainter *p, PageItem *item)
+{
+	p->save();
+	m_box->render(p, item);
+	p->restore();
+}
+
+void TextLayout::renderBackground(TextLayoutPainter *p)
+{
+	foreach (const Box* column, m_box->boxes())
+	{
+		const ParagraphStyle& style = m_story->paragraphStyle(column->firstChar());
+		if (style.backgroundColor() != CommonStrings::None)
+		{
+			p->save();
+			TextLayoutColor backColor(style.backgroundColor(), style.backgroundShade());
+			p->setFillColor(backColor);
+			p->setStrokeColor(backColor);
+			p->drawRect(column->bbox());
+			p->restore();
+		}
+	}
+}
+
+void TextLayout::render(TextLayoutPainter *p)
+{
+	p->save();
+	m_box->render(p);
+	p->restore();
+}
+
+void TextLayout::addColumn(double colLeft, double colWidth)
+{
+	GroupBox *newBox = new GroupBox(Box::D_Vertical);
+	newBox->moveTo(colLeft, 0.0);
+	newBox->setWidth(colWidth);
+	newBox->setAscent(m_frame->height());
+	m_box->addBox(newBox);
+
+	// Update the box width and height, any better place to do this?
+	m_box->setAscent(m_frame->height());
+	m_box->setWidth(m_frame->width());
+}
 
 void TextLayout::clear() 
 {
-	m_lines.clear();
+	delete m_box;
+	m_box = new GroupBox(Box::D_Horizontal);
 	m_path.clear();
-	m_firstInFrame = 0;
-	m_lastInFrame = -1;
 	if (m_frame->asPathText() != NULL)
 		m_path.resize(story()->length());
 }
@@ -114,198 +171,154 @@
 
 int TextLayout::startOfLine(int pos) const
 {
-	for (int i=0; i < m_lines.count(); ++i) {
-		const LineSpec & ls(m_lines.at(i));
-		if (ls.firstItem <= pos && pos <= ls.lastItem)
-			return ls.firstItem;
+	for (uint i=0; i < lines(); ++i) {
+		const LineBox* ls = line(i);
+		if (ls->firstChar() <= pos && pos <= ls->lastChar())
+			return ls->firstChar();
 	}
 	return 0;
 }
 
 int TextLayout::endOfLine(int pos) const
 {
-	for (int i=0; i < m_lines.count(); ++i) {
-		const LineSpec & ls(m_lines.at(i));
-		if (ls.firstItem <= pos && pos <= ls.lastItem)
-			return story()->text(ls.lastItem) == SpecialChars::PARSEP ? ls.lastItem :
-				story()->text(ls.lastItem) == ' ' ? ls.lastItem : ls.lastItem + 1;
+	for (uint i=0; i < lines(); ++i) {
+		const LineBox* ls = line(i);
+		if (ls->containsPos(pos))
+			return story()->text(ls->lastChar()) == SpecialChars::PARSEP ? ls->lastChar() :
+				story()->text(ls->lastChar()) == ' ' ? ls->lastChar() : ls->lastChar() + 1;
 	}
 	return story()->length();
 }
 
 int TextLayout::prevLine(int pos) const
 {
-	for (int i=0; i < m_lines.count(); ++i)
+	for (uint i=0; i < lines(); ++i)
 	{
 		// find line for pos
-		const LineSpec & ls(m_lines.at(i));
-		if (ls.firstItem <= pos && pos <= ls.lastItem)
+		const LineBox* ls = line(i);
+		if (ls->containsPos(pos))
 		{
 			if (i == 0)
 				return startOfLine(pos);
 			// find current xpos
-			qreal xpos = 0.0;
-			for (int j = ls.firstItem; j < pos; ++j)
-				xpos += story()->getGlyphs(j)->wide();
+			qreal xpos = ls->positionToPoint(pos).x1();
 			if (pos != m_lastMagicPos || xpos > m_magicX)
 				m_magicX = xpos;
-			const LineSpec & ls2(m_lines.at(i-1));
+
+			const LineBox* ls2 = line(i-1);
 			// find new cpos
-			xpos = 0.0;
-			for (int j = ls2.firstItem; j <= ls2.lastItem; ++j)
+			for (int j = ls2->firstChar(); j <= ls2->lastChar(); ++j)
 			{
-				xpos += story()->getGlyphs(j)->wide();
+				xpos = ls2->positionToPoint(j).x1();
 				if (xpos > m_magicX) {
 					m_lastMagicPos = j;
 					return j;
 				}
 			}
-			m_lastMagicPos = ls2.lastItem;
-			return ls2.lastItem;
-		}
-	}
-	return m_firstInFrame;
+			m_lastMagicPos = ls2->lastChar();
+			return ls2->lastChar();
+		}
+	}
+	return m_box->firstChar();
 }
 
 int TextLayout::nextLine(int pos) const
 {
-	for (int i=0; i < m_lines.count(); ++i)
+	for (uint i=0; i < lines(); ++i)
 	{
 		// find line for pos
-		const LineSpec & ls(m_lines.at(i));
-		if (ls.firstItem <= pos && pos <= ls.lastItem)
-		{
-			if (i+1 == m_lines.count())
+		const LineBox* ls = line(i);
+		if (ls->containsPos(pos))
+		{
+			if (i+1 == lines())
 				return endOfLine(pos);
 			// find current xpos
-			qreal xpos = 0.0;
-			for (int j = ls.firstItem; j < pos; ++j)
-				xpos += story()->getGlyphs(j)->wide();
+			qreal xpos = ls->positionToPoint(pos).x1();
+
 			if (pos != m_lastMagicPos || xpos > m_magicX)
 				m_magicX = xpos;
-			const LineSpec & ls2(m_lines.at(i+1));
+
+			const LineBox* ls2 = line(i+1);
 			// find new cpos
-			xpos = 0.0;
-			for (int j = ls2.firstItem; j <= ls2.lastItem; ++j)
+			for (int j = ls2->firstChar(); j <= ls2->lastChar(); ++j)
 			{
-				xpos += story()->getGlyphs(j)->wide();
+				xpos = ls2->positionToPoint(j).x1();
 				if (xpos > m_magicX) {
 					m_lastMagicPos = j;
 					return j;
 				}
 			}
-			m_lastMagicPos = ls2.lastItem + 1;
-			return ls2.lastItem + 1;
-		}
-	}
-	return m_lastInFrame;
+			m_lastMagicPos = ls2->lastChar() + 1;
+			return ls2->lastChar() + 1;
+		}
+	}
+	return m_box->lastChar();
 }
 
 int TextLayout::startOfFrame() const
 {
-	return m_firstInFrame;
+	return m_box->firstChar();
 }
 
 int TextLayout::endOfFrame() const
 {
-	return m_lastInFrame + 1;
-}
-
-
-int TextLayout::screenToPosition(FPoint coord) const
-{
-	qreal maxx = coord.x() - 1.0;
-	for (unsigned int i=0; i < lines(); ++i)
-	{
-		LineSpec ls = line(i);
-//		qDebug() << QString("screenToPosition: (%1,%2) -> y %3 - %4 + %5").arg(coord.x()).arg(coord.y()).arg(ls.y).arg(ls.ascent).arg(ls.descent);
-		if (ls.y + ls.descent < coord.y())
-			continue;
-		qreal xpos = ls.x;
-		for (int j = ls.firstItem; j <= ls.lastItem; ++j)
-		{
-//				qDebug() << QString("screenToPosition: (%1,%2) -> x %3 + %4").arg(coord.x()).arg(coord.y()).arg(xpos).arg(item(j)->glyph.wide());
-			qreal width = story()->getGlyphs(j)->wide();
-			xpos += width;
-			if (xpos >= coord.x())
+	return m_box->lastChar() + 1;
+}
+
+
+int TextLayout::pointToPosition(QPointF coord) const
+{
+	int position = m_box->pointToPosition(coord);
+	if (position == m_box->lastChar())
+		position += 1;
+	return position;
+}
+
+
+QLineF TextLayout::positionToPoint(int pos) const
+{
+	QLineF result;
+
+	result = m_box->positionToPoint(pos);
+	if (result.isNull())
+	{
+		qreal x, y1, y2;
+		if (lines() > 0)
+		{
+			// TODO: move this branch to GroupBox::positionToPoint()
+			// last glyph box in last line
+			Box* column = m_box->boxes().last();
+			Box* line = column->boxes().last();
+			Box* glyph = line->boxes().last();
+			QChar ch = story()->text(glyph->lastChar());
+			if (ch == SpecialChars::PARSEP || ch == SpecialChars::LINEBREAK)
 			{
-				if (story()->hasObject(j))
-					return j;
-				else
-					return xpos - width/2 > coord.x() ? j : j+1;
+				// last character is a newline, draw the cursor on the next line.
+				x = 1;
+				y1 = line->y() + line->height();
+				y2 = y1 + line->height();
 			}
-		}
-		if (xpos > maxx)
-			maxx = xpos;
-		if (xpos + 1.0 > coord.x()) // allow 1pt after end of line
-			return ls.lastItem + 1;
-		else if (coord.x() <= ls.x + ls.width) // last line of paragraph?
-			return ((ls.lastItem == m_lastInFrame) ? (ls.lastItem + 1) : ls.lastItem);
-		else if (xpos < ls.x + 0.01 && maxx >= coord.x()) // check for empty line
-			return ls.firstItem;
-	}
-	return qMax(m_lastInFrame+1, m_firstInFrame);
-}
-
-
-FRect TextLayout::boundingBox(int pos, uint len) const
-{
-	FRect result;
-	LineSpec ls;
-	for (uint i=0; i < lines(); ++i)
-	{
-		ls = line(i);
-		if (ls.lastItem < pos)
-			continue;
-		if (ls.firstItem <= pos) {
-			/*
-			//if (ls.lastItem == pos && (item(pos)->effects() & ScLayout_SuppressSpace)  )
+			else
 			{
-				if (i+1 < lines())
-				{
-					ls = line(i+1);
-					result.setRect(ls.x, ls.y - ls.ascent, 1, ls.ascent + ls.descent);
-				}
-				else
-				{
-					ls = line(lines()-1);
-					const ParagraphStyle& pstyle(paragraphStyle(pos));
-					result.setRect(ls.x, ls.y + pstyle.lineSpacing() - ls.ascent, 1, ls.ascent + ls.descent);
-				}
+				// draw the cursor at the end of last line.
+				x = line->x() + glyph->x() + glyph->width();
+				y1 = line->y();
+				y2 = y1 + line->height();
 			}
-			else */
-			{
-				qreal xpos = ls.x;
-				for (int j = ls.firstItem; j < pos; ++j)
-				{
-					if (story()->hasObject(j))
-						xpos += (story()->object(j)->width() + story()->object(j)->lineWidth()) * story()->getGlyphs(j)->scaleH;
-					else
-						xpos += story()->getGlyphs(j)->wide();
-				}
-				qreal finalw = 1;
-				if (story()->hasObject(pos))
-					finalw = (story()->object(pos)->width() + story()->object(pos)->lineWidth()) * story()->getGlyphs(pos)->scaleH;
-				else
-					finalw = story()->getGlyphs(pos)->wide();
-				const CharStyle& cs(story()->charStyle(pos));
-				qreal desc = -cs.font().descent(cs.fontSize() / 10.0);
-				qreal asce = cs.font().ascent(cs.fontSize() / 10.0);
-				result.setRect(xpos, ls.y - asce, pos < story()->length()? finalw : 1, desc+asce);
-			}
-			return result;
-		}
-	}
-	const ParagraphStyle& pstyle(story()->paragraphStyle(qMin(pos, story()->length()))); // rather the trailing style than a segfault.
-	if (lines() > 0)
-	{
-		ls = line(lines()-1);
-		result.setRect(ls.x, ls.y + pstyle.lineSpacing() - ls.ascent, 1, ls.ascent + ls.descent);
-	}
-	else
-	{
-		result.setRect(1, 1, 1, pstyle.lineSpacing());
-	}
+			result.setLine(x, y1, x, y2);
+			result.translate(column->x(), column->y());
+		}
+		else
+		{
+			// rather the trailing style than a segfault.
+			const ParagraphStyle& pstyle(story()->paragraphStyle(qMin(pos, story()->length())));
+			x = 1;
+			y1 = 0;
+			y2 = pstyle.lineSpacing();
+			result.setLine(x, y1, x, y2);
+		}
+		result.translate(m_box->x(), m_box->y());
+	}
+
 	return result;
 }
-

Modified: trunk/Scribus/scribus/text/textlayout.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21107&path=/trunk/Scribus/scribus/text/textlayout.h
==============================================================================
--- trunk/Scribus/scribus/text/textlayout.h	(original)
+++ trunk/Scribus/scribus/text/textlayout.h	Wed Mar 23 20:21:36 2016
@@ -26,22 +26,10 @@
 #include "sctextstruct.h"
 
 class StoryText;
-
-struct LineSpec
-{
-	qreal x;
-	qreal y;
-	qreal width;
-	qreal ascent;
-	qreal descent;
-	qreal colLeft;
-
-	int firstItem;
-	int lastItem;
-	qreal naturalWidth;
-	bool isFirstLine;
-	qreal height;
-};
+class Box;
+class GroupBox;
+class LineBox;
+class TextLayoutPainter;
 
 struct PathData
 {
@@ -61,13 +49,16 @@
 {
 public:
 	TextLayout(StoryText* text, PageItem* frame);
+	~TextLayout();
 
 	bool overflows() const;
 	
 	StoryText* story() { return m_story; }
 	const StoryText* story() const { return m_story; }
 	void setStory(StoryText* story);
-
+	void render(TextLayoutPainter *p, PageItem *item);
+	void render(TextLayoutPainter *p);
+	void renderBackground(TextLayoutPainter *p);
 	int startOfLine(int pos) const;
 	int endOfLine(int pos) const;
 	int prevLine(int pos) const;
@@ -75,17 +66,20 @@
 	int startOfFrame() const;
 	int endOfFrame() const;
 
-	int screenToPosition(FPoint coord) const;
- 	FRect boundingBox(int pos, uint len = 1) const;
+	int pointToPosition(QPointF coord) const;
+	QLineF positionToPoint(int pos) const;
 
 	uint lines() const;
 	
-	const LineSpec& line(uint i) const;
+	const LineBox*  line(uint i) const;
+	const Box* box() const;
+	Box* box();
 	const PathData& point(int pos) const;
 	PathData& point(int pos);
 
-	void appendLine(const LineSpec& ls);
+	void appendLine(LineBox* ls);
 	void removeLastLine ();
+	void addColumn(double colLeft, double colWidth);
 
 	void clear();
 
@@ -94,10 +88,8 @@
 	
 	StoryText* m_story;
     PageItem* m_frame;
+	GroupBox* m_box;
 	
-    int m_firstInFrame;
-	int m_lastInFrame;
-	QList<LineSpec> m_lines;
 	QVector<PathData> m_path;
 	bool m_validLayout;
 	mutable qreal m_magicX;




More information about the scribus-commit mailing list