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 "samplewidget.h"
22 #include "sampletoolbar.h"
23 #include "ui_samplewidget.h"
24 #include "typotek.h"
25 #include "fmbaseshaper.h"
26 #include "fmfontdb.h"
27 #include "fontitem.h"
28 #include "fmlayout.h"
29 #include "textprogression.h"
30 #include "opentypetags.h"
31
32 #include <QApplication>
33 #include <QMap>
34 #include <QTreeWidgetItem>
35 #include <QSettings>
36 #include <QPrintDialog>
37 #include <QPrinter>
38 #include <QFileSystemWatcher>
39 #include <QDebug>
40 #include <QTimer>
41 #include <QDataStream>
42 #include <QSettings>
43 #include <QStyledItemDelegate>
44 #include <QKeyEvent>
45 #include <QDateTime>
46
47
toByteArray() const48 QByteArray SampleWidget::State::toByteArray() const
49 {
50 QByteArray b;
51 QDataStream ds(&b, QIODevice::WriteOnly);
52 ds << sampleName;
53 ds << fontSize;
54 ds << renderHinting;
55 ds << shaper;
56 ds << script;
57 return b;
58 }
59
60
setLayout(FMLayout * l,const QList<GlyphList> & spec,double fs,FontItem * f,unsigned int hinting)61 void FMLayoutThread::setLayout(FMLayout * l, const QList<GlyphList>& spec , double fs, FontItem* f, unsigned int hinting)
62 {
63 pLayout = l;
64 pLayout->setContext(false);
65 gl = spec;
66 fontSize = fs;
67 font = f;
68 fHinting = hinting;
69 }
70
run()71 void FMLayoutThread::run()
72 {
73 FontItem * tf(new FontItem(font->path(),font->family(),font->variant(),font->type(), font->isActivated()));
74 tf->setFTHintMode(fHinting);
75 pLayout->doLayout(gl, fontSize, tf);
76 delete tf;
77 }
78
fromByteArray(QByteArray b)79 SampleWidget::State SampleWidget::State::fromByteArray(QByteArray b)
80 {
81 QDataStream ds(&b, QIODevice::ReadOnly);
82 QString sn;
83 double fs;
84 unsigned int rh;
85 QString sh;
86 QString sc;
87 ds >> sn;
88 ds >> fs;
89 ds >> rh;
90 ds >> sh;
91 ds >> sc;
92 // State* pState(new State(sn,fs,rh,sh,sc));
93 // State rState(*pState);
94 sampleName = sn;
95 fontSize = fs;
96 renderHinting = rh;
97 shaper = sh;
98 script = sc;
99 // return State(sn,fs,rh,sh,sc);
100 return *this;
101 }
102
103 const QString SampleWidget::Name = QObject::tr("Sample");
104
SampleWidget(const QString & fid,QWidget * parent)105 SampleWidget::SampleWidget(const QString& fid, QWidget *parent) :
106 FloatingWidget(fid, Name, parent),
107 ui(new Ui::SampleWidget),
108 fontIdentifier(fid)
109 {
110 layoutTimer = new QTimer(this);
111 layoutWait = 1000;
112 layoutForPrint = false;
113 layoutSwitch = false;
114 ui->setupUi(this);
115 // ui->textProgression->setVisible(false);
116
117 sampleToolBar = new SampleToolBar(this);
118 ui->sampleGridLayout->addWidget(sampleToolBar, 1,0, Qt::AlignRight | Qt::AlignBottom);
119
120
121 sampleNameEditor = new QStyledItemDelegate(ui->sampleTextTree);
122 ui->sampleTextTree->setItemDelegate(sampleNameEditor);
123 refillSampleList();
124 fillOTTree();
125
126 #ifdef PLATFORM_APPLE
127 fileInfo.setFile(fid);
128 fileLastModified = fileInfo.lastModified().toMSecsSinceEpoch();
129 #endif
130 sysWatcher = new QFileSystemWatcher(this);
131 sysWatcher->addPath(fid);
132 reloadTimer = new QTimer(this);
133 reloadTimer->setInterval(1000);
134
135 loremScene = new QGraphicsScene;
136 ftScene = new QGraphicsScene;
137 QRectF pageRect ( 0,0,597.6,842.4 ); //TODO find means to smartly decide of page size (here, iso A4)
138
139 loremScene->setSceneRect ( pageRect );
140
141 ftScene->setSceneRect ( 0,0, 597.6 * typotek::getInstance()->getDpiX() / 72.0, 842.4 * typotek::getInstance()->getDpiX() / 72.0);
142 ui->loremView->setScene ( loremScene );
143 ui->loremView->locker = false;
144 double horiScaleT (typotek::getInstance()->getDpiX() / 72.0);
145 double vertScaleT ( typotek::getInstance()->getDpiY() / 72.0);
146 QTransform adjustAbsoluteViewT( horiScaleT , 0, 0,vertScaleT, 0, 0 );
147 ui->loremView->setTransform ( adjustAbsoluteViewT , false );
148
149 ui->loremView_FT->setScene ( ftScene );
150 ui->loremView_FT->locker = false;
151 ui->loremView_FT->fakePage();
152
153 layoutThread = new FMLayoutThread;
154
155 FontItem * cf(FMFontDb::DB()->Font(fid));
156 textLayoutVect = new FMLayout(loremScene, cf);
157 textLayoutFT = new FMLayout(ftScene);
158
159
160 QSettings settings;
161 State s;
162 s.fontSize = 14;
163 QByteArray bs = settings.value("Sample/state", s.toByteArray()).toByteArray();
164 setState(s.fromByteArray(bs));
165 sampleRatio = 1.2;
166 sampleInterSize = sampleFontSize * sampleRatio;
167
168 createConnections();
169 slotView();
170 }
171
~SampleWidget()172 SampleWidget::~SampleWidget()
173 {
174 removeConnections();
175 delete ui;
176 delete loremScene;
177 delete ftScene;
178 delete textLayoutFT;
179 delete textLayoutVect;
180 }
181
createConnections()182 void SampleWidget::createConnections()
183 {
184 // connections
185
186 connect ( ui->loremView, SIGNAL(pleaseUpdateMe()), this, SLOT(slotUpdateSView()));
187 connect ( ui->loremView, SIGNAL(pleaseZoom(int)),this,SLOT(slotZoom(int)));
188
189 connect ( ui->loremView_FT, SIGNAL(pleaseZoom(int)),this,SLOT(slotZoom(int)));
190 connect ( ui->loremView_FT, SIGNAL(pleaseUpdateMe()), this, SLOT(slotUpdateRView()));
191
192 connect ( textLayoutVect, SIGNAL(updateLayout()),this, SLOT(slotView()));
193 connect ( this, SIGNAL(stopLayout()), textLayoutVect,SLOT(stopLayout()));
194 connect ( textLayoutFT, SIGNAL(updateLayout()),this, SLOT(slotView()));
195 connect ( this, SIGNAL(stopLayout()), textLayoutFT,SLOT(stopLayout()));
196
197 connect ( ui->sampleTextTree,SIGNAL ( itemSelectionChanged ()),this,SLOT ( slotSampleChanged() ) );
198 connect ( ui->sampleTextTree,SIGNAL ( itemSelectionChanged ()),this,SLOT ( slotEditSample() ) );
199 connect ( sampleToolBar, SIGNAL( SizeChanged(double) ),this,SLOT(slotLiveFontSize(double)));
200
201 connect ( ui->OpenTypeTree, SIGNAL ( itemClicked ( QTreeWidgetItem*, int ) ), this, SLOT ( slotFeatureChanged() ) );
202 connect ( ui->saveDefOTFBut, SIGNAL(released()),this,SLOT(slotDefaultOTF()));
203 connect ( ui->resetDefOTFBut, SIGNAL(released()),this,SLOT(slotResetOTF()));
204
205 // connect ( ui->textProgression, SIGNAL ( stateChanged ( ) ),this ,SLOT(slotProgressionChanged()));
206
207 connect(ui->toolbar, SIGNAL(Print()), this, SLOT(slotPrint()));
208 connect(ui->toolbar, SIGNAL(Close()), this, SLOT(close()));
209 connect(ui->toolbar, SIGNAL(Hide()), this, SLOT(hide()));
210 connect(ui->toolbar, SIGNAL(Detach()), this, SLOT(ddetach()));
211
212 connect(sysWatcher, SIGNAL(fileChanged(QString)),this, SLOT(slotFileChanged(QString)));
213 connect(reloadTimer,SIGNAL(timeout()), this, SLOT(slotReload()));
214
215 connect(this, SIGNAL(stateChanged()), this, SLOT(saveState()));
216
217 connect(sampleToolBar, SIGNAL(OpenTypeToggled(bool)), this, SLOT(slotShowOpenType(bool)));
218 connect(sampleToolBar, SIGNAL(SampleToggled(bool)), this, SLOT(slotShowSamples(bool)));
219 connect(sampleToolBar, SIGNAL(ScriptSelected()), this, SLOT(slotScriptChange()));
220
221 connect(ui->addSampleButton, SIGNAL(clicked()), this, SLOT(slotAddSample()));
222 connect(ui->removeSampleButton, SIGNAL(clicked()), this, SLOT(slotRemoveSample()));
223 connect(sampleNameEditor, SIGNAL(closeEditor(QWidget*)), this, SLOT(slotSampleNameEdited(QWidget*)));
224 connect(ui->sampleEdit, SIGNAL(textChanged()), this, SLOT(slotUpdateSample()));
225
226
227 connect(textLayoutFT, SIGNAL(clearScene()), this, SLOT(clearFTScene()));
228 }
229
230
removeConnections()231 void SampleWidget::removeConnections()
232 {
233
234 disconnect ( ui->loremView, SIGNAL(pleaseUpdateMe()), this, SLOT(slotUpdateSView()));
235 disconnect ( ui->loremView, SIGNAL(pleaseZoom(int)),this,SLOT(slotZoom(int)));
236
237 disconnect ( ui->loremView_FT, SIGNAL(pleaseZoom(int)),this,SLOT(slotZoom(int)));
238 disconnect ( ui->loremView_FT, SIGNAL(pleaseUpdateMe()), this, SLOT(slotUpdateRView()));
239
240 disconnect ( textLayoutVect, SIGNAL(updateLayout()),this, SLOT(slotView()));
241 disconnect ( this, SIGNAL(stopLayout()), textLayoutVect,SLOT(stopLayout()));
242 disconnect ( textLayoutFT, SIGNAL(updateLayout()),this, SLOT(slotView()));
243 disconnect ( this, SIGNAL(stopLayout()), textLayoutFT,SLOT(stopLayout()));
244
245 disconnect ( ui->sampleTextTree,SIGNAL ( itemSelectionChanged ()),this,SLOT ( slotSampleChanged() ) );
246 disconnect ( sampleToolBar, SIGNAL( SizeChanged(double) ),this,SLOT(slotLiveFontSize(double)));
247
248 disconnect ( ui->OpenTypeTree, SIGNAL ( itemClicked ( QTreeWidgetItem*, int ) ), this, SLOT ( slotFeatureChanged() ) );
249 disconnect ( ui->saveDefOTFBut, SIGNAL(released()),this,SLOT(slotDefaultOTF()));
250 disconnect ( ui->resetDefOTFBut, SIGNAL(released()),this,SLOT(slotResetOTF()));
251
252 // disconnect ( ui->textProgression, SIGNAL ( stateChanged ( ) ),this ,SLOT(slotProgressionChanged()));
253
254 disconnect(ui->toolbar, SIGNAL(Print()), this, SLOT(slotPrint()));
255 disconnect(ui->toolbar, SIGNAL(Close()), this, SLOT(close()));
256 disconnect(ui->toolbar, SIGNAL(Hide()), this, SLOT(hide()));
257 disconnect(ui->toolbar, SIGNAL(Detach()), this, SLOT(ddetach()));
258
259 disconnect(sysWatcher, SIGNAL(fileChanged(QString)),this, SLOT(slotFileChanged(QString)));
260
261 disconnect(this, SIGNAL(stateChanged()), this, SLOT(saveState()));
262 }
263
changeEvent(QEvent * e)264 void SampleWidget::changeEvent(QEvent *e)
265 {
266 QWidget::changeEvent(e);
267 switch (e->type()) {
268 case QEvent::LanguageChange:
269 ui->retranslateUi(this);
270 break;
271 default:
272 break;
273 }
274 }
275
276
textScene() const277 QGraphicsScene * SampleWidget::textScene() const
278 {
279 return loremScene;
280 }
281
state() const282 SampleWidget::State SampleWidget::state() const
283 {
284 State ret;
285 ret.set = true;
286 ret.fontSize = sampleToolBar->getFontSize();
287 // ret.renderRaster = ui->freetypeRadio->isChecked();
288 ret.renderHinting = 0;
289 // if(ui->normalHinting->isChecked())
290 // ret.renderHinting = 1;
291 // else if(ui->lightHinting->isChecked())
292 // ret.renderHinting = 2;
293 ret.sampleName = ui->sampleTextTree->currentItem()->data(0, Qt::UserRole).toString();
294 if(ui->useShaperCheck->isChecked())
295 {
296 ret.script = ui->langCombo->currentText();
297 ret.shaper = ui->shaperTypeCombo->currentText();
298 }
299 return ret;
300 }
301
setState(const SampleWidget::State & s)302 void SampleWidget::setState(const SampleWidget::State &s)
303 {
304 if(!s.set)
305 return;
306 sampleToolBar->setFontSize( s.fontSize );
307 reSize( s.fontSize, s.fontSize * sampleRatio );
308
309 // {
310 // switch(s.renderHinting)
311 // {
312 // case 0: ui->noHinting->setChecked(true);
313 // break;
314 // case 1: ui->normalHinting->setChecked(true);
315 // break;
316 // case 2: ui->lightHinting->setChecked(true);
317 // break;
318 // default:break;
319 // }
320 // }
321
322 QTreeWidgetItem * targetItem = 0;
323 for(int i(0); i < ui->sampleTextTree->topLevelItemCount(); ++i)
324 {
325 QTreeWidgetItem * tli(ui->sampleTextTree->topLevelItem(i));
326 for(int ii(0); ii < tli->childCount(); ++ii)
327 {
328 if(tli->child(ii)->data(0, Qt::UserRole).toString() == s.sampleName)
329 {
330 targetItem = tli->child(ii);
331 typotek::getInstance()->namedSample(s.sampleName);
332 break;
333 }
334 }
335 if(targetItem != 0)
336 break;
337 }
338 // qDebug()<<"TI"<<targetItem;
339 if(targetItem != 0)
340 ui->sampleTextTree->setCurrentItem(targetItem, 0, QItemSelectionModel::SelectCurrent);
341
342 // if(!s.shaper.isEmpty())
343 // {
344 // ui->useShaperCheck->setChecked(true);
345 // ui->shaperTypeCombo->setCurrentIndex(ui->shaperTypeCombo->findText(s.shaper));
346 // ui->langCombo->setCurrentIndex(ui->langCombo->findText(s.script));
347 // }
348
349 slotView();
350 slotEditSample();
351 }
352
slotView()353 void SampleWidget::slotView()
354 {
355 qDebug()<<"SampleWidget::slotView "<< fontIdentifier;
356 // disconnect(textLayoutFT, SIGNAL(drawBaselineForMe(double)), this, SLOT(drawBaseline(double)));
357 QTime t;
358 t.start();
359 FontItem *f(FMFontDb::DB()->Font( fontIdentifier ));
360 if ( !f )
361 return;
362
363 bool wantDeviceDependant = !layoutForPrint;
364 if(wantDeviceDependant)
365 {
366 f->setFTHintMode(hinting());
367 }
368
369 // if(ui->textProgression->inLine() == TextProgression::INLINE_LTR )
370 f->setProgression(PROGRESSION_LTR );
371 // else if(ui->textProgression->inLine() == TextProgression::INLINE_RTL )
372 // f->setProgression(PROGRESSION_RTL);
373 // else if(ui->textProgression->inLine() == TextProgression::INLINE_TTB )
374 // f->setProgression(PROGRESSION_TTB );
375 // else if(ui->textProgression->inLine() == TextProgression::INLINE_BTT )
376 // f->setProgression(PROGRESSION_BTT);
377
378 f->setFTRaster ( wantDeviceDependant );
379
380 // if ( ui->loremView->isVisible() || ui->loremView_FT->isVisible() || layoutForPrint)
381 {
382 if(!layoutForPrint && !textLayoutFT->isLayoutFinished())
383 {
384 connect(textLayoutFT, SIGNAL(layoutFinished()), this, SLOT(slotView()));
385 textLayoutFT->stopLayout();
386 qDebug()<<"\tLayout stopped";
387 layoutSwitch = false;
388 return;
389 }
390 else
391 {
392 disconnect(textLayoutFT, SIGNAL(layoutFinished()), this, SLOT(slotView()));
393 }
394 // else if(textLayoutVect->isRunning())
395 // textLayoutVect->stopLayout();
396 // else
397 {
398 qDebug()<<"\tStart layout";
399 ui->loremView_FT->unSheduleUpdate();
400 ui->loremView->unSheduleUpdate();
401 FMLayout * textLayout;
402 if(layoutForPrint)
403 textLayout = textLayoutVect;
404 else
405 textLayout = textLayoutFT;
406
407 bool processFeatures = f->isOpenType() && !deFillOTTree().isEmpty();
408 QString script(sampleToolBar->getScript());
409 bool processScript( !script.isEmpty() );
410 textLayout->setDeviceIndy(!wantDeviceDependant);
411 textLayout->setAdjustedSampleInter( sampleInterSize );
412
413 double fSize(sampleFontSize);
414
415 QList<GlyphList> list;
416 QStringList stl( typotek::getInstance()->namedSample().split("\n"));
417 // qDebug()<<"Sample:\n\t"<<stl.join("\n\t");
418 if ( processScript )
419 {
420 for(int p(0);p<stl.count();++p)
421 {
422 list << f->glyphs( stl[p] , fSize, script );
423 }
424 }
425 else if(processFeatures)
426 {
427 for(int p(0);p<stl.count();++p)
428 {
429 list << f->glyphs( stl[p] , fSize, deFillOTTree());
430 }
431 }
432 else
433 {
434 for(int p(0);p<stl.count();++p)
435 list << f->glyphs( stl[p] , fSize );
436 }
437 if(!layoutForPrint)
438 {
439 layoutThread->setLayout(textLayout, list, fSize, f, hinting());
440 connect(textLayout, SIGNAL(drawPixmapForMe(int,double,double,double)), this, SLOT(drawPixmap(int,double,double,double)));
441 // connect(textLayoutFT, SIGNAL(drawBaselineForMe(double)), this, SLOT(drawBaseline(double)));
442 connect(textLayout, SIGNAL(layoutFinished()), this, SLOT(endLayout()));
443 layoutSwitch = true;
444 pixmapDrawn = 0;
445 layoutThread->start();
446 }
447 else
448 {
449 textLayout->doLayout(list, fSize);
450 }
451 }
452 }
453
454 }
455
drawPixmap(int index,double fontsize,double x,double y)456 void SampleWidget::drawPixmap(int index, double fontsize, double x, double y)
457 {
458 // qDebug()<<"SampleWidget::drawPixmap index:"<<index<< "Y:"<<y;
459 if(index < 0)
460 disconnect(textLayoutFT, SIGNAL(drawPixmapForMe(int,double,double,double)), this, SLOT(drawPixmap(int,double,double,double)));
461 FontItem * f( FMFontDb::DB()->Font( fontIdentifier ) );
462 if(!f)
463 return;
464 ++pixmapDrawn;
465 QGraphicsPixmapItem *glyph = f->itemFromGindexPix ( index , fontsize );
466 // qDebug()<<"SampleWidget::drawPixmap index:"<<index<< y << glyph->data(GLYPH_DATA_BITMAPTOP).toDouble();
467 ftScene->addItem ( glyph );
468 glyph->setZValue ( 100.0 );
469 glyph->setPos ( x,y );
470 // QGraphicsLineItem * l = ftScene->addLine(x,y,x,y + glyph->data(GLYPH_DATA_BITMAPTOP).toDouble());
471 // l->setData(GLYPH_DATA_GLYPH, 1);
472 // glyph->pixmap().toImage().save(QString("/tmp/%1.png").arg(index));
473 }
474
drawBaseline(double y)475 void SampleWidget::drawBaseline(double y)
476 {
477 QGraphicsLineItem * l = ftScene->addLine(0,y,ftScene->width(),y);
478 l->setData(GLYPH_DATA_GLYPH, 1);
479 }
480
clearFTScene()481 void SampleWidget::clearFTScene()
482 {
483 qDebug()<<"SampleWidget::clearFTScene"<< layoutSwitch;
484 // if(layoutSwitch)
485 // return;
486 foreach(QGraphicsItem* gi, ftScene->items())
487 {
488 if(gi->data(GLYPH_DATA_GLYPH).toInt() > 0)
489 delete gi;
490 }
491 }
492
endLayout()493 void SampleWidget::endLayout()
494 {
495 QPointF texttopLeft(ui->loremView_FT->mapFromScene(textLayoutFT->getRect().topLeft()));
496 ui->loremView_FT->translate( 10 -texttopLeft.x(), 10 -texttopLeft.y());
497 ui->loremView_FT->update();
498 // qDebug()<<"Pixmaps:"<<pixmapDrawn;
499
500 }
501
fillOTTree()502 void SampleWidget::fillOTTree()
503 {
504 ui->OpenTypeTree->clear();
505 ui->langCombo->clear();
506 ui->langCombo->setEnabled ( false );
507 ui->useShaperCheck->setCheckState ( Qt::Unchecked );
508 ui->useShaperCheck->setEnabled ( false );
509 typotek * typo(typotek::getInstance());
510 QStringList scripts;
511 FontItem * theVeryFont(FMFontDb::DB()->Font( fontIdentifier ));
512 if ( theVeryFont && theVeryFont->isOpenType() )
513 {
514 FMOtf * otf = theVeryFont->takeOTFInstance();
515 foreach ( QString table, otf->get_tables() )
516 {
517 otf->set_table ( table );
518 QTreeWidgetItem *tab_item = new QTreeWidgetItem ( ui->OpenTypeTree,QStringList ( table ) );
519 tab_item->setExpanded ( true );
520 foreach ( QString script, otf->get_scripts() )
521 {
522 scripts << script;
523 otf->set_script ( script );
524 QTreeWidgetItem *script_item = new QTreeWidgetItem ( tab_item, QStringList ( script ) );
525 script_item->setExpanded ( true );
526 foreach ( QString lang, otf->get_langs() )
527 {
528 otf->set_lang ( lang );
529 QTreeWidgetItem *lang_item = new QTreeWidgetItem ( script_item, QStringList ( lang ) );
530 lang_item->setExpanded ( true );
531 foreach ( QString feature, otf->get_features() )
532 {
533 QStringList f ( feature );
534 f << OTTagMeans ( feature );
535 QTreeWidgetItem *feature_item = new QTreeWidgetItem ( lang_item, f );
536 feature_item->setCheckState ( 0, Qt::Unchecked );
537 if(table == "GPOS")
538 {
539 if(typo->getDefaultOTFScript() == script && typo->getDefaultOTFLang() == lang && typo->getDefaultOTFGPOS().contains(feature) )
540 {
541 feature_item->setCheckState ( 0, Qt::Checked );
542 }
543 }
544 else if(table == "GSUB")
545 {
546 if(typo->getDefaultOTFScript() == script && typo->getDefaultOTFLang() == lang && typo->getDefaultOTFGSUB().contains(feature) )
547 {
548 feature_item->setCheckState ( 0, Qt::Checked );
549 }
550 }
551 }
552 }
553 }
554 }
555 ui->OpenTypeTree->resizeColumnToContents ( 0 ) ;
556 theVeryFont->releaseOTFInstance ( otf );
557 }
558 scripts = scripts.toSet().toList();
559 // scripts.removeAll ( "latn" );
560 // if ( !scripts.isEmpty() )
561 {
562 // ui->langCombo->setEnabled ( true );
563 // ui->useShaperCheck->setEnabled ( true );
564 // ui->langCombo->addItems ( scripts );
565 sampleToolBar->setScripts(scripts);
566 }
567 }
568
deFillOTTree()569 OTFSet SampleWidget::deFillOTTree()
570 {
571 // qDebug() << "MainViewWidget::deFillOTTree()";
572 OTFSet ret;
573 // qDebug() << ui->OpenTypeTree->topLevelItemCount();
574 for ( int table_index = 0; table_index < ui->OpenTypeTree->topLevelItemCount(); ++table_index ) //tables
575 {
576 // qDebug() << "table_index = " << table_index;
577 QTreeWidgetItem * table_item = ui->OpenTypeTree->topLevelItem ( table_index ) ;
578 // qDebug() << table_item->text(0);
579 for ( int script_index = 0; script_index < table_item->childCount();++script_index ) //scripts
580 {
581 QTreeWidgetItem * script_item = table_item->child ( script_index );
582 // qDebug() << "\tscript_index = " << script_index << script_item->text(0);
583 for ( int lang_index = 0; lang_index < script_item->childCount(); ++lang_index ) //langs
584 {
585 QTreeWidgetItem * lang_item = script_item->child ( lang_index );
586 // qDebug() << "\t\tlang_index = "<< lang_index << lang_item->text(0);
587 for ( int feature_index = 0; feature_index < lang_item->childCount(); ++feature_index ) //features
588 {
589 // qDebug() << lang_item->childCount() <<" / "<< feature_index;
590 QTreeWidgetItem * feature_item = lang_item->child ( feature_index );
591 // qDebug() << "\t\t\tfeature_item -> "<< feature_item->text(0);
592 if ( feature_item->checkState ( 0 ) == Qt::Checked )
593 {
594 if ( table_item->text ( 0 ) == "GPOS" )
595 {
596 ret.script = script_item->text ( 0 );
597 ret.lang = lang_item->text ( 0 );
598 ret.gpos_features.append ( feature_item->text ( 0 ) );
599 }
600 if ( table_item->text ( 0 ) == "GSUB" )
601 {
602 ret.script = script_item->text ( 0 );
603 ret.lang = lang_item->text ( 0 );
604 ret.gsub_features.append ( feature_item->text ( 0 ) );
605 }
606 }
607 }
608 }
609 }
610 }
611 // qDebug() << "endOf";
612 return ret;
613
614 }
615
616 //void SampleWidget::slotChangeViewPage(QAbstractButton* but)
617 //{
618 // QString radioName( but->objectName() );
619
620 // if(radioName == "freetypeRadio" )
621 // {
622 // ui->stackedViews->setCurrentIndex(VIEW_PAGE_FREETYPE);
623 // ui->hintingSelect->setEnabled(true);
624 // }
625 // else if(radioName == "nativeRadio" )
626 // {
627 // ui->stackedViews->setCurrentIndex(VIEW_PAGE_ABSOLUTE);
628 // ui->hintingSelect->setEnabled(false);
629 // }
630
631 // slotView(true);
632 //}
633
634 //void SampleWidget::slotHintChanged(int )
635 //{
636 // slotView(true);
637 // emit stateChanged();
638 //}
639
640
641 //void SampleWidget::slotChangeViewPageSetting ( bool ch )
642 //{
643 // // qDebug() <<"MainViewWidget::slotChangeViewPageSetting("<<ch<<")";
644 // QString butName ( sender()->objectName() );
645 // if ( !ch )
646 // {
647 // toolPanelWidth = ui->splitter_2->sizes().at ( 1 ) ;
648 // ui->stackedTools->hide();
649 // }
650 // else
651 // {
652 // ui->stackedTools->show();
653 // if ( ui->splitter_2->sizes().at ( 1 ) == 0 )
654 // {
655 // QList<int> li;
656 // li << ui->splitter_2->width() - toolPanelWidth << toolPanelWidth;
657 // ui->splitter_2->setSizes ( li );
658 // }
659 // }
660
661 // QMap<QString, QToolButton*> bmap;
662 // QMap<QString, int> pmap;
663 // bmap[ "settingsButton" ] = ui->settingsButton;
664 // bmap[ "openTypeButton" ] = ui->openTypeButton;
665 // bmap[ "sampleButton" ] = ui->sampleButton;
666 // pmap[ "settingsButton" ] = VIEW_PAGE_SETTINGS;
667 // pmap[ "openTypeButton" ] = VIEW_PAGE_OPENTYPE;
668 // pmap[ "sampleButton" ] = VIEW_PAGE_SAMPLES;
669
670 // foreach(QString pk, bmap.keys())
671 // {
672 // if(butName == pk)
673 // {
674 // ui->stackedTools->setCurrentIndex(pmap[pk]);
675 // }
676 // else
677 // {
678 // bmap[pk]->setChecked ( false );
679 // }
680 // }
681 //}
682
683
slotUpdateSView()684 void SampleWidget::slotUpdateSView()
685 {
686 if(ui->loremView->isVisible())
687 slotView();
688 }
689
690
slotZoom(int z)691 void SampleWidget::slotZoom ( int z )
692 {
693 double delta = 1.0 + ( z/1000.0 ) ;
694 QTransform trans;
695 trans.scale ( delta,delta );
696
697 QGraphicsView * concernedView;
698 if ( ui->loremView_FT->isVisible() )
699 concernedView = ui->loremView_FT;
700 else if ( ui->loremView->isVisible() )
701 {
702 concernedView = ui->loremView;
703 if ( delta == 1.0 )
704 {
705 double horiScaleT (typotek::getInstance()->getDpiX() / 72.0);
706 double vertScaleT ( typotek::getInstance()->getDpiY() / 72.0);
707 QTransform adjustAbsoluteViewT( horiScaleT , 0, 0,vertScaleT, 0, 0 );
708 trans = adjustAbsoluteViewT;
709 }
710 }
711 concernedView->setTransform ( trans, ( z == 0 ) ? false : true );
712
713 }
714
715
slotUpdateRView()716 void SampleWidget::slotUpdateRView()
717 {
718 if(ui->loremView_FT->isVisible())
719 slotView();
720 }
721
slotSampleChanged()722 void SampleWidget::slotSampleChanged()
723 {
724 typotek::getInstance()->namedSample( ui->sampleTextTree->currentItem()->data(0, Qt::UserRole).toString() );
725 ui->removeSampleButton->setEnabled(ui->sampleTextTree->currentItem()->parent() == uRoot);
726 slotView ( );
727 emit stateChanged();
728 }
729
730
731
slotLiveFontSize(double fs)732 void SampleWidget::slotLiveFontSize(double fs)
733 {
734 // double fs( sampleToolBar->getFontSize() );
735 reSize(fs, fs * sampleRatio);
736 slotView();
737 emit stateChanged();
738 }
739
slotFeatureChanged()740 void SampleWidget::slotFeatureChanged()
741 {
742 // OTFSet ret = deFillOTTree();
743 slotView ( );
744 emit stateChanged();
745 }
746
slotDefaultOTF()747 void SampleWidget::slotDefaultOTF()
748 {
749 OTFSet ots(deFillOTTree());
750 typotek* typo(typotek::getInstance());
751 typo->setDefaultOTFScript(ots.script);
752 typo->setDefaultOTFLang(ots.lang);
753 typo->setDefaultOTFGPOS(ots.gpos_features);
754 typo->setDefaultOTFGSUB(ots.gsub_features);
755 }
756
slotResetOTF()757 void SampleWidget::slotResetOTF()
758 {
759 typotek* typo(typotek::getInstance());
760 typo->setDefaultOTFScript(QString());
761 typo->setDefaultOTFLang(QString());
762 typo->setDefaultOTFGPOS(QStringList());
763 typo->setDefaultOTFGSUB(QStringList());
764 }
765
766
slotChangeScript()767 void SampleWidget::slotChangeScript()
768 {
769 if ( ui->useShaperCheck->checkState() == Qt::Checked )
770 {
771 slotView ( );
772 }
773 emit stateChanged();
774 }
775
slotProgressionChanged()776 void SampleWidget::slotProgressionChanged()
777 {
778 slotView();
779 }
780
slotWantShape()781 void SampleWidget::slotWantShape()
782 {
783 slotView ( );
784 emit stateChanged();
785 }
786
787
refillSampleList()788 void SampleWidget::refillSampleList()
789 {
790 ui->sampleTextTree->clear();
791
792 QTreeWidgetItem * curIt = 0;
793 QMap<QString, QList<QString> > sl = typotek::getInstance()->namedSamplesNames();
794 QList<QString> ul( sl.take(QString("User")) );
795 uRoot = new QTreeWidgetItem(ui->sampleTextTree);
796 //: Identify root of user defined sample texts
797 uRoot->setText(0, tr("User"));
798 if(ul.count())
799 {
800
801 bool first(true);
802 foreach(QString uk, ul)
803 {
804 if(first)
805 {
806 first = false;
807 uRoot->setData(0, Qt::UserRole , QString("User::") + uk);
808 curIt = uRoot;
809 }
810 QTreeWidgetItem * it = new QTreeWidgetItem();
811 it->setText(0, uk);
812 it->setData(0, Qt::UserRole , QString("User::") + uk);
813 uRoot->addChild(it);
814 }
815 }
816 foreach(QString k, sl.keys())
817 {
818 QTreeWidgetItem * kRoot = new QTreeWidgetItem(ui->sampleTextTree);
819 kRoot->setText(0, k);
820 bool first(true);
821 foreach(QString n, sl[k])
822 {
823 if(first)
824 {
825 first = false;
826 kRoot->setData(0, Qt::UserRole , k + QString("::") + n);
827 if(!curIt)
828 curIt = kRoot;
829 }
830 QTreeWidgetItem * it = new QTreeWidgetItem();
831 it->setText(0, n);
832 it->setData(0, Qt::UserRole, k + QString("::") + n);
833 kRoot->addChild(it);
834 }
835 }
836
837 ui->sampleTextTree->setCurrentItem(curIt);
838 }
839
hinting()840 unsigned int SampleWidget::hinting()
841 {
842 // if(ui->lightHinting->isChecked())
843 // return FT_LOAD_TARGET_LIGHT;
844 // else if(ui->normalHinting->isChecked())
845 // return FT_LOAD_TARGET_NORMAL;
846
847 return FT_LOAD_NO_HINTING ;
848 }
849
850
slotPrint()851 void SampleWidget::slotPrint()
852 {
853 FontItem * font(FMFontDb::DB()->Font( fontIdentifier ));
854 if(!font)
855 return;
856
857 if(printer == 0)
858 printer = new QPrinter(QPrinter::HighResolution);
859 if(printDialog == 0)
860 printDialog = new QPrintDialog(printer, this);
861
862 printDialog->setWindowTitle("Fontmatrix - " + tr("Print Sample") +" - " + font->fancyName() );
863 printDialog->open(this, SLOT(slotDoPrinting()));
864 }
865
866
slotDoPrinting()867 void SampleWidget::slotDoPrinting()
868 {
869 layoutForPrint = true;
870 slotView();
871 printer->setFullPage ( true );
872 QPainter aPainter ( printer );
873 loremScene->render(&aPainter);
874 layoutForPrint = false;
875 }
876
slotFileChanged(const QString &)877 void SampleWidget::slotFileChanged(const QString &)
878 {
879 #ifdef PLATFORM_APPLE
880 if(fileInfo.lastModified().toMSecsSinceEpoch() == fileLastModified)
881 return;
882 fileLastModified = fileInfo.lastModified().toMSecsSinceEpoch();
883 #endif
884 if(reloadTimer->isActive())
885 reloadTimer->start();
886 else
887 {
888 reloadTimer->start();
889 }
890 }
891
slotReload()892 void SampleWidget::slotReload()
893 {
894 // reloadTimer->stop();
895 slotView();
896 }
897
slotScriptChange()898 void SampleWidget::slotScriptChange()
899 {
900 slotView();
901 }
902
saveState()903 void SampleWidget::saveState()
904 {
905 QSettings settings;
906 State s(state());
907 QByteArray bs(s.toByteArray());
908 settings.setValue("Sample/state", bs);
909 }
910
slotShowSamples(bool b)911 void SampleWidget::slotShowSamples(bool b)
912 {
913 if(b)
914 {
915 if(sampleToolBar->isChecked(SampleToolBar::OpenTypeButton))
916 {
917 ui->sampleGridLayout->removeWidget(ui->opentypeWidget);
918 ui->opentypeWidget->setParent(ui->stackedViews->widget(VIEW_PAGE_OPENTYPE));
919 sampleToolBar->toggle(SampleToolBar::OpenTypeButton, false);
920 }
921 ui->sampleEditWidget->setAutoFillBackground(true);
922 ui->sampleEditWidget->resize(ui->sampleGridLayout->geometry().width() / 2, ui->sampleGridLayout->geometry().height());
923 ui->sampleGridLayout->addWidget(ui->sampleEditWidget, 0,0, Qt::AlignRight);
924 }
925 else
926 {
927 ui->sampleGridLayout->removeWidget(ui->sampleEditWidget);
928 ui->sampleEditWidget->setParent(ui->stackedViews->widget(VIEW_PAGE_SAMPLES));
929 }
930 }
931
slotShowOpenType(bool b)932 void SampleWidget::slotShowOpenType(bool b)
933 {
934 if(b)
935 {
936 if(sampleToolBar->isChecked(SampleToolBar::SampleButton))
937 {
938 ui->sampleGridLayout->removeWidget(ui->sampleEditWidget);
939 ui->sampleEditWidget->setParent(ui->stackedViews->widget(VIEW_PAGE_SAMPLES));
940 sampleToolBar->toggle(SampleToolBar::SampleButton, false);
941 }
942 ui->opentypeWidget->setAutoFillBackground(true);
943 ui->opentypeWidget->resize(ui->sampleGridLayout->geometry().width() / 2, ui->sampleGridLayout->geometry().height());
944 ui->sampleGridLayout->addWidget(ui->opentypeWidget, 0,0, Qt::AlignRight);
945 }
946 else
947 {
948 ui->sampleGridLayout->removeWidget(ui->opentypeWidget);
949 ui->opentypeWidget->setParent(ui->stackedViews->widget(VIEW_PAGE_OPENTYPE));
950 }
951 }
952
slotAddSample()953 void SampleWidget::slotAddSample()
954 {
955 QString nu( tr("New Sample") );
956 newSampleName = new QTreeWidgetItem();
957 newSampleName->setText(0,nu);
958 newSampleName->setData(0, Qt::UserRole , QString("NEW_SAMPLE"));
959 newSampleName->setFlags(newSampleName->flags() | Qt::ItemIsEditable);
960 uRoot->addChild(newSampleName);
961 ui->sampleTextTree->openPersistentEditor(newSampleName);
962 if(!uRoot->isExpanded())
963 uRoot->setExpanded(true);
964 ui->sampleTextTree->setCurrentItem(newSampleName);
965 }
966
slotSampleNameEdited(QWidget * w)967 void SampleWidget::slotSampleNameEdited(QWidget *w)
968 {
969 ui->sampleTextTree->closePersistentEditor(newSampleName);
970 newSampleName->setData(0, Qt::UserRole , QString("User::") + newSampleName->text(0));
971 typotek::getInstance()->changeSample(newSampleName->text(0), ui->sampleEdit->toPlainText() );
972 }
973
slotRemoveSample()974 void SampleWidget::slotRemoveSample()
975 {
976 QString name(ui->sampleTextTree->currentItem()->text(0));
977 QTreeWidgetItem * currentItem = ui->sampleTextTree->currentItem();
978 uRoot->removeChild(currentItem);
979 typotek::getInstance()->removeNamedSample(name);
980 }
981
slotEditSample()982 void SampleWidget::slotEditSample()
983 {
984 disconnect(ui->sampleEdit, SIGNAL(textChanged()), this, SLOT(slotUpdateSample()));
985 QTreeWidgetItem * currentItem = ui->sampleTextTree->currentItem();
986 ui->sampleEdit->setPlainText(typotek::getInstance()->namedSample( currentItem->data(0, Qt::UserRole).toString() ));
987 ui->sampleEdit->setReadOnly(currentItem->parent() != uRoot);
988 connect(ui->sampleEdit, SIGNAL(textChanged()), this, SLOT(slotUpdateSample()));
989 }
990
slotUpdateSample()991 void SampleWidget::slotUpdateSample()
992 {
993 typotek::getInstance()->changeSample(ui->sampleTextTree->currentItem()->text(0), ui->sampleEdit->toPlainText());
994 slotView();
995 }
996
997