Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
@@ -33,6 +33,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/fmfontcompareview.cpp
33 33 ${CMAKE_CURRENT_SOURCE_DIR}/fmfontdb.cpp
34 34 ${CMAKE_CURRENT_SOURCE_DIR}/fmfontextract.cpp
35 35 ${CMAKE_CURRENT_SOURCE_DIR}/fmfontstrings.cpp
  36 +${CMAKE_CURRENT_SOURCE_DIR}/fmfreetypelib.cpp
36 37 ${CMAKE_CURRENT_SOURCE_DIR}/fmglyphhighlight.cpp
37 38 ${CMAKE_CURRENT_SOURCE_DIR}/fmglyphsview.cpp
38 39 ${CMAKE_CURRENT_SOURCE_DIR}/fminfodisplay.cpp
@@ -171,6 +172,7 @@ fmfontcompareview.h
171 172 fmfontdb.h
172 173 fmfontextract.h
173 174 fmfontstrings.h
  175 +fmfreetypelib.h
174 176 fmglyphhighlight.h
175 177 fmglyphsview.h
176 178 fmlayoptwidget.h
71 src/fmfreetypelib.cpp
... ... @@ -0,0 +1,71 @@
  1 +/***************************************************************************
  2 + * Copyright (C) 2010 by Pierre Marchand *
  3 + * pierre@oep-h.com *
  4 + * *
  5 + * This program is free software; you can redistribute it and/or modify *
  6 + * it under the terms of the GNU General Public License as published by *
  7 + * the Free Software Foundation; either version 2 of the License, or *
  8 + * (at your option) any later version. *
  9 + * *
  10 + * This program is distributed in the hope that it will be useful, *
  11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13 + * GNU General Public License for more details. *
  14 + * *
  15 + * You should have received a copy of the GNU General Public License *
  16 + * along with this program; if not, write to the *
  17 + * Free Software Foundation, Inc., *
  18 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19 + ***************************************************************************/
  20 +
  21 +#include "fmfreetypelib.h"
  22 +
  23 +#include <QThread>
  24 +#include <QMutexLocker>
  25 +#include <QDebug>
  26 +
  27 +FMFreetypeLib *FMFreetypeLib::instance = 0;
  28 +
  29 +FMFreetypeLib::FMFreetypeLib(QObject *parent) :
  30 + QObject(parent)
  31 +{
  32 + FT_Library theLibrary;
  33 + FT_Init_FreeType ( &theLibrary );
  34 + libraries.insert(thread(), theLibrary);
  35 + qDebug()<<"FT_Library"<<theLibrary<<thread();
  36 + mutex = new QMutex;
  37 +}
  38 +
  39 +FMFreetypeLib * FMFreetypeLib::that()
  40 +{
  41 + if(0 == instance)
  42 + instance = new FMFreetypeLib;
  43 + return instance;
  44 +}
  45 +
  46 +FT_Library FMFreetypeLib::lib(QThread *t)
  47 +{
  48 +// return that()->libraries.value(that()->thread());
  49 + QMutexLocker(that()->mutex);
  50 + if(that()->libraries.contains(t))
  51 + return that()->libraries.value(t);
  52 +
  53 + FTLibFactory ff;
  54 + ff.moveToThread(t);
  55 + that()->libraries.insert(t, ff.createLib());
  56 + connect(t, SIGNAL(terminated()), that(), SLOT(releaseLibrary()));
  57 + return that()->libraries.value(t);
  58 +}
  59 +
  60 +void FMFreetypeLib::releaseLibrary()
  61 +{
  62 + if(sender())
  63 + {
  64 + QThread *t(reinterpret_cast<QThread*>(sender()));
  65 + if(t && libraries.contains(t))
  66 + {
  67 + FT_Done_FreeType(libraries[t]);
  68 + libraries.remove(t);
  69 + }
  70 + }
  71 +}
61 src/fmfreetypelib.h
... ... @@ -0,0 +1,61 @@
  1 +/***************************************************************************
  2 + * Copyright (C) 2010 by Pierre Marchand *
  3 + * pierre@oep-h.com *
  4 + * *
  5 + * This program is free software; you can redistribute it and/or modify *
  6 + * it under the terms of the GNU General Public License as published by *
  7 + * the Free Software Foundation; either version 2 of the License, or *
  8 + * (at your option) any later version. *
  9 + * *
  10 + * This program is distributed in the hope that it will be useful, *
  11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13 + * GNU General Public License for more details. *
  14 + * *
  15 + * You should have received a copy of the GNU General Public License *
  16 + * along with this program; if not, write to the *
  17 + * Free Software Foundation, Inc., *
  18 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19 + ***************************************************************************/
  20 +
  21 +#ifndef FMFREETYPELIB_H
  22 +#define FMFREETYPELIB_H
  23 +
  24 +#include <ft2build.h>
  25 +#include FT_FREETYPE_H
  26 +
  27 +#include <QObject>
  28 +#include <QMap>
  29 +#include <QMutex>
  30 +
  31 +class FMFreetypeLib : public QObject
  32 +{
  33 + Q_OBJECT
  34 +
  35 + static FMFreetypeLib * instance;
  36 + static FMFreetypeLib * that();
  37 + explicit FMFreetypeLib(QObject *parent = 0);
  38 +
  39 + QMap<QThread *, FT_Library> libraries;
  40 + QMutex *mutex;
  41 +
  42 + class FTLibFactory : public QObject
  43 + {
  44 + public:
  45 + FT_Library createLib()
  46 + {
  47 + FT_Library theLibrary;
  48 + FT_Init_FreeType ( &theLibrary );
  49 + return theLibrary;
  50 + }
  51 + };
  52 +
  53 +public:
  54 + static FT_Library lib(QThread * t);
  55 +
  56 +private slots:
  57 + void releaseLibrary();
  58 +
  59 +};
  60 +
  61 +#endif // FMFREETYPELIB_H
123 src/fmlayout.cpp
@@ -33,6 +33,8 @@
33 33 // #include <QMutexLocker>
34 34 #include <QMutex>
35 35 // #include <QWaitCondition>
  36 +#include <QCoreApplication>
  37 +#include <QGraphicsObject>
36 38
37 39 #define OUT_OF_RECT 99999999.0
38 40
@@ -136,7 +138,7 @@ void Node::sPath ( double dist , QList< int > curList, QList< int > & theList, d
136 138 // {debugL << v.n->index;}
137 139 // qDebug()<<"Node::sPath(" <<dist<< ", "<<curList<<", "<<theList<<", "<<theScore<<")"<< "I L"<<index<<debugL;
138 140 int deep ( curList.count() + 1 );
139   -// FMLayout* lyt ( FMLayout::getLayout() );
  141 + // FMLayout* lyt ( FMLayout::getLayout() );
140 142 if ( lyt->stopIt )
141 143 {
142 144 theScore = 0;
@@ -309,7 +311,9 @@ void Node::sPath ( double dist , QList< int > curList, QList< int > & theList, d
309 311 //FMLayout *FMLayout::instance = 0;
310 312 FMLayout::FMLayout ( QGraphicsScene * scene, FontItem * font , QRectF rect )
311 313 :theScene(scene),
312   - theFont(font)
  314 + theFont(font),
  315 + layoutIsFinished(true),
  316 + contextIsMainThread(true)
313 317 {
314 318 if(rect.isNull())
315 319 {
@@ -335,9 +339,9 @@ FMLayout::FMLayout ( QGraphicsScene * scene, FontItem * font , QRectF rect )
335 339 // onSceneProgressBar->setWidget ( progressBar );
336 340 // onSceneProgressBar->setZValue ( 1000 );
337 341
338   -// connect ( this, SIGNAL ( paragraphFinished() ), this, SLOT( endOfParagraph() ) );
339   -// connect ( this, SIGNAL ( layoutFinished() ), this, SLOT ( doDraw() ) );
340   -// connect ( this, SIGNAL ( paintFinished() ), this, SLOT ( endOfRun() ) );
  342 + // connect ( this, SIGNAL ( paragraphFinished() ), this, SLOT( endOfParagraph() ) );
  343 + // connect ( this, SIGNAL ( layoutFinished() ), this, SLOT ( doDraw() ) );
  344 + // connect ( this, SIGNAL ( paintFinished() ), this, SLOT ( endOfRun() ) );
341 345
342 346 FM_LAYOUT_NODE_SOON_F= 1200.0;
343 347 FM_LAYOUT_NODE_FIT_F= 1000.0;
@@ -347,7 +351,7 @@ FMLayout::FMLayout ( QGraphicsScene * scene, FontItem * font , QRectF rect )
347 351 FM_LAYOUT_MAX_COMPRESSION = 50.0; // 50%
348 352
349 353 optionDialog = new QWidget;
350   -// optionDialog->setWindowTitle ( tr ( "Text engine options" ) );
  354 + // optionDialog->setWindowTitle ( tr ( "Text engine options" ) );
351 355 optionLayout = new QGridLayout(optionDialog) ;
352 356
353 357 optionsWidget = new FMLayOptWidget;
@@ -367,7 +371,8 @@ FMLayout::FMLayout ( QGraphicsScene * scene, FontItem * font , QRectF rect )
367 371
368 372 optionLayout->addWidget(optionsWidget,0,0);
369 373
370   - connect ( optionsWidget,SIGNAL ( valueChanged ( int ) ),this,SLOT ( slotOption ( int ) ) );
  374 +// connect ( optionsWidget,SIGNAL ( valueChanged ( int ) ),this,SLOT ( slotOption ( int ) ) );
  375 + connect(this, SIGNAL(objectWanted(QObject*)), typotek::getInstance(), SLOT(pushObject(QObject*)));
371 376
372 377 }
373 378
@@ -389,9 +394,9 @@ FMLayout::~ FMLayout()
389 394
390 395 void FMLayout::run()
391 396 {
392   - if(justRedraw)
393   - doDraw();
394   - else
  397 +// if(justRedraw)
  398 +// doDraw();
  399 +// else
395 400 {
396 401 for ( int i ( 0 ); i < paragraphs.count() ; ++ i )
397 402 {
@@ -426,13 +431,16 @@ void FMLayout::run()
426 431 emit paragraphFinished();
427 432
428 433 }
429   - doDraw();
  434 + doDraw();
430 435 }
431 436 qDebug()<<"\tLayout Finished";
432 437 }
433 438
434   -void FMLayout::doLayout ( const QList<GlyphList> & spec , double fs )
  439 +void FMLayout::doLayout ( const QList<GlyphList> & spec , double fs, FontItem* font)
435 440 {
  441 + qDebug()<<"FMLayout::doLayout"<<thread();
  442 + if(font)
  443 + theFont = font;
436 444 stopIt = false;
437 445 layoutIsFinished = false;
438 446
@@ -455,18 +463,18 @@ void FMLayout::doLayout ( const QList<GlyphList> & spec , double fs )
455 463 origine.rx() = theRect.left();
456 464
457 465 // qDebug()<<"LO"<<lastOrigine<<"O"<<origine<<"options"<<optionHasChanged;
458   - if( !optionHasChanged && origine == lastOrigine && fontSize == fs && paragraphs == spec )
459   - {
460   - justRedraw = true;
461   -// typotek::getInstance()->startProgressJob( lines.count() );
462   - // qDebug()<<"LAYOUT O : lines "<<lines.count();
463   - }
464   - else
  466 +// if( !optionHasChanged && origine == lastOrigine && fontSize == fs && paragraphs == spec )
  467 +// {
  468 +// justRedraw = true;
  469 +// // typotek::getInstance()->startProgressJob( lines.count() );
  470 +// // qDebug()<<"LAYOUT O : lines "<<lines.count();
  471 +// }
  472 +// else
465 473 {
466 474 // qDebug()<<"LAYOUT 1";
467 475 justRedraw = false;
468 476 lines.clear();
469   -// typotek::getInstance()->startProgressJob( paragraphs.count() + ( theRect.height() / fs*1.20 ) );// layout AND draw
  477 + // typotek::getInstance()->startProgressJob( paragraphs.count() + ( theRect.height() / fs*1.20 ) );// layout AND draw
470 478 }
471 479 lastOrigine = origine;
472 480 fontSize = fs;
@@ -475,7 +483,8 @@ void FMLayout::doLayout ( const QList<GlyphList> & spec , double fs )
475 483
476 484 run();
477 485 layoutIsFinished = true;
478   - qDebug()<< "FMLayout::doLayout return";
  486 + emit layoutFinished();
  487 + qDebug()<< "FMLayout::doLayout return" << justRedraw;
479 488 }
480 489
481 490 void FMLayout::endOfRun()
@@ -493,11 +502,11 @@ void FMLayout::endOfRun()
493 502 if ( stopIt ) // We’re here after a interruption
494 503 {
495 504 stopIt = false;
496   -// typotek::getInstance()->endProgressJob();
  505 + // typotek::getInstance()->endProgressJob();
497 506 emit updateLayout();
498 507 }
499   -// else
500   -// typotek::getInstance()->endProgressJob();
  508 + // else
  509 + // typotek::getInstance()->endProgressJob();
501 510
502 511 // qDebug()<<"EOR B"<<lines.count();
503 512 }
@@ -505,7 +514,7 @@ void FMLayout::endOfRun()
505 514 void FMLayout::stopLayout()
506 515 {
507 516 stopIt = true;
508   - layoutIsFinished = true;
  517 + emit clearScene();
509 518 }
510 519
511 520 void FMLayout::doGraph() // Has became doBreaks
@@ -815,8 +824,9 @@ void FMLayout::doDraw()
815 824
816 825 double scale = fontSize / theFont->getUnitPerEm();
817 826 double pixelAdjustX = typotek::getInstance()->getDpiX() / 72.0 ;
818   - double pixelAdjustY = typotek::getInstance()->getDpiX() / 72.0 ;
  827 + double pixelAdjustY = typotek::getInstance()->getDpiY() / 72.0 ;
819 828
  829 + int pd =0;
820 830
821 831 for ( int lIdx ( 0 ); lIdx < lines.count() ; ++lIdx )
822 832 {
@@ -834,14 +844,18 @@ void FMLayout::doDraw()
834 844 ++drawnLines;
835 845 clearCaches();
836 846 GlyphList refGlyph ( lines[lIdx] );
837   -
  847 +// emit drawBaselineForMe(pen.y());
838 848 if ( !deviceIndy )
839 849 {
840 850 for ( int i=0; i < refGlyph.count(); ++i )
841 851 {
842 852 if ( !refGlyph[i].glyph )
843 853 continue;
844   - QGraphicsPixmapItem *glyph = theFont->itemFromGindexPix ( refGlyph[i].glyph , fontSize );
  854 + QGraphicsItem *glyph;
  855 + if(contextIsMainThread)
  856 + glyph = theFont->itemFromGindexPix ( refGlyph[i].glyph , fontSize );
  857 + else
  858 + glyph = theFont->itemFromGindexPix_mt( refGlyph[i].glyph , fontSize );
845 859 if ( !glyph )
846 860 continue;
847 861 if ( tp->inLine() == TextProgression::INLINE_RTL )
@@ -854,11 +868,33 @@ void FMLayout::doDraw()
854 868 }
855 869
856 870 /*************************************************/
857   - pixList << glyph;
858   - theScene->addItem ( glyph );
859   - glyph->setZValue ( 100.0 );
860   - glyph->setPos ( pen.x() + ( refGlyph[i].xoffset * pixelAdjustX ) + glyph->data ( GLYPH_DATA_BITMAPLEFT ).toDouble() * scale ,
861   - pen.y() + ( refGlyph[i].yoffset * pixelAdjustY ) - glyph->data ( GLYPH_DATA_BITMAPTOP ).toInt() );
  871 + if(contextIsMainThread)
  872 + {
  873 + pixList << reinterpret_cast<QGraphicsPixmapItem*>(glyph);
  874 + theScene->addItem ( glyph );
  875 + glyph->setZValue ( 100.0 );
  876 + glyph->setPos ( pen.x()
  877 + + ( refGlyph[i].xoffset * pixelAdjustX )
  878 + + glyph->data (GLYPH_DATA_BITMAPLEFT).toDouble() * scale ,
  879 + pen.y()
  880 + + ( refGlyph[i].yoffset * pixelAdjustY )
  881 + - glyph->data(GLYPH_DATA_BITMAPTOP).toDouble());
  882 + }
  883 + else
  884 + {
  885 +// refGlyph[i].dump();
  886 + MetaGlyphItem * mgi(reinterpret_cast<MetaGlyphItem*>(glyph));
  887 +// qDebug()<<refGlyph[i].glyph<<pen.y() << ( refGlyph[i].yoffset * pixelAdjustY ) << mgi->metaData ( GLYPH_DATA_BITMAPTOP ).toDouble();
  888 + ++pd;
  889 + emit drawPixmapForMe(refGlyph[i].glyph,
  890 + fontSize,
  891 + pen.x()
  892 + + (refGlyph[i].xoffset * pixelAdjustX)
  893 + + mgi->metaData(GLYPH_DATA_BITMAPLEFT).toDouble() * scale,
  894 + pen.y()
  895 + + (refGlyph[i].yoffset * pixelAdjustY)
  896 + - mgi->metaData(GLYPH_DATA_BITMAPTOP).toDouble());
  897 + }
862 898 /*************************************************/
863 899
864 900 if ( tp->inLine() == TextProgression::INLINE_LTR )
@@ -929,13 +965,14 @@ void FMLayout::doDraw()
929 965 pen.rx() += adjustedSampleInter;
930 966 }
931 967
932   -// typotek::getInstance()->runProgressJob();
  968 + // typotek::getInstance()->runProgressJob();
933 969 // qDebug() <<"P"<<pen;
934 970 }
935 971 //
936 972 // qDebug() <<"doDraw T(ms)"<<t.elapsed();
937 973 emit paintFinished();
938   - theScene->update(theRect);
  974 + emit drawPixmapForMe(-1,0,0,0);
  975 + qDebug()<<"P emitted:"<<pd;
939 976 }
940 977
941 978 int FMLayout::sepCount(int start, int end, const GlyphList & gl)
@@ -1275,7 +1312,11 @@ void FMLayout::resetScene()
1275 1312 {
1276 1313 if(persistentScene)
1277 1314 return;
1278   -
  1315 + if(!contextIsMainThread)
  1316 + {
  1317 + emit clearScene();
  1318 + return;
  1319 + }
1279 1320 int pCount ( pixList.count() );
1280 1321 for ( int i = 0; i < pCount ; ++i )
1281 1322 {
@@ -1421,10 +1462,18 @@ void FMLayout::clearCaches()
1421 1462
1422 1463 void FMLayout::endOfParagraph()
1423 1464 {
1424   -// typotek::getInstance()->runProgressJob();
  1465 + // typotek::getInstance()->runProgressJob();
1425 1466 }
1426 1467
1427 1468
  1469 +void FMLayout::setContext(bool c)
  1470 +{
  1471 + contextIsMainThread = c;
  1472 +// if(c)
  1473 +// theFont->moveToThread(QApplication::instance()->thread());
  1474 +// else
  1475 +// emit objectWanted(theFont);
  1476 +}
1428 1477
1429 1478
1430 1479
14 src/fmlayout.h
@@ -89,10 +89,9 @@ class FMLayout : public QObject
89 89 Q_OBJECT
90 90
91 91 public:
92   - explicit FMLayout ( QGraphicsScene* scene, FontItem* font, QRectF rect = QRectF());
  92 + explicit FMLayout ( QGraphicsScene* scene, FontItem* font = 0, QRectF rect = QRectF());
93 93 ~FMLayout();
94   - void doLayout(const QList<GlyphList>& spec , double fs);
95   -// static FMLayout *getLayout();
  94 + void doLayout(const QList<GlyphList>& spec , double fs, FontItem* font = 0 );
96 95
97 96 private://methods
98 97 /// Build a graph on node
@@ -118,6 +117,8 @@ class FMLayout : public QObject
118 117 // QMutex *layoutMutex;
119 118 bool stopIt;
120 119 int drawnLines;
  120 +
  121 + void setContext(bool c);
121 122
122 123 public slots:
123 124 void stopLayout();
@@ -125,6 +126,7 @@ class FMLayout : public QObject
125 126 private:// data
126 127 // Argued
127 128 // static FMLayout *instance;
  129 + bool contextIsMainThread;
128 130 QGraphicsScene* theScene;
129 131 FontItem* theFont;
130 132 QList<GlyphList> paragraphs;
@@ -186,6 +188,12 @@ class FMLayout : public QObject
186 188 void slotOption(int v);
187 189
188 190 signals:
  191 + // needed if layout is executed outside the main (GUI) thread
  192 + // receiver is expected to know with what font and on which scene;
  193 + void drawPixmapForMe(int index, double fontsize, double x, double y);
  194 + void drawBaselineForMe(double y);
  195 + void clearScene();
  196 + void objectWanted(QObject*);
189 197 void updateLayout();
190 198 void layoutFinished();
191 199 void paragraphFinished();
160 src/fontitem.cpp
@@ -23,6 +23,7 @@
23 23 #include "fmencdata.h"
24 24 #include "fmfontdb.h"
25 25 #include "fmfontstrings.h"
  26 +#include "fmfreetypelib.h"
26 27 #include "fmglyphsview.h"
27 28 #include "glyphtosvghelper.h"
28 29 #include "typotek.h"
@@ -36,6 +37,7 @@
36 37 #include <QDebug>
37 38 #include <QFileInfo>
38 39 #include <QGraphicsPixmapItem>
  40 +#include <QGraphicsObject>
39 41 #include <QGraphicsScene>
40 42 #include <QGraphicsView>
41 43 #include <QGraphicsPathItem>
@@ -63,7 +65,6 @@
63 65
64 66 int fm_num_face_opened = 0;
65 67
66   -FT_Library FontItem::theLibrary = 0;
67 68 QGraphicsScene *FontItem::theOneLineScene = 0;
68 69
69 70
@@ -217,7 +218,7 @@ FontItem::FontItem ( QString path , bool remote, bool faststart )
217 218 remoteCached = false;
218 219 stopperDownload = false;
219 220 m_face = 0;
220   - facesRef = 0;
  221 + lastFace = 0;
221 222 m_glyphsPerRow = 5;
222 223 m_isEncoded = false;
223 224 currentChar = -1;
@@ -343,7 +344,7 @@ FontItem::FontItem(QString path, QString family, QString variant, QString type,b
343 344 remoteCached = false;
344 345 stopperDownload = false;
345 346 m_face = 0;
346   - facesRef = 0;
  347 + lastFace = 0;
347 348 m_glyphsPerRow = 5;
348 349 m_isEncoded = false;
349 350 currentChar = -1;
@@ -378,6 +379,12 @@ FontItem::FontItem(QString path, QString family, QString variant, QString type,b
378 379 m_type = type;
379 380 }
380 381
  382 +FontItem * FontItem::Clone()
  383 +{
  384 + FontItem *fitem = new FontItem ( m_path, m_family, m_variant, m_type, m_active );
  385 + return fitem;
  386 +}
  387 +
381 388 void FontItem::updateItem()
382 389 {
383 390 if(isUpToDate)
@@ -441,18 +448,6 @@ FontItem::~FontItem()
441 448 }
442 449 }
443 450
444   -bool FontItem::ensureLibrary()
445   -{
446   - if ( theLibrary )
447   - return true;
448   - ft_error = FT_Init_FreeType ( &theLibrary );
449   - if ( ft_error )
450   - {
451   - qDebug() << "Error loading ft_library ";
452   - return false;
453   - }
454   - return true;
455   -}
456 451
457 452 void FontItem::encodeFace()
458 453 {
@@ -508,40 +503,39 @@ void FontItem::encodeFace()
508 503
509 504 bool FontItem::ensureFace()
510 505 {
511   - if ( ensureLibrary() )
  506 + FT_Library ftlib = FMFreetypeLib::lib(thread());
  507 +// qDebug()<<"FontItem::ensureFace"<<thread();
  508 +
  509 + if ( m_face )
512 510 {
513   - if ( m_face )
514   - {
515   - ++facesRef;
516   - return true;
517   - }
518   - QString trueFile ( m_remote ? remoteHerePath : m_path );
519   - ft_error = FT_New_Face ( theLibrary, trueFile.toLocal8Bit() , 0, &m_face );
520   - if ( ft_error )
521   - {
522   - qDebug() << "Error loading face [" << trueFile <<"]";
523   - return false;
524   - }
525   - encodeFace();
526   - if ( spaceIndex.isEmpty() )
  511 + ++facesRef;
  512 + return true;
  513 + }
  514 + QString trueFile ( m_remote ? remoteHerePath : m_path );
  515 + ft_error = FT_New_Face ( ftlib, trueFile.toLocal8Bit() , 0, &m_face );
  516 + if ( ft_error )
  517 + {
  518 + qDebug() << "Error loading face [" << trueFile <<"]";
  519 + return false;
  520 + }
  521 + encodeFace();
  522 + if ( spaceIndex.isEmpty() )
  523 + {
  524 + int gIndex ( 0 );
  525 + for ( int i ( 0 ); i < legitimateNonPathChars.count(); ++i )
527 526 {
528   - int gIndex ( 0 );
529   - for ( int i ( 0 ); i < legitimateNonPathChars.count(); ++i )
  527 + gIndex = FT_Get_Char_Index ( m_face , legitimateNonPathChars[i] );
  528 + if ( gIndex )
530 529 {
531   - gIndex = FT_Get_Char_Index ( m_face , legitimateNonPathChars[i] );
532   - if ( gIndex )
533   - {
534   - spaceIndex << gIndex;
535   - }
  530 + spaceIndex << gIndex;
536 531 }
537 532 }
538   - unitPerEm = m_face->units_per_EM;
539   - m_glyph = m_face->glyph;
540   - ++facesRef;
541   - ++fm_num_face_opened;
542   - return true;
543 533 }
544   - return false;
  534 + unitPerEm = m_face->units_per_EM;
  535 + m_glyph = m_face->glyph;
  536 + facesRef = 1;
  537 + ++fm_num_face_opened;
  538 + return true;
545 539 }
546 540
547 541 void FontItem::releaseFace()
@@ -735,8 +729,8 @@ QGraphicsPixmapItem * FontItem::itemFromGindexPix ( int index, double size )
735 729 }
736 730
737 731 double takeAdvanceBeforeRender = m_glyph->metrics.horiAdvance * ( typotek::getInstance()->getDpiX() / 72.0 );
738   - double takeVertAdvanceBeforeRender = m_glyph->metrics.vertAdvance * ( typotek::getInstance()->getDpiX() / 72.0 );
739   - double takeLeftBeforeRender = ( double ) m_glyph->metrics.horiBearingX * ( typotek::getInstance()->getDpiX() / 72.0 );
  732 + double takeVertAdvanceBeforeRender = m_glyph->metrics.vertAdvance * ( typotek::getInstance()->getDpiY() / 72.0 );
  733 + double takeLeftBeforeRender = double(m_glyph->metrics.horiBearingX) * ( typotek::getInstance()->getDpiX() / 72.0 );
740 734
741 735 // if(m_FTHintMode != FT_LOAD_NO_HINTING)
742 736 {
@@ -785,7 +779,7 @@ QGraphicsPixmapItem * FontItem::itemFromGindexPix ( int index, double size )
785 779 // we need to transport more data
786 780 glyph->setData ( GLYPH_DATA_GLYPH , index );
787 781 glyph->setData ( GLYPH_DATA_BITMAPLEFT , takeLeftBeforeRender );
788   - glyph->setData ( GLYPH_DATA_BITMAPTOP , m_face->glyph->bitmap_top );
  782 + glyph->setData ( GLYPH_DATA_BITMAPTOP , double(m_face->glyph->bitmap_top) );
789 783 glyph->setData ( GLYPH_DATA_HADVANCE , takeAdvanceBeforeRender );
790 784 glyph->setData ( GLYPH_DATA_VADVANCE , takeVertAdvanceBeforeRender );
791 785 }
@@ -794,6 +788,78 @@ QGraphicsPixmapItem * FontItem::itemFromGindexPix ( int index, double size )
794 788 return glyph;
795 789 }
796 790
  791 +MetaGlyphItem * FontItem::itemFromGindexPix_mt(int index, double size)
  792 +{
  793 + if ( !ensureFace() )
  794 + return 0;
  795 + int charcode = index ;
  796 +// qDebug()<<"FontItem::itemFromGindexPix_mt"<< thread();
  797 + MetaGlyphItem * glyph = new MetaGlyphItem;
  798 + double scaleFactor = size / m_face->units_per_EM;
  799 +
  800 + // Set size
  801 + FT_Set_Char_Size ( m_face,
  802 + qRound( size * 64 ),
  803 + 0,
  804 + typotek::getInstance()->getDpiX(),
  805 + typotek::getInstance()->getDpiY() );
  806 +
  807 + // Grab metrics in FONT UNIT
  808 + ft_error = FT_Load_Glyph ( m_face,
  809 + charcode ,
  810 + FT_LOAD_NO_SCALE );
  811 + if ( ft_error )
  812 + {
  813 + glyph->setMetaData ( GLYPH_DATA_GLYPH ,index );
  814 + glyph->setMetaData ( GLYPH_DATA_BITMAPLEFT , 0 );
  815 + glyph->setMetaData ( GLYPH_DATA_BITMAPTOP,size );
  816 + glyph->setMetaData ( GLYPH_DATA_HADVANCE ,size / scaleFactor );
  817 + releaseFace();
  818 + return glyph;
  819 + }
  820 +
  821 + double takeAdvanceBeforeRender = m_glyph->metrics.horiAdvance * ( typotek::getInstance()->getDpiX() / 72.0 );
  822 + double takeVertAdvanceBeforeRender = m_glyph->metrics.vertAdvance * ( typotek::getInstance()->getDpiX() / 72.0 );
  823 + double takeLeftBeforeRender = ( double ) m_glyph->metrics.horiBearingX * ( typotek::getInstance()->getDpiX() / 72.0 );
  824 +
  825 +// if(m_FTHintMode != FT_LOAD_NO_HINTING)
  826 + {
  827 + ft_error = FT_Load_Glyph ( m_face, charcode , FT_LOAD_DEFAULT | m_FTHintMode );
  828 + }
  829 + // Render the glyph into a grayscale bitmap
  830 + ft_error = FT_Render_Glyph ( m_face->glyph, FT_RENDER_MODE_NORMAL );
  831 + if ( ft_error )
  832 + {
  833 + glyph->setMetaData ( GLYPH_DATA_GLYPH , index );
  834 + glyph->setMetaData ( GLYPH_DATA_BITMAPLEFT , 0 );
  835 + glyph->setMetaData ( GLYPH_DATA_BITMAPTOP,size );
  836 + glyph->setMetaData ( GLYPH_DATA_HADVANCE ,size / scaleFactor );
  837 + releaseFace();
  838 + return glyph;
  839 + }
  840 +
  841 +
  842 + QImage img ( glyphImage() );
  843 +
  844 + if ( img.isNull() && !spaceIndex.contains ( index ) )
  845 + {
  846 + glyph->setMetaData ( GLYPH_DATA_GLYPH , index );
  847 + glyph->setMetaData ( GLYPH_DATA_BITMAPLEFT , 0 );
  848 + glyph->setMetaData ( GLYPH_DATA_BITMAPTOP,size );
  849 + glyph->setMetaData ( GLYPH_DATA_HADVANCE ,size /scaleFactor );
  850 + }
  851 + else
  852 + {
  853 + glyph->setMetaData ( GLYPH_DATA_GLYPH , index );
  854 + glyph->setMetaData ( GLYPH_DATA_BITMAPLEFT , takeLeftBeforeRender );
  855 + glyph->setMetaData ( GLYPH_DATA_BITMAPTOP , double(m_face->glyph->bitmap_top) );
  856 + glyph->setMetaData ( GLYPH_DATA_HADVANCE , takeAdvanceBeforeRender );
  857 + glyph->setMetaData ( GLYPH_DATA_VADVANCE , takeVertAdvanceBeforeRender );
  858 + }
  859 +
  860 + releaseFace();
  861 + return glyph;
  862 +}
797 863
798 864 QImage FontItem::charImage(int charcode, double size)
799 865 {
@@ -3107,7 +3173,7 @@ void FontItem::fileRemote ( QString f , QString v, QString t, QString i, QPixmap
3107 3173 m_variant = v;
3108 3174 m_type = t;
3109 3175 // m_cacheInfo = i;
3110   - fixedPixmap = p;
  3176 +// fixedPixmap = p;
3111 3177 }
3112 3178
3113 3179 /// the same, but just for speedup startup with a lot of font files
38 src/fontitem.h
@@ -32,6 +32,9 @@
32 32 #include <QUrl>
33 33 #include <QFlags>
34 34 // #include <QThread>
  35 +#include <QGraphicsItem>
  36 +#include <QRectF>
  37 +#include <QVariant>
35 38
36 39 #include <ft2build.h>
37 40 #include FT_FREETYPE_H
@@ -45,6 +48,7 @@ class QGraphicsTextItem;
45 48 struct OTFSet;
46 49 class FMOtf;
47 50 class QGraphicsView;
  51 +class QGraphicsObject;
48 52
49 53 class QProgressDialog;
50 54 class QHttp;
@@ -85,6 +89,22 @@ struct FontLocalInfo
85 89 QPixmap pix;
86 90 };
87 91
  92 +class MetaGlyphItem : public QGraphicsItem
  93 +{
  94 + QMap<int, QVariant> m_Data;
  95 +public:
  96 + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){}
  97 + QRectF boundingRect() const {return QRectF();}
  98 + void setMetaData(int key, const QVariant &value)
  99 + {
  100 + m_Data.insert(key,value);
  101 + }
  102 + QVariant metaData(int key) const
  103 + {
  104 + return m_Data.value(key);
  105 + }
  106 +};
  107 +
88 108 class FontItem : public QObject
89 109 {
90 110 Q_OBJECT
@@ -109,6 +129,7 @@ class FontItem : public QObject
109 129
110 130 FontItem ( QString path , bool remote = false, bool faststart = false);
111 131 FontItem (QString path, QString family, QString variant, QString type , bool active);
  132 + FontItem * Clone();
112 133 /** Needed when the item has been instantiate with "faststart=true" */
113 134 void updateItem();
114 135 ~FontItem();
@@ -158,9 +179,11 @@ class FontItem : public QObject
158 179 bool m_isOpenType;
159 180 FMOtf *otf;
160 181
161   - static FT_Library theLibrary;
  182 +// FT_Library theLibrary;
  183 + FT_Face m_face;
  184 + FT_Face lastFace;
162 185 FT_Error ft_error;
163   - FT_Face m_face;
  186 +// QMap<FT_Library,FT_Face> faces;
164 187 int facesRef;
165 188 FT_GlyphSlot m_glyph;
166 189
@@ -172,8 +195,7 @@ class FontItem : public QObject
172 195 bool m_rasterFreetype;
173 196 unsigned int m_FTHintMode;
174 197 // unsigned int m_FTRenderMode;not yet implemented
175   -
176   - bool ensureLibrary();
  198 +
177 199 bool ensureFace();
178 200 void releaseFace();
179 201 void encodeFace();
@@ -193,7 +215,6 @@ class FontItem : public QObject
193 215 QMap<int, QGraphicsTextItem*> fancyTexts;
194 216 QMap<int, QList<QGraphicsPixmapItem*> > fancyAlternates;
195 217
196   - QPixmap fixedPixmap;
197 218
198 219 bool allIsRendered;
199 220 bool isDerendered;
@@ -298,9 +319,10 @@ class FontItem : public QObject
298 319 QGraphicsPathItem* itemFromChar ( int charcode, double size );
299 320 QGraphicsPathItem* itemFromGindex ( int index, double size );
300 321
301   - QGraphicsPixmapItem* itemFromCharPix ( int charcode, double size );
302   - QGraphicsPixmapItem* itemFromGindexPix ( int index, double size );
303   - QGraphicsPixmapItem* itemFromGindexPix_mt ( int index, double size );
  322 + QGraphicsPixmapItem* itemFromCharPix ( int charcode, double size);
  323 + QGraphicsPixmapItem* itemFromGindexPix ( int index, double size);
  324 + // cant have qpixmap outside main thread and QGraphicsPixmapItem create at least a null one when instantiated
  325 + MetaGlyphItem* itemFromGindexPix_mt ( int index, double size );
304 326
305 327 QImage charImage(int charcode, double size);
306 328 QImage glyphImage(int index, double size);
6 src/sampletoolbar.ui
@@ -25,7 +25,11 @@
25 25 </widget>
26 26 </item>
27 27 <item row="0" column="1">
28   - <widget class="QDoubleSpinBox" name="liveSize"/>
  28 + <widget class="QDoubleSpinBox" name="liveSize">
  29 + <property name="maximum">
  30 + <double>999.990000000000009</double>
  31 + </property>
  32 + </widget>
29 33 </item>
30 34 <item row="0" column="2">
31 35 <widget class="QToolButton" name="sampleButton">
156 src/samplewidget.cpp
@@ -29,6 +29,7 @@
29 29 #include "textprogression.h"
30 30 #include "opentypetags.h"
31 31
  32 +#include <QApplication>
32 33 #include <QMap>
33 34 #include <QTreeWidgetItem>
34 35 #include <QSettings>
@@ -41,7 +42,6 @@
41 42 #include <QSettings>
42 43 #include <QStyledItemDelegate>
43 44 #include <QKeyEvent>
44   -#include <QThread>
45 45
46 46
47 47 QByteArray SampleWidget::State::toByteArray() const
@@ -56,6 +56,25 @@ QByteArray SampleWidget::State::toByteArray() const
56 56 return b;
57 57 }
58 58
  59 +
  60 +void FMLayoutThread::setLayout(FMLayout * l, const QList<GlyphList>& spec , double fs, FontItem* f, unsigned int hinting)
  61 +{
  62 + pLayout = l;
  63 + pLayout->setContext(false);
  64 + gl = spec;
  65 + fontSize = fs;
  66 + font = f;
  67 + fHinting = hinting;
  68 +}
  69 +
  70 +void FMLayoutThread::run()
  71 +{
  72 + FontItem * tf(new FontItem(font->path(),font->family(),font->variant(),font->type(), font->isActivated()));
  73 + tf->setFTHintMode(fHinting);
  74 + pLayout->doLayout(gl, fontSize, tf);
  75 + delete tf;
  76 +}
  77 +
59 78 SampleWidget::State SampleWidget::State::fromByteArray(QByteArray b)
60 79 {
61 80 QDataStream ds(&b, QIODevice::ReadOnly);
@@ -90,6 +109,7 @@ SampleWidget::SampleWidget(const QString& fid, QWidget *parent) :
90 109 layoutTimer = new QTimer(this);
91 110 layoutWait = 1000;
92 111 layoutForPrint = false;
  112 + layoutSwitch = false;
93 113 ui->setupUi(this);
94 114 // ui->textProgression->setVisible(false);
95 115
@@ -125,12 +145,12 @@ SampleWidget::SampleWidget(const QString& fid, QWidget *parent) :
125 145 ui->loremView_FT->locker = false;
126 146 ui->loremView_FT->fakePage();
127 147
  148 + layoutThread = new FMLayoutThread;
  149 +
128 150 FontItem * cf(FMFontDb::DB()->Font(fid));
129 151 textLayoutVect = new FMLayout(loremScene, cf);
130   - textLayoutFT = new FMLayout(ftScene, cf);
  152 + textLayoutFT = new FMLayout(ftScene);
131 153
132   - layoutThread = new QThread(this);
133   - textLayoutFT->moveToThread(layoutThread);
134 154
135 155 QSettings settings;
136 156 State s;
@@ -141,7 +161,7 @@ SampleWidget::SampleWidget(const QString& fid, QWidget *parent) :
141 161 sampleInterSize = sampleFontSize * sampleRatio;
142 162
143 163 createConnections();
144   - slotView(true);
  164 + slotView();
145 165 }
146 166
147 167 SampleWidget::~SampleWidget()
@@ -198,7 +218,8 @@ void SampleWidget::createConnections()
198 218 connect(sampleNameEditor, SIGNAL(closeEditor(QWidget*)), this, SLOT(slotSampleNameEdited(QWidget*)));
199 219 connect(ui->sampleEdit, SIGNAL(textChanged()), this, SLOT(slotUpdateSample()));
200 220
201   - connect(layoutTimer, SIGNAL(timeout()), this, SLOT(slotUpdateSample()));
  221 +
  222 + connect(textLayoutFT, SIGNAL(clearScene()), this, SLOT(clearFTScene()));
202 223 }
203 224
204 225
@@ -231,7 +252,6 @@ void SampleWidget::removeConnections()
231 252 disconnect(ui->toolbar, SIGNAL(Detach()), this, SLOT(ddetach()));
232 253
233 254 disconnect(sysWatcher, SIGNAL(fileChanged(QString)),this, SLOT(slotFileChanged(QString)));
234   - disconnect(reloadTimer,SIGNAL(timeout()), this, SLOT(slotReload()));
235 255
236 256 disconnect(this, SIGNAL(stateChanged()), this, SLOT(saveState()));
237 257 }
@@ -325,18 +345,15 @@ void SampleWidget::setState(const SampleWidget::State &s)
325 345 slotEditSample();
326 346 }
327 347
328   -void SampleWidget::slotView ( bool needDeRendering )
  348 +void SampleWidget::slotView()
329 349 {
330   - qDebug()<<"SampleWidget::slotView ";
  350 + qDebug()<<"SampleWidget::slotView "<< fontIdentifier;
  351 +// disconnect(textLayoutFT, SIGNAL(drawBaselineForMe(double)), this, SLOT(drawBaseline(double)));
331 352 QTime t;
332 353 t.start();
333 354 FontItem *f(FMFontDb::DB()->Font( fontIdentifier ));
334 355 if ( !f )
335 356 return;
336   - if ( needDeRendering )
337   - {
338   -// f->deRenderAll();
339   - }
340 357
341 358 bool wantDeviceDependant = !layoutForPrint;
342 359 if(wantDeviceDependant)
@@ -357,10 +374,17 @@ void SampleWidget::slotView ( bool needDeRendering )
357 374
358 375 // if ( ui->loremView->isVisible() || ui->loremView_FT->isVisible() || layoutForPrint)
359 376 {
360   - if(!textLayoutFT->isLayoutFinished())
  377 + if(!layoutForPrint && !textLayoutFT->isLayoutFinished())
361 378 {
  379 + connect(textLayoutFT, SIGNAL(layoutFinished()), this, SLOT(slotView()));
362 380 textLayoutFT->stopLayout();
363 381 qDebug()<<"\tLayout stopped";
  382 + layoutSwitch = false;
  383 + return;
  384 + }
  385 + else
  386 + {
  387 + disconnect(textLayoutFT, SIGNAL(layoutFinished()), this, SLOT(slotView()));
364 388 }
365 389 // else if(textLayoutVect->isRunning())
366 390 // textLayoutVect->stopLayout();
@@ -385,6 +409,7 @@ void SampleWidget::slotView ( bool needDeRendering )
385 409
386 410 QList<GlyphList> list;
387 411 QStringList stl( typotek::getInstance()->namedSample().split("\n"));
  412 +// qDebug()<<"Sample:\n\t"<<stl.join("\n\t");
388 413 if ( processScript )
389 414 {
390 415 for(int p(0);p<stl.count();++p)
@@ -404,17 +429,70 @@ void SampleWidget::slotView ( bool needDeRendering )
404 429 for(int p(0);p<stl.count();++p)
405 430 list << f->glyphs( stl[p] , fSize );
406 431 }
407   - textLayout->doLayout(list, fSize);
408   -
  432 + if(!layoutForPrint)
  433 + {
  434 + layoutThread->setLayout(textLayout, list, fSize, f, hinting());
  435 + connect(textLayout, SIGNAL(drawPixmapForMe(int,double,double,double)), this, SLOT(drawPixmap(int,double,double,double)));
  436 +// connect(textLayoutFT, SIGNAL(drawBaselineForMe(double)), this, SLOT(drawBaseline(double)));
  437 + connect(textLayout, SIGNAL(layoutFinished()), this, SLOT(endLayout()));
  438 + layoutSwitch = true;
  439 + pixmapDrawn = 0;
  440 + layoutThread->start();
  441 + }
  442 + else
409 443 {
410   - QPointF texttopLeft(ui->loremView_FT->mapFromScene(textLayout->getRect().topLeft()));
411   - ui->loremView_FT->translate( 10 -texttopLeft.x(), 10 -texttopLeft.y());
  444 + textLayout->doLayout(list, fSize);
412 445 }
413 446 }
414 447 }
415 448
416 449 }
417 450
  451 +void SampleWidget::drawPixmap(int index, double fontsize, double x, double y)
  452 +{
  453 +// qDebug()<<"SampleWidget::drawPixmap index:"<<index<< "Y:"<<y;
  454 + if(index < 0)
  455 + disconnect(textLayoutFT, SIGNAL(drawPixmapForMe(int,double,double,double)), this, SLOT(drawPixmap(int,double,double,double)));
  456 + FontItem * f( FMFontDb::DB()->Font( fontIdentifier ) );
  457 + if(!f)
  458 + return;
  459 + ++pixmapDrawn;
  460 + QGraphicsPixmapItem *glyph = f->itemFromGindexPix ( index , fontsize );
  461 +// qDebug()<<"SampleWidget::drawPixmap index:"<<index<< y << glyph->data(GLYPH_DATA_BITMAPTOP).toDouble();
  462 + ftScene->addItem ( glyph );
  463 + glyph->setZValue ( 100.0 );
  464 + glyph->setPos ( x,y );
  465 +// QGraphicsLineItem * l = ftScene->addLine(x,y,x,y + glyph->data(GLYPH_DATA_BITMAPTOP).toDouble());
  466 +// l->setData(GLYPH_DATA_GLYPH, 1);
  467 +// glyph->pixmap().toImage().save(QString("/tmp/%1.png").arg(index));
  468 +}
  469 +
  470 +void SampleWidget::drawBaseline(double y)
  471 +{
  472 + QGraphicsLineItem * l = ftScene->addLine(0,y,ftScene->width(),y);
  473 + l->setData(GLYPH_DATA_GLYPH, 1);
  474 +}
  475 +
  476 +void SampleWidget::clearFTScene()
  477 +{
  478 + qDebug()<<"SampleWidget::clearFTScene"<< layoutSwitch;
  479 +// if(layoutSwitch)
  480 +// return;
  481 + foreach(QGraphicsItem* gi, ftScene->items())
  482 + {
  483 + if(gi->data(GLYPH_DATA_GLYPH).toInt() > 0)
  484 + delete gi;
  485 + }
  486 +}
  487 +
  488 +void SampleWidget::endLayout()
  489 +{
  490 + QPointF texttopLeft(ui->loremView_FT->mapFromScene(textLayoutFT->getRect().topLeft()));
  491 + ui->loremView_FT->translate( 10 -texttopLeft.x(), 10 -texttopLeft.y());
  492 + ui->loremView_FT->update();
  493 +// qDebug()<<"Pixmaps:"<<pixmapDrawn;
  494 +
  495 +}
418 496
419 497 void SampleWidget::fillOTTree()
420 498 {
@@ -601,7 +679,7 @@ OTFSet SampleWidget::deFillOTTree()
601 679 void SampleWidget::slotUpdateSView()
602 680 {
603 681 if(ui->loremView->isVisible())
604   - slotView(true);
  682 + slotView();
605 683 }
606 684
607 685
@@ -633,14 +711,14 @@ void SampleWidget::slotZoom ( int z )
633 711 void SampleWidget::slotUpdateRView()
634 712 {
635 713 if(ui->loremView_FT->isVisible())
636   - slotView(true);
  714 + slotView();
637 715 }
638 716
639 717 void SampleWidget::slotSampleChanged()
640 718 {
641 719 typotek::getInstance()->namedSample( ui->sampleTextTree->currentItem()->data(0, Qt::UserRole).toString() );
642 720 ui->removeSampleButton->setEnabled(ui->sampleTextTree->currentItem()->parent() == uRoot);
643   - slotView ( true );
  721 + slotView ( );
644 722 emit stateChanged();
645 723 }
646 724
@@ -650,14 +728,14 @@ void SampleWidget::slotLiveFontSize(double fs)
650 728 {
651 729 // double fs( sampleToolBar->getFontSize() );
652 730 reSize(fs, fs * sampleRatio);
653   - slotView(true);
  731 + slotView();
654 732 emit stateChanged();
655 733 }
656 734
657 735 void SampleWidget::slotFeatureChanged()
658 736 {
659 737 // OTFSet ret = deFillOTTree();
660   - slotView ( true );
  738 + slotView ( );
661 739 emit stateChanged();
662 740 }
663 741
@@ -685,19 +763,19 @@ void SampleWidget::slotChangeScript()
685 763 {
686 764 if ( ui->useShaperCheck->checkState() == Qt::Checked )
687 765 {
688   - slotView ( true );
  766 + slotView ( );
689 767 }
690 768 emit stateChanged();
691 769 }
692 770
693 771 void SampleWidget::slotProgressionChanged()
694 772 {
695   - slotView(true);
  773 + slotView();
696 774 }
697 775
698 776 void SampleWidget::slotWantShape()
699 777 {
700   - slotView ( true );
  778 + slotView ( );
701 779 emit stateChanged();
702 780 }
703 781
@@ -770,7 +848,7 @@ void SampleWidget::slotPrint()
770 848 if(!font)
771 849 return;
772 850 layoutForPrint = true;
773   - slotView(false);
  851 + slotView();
774 852 // if( textLayoutVect->isRunning() )
775 853 // {
776 854 // connect(textLayoutVect, SIGNAL(paintFinished()), this,SLOT(slotPrint()));
@@ -907,28 +985,6 @@ void SampleWidget::slotEditSample()
907 985 void SampleWidget::slotUpdateSample()
908 986 {
909 987 typotek::getInstance()->changeSample(ui->sampleTextTree->currentItem()->text(0), ui->sampleEdit->toPlainText());
910   - slotView(true);
911   -// if(firstUpdateRequest)
912   -// {
913   -// typotek::getInstance()->changeSample(ui->sampleTextTree->currentItem()->text(0), ui->sampleEdit->toPlainText());
914   -// slotView(true);
915   -// firstUpdateRequest = false;
916   -// firstUpdateRequestTimeStamp = layoutTime.elapsed();
917   -// }
918   -// else
919   -// {
920   -// if((layoutTime.elapsed() - firstUpdateRequestTimeStamp) < layoutWait)
921   -// {
922   -// firstUpdateRequestTimeStamp = layoutTime.elapsed();
923   -// layoutTimer->start(layoutWait);
924   -// }
925   -// else
926   -// {
927   -// layoutTimer->stop();
928   -// firstUpdateRequest = true;
929   -// typotek::getInstance()->changeSample(ui->sampleTextTree->currentItem()->text(0), ui->sampleEdit->toPlainText());
930   -// slotView(true);
931   -// }
932   -// }
  988 + slotView();
933 989 }
934 990
26 src/samplewidget.h
@@ -27,6 +27,7 @@
27 27 #include <QString>
28 28 #include <QByteArray>
29 29 #include <QTime>
  30 +#include <QThread>
30 31
31 32 class QGraphicsScene;
32 33 class FMLayout;
@@ -37,7 +38,7 @@ class QTimer;
37 38 class SampleToolBar;
38 39 class QTreeWidgetItem;
39 40 class QStyledItemDelegate;
40   -class QThread;
  41 +class FontItem;
41 42
42 43 namespace Ui {
43 44 class SampleWidget;
@@ -49,6 +50,19 @@ namespace Ui {
49 50 //#define VIEW_PAGE_SETTINGS 1
50 51 #define VIEW_PAGE_SAMPLES 4
51 52
  53 +class FMLayoutThread : public QThread
  54 +{
  55 + FMLayout * pLayout;
  56 + QList<GlyphList> gl;
  57 + double fontSize;
  58 + FontItem * font;
  59 + unsigned int fHinting;
  60 +
  61 +public:
  62 + void setLayout(FMLayout * l, const QList<GlyphList>& spec , double fs, FontItem * f, unsigned int hinting);
  63 + void run();
  64 +};
  65 +
52 66 class SampleWidget : public FloatingWidget
53 67 {
54 68 Q_OBJECT
@@ -133,12 +147,18 @@ class SampleWidget : public FloatingWidget
133 147 QTime layoutTime;
134 148 QTimer *layoutTimer;
135 149 int layoutWait;
136   - QThread * layoutThread;
  150 + FMLayoutThread * layoutThread;
  151 + bool layoutSwitch;
  152 + int pixmapDrawn;
137 153