r21349 by jghali -

scribus-commit scribus-commit at lists.scribus.net
Sun May 22 20:49:41 UTC 2016


Author: jghali
Date: Sun May 22 20:49:41 2016
New Revision: 21349

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=21349
Log:
Better sizing of text cursor in paragraph with drop caps or different font size 

Modified:
    trunk/Scribus/scribus/pageitem_textframe.cpp
    trunk/Scribus/scribus/text/boxes.cpp
    trunk/Scribus/scribus/text/boxes.h
    trunk/Scribus/scribus/text/textlayout.cpp

Modified: trunk/Scribus/scribus/pageitem_textframe.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21349&path=/trunk/Scribus/scribus/pageitem_textframe.cpp
==============================================================================
--- trunk/Scribus/scribus/pageitem_textframe.cpp	(original)
+++ trunk/Scribus/scribus/pageitem_textframe.cpp	Sun May 22 20:49:41 2016
@@ -808,7 +808,7 @@
 		result->moveTo(line.x - colLeft, line.y);
 		result->setWidth(line.width);
 		result->setAscent(line.ascent);
-		result->setDescent(line.descent);
+		result->setDescent(-line.descent);
 
 		for (int i = line.firstRun; i <= line.lastRun; ++i)
 		{

Modified: trunk/Scribus/scribus/text/boxes.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21349&path=/trunk/Scribus/scribus/text/boxes.cpp
==============================================================================
--- trunk/Scribus/scribus/text/boxes.cpp	(original)
+++ trunk/Scribus/scribus/text/boxes.cpp	Sun May 22 20:49:41 2016
@@ -154,8 +154,24 @@
 	{
 		if (box->containsPos(pos))
 		{
+			const GlyphBox* glypBox = dynamic_cast<const GlyphBox*>(box);
+			if (!glypBox)
+			{
+				double xPos = x() + box->x();
+				result = QLineF(xPos, y(), xPos, y() + height());
+				break;
+			}
+
+			const CharStyle& cStyle(glypBox->style());
+			double fontSize = cStyle.fontSize() / 10.0;
+			double scaleV = cStyle.scaleV() / 1000.0;
+			double offset = fontSize * (cStyle.baselineOffset() / 1000.0);
+			double asce = cStyle.font().ascent(fontSize) * scaleV + offset;
+			double desc = cStyle.font().descent(fontSize) * scaleV - offset;
+
 			double xPos = x() + box->x();
-			result = QLineF(xPos, y(), xPos, y() + height());
+			double yPos = y() + box->y() + ascent();
+			result = QLineF(xPos, yPos - asce, xPos, yPos - desc);
 			break;
 		}
 	}

Modified: trunk/Scribus/scribus/text/boxes.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21349&path=/trunk/Scribus/scribus/text/boxes.h
==============================================================================
--- trunk/Scribus/scribus/text/boxes.h	(original)
+++ trunk/Scribus/scribus/text/boxes.h	Sun May 22 20:49:41 2016
@@ -121,6 +121,9 @@
 
 	/// Same as render() but handles text selection, for rendering on screen.
 	virtual void render(TextLayoutPainter *p, PageItem *item) const = 0;
+
+	/// Return the box type
+	BoxType type() const { return m_type; }
 
 public slots:
 	virtual void childChanged() { }

Modified: trunk/Scribus/scribus/text/textlayout.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21349&path=/trunk/Scribus/scribus/text/textlayout.cpp
==============================================================================
--- trunk/Scribus/scribus/text/textlayout.cpp	(original)
+++ trunk/Scribus/scribus/text/textlayout.cpp	Sun May 22 20:49:41 2016
@@ -1,338 +1,352 @@
-/*
- For general Scribus (>=1.3.2) copyright and licensing information please refer
- to the COPYING file provided with the program. Following this notice may exist
- a copyright and/or license notice that predates the release of Scribus 1.3.2
- for which a new license (GPL+exception) is in place.
- */
-/***************************************************************************
-*                                                                         *
-*   This program is free software; you can redistribute it and/or modify  *
-*   it under the terms of the GNU General Public License as published by  *
-*   the Free Software Foundation; either version 2 of the License, or     *
-*   (at your option) any later version.                                   *
-*                                                                         *
-***************************************************************************/
-
-#undef NDEBUG
-
-#include <cassert>
-#include "../styles/charstyle.h"
-#include "pageitem.h"
-#include "prefsstructs.h"
-#include "../styles/paragraphstyle.h"
-#include "specialchars.h"
-#include "storytext.h"
-#include "textlayout.h"
-#include "textlayoutpainter.h"
-#include "boxes.h"
-
-
-
-
-TextLayout::TextLayout(StoryText* text, PageItem* frame)
-{
-	m_story = text;
-	m_frame = frame;
-
-	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
-{
-	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
-{
-	return m_path[pos];
-}
-
-PathData& TextLayout::point(int pos)
-{
-	if (pos >= story()->length())
-		m_path.resize(story()->length());
-	return m_path[pos];
-}
-
-
-void TextLayout::appendLine(LineBox* ls)
-{
-	assert(ls);
-	assert(ls->firstChar() >= 0);
-	assert(ls->firstChar() < story()->length());
-	assert(ls->lastChar() < story()->length());
-	assert(!m_box->boxes().empty());
-
-	GroupBox* column = dynamic_cast<GroupBox*>(m_box->boxes().last());
-	assert(column);
-
-	// HACK: the ascent set by PageItem_TextFrame::layout()
-	// is useless, we reset it again based on the y position
-	ls->setAscent(ls->y() - column->naturalHeight());
-	column->addBox(ls);
-}
-
-// Remove the last line from the list. Used when we need to backtrack on the layouting.
-void TextLayout::removeLastLine ()
-{
-	QList<Box*>& boxes = m_box->boxes();
-	if (boxes.isEmpty())
-		return;
-
-	GroupBox* column = dynamic_cast<GroupBox*>(boxes.last());
-	assert(column);
-
-	int lineCount = column->boxes().count();
-	if (lineCount > 0)
-		column->removeBox(lineCount - 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() 
-{
-	delete m_box;
-	m_box = new GroupBox(Box::D_Horizontal);
-	m_path.clear();
-	if (m_frame->asPathText() != NULL)
-		m_path.resize(story()->length());
-}
-
-void TextLayout::setStory(StoryText *story)
-{
-	m_story = story;
-	clear();
-}
-
-int TextLayout::startOfLine(int pos) const
-{
-	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 (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 (uint i=0; i < lines(); ++i)
-	{
-		// find line for pos
-		const LineBox* ls = line(i);
-		if (ls->containsPos(pos))
-		{
-			if (i == 0)
-				return startOfLine(pos);
-			// find current xpos
-			qreal xpos = ls->positionToPoint(pos).x1();
-			if (pos != m_lastMagicPos || xpos > m_magicX)
-				m_magicX = xpos;
-
-			const LineBox* ls2 = line(i-1);
-			// find new cpos
-			for (int j = ls2->firstChar(); j <= ls2->lastChar(); ++j)
-			{
-				xpos = ls2->positionToPoint(j).x1();
-				if (xpos > m_magicX) {
-					m_lastMagicPos = j;
-					return j;
-				}
-			}
-			m_lastMagicPos = ls2->lastChar();
-			return ls2->lastChar();
-		}
-	}
-	return m_box->firstChar();
-}
-
-int TextLayout::nextLine(int pos) const
-{
-	for (uint i=0; i < lines(); ++i)
-	{
-		// find line for pos
-		const LineBox* ls = line(i);
-		if (ls->containsPos(pos))
-		{
-			if (i+1 == lines())
-				return endOfLine(pos);
-			// find current xpos
-			qreal xpos = ls->positionToPoint(pos).x1();
-
-			if (pos != m_lastMagicPos || xpos > m_magicX)
-				m_magicX = xpos;
-
-			const LineBox* ls2 = line(i+1);
-			// find new cpos
-			for (int j = ls2->firstChar(); j <= ls2->lastChar(); ++j)
-			{
-				xpos = ls2->positionToPoint(j).x1();
-				if (xpos > m_magicX) {
-					m_lastMagicPos = j;
-					return j;
-				}
-			}
-			m_lastMagicPos = ls2->lastChar() + 1;
-			return ls2->lastChar() + 1;
-		}
-	}
-	return m_box->lastChar();
-}
-
-int TextLayout::startOfFrame() const
-{
-	return m_box->firstChar();
-}
-
-int TextLayout::endOfFrame() const
-{
-	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)
-			{
-				// last character is a newline, draw the cursor on the next line.
-				x = 1;
-				y1 = line->y() + line->height();
-				y2 = y1 + line->height();
-			}
-			else
-			{
-				// draw the cursor at the end of last line.
-				x = line->x() + glyph->x() + glyph->width();
-				y1 = line->y();
-				y2 = y1 + line->height();
-			}
-			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;
-}
+/*
+ For general Scribus (>=1.3.2) copyright and licensing information please refer
+ to the COPYING file provided with the program. Following this notice may exist
+ a copyright and/or license notice that predates the release of Scribus 1.3.2
+ for which a new license (GPL+exception) is in place.
+ */
+/***************************************************************************
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************/
+
+#undef NDEBUG
+
+#include <cassert>
+#include "../styles/charstyle.h"
+#include "pageitem.h"
+#include "prefsstructs.h"
+#include "../styles/paragraphstyle.h"
+#include "specialchars.h"
+#include "storytext.h"
+#include "textlayout.h"
+#include "textlayoutpainter.h"
+#include "boxes.h"
+
+
+
+
+TextLayout::TextLayout(StoryText* text, PageItem* frame)
+{
+	m_story = text;
+	m_frame = frame;
+
+	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
+{
+	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
+{
+	return m_path[pos];
+}
+
+PathData& TextLayout::point(int pos)
+{
+	if (pos >= story()->length())
+		m_path.resize(story()->length());
+	return m_path[pos];
+}
+
+
+void TextLayout::appendLine(LineBox* ls)
+{
+	assert(ls);
+	assert(ls->firstChar() >= 0);
+	assert(ls->firstChar() < story()->length());
+	assert(ls->lastChar() < story()->length());
+	assert(!m_box->boxes().empty());
+
+	GroupBox* column = dynamic_cast<GroupBox*>(m_box->boxes().last());
+	assert(column);
+
+	// HACK: the ascent set by PageItem_TextFrame::layout()
+	// is useless, we reset it again based on the y position
+	ls->setAscent(ls->y() - column->naturalHeight());
+	column->addBox(ls);
+}
+
+// Remove the last line from the list. Used when we need to backtrack on the layouting.
+void TextLayout::removeLastLine ()
+{
+	QList<Box*>& boxes = m_box->boxes();
+	if (boxes.isEmpty())
+		return;
+
+	GroupBox* column = dynamic_cast<GroupBox*>(boxes.last());
+	assert(column);
+
+	int lineCount = column->boxes().count();
+	if (lineCount > 0)
+		column->removeBox(lineCount - 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() 
+{
+	delete m_box;
+	m_box = new GroupBox(Box::D_Horizontal);
+	m_path.clear();
+	if (m_frame->asPathText() != NULL)
+		m_path.resize(story()->length());
+}
+
+void TextLayout::setStory(StoryText *story)
+{
+	m_story = story;
+	clear();
+}
+
+int TextLayout::startOfLine(int pos) const
+{
+	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 (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 (uint i=0; i < lines(); ++i)
+	{
+		// find line for pos
+		const LineBox* ls = line(i);
+		if (ls->containsPos(pos))
+		{
+			if (i == 0)
+				return startOfLine(pos);
+			// find current xpos
+			qreal xpos = ls->positionToPoint(pos).x1();
+			if (pos != m_lastMagicPos || xpos > m_magicX)
+				m_magicX = xpos;
+
+			const LineBox* ls2 = line(i-1);
+			// find new cpos
+			for (int j = ls2->firstChar(); j <= ls2->lastChar(); ++j)
+			{
+				xpos = ls2->positionToPoint(j).x1();
+				if (xpos > m_magicX) {
+					m_lastMagicPos = j;
+					return j;
+				}
+			}
+			m_lastMagicPos = ls2->lastChar();
+			return ls2->lastChar();
+		}
+	}
+	return m_box->firstChar();
+}
+
+int TextLayout::nextLine(int pos) const
+{
+	for (uint i=0; i < lines(); ++i)
+	{
+		// find line for pos
+		const LineBox* ls = line(i);
+		if (ls->containsPos(pos))
+		{
+			if (i+1 == lines())
+				return endOfLine(pos);
+			// find current xpos
+			qreal xpos = ls->positionToPoint(pos).x1();
+
+			if (pos != m_lastMagicPos || xpos > m_magicX)
+				m_magicX = xpos;
+
+			const LineBox* ls2 = line(i+1);
+			// find new cpos
+			for (int j = ls2->firstChar(); j <= ls2->lastChar(); ++j)
+			{
+				xpos = ls2->positionToPoint(j).x1();
+				if (xpos > m_magicX) {
+					m_lastMagicPos = j;
+					return j;
+				}
+			}
+			m_lastMagicPos = ls2->lastChar() + 1;
+			return ls2->lastChar() + 1;
+		}
+	}
+	return m_box->lastChar();
+}
+
+int TextLayout::startOfFrame() const
+{
+	return m_box->firstChar();
+}
+
+int TextLayout::endOfFrame() const
+{
+	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)
+			{
+				// last character is a newline, draw the cursor on the next line.
+				x = 1;
+				y1 = line->y() + line->height();
+				y2 = y1 + line->height();
+			}
+			else if (glyph->type() == Box::T_Glyph)
+			{
+				// draw the cursor at the end of last line.
+				const CharStyle& cStyle(story()->charStyle(glyph->lastChar()));
+				double fontSize = cStyle.fontSize() / 10.0;
+				double scaleV = cStyle.scaleV() / 1000.0;
+				double offset = fontSize * (cStyle.baselineOffset() / 1000.0);
+				double asce = cStyle.font().ascent(fontSize) * scaleV + offset;
+				double desc = cStyle.font().descent(fontSize) * scaleV - offset;
+
+				x = line->x() + glyph->x() + glyph->width();
+				y1 = line->y() + line->ascent() - asce;
+				y2 = line->y() + line->ascent() - desc;
+			}
+			else
+			{
+				// draw the cursor at the end of last line.
+				x = line->x() + glyph->x() + glyph->width();
+				y1 = line->y();
+				y2 = y1 + line->height();
+			}
+			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;
+}




More information about the scribus-commit mailing list