Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed - got threading of sample preview to work (was a tough job)

  • Loading branch information...
commit 64edd2ad9924ec907d516f974c890a7df9170c07 1 parent e137c81
Pierre Marchand authored
2  src/CMakeLists.txt
View
@@ -33,6 +33,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/fmfontcompareview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fmfontdb.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fmfontextract.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fmfontstrings.cpp
+${CMAKE_CURRENT_SOURCE_DIR}/fmfreetypelib.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fmglyphhighlight.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fmglyphsview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fminfodisplay.cpp
@@ -171,6 +172,7 @@ fmfontcompareview.h
fmfontdb.h
fmfontextract.h
fmfontstrings.h
+fmfreetypelib.h
fmglyphhighlight.h
fmglyphsview.h
fmlayoptwidget.h
71 src/fmfreetypelib.cpp
View
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Pierre Marchand *
+ * pierre@oep-h.com *
+ * *
+ * 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. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "fmfreetypelib.h"
+
+#include <QThread>
+#include <QMutexLocker>
+#include <QDebug>
+
+FMFreetypeLib *FMFreetypeLib::instance = 0;
+
+FMFreetypeLib::FMFreetypeLib(QObject *parent) :
+ QObject(parent)
+{
+ FT_Library theLibrary;
+ FT_Init_FreeType ( &theLibrary );
+ libraries.insert(thread(), theLibrary);
+ qDebug()<<"FT_Library"<<theLibrary<<thread();
+ mutex = new QMutex;
+}
+
+FMFreetypeLib * FMFreetypeLib::that()
+{
+ if(0 == instance)
+ instance = new FMFreetypeLib;
+ return instance;
+}
+
+FT_Library FMFreetypeLib::lib(QThread *t)
+{
+// return that()->libraries.value(that()->thread());
+ QMutexLocker(that()->mutex);
+ if(that()->libraries.contains(t))
+ return that()->libraries.value(t);
+
+ FTLibFactory ff;
+ ff.moveToThread(t);
+ that()->libraries.insert(t, ff.createLib());
+ connect(t, SIGNAL(terminated()), that(), SLOT(releaseLibrary()));
+ return that()->libraries.value(t);
+}
+
+void FMFreetypeLib::releaseLibrary()
+{
+ if(sender())
+ {
+ QThread *t(reinterpret_cast<QThread*>(sender()));
+ if(t && libraries.contains(t))
+ {
+ FT_Done_FreeType(libraries[t]);
+ libraries.remove(t);
+ }
+ }
+}
61 src/fmfreetypelib.h
View
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Pierre Marchand *
+ * pierre@oep-h.com *
+ * *
+ * 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. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef FMFREETYPELIB_H
+#define FMFREETYPELIB_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include <QObject>
+#include <QMap>
+#include <QMutex>
+
+class FMFreetypeLib : public QObject
+{
+ Q_OBJECT
+
+ static FMFreetypeLib * instance;
+ static FMFreetypeLib * that();
+ explicit FMFreetypeLib(QObject *parent = 0);
+
+ QMap<QThread *, FT_Library> libraries;
+ QMutex *mutex;
+
+ class FTLibFactory : public QObject
+ {
+ public:
+ FT_Library createLib()
+ {
+ FT_Library theLibrary;
+ FT_Init_FreeType ( &theLibrary );
+ return theLibrary;
+ }
+ };
+
+public:
+ static FT_Library lib(QThread * t);
+
+private slots:
+ void releaseLibrary();
+
+};
+
+#endif // FMFREETYPELIB_H
123 src/fmlayout.cpp
View
@@ -33,6 +33,8 @@
// #include <QMutexLocker>
#include <QMutex>
// #include <QWaitCondition>
+#include <QCoreApplication>
+#include <QGraphicsObject>
#define OUT_OF_RECT 99999999.0
@@ -136,7 +138,7 @@ void Node::sPath ( double dist , QList< int > curList, QList< int > & theList, d
// {debugL << v.n->index;}
// qDebug()<<"Node::sPath(" <<dist<< ", "<<curList<<", "<<theList<<", "<<theScore<<")"<< "I L"<<index<<debugL;
int deep ( curList.count() + 1 );
-// FMLayout* lyt ( FMLayout::getLayout() );
+ // FMLayout* lyt ( FMLayout::getLayout() );
if ( lyt->stopIt )
{
theScore = 0;
@@ -309,7 +311,9 @@ void Node::sPath ( double dist , QList< int > curList, QList< int > & theList, d
//FMLayout *FMLayout::instance = 0;
FMLayout::FMLayout ( QGraphicsScene * scene, FontItem * font , QRectF rect )
:theScene(scene),
- theFont(font)
+ theFont(font),
+ layoutIsFinished(true),
+ contextIsMainThread(true)
{
if(rect.isNull())
{
@@ -335,9 +339,9 @@ FMLayout::FMLayout ( QGraphicsScene * scene, FontItem * font , QRectF rect )
// onSceneProgressBar->setWidget ( progressBar );
// onSceneProgressBar->setZValue ( 1000 );
-// connect ( this, SIGNAL ( paragraphFinished() ), this, SLOT( endOfParagraph() ) );
-// connect ( this, SIGNAL ( layoutFinished() ), this, SLOT ( doDraw() ) );
-// connect ( this, SIGNAL ( paintFinished() ), this, SLOT ( endOfRun() ) );
+ // connect ( this, SIGNAL ( paragraphFinished() ), this, SLOT( endOfParagraph() ) );
+ // connect ( this, SIGNAL ( layoutFinished() ), this, SLOT ( doDraw() ) );
+ // connect ( this, SIGNAL ( paintFinished() ), this, SLOT ( endOfRun() ) );
FM_LAYOUT_NODE_SOON_F= 1200.0;
FM_LAYOUT_NODE_FIT_F= 1000.0;
@@ -347,7 +351,7 @@ FMLayout::FMLayout ( QGraphicsScene * scene, FontItem * font , QRectF rect )
FM_LAYOUT_MAX_COMPRESSION = 50.0; // 50%
optionDialog = new QWidget;
-// optionDialog->setWindowTitle ( tr ( "Text engine options" ) );
+ // optionDialog->setWindowTitle ( tr ( "Text engine options" ) );
optionLayout = new QGridLayout(optionDialog) ;
optionsWidget = new FMLayOptWidget;
@@ -367,7 +371,8 @@ FMLayout::FMLayout ( QGraphicsScene * scene, FontItem * font , QRectF rect )
optionLayout->addWidget(optionsWidget,0,0);
- connect ( optionsWidget,SIGNAL ( valueChanged ( int ) ),this,SLOT ( slotOption ( int ) ) );
+// connect ( optionsWidget,SIGNAL ( valueChanged ( int ) ),this,SLOT ( slotOption ( int ) ) );
+ connect(this, SIGNAL(objectWanted(QObject*)), typotek::getInstance(), SLOT(pushObject(QObject*)));
}
@@ -389,9 +394,9 @@ FMLayout::~ FMLayout()
void FMLayout::run()
{
- if(justRedraw)
- doDraw();
- else
+// if(justRedraw)
+// doDraw();
+// else
{
for ( int i ( 0 ); i < paragraphs.count() ; ++ i )
{
@@ -426,13 +431,16 @@ void FMLayout::run()
emit paragraphFinished();
}
- doDraw();
+ doDraw();
}
qDebug()<<"\tLayout Finished";
}
-void FMLayout::doLayout ( const QList<GlyphList> & spec , double fs )
+void FMLayout::doLayout ( const QList<GlyphList> & spec , double fs, FontItem* font)
{
+ qDebug()<<"FMLayout::doLayout"<<thread();
+ if(font)
+ theFont = font;
stopIt = false;
layoutIsFinished = false;
@@ -455,18 +463,18 @@ void FMLayout::doLayout ( const QList<GlyphList> & spec , double fs )
origine.rx() = theRect.left();
// qDebug()<<"LO"<<lastOrigine<<"O"<<origine<<"options"<<optionHasChanged;
- if( !optionHasChanged && origine == lastOrigine && fontSize == fs && paragraphs == spec )
- {
- justRedraw = true;
-// typotek::getInstance()->startProgressJob( lines.count() );
- // qDebug()<<"LAYOUT O : lines "<<lines.count();
- }
- else
+// if( !optionHasChanged && origine == lastOrigine && fontSize == fs && paragraphs == spec )
+// {
+// justRedraw = true;
+// // typotek::getInstance()->startProgressJob( lines.count() );
+// // qDebug()<<"LAYOUT O : lines "<<lines.count();
+// }
+// else
{
// qDebug()<<"LAYOUT 1";
justRedraw = false;
lines.clear();
-// typotek::getInstance()->startProgressJob( paragraphs.count() + ( theRect.height() / fs*1.20 ) );// layout AND draw
+ // typotek::getInstance()->startProgressJob( paragraphs.count() + ( theRect.height() / fs*1.20 ) );// layout AND draw
}
lastOrigine = origine;
fontSize = fs;
@@ -475,7 +483,8 @@ void FMLayout::doLayout ( const QList<GlyphList> & spec , double fs )
run();
layoutIsFinished = true;
- qDebug()<< "FMLayout::doLayout return";
+ emit layoutFinished();
+ qDebug()<< "FMLayout::doLayout return" << justRedraw;
}
void FMLayout::endOfRun()
@@ -493,11 +502,11 @@ void FMLayout::endOfRun()
if ( stopIt ) // We’re here after a interruption
{
stopIt = false;
-// typotek::getInstance()->endProgressJob();
+ // typotek::getInstance()->endProgressJob();
emit updateLayout();
}
-// else
-// typotek::getInstance()->endProgressJob();
+ // else
+ // typotek::getInstance()->endProgressJob();
// qDebug()<<"EOR B"<<lines.count();
}
@@ -505,7 +514,7 @@ void FMLayout::endOfRun()
void FMLayout::stopLayout()
{
stopIt = true;
- layoutIsFinished = true;
+ emit clearScene();
}
void FMLayout::doGraph() // Has became doBreaks
@@ -815,8 +824,9 @@ void FMLayout::doDraw()
double scale = fontSize / theFont->getUnitPerEm();
double pixelAdjustX = typotek::getInstance()->getDpiX() / 72.0 ;
- double pixelAdjustY = typotek::getInstance()->getDpiX() / 72.0 ;
+ double pixelAdjustY = typotek::getInstance()->getDpiY() / 72.0 ;
+ int pd =0;
for ( int lIdx ( 0 ); lIdx < lines.count() ; ++lIdx )
{
@@ -834,14 +844,18 @@ void FMLayout::doDraw()
++drawnLines;
clearCaches();
GlyphList refGlyph ( lines[lIdx] );
-
+// emit drawBaselineForMe(pen.y());
if ( !deviceIndy )
{
for ( int i=0; i < refGlyph.count(); ++i )
{
if ( !refGlyph[i].glyph )
continue;
- QGraphicsPixmapItem *glyph = theFont->itemFromGindexPix ( refGlyph[i].glyph , fontSize );
+ QGraphicsItem *glyph;
+ if(contextIsMainThread)
+ glyph = theFont->itemFromGindexPix ( refGlyph[i].glyph , fontSize );
+ else
+ glyph = theFont->itemFromGindexPix_mt( refGlyph[i].glyph , fontSize );
if ( !glyph )
continue;
if ( tp->inLine() == TextProgression::INLINE_RTL )
@@ -854,11 +868,33 @@ void FMLayout::doDraw()
}
/*************************************************/
- pixList << glyph;
- theScene->addItem ( glyph );
- glyph->setZValue ( 100.0 );
- glyph->setPos ( pen.x() + ( refGlyph[i].xoffset * pixelAdjustX ) + glyph->data ( GLYPH_DATA_BITMAPLEFT ).toDouble() * scale ,
- pen.y() + ( refGlyph[i].yoffset * pixelAdjustY ) - glyph->data ( GLYPH_DATA_BITMAPTOP ).toInt() );
+ if(contextIsMainThread)
+ {
+ pixList << reinterpret_cast<QGraphicsPixmapItem*>(glyph);
+ theScene->addItem ( glyph );
+ glyph->setZValue ( 100.0 );
+ glyph->setPos ( pen.x()
+ + ( refGlyph[i].xoffset * pixelAdjustX )
+ + glyph->data (GLYPH_DATA_BITMAPLEFT).toDouble() * scale ,
+ pen.y()
+ + ( refGlyph[i].yoffset * pixelAdjustY )
+ - glyph->data(GLYPH_DATA_BITMAPTOP).toDouble());
+ }
+ else
+ {
+// refGlyph[i].dump();
+ MetaGlyphItem * mgi(reinterpret_cast<MetaGlyphItem*>(glyph));
+// qDebug()<<refGlyph[i].glyph<<pen.y() << ( refGlyph[i].yoffset * pixelAdjustY ) << mgi->metaData ( GLYPH_DATA_BITMAPTOP ).toDouble();
+ ++pd;
+ emit drawPixmapForMe(refGlyph[i].glyph,
+ fontSize,
+ pen.x()
+ + (refGlyph[i].xoffset * pixelAdjustX)
+ + mgi->metaData(GLYPH_DATA_BITMAPLEFT).toDouble() * scale,
+ pen.y()
+ + (refGlyph[i].yoffset * pixelAdjustY)
+ - mgi->metaData(GLYPH_DATA_BITMAPTOP).toDouble());
+ }
/*************************************************/
if ( tp->inLine() == TextProgression::INLINE_LTR )
@@ -929,13 +965,14 @@ void FMLayout::doDraw()
pen.rx() += adjustedSampleInter;
}
-// typotek::getInstance()->runProgressJob();
+ // typotek::getInstance()->runProgressJob();
// qDebug() <<"P"<<pen;
}
//
// qDebug() <<"doDraw T(ms)"<<t.elapsed();
emit paintFinished();
- theScene->update(theRect);
+ emit drawPixmapForMe(-1,0,0,0);
+ qDebug()<<"P emitted:"<<pd;
}
int FMLayout::sepCount(int start, int end, const GlyphList & gl)
@@ -1275,7 +1312,11 @@ void FMLayout::resetScene()
{
if(persistentScene)
return;
-
+ if(!contextIsMainThread)
+ {
+ emit clearScene();
+ return;
+ }
int pCount ( pixList.count() );
for ( int i = 0; i < pCount ; ++i )
{
@@ -1421,10 +1462,18 @@ void FMLayout::clearCaches()
void FMLayout::endOfParagraph()
{
-// typotek::getInstance()->runProgressJob();
+ // typotek::getInstance()->runProgressJob();
}
+void FMLayout::setContext(bool c)
+{
+ contextIsMainThread = c;
+// if(c)
+// theFont->moveToThread(QApplication::instance()->thread());
+// else
+// emit objectWanted(theFont);
+}
14 src/fmlayout.h
View
@@ -89,10 +89,9 @@ class FMLayout : public QObject
Q_OBJECT
public:
- explicit FMLayout ( QGraphicsScene* scene, FontItem* font, QRectF rect = QRectF());
+ explicit FMLayout ( QGraphicsScene* scene, FontItem* font = 0, QRectF rect = QRectF());
~FMLayout();
- void doLayout(const QList<GlyphList>& spec , double fs);
-// static FMLayout *getLayout();
+ void doLayout(const QList<GlyphList>& spec , double fs, FontItem* font = 0 );
private://methods
/// Build a graph on node
@@ -118,6 +117,8 @@ class FMLayout : public QObject
// QMutex *layoutMutex;
bool stopIt;
int drawnLines;
+
+ void setContext(bool c);
public slots:
void stopLayout();
@@ -125,6 +126,7 @@ class FMLayout : public QObject
private:// data
// Argued
// static FMLayout *instance;
+ bool contextIsMainThread;
QGraphicsScene* theScene;
FontItem* theFont;
QList<GlyphList> paragraphs;
@@ -186,6 +188,12 @@ class FMLayout : public QObject
void slotOption(int v);
signals:
+ // needed if layout is executed outside the main (GUI) thread
+ // receiver is expected to know with what font and on which scene;
+ void drawPixmapForMe(int index, double fontsize, double x, double y);
+ void drawBaselineForMe(double y);
+ void clearScene();
+ void objectWanted(QObject*);
void updateLayout();
void layoutFinished();
void paragraphFinished();
160 src/fontitem.cpp
View
@@ -23,6 +23,7 @@
#include "fmencdata.h"
#include "fmfontdb.h"
#include "fmfontstrings.h"
+#include "fmfreetypelib.h"
#include "fmglyphsview.h"
#include "glyphtosvghelper.h"
#include "typotek.h"
@@ -36,6 +37,7 @@
#include <QDebug>
#include <QFileInfo>
#include <QGraphicsPixmapItem>
+#include <QGraphicsObject>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPathItem>
@@ -63,7 +65,6 @@
int fm_num_face_opened = 0;
-FT_Library FontItem::theLibrary = 0;
QGraphicsScene *FontItem::theOneLineScene = 0;
@@ -217,7 +218,7 @@ FontItem::FontItem ( QString path , bool remote, bool faststart )
remoteCached = false;
stopperDownload = false;
m_face = 0;
- facesRef = 0;
+ lastFace = 0;
m_glyphsPerRow = 5;
m_isEncoded = false;
currentChar = -1;
@@ -343,7 +344,7 @@ FontItem::FontItem(QString path, QString family, QString variant, QString type,b
remoteCached = false;
stopperDownload = false;
m_face = 0;
- facesRef = 0;
+ lastFace = 0;
m_glyphsPerRow = 5;
m_isEncoded = false;
currentChar = -1;
@@ -378,6 +379,12 @@ FontItem::FontItem(QString path, QString family, QString variant, QString type,b
m_type = type;
}
+FontItem * FontItem::Clone()
+{
+ FontItem *fitem = new FontItem ( m_path, m_family, m_variant, m_type, m_active );
+ return fitem;
+}
+
void FontItem::updateItem()
{
if(isUpToDate)
@@ -441,18 +448,6 @@ FontItem::~FontItem()
}
}
-bool FontItem::ensureLibrary()
-{
- if ( theLibrary )
- return true;
- ft_error = FT_Init_FreeType ( &theLibrary );
- if ( ft_error )
- {
- qDebug() << "Error loading ft_library ";
- return false;
- }
- return true;
-}
void FontItem::encodeFace()
{
@@ -508,40 +503,39 @@ void FontItem::encodeFace()
bool FontItem::ensureFace()
{
- if ( ensureLibrary() )
+ FT_Library ftlib = FMFreetypeLib::lib(thread());
+// qDebug()<<"FontItem::ensureFace"<<thread();
+
+ if ( m_face )
{
- if ( m_face )
- {
- ++facesRef;
- return true;
- }
- QString trueFile ( m_remote ? remoteHerePath : m_path );
- ft_error = FT_New_Face ( theLibrary, trueFile.toLocal8Bit() , 0, &m_face );
- if ( ft_error )
- {
- qDebug() << "Error loading face [" << trueFile <<"]";
- return false;
- }
- encodeFace();
- if ( spaceIndex.isEmpty() )
+ ++facesRef;
+ return true;
+ }
+ QString trueFile ( m_remote ? remoteHerePath : m_path );
+ ft_error = FT_New_Face ( ftlib, trueFile.toLocal8Bit() , 0, &m_face );
+ if ( ft_error )
+ {
+ qDebug() << "Error loading face [" << trueFile <<"]";
+ return false;
+ }
+ encodeFace();
+ if ( spaceIndex.isEmpty() )
+ {
+ int gIndex ( 0 );
+ for ( int i ( 0 ); i < legitimateNonPathChars.count(); ++i )
{
- int gIndex ( 0 );
- for ( int i ( 0 ); i < legitimateNonPathChars.count(); ++i )
+ gIndex = FT_Get_Char_Index ( m_face , legitimateNonPathChars[i] );
+ if ( gIndex )
{
- gIndex = FT_Get_Char_Index ( m_face , legitimateNonPathChars[i] );
- if ( gIndex )
- {
- spaceIndex << gIndex;
- }
+ spaceIndex << gIndex;
}
}
- unitPerEm = m_face->units_per_EM;
- m_glyph = m_face->glyph;
- ++facesRef;
- ++fm_num_face_opened;
- return true;
}
- return false;
+ unitPerEm = m_face->units_per_EM;
+ m_glyph = m_face->glyph;
+ facesRef = 1;
+ ++fm_num_face_opened;
+ return true;
}
void FontItem::releaseFace()
@@ -735,8 +729,8 @@ QGraphicsPixmapItem * FontItem::itemFromGindexPix ( int index, double size )
}
double takeAdvanceBeforeRender = m_glyph->metrics.horiAdvance * ( typotek::getInstance()->getDpiX() / 72.0 );
- double takeVertAdvanceBeforeRender = m_glyph->metrics.vertAdvance * ( typotek::getInstance()->getDpiX() / 72.0 );
- double takeLeftBeforeRender = ( double ) m_glyph->metrics.horiBearingX * ( typotek::getInstance()->getDpiX() / 72.0 );
+ double takeVertAdvanceBeforeRender = m_glyph->metrics.vertAdvance * ( typotek::getInstance()->getDpiY() / 72.0 );
+ double takeLeftBeforeRender = double(m_glyph->metrics.horiBearingX) * ( typotek::getInstance()->getDpiX() / 72.0 );
// if(m_FTHintMode != FT_LOAD_NO_HINTING)
{
@@ -785,7 +779,7 @@ QGraphicsPixmapItem * FontItem::itemFromGindexPix ( int index, double size )
// we need to transport more data
glyph->setData ( GLYPH_DATA_GLYPH , index );
glyph->setData ( GLYPH_DATA_BITMAPLEFT , takeLeftBeforeRender );
- glyph->setData ( GLYPH_DATA_BITMAPTOP , m_face->glyph->bitmap_top );
+ glyph->setData ( GLYPH_DATA_BITMAPTOP , double(m_face->glyph->bitmap_top) );
glyph->setData ( GLYPH_DATA_HADVANCE , takeAdvanceBeforeRender );
glyph->setData ( GLYPH_DATA_VADVANCE , takeVertAdvanceBeforeRender );
}
@@ -794,6 +788,78 @@ QGraphicsPixmapItem * FontItem::itemFromGindexPix ( int index, double size )
return glyph;
}
+MetaGlyphItem * FontItem::itemFromGindexPix_mt(int index, double size)
+{
+ if ( !ensureFace() )
+ return 0;
+ int charcode = index ;
+// qDebug()<<"FontItem::itemFromGindexPix_mt"<< thread();
+ MetaGlyphItem * glyph = new MetaGlyphItem;
+ double scaleFactor = size / m_face->units_per_EM;
+
+ // Set size
+ FT_Set_Char_Size ( m_face,
+ qRound( size * 64 ),
+ 0,
+ typotek::getInstance()->getDpiX(),
+ typotek::getInstance()->getDpiY() );
+
+ // Grab metrics in FONT UNIT
+ ft_error = FT_Load_Glyph ( m_face,
+ charcode ,
+ FT_LOAD_NO_SCALE );
+ if ( ft_error )
+ {
+ glyph->setMetaData ( GLYPH_DATA_GLYPH ,index );
+ glyph->setMetaData ( GLYPH_DATA_BITMAPLEFT , 0 );
+ glyph->setMetaData ( GLYPH_DATA_BITMAPTOP,size );
+ glyph->setMetaData ( GLYPH_DATA_HADVANCE ,size / scaleFactor );
+ releaseFace();
+ return glyph;
+ }
+
+ double takeAdvanceBeforeRender = m_glyph->metrics.horiAdvance * ( typotek::getInstance()->getDpiX() / 72.0 );
+ double takeVertAdvanceBeforeRender = m_glyph->metrics.vertAdvance * ( typotek::getInstance()->getDpiX() / 72.0 );
+ double takeLeftBeforeRender = ( double ) m_glyph->metrics.horiBearingX * ( typotek::getInstance()->getDpiX() / 72.0 );
+
+// if(m_FTHintMode != FT_LOAD_NO_HINTING)
+ {
+ ft_error = FT_Load_Glyph ( m_face, charcode , FT_LOAD_DEFAULT | m_FTHintMode );
+ }
+ // Render the glyph into a grayscale bitmap
+ ft_error = FT_Render_Glyph ( m_face->glyph, FT_RENDER_MODE_NORMAL );
+ if ( ft_error )
+ {
+ glyph->setMetaData ( GLYPH_DATA_GLYPH , index );
+ glyph->setMetaData ( GLYPH_DATA_BITMAPLEFT , 0 );
+ glyph->setMetaData ( GLYPH_DATA_BITMAPTOP,size );
+ glyph->setMetaData ( GLYPH_DATA_HADVANCE ,size / scaleFactor );
+ releaseFace();
+ return glyph;
+ }
+
+
+ QImage img ( glyphImage() );
+
+ if ( img.isNull() && !spaceIndex.contains ( index ) )
+ {
+ glyph->setMetaData ( GLYPH_DATA_GLYPH , index );
+ glyph->setMetaData ( GLYPH_DATA_BITMAPLEFT , 0 );
+ glyph->setMetaData ( GLYPH_DATA_BITMAPTOP,size );
+ glyph->setMetaData ( GLYPH_DATA_HADVANCE ,size /scaleFactor );
+ }
+ else
+ {
+ glyph->setMetaData ( GLYPH_DATA_GLYPH , index );
+ glyph->setMetaData ( GLYPH_DATA_BITMAPLEFT , takeLeftBeforeRender );
+ glyph->setMetaData ( GLYPH_DATA_BITMAPTOP , double(m_face->glyph->bitmap_top) );
+ glyph->setMetaData ( GLYPH_DATA_HADVANCE , takeAdvanceBeforeRender );
+ glyph->setMetaData ( GLYPH_DATA_VADVANCE , takeVertAdvanceBeforeRender );
+ }
+
+ releaseFace();
+ return glyph;
+}
QImage FontItem::charImage(int charcode, double size)
{
@@ -3107,7 +3173,7 @@ void FontItem::fileRemote ( QString f , QString v, QString t, QString i, QPixmap
m_variant = v;
m_type = t;
// m_cacheInfo = i;
- fixedPixmap = p;
+// fixedPixmap = p;
}
/// the same, but just for speedup startup with a lot of font files
38 src/fontitem.h
View
@@ -32,6 +32,9 @@
#include <QUrl>
#include <QFlags>
// #include <QThread>
+#include <QGraphicsItem>
+#include <QRectF>
+#include <QVariant>
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -45,6 +48,7 @@ class QGraphicsTextItem;
struct OTFSet;
class FMOtf;
class QGraphicsView;
+class QGraphicsObject;
class QProgressDialog;
class QHttp;
@@ -85,6 +89,22 @@ struct FontLocalInfo
QPixmap pix;
};
+class MetaGlyphItem : public QGraphicsItem
+{
+ QMap<int, QVariant> m_Data;
+public:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){}
+ QRectF boundingRect() const {return QRectF();}
+ void setMetaData(int key, const QVariant &value)
+ {
+ m_Data.insert(key,value);
+ }
+ QVariant metaData(int key) const
+ {
+ return m_Data.value(key);
+ }
+};
+
class FontItem : public QObject
{
Q_OBJECT
@@ -109,6 +129,7 @@ class FontItem : public QObject
FontItem ( QString path , bool remote = false, bool faststart = false);
FontItem (QString path, QString family, QString variant, QString type , bool active);
+ FontItem * Clone();
/** Needed when the item has been instantiate with "faststart=true" */
void updateItem();
~FontItem();
@@ -158,9 +179,11 @@ class FontItem : public QObject
bool m_isOpenType;
FMOtf *otf;
- static FT_Library theLibrary;
+// FT_Library theLibrary;
+ FT_Face m_face;
+ FT_Face lastFace;
FT_Error ft_error;
- FT_Face m_face;
+// QMap<FT_Library,FT_Face> faces;
int facesRef;
FT_GlyphSlot m_glyph;
@@ -172,8 +195,7 @@ class FontItem : public QObject
bool m_rasterFreetype;
unsigned int m_FTHintMode;
// unsigned int m_FTRenderMode;not yet implemented
-
- bool ensureLibrary();
+
bool ensureFace();
void releaseFace();
void encodeFace();
@@ -193,7 +215,6 @@ class FontItem : public QObject
QMap<int, QGraphicsTextItem*> fancyTexts;
QMap<int, QList<QGraphicsPixmapItem*> > fancyAlternates;
- QPixmap fixedPixmap;
bool allIsRendered;
bool isDerendered;
@@ -298,9 +319,10 @@ class FontItem : public QObject
QGraphicsPathItem* itemFromChar ( int charcode, double size );
QGraphicsPathItem* itemFromGindex ( int index, double size );
- QGraphicsPixmapItem* itemFromCharPix ( int charcode, double size );
- QGraphicsPixmapItem* itemFromGindexPix ( int index, double size );
- QGraphicsPixmapItem* itemFromGindexPix_mt ( int index, double size );
+ QGraphicsPixmapItem* itemFromCharPix ( int charcode, double size);
+ QGraphicsPixmapItem* itemFromGindexPix ( int index, double size);
+ // cant have qpixmap outside main thread and QGraphicsPixmapItem create at least a null one when instantiated
+ MetaGlyphItem* itemFromGindexPix_mt ( int index, double size );
QImage charImage(int charcode, double size);
QImage glyphImage(int index, double size);
6 src/sampletoolbar.ui
View
@@ -25,7 +25,11 @@
</widget>
</item>
<item row="0" column="1">
- <widget class="QDoubleSpinBox" name="liveSize"/>
+ <widget class="QDoubleSpinBox" name="liveSize">
+ <property name="maximum">
+ <double>999.990000000000009</double>
+ </property>
+ </widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="sampleButton">
156 src/samplewidget.cpp
View
@@ -29,6 +29,7 @@
#include "textprogression.h"
#include "opentypetags.h"
+#include <QApplication>
#include <QMap>
#include <QTreeWidgetItem>
#include <QSettings>
@@ -41,7 +42,6 @@
#include <QSettings>
#include <QStyledItemDelegate>
#include <QKeyEvent>
-#include <QThread>
QByteArray SampleWidget::State::toByteArray() const
@@ -56,6 +56,25 @@ QByteArray SampleWidget::State::toByteArray() const
return b;
}
+
+void FMLayoutThread::setLayout(FMLayout * l, const QList<GlyphList>& spec , double fs, FontItem* f, unsigned int hinting)
+{
+ pLayout = l;
+ pLayout->setContext(false);
+ gl = spec;
+ fontSize = fs;
+ font = f;
+ fHinting = hinting;
+}
+
+void FMLayoutThread::run()
+{
+ FontItem * tf(new FontItem(font->path(),font->family(),font->variant(),font->type(), font->isActivated()));
+ tf->setFTHintMode(fHinting);
+ pLayout->doLayout(gl, fontSize, tf);
+ delete tf;
+}
+
SampleWidget::State SampleWidget::State::fromByteArray(QByteArray b)
{
QDataStream ds(&b, QIODevice::ReadOnly);
@@ -90,6 +109,7 @@ SampleWidget::SampleWidget(const QString& fid, QWidget *parent) :
layoutTimer = new QTimer(this);
layoutWait = 1000;
layoutForPrint = false;
+ layoutSwitch = false;
ui->setupUi(this);
// ui->textProgression->setVisible(false);
@@ -125,12 +145,12 @@ SampleWidget::SampleWidget(const QString& fid, QWidget *parent) :
ui->loremView_FT->locker = false;
ui->loremView_FT->fakePage();
+ layoutThread = new FMLayoutThread;
+
FontItem * cf(FMFontDb::DB()->Font(fid));
textLayoutVect = new FMLayout(loremScene, cf);
- textLayoutFT = new FMLayout(ftScene, cf);
+ textLayoutFT = new FMLayout(ftScene);
- layoutThread = new QThread(this);
- textLayoutFT->moveToThread(layoutThread);
QSettings settings;
State s;
@@ -141,7 +161,7 @@ SampleWidget::SampleWidget(const QString& fid, QWidget *parent) :
sampleInterSize = sampleFontSize * sampleRatio;
createConnections();
- slotView(true);
+ slotView();
}
SampleWidget::~SampleWidget()
@@ -198,7 +218,8 @@ void SampleWidget::createConnections()
connect(sampleNameEditor, SIGNAL(closeEditor(QWidget*)), this, SLOT(slotSampleNameEdited(QWidget*)));
connect(ui->sampleEdit, SIGNAL(textChanged()), this, SLOT(slotUpdateSample()));
- connect(layoutTimer, SIGNAL(timeout()), this, SLOT(slotUpdateSample()));
+
+ connect(textLayoutFT, SIGNAL(clearScene()), this, SLOT(clearFTScene()));
}
@@ -231,7 +252,6 @@ void SampleWidget::removeConnections()
disconnect(ui->toolbar, SIGNAL(Detach()), this, SLOT(ddetach()));
disconnect(sysWatcher, SIGNAL(fileChanged(QString)),this, SLOT(slotFileChanged(QString)));
- disconnect(reloadTimer,SIGNAL(timeout()), this, SLOT(slotReload()));
disconnect(this, SIGNAL(stateChanged()), this, SLOT(saveState()));
}
@@ -325,18 +345,15 @@ void SampleWidget::setState(const SampleWidget::State &s)
slotEditSample();
}
-void SampleWidget::slotView ( bool needDeRendering )
+void SampleWidget::slotView()
{
- qDebug()<<"SampleWidget::slotView ";
+ qDebug()<<"SampleWidget::slotView "<< fontIdentifier;
+// disconnect(textLayoutFT, SIGNAL(drawBaselineForMe(double)), this, SLOT(drawBaseline(double)));
QTime t;
t.start();
FontItem *f(FMFontDb::DB()->Font( fontIdentifier ));
if ( !f )
return;
- if ( needDeRendering )
- {
-// f->deRenderAll();
- }
bool wantDeviceDependant = !layoutForPrint;
if(wantDeviceDependant)
@@ -357,10 +374,17 @@ void SampleWidget::slotView ( bool needDeRendering )
// if ( ui->loremView->isVisible() || ui->loremView_FT->isVisible() || layoutForPrint)
{
- if(!textLayoutFT->isLayoutFinished())
+ if(!layoutForPrint && !textLayoutFT->isLayoutFinished())
{
+ connect(textLayoutFT, SIGNAL(layoutFinished()), this, SLOT(slotView()));
textLayoutFT->stopLayout();
qDebug()<<"\tLayout stopped";
+ layoutSwitch = false;
+ return;
+ }
+ else
+ {
+ disconnect(textLayoutFT, SIGNAL(layoutFinished()), this, SLOT(slotView()));
}
// else if(textLayoutVect->isRunning())
// textLayoutVect->stopLayout();
@@ -385,6 +409,7 @@ void SampleWidget::slotView ( bool needDeRendering )
QList<GlyphList> list;
QStringList stl( typotek::getInstance()->namedSample().split("\n"));
+// qDebug()<<"Sample:\n\t"<<stl.join("\n\t");
if ( processScript )
{
for(int p(0);p<stl.count();++p)
@@ -404,17 +429,70 @@ void SampleWidget::slotView ( bool needDeRendering )
for(int p(0);p<stl.count();++p)
list << f->glyphs( stl[p] , fSize );
}
- textLayout->doLayout(list, fSize);
-
+ if(!layoutForPrint)
+ {
+ layoutThread->setLayout(textLayout, list, fSize, f, hinting());
+ connect(textLayout, SIGNAL(drawPixmapForMe(int,double,double,double)), this, SLOT(drawPixmap(int,double,double,double)));
+// connect(textLayoutFT, SIGNAL(drawBaselineForMe(double)), this, SLOT(drawBaseline(double)));
+ connect(textLayout, SIGNAL(layoutFinished()), this, SLOT(endLayout()));
+ layoutSwitch = true;
+ pixmapDrawn = 0;
+ layoutThread->start();
+ }
+ else
{
- QPointF texttopLeft(ui->loremView_FT->mapFromScene(textLayout->getRect().topLeft()));
- ui->loremView_FT->translate( 10 -texttopLeft.x(), 10 -texttopLeft.y());
+ textLayout->doLayout(list, fSize);
}
}
}
}
+void SampleWidget::drawPixmap(int index, double fontsize, double x, double y)
+{
+// qDebug()<<"SampleWidget::drawPixmap index:"<<index<< "Y:"<<y;
+ if(index < 0)
+ disconnect(textLayoutFT, SIGNAL(drawPixmapForMe(int,double,double,double)), this, SLOT(drawPixmap(int,double,double,double)));
+ FontItem * f( FMFontDb::DB()->Font( fontIdentifier ) );
+ if(!f)
+ return;
+ ++pixmapDrawn;
+ QGraphicsPixmapItem *glyph = f->itemFromGindexPix ( index , fontsize );
+// qDebug()<<"SampleWidget::drawPixmap index:"<<index<< y << glyph->data(GLYPH_DATA_BITMAPTOP).toDouble();
+ ftScene->addItem ( glyph );
+ glyph->setZValue ( 100.0 );
+ glyph->setPos ( x,y );
+// QGraphicsLineItem * l = ftScene->addLine(x,y,x,y + glyph->data(GLYPH_DATA_BITMAPTOP).toDouble());
+// l->setData(GLYPH_DATA_GLYPH, 1);
+// glyph->pixmap().toImage().save(QString("/tmp/%1.png").arg(index));
+}
+
+void SampleWidget::drawBaseline(double y)
+{
+ QGraphicsLineItem * l = ftScene->addLine(0,y,ftScene->width(),y);
+ l->setData(GLYPH_DATA_GLYPH, 1);
+}
+
+void SampleWidget::clearFTScene()
+{
+ qDebug()<<"SampleWidget::clearFTScene"<< layoutSwitch;
+// if(layoutSwitch)
+// return;
+ foreach(QGraphicsItem* gi, ftScene->items())
+ {
+ if(gi->data(GLYPH_DATA_GLYPH).toInt() > 0)
+ delete gi;
+ }
+}
+
+void SampleWidget::endLayout()
+{
+ QPointF texttopLeft(ui->loremView_FT->mapFromScene(textLayoutFT->getRect().topLeft()));
+ ui->loremView_FT->translate( 10 -texttopLeft.x(), 10 -texttopLeft.y());
+ ui->loremView_FT->update();
+// qDebug()<<"Pixmaps:"<<pixmapDrawn;
+
+}
void SampleWidget::fillOTTree()
{
@@ -601,7 +679,7 @@ OTFSet SampleWidget::deFillOTTree()
void SampleWidget::slotUpdateSView()
{
if(ui->loremView->isVisible())
- slotView(true);
+ slotView();
}
@@ -633,14 +711,14 @@ void SampleWidget::slotZoom ( int z )
void SampleWidget::slotUpdateRView()
{
if(ui->loremView_FT->isVisible())
- slotView(true);
+ slotView();
}
void SampleWidget::slotSampleChanged()
{
typotek::getInstance()->namedSample( ui->sampleTextTree->currentItem()->data(0, Qt::UserRole).toString() );
ui->removeSampleButton->setEnabled(ui->sampleTextTree->currentItem()->parent() == uRoot);
- slotView ( true );
+ slotView ( );
emit stateChanged();
}
@@ -650,14 +728,14 @@ void SampleWidget::slotLiveFontSize(double fs)
{
// double fs( sampleToolBar->getFontSize() );
reSize(fs, fs * sampleRatio);
- slotView(true);
+ slotView();
emit stateChanged();
}
void SampleWidget::slotFeatureChanged()
{
// OTFSet ret = deFillOTTree();
- slotView ( true );
+ slotView ( );
emit stateChanged();
}
@@ -685,19 +763,19 @@ void SampleWidget::slotChangeScript()
{
if ( ui->useShaperCheck->checkState() == Qt::Checked )
{
- slotView ( true );
+ slotView ( );
}
emit stateChanged();
}
void SampleWidget::slotProgressionChanged()
{
- slotView(true);
+ slotView();
}
void SampleWidget::slotWantShape()
{
- slotView ( true );
+ slotView ( );
emit stateChanged();
}
@@ -770,7 +848,7 @@ void SampleWidget::slotPrint()
if(!font)
return;
layoutForPrint = true;
- slotView(false);
+ slotView();
// if( textLayoutVect->isRunning() )
// {
// connect(textLayoutVect, SIGNAL(paintFinished()), this,SLOT(slotPrint()));
@@ -907,28 +985,6 @@ void SampleWidget::slotEditSample()
void SampleWidget::slotUpdateSample()
{
typotek::getInstance()->changeSample(ui->sampleTextTree->currentItem()->text(0), ui->sampleEdit->toPlainText());
- slotView(true);
-// if(firstUpdateRequest)
-// {
-// typotek::getInstance()->changeSample(ui->sampleTextTree->currentItem()->text(0), ui->sampleEdit->toPlainText());
-// slotView(true);
-// firstUpdateRequest = false;
-// firstUpdateRequestTimeStamp = layoutTime.elapsed();
-// }
-// else
-// {
-// if((layoutTime.elapsed() - firstUpdateRequestTimeStamp) < layoutWait)
-// {
-// firstUpdateRequestTimeStamp = layoutTime.elapsed();
-// layoutTimer->start(layoutWait);
-// }
-// else
-// {
-// layoutTimer->stop();
-// firstUpdateRequest = true;
-// typotek::getInstance()->changeSample(ui->sampleTextTree->currentItem()->text(0), ui->sampleEdit->toPlainText());
-// slotView(true);
-// }
-// }
+ slotView();
}
26 src/samplewidget.h
View
@@ -27,6 +27,7 @@
#include <QString>
#include <QByteArray>
#include <QTime>
+#include <QThread>
class QGraphicsScene;
class FMLayout;
@@ -37,7 +38,7 @@ class QTimer;
class SampleToolBar;
class QTreeWidgetItem;
class QStyledItemDelegate;
-class QThread;
+class FontItem;
namespace Ui {
class SampleWidget;
@@ -49,6 +50,19 @@ namespace Ui {
//#define VIEW_PAGE_SETTINGS 1
#define VIEW_PAGE_SAMPLES 4
+class FMLayoutThread : public QThread
+{
+ FMLayout * pLayout;
+ QList<GlyphList> gl;
+ double fontSize;
+ FontItem * font;
+ unsigned int fHinting;
+
+public:
+ void setLayout(FMLayout * l, const QList<GlyphList>& spec , double fs, FontItem * f, unsigned int hinting);
+ void run();
+};
+
class SampleWidget : public FloatingWidget
{
Q_OBJECT
@@ -133,12 +147,18 @@ class SampleWidget : public FloatingWidget
QTime layoutTime;
QTimer *layoutTimer;
int layoutWait;
- QThread * layoutThread;
+ FMLayoutThread * layoutThread;
+ bool layoutSwitch;
+ int pixmapDrawn;
void reSize(double fSize, double lSize){sampleFontSize = fSize; sampleInterSize = lSize;}
private slots:
- void slotView(bool needDeRendering = false);
+ void slotView();
+ void drawPixmap(int index, double fontsize, double x, double y);
+ void drawBaseline(double y);
+ void clearFTScene();
+ void endLayout();
// void slotChangeViewPage(QAbstractButton* );
// void slotHintChanged(int);
// void slotChangeViewPageSetting(bool);
5 src/typotek.cpp
View
@@ -2466,4 +2466,7 @@ void typotek::toggleMainView(bool v)
mainStack->setCurrentWidget(theMainView);
}
-
+void typotek::pushObject(QObject *o)
+{
+ o->moveToThread(sender()->thread());
+}
1  src/typotek.h
View
@@ -117,6 +117,7 @@ public slots:
void showAllFloatings();
void hideAllFloatings();
void toggleMainView(bool v);
+ void pushObject(QObject* o);
void hide();
void show();
Please sign in to comment.
Something went wrong with that request. Please try again.