546 + " in order to use defaults" |
549 + " in order to use defaults" |
547 " or specify textures and shaders as parameters"); |
550 " or specify textures and shaders as parameters"); |
548 } |
551 } |
549 } |
552 } |
550 |
553 |
551 void OHP3D::Impl::parametrizeTexture(std::shared_ptr<Texture> tex) { |
554 void OHP3D::Impl::loadDocuments() { |
552 XAttrs xa(tex->getFileName()); |
555 for (const Configuration::File& document : cfg.documents) { |
553 std::string magf = xa["ohp3d.texture.mag-filter"]; |
556 std::cerr << "loading document: " << document.fileName.c_str() << "\n"; |
554 std::string minf = xa["ohp3d.texture.min-filter"]; |
557 |
555 std::string scale = xa["ohp3d.texture.scale"]; |
558 MappedFile buffer(document.fileName); |
556 |
559 |
557 auto GLT2D = GL_TEXTURE_2D; |
560 namespace pp = poppler; |
558 auto MAG = GL_TEXTURE_MAG_FILTER; |
561 using Document = pp::document; |
559 auto MIN = GL_TEXTURE_MIN_FILTER; |
562 |
560 |
563 std::shared_ptr<Document> doc = std::shared_ptr<Document>( |
561 if (magf == "linear") glTexParameteri(GLT2D, MAG, GL_LINEAR); |
564 Document::load_from_raw_data(buffer.getData(), buffer.getSize())); |
562 else if (magf == "nearest") glTexParameteri(GLT2D, MAG, GL_NEAREST); |
565 |
563 |
566 log(LogLevel::INFO, std::string("PDF parsed:") |
564 if (minf == "linear") glTexParameteri(GLT2D, MIN, GL_LINEAR); |
567 + " pages=" + std::to_string(doc->pages())); |
565 else if (minf == "nearest") glTexParameteri(GLT2D, MIN, GL_NEAREST); |
568 |
566 |
569 log(LogLevel::INFO, "loadig pages to textures..."); |
567 if (scale.size()) { |
570 auto timingStart = std::chrono::steady_clock::now(); |
568 float sc; |
571 pp::page_renderer renderer; |
569 if (std::from_chars(scale.data(), scale.data() + scale.size(), sc).ec |
572 renderer.set_image_format(pp::image::format_rgb24); |
570 == std::errc{}) tex->setScale(sc); |
573 double dpi = cfg.dpi; |
571 else std::cerr << "Invalid texture scale value - expecting float\n"; |
574 for (int i = 0, limit = doc->pages(); i < limit; i++) { |
572 // tex->setScale(std::stof(scale)); // locale-dependent (. vs ,) |
575 std::shared_ptr<pp::page> page(doc->create_page(i)); |
573 } |
576 pp::image pageImage = renderer.render_page(page.get(), dpi, dpi); |
574 } |
577 |
575 |
578 PageBuffer img( |
576 void OHP3D::Impl::loadTextures() { |
579 pageImage.data(), |
577 // Load default texture if there is no configured: |
580 pageImage.bytes_per_row() * pageImage.height(), |
578 if (cfg.textures.empty()) |
581 pageImage.width(), pageImage.height()); |
579 cfg.textures.push_back({getDefaultFile("textures/default.png")}); |
582 |
580 |
583 textures.push_back(std::make_shared<Texture>( |
581 for (const Configuration::Texture& tex : cfg.textures) { |
584 pageImage.width(), pageImage.height(), |
582 std::shared_ptr<ImageLoader::ImageBuffer> |
585 img, document.fileName)); |
583 img(imageLoader.loadImage(MappedFile(tex.fileName))); |
586 log(LogLevel::INFO, " page " + std::to_string(i + 1) |
584 textures.push_back(std::make_shared<Texture>( |
587 + "/" + std::to_string(limit)); |
585 img->width, img->height, *img, tex.fileName)); |
588 } |
586 parametrizeTexture(textures.back()); |
589 |
587 // static const uint32_t watchMask = IN_CLOSE_WRITE | IN_ATTRIB; |
590 auto timingEnd = std::chrono::steady_clock::now(); |
588 // watchedFiles.push_back(fileMonitor.watch(tex.fileName, watchMask)); |
591 auto timingTotal = std::chrono::duration_cast<std::chrono::microseconds> |
589 watchedFiles.push_back(fileMonitor.watch(tex.fileName)); |
592 (timingEnd - timingStart).count(); |
590 // TODO: review texture loading and binding |
593 |
591 // works even without this - default texture |
594 std::stringstream timingMsg; |
592 // glUniform1i(..., ...); |
595 timingMsg.imbue(std::locale("")); |
593 // checkError(&std::cerr); |
596 timingMsg << "PDF to texture load time:" |
594 } |
597 << " page average = " << (timingTotal / doc->pages()) << " µs," |
595 } |
598 << " total = " << timingTotal << " µs (" |
596 |
599 << doc->pages() << " pages)"; |
597 bool OHP3D::Impl::reloadTexture(const std::string& fileName) { |
600 log(LogLevel::INFO, timingMsg.str()); |
598 for (std::shared_ptr<Texture> tex : textures) { |
601 if (timingTotal < 400000) logOutput << ">>> Doherty threshold met! <<<\n"; |
599 if (tex->getFileName() == fileName) { |
602 } |
600 std::shared_ptr<ImageLoader::ImageBuffer> |
|
601 img(imageLoader.loadImage(MappedFile(fileName))); |
|
602 tex->update(img->width, img->height, *img); |
|
603 parametrizeTexture(tex); |
|
604 loadVertices(); |
|
605 return true; |
|
606 } |
|
607 } |
|
608 return false; |
|
609 } |
603 } |
610 |
604 |
611 void OHP3D::Impl::loadShaders() { |
605 void OHP3D::Impl::loadShaders() { |
612 // Vertex Array Object (VAO) |
606 // Vertex Array Object (VAO) |
613 GLuint vao; |
607 GLuint vao; |