Index: scribus/pageitem.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/pageitem.cpp,v
retrieving revision 1.121.2.418
diff -u -8 -p -r1.121.2.418 pageitem.cpp
--- scribus/pageitem.cpp	12 Mar 2007 15:57:39 -0000	1.121.2.418
+++ scribus/pageitem.cpp	20 Mar 2007 09:06:47 -0000
@@ -1747,16 +1747,170 @@ double PageItem::layoutGlyphs(const Char
 			layout.yadvance = layout.more->yadvance;
 	}
 	else {
 		layout.shrink();
 	}
 	return retval;
 }
 
+// the same, but character to render is retrieved from contextStringPointer
+double PageItem::layoutGlyphs(const CharStyle& style, int len, GlyphLayout& layout)
+{
+	QString chars;
+	bool otf = style.font().isOTF();
+	if(contextString[0] == 0) // We have a special char that can't be processed by libotf
+	{
+		chars = contextString[1].unicode();
+	}
+	else if(otf)
+	{
+		
+		if (contextStringPointer == 0) 
+		{
+			contextGlyphsString = style.font().otfied(contextString);
+		  //Now, we have 4 possibilities :
+		  // 1/ one glyph for one character ;
+		  // 2/ many glyphs for one character ;
+		  // 3/ one glyph for many characters ;
+		  // 4/ nothing if character was rendered in a previous case 3 call.
+		  // Too much complicated for me, I take the shorter way.
+			int ls = contextString.length();
+			int lg = contextGlyphsString.length();
+			contexLengthChange = lg - ls;
+		}
+		if (contexLengthChange < 0) // source string is longer then the rendered string
+		{
+			contexLengthChange += 1; // waiting
+			contextStringPointer = -1;
+			layout.glyph = ScFace::CONTROL_GLYPHS + SpecialChars::ZWSPACE.unicode();
+			return 0.0;
+		}
+		else if (contexLengthChange > 0) // in that case we just trust the GLyphLayout grow()
+		{
+			chars = contextGlyphsString.mid(contextStringPointer,contexLengthChange  + len);
+			contexLengthChange = 0;
+		}
+		else if(contexLengthChange == 0)
+		{
+			if(contextStringPointer == -1) contextStringPointer = 0;
+			chars = contextGlyphsString.mid(contextStringPointer,len);
+		}
+		//contextStringPointer += 1;
+	}
+	else 
+	{
+		chars = contextString.mid(contextStringPointer,len);
+	}
+	qDebug(QString("char is [%1], contextGlyphsString is [%2], contextStringPointer[%3], len [%4]").arg(chars[0].unicode()).arg(contextGlyphsString).arg(contextStringPointer).arg(len));
+	double retval = 0.0;
+	double asce = style.font().ascent(style.fontSize() / 10.0);
+	int chst = style.effects() & 1919;
+	if (chars[0] == SpecialChars::ZWSPACE ||
+		   chars[0] == SpecialChars::ZWNBSPACE ||
+		   chars[0] == SpecialChars::NBSPACE ||
+		   chars[0] == SpecialChars::NBHYPHEN ||
+		   chars[0] == SpecialChars::SHYPHEN ||
+		   chars[0] == SpecialChars::PARSEP ||
+		   chars[0] == SpecialChars::COLBREAK ||
+		   chars[0] == SpecialChars::LINEBREAK ||
+		   chars[0] == SpecialChars::FRAMEBREAK ||
+		   chars[0] == SpecialChars::TAB)
+	{
+		layout.glyph = ScFace::CONTROL_GLYPHS + chars[0].unicode();
+	}
+	else 
+	{
+		layout.glyph = style.font().char2CMap(chars[0].unicode()); //otf comment : here we assume that the proper pair is in the c_Map cache
+	}
+	
+	double tracking = 0.0;
+	if ( (style.effects() & ScStyle_StartOfLine) == 0)
+		tracking = style.fontSize() * style.tracking() / 10000.0;
+
+	layout.xoffset = tracking;
+	layout.yoffset = 0;
+	if (chst != ScStyle_Default)
+	{
+		if (chst & ScStyle_Superscript)
+		{
+			retval -= asce * m_Doc->typographicSettings.valueSuperScript / 100.0;
+			layout.yoffset -= asce * m_Doc->typographicSettings.valueSuperScript / 100.0;
+			layout.scaleV = layout.scaleH = QMAX(m_Doc->typographicSettings.scalingSuperScript / 100.0, 10.0 / style.fontSize());
+		}
+		else if (chst & ScStyle_Subscript)
+		{
+			retval += asce * m_Doc->typographicSettings.valueSubScript / 100.0;
+			layout.yoffset += asce * m_Doc->typographicSettings.valueSubScript / 100.0;
+			layout.scaleV = layout.scaleH = QMAX(m_Doc->typographicSettings.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;
+		if (chst & ScStyle_AllCaps)
+		{
+			layout.glyph = style.font().char2CMap(chars[0].upper().unicode());
+		}
+		if (chst & ScStyle_SmallCaps)
+		{
+			
+			double smallcapsScale = m_Doc->typographicSettings.valueSmallCaps / 100.0;
+			QChar uc = chars[0].upper();
+			if (uc != chars[0])
+			{
+				layout.glyph = style.font().char2CMap(chars[0].upper().unicode());
+				layout.scaleV *= smallcapsScale;
+				layout.scaleH *= smallcapsScale;
+			}
+		}
+	}
+	else {
+		layout.scaleH = style.scaleH() / 1000.0;
+		layout.scaleV = style.scaleV() / 1000.0;
+	}	
+	
+	if (layout.glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBSPACE.unicode())) {
+		uint replGlyph = style.font().char2CMap(QChar(' '));
+		layout.xadvance = style.font().glyphWidth(replGlyph, style.fontSize() / 10) * layout.scaleH;
+		layout.yadvance = style.font().glyphBBox(replGlyph, style.fontSize() / 10).ascent * layout.scaleV;
+	}
+	else if (layout.glyph == (ScFace::CONTROL_GLYPHS + SpecialChars::NBHYPHEN.unicode())) {
+		uint replGlyph = style.font().char2CMap(QChar('-'));
+		layout.xadvance = style.font().glyphWidth(replGlyph, style.fontSize() / 10) * layout.scaleH;
+		layout.yadvance = style.font().glyphBBox(replGlyph, style.fontSize() / 10).ascent * layout.scaleV;
+	}
+	else if (layout.glyph >= ScFace::CONTROL_GLYPHS) {
+		layout.xadvance = 0;
+		layout.yadvance = 0;
+	}
+	else {
+		layout.xadvance = style.font().glyphWidth(layout.glyph, style.fontSize() / 10) * layout.scaleH;
+		layout.yadvance = style.font().glyphBBox(layout.glyph, style.fontSize() / 10).ascent * layout.scaleV;
+	}
+	if (layout.xadvance > 0)
+		layout.xadvance += tracking;
+
+	if (chars.length() > 1) {
+		layout.grow();
+		contextStringPointer += 1;
+		layoutGlyphs(style, chars.length()-1, *layout.more);
+		layout.xadvance += style.font().glyphKerning(layout.glyph, layout.more->glyph, style.fontSize() / 10) * layout.scaleH;
+		if (layout.more->yadvance > layout.yadvance)
+			layout.yadvance = layout.more->yadvance;
+	}
+	else {
+		contextStringPointer += 1;
+		layout.shrink();
+	}
+	
+	return retval;
+}
+
 void PageItem::drawGlyphs(ScPainter *p, const CharStyle& style, GlyphLayout& glyphs)
 {
 	uint glyph = glyphs.glyph;
 	if ((m_Doc->guidesSettings.showControls) && 
 		(glyph == style.font().char2CMap(QChar(' ')) || glyph >=  ScFace::CONTROL_GLYPHS))
 	{
 		bool stroke = false;
 		if (glyph >=  ScFace::CONTROL_GLYPHS)
Index: scribus/pageitem.h
===================================================================
RCS file: /cvs/Scribus/scribus/pageitem.h,v
retrieving revision 1.26.2.181
diff -u -8 -p -r1.26.2.181 pageitem.h
--- scribus/pageitem.h	6 Mar 2007 21:32:15 -0000	1.26.2.181
+++ scribus/pageitem.h	20 Mar 2007 09:06:49 -0000
@@ -289,16 +289,17 @@ public:
 	/// returns the style at the current charpos
 	const ParagraphStyle& currentStyle() const;
 	/// returns the style at the current charpos
 	ParagraphStyle& changeCurrentStyle();
 	/// returns the style at the current charpos
 	const CharStyle& currentCharStyle() const;
 	// deprecated:
 	double layoutGlyphs(const CharStyle& style, const QString chars, GlyphLayout& layout);
+	double layoutGlyphs(const CharStyle& style, int len, GlyphLayout& layout);
 	void SetFarbe(QColor *tmp, QString farbe, int shad);
 	void drawGlyphs(ScPainter *p, const CharStyle& style, GlyphLayout& glyphs );
 	void DrawPolyL(QPainter *p, QPointArray pts);
 	QString ExpandToken(uint base);
 	
 	bool AutoName;	
 	double gXpos;
 	double gYpos;
@@ -1208,16 +1209,22 @@ public:
 	
 	/** Darstellungsart Bild/Titel */
 	bool PicArt;
 	
 	 /** Line width */
 	double m_lineWidth;
 	double Oldm_lineWidth;
 	
+	/** Context String */
+	QString contextString;
+	QString contextGlyphsString;
+	int contextStringPointer;
+	int contexLengthChange;
+	
 signals:
 	//Frame signals
 	void myself(PageItem *);
 	void frameType(int);   // not related to Frametype but to m_itemIype :-/
 	void position(double, double); //X,Y
 	void widthAndHeight(double, double); //W,H
 	void rotation(double); //Degrees rotation	
 	void colors(QString, QString, int, int); //lineColor, fillColor, lineShade, fillShade
Index: scribus/pageitem_textframe.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/Attic/pageitem_textframe.cpp,v
retrieving revision 1.1.2.152
diff -u -8 -p -r1.1.2.152 pageitem_textframe.cpp
--- scribus/pageitem_textframe.cpp	11 Mar 2007 15:12:07 -0000	1.1.2.152
+++ scribus/pageitem_textframe.cpp	20 Mar 2007 09:06:55 -0000
@@ -537,17 +537,47 @@ static double opticalRightMargin(const S
 			rightCorr = itemText.charStyle(b).font().charWidth(chr, chs / 10.0);
 			rightCorr -= itemText.charStyle(b).font().charWidth(chr, chs / 10.0, QChar('.'));
 		}
 		return rightCorr;
 	}
 	return 0.0;
 }
 
+// TEST
+static void prepareText(StoryText& itemText, int begin, int end)
+{
+	/* here, it could be possible to send text to a substitution engine */
+	/* example (pseudopseudocode):
+	QString final = itemText.charStyle(i)->font->subtitute(itemText.text(begin , end - begin), itemText.charStyle(i)->font->sub_features_set());
+	
+	for(int i = begin, i <= end ; ++i)
+	{
+	if(final.at(i)) itemText.item(i)->ch = final.at(i);
+	else itemText.remove(i);
+	}
+	
+	 
+	*/
+	
+// 	if(itemText.charStyle(begin).font().isOTF())
+// 	{
+// 		QString os = itemText.text(begin, end - begin );
+// 		QString ns = itemText.charStyle(begin).font().otfSub(os);
+// 		if(os != ns)
+// 		{
+// 			CharStyle back = itemText.charStyle(begin);
+// 			itemText.removeChars(begin , end);
+// 			itemText.insertChars( begin  ,  ns );
+// 			itemText.setCharStyle(begin , ns.length() , back );
+// 		}
+// 	}
 
+}
+// ENDTEST
 void PageItem_TextFrame::layout() 
 {
 	
 	if (BackBox != NULL && BackBox->invalid) {
 //		qDebug("textframe: len=%d, going back", itemText.length());
 		invalid = false;
 		PageItem_TextFrame* prevInChain = dynamic_cast<PageItem_TextFrame*>(BackBox);
 		if (!prevInChain)
@@ -671,18 +701,93 @@ void PageItem_TextFrame::layout() 
 		{
 			desc2 = -itemText.defaultStyle().charStyle().font().descent(itemText.defaultStyle().charStyle().fontSize() / 10.0);
 			current.yPos = itemText.defaultStyle().lineSpacing() + extra.Top+lineCorr-desc2;
 		}
 		current.startLine(firstInFrame());
 		outs = false;
 		OFs = 0;
 		MaxChars = 0;
+		//TEST
+// 		CharStyle control_charstyle;
+// 		int begin_prepare;
+// 		int end_prepare =  begin_prepare = firstInFrame();
+// 		for (int a = firstInFrame(); a < itemText.length(); ++a)
+// 		{
+// 			if(a == begin_prepare)
+// 			{
+// 				control_charstyle = itemText.charStyle(a);
+// 				continue;
+// 			}
+// 			if(control_charstyle != itemText.charStyle(a))
+// 			{
+// 				end_prepare = a-1;
+// 				prepareText(itemText, begin_prepare, end_prepare);
+// 				begin_prepare = end_prepare = a;
+// 				control_charstyle = itemText.charStyle(a);
+// 				continue;
+// 			}
+// 			if(a  == itemText.length() -1)
+// 			{
+// 				prepareText(itemText, begin_prepare, a + 1);
+// 				break;
+// 			}
+// 			++end_prepare;
+// 		}
+		// ENDTEST	
+		// BIGLOOP
+		int contextrest = 0;
+		int sccontrol;
 		for (int a = firstInFrame(); a < itemText.length(); ++a)
 		{
+			// here we set the context string
+			if(contextrest == 0)
+			{
+				contextString = "";
+				sccontrol = 0;
+				for(int ctsg = a; ctsg < itemText.length(); ++ctsg)
+				{
+					
+					QString contmp = ExpandToken(ctsg);
+					if(contmp[0] == SpecialChars::ZWSPACE ||
+								contmp[0] == SpecialChars::ZWNBSPACE ||
+								contmp[0] == SpecialChars::NBSPACE ||
+								contmp[0] == SpecialChars::NBHYPHEN ||
+								contmp[0] == SpecialChars::SHYPHEN ||
+								contmp[0] == SpecialChars::PARSEP ||
+								contmp[0] == SpecialChars::COLBREAK ||
+								contmp[0] == SpecialChars::LINEBREAK ||
+								contmp[0] == SpecialChars::FRAMEBREAK ||
+								contmp[0] == SpecialChars::TAB || 
+								contmp[0] == SpecialChars::BLANK)
+					{
+						if(sccontrol > 0)
+						{
+							break;
+						}
+						else
+						{
+						contextString += QChar(0) ;
+						contextString += contmp[0].unicode();
+						break;
+						}
+					}
+					else
+					{
+						sccontrol += 1;
+						contextString += contmp;
+					}
+				}
+				contextrest = (sccontrol == 0 ? 1 : contextString.length());// we send special char one by one
+				contextStringPointer = 0;
+				qDebug(QString("contextrest = %1 and context string is \"%2\"").arg(contextrest).arg(contextString));
+			}
+			--contextrest;
+
+			
 			hl = itemText.item(a);
 			if (a > 0 && itemText.text(a-1) == SpecialChars::PARSEP)
 				style = itemText.paragraphStyle(a);
 			if (current.itemsInLine == 0)
 				opticalMargins = style.opticalMargins();
 			
 //			qDebug(QString("style pos %1: %2 (%3)").arg(a).arg(style.alignment()).arg(style.parent()));
 			const CharStyle& charStyle = itemText.charStyle(a);
@@ -857,17 +962,19 @@ void PageItem_TextFrame::layout() 
 				kernVal = 0;
 			}
 			else
 			{
 				kernVal = 0; // chs * charStyle.tracking() / 10000.0;
 				itemText.item(a)->setEffects(itemText.item(a)->effects() & ~ScStyle_StartOfLine);
 			}
 			hl->glyph.yadvance = 0;
-			oldCurY = layoutGlyphs(*hl, chstr, hl->glyph);
+			//qDebug(QString("sending [%1] to layoutGlyphs()").arg(chstr));
+			oldCurY = layoutGlyphs(*hl, chstr.length(), hl->glyph);
+			//oldCurY = layoutGlyphs(*hl, chstr, hl->glyph);
 			// find out width of char
 			if ((hl->ch == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
 				wide = hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth();
 			else
 			{
 /*				if (a+1 < itemText.length())
 				{
 						chstr3 = itemText.text(a+1);
Index: scribus/fonts/CMakeLists.txt
===================================================================
RCS file: /cvs/Scribus/scribus/fonts/Attic/CMakeLists.txt,v
retrieving revision 1.1.2.1
diff -u -8 -p -r1.1.2.1 CMakeLists.txt
--- scribus/fonts/CMakeLists.txt	23 Jul 2006 12:07:47 -0000	1.1.2.1
+++ scribus/fonts/CMakeLists.txt	20 Mar 2007 09:06:58 -0000
@@ -5,12 +5,24 @@ ${CMAKE_SOURCE_DIR}/scribus
 
 
 SET(SCRIBUS_FONTS_LIB_SOURCES
 scface.cpp
 ftface.cpp
 scface_ps.cpp
 scface_ttf.cpp
 scfontmetrics.cpp
+myotf.cpp
 )
 
+SET(OTF_DIR  ${CMAKE_MODULE_PATH})
+FIND_PACKAGE(OTF REQUIRED)
+IF(OTF_FOUND)
+  SET(HAVE_OTF 1)
+  MESSAGE("LIBOTF Library found")
+ELSE(OTF_FOUND)
+  MESSAGE(FATAL_ERROR "Could not find the libOtf Library")
+ENDIF(OTF_FOUND)
+
+LINK_LIBRARIES ( ${OTF_LIBRARIES})
+
 SET(SCRIBUS_FONTS_LIB "scribus_fonts_lib")
 ADD_LIBRARY(${SCRIBUS_FONTS_LIB} STATIC ${SCRIBUS_FONTS_LIB_SOURCES})
Index: scribus/fonts/ftface.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/fonts/Attic/ftface.cpp,v
retrieving revision 1.1.2.9
diff -u -8 -p -r1.1.2.9 ftface.cpp
--- scribus/fonts/ftface.cpp	11 Jan 2007 15:29:46 -0000	1.1.2.9
+++ scribus/fonts/ftface.cpp	20 Mar 2007 09:06:59 -0000
@@ -2,16 +2,19 @@
 #include "fonts/ftface.h"
 
 #include FT_OUTLINE_H
 #include FT_GLYPH_H
 
 #include <qobject.h>
 #include <qfile.h>
 
+#include <qmessagebox.h>
+#include <qinputdialog.h>
+
 #include "scfonts.h"
 #include "fonts/scfontmetrics.h"
 
 // static:
 FT_Library FtFace::library = NULL;
 
 /*****
    ScFace lifecycle:  unchecked -> loaded -> glyphs checked
@@ -136,36 +139,104 @@ void FtFace::load() const
 		++goodGlyph;
 		if (m_face->glyph->format == FT_GLYPH_FORMAT_PLOTTER)
 			const_cast<FtFace*>(this)->isStroked = true;
 		charcode = FT_Get_Next_Char( m_face, charcode, &gindex );
 	}
 	if (invalidGlyph > 0) {
 		status = ScFace::BROKENGLYPHS;
 	}
+	//TEST libotf
+	if(typeCode == ScFace::OTF)
+	{
+		_otf = new myotf(QFile::encodeName(fontFile));
+		bool ok;
+		QMessageBox::information( 0, "Scribus",
+					  "You choose to use an OpenType Font file.\n"
+							  "You have to set parameters for this font." );
+		_otf->set_table("GSUB");
+		QStringList choice = _otf->get_scripts();
+		if(choice.count() > 1)
+		{
+			otfScript = QInputDialog::getItem("Scribus :: otf", "Select the script ", choice, 1, FALSE, &ok );
+			_otf->set_script(otfScript);
+		}
+		else
+		{
+			otfScript = choice[0];
+			_otf->set_script(otfScript);
+		}
+		choice = _otf->get_langs();
+		choice.append("default");
+		if(choice.count() > 1)
+		{
+			otfLang = QInputDialog::getItem("Scribus :: otf", QString("Select the language for script %1").arg(otfScript), choice, 1, FALSE, &ok );
+			_otf->set_lang(otfLang);
+		}
+		else
+		{
+			otfLang = choice[0];
+			_otf->set_lang(otfLang);
+		}
+		choice =_otf->get_features();
+		QString ft;
+		while(QMessageBox::question(0,"Scribus","Want to choose features for GSUB ?",QMessageBox::Ok,QMessageBox::No,QMessageBox::NoButton) == QMessageBox::Ok)
+		{
+			ft = QInputDialog::getItem("Scribus :: otf", QString("Select feature for lang  %1").arg(otfLang), choice, 1, FALSE, &ok );
+			if(ok)
+			otfSubFeatures.append(ft);
+		}
+		_otf->set_table("GPOS");
+		_otf->set_script(otfScript);
+		_otf->set_lang(otfLang);
+		choice =_otf->get_features();
+		while(QMessageBox::question(0,"Scribus","Want to choose features for GPOS ?",QMessageBox::Ok,QMessageBox::No,QMessageBox::NoButton) == QMessageBox::Ok)
+		{
+			ft = QInputDialog::getItem("Scribus :: otf", QString("Select feature for lang %1").arg(otfLang), choice, 1, FALSE, &ok );
+			if(ok)
+			otfPosFeatures.append(ft);
+		}
+		//here we make otf init "by hand" and it's just intended to work with the MinionPro shipped with adobe reader
+// 		otfScript = "latn";
+// 		otfLang = "default";
+// 		otfSubFeatures.append("liga");
+// 		otfSubFeatures.append("dlig");
+// 		otfSubFeatures.append("onum");
+// 		otfPosFeatures.append("kern");
+// 		otfPosFeatures.append("cpsp");
+		
+	}
 }
 
 
 void FtFace::unload() const
 {
 	if (m_face) {
 		FT_Done_Face( m_face );
 		m_face = NULL;
 	}
 	// clear caches
+	if(_otf) delete _otf;
 	ScFaceData::unload();
 }
 
 
 uint FtFace::char2CMap(QChar ch) const
 {
-	// FIXME use cMap cache
-	FT_Face face = ftFace();
-	uint gl = FT_Get_Char_Index(face, ch.unicode());
-	return gl;
+	if(m_cMap.contains(ch.unicode()))
+	{
+		return m_cMap[ch.unicode()];
+	}
+	else
+	{
+		FT_Face face = ftFace();
+		uint gl = FT_Get_Char_Index(face, ch.unicode());
+		m_cMap.insert(ch.unicode(), gl);
+		return gl;
+	}
 }
 
 
 void FtFace::loadGlyph(uint gl) const
 {
 	if (m_glyphWidth.contains(gl))
 		return;
 	
@@ -307,9 +378,27 @@ void FtFace::RawData(QByteArray & bb) co
 //	 if (showFontInformation)
 	 {
 		 QFile f(fontFile);
 		 qDebug(QObject::tr("RawData for Font %1(%2): size=%3 filesize=%4").arg(fontFile).arg(faceIndex).arg(bb.size()).arg(f.size()));
 	 }
 */	 
 }
 
+QString FtFace::otfied(QString s) const
+{
+	if(typeCode == ScFace::OTF)
+	{
+		int nbg = _otf->procstring(s,otfScript,otfLang,otfSubFeatures,otfPosFeatures);
+		QString newstring;
+		for (int i = 0; i < nbg ; ++i)
+		{
+			newstring += QChar(_otf->unicode(  _otf->otfString()->glyphs[i].glyph_id ));
+			m_cMap.insert(_otf->unicode( _otf->otfString()->glyphs[i].glyph_id), _otf->otfString()->glyphs[i].glyph_id);
+		}
+		
+		
+		qDebug(QString("oldstring is \"%1\" and new string os \"%2\"").arg(s).arg(newstring));
+		return newstring;
 
+	}
+	return s;
+}
Index: scribus/fonts/ftface.h
===================================================================
RCS file: /cvs/Scribus/scribus/fonts/Attic/ftface.h,v
retrieving revision 1.1.2.5
diff -u -8 -p -r1.1.2.5 ftface.h
--- scribus/fonts/ftface.h	1 Sep 2006 23:55:18 -0000	1.1.2.5
+++ scribus/fonts/ftface.h	20 Mar 2007 09:06:59 -0000
@@ -107,11 +107,20 @@ protected:
 	mutable double m_height;
 	mutable double m_xHeight;
 	mutable double m_capHeight;
 	mutable double m_maxAdvanceWidth;
 	mutable double m_underlinePos;
 	mutable double m_strikeoutPos;
 	mutable double m_strokeWidth;
 	
+	//TEST libotf
+	public:
+		mutable QStringList otfSubFeatures;
+		mutable QStringList otfPosFeatures;
+		mutable QString otfScript;
+		mutable QString otfLang;
+		QString otfied(QString s) const ;
+		mutable myotf * _otf;
+	
 };
 
 #endif
Index: scribus/fonts/myotf.cpp
===================================================================
RCS file: scribus/fonts/myotf.cpp
diff -N scribus/fonts/myotf.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ scribus/fonts/myotf.cpp	20 Mar 2007 09:07:00 -0000
@@ -0,0 +1,596 @@
+/* un test de libotf mer18jan */
+
+
+#include "myotf.h"
+
+
+
+void
+myotf::set_subalt (bool b)
+{
+  subAlt = b;
+}
+
+int
+myotf::get_glyph_used()
+{
+	return mys.used;
+}
+
+myotf::myotf (QString n)
+{
+  nom = n;
+  my = OTF_open ((char*)nom.ascii());
+  subAlt = false;
+  glyphAlloc = false;
+  if (OTF_get_table (my, "head") == 0)
+    head = 1;
+  else
+    head = 0;
+  if (OTF_get_table (my, "name") == 0)
+    name = 1;
+  else
+    name = 0;
+  if (OTF_get_table (my, "cmap") == 0)
+    cmap = 1;
+  else
+    cmap = 0;
+  if (OTF_get_table (my, "GDEF") == 0)
+    GDEF = 1;
+  else
+    GDEF = 0;
+  if (OTF_get_table (my, "GSUB") == 0)
+    GSUB = 1;
+  else
+    GSUB = 0;
+  if (OTF_get_table (my, "GPOS") == 0)
+    GPOS = 1;
+  else
+    GPOS = 0;
+  // if (GSUB){ OTF_get_scripts (my, 1); OTF_get_features (my, 1);}
+  // if (GPOS){ OTF_get_scripts (my, 0); OTF_get_features (my, 0);}
+
+/*
+  std::cout << "head : " << head << "\n";
+  std::cout << "name : " << name << "\n";
+  std::cout << "cmap : " << cmap << "\n";
+  std::cout << "GDEF : " << GDEF << "\n";
+  std::cout << "GSUB : " << GSUB << "\n";
+  std::cout << "GPOS : " << GPOS << "\n";
+*/
+}
+
+myotf::~myotf ()
+{
+  if (glyphAlloc)
+    free (mys.glyphs);
+  OTF_close (my);
+}
+
+int
+myotf::procstring (QString s)
+{
+	int n = s.length();
+  if (glyphAlloc)
+    free (mys.glyphs);
+  mys.size = n;
+  mys.used = n;
+  mys.glyphs = (OTF_Glyph *) calloc (n , sizeof (OTF_Glyph));
+  glyphAlloc = true;
+  OTF_error = 0;
+  for (int i = 0; i < n; i++)
+    {
+	    mys.glyphs[i].c =  s[i].unicode();
+      mys.glyphs[i].glyph_id = 0;
+    }
+  
+  if(OTF_drive_cmap (my, &mys))OTF_perror("drive_cmap ") ;
+  
+  for (int i = 0; i < mys.used; i++)
+    {
+      std::cout << hex << setw(4) << setfill('0') << OTF_get_unicode( my, mys.glyphs[i].glyph_id) << " : " << dec;
+    }
+  cout << "\n";
+
+  QString fe;
+  for (QStringList::iterator ife = curFeatures.begin ();
+       ife != curFeatures.end (); ife++)
+    {
+      fe += *ife;
+      fe += ',';
+    }
+  //*(fe.end()) = NULL ;
+
+    char *argsc =  (char *) curScriptName.ascii();
+    char *argla =  (char *) curLangName.ascii();
+    char *argfe =  (char *) fe.ascii();
+
+  if (GDEF) 
+	  {if(OTF_drive_gdef(my, &mys) != 0 )OTF_perror("drive_GDEF ");}
+  
+  if (curTable == "GPOS")
+  {
+    if(OTF_drive_gpos (my, &mys, argsc, argla, argfe))OTF_perror("drive_GPOS");
+    OTF_perror("force(drive_GPOS)");
+    for( int n = 0; n < mys.used ; n++)
+	    get_position(n);
+  }
+
+  if (curTable == "GSUB")
+  {
+	  if (!subAlt)
+      {
+	if(OTF_drive_gsub (my, &mys, argsc, argla, argfe))OTF_perror("drive_GSUB");
+      }
+    else
+      {
+	if(OTF_drive_gsub_alternate (my, &mys, argsc, argla, argfe))OTF_perror("drive_GSUB_alt");
+
+      }
+  }
+  
+  
+  for (int i = 0; i < mys.used; i++)
+    {
+      std::cout << hex << setw(4) << setfill('0') << OTF_get_unicode (my , mys.glyphs[i].glyph_id ) << " : " << dec ;
+    	std::cout << '['<<(char)OTF_get_unicode (my , mys.glyphs[i].glyph_id )<<']'  ;
+    }
+  cout << "\n";
+
+
+  
+  return mys.used;
+}
+
+int
+		myotf::procstring (QString s,QString script, QString lang, QStringList gsub, QStringList gpos)
+{
+	int n = s.length();
+	if (glyphAlloc)
+		free (mys.glyphs);
+	mys.size = n;
+	mys.used = n;
+	mys.glyphs = (OTF_Glyph *) calloc (n , sizeof (OTF_Glyph));
+	glyphAlloc = true;
+	OTF_error = 0;
+	for (int i = 0; i < n; i++)
+	{
+		mys.glyphs[i].c =  s[i].unicode();
+		mys.glyphs[i].glyph_id = 0;
+	}
+  
+	if(OTF_drive_cmap (my, &mys))OTF_perror("drive_cmap ") ;
+  
+// 	for (int i = 0; i < mys.used; i++)
+// 	{
+// 		std::cout << hex << setw(4) << setfill('0') << OTF_get_unicode( my, mys.glyphs[i].glyph_id) << " : " << dec;
+// 	}
+// 	cout << "\n";
+
+	QString gsubfe;
+	for (QStringList::iterator ife = gsub.begin ();
+		    ife != gsub.end (); ife++)
+	{
+		gsubfe += *ife;
+		gsubfe += ',';
+	}
+	QString gposfe;
+	for (QStringList::iterator ife = gpos.begin ();
+		    ife != gpos.end (); ife++)
+	{
+		gposfe += *ife;
+		gposfe += ',';
+	}
+  //*(fe.end()) = NULL ;
+
+	char *argsc =  (char *) script.ascii();
+	char *argla =  (char *) lang.ascii();
+	char *arggsubfe =  (char *) gsubfe.ascii();
+	char *arggposfe =  (char *) gposfe.ascii();
+
+	if (GDEF) 
+	{
+		if(OTF_drive_gdef(my, &mys) != 0 )OTF_perror("drive_GDEF ");
+	}
+	if (GSUB)
+	{
+		if(OTF_drive_gsub(my, &mys, argsc, argla, arggsubfe))OTF_perror("drive_GSUB");
+	}
+	if (GPOS)
+	{
+		if(OTF_drive_gpos(my, &mys, argsc, argla, arggposfe))OTF_perror("drive_GPOS");
+	}
+
+// 	for (int i = 0; i < mys.used; i++)
+// 	{
+// 		std::cout << hex << setw(4) << setfill('0') << OTF_get_unicode (my , mys.glyphs[i].glyph_id ) << " : " << dec ;
+// 		std::cout << '['<<(char)OTF_get_unicode (my , mys.glyphs[i].glyph_id )<<']'  ;
+// 	}
+// 	cout << "\n";
+// 
+
+  
+	return mys.used;
+}
+
+int
+myotf::procstring()
+{
+ QString fe;
+  for (QStringList::iterator ife = curFeatures.begin ();
+       ife != curFeatures.end (); ife++)
+    {
+      fe += *ife;
+      fe += ',';
+    }
+  //*(fe.end()) = NULL ;
+    char *argsc =  (char *) curScriptName.ascii();
+    char *argla =  (char *) curLangName.ascii();
+    char *argfe =  (char *) fe.ascii();
+
+  if (curTable == "GPOS")
+  {
+    OTF_drive_gpos (my, &mys, argsc, argla, argfe);
+    for( int n = 0; n < mys.used ; n++)
+	    get_position(n);
+  }
+
+  if (curTable == "GSUB")
+    if (!subAlt)
+      {
+	OTF_drive_gsub (my, &mys, argsc, argla, argfe);
+      }
+    else
+      {
+	OTF_drive_gsub_alternate (my, &mys, argsc, argla, argfe);
+
+      }
+  for (int i = 0; i < mys.used; i++)
+    {
+      std::cout << mys.glyphs[i].glyph_id << " : ";
+    }
+  cout << "\n";
+
+
+  
+  return mys.used;
+}
+
+
+
+
+	
+QStringList myotf::get_tables ()
+{
+  QStringList ret;
+
+  if (GDEF)
+    ret.insert (ret.end (), "GDEF");
+  if (GPOS)
+    ret.insert (ret.end (), "GPOS");
+  if (GSUB)
+    ret.insert (ret.end (), "GSUB");
+
+  return ret;
+}
+
+void
+myotf::set_table (QString s)
+{
+  curTable = s;
+}
+
+QStringList myotf::get_scripts ()
+{
+  QStringList ret;
+  char
+    aa[5];
+  if (curTable == "GSUB")
+    {
+      int
+	ns = my->gsub->ScriptList.ScriptCount;
+      char *
+	a = aa;
+      std::
+	cout << "Il y a " << ns << " systèmes d'écriture dans cette fonte.\n";
+      for (int i = 0; i < ns; i++)
+	{
+	  OTF_tag_name (my->gsub->ScriptList.Script[i].ScriptTag, a);
+	  std::cout << a;
+	  std::cout << "\n";
+	  ret.insert (ret.end (), a);
+	}
+    }
+  if (curTable == "GPOS")
+    {
+      int
+	ns = my->gpos->ScriptList.ScriptCount;
+      char *
+	a = aa;
+      std::
+	cout << "Il y a " << ns << " systèmes d'écriture dans cette fonte.\n";
+      for (int i = 0; i < ns; i++)
+	{
+	  OTF_tag_name (my->gpos->ScriptList.Script[i].ScriptTag, a);
+	  std::cout << a;
+	  std::cout << "\n";
+	  ret.insert (ret.end (), a);
+	}
+    }
+  return ret;
+
+}
+
+void
+myotf::set_script (QString s)
+{
+  char a[5];
+  if (curTable == "GPOS")
+    {
+      for (int i = 0; i < my->gpos->ScriptList.ScriptCount; i++)
+	{
+	  OTF_tag_name (my->gpos->ScriptList.Script[i].ScriptTag, a);
+	  if (a == s)
+	    curScript = i;
+	}
+    }
+  if (curTable == "GSUB")
+    {
+      for (int i = 0; i < my->gsub->ScriptList.ScriptCount; i++)
+	{
+	  OTF_tag_name (my->gsub->ScriptList.Script[i].ScriptTag, a);
+	  if (a == s)
+	    curScript = i;
+	}
+    }
+  curScriptName = s;
+}
+
+
+QStringList myotf::get_langs ()
+{
+  QStringList ret;
+  char
+    a[5];
+  if (curTable == "GPOS")
+    {
+      int
+	nl = my->gpos->ScriptList.Script[curScript].LangSysCount;
+      cout << "Il y a là " << nl << " langues" << "\n";
+      for (int i = 0; i < nl; i++)
+	{
+	  OTF_tag_name (my->gpos->ScriptList.Script[curScript].
+			LangSysRecord[i].LangSysTag, a);
+	  std::cout << a;
+	  std::cout << "\n";
+	  ret.insert (ret.end (), a);
+	}
+    }
+  if (curTable == "GSUB")
+    {
+      int
+	nl = my->gsub->ScriptList.Script[curScript].LangSysCount;
+      cout << "Il y a là " << nl << " langues" << "\n";
+      for (int i = 0; i < nl; i++)
+	{
+	  OTF_tag_name (my->gsub->ScriptList.Script[curScript].
+			LangSysRecord[i].LangSysTag, a);
+	  std::cout << a;
+	  std::cout << "\n";
+	  ret.insert (ret.end (), a);
+	}
+    }
+
+  return ret;
+}
+
+void
+myotf::set_lang (QString s)
+{
+  if (s == "default")
+    {
+      curLangName = "dflt";
+      curLang = -1;
+      return;
+    }
+
+  char a[5];
+  if (curTable == "GPOS")
+    {
+      for (int i = 0; i < my->gpos->ScriptList.Script[curScript].LangSysCount;
+	   i++)
+	{
+	  OTF_tag_name (my->gpos->ScriptList.Script[curScript].
+			LangSysRecord[i].LangSysTag, a);
+	  if (a == s)
+	    curLang = i;
+	}
+    }
+  if (curTable == "GSUB")
+    {
+      for (int i = 0; i < my->gsub->ScriptList.Script[curScript].LangSysCount;
+	   i++)
+	{
+	  OTF_tag_name (my->gsub->ScriptList.Script[curScript].
+			LangSysRecord[i].LangSysTag, a);
+	  if (a == s)
+	    curLang = i;
+	}
+    }
+  curLangName = s;
+}
+
+
+QStringList myotf::get_features ()
+{
+  QStringList ret;
+  char
+    a[10];
+  int
+    nf,
+    findex,
+    i;
+  OTF_Tag
+    ftag;
+  if (curTable == "GPOS")
+    {
+      if (curLang >= 0)
+	nf =
+	  my->gpos->ScriptList.Script[curScript].LangSys[curLang].
+	  FeatureCount;
+      else
+	nf =
+	  my->gpos->ScriptList.Script[curScript].DefaultLangSys.FeatureCount;
+      cout << "Il y a là " << nf << " fonctionnalités " << "\n";
+      for (i = 0; i < nf; i++)
+	{
+	  if (curLang >= 0)
+	    {
+	      findex =
+		my->gpos->ScriptList.Script[curScript].LangSys[curLang].
+		FeatureIndex[i];
+	      ftag = my->gpos->FeatureList.Feature[findex].FeatureTag;
+	      OTF_tag_name (ftag, a);
+	    }
+	  else
+	    {
+	      findex =
+		my->gpos->ScriptList.Script[curScript].DefaultLangSys.
+		FeatureIndex[i];
+	      ftag = my->gpos->FeatureList.Feature[findex].FeatureTag;
+	      OTF_tag_name (ftag, a);
+	    }
+	  std::cout << a;
+	  std::cout << "\n";
+	  ret.insert (ret.end (), a);
+	}
+    }
+  if (curTable == "GSUB")
+    {
+      if (curLang >= 0)
+	nf =
+	  my->gsub->ScriptList.Script[curScript].LangSys[curLang].
+	  FeatureCount;
+      else
+	nf =
+	  my->gsub->ScriptList.Script[curScript].DefaultLangSys.FeatureCount;
+
+      cout << "Il y a là " << nf << " fonctionnalités " << "\n";
+
+      for (i = 0; i < nf; i++)
+	{
+
+	  if (curLang >= 0)
+	    {
+	      findex =
+		my->gsub->ScriptList.Script[curScript].LangSys[curLang].
+		FeatureIndex[i];
+	      ftag = my->gsub->FeatureList.Feature[findex].FeatureTag;
+	      OTF_tag_name (ftag, a);
+	    }
+	  else
+	    {
+	      findex =
+		my->gsub->ScriptList.Script[curScript].DefaultLangSys.
+		FeatureIndex[i];
+	      ftag = my->gsub->FeatureList.Feature[findex].FeatureTag;
+	      OTF_tag_name (ftag, a);
+	    }
+	  std::cout << a;
+	  std::cout << "\n";
+	  ret.insert (ret.end (), a);
+	}
+    }
+  return ret;
+}
+
+void
+myotf::set_features (QStringList ls)
+{
+  curFeatures = ls;
+}
+
+
+int
+myotf::get_position_type (int ind)
+{
+  return (mys.glyphs[ind].positioning_type);
+}
+
+posglyph
+myotf::get_position(int g)
+{
+	posglyph ret;
+	int gt = get_position_type(g);
+	OTF_Glyph  og = mys.glyphs[g] ;
+	if (gt == 1)
+	{
+		for( int i= 0x00001 ; i < 0x0081 ; i*=2)
+		{
+			if(og.f.f1.format & i )
+			{
+				switch (i)
+				{
+					case 0x0001 : ret.Xposition =  og.f.f1.value->XPlacement ;
+						      break;
+					case 0x0002 : ret.Yposition =  og.f.f1.value->YPlacement ;
+						      break;
+					case 0x0004 : ret.Xadvance =  og.f.f1.value->XAdvance  ;
+						      break;
+					case 0x0008 : ret.Yadvance =  og.f.f1.value->YAdvance  ;
+						      break;
+						      default : qDebug( "Don't know how to handle OTF_DeviceTable!");
+						  break;
+				}
+			}
+		}
+	}
+	if (gt == 2)
+	{
+		for( int i= 0x0001 ; i < 0x0081 ; i*=2)
+		{
+			if(og.f.f2.format & i)
+			{
+				switch (i)
+				{
+					case 0x0001 : ret.Xposition =  og.f.f1.value->XPlacement ;
+					break;
+					case 0x0002 : ret.Yposition =  og.f.f1.value->YPlacement ;
+					break;
+					case 0x0004 : ret.Xadvance =  og.f.f1.value->XAdvance  ;
+					break;
+					case 0x0008 : ret.Yadvance =  og.f.f1.value->YAdvance  ;
+					break;
+					default : qDebug( "Don't know how to handle OTF_DeviceTable!");
+					break;
+				}
+			}
+		}
+	}
+	return ret;
+}
+
+
+
+		      
+
+// int
+// main (int ac, char **av)
+// {
+//   myotf lafonte (av[1]);
+//   QStringList feat;
+//   lafonte.set_table (av[3]);
+//   lafonte.set_script (av[4]);
+//   lafonte.set_lang (av[5]);
+// 
+//  for(int c = 6; c < ac ; c++) 
+//  {
+// 	 cout << av[c] << "\n";
+//  	feat.insert(feat.end(), av[c]);
+//  }
+// // feat.insert(feat.end(), "cpsp");
+//   lafonte.set_features (feat);
+// //  int use;
+//  lafonte.procstring (av[2]);
+//   return 0;
+// }
Index: scribus/fonts/myotf.h
===================================================================
RCS file: scribus/fonts/myotf.h
diff -N scribus/fonts/myotf.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ scribus/fonts/myotf.h	20 Mar 2007 09:07:00 -0000
@@ -0,0 +1,94 @@
+// myotf.h
+
+#ifndef WRAPLIBOTF
+#define WRAPLIBOTF
+
+
+extern "C"
+{
+#include <otf.h>
+#include <stdlib.h>
+}
+
+#include <iostream>
+#include <iomanip>
+
+#include <qstring.h>
+#include <qstringlist.h>
+
+using namespace std;
+
+struct posglyph
+{
+	double Xposition;
+	double Yposition;
+	double Xadvance;
+	double Yadvance;
+	double xadvance(){return Xadvance;}
+	double yadvance(){return Yadvance;}
+	double xposition(){return Xposition;}
+	double yposition(){return Yposition;}
+};
+
+class myotf
+{
+  QString nom;
+  
+  OTF *my;
+  OTF_GlyphString mys;
+  
+
+  
+  bool subAlt;
+  bool glyphAlloc;
+  
+  int head, name, cmap, GDEF, GSUB, GPOS;
+  
+public: 
+	OTF_GlyphString * otfString() {return &mys;}
+	int unicode(int gid){ return OTF_get_unicode(my, gid);}
+	 QString curTable;
+  int curScript, curLang;
+  QString curScriptName, curLangName;
+    QStringList curFeatures;
+    myotf (QString n);
+   ~myotf ();
+/*
+ * These members functions apply features currently set 
+ */
+  int procstring (QString );
+  int procstring ();
+  int procstring (QString s, QString script, QString lang, QStringList gsub, QStringList gpos); 
+/*
+  * These functions give access to informations contained in the fontfile
+ */
+  QStringList get_tables ();
+  QStringList   get_scripts ();
+  QStringList   get_langs ();
+  QStringList   get_features ();
+/*
+ * These allow to set up the features ( Tab -> Scr -> Lan -> Fea )
+ */
+  void set_table (QString);
+  void set_script (QString);
+  void set_lang (QString);
+  void set_features (QStringList);
+  void set_subalt (bool);
+/*
+ * I can't remember what this so important method is expected to achieve !
+ */
+  int get_position_type (int);
+  /*
+   * for the moment, it just does nothing. Because I have no idea
+   * of which sruct can be the target of this function.Nevertheless
+   * I'm clearly aware that's the key function, it's the reason why
+   * i put this apart from procstring().
+   * The argument is the number of the glyph 
+   */
+ 
+  posglyph get_position(int);
+  int get_glyph_used();
+
+};
+
+#endif
Index: scribus/fonts/scface.h
===================================================================
RCS file: /cvs/Scribus/scribus/fonts/Attic/scface.h,v
retrieving revision 1.1.2.10
diff -u -8 -p -r1.1.2.10 scface.h
--- scribus/fonts/scface.h	26 Nov 2006 13:15:19 -0000	1.1.2.10
+++ scribus/fonts/scface.h	20 Mar 2007 09:07:01 -0000
@@ -16,16 +16,19 @@ virtual:      dispatch to constituents, 
 #include <qstring.h>
 //#include <qvector.h>
 #include <qmap.h>
 //#include <qarray.h>
 #include <utility>
 
 #include "fpointarray.h"
 
+//TEST libotf
+
+#include "myotf.h"
 
 
 struct GlyphMetrics {
 	double width;
 	double ascent;
 	double descent;
 };
 
@@ -166,16 +169,19 @@ public:
 		virtual double maxAdvanceWidth(double sz)  const { return sz; }
 		virtual uint   char2CMap(QChar /*ch*/)         const { return 0; }
 		virtual double glyphKerning(uint gl1, uint gl2, double sz) const;
 		virtual QMap<QString,QString> fontDictionary(double sz=1.0) const;
 		virtual GlyphMetrics glyphBBox(uint gl, double sz) const;
 		virtual bool EmbedFont(QString &/*str*/)       const { return false; }
 		virtual void RawData(QByteArray & /*bb*/)      const {}
 		virtual bool glyphNames(QMap<uint, std::pair<QChar, QString> >& gList) const;
+		
+		virtual QString otfied(QString s) const {return s;}
+		
 
 		// these use the cache:
 		virtual double      glyphWidth(uint gl, double sz)   const;
 		virtual FPointArray glyphOutline(uint gl, double sz) const; 
 		virtual FPoint      glyphOrigin (uint gl, double sz) const;
 		
 	};
 		
@@ -351,16 +357,19 @@ public:
 	double realCharHeight(QChar ch, double sz=1.0) const { GlyphMetrics gm=glyphBBox(char2CMap(ch),sz); return gm.ascent + gm.descent; }
 	
 	/// deprecated, see glyphBBox()
 	double realCharAscent(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).ascent; }
 	
 	/// deprecated, see glyphBBox()
 	double realCharDescent(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).descent; }
 	
+	//TEST libotf
+	QString otfied (QString s) const {  return m->otfied(s); }
+
 private:
 		
 	friend class SCFonts;
 	
 	ScFace(ScFaceData* md);
 	ScFaceData* m;
 	QString replacedName;
 	QString replacedInDoc;
