diff --git a/YACReader/YACReader.pro b/YACReader/YACReader.pro index 96aecc7e..3dd4d1fa 100644 --- a/YACReader/YACReader.pro +++ b/YACReader/YACReader.pro @@ -7,7 +7,7 @@ DEPENDPATH += . \ release INCLUDEPATH += . INCLUDEPATH += ../common -QT += network webkit phonon +QT += network webkit phonon opengl CONFIG += release CONFIG -= flat @@ -28,7 +28,11 @@ HEADERS += comic.h \ bookmarks_dialog.h \ render.h \ shortcuts_dialog.h \ - translator.h + translator.h \ + ../common/goto_flow_widget.h \ + goto_flow_gl.h \ + ../common/yacreader_flow_gl.h + SOURCES += comic.cpp \ configuration.cpp \ goto_dialog.cpp \ @@ -46,7 +50,11 @@ SOURCES += comic.cpp \ bookmarks_dialog.cpp \ render.cpp \ shortcuts_dialog.cpp \ - translator.cpp + translator.cpp \ + ../common/goto_flow_widget.cpp \ + goto_flow_gl.cpp \ + ../common/yacreader_flow_gl.cpp + RESOURCES += images.qrc \ files.qrc RC_FILE = icon.rc diff --git a/YACReader/goto_flow.cpp b/YACReader/goto_flow.cpp index edb8fd17..08fe6afb 100644 --- a/YACReader/goto_flow.cpp +++ b/YACReader/goto_flow.cpp @@ -19,7 +19,7 @@ QMutex mutexGoToFlow; GoToFlow::GoToFlow(QWidget *parent,PictureFlow::FlowType flowType) -:QWidget(parent),ready(false) +:GoToFlowWidget(parent),ready(false) { updateTimer = new QTimer; connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateImageData())); diff --git a/YACReader/goto_flow.h b/YACReader/goto_flow.h index c521f2f4..b4a77247 100644 --- a/YACReader/goto_flow.h +++ b/YACReader/goto_flow.h @@ -12,12 +12,13 @@ #include #include #include "custom_widgets.h" +#include "goto_flow_widget.h" class Comic; class SlideInitializer; class PageLoader; -class GoToFlow : public QWidget +class GoToFlow : public GoToFlowWidget { Q_OBJECT public: @@ -31,7 +32,7 @@ private: QIntValidator * v; QPushButton * centerButton; QPushButton * goToButton; - Comic * comic; + //Comic * comic; QSize imageSize; QVector imagesLoaded; diff --git a/YACReader/images.qrc b/YACReader/images.qrc index 2aab79e4..26a9d978 100644 --- a/YACReader/images.qrc +++ b/YACReader/images.qrc @@ -62,6 +62,7 @@ ../images/helpImages/shortcuts.png ../images/helpImages/keyboard.png ../images/helpImages/mouse.png - ../images/helpImages/speaker.png + ../images/helpImages/speaker.png + ../images/defaultCover.png diff --git a/YACReader/viewer.cpp b/YACReader/viewer.cpp index daa54a4d..477742d7 100644 --- a/YACReader/viewer.cpp +++ b/YACReader/viewer.cpp @@ -3,6 +3,7 @@ #include "configuration.h" #include "magnifying_glass.h" #include "goto_flow.h" +#include "goto_flow_gl.h" #include "bookmarks_dialog.h" #include "render.h" #include "goto_dialog.h" @@ -65,7 +66,7 @@ drag(false) goToDialog = new GoToDialog(this); - goToFlow = new GoToFlow(this,Configuration::getConfiguration().getFlowType()); + goToFlow = new GoToFlowGL(this,Configuration::getConfiguration().getFlowType()); goToFlow->hide(); showGoToFlowAnimation = new QPropertyAnimation(goToFlow,"pos"); showGoToFlowAnimation->setDuration(150); diff --git a/YACReader/viewer.h b/YACReader/viewer.h index 6da04035..8f16d0bf 100644 --- a/YACReader/viewer.h +++ b/YACReader/viewer.h @@ -24,6 +24,7 @@ class BookmarksDialog; class Render; class GoToDialog; class YACReaderTranslator; +class GoToFlowWidget; class Viewer : public QScrollArea { @@ -78,7 +79,7 @@ virtual void mouseReleaseEvent ( QMouseEvent * event ); QTimer * scroller; int posByStep; int nextPos; - GoToFlow * goToFlow; + GoToFlowWidget * goToFlow; QPropertyAnimation * showGoToFlowAnimation; GoToDialog * goToDialog; //!Image properties diff --git a/YACReaderLibrary/images.qrc b/YACReaderLibrary/images.qrc index 92ef8e47..8658670d 100644 --- a/YACReaderLibrary/images.qrc +++ b/YACReaderLibrary/images.qrc @@ -37,5 +37,6 @@ ../images/importComicsInfo.png ../images/db.png ../images/asignNumber.png + ../images/defaultCover.png \ No newline at end of file diff --git a/common/comic_flow_widget.cpp b/common/comic_flow_widget.cpp index 483d1573..e0891027 100644 --- a/common/comic_flow_widget.cpp +++ b/common/comic_flow_widget.cpp @@ -124,7 +124,7 @@ void ComicFlowWidgetSW::mouseDoubleClickEvent(QMouseEvent* event) ComicFlowWidgetGL::ComicFlowWidgetGL(QWidget * parent) :ComicFlowWidget(parent) { - flow = new YACReaderFlowGL(parent); + flow = new YACReaderComicFlowGL(parent); connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int))); connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int))); diff --git a/common/comic_flow_widget.h b/common/comic_flow_widget.h index 832059f3..d6d53f8b 100644 --- a/common/comic_flow_widget.h +++ b/common/comic_flow_widget.h @@ -69,7 +69,7 @@ class ComicFlowWidgetGL : public ComicFlowWidget { Q_OBJECT private: - YACReaderFlowGL * flow; + YACReaderComicFlowGL * flow; public: ComicFlowWidgetGL(QWidget * parent = 0); diff --git a/common/yacreader_flow_gl.cpp b/common/yacreader_flow_gl.cpp index 4057e88f..70723870 100644 --- a/common/yacreader_flow_gl.cpp +++ b/common/yacreader_flow_gl.cpp @@ -204,9 +204,6 @@ YACReaderFlowGL::YACReaderFlowGL(QWidget *parent,struct Preset p) viewRotateActive = 0; stepBackup = config.animationStep/config.animationSpeedUp; - worker = new ImageLoaderGL(this); - worker->flow = this; - /*QTimer * timer = new QTimer(); connect(timer, SIGNAL(timeout()), this, SLOT(updateImageData())); timer->start(70); @@ -679,7 +676,7 @@ void YACReaderFlowGL::populate(int n) float x = 1; float y = 1 * (700/480.0); int i; - GLuint cover = bindTexture(QImage(":/images/notCover.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); + GLuint cover = bindTexture(QImage(":/images/defaultCover.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); markTexture = bindTexture(QImage(":/images/setRead.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); for(i = 0;ibusy()) - return; - - // set image of last one - int idx = worker->index(); - if( idx >= 0 && !worker->result().isNull()) - { - if(!loaded[idx]) - { - float x = 1; - QImage img = worker->result(); - GLuint cover = bindTexture(img, GL_TEXTURE_2D,GL_RGB,QGLContext::LinearFilteringBindOption); - float y = 1 * (float(img.height())/img.width()); - replace("cover", cover, x, y,idx); - /*CFImages[idx].width = x; - CFImages[idx].height = y; - CFImages[idx].img = worker->resultTexture; - strcpy(CFImages[idx].name,"cover");*/ - loaded[idx] = true; - //numImagesLoaded++; - } - } - - // try to load only few images on the left and right side - // i.e. all visible ones plus some extra -#define COUNT 8 - int indexes[2*COUNT+1]; - int center = currentSelected; - indexes[0] = center; - for(int j = 0; j < COUNT; j++) - { - indexes[j*2+1] = center+j+1; - indexes[j*2+2] = center-j-1; - } - for(int c = 0; c < 2*COUNT+1; c++) - { - int i = indexes[c]; - if((i >= 0) && (i < numObjects)) - if(!loaded[i])//slide(i).isNull()) - { - //loader->loadTexture(i); - //loaded[i]=true; - // schedule thumbnail generation - if(paths.size()>0) - { - QString fname = paths.at(i); - //loaded[i]=true; - - worker->generate(i, fname); - } - return; - } - } -} void YACReaderFlowGL::setPreset(const Preset & p) { @@ -873,15 +807,7 @@ void YACReaderFlowGL::clear() { reset(); } -void YACReaderFlowGL::setImagePaths(QStringList paths) -{ - worker->reset(); - reset(); - numObjects = 0; - populate(paths.size()); - this->paths = paths; - numObjects = paths.size(); -} + void YACReaderFlowGL::setCenterIndex(int index) { setCurrentIndex(index); @@ -986,6 +912,170 @@ void YACReaderFlowGL::mouseDoubleClickEvent(QMouseEvent* event) emit selected(centerIndex()); } +YACReaderComicFlowGL::YACReaderComicFlowGL(QWidget *parent,struct Preset p ) + :YACReaderFlowGL(parent,p) +{ + worker = new ImageLoaderGL(this); + worker->flow = this; +} + +void YACReaderComicFlowGL::setImagePaths(QStringList paths) +{ + worker->reset(); + reset(); + numObjects = 0; + populate(paths.size()); + this->paths = paths; + numObjects = paths.size(); +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +void YACReaderComicFlowGL::updateImageData() +{ + // can't do anything, wait for the next possibility + if(worker->busy()) + return; + + // set image of last one + int idx = worker->index(); + if( idx >= 0 && !worker->result().isNull()) + { + if(!loaded[idx]) + { + float x = 1; + QImage img = worker->result(); + GLuint cover = bindTexture(img, GL_TEXTURE_2D,GL_RGB,QGLContext::LinearFilteringBindOption); + float y = 1 * (float(img.height())/img.width()); + replace("cover", cover, x, y,idx); + /*CFImages[idx].width = x; + CFImages[idx].height = y; + CFImages[idx].img = worker->resultTexture; + strcpy(CFImages[idx].name,"cover");*/ + loaded[idx] = true; + //numImagesLoaded++; + } + } + + // try to load only few images on the left and right side + // i.e. all visible ones plus some extra +#define COUNT 8 + int indexes[2*COUNT+1]; + int center = currentSelected; + indexes[0] = center; + for(int j = 0; j < COUNT; j++) + { + indexes[j*2+1] = center+j+1; + indexes[j*2+2] = center-j-1; + } + for(int c = 0; c < 2*COUNT+1; c++) + { + int i = indexes[c]; + if((i >= 0) && (i < numObjects)) + if(!loaded[i])//slide(i).isNull()) + { + //loader->loadTexture(i); + //loaded[i]=true; + // schedule thumbnail generation + if(paths.size()>0) + { + QString fname = paths.at(i); + //loaded[i]=true; + + worker->generate(i, fname); + } + return; + } + } +} + + +YACReaderPageFlowGL::YACReaderPageFlowGL(QWidget *parent,struct Preset p ) + :YACReaderFlowGL(parent,p) +{ + worker = new ImageLoaderByteArrayGL(this); + worker->flow = this; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +void YACReaderPageFlowGL::updateImageData() +{ + // can't do anything, wait for the next possibility + if(worker->busy()) + return; + + // set image of last one + int idx = worker->index(); + if( idx >= 0 && !worker->result().isNull()) + { + if(!loaded[idx]) + { + float x = 1; + QImage img = worker->result(); + GLuint cover = bindTexture(img, GL_TEXTURE_2D,GL_RGB,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); + float y = 1 * (float(img.height())/img.width()); + replace("cover", cover, x, y,idx); + /*CFImages[idx].width = x; + CFImages[idx].height = y; + CFImages[idx].img = worker->resultTexture; + strcpy(CFImages[idx].name,"cover");*/ + loaded[idx] = true; + //numImagesLoaded++; + } + } + + // try to load only few images on the left and right side + // i.e. all visible ones plus some extra +#define COUNT 8 + int indexes[2*COUNT+1]; + int center = currentSelected; + indexes[0] = center; + for(int j = 0; j < COUNT; j++) + { + indexes[j*2+1] = center+j+1; + indexes[j*2+2] = center-j-1; + } + for(int c = 0; c < 2*COUNT+1; c++) + { + int i = indexes[c]; + if((i >= 0) && (i < numObjects)) + if(rawImages.size()>0) + + if(!loaded[i]&&imagesReady[i])//slide(i).isNull()) + { + //loader->loadTexture(i); + //loaded[i]=true; + // schedule thumbnail generation + + //loaded[i]=true; + + worker->generate(i, rawImages.at(i)); + + return; + } + } +} + +void YACReaderPageFlowGL::populate(int n) +{ + YACReaderFlowGL::populate(n); + imagesReady = QVector (n,false); + rawImages = QVector (n); + imagesSetted = QVector (n,false); //puede sobrar + +} + + //----------------------------------------------------------------------------- //ImageLoader //----------------------------------------------------------------------------- @@ -1079,17 +1169,110 @@ QImage ImageLoaderGL::result() return img; } -WidgetLoader::WidgetLoader(QWidget *parent, QGLWidget * shared) - :QGLWidget(parent,shared) -{ -} - -void WidgetLoader::loadTexture(int index) +//----------------------------------------------------------------------------- +//ImageLoader +//----------------------------------------------------------------------------- +QImage ImageLoaderByteArrayGL::loadImage(const QByteArray& raw) { QImage image; - bool result = image.load(QString("./cover%1.jpg").arg(index+1)); - //image = image.scaledToWidth(128,Qt::SmoothTransformation); //TODO parametrizar - flow->cfImages[index].width = 0.5; - flow->cfImages[index].height = 0.5 * (float(image.height())/image.width()); - flow->cfImages[index].img = bindTexture(image, GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); -} \ No newline at end of file + bool result = image.loadFromData(raw); + + //QGLPixelBuffer * pb = new QGLPixelBuffer(image.size(),flow->format(),flow); + //resultTexture = pb->bindTexture(image,GL_TEXTURE_2D); + + //resultTexture = flow->bindTexture(image,GL_TEXTURE_2D); + + //TODO parametrizar + image = image.scaledToWidth(128,Qt::SmoothTransformation); + + + if(!result) + return QImage(); + + return image; +} + +ImageLoaderByteArrayGL::ImageLoaderByteArrayGL(YACReaderFlowGL * flow): +QThread(),flow(flow),restart(false), working(false), idx(-1) +{ + +} + +ImageLoaderByteArrayGL::~ImageLoaderByteArrayGL() +{ + mutex.lock(); + condition.wakeOne(); + mutex.unlock(); + wait(); +} + +bool ImageLoaderByteArrayGL::busy() const +{ + return isRunning() ? working : false; +} + +void ImageLoaderByteArrayGL::generate(int index, const QByteArray& raw) +{ + mutex.lock(); + this->idx = index; + this->rawData = raw; + this->size = size; + this->img = QImage(); + mutex.unlock(); + + if (!isRunning()) + start(); + else + { + // already running, wake up whenever ready + restart = true; + condition.wakeOne(); + } +} + +void ImageLoaderByteArrayGL::run() +{ + for(;;) + { + // copy necessary data + mutex.lock(); + this->working = true; + QByteArray raw = this->rawData; + mutex.unlock(); + + QImage image = loadImage(raw); + + // let everyone knows it is ready + mutex.lock(); + this->working = false; + this->img = image; + mutex.unlock(); + + // put to sleep + mutex.lock(); + if (!this->restart) + condition.wait(&mutex); + restart = false; + mutex.unlock(); + } +} + +QImage ImageLoaderByteArrayGL::result() +{ + return img; +} + +//WidgetLoader::WidgetLoader(QWidget *parent, QGLWidget * shared) +// :QGLWidget(parent,shared) +//{ +//} +// +//void WidgetLoader::loadTexture(int index) +//{ +// QImage image; +// bool result = image.load(QString("./cover%1.jpg").arg(index+1)); +// //image = image.scaledToWidth(128,Qt::SmoothTransformation); //TODO parametrizar +// flow->cfImages[index].width = 0.5; +// flow->cfImages[index].height = 0.5 * (float(image.height())/image.width()); +// flow->cfImages[index].img = bindTexture(image, GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); +//} \ No newline at end of file diff --git a/common/yacreader_flow_gl.h b/common/yacreader_flow_gl.h index 2a34efe4..4b018ec5 100644 --- a/common/yacreader_flow_gl.h +++ b/common/yacreader_flow_gl.h @@ -16,6 +16,7 @@ class ImageLoaderGL; class QGLContext; class WidgetLoader; +class ImageLoaderByteArrayGL; //Cover Vector typedef struct RVect{ @@ -109,7 +110,7 @@ private: void calcRV(RVect *RV,int pos); void animate(RVect *Current,RVect to); void drawCover(CFImage *CF); - ImageLoaderGL * worker; + int updateCount; WidgetLoader * loader; int fontSize; @@ -211,7 +212,7 @@ public: void setPreset(const Preset & p); - void updateImageData(); + virtual void updateImageData() = 0; void reset(); @@ -223,7 +224,6 @@ public: void unmarkSlide(int index); void setSlideSize(QSize size); void clear(); - void setImagePaths(QStringList paths); void setCenterIndex(int index); void showSlide(int index); int centerIndex(); @@ -243,15 +243,40 @@ signals: void selected(unsigned int); }; -class WidgetLoader : public QGLWidget -{ - Q_OBJECT -public: - WidgetLoader(QWidget *parent, QGLWidget * shared); - YACReaderFlowGL * flow; -public slots: - void loadTexture(int index); +//class WidgetLoader : public QGLWidget +//{ +// Q_OBJECT +//public: +// WidgetLoader(QWidget *parent, QGLWidget * shared); +// YACReaderFlowGL * flow; +//public slots: +// void loadTexture(int index); +// +//}; +class YACReaderComicFlowGL : public YACReaderFlowGL +{ +public: + YACReaderComicFlowGL(QWidget *parent = 0,struct Preset p = defaultYACReaderFlowConfig); + void setImagePaths(QStringList paths); + void updateImageData(); + +private: + ImageLoaderGL * worker; + +}; + +class YACReaderPageFlowGL : public YACReaderFlowGL +{ +public: + YACReaderPageFlowGL(QWidget *parent = 0,struct Preset p = defaultYACReaderFlowConfig); + void updateImageData(); + void populate(int n); + QVector imagesReady; + QVector rawImages; + QVector imagesSetted; +private: + ImageLoaderByteArrayGL * worker; }; class ImageLoaderGL : public QThread @@ -285,6 +310,37 @@ private: QImage img; }; +class ImageLoaderByteArrayGL : public QThread +{ +public: + ImageLoaderByteArrayGL(YACReaderFlowGL * flow); + ~ImageLoaderByteArrayGL(); + // returns FALSE if worker is still busy and can't take the task + bool busy() const; + void generate(int index, const QByteArray& raw); + void reset(){idx = -1;}; + int index() const { return idx; }; + QImage result(); + YACReaderFlowGL * flow; + GLuint resultTexture; + QImage loadImage(const QByteArray& rawData); + +protected: + void run(); + +private: + QMutex mutex; + QWaitCondition condition; + + + bool restart; + bool working; + int idx; + QByteArray rawData; + QSize size; + QImage img; +}; + //class TextureLoader : public QThread //{ //public: diff --git a/images/defaultCover.png b/images/defaultCover.png new file mode 100644 index 00000000..32d6bc19 Binary files /dev/null and b/images/defaultCover.png differ