No images in this repository’s iceberg at this time
Download raw (39.3 KB)
/***************************************************************************
* Copyright (C) 2007 by Pierre Marchand *
* pierre@moulindetouvois.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 <QtGui>
#include "underline.h"
#include "ulpageitem.h"
#include "ulglyphcollection.h"
#include "ulglyphscene.h"
#include "ullineeditor.h"
#include "uleditglyph.h"
#include "ulpageview.h"
#include "pagebuffer.h"
#include "ulglyphitem.h"
#include "ulunit.h"
#include "ulextragraphic.h"
#include "ulextragraphicscene.h"
#include <QTextEdit>
#include <QTextStream>
#include <QDataStream>
#include <QCloseEvent>
#include <QFileDialog>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QDockWidget>
#include <QTabWidget>
#include <QPushButton>
#include <QInputDialog>
#include <QPrinter>
#include <QPainter>
#include <QPrintDialog>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QSizePolicy>
#include <QDoubleSpinBox>
#include <QComboBox>
#include <QDomDocument>
#include <QDomNodeList>
#include <QButtonGroup>
#include <QRadioButton>
#include <QCheckBox>
#include <QMapIterator>
#include <QDebug>
undertype* undertype::theMainWindow = 0;
undertype::undertype()
{
maybeFlag = true;
m_usecmap = false;
theMainWindow = this;
pages = new ULPageItem ( 595.276,841.89 ); // a4
mainView = new ULPageView ( pages );
pageWidget = new QGroupBox ( this );
pageLayout = new QVBoxLayout();
pageControls = new QHBoxLayout();
pageControls->addWidget ( new QLabel ( "cursor (X)" ) );
pageCursorX = new QDoubleSpinBox();
pageCursorX->setRange ( 0.0,10000.0 );
pageControls->addWidget ( pageCursorX );
pageControls->addWidget ( new QLabel ( "cursor (Y)" ) );
pageCursorY = new QDoubleSpinBox();
pageCursorY->setRange ( 0.0,10000.0 );
pageControls->addWidget ( pageCursorY );
pageAA = new QPushButton ( "switch AA",0 );
pageControls->addWidget ( pageAA );
pageControls->addStretch();
currentLineLabel = new QLabel("");
pageControls->addWidget (currentLineLabel);
pageDimLabel = new QLabel ( "page : " + QString().number ( ULUnit ( 595.276 ).mm() ) +" mm x "+QString().number ( ULUnit ( 841.89 ).mm() ) + " mm" );
pageDimLabel->setFont ( QFont ( "sans", 7 ) );
pageRatioLabel = new QLabel("100 %");
pageRatioLabel->setFont ( QFont ( "sans", 7 ,QFont::Bold) );
statusBar()->addPermanentWidget ( pageDimLabel );
statusBar()->addPermanentWidget ( pageRatioLabel );
pageLayout->addLayout ( pageControls );
pageLayout->addWidget ( mainView );
pageWidget->setLayout ( pageLayout );
setCentralWidget ( pageWidget );
glyphPalette = new QDockWidget ( tr ( "Casses" ), this );
tabCasses = new QTabWidget ( glyphPalette );
newCasseBut = new QPushButton ( "New" );
saveCasseBut = new QPushButton ( "Save" );
loadCasseBut = new QPushButton ( "Load" );
useCMapCheck = new QCheckBox ("Use Cmap");
casseSelect = new QComboBox();
casseBox = new QGroupBox ( tabCasses );
casseManagerLayout = new QGridLayout();
casseManagerLayout->addWidget ( newCasseBut, 0,0 );
casseManagerLayout->addWidget ( loadCasseBut,0,1 );
casseManagerLayout->addWidget ( casseSelect,1,0 );
casseManagerLayout->addWidget ( saveCasseBut,1,1 );
casseManagerLayout->addWidget ( useCMapCheck,2,1);
casseBox->setLayout ( casseManagerLayout );
tabCasses->addTab ( casseBox, "manager" );
glyphPalette->setWidget ( tabCasses );
addDockWidget ( Qt::RightDockWidgetArea, glyphPalette );
extraScene = new ULExtraGraphicScene ( pages );
extraView = new QGraphicsView ( extraScene );
extraView->scale((double)physicalDpiX() / 72.0, (double)physicalDpiY() / 72.0);
tabCasses->addTab ( extraView, "Graphics" );
lineEditor = new QDockWidget ( tr ( "Composteur" ), this );
lineWidget = new QGroupBox ( lineEditor );
lineLayout = new QHBoxLayout();
lineControls = new QGridLayout();
lineControls->addWidget ( new QLabel ( "Line height" ),0,0 );
lhSpin = new QDoubleSpinBox ( lineWidget );
lhSpin->setSingleStep ( 0.1 );
lhSpin->setRange ( -1000.0,1000.0 );
lineControls->addWidget ( lhSpin,0,1 );
lineControls->addWidget ( new QLabel ( "Line width" ),1,0 );
lwSpin = new QDoubleSpinBox ( lineWidget );
lwSpin->setSingleStep ( 0.1 );
lwSpin->setRange ( -1000.0,1000.0 );
lineControls->addWidget ( lwSpin,1,1 );
lineControls->addWidget ( new QLabel ( "cursor(x)" ),2,0 );
gcursor = new QDoubleSpinBox ( lineWidget );
gcursor->setSingleStep ( 0.1 );
gcursor->setRange ( -1000.0,1000.0 );
lineControls->addWidget ( gcursor,2,1 );
gcursorBegin = new QPushButton ( "to begin", 0 );
gcursorEnd = new QPushButton ( "to end",0 );
lineControls->addWidget ( gcursorBegin, 3,0 );
lineControls->addWidget ( gcursorEnd, 3,1 );
gcursorLTR = new QCheckBox ( "Left to Right",0 );
gcursorLTR->setCheckState ( Qt::Checked );
lineControls->addWidget ( gcursorLTR,4,0 );
lineScene = new ULLineEditor ( pages );
lineView = new QGraphicsView ( lineScene );
lineView->setRenderHints ( QPainter::Antialiasing );
pageAntiAlias = true;
// lineView->setViewport(new QGLWidget);
lineView->move ( 100.0,10.0 );
lineLayout->addLayout ( lineControls );
lineLayout->addWidget ( lineView );
lineWidget->setLayout ( lineLayout );
lineEditor->setWidget ( lineWidget );
addDockWidget ( Qt::BottomDockWidgetArea, lineEditor );
connect ( newCasseBut,SIGNAL ( released() ),this,SLOT ( newCasse() ) );
connect ( saveCasseBut,SIGNAL ( released() ),this,SLOT ( saveCasse() ) );
connect ( loadCasseBut,SIGNAL ( released() ),this,SLOT ( loadCasse() ) );
connect(useCMapCheck,SIGNAL(toggled( bool )),this,SLOT(switchCMap(bool)));
connect ( lineScene,SIGNAL ( wantEdit ( ULGlyphItem* ) ),this,SLOT ( editGlyph ( ULGlyphItem* ) ) );
connect ( lhSpin,SIGNAL ( valueChanged ( double ) ),lineScene,SLOT ( slotChangeBaseLine ( double ) ) );
connect ( lwSpin,SIGNAL ( valueChanged ( double ) ),lineScene,SLOT ( slotChangeWidth ( double ) ) );
connect ( gcursor,SIGNAL ( valueChanged ( double ) ),lineScene,SLOT ( slotMoveCursor ( double ) ) );
connect ( lineScene,SIGNAL ( linesChanged ( double, double, double ) ),this,SLOT ( changeLineWidgetValues ( double, double, double ) ) );
connect ( gcursorBegin, SIGNAL ( released() ), this,SLOT ( moveGcursorBegin() ) );
connect ( gcursorEnd,SIGNAL ( released() ), this, SLOT ( moveGcursorEnd() ) );
connect ( gcursorLTR, SIGNAL ( stateChanged ( int ) ), lineScene, SLOT ( slotLTR ( int ) ) );
connect ( pageCursorX,SIGNAL ( valueChanged ( double ) ),pages,SLOT ( setCurX ( double ) ) );
connect ( pageCursorY,SIGNAL ( valueChanged ( double ) ),pages,SLOT ( setCurY ( double ) ) );
connect ( pages,SIGNAL ( curPosXChanged ( double ) ),pageCursorX,SLOT ( setValue ( double ) ) );
connect ( pages,SIGNAL ( curPosYChanged ( double ) ),pageCursorY,SLOT ( setValue ( double ) ) );
connect ( pageAA, SIGNAL ( released() ),this, SLOT ( switchPAA() ) );
connect ( pages,SIGNAL ( wantEditLine ( QGraphicsItem* ) ),lineScene,SLOT ( slotEditGroup ( QGraphicsItem* ) ) );
connect ( pages, SIGNAL(infoCurrentLine(QString)), currentLineLabel, SLOT(setText(QString)));
newLine();
pageCursorY->setValue ( 40.0 );
pageCursorX->setValue ( 40.0 );
createActions();
createMenus();
createToolBars();
createStatusBar();
readSettings();
setCurrentFile ( "" );
}
void undertype::closeEvent ( QCloseEvent *event )
{
// if (maybeSave()) {
// writeSettings();
// event->accept();
// } else {
// event->ignore();
// }
}
void undertype::newFile()
{
if ( maybeSave() )
{
maybeFlag =false;
closeDoc();
maybeFlag = true;
setCurrentFile ( "" );
}
}
void undertype::open()
{
if ( maybeSave() )
{
QString fileName = QFileDialog::getOpenFileName ( this );
if ( !fileName.isEmpty() )
{
maybeFlag = false;
closeDoc();
maybeFlag = true;
loadFile ( fileName );
}
}
}
bool undertype::save()
{
if ( curFile.isEmpty() )
{
return saveAs();
}
else
{
return saveFile ( curFile );
}
}
bool undertype::saveAs()
{
QString fileName = QFileDialog::getSaveFileName ( this );
if ( fileName.isEmpty() )
return false;
return saveFile ( fileName );
}
void undertype::about()
{
QMessageBox::about ( this, tr ( "About UnderType" ),
QString ( "Un projet pédagogique de formation de l'imprimé" ) );
}
void undertype::documentWasModified()
{
setWindowModified ( true );
}
void undertype::createActions()
{
newAct = new QAction ( QIcon ( ":/filenew.xpm" ), tr ( "&New" ), this );
newAct->setShortcut ( tr ( "Ctrl+N" ) );
newAct->setStatusTip ( tr ( "Create a new file" ) );
connect ( newAct, SIGNAL ( triggered() ), this, SLOT ( newFile() ) );
openAct = new QAction ( QIcon ( ":/fileopen.xpm" ), tr ( "&Open..." ), this );
openAct->setShortcut ( tr ( "Ctrl+O" ) );
openAct->setStatusTip ( tr ( "Open an existing file" ) );
connect ( openAct, SIGNAL ( triggered() ), this, SLOT ( open() ) );
saveAct = new QAction ( QIcon ( ":/filesave.xpm" ), tr ( "&Save" ), this );
saveAct->setShortcut ( tr ( "Ctrl+S" ) );
saveAct->setStatusTip ( tr ( "Save the document to disk" ) );
connect ( saveAct, SIGNAL ( triggered() ), this, SLOT ( save() ) );
saveAsAct = new QAction ( tr ( "Save &As..." ), this );
saveAsAct->setStatusTip ( tr ( "Save the document under a new name" ) );
connect ( saveAsAct, SIGNAL ( triggered() ), this, SLOT ( saveAs() ) );
closeAct = new QAction(tr("Close doc"),this);
connect ( closeAct, SIGNAL(triggered( bool )),this,SLOT(closeDoc()));
exitAct = new QAction ( tr ( "E&xit" ), this );
exitAct->setShortcut ( tr ( "Ctrl+Q" ) );
exitAct->setStatusTip ( tr ( "Exit the application" ) );
connect ( exitAct, SIGNAL ( triggered() ), this, SLOT ( close() ) );
pageAct = new QAction ( tr ( "Page Setup..." ),this );
pageAct->setStatusTip ( tr ( "Set up page dim." ) );
connect ( pageAct, SIGNAL ( triggered() ),this, SLOT ( pageSetup() ) );
pdfAct = new QAction ( tr ( "Export to PDF..." ),this );
connect ( pdfAct, SIGNAL ( triggered() ),this, SLOT ( exportPDF() ) );
aboutAct = new QAction ( tr ( "&About" ), this );
aboutAct->setStatusTip ( tr ( "Show the application's About box" ) );
connect ( aboutAct, SIGNAL ( triggered() ), this, SLOT ( about() ) );
aboutQtAct = new QAction ( tr ( "About &Qt" ), this );
aboutQtAct->setStatusTip ( tr ( "Show the Qt library's About box" ) );
connect ( aboutQtAct, SIGNAL ( triggered() ), qApp, SLOT ( aboutQt() ) );
printAct = new QAction ( tr ( "&Print" ),this );
connect ( printAct, SIGNAL ( triggered() ), this, SLOT ( print() ) );
}
void undertype::createMenus()
{
fileMenu = menuBar()->addMenu ( tr ( "&File" ) );
fileMenu->addAction ( newAct );
fileMenu->addAction ( openAct );
fileMenu->addAction ( saveAct );
fileMenu->addAction ( saveAsAct );
fileMenu->addSeparator();
fileMenu->addAction(closeAct);
fileMenu->addSeparator();
fileMenu->addAction ( printAct );
fileMenu->addSeparator();
fileMenu->addAction ( exitAct );
editMenu = menuBar()->addMenu ( tr ( "&Page" ) );
editMenu->addAction ( pageAct );
editMenu->addAction ( pdfAct );
// editMenu->addAction ( cutAct );
// editMenu->addAction ( copyAct );
// editMenu->addAction ( pasteAct );
menuBar()->addSeparator();
helpMenu = menuBar()->addMenu ( tr ( "&Help" ) );
helpMenu->addAction ( aboutAct );
// helpMenu->addAction ( aboutQtAct );
}
void undertype::createToolBars()
{
fileToolBar = addToolBar ( tr ( "File" ) );
fileToolBar->addAction ( newAct );
fileToolBar->addAction ( openAct );
fileToolBar->addAction ( saveAct );
}
void undertype::createStatusBar()
{
statusBar()->showMessage ( tr ( "Ready" ) );
}
void undertype::readSettings()
{
QSettings settings ( "Undertype" );
QPoint pos = settings.value ( "pos", QPoint ( 200, 200 ) ).toPoint();
QSize size = settings.value ( "size", QSize ( 400, 400 ) ).toSize();
resize ( size );
move ( pos );
}
void undertype::writeSettings()
{
QSettings settings ( "Undertype" );
settings.setValue ( "pos", pos() );
settings.setValue ( "size", size() );
}
bool undertype::maybeSave()
{
if ( maybeFlag)
{
int ret = QMessageBox::warning ( this, tr ( "Application" ),
tr ( "The document has been modified.\n"
"Do you want to save your changes?" ),
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No,
QMessageBox::Cancel | QMessageBox::Escape );
if ( ret == QMessageBox::Yes )
return save();
else if ( ret == QMessageBox::Cancel )
return false;
}
return true;
}
void undertype::loadFile ( const QString &fileName )
{
QDomDocument doc ( "udl" );
QFile file ( fileName );
if ( !file.open ( QFile::ReadOnly ) )
{
QMessageBox::warning ( this, tr ( "Application" ),
tr ( "Cannot read file %1:\n%2." )
.arg ( fileName )
.arg ( file.errorString() ) );
return;
}
if ( !doc.setContent ( &file ) )
{
file.close();
statusBar()->showMessage ( tr ( "ERROR loading xml for %1" ).arg ( fileName ),3000 );
return;
}
file.close();
statusBar()->showMessage ( tr ( "loading %1" ).arg ( fileName ) );
//loading page
QDomNodeList pagList = doc.elementsByTagName ( "page" );
if ( pagList.length() == 0 )
{
statusBar()->showMessage ( tr ( "ERROR loading page for %1" ).arg ( fileName ),3000 );
return;
}
QDomNode pag = pagList.item ( 0 );
double pw = pag.attributes().namedItem ( "width" ).toAttr().value().toDouble();
double ph = pag.attributes().namedItem ( "height" ).toAttr().value().toDouble();
pages->setPageSize ( pw,ph );
pageDimLabel->setText ( "page : " + QString().number ( ULUnit ( pw ).mm() ) +" mm x "+QString().number ( ULUnit ( ph ).mm() ) + " mm" );
//loading casses
QDomNodeList colList = doc.elementsByTagName ( "collection" );
if ( colList.length() == 0 )
{
statusBar()->showMessage ( tr ( "WARNING: no casse in %1" ).arg ( fileName ),3000 );
// return;
}
qDebug() << colList.length();
for ( uint i = 0; i < colList.length(); ++i )
{
QDomNode col = colList.item ( i );
QString fp = col.namedItem ( "fontfile" ).toElement().text();
QString fn = col.namedItem ( "name" ).toElement().text();
double fs = QString ( col.namedItem ( "size" ).toElement().text() ).toDouble();
QMap<uint,QString> indname;
QDomNode gnode = col.firstChildElement ( "index" );
if(PageBuffer::getInstance()->fontCollection.contains(fn))
continue;
while ( !gnode.isNull() )
{
QDomElement inode = gnode.toElement();
gnode = gnode.nextSiblingElement();
QDomElement nnode = gnode.toElement();
indname.insert ( QString ( inode.text() ).toDouble(), nnode.text() );
gnode = gnode.nextSiblingElement ( "index" );
}
qDebug() << indname.count();
ULGlyphScene *scene = new ULGlyphScene();
scene->setBackgroundBrush ( Qt::lightGray );
scene->setMainScene ( lineScene );
glyphScene.append ( scene );
QGraphicsView *view = new QGraphicsView ( scene );
view->setRenderHints ( QPainter::Antialiasing );
glyphView.append ( view );
ULGlyphCollection * coll = new ULGlyphCollection ( scene,fs );
scene->setCollection ( coll );
coll->userFeed ( fp, fn, indname );
casses.append ( coll );
cassesMap.insert ( fn, coll );
casseSelect->addItem ( coll->name(), QVariant ( coll->name() ) );
tabCasses->setCurrentIndex ( tabCasses->addTab ( view, coll->name() ) );
}
// loading glyphs
QDomNodeList grList = doc.elementsByTagName ( "group" );
for ( uint i = 0; i < grList.length(); ++i )
{
QGraphicsItemGroup * g = new QGraphicsItemGroup;
QDomNode gr = grList.item ( i );
double gxpos = QString ( gr.attributes().namedItem ( "xpos" ).toAttr().value() ).toDouble();
double gypos = QString ( gr.attributes().namedItem ( "ypos" ).toAttr().value() ).toDouble();
double bali = QString ( gr.attributes().namedItem ( "baseline" ).toAttr().value() ).toDouble();
double lihe = QString ( gr.attributes().namedItem ( "lineheight" ).toAttr().value() ).toDouble();
double cupo = QString ( gr.attributes().namedItem ( "curpos" ).toAttr().value() ).toDouble();
int xltr = QString ( gr.attributes().namedItem ( "ltr" ).toAttr().value() ).toInt();
QList<ULGlyphItem*> glist;
QDomNode gnode = gr.firstChildElement ( "gitem" );
while ( !gnode.isNull() )
{
double xpos = QString ( gnode.namedItem ( "xpos" ).toElement().text() ).toDouble();
double ypos = QString ( gnode.namedItem ( "ypos" ).toElement().text() ).toDouble();
// qDebug() << gnode.namedItem("key").toElement().text();
QString from(gnode.namedItem ( "from" ).toElement().text() );
QString key(gnode.namedItem ( "key" ).toElement().text());
ULGlyphCollection* gCollection = cassesMap[from];
ULGlyphScene * cScene = gCollection->scene();
ULGlyphItem *selected = cScene->keyItem(key);
ULGlyphItem *item = new ULGlyphItem ();
item->setPath ( selected->shape() );
item->setBrush ( QBrush ( Qt::SolidPattern ) );
item->setData ( 1,"glyph" );
item->setData ( 2,selected->key );
item->key = selected->key;
item->collection = selected->collection;
item->setPDF ( selected->XObject() );
item->scale ( selected->size / selected->uniem() ,- ( selected->size ) /selected->uniem() );
item->m_xadvance = selected->m_xadvance;
item->textKey = selected->textKey;
item->showText ( false );
item->makeActive();
item->setPos ( xpos,ypos );
glist.append ( item );
g->addToGroup ( item );
gnode = gnode.nextSiblingElement ( "gitem" );
}
uint gid = PageBuffer::getInstance()->put ( glist );
pages->addItem ( g );
g->setFlags ( QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable );
g->setData ( 1,"group" );
g->setZValue ( 10.0 );
g->setHandlesChildEvents ( true );
g->setData ( 2, gid );
g->setData ( 3, bali );
g->setData ( 4, lihe );
g->setData ( 5, cupo );
g->setData ( 6, xltr );
g->setPos ( gxpos, gypos );
}
QDomNodeList ra = doc.elementsByTagName ( "raster" );
for ( uint i = 0;i < ra.count(); ++i )
{
double xra = QString ( ra.item ( i ).attributes().namedItem ( "xpos" ).toAttr().value() ).toDouble();
double yra = QString ( ra.item ( i ).attributes().namedItem ( "ypos" ).toAttr().value() ).toDouble();
double zra = QString ( ra.item ( i ).attributes().namedItem ( "zindex" ).toAttr().value() ).toDouble();
QString fra = ra.item ( i ).attributes().namedItem ( "file" ).toAttr().value();
qDebug() << "loading raster " << fra;
extraScene->load ( fra, xra, yra , zra);
}
QDomNodeList svg = doc.elementsByTagName ( "svg" );
for ( uint i = 0;i < svg.count(); ++i )
{
double xra = QString ( svg.item ( i ).attributes().namedItem ( "xpos" ).toAttr().value() ).toDouble();
double yra = QString ( svg.item ( i ).attributes().namedItem ( "ypos" ).toAttr().value() ).toDouble();
double zra = QString ( svg.item ( i ).attributes().namedItem ( "zindex" ).toAttr().value() ).toDouble();
QString fra = svg.item ( i ).attributes().namedItem ( "file" ).toAttr().value();
qDebug() << "loading svg " << fra;
extraScene->load ( fra, xra, yra , zra);
}
QDomNodeList cu = doc.elementsByTagName ( "cursor" );
double cux = QString ( cu.item ( 0 ).attributes().namedItem ( "xpos" ).toAttr().value() ).toDouble();
double cuy = QString ( cu.item ( 0 ).attributes().namedItem ( "ypos" ).toAttr().value() ).toDouble();
// qDebug() << cux << " " << cuy;
pageCursorX->setValue ( cux );
pageCursorY->setValue ( cuy );
QDomNodeList lh = doc.elementsByTagName ( "lineh" );
double slh = QString ( lh.item ( 0 ).toElement().text() ).toDouble();
QDomNodeList lw = doc.elementsByTagName ( "linew" );
double slw = QString ( lw.item ( 0 ).toElement().text() ).toDouble();
lhSpin->setValue ( slh );
lwSpin->setValue ( slw );
setCurrentFile ( fileName );
statusBar()->showMessage ( tr ( "%1 loaded" ).arg ( fileName ), 2000 );
}
bool undertype::saveFile ( const QString &fileName )
{
QFile file ( fileName );
if ( !file.open ( QFile::WriteOnly ) )
{
QMessageBox::warning ( this, tr ( "Application" ),
tr ( "Cannot write file %1:\n%2." )
.arg ( fileName )
.arg ( file.errorString() ) );
return false;
}
// my own code
QTextStream ts ( &file );
ts << "<undertype>\n";
ts << QString ( "<page width=\"%1\" height=\"%2\"/>\n" ).arg ( pages->width() ).arg ( pages->height() );
QMap<uint, QPointF> gr = pages->groups();
QList<uint> k = gr.keys();
QList<ULGlyphItem*> gl;
for ( uint i = 0; i < glyphScene.count(); ++i )
{
ts << glyphScene[i]->collection()->toElement();
}
for ( uint i = 0; i < k.count(); ++i )
{
ts << "<group id=\""<< k[i]
<< "\" xpos=\"" << gr[k[i]].x()
<< "\" ypos=\"" << gr[k[i]].y()
<< "\" baseline=\"" << pages->groupById ( k[i] )->data ( 3 ).toDouble()
<< "\" lineheight=\"" << pages->groupById ( k[i] )->data ( 4 ).toDouble()
<< "\" curpos=\"" << pages->groupById ( k[i] )->data ( 5 ).toDouble()
<< "\" ltr=\"" << pages->groupById ( k[i] )->data ( 6 ).toInt()
<< "\">\n";
gl.clear();
gl = PageBuffer::getInstance()->take ( k[i] );
for ( uint j=0;j<gl.count();++j )
{
ts << gl[j]->toElement();
}
ts << "</group>\n";
}
QList<QGraphicsItem*> grlist = pages->items();
for ( uint i = 0; i <grlist.count(); ++i )
{
if ( grlist[i]->data ( 1 ).toString() == "raster" )
{
QString rf = grlist[i]->data ( 2 ).toString();
rf.chop ( 10 );
ts << QString ( "<raster file=\"%1\" xpos=\"%2\" ypos=\"%3\" zindex=\"%4\"/>\n" )
.arg ( rf )
.arg ( grlist[i]->scenePos().x() )
.arg ( grlist[i]->scenePos().y() )
.arg(grlist[i]->zValue()) ;
}
if ( grlist[i]->data ( 1 ).toString() == "svg" )
{
QString rf = grlist[i]->data ( 2 ).toString();
rf.chop ( 10 );
ts << QString ( "<svg file=\"%1\" xpos=\"%2\" ypos=\"%3\" zindex=\"%4\"/>\n" )
.arg ( rf )
.arg ( grlist[i]->scenePos().x() )
.arg ( grlist[i]->scenePos().y() )
.arg(grlist[i]->zValue()) ;
}
}
ts << "<cursor xpos=\""<< QString::number ( pageCursorX->value() ) <<"\" ypos=\""<< QString::number ( pageCursorY->value() ) <<"\"/>";
ts << "<lineh>" << QString::number ( lhSpin->value() ) << "</lineh>";
ts << "<linew>" << QString::number ( lwSpin->value() ) << "</linew>";
ts << "\n</undertype>";
file.close();
// end of my own code
setCurrentFile ( fileName );
statusBar()->showMessage ( tr ( "%1 saved" ).arg ( fileName ), 2000 );
return true;
}
void undertype::setCurrentFile ( const QString &fileName )
{
curFile = fileName;
setWindowModified ( false );
QString shownName;
if ( curFile.isEmpty() )
shownName = "untitled.udl";
else
shownName = strippedName ( curFile );
setWindowTitle ( tr ( "%1[*] - %2" ).arg ( shownName ).arg ( tr ( "UnderType" ) ) );
}
QString undertype::strippedName ( const QString &fullFileName )
{
return QFileInfo ( fullFileName ).fileName();
}
undertype::~undertype()
{}
void undertype::newCasse()
{
ULGlyphScene *scene = new ULGlyphScene();
scene->setBackgroundBrush ( Qt::lightGray );
scene->setMainScene ( lineScene );
glyphScene.append ( scene );
QGraphicsView *view = new QGraphicsView ( scene );
view->setRenderHints ( QPainter::Antialiasing );
glyphView.append ( view );
double size = QInputDialog::getDouble ( this, "Size","Size", 12.0,4.0,200.0,1 );
ULGlyphCollection * col = new ULGlyphCollection ( scene,size );
scene->setCollection ( col );
col->autoFeed();
casses.append ( col );
casseSelect->addItem ( col->name(), QVariant ( col->name() ) );
tabCasses->setCurrentIndex ( tabCasses->addTab ( view, col->name() ) );
}
void undertype::loadCasse()
{
QStringList cassePath = QFileDialog::getOpenFileNames ( this );
if ( cassePath.isEmpty() )
{
return;
}
QString control = "UNDERTYPE_CASSE";
for ( uint f = 0; f < cassePath.count(); ++f )
{
QFile fontfile ( cassePath[f] );
if ( !fontfile.open ( QIODevice::ReadOnly | QIODevice::Text ) )
continue;
QTextStream fontstream ( &fontfile );
if ( fontstream.readLine() == control )
{
QString fname;
QString fpath;
double fsize;
QMap<uint,QString> gmap;
fpath = fontstream.readLine();
qDebug ( fpath.toAscii() );
fsize = fontstream.readLine().toDouble();
qDebug ( QString::number ( fsize ).toAscii() );
fname = fontstream.readLine();
qDebug ( fname.toAscii() );
while ( !fontstream.atEnd() )
{
QString it = fontstream.readLine();
qDebug ( it.toAscii() );
QStringList lit = it.split ( ' ' );
if ( lit.count() == 2 )
gmap.insert ( lit[0].toUInt(),lit[1] );
}
ULGlyphScene *scene = new ULGlyphScene();
scene->setBackgroundBrush ( Qt::lightGray );
scene->setMainScene ( lineScene );
glyphScene.append ( scene );
QGraphicsView *view = new QGraphicsView ( scene );
view->setRenderHints ( QPainter::Antialiasing );
glyphView.append ( view );
ULGlyphCollection * col = new ULGlyphCollection ( scene,fsize );
scene->setCollection ( col );
col->userFeed ( fpath,fname,gmap );
casses.append ( col );
casseSelect->addItem ( col->name(), QVariant ( col->name() ) );
tabCasses->setCurrentIndex ( tabCasses->addTab ( view, col->name() ) );
}
fontfile.close();
}
}
void undertype::print()
{
QPrinter thePrinter ( QPrinter::HighResolution );
QPrintDialog printDialog ( &thePrinter, this );
if ( printDialog.exec() == QDialog::Accepted )
{
thePrinter.setFullPage ( true );
QPainter painter ( &thePrinter );
painter.setRenderHint ( QPainter::Antialiasing );
painter.setBackgroundMode ( Qt::TransparentMode );
// painter.setViewport(pages->sceneRect().toAlignedRect());
pages->hideCursor();
pages->render ( &painter );
pages->showCursor();
}
}
void undertype::newLine()
{
//Setting default line
// // double b = QInputDialog::getDouble(this,"line","set line height");
// // double w = QInputDialog::getDouble(this,"line","set line width");
lineScene->init ( 20.0,250.0 );
}
void undertype::editGlyph ( ULGlyphItem * g )
{
glyphEditor = new QDockWidget ( tr ( "Établi" ), this );
QGroupBox *frame= new QGroupBox ( this );
// inputs
typedef QPair<QLabel*,QDoubleSpinBox*> InputPair;
QMap<QString, InputPair > inputs;
inputs.insert ( "scale", InputPair ( new QLabel ( "Scale",glyphEditor ),new QDoubleSpinBox() ) );
inputs.insert ( "rotate",InputPair ( new QLabel ( "Rotate",glyphEditor ),new QDoubleSpinBox() ) );
inputs.insert ( "transH",InputPair ( new QLabel ( "Translate Hor.",glyphEditor ),new QDoubleSpinBox() ) );
inputs.insert ( "transV",InputPair ( new QLabel ( "Translate Vert.",glyphEditor ),new QDoubleSpinBox() ) );
inputs.insert ( "advance",InputPair ( new QLabel ( "Advance",glyphEditor ),new QDoubleSpinBox() ) );
inputs["scale"].second->setRange ( 0.1,10.0 );
inputs["scale"].second->setSingleStep ( 0.1 );
inputs["scale"].second->setValue ( 1.0 );
inputs["rotate"].second->setRange ( -180.0,180.0 );
inputs["transH"].second->setRange ( -100.0,100.0 );
inputs["transV"].second->setRange ( -100.0,100.0 );
inputs["advance"].second->setRange ( -100.0,100.0 );
inputs["advance"].second->setSingleStep ( 0.1 );
inputs["advance"].second->setValue ( g->m_xadvance );
// glyph slot
ULEditGlyph *gscene = new ULEditGlyph();
QGraphicsView *gview = new QGraphicsView ( gscene );
gscene->putGlyph ( lineScene,g );
gview->scale ( 5.0,5.0 );
// layout
QHBoxLayout *vbox = new QHBoxLayout();
QGridLayout *glay = new QGridLayout();
QVBoxLayout *v = new QVBoxLayout();
glay->addWidget ( inputs["scale"].first, 0,0 );
glay->addWidget ( inputs["scale"].second, 0,1 );
glay->addWidget ( inputs["rotate"].first, 1,0 );
glay->addWidget ( inputs["rotate"].second, 1,1 );
glay->addWidget ( inputs["transH"].first, 2,0 );
glay->addWidget ( inputs["transH"].second, 2,1 );
glay->addWidget ( inputs["transV"].first, 3,0 );
glay->addWidget ( inputs["transV"].second, 3,1 );
glay->addWidget ( inputs["advance"].first, 4,0 );
glay->addWidget ( inputs["advance"].second, 4,1 );
v->addWidget ( gview );
v->addWidget ( new QLabel ( "The Glyph" ) );
vbox->addLayout ( v );
vbox->addLayout ( glay );
frame->setLayout ( vbox );
glyphEditor->setWidget ( frame );
addDockWidget ( Qt::BottomDockWidgetArea, glyphEditor );
connect ( inputs["scale"].second, SIGNAL ( valueChanged ( double ) ),gscene,SLOT ( slotScale ( double ) ) );
connect ( inputs["rotate"].second, SIGNAL ( valueChanged ( double ) ),gscene,SLOT ( slotRotate ( double ) ) );
connect ( inputs["transH"].second, SIGNAL ( valueChanged ( double ) ),gscene,SLOT ( slotTransX ( double ) ) );
connect ( inputs["transV"].second, SIGNAL ( valueChanged ( double ) ),gscene,SLOT ( slotTransY ( double ) ) );
connect ( inputs["advance"].second, SIGNAL ( valueChanged ( double ) ),gscene,SLOT ( slotAdvance ( double ) ) );
connect ( gscene,SIGNAL ( endEdit() ),glyphEditor,SLOT ( close() ) );
}
void undertype::changeLineWidgetValues ( double lh, double w, double cursor )
{
lhSpin->setValue ( lh );
lwSpin->setValue ( w );
gcursor->setValue ( cursor );
}
void undertype::saveCasse()
{
QString control = "UNDERTYPE_CASSE";
QString sel = casseSelect->currentText();
ULGlyphCollection *les;
for ( uint i = 0; i < glyphScene.count(); ++i )
{
if ( glyphScene[i]->collection()->name() == sel )
les = glyphScene[i]->collection();
}
// QFileDialog dialog(this);
// // dialog.setFileMode(QFileDialog::AnyFile);
// // dialog.setAcceptMode(QFileDialog::AcceptSave);
QString filepath = QFileDialog::getSaveFileName();
QFile file ( filepath );
if ( !file.open ( QIODevice::WriteOnly | QIODevice::Text ) )
return;
QTextStream out ( &file );
out << control << "\n";
out << les->fontPath() << "\n";
out << les->fontSize() << "\n";
out << les->name() << "\n";
for ( uint i = 0; i < les->count(); ++i )
{
out << ( i + 1 ) << " " << ( *les ) [i]->key << "\n";
}
file.close();
}
void undertype::moveGcursorBegin()
{
gcursor->setValue ( 0.0 );
}
void undertype::moveGcursorEnd()
{
gcursor->setValue ( lwSpin->value() );
}
void undertype::switchPAA()
{
mainView->setRenderHint ( QPainter::Antialiasing, !pageAntiAlias );
pageAntiAlias = !pageAntiAlias;
}
void undertype::pageSetup()
{
QDialog *dial = new QDialog ( this );
QGridLayout *lay = new QGridLayout ( dial );
QLabel *pw = new QLabel ( "Width" );
QLabel *ph = new QLabel ( "Height" );
QDoubleSpinBox *sw = new QDoubleSpinBox();
sw->setRange ( 1.0,10000.0 );
// sw->setSuffix(" pt");
sw->setValue ( pages->width() );
QDoubleSpinBox *sh = new QDoubleSpinBox();
sh->setRange ( 1.0,10000.0 );
// sh->setSuffix(" pt");
sh->setValue ( pages->height() );
QButtonGroup * unit = new QButtonGroup();
QRadioButton * pt = new QRadioButton ( "pt" );
QRadioButton * mm = new QRadioButton ( "mm" );
unit->addButton ( pt );
unit->addButton ( mm );
pt->setChecked ( true );
QPushButton *ok = new QPushButton ( "OK" );
lay->addWidget ( pw,0,0 );
lay->addWidget ( ph,1,0 );
lay->addWidget ( sw,0,1 );
lay->addWidget ( sh,1,1 );
lay->addWidget ( pt,2,0 );
lay->addWidget ( mm,2,1 );
lay->addWidget ( ok,3,1 );
connect ( ok,SIGNAL ( released() ),dial,SLOT ( close() ) );
dial->exec();
QString u = unit->checkedButton()->text();
ULUnit w ( sw->value(),u );
ULUnit h ( sh->value(),u );
pages->setPageSize ( w.pt(), h.pt() );
pageDimLabel->setText ( "page : " + QString().number ( w.mm() ) +" mm x "+QString().number ( h.mm() ) + " mm" );
delete sw;
delete sh;
delete pw;
delete ph;
delete lay;
delete dial;
}
void undertype::exportPDF()
{
qDebug ( "exporting pdf" );
QString fileName = QFileDialog::getSaveFileName ( this, tr ( "Export to PDF" ), curFile + ".pdf", tr ( "Portable etc. (*.pdf)" ) );
QFile file ( fileName );
if ( !file.open ( QIODevice::WriteOnly ) )
return;
QByteArray buffer;
QDataStream pdf ( &buffer, QIODevice::WriteOnly );
QString xref;
xref = "0000000000 65535 f \n";
QByteArray tmp = QString ( "%PDF-1.3\n" ).toAscii();
pdf.writeRawData ( tmp,tmp.size() );
qDebug() << buffer;
QString xDic;
QByteArray content;
QMap<double, QByteArray > stackedcontent;
uint obj = 1;
QMap<ULGlyphItem*, uint> objMap;
PageBuffer *pb = PageBuffer::getInstance();
uint nit = pb->maxId() + 1;
double gZindex = 10.0;
for ( uint i = 1; i < nit ; ++i )
{
QList<ULGlyphItem*> glist = pb->take ( i );
for ( uint g=0;g<glist.count();++g )
{
xref.append ( QString ( "%1 00000 n \n" ).arg ( buffer.size()-1,10,10,QChar ( '0' ) ) );
QByteArray tmp;
tmp.append ( QString ( "%1 0 obj\n" ).arg ( obj ).toAscii() );
tmp.append ( glist[g]->XObject().toAscii() );
tmp.append ( "endobj\n" );
pdf.writeRawData ( tmp.constData(), tmp.size() );
objMap.insert ( glist[g], obj );
xDic.append ( QString ( "/gl%1 %1 0 R\n" ).arg ( obj ) );
stackedcontent.insert(gZindex, QString ( "q\n1 0 0 1 %1 %2 cm\n/gl%3 Do\nQ\n" ).arg ( glist[g]->scenePos().x() ).arg ( pages->height() - glist[g]->scenePos().y() ).arg ( obj ).toAscii() );
++obj;
gZindex += 0.0000001;
}
}
QMap<QString, uint> gobjs;
QMap<QString, QRectF> grect;
QMap<QString, bool> grast;
QMap<QString, double> gstack;
QList<QGraphicsItem*> allI = pages->items();
for ( uint i=0; i < allI.count(); ++i )
{
if ( allI[i]->data ( 1 ).toString() == "raster" )
{
grect.insert ( allI[i]->data ( 2 ).toString(), allI[i]->sceneBoundingRect() );
grast.insert ( allI[i]->data ( 2 ).toString(), true );
gstack.insert ( allI[i]->data ( 2 ).toString(), allI[i]->zValue() );
}
if ( allI[i]->data ( 1 ).toString() == "svg" )
{
grect.insert ( allI[i]->data ( 2 ).toString(), allI[i]->sceneBoundingRect() );
grast.insert ( allI[i]->data ( 2 ).toString(), false );
gstack.insert ( allI[i]->data ( 2 ).toString(), allI[i]->zValue() );
}
}
QStringList imgs = grect.keys();
for ( uint i = 0; i < imgs.count(); ++i )
{
QString name = imgs[i];
QString realname = name;
realname.chop ( 10 );
if ( !gobjs.contains ( realname ) )
{
double zz = gstack[name];
while ( stackedcontent.contains ( zz ) )
{
zz += 0.0000001;
}
xref.append ( QString ( "%1 00000 n \n" ).arg ( buffer.size()-1,10,10,QChar ( '0' ) ) );
bool rast = grast[name];
gobjs.insert ( realname, obj );
QByteArray tmp ( QString ( "%1 0 obj\n" ).arg ( obj ).toAscii() );
tmp.append ( pb->graphics[realname]->XObject() );
tmp.append ( "endobj\n" );
pdf.writeRawData ( tmp.constData(), tmp.size() );
xDic.append ( QString ( "/graphic%1 %1 0 R\n" ).arg ( obj ) );
stackedcontent.insert ( zz, QString ( "q\n%1 0 0 %2 %3 %4 cm\n/graphic%5 Do\nQ\n" )
.arg ( rast ? grect[name].width() : 1 )
.arg ( rast ? grect[name].height() : 1 )
.arg ( grect[name].x() )
.arg ( rast ? pages->height() - grect[name].bottom() : pages->height() - grect[name].y() )
.arg ( obj )
.toAscii()
);
++obj;
}
else
{
double zz = gstack[name];
while ( stackedcontent.contains ( zz ) )
{
zz += 0.0000001;
}
uint tmpobj = gobjs[realname];
bool rast = grast[name];
stackedcontent.insert ( zz, QString ( "q\n%1 0 0 %2 %3 %4 cm\n/graphic%5 Do\nQ\n" )
.arg ( rast ? grect[name].width() : 1 )
.arg ( rast ? grect[name].height() : 1 )
.arg ( grect[name].x() )
.arg ( rast ? pages->height() - grect[name].bottom() : pages->height() - grect[name].y() )
.arg ( tmpobj )
.toAscii()
);
}
}
QMapIterator<double, QByteArray> i(stackedcontent);
while (i.hasNext()) {
i.next();
content.append(i.value());
}
xref.append ( QString ( "%1 00000 n \n" ).arg ( buffer.size()-1,10,10,QChar ( '0' ) ) );
tmp = QString ( "%1 0 obj\n" ).arg ( obj ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
uint root = obj;
++obj;
tmp = QString ( "<<\n/Type /Catalog\n/Pages %1 0 R\n>>\nendobj\n" ).arg ( obj ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
xref.append ( QString ( "%1 00000 n \n" ).arg ( buffer.size()-1,10,10,QChar ( '0' ) ) );
tmp = QString ( "%1 0 obj\n" ).arg ( obj ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
++obj;
tmp = QString ( "<<\n/Type /Pages\n/Kids [%1 0 R]\n/Count 1\n>>\nendobj\n" ).arg ( obj ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
xref.append ( QString ( "%1 00000 n \n" ).arg ( buffer.size()-1,10,10,QChar ( '0' ) ) );
tmp = QString ( "%1 0 obj\n" ).arg ( obj ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
++obj;
tmp =QString ( "<<\n/Type /Page\n/Parent %1 0 R\n" ).arg ( obj - 2 ).toAscii() ;
pdf.writeRawData ( tmp.constData(), tmp.size() );
tmp = QString ( "/MediaBox [0 0 %1 %2]\n" ).arg ( pages->width() ).arg ( pages->height() ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
tmp = QString ( "/Contents %1 0 R\n" ).arg ( obj + 1 ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
tmp = QString ( "/Resources << /XObject %1 0 R >>\n>>\nendobj\n" ).arg ( obj ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
xref.append ( QString ( "%1 00000 n \n" ).arg ( buffer.size()-1,10,10,QChar ( '0' ) ) );
xDic.prepend ( QString ( "%1 0 obj\n<<\n" ).arg ( obj ) );
tmp = QString ( xDic + ">>\nendobj\n" ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
++obj;
uint sizecontent = content.length();
content.prepend ( QString ( "%2 0 obj\n << /Length %1 >>\nstream\n" ).arg ( sizecontent ).arg ( obj ).toAscii() );
content.append ( "endstream\nendobj\n" );
xref.append ( QString ( "%1 00000 n \n" ).arg ( buffer.size()-1,10,10,QChar ( '0' ) ) );
pdf.writeRawData ( content, content.size() );
uint xrefref = buffer.size();
xref.prepend ( QString ( "xref\n0 %1\n" ).arg ( obj + 1 ) );
tmp = xref.toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
tmp=QString ( "trailer\n<< /Size %1 \n" ).arg ( obj + 1 ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
tmp= QString ( "/Root %1 0 R>>\nstartxref\n" ).arg ( root ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
tmp= QString ( "%1\n%%EOF" ).arg ( xrefref ).toAscii();
pdf.writeRawData ( tmp.constData(), tmp.size() );
//control
// QStringList xl = xref.split('\n');
// for(uint i = 1 ;i < xl.count(); ++i)
// {
// uint seek = xl[i].left(10).toLongLong();
// qDebug() << xl[i] << seek << buffer.mid(seek, 10) ;
// }
file.seek ( 0 );
QDataStream out ( &file );
out.writeRawData ( buffer.constData(),buffer.size() );
file.close();
statusBar()->showMessage ( QString ( "%1 saved" ).arg ( fileName ),3000 );
}
void undertype::closeDoc()
{
if(maybeSave())
{
PageBuffer::getInstance()->clear();
pages->clear();
}
pages->setCur(40,40);
}
void undertype::switchCMap(bool b)
{
m_usecmap = b;
}