mirror of
https://github.com/YACReader/yacreader
synced 2026-03-01 18:33:09 -05:00
Extract the comic and page flow classes to their own files
This commit is contained in:
@ -1259,446 +1259,6 @@ QSize YACReaderFlow3D::minimumSizeHint() const
|
||||
}
|
||||
|
||||
// YACReaderComicFlow3D implementation
|
||||
YACReaderComicFlow3D::YACReaderComicFlow3D(QWidget *parent, struct Preset p)
|
||||
: YACReaderFlow3D(parent, p)
|
||||
{
|
||||
worker = new ImageLoader3D(this);
|
||||
worker->flow = this;
|
||||
}
|
||||
// YACReaderComicFlow3D implementation moved to common/rhi/yacreader_comic_flow_rhi.*
|
||||
|
||||
void YACReaderComicFlow3D::setImagePaths(QStringList paths)
|
||||
{
|
||||
worker->reset();
|
||||
reset();
|
||||
numObjects = 0;
|
||||
|
||||
if (hasBeenInitialized) {
|
||||
YACReaderFlow3D::populate(paths.size());
|
||||
} else {
|
||||
lazyPopulateObjects = paths.size();
|
||||
}
|
||||
|
||||
this->paths = paths;
|
||||
}
|
||||
|
||||
void YACReaderComicFlow3D::updateImageData()
|
||||
{
|
||||
if (worker->busy())
|
||||
return;
|
||||
|
||||
int idx = worker->index();
|
||||
if (idx >= 0 && !worker->result().isNull()) {
|
||||
if (!loaded[idx]) {
|
||||
float x = 1;
|
||||
QImage img = worker->result();
|
||||
|
||||
// // Ensure the loaded image is in RGBA8888 layout so QRhi interprets channels correctly
|
||||
// if (img.format() != QImage::Format_RGBA8888)
|
||||
// img = img.convertToFormat(QImage::Format_RGBA8888);
|
||||
|
||||
// Create QRhiTexture from the loaded image
|
||||
if (m_rhi) {
|
||||
QRhiTexture *texture = m_rhi->newTexture(QRhiTexture::BGRA8, img.size(), 1,
|
||||
(performance == high || performance == ultraHigh) ? QRhiTexture::MipMapped : QRhiTexture::UsedAsTransferSource);
|
||||
|
||||
if (texture->create()) {
|
||||
// Queue texture upload (image already converted to RGBA8888)
|
||||
PendingTextureUpload upload;
|
||||
upload.index = idx;
|
||||
upload.image = img;
|
||||
upload.x = x;
|
||||
upload.y = 1 * (float(img.height()) / img.width());
|
||||
pendingTextureUploads.append(upload);
|
||||
|
||||
QString s = "cover";
|
||||
replace(s.toLocal8Bit().data(), texture, upload.x, upload.y, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = 8;
|
||||
switch (performance) {
|
||||
case low:
|
||||
count = 8;
|
||||
break;
|
||||
case medium:
|
||||
count = 10;
|
||||
break;
|
||||
case high:
|
||||
count = 12;
|
||||
break;
|
||||
case ultraHigh:
|
||||
count = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
int *indexes = new int[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]) {
|
||||
if (paths.size() > 0) {
|
||||
QString fname = paths.at(i);
|
||||
worker->generate(i, fname);
|
||||
}
|
||||
delete[] indexes;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] indexes;
|
||||
}
|
||||
|
||||
void YACReaderComicFlow3D::remove(int item)
|
||||
{
|
||||
worker->lock();
|
||||
worker->reset();
|
||||
YACReaderFlow3D::remove(item);
|
||||
if (item >= 0 && item < paths.size()) {
|
||||
paths.removeAt(item);
|
||||
}
|
||||
worker->unlock();
|
||||
}
|
||||
|
||||
void YACReaderComicFlow3D::add(const QString &path, int index)
|
||||
{
|
||||
worker->lock();
|
||||
worker->reset();
|
||||
paths.insert(index, path);
|
||||
YACReaderFlow3D::add(index);
|
||||
worker->unlock();
|
||||
}
|
||||
|
||||
void YACReaderComicFlow3D::resortCovers(QList<int> newOrder)
|
||||
{
|
||||
worker->lock();
|
||||
worker->reset();
|
||||
startAnimationTimer();
|
||||
|
||||
QList<QString> pathsNew;
|
||||
QVector<bool> loadedNew;
|
||||
QVector<YACReaderComicReadStatus> marksNew;
|
||||
QVector<YACReader3DImageRHI> imagesNew;
|
||||
|
||||
int index = 0;
|
||||
foreach (int i, newOrder) {
|
||||
if (i < 0 || i >= images.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pathsNew << paths.at(i);
|
||||
loadedNew << loaded.at(i);
|
||||
marksNew << marks.at(i);
|
||||
imagesNew << images.at(i);
|
||||
imagesNew.last().index = index++;
|
||||
}
|
||||
|
||||
paths = pathsNew;
|
||||
loaded = loadedNew;
|
||||
marks = marksNew;
|
||||
images = imagesNew;
|
||||
|
||||
worker->unlock();
|
||||
}
|
||||
|
||||
// YACReaderPageFlow3D implementation
|
||||
YACReaderPageFlow3D::YACReaderPageFlow3D(QWidget *parent, struct Preset p)
|
||||
: YACReaderFlow3D(parent, p)
|
||||
{
|
||||
worker = new ImageLoaderByteArray3D(this);
|
||||
worker->flow = this;
|
||||
}
|
||||
|
||||
YACReaderPageFlow3D::~YACReaderPageFlow3D()
|
||||
{
|
||||
if (timerId != -1) {
|
||||
this->killTimer(timerId);
|
||||
timerId = -1;
|
||||
}
|
||||
rawImages.clear();
|
||||
|
||||
// Clean up textures and clear images to prevent double-delete in base destructor
|
||||
for (auto &image : images) {
|
||||
if (image.texture != scene.defaultTexture.get()) {
|
||||
delete image.texture;
|
||||
}
|
||||
}
|
||||
images.clear();
|
||||
numObjects = 0;
|
||||
}
|
||||
|
||||
void YACReaderPageFlow3D::updateImageData()
|
||||
{
|
||||
if (worker->busy())
|
||||
return;
|
||||
|
||||
int idx = worker->index();
|
||||
if (idx >= 0 && !worker->result().isNull()) {
|
||||
if (!loaded[idx]) {
|
||||
float x = 1;
|
||||
QImage img = worker->result();
|
||||
|
||||
// Create QRhiTexture from the loaded image
|
||||
if (m_rhi) {
|
||||
QRhiTexture *texture = m_rhi->newTexture(QRhiTexture::BGRA8, img.size(), 1,
|
||||
(performance == high || performance == ultraHigh) ? QRhiTexture::MipMapped : QRhiTexture::UsedAsTransferSource);
|
||||
|
||||
if (texture->create()) {
|
||||
float y = 1 * (float(img.height()) / img.width());
|
||||
QString s = "cover";
|
||||
replace(s.toLocal8Bit().data(), texture, x, y, idx);
|
||||
loaded[idx] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = 8;
|
||||
switch (performance) {
|
||||
case low:
|
||||
count = 8;
|
||||
break;
|
||||
case medium:
|
||||
count = 10;
|
||||
break;
|
||||
case high:
|
||||
count = 12;
|
||||
break;
|
||||
case ultraHigh:
|
||||
count = 14;
|
||||
break;
|
||||
}
|
||||
|
||||
int *indexes = new int[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]) {
|
||||
worker->generate(i, rawImages.at(i));
|
||||
delete[] indexes;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] indexes;
|
||||
}
|
||||
|
||||
void YACReaderPageFlow3D::populate(int n)
|
||||
{
|
||||
worker->reset();
|
||||
|
||||
if (hasBeenInitialized) {
|
||||
YACReaderFlow3D::populate(n);
|
||||
} else {
|
||||
lazyPopulateObjects = n;
|
||||
}
|
||||
|
||||
imagesReady = QVector<bool>(n, false);
|
||||
rawImages = QVector<QByteArray>(n);
|
||||
imagesSetted = QVector<bool>(n, false);
|
||||
}
|
||||
|
||||
// ImageLoader3D implementation
|
||||
QImage ImageLoader3D::loadImage(const QString &fileName)
|
||||
{
|
||||
QImage image;
|
||||
|
||||
if (!image.load(fileName)) {
|
||||
return QImage();
|
||||
}
|
||||
|
||||
switch (flow->performance) {
|
||||
case low:
|
||||
image = image.scaledToWidth(200, Qt::SmoothTransformation);
|
||||
break;
|
||||
case medium:
|
||||
image = image.scaledToWidth(256, Qt::SmoothTransformation);
|
||||
break;
|
||||
case high:
|
||||
image = image.scaledToWidth(320, Qt::SmoothTransformation);
|
||||
break;
|
||||
case ultraHigh:
|
||||
break;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
ImageLoader3D::ImageLoader3D(YACReaderFlow3D *flow)
|
||||
: QThread(), flow(flow), restart(false), working(false), idx(-1)
|
||||
{
|
||||
}
|
||||
|
||||
ImageLoader3D::~ImageLoader3D()
|
||||
{
|
||||
mutex.lock();
|
||||
condition.wakeOne();
|
||||
mutex.unlock();
|
||||
wait();
|
||||
}
|
||||
|
||||
bool ImageLoader3D::busy() const
|
||||
{
|
||||
return isRunning() ? working : false;
|
||||
}
|
||||
|
||||
void ImageLoader3D::generate(int index, const QString &fileName)
|
||||
{
|
||||
mutex.lock();
|
||||
this->idx = index;
|
||||
this->fileName = fileName;
|
||||
this->size = size;
|
||||
this->img = QImage();
|
||||
mutex.unlock();
|
||||
|
||||
if (!isRunning())
|
||||
start();
|
||||
else {
|
||||
restart = true;
|
||||
condition.wakeOne();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageLoader3D::lock()
|
||||
{
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
void ImageLoader3D::unlock()
|
||||
{
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void ImageLoader3D::run()
|
||||
{
|
||||
for (;;) {
|
||||
mutex.lock();
|
||||
this->working = true;
|
||||
QString fileName = this->fileName;
|
||||
mutex.unlock();
|
||||
|
||||
QImage image = loadImage(fileName);
|
||||
|
||||
mutex.lock();
|
||||
this->working = false;
|
||||
this->img = image;
|
||||
mutex.unlock();
|
||||
|
||||
mutex.lock();
|
||||
if (!this->restart)
|
||||
condition.wait(&mutex);
|
||||
restart = false;
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
QImage ImageLoader3D::result()
|
||||
{
|
||||
return img;
|
||||
}
|
||||
|
||||
// ImageLoaderByteArray3D implementation
|
||||
QImage ImageLoaderByteArray3D::loadImage(const QByteArray &raw)
|
||||
{
|
||||
QImage image;
|
||||
|
||||
if (!image.loadFromData(raw)) {
|
||||
return QImage();
|
||||
}
|
||||
|
||||
switch (flow->performance) {
|
||||
case low:
|
||||
image = image.scaledToWidth(128, Qt::SmoothTransformation);
|
||||
break;
|
||||
case medium:
|
||||
image = image.scaledToWidth(196, Qt::SmoothTransformation);
|
||||
break;
|
||||
case high:
|
||||
image = image.scaledToWidth(256, Qt::SmoothTransformation);
|
||||
break;
|
||||
case ultraHigh:
|
||||
image = image.scaledToWidth(320, Qt::SmoothTransformation);
|
||||
break;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
ImageLoaderByteArray3D::ImageLoaderByteArray3D(YACReaderFlow3D *flow)
|
||||
: QThread(), flow(flow), restart(false), working(false), idx(-1)
|
||||
{
|
||||
}
|
||||
|
||||
ImageLoaderByteArray3D::~ImageLoaderByteArray3D()
|
||||
{
|
||||
mutex.lock();
|
||||
condition.wakeOne();
|
||||
mutex.unlock();
|
||||
wait();
|
||||
}
|
||||
|
||||
bool ImageLoaderByteArray3D::busy() const
|
||||
{
|
||||
return isRunning() ? working : false;
|
||||
}
|
||||
|
||||
void ImageLoaderByteArray3D::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 {
|
||||
restart = true;
|
||||
condition.wakeOne();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageLoaderByteArray3D::run()
|
||||
{
|
||||
for (;;) {
|
||||
mutex.lock();
|
||||
this->working = true;
|
||||
QByteArray raw = this->rawData;
|
||||
mutex.unlock();
|
||||
|
||||
QImage image = loadImage(raw);
|
||||
|
||||
mutex.lock();
|
||||
this->working = false;
|
||||
this->img = image;
|
||||
mutex.unlock();
|
||||
|
||||
mutex.lock();
|
||||
if (!this->restart)
|
||||
condition.wait(&mutex);
|
||||
restart = false;
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
QImage ImageLoaderByteArray3D::result()
|
||||
{
|
||||
return img;
|
||||
}
|
||||
// Implementations for derived flows and loaders live in their own files.
|
||||
|
||||
Reference in New Issue
Block a user