1 /*
2  For general Scribus (>=1.3.2) copyright and licensing information please refer
3  to the COPYING file provided with the program. Following this notice may exist
4  a copyright and/or license notice that predates the release of Scribus 1.3.2
5  for which a new license (GPL+exception) is in place.
6  */
7 
8 #include "shapedtext.h"
9 
10 #include <QSharedData>
11 
12 
13 class ShapedTextImplementation : QSharedData
14 {
15 
16 public:
ShapedTextImplementation(ITextSource * src,int firstChar,int lastChar,ITextContext * ctx)17 	ShapedTextImplementation(ITextSource* src, int firstChar, int lastChar, ITextContext* ctx) : m_needsContext(false), m_source(src), m_context(ctx)
18 	{
19 		m_firstChar = firstChar;
20 		m_lastChar = lastChar < 0? src->length() - 1 : lastChar;
21 	}
22 
ShapedTextImplementation(const ShapedTextImplementation & o)23 	ShapedTextImplementation(const ShapedTextImplementation& o) : m_needsContext(o.m_needsContext), m_source(o.m_source), m_context(o.m_context), m_firstChar(o.m_firstChar), m_lastChar(o.m_lastChar),m_glyphs(o.m_glyphs)
24 	{}
25 
26 
27 	bool m_needsContext;
28 	const ITextSource* m_source;
29 	const ITextContext* m_context;
30 	int m_firstChar;
31 	int m_lastChar;
32 	QList<GlyphCluster> m_glyphs;
33 
34 	/** only possible if it also cleanly splits the textsource */
canSplit(int charPos) const35 	bool canSplit(int charPos) const
36 	{
37 		return splitPosition(charPos) >= 0;
38 	}
39 
split(int charPos)40 	ShapedText split(int charPos)
41 	{
42 		int pos = splitPosition(charPos);
43 		this->m_lastChar = charPos - 1;
44 		this->m_glyphs.erase(this->m_glyphs.begin() + pos, this->m_glyphs.end());
45 
46 		ShapedTextImplementation* result = new ShapedTextImplementation(*this);
47 		result->m_firstChar = charPos;
48 		result->m_glyphs.erase(result->m_glyphs.begin(), result->m_glyphs.begin() + pos);
49 		return ShapedText(result);
50 }
51 
52 	/** only possible if they are adjacent pieces of the same text source */
canCombine(const QSharedPointer<ShapedTextImplementation> other) const53 	bool canCombine(const QSharedPointer<ShapedTextImplementation>  other) const
54 	{
55 		return false; // TODO: implement
56 	}
57 
combine(QSharedPointer<ShapedTextImplementation> other)58 	void combine(QSharedPointer<ShapedTextImplementation>  other)
59 	{
60 		// TODO: implement
61 	}
62 
63 private:
64 
splitPosition(int charPos) const65 	int splitPosition(int charPos) const
66 	{
67 		int result = 0;
68 		while (result < m_glyphs.count() && m_glyphs[result].lastChar() < charPos)
69 			++result;
70 		for (int check = result + 1; check < m_glyphs.count(); ++check)
71 		{
72 			if (m_glyphs[check].firstChar() < charPos)
73 				return -1;
74 		}
75 		return result;
76 	}
77 };
78 
79 
80 
81 ShapedText ShapedText::Invalid = ShapedText(nullptr);
82 
isValid() const83 bool ShapedText::isValid() const
84 {
85 	return p_impl != nullptr && p_impl->m_source != nullptr;
86 }
87 
88 
ShapedText(ShapedTextImplementation * my_p_impl)89 ShapedText::ShapedText(ShapedTextImplementation* my_p_impl) : p_impl(my_p_impl) {}
ShapedText(ITextSource * src,int firstChar,int lastChar,ITextContext * ctx)90 ShapedText::ShapedText(ITextSource* src, int firstChar, int lastChar, ITextContext* ctx) : p_impl(new ShapedTextImplementation(src,firstChar,lastChar,ctx)) {}
ShapedText(const ShapedText & other)91 ShapedText::ShapedText(const ShapedText& other) : p_impl(other.p_impl) {}
92 
needsContext() const93 bool ShapedText::needsContext() const { return p_impl->m_needsContext; }
needsContext(bool b)94 void ShapedText::needsContext(bool b) { p_impl->m_needsContext = b; }
source() const95 const ITextSource* ShapedText::source() const { return p_impl->m_source; }
firstChar() const96 int ShapedText::firstChar() const { return p_impl->m_firstChar; }
lastChar() const97 int ShapedText::lastChar() const { return p_impl->m_lastChar; }
glyphs() const98 const QList<GlyphCluster>& ShapedText::glyphs() const { return p_impl->m_glyphs; }
glyphs()99 QList<GlyphCluster>& ShapedText::glyphs() { return p_impl->m_glyphs; }
100 
canSplit(int pos) const101 bool ShapedText::canSplit(int pos) const { return p_impl->canSplit(pos); }
split(int pos)102 ShapedText ShapedText::split(int pos) { return p_impl->split(pos); }
canCombine(const ShapedText & other) const103 bool ShapedText::canCombine(const ShapedText& other) const { return p_impl->canCombine(other.p_impl); }
combine(ShapedText & other)104 void ShapedText::combine(ShapedText& other) { p_impl->combine(other.p_impl); }
105 
106