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(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 #include +#include +#include + #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(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 +#include +} + +#include +#include + +#include +#include + +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 //#include #include //#include #include #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 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 >& 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;