/* * rendering.cpp (C) 2006-2008, Aurélien Croc (AP²C) * * 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; version 2 of the License. * * 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $Id$ * */ #include "rendering.h" #include "qpdl.h" #include "page.h" #include "cache.h" #include "errlog.h" #include "colors.h" #include "request.h" #include "printer.h" #include "compress.h" #include "document.h" #ifndef DISABLE_THREADS #include #include "semaphore.h" static Document document; static Semaphore _lock; static bool _returnState=true; /* * This function is executed by each compression thread * It compress each page, page by page and store them * into the cache */ static void *_compressPage(void* data) { const Request *request = (const Request *)data; bool rotateEvenPages; Page* page; rotateEvenPages = request->duplex() == Request::ManualLongEdge; do { // Load the page { _lock.lock(); page = document.getNextRawPage(*request); _lock.unlock(); } if (!page) { setNumberOfPages(document.numberOfPages()); break; } // Make rotation on even pages for ManualLongEdge duplex mode if (rotateEvenPages && !(page->pageNr() % 2)) { page->rotate(); } // Apply some colors optimizations #ifndef DISABLE_BLACKOPTIM applyBlackOptimization(page); #endif /* DISABLE_BLACKOPTIM */ // Compress the page if (compressPage(*request, page)) { DEBUGMSG(_("Page %lu has been compressed and is ready for " "rendering"), page->pageNr()); } else { ERRORMSG(_("Error while compressing the page. Check the previous " "message. Trying to print the other pages.")); page->setEmpty(); _returnState = false; } registerPage(page); } while (page); DEBUGMSG(_("Compression thread: work done. See ya")); return NULL; } bool render(Request& request) { bool manualDuplex=false, checkLastPage=false, lastPage=false; pthread_t threads[THREADS]; Page *page; // Load the document if (!document.load(request)) { ERRORMSG(_("Error while rendering the request. Check the previous " "message")); return false; } // Load the compression threads for (unsigned int i=0; i < THREADS; i++) { if (pthread_create(&threads[i], NULL, _compressPage, (void*)&request)) { ERRORMSG(_("Cannot load compression threads. Operation aborted.")); return false; } } // Prepare the manual duplex if (request.duplex() == Request::ManualLongEdge || request.duplex() == Request::ManualShortEdge) { manualDuplex = true; setCachePolicy(EvenDecreasing); } //Load the first page /* * NOTE: To prevent printer timeout, PJL header must be sent when the first * page to render is available (which is very quickly for normal request but * can take very long time if a big document in manual duplex is printed). */ page = getNextPage(); // Prevent troubles if the last page is an odd page (in manual duplex mode) if (manualDuplex && document.numberOfPages() % 2) checkLastPage = true; // Send the PJL Header if (page) request.printer()->sendPJLHeader(request, page->compression(), page->xResolution(), page->yResolution() ); else request.printer()->sendPJLHeader(request, 0, 0, 0); // Render the whole document while (page) { if (checkLastPage && document.numberOfPages() == page->pageNr()) lastPage = true; if (!page->isEmpty()) { if (!renderPage(request, page, lastPage)) { ERRORMSG(_("Error while rendering the page. Check the previous " "message. Trying to print the other pages.")); _returnState = false; } fprintf(stderr, "PAGE: %lu %lu\n", page->pageNr(), page->copiesNr()); } delete page; page = getNextPage(); } // Send the PJL footer request.printer()->sendPJLFooter(request); // Wait for threads to be finished for (unsigned int i=0; i < THREADS; i++) { void *result; if (pthread_join(threads[i], &result)) ERRORMSG(_("An error occurred while waiting the end of a thread")); } return _returnState; } #else /* DISABLE_THREADS */ bool render(Request& request) { Document document; Page* page; // Load the document if (!document.load(request)) { ERRORMSG(_("Error while rendering the request. Check the previous " "message")); return false; } // Get first Page page = document.getNextRawPage(request); // Send the PJL Header if (page) request.printer()->sendPJLHeader(request, page->compression(), page->xResolution(), page->yResolution() ); else request.printer()->sendPJLHeader(request, 0, 0, 0); // Send each page while (page) { #ifndef DISABLE_BLACKOPTIM applyBlackOptimization(page); #endif /* DISABLE_BLACKOPTIM */ if (compressPage(request, page)) { if (!renderPage(request, page)) ERRORMSG(_("Error while rendering the page. Check the previous " "message. Trying to print the other pages.")); } else ERRORMSG(_("Error while compressing the page. Check the previous " "message. Trying to print the other pages.")); fprintf(stderr, "PAGE: %lu %lu\n", page->pageNr(), page->copiesNr()); delete page; page = document.getNextRawPage(request); } // Send the PJL footer request.printer()->sendPJLFooter(request); return true; } #endif /* DISABLE_THREADS */ /* vim: set expandtab tabstop=4 shiftwidth=4 smarttab tw=80 cin enc=utf8: */