--- a/OHP3D.cpp Wed Dec 27 01:50:38 2023 +0100
+++ b/OHP3D.cpp Wed Dec 27 10:34:12 2023 +0100
@@ -23,13 +23,21 @@
#include <functional>
#include <sstream>
#include <vector>
+#include <chrono>
+#include <unistd.h>
+
+#include <poppler/cpp/poppler-document.h>
+#include <poppler/cpp/poppler-page.h>
+#include <poppler/cpp/poppler-toc.h>
+#include <sys/stat.h>
+#include <poppler/cpp/poppler-page-renderer.h>
#include "x11.h"
#include "opengl.h"
#include "EPoll.h"
#include "Logger.h"
#include "MappedFile.h"
-#include "ImageLoader.h"
+#include "PageBuffer.h"
#include "Texture.h"
#include "Shader.h"
#include "Program.h"
@@ -166,7 +174,6 @@
FileMonitor fileMonitor;
std::vector<WatchedFile> watchedFiles;
- ImageLoader imageLoader;
std::vector<std::shared_ptr<Shader>> shaders;
std::shared_ptr<Program> shaderProgram;
std::vector<std::shared_ptr<Texture>> textures;
@@ -184,9 +191,7 @@
void log(LogLevel level, std::string message);
int setNonBlocking(int fd);
void loadVertices();
- void parametrizeTexture(std::shared_ptr<Texture> tex);
- bool reloadTexture(const std::string& fileName);
- void loadTextures();
+ void loadDocuments();
void loadShaders();
void updateVariableLocations();
bool reloadShader(const std::string& fileName);
@@ -271,9 +276,8 @@
glXSwapBuffers(dpy, win);
- // Load GLSL shaders:
loadShaders();
- loadTextures();
+ loadDocuments();
loadVertices();
auto toggleFullscreen = [&]() {
@@ -409,7 +413,6 @@
<< " mask=" << fe.mask
<< std::endl;
try {
- redraw |= reloadTexture(fe.fileName);
redraw |= reloadShader(fe.fileName);
setTitle();
} catch (const std::exception& e) {
@@ -548,66 +551,57 @@
}
}
-void OHP3D::Impl::parametrizeTexture(std::shared_ptr<Texture> tex) {
- XAttrs xa(tex->getFileName());
- std::string magf = xa["ohp3d.texture.mag-filter"];
- std::string minf = xa["ohp3d.texture.min-filter"];
- std::string scale = xa["ohp3d.texture.scale"];
+void OHP3D::Impl::loadDocuments() {
+ for (const Configuration::File& document : cfg.documents) {
+ std::cerr << "loading document: " << document.fileName.c_str() << "\n";
+
+ MappedFile buffer(document.fileName);
- auto GLT2D = GL_TEXTURE_2D;
- auto MAG = GL_TEXTURE_MAG_FILTER;
- auto MIN = GL_TEXTURE_MIN_FILTER;
+ namespace pp = poppler;
+ using Document = pp::document;
+
+ std::shared_ptr<Document> doc = std::shared_ptr<Document>(
+ Document::load_from_raw_data(buffer.getData(), buffer.getSize()));
- if (magf == "linear") glTexParameteri(GLT2D, MAG, GL_LINEAR);
- else if (magf == "nearest") glTexParameteri(GLT2D, MAG, GL_NEAREST);
-
- if (minf == "linear") glTexParameteri(GLT2D, MIN, GL_LINEAR);
- else if (minf == "nearest") glTexParameteri(GLT2D, MIN, GL_NEAREST);
+ log(LogLevel::INFO, std::string("PDF parsed:")
+ + " pages=" + std::to_string(doc->pages()));
- if (scale.size()) {
- float sc;
- if (std::from_chars(scale.data(), scale.data() + scale.size(), sc).ec
- == std::errc{}) tex->setScale(sc);
- else std::cerr << "Invalid texture scale value - expecting float\n";
- // tex->setScale(std::stof(scale)); // locale-dependent (. vs ,)
- }
-}
+ log(LogLevel::INFO, "loadig pages to textures...");
+ auto timingStart = std::chrono::steady_clock::now();
+ pp::page_renderer renderer;
+ renderer.set_image_format(pp::image::format_rgb24);
+ double dpi = cfg.dpi;
+ for (int i = 0, limit = doc->pages(); i < limit; i++) {
+ std::shared_ptr<pp::page> page(doc->create_page(i));
+ pp::image pageImage = renderer.render_page(page.get(), dpi, dpi);
-void OHP3D::Impl::loadTextures() {
- // Load default texture if there is no configured:
- if (cfg.textures.empty())
- cfg.textures.push_back({getDefaultFile("textures/default.png")});
+ PageBuffer img(
+ pageImage.data(),
+ pageImage.bytes_per_row() * pageImage.height(),
+ pageImage.width(), pageImage.height());
+
+ textures.push_back(std::make_shared<Texture>(
+ pageImage.width(), pageImage.height(),
+ img, document.fileName));
+ log(LogLevel::INFO, " page " + std::to_string(i + 1)
+ + "/" + std::to_string(limit));
+ }
- for (const Configuration::Texture& tex : cfg.textures) {
- std::shared_ptr<ImageLoader::ImageBuffer>
- img(imageLoader.loadImage(MappedFile(tex.fileName)));
- textures.push_back(std::make_shared<Texture>(
- img->width, img->height, *img, tex.fileName));
- parametrizeTexture(textures.back());
- // static const uint32_t watchMask = IN_CLOSE_WRITE | IN_ATTRIB;
- // watchedFiles.push_back(fileMonitor.watch(tex.fileName, watchMask));
- watchedFiles.push_back(fileMonitor.watch(tex.fileName));
- // TODO: review texture loading and binding
- // works even without this - default texture
- // glUniform1i(..., ...);
- // checkError(&std::cerr);
+ auto timingEnd = std::chrono::steady_clock::now();
+ auto timingTotal = std::chrono::duration_cast<std::chrono::microseconds>
+ (timingEnd - timingStart).count();
+
+ std::stringstream timingMsg;
+ timingMsg.imbue(std::locale(""));
+ timingMsg << "PDF to texture load time:"
+ << " page average = " << (timingTotal / doc->pages()) << " µs,"
+ << " total = " << timingTotal << " µs ("
+ << doc->pages() << " pages)";
+ log(LogLevel::INFO, timingMsg.str());
+ if (timingTotal < 400000) logOutput << ">>> Doherty threshold met! <<<\n";
}
}
-bool OHP3D::Impl::reloadTexture(const std::string& fileName) {
- for (std::shared_ptr<Texture> tex : textures) {
- if (tex->getFileName() == fileName) {
- std::shared_ptr<ImageLoader::ImageBuffer>
- img(imageLoader.loadImage(MappedFile(fileName)));
- tex->update(img->width, img->height, *img);
- parametrizeTexture(tex);
- loadVertices();
- return true;
- }
- }
- return false;
-}
-
void OHP3D::Impl::loadShaders() {
// Vertex Array Object (VAO)
GLuint vao;