You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

192 lines
4.4 KiB

#include "RenderJob.h"
#include "control/Control.h"
#include "control/ToolHandler.h"
#include "gui/PageView.h"
#include "gui/XournalView.h"
#include "model/Document.h"
#include "view/DocumentView.h"
#include "view/PdfView.h"
#include <Rectangle.h>
#include <Util.h>
#include <list>
RenderJob::RenderJob(XojPageView* view)
{
XOJ_INIT_TYPE(RenderJob);
this->view = view;
}
RenderJob::~RenderJob()
{
XOJ_CHECK_TYPE(RenderJob);
this->view = NULL;
XOJ_RELEASE_TYPE(RenderJob);
}
void* RenderJob::getSource()
{
XOJ_CHECK_TYPE(RenderJob);
return this->view;
}
void RenderJob::rerenderRectangle(Rectangle* rect)
{
XOJ_CHECK_TYPE(RenderJob);
double zoom = view->xournal->getZoom();
Document* doc = view->xournal->getDocument();
doc->lock();
double pageWidth = view->page->getWidth();
double pageHeight = view->page->getHeight();
doc->unlock();
int x = rect->x * zoom;
int y = rect->y * zoom;
int width = rect->width * zoom;
int height = rect->height * zoom;
cairo_surface_t* rectBuffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
cairo_t* crRect = cairo_create(rectBuffer);
cairo_translate(crRect, -x, -y);
cairo_scale(crRect, zoom, zoom);
DocumentView v;
Control* control = view->getXournal()->getControl();
v.setMarkAudioStroke(control->getToolHandler()->getToolType() == TOOL_PLAY_OBJECT);
v.limitArea(rect->x, rect->y, rect->width, rect->height);
if (view->page->getBackgroundType().isPdfPage())
{
int pgNo = view->page->getPdfPageNr();
XojPdfPageSPtr popplerPage = doc->getPdfPage(pgNo);
PdfCache* cache = view->xournal->getCache();
PdfView::drawPage(cache, popplerPage, crRect, zoom, pageWidth, pageHeight);
}
doc->lock();
v.drawPage(view->page, crRect, false);
doc->unlock();
cairo_destroy(crRect);
g_mutex_lock(&view->drawingMutex);
cairo_t * crPageBuffer = cairo_create(view->crBuffer);
cairo_set_operator(crPageBuffer, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface(crPageBuffer, rectBuffer, x, y);
cairo_rectangle(crPageBuffer, x, y, width, height);
cairo_fill(crPageBuffer);
cairo_destroy(crPageBuffer);
cairo_surface_destroy(rectBuffer);
g_mutex_unlock(&view->drawingMutex);
}
void RenderJob::run()
{
XOJ_CHECK_TYPE(RenderJob);
double zoom = this->view->xournal->getZoom();
g_mutex_lock(&this->view->repaintRectMutex);
bool rerenderComplete = this->view->rerenderComplete;
std::vector<Rectangle*> rerenderRects = this->view->rerenderRects;
this->view->rerenderRects.clear();
this->view->rerenderComplete = false;
g_mutex_unlock(&this->view->repaintRectMutex);
if (rerenderComplete)
{
Document* doc = this->view->xournal->getDocument();
int dispWidth = this->view->getDisplayWidth();
int dispHeight = this->view->getDisplayHeight();
cairo_surface_t* crBuffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dispWidth, dispHeight);
cairo_t* cr2 = cairo_create(crBuffer);
cairo_scale(cr2, zoom, zoom);
XojPdfPageSPtr popplerPage;
doc->lock();
if (this->view->page->getBackgroundType().isPdfPage())
{
int pgNo = this->view->page->getPdfPageNr();
popplerPage = doc->getPdfPage(pgNo);
}
Control* control = view->getXournal()->getControl();
DocumentView view;
view.setMarkAudioStroke(control->getToolHandler()->getToolType() == TOOL_PLAY_OBJECT);
int width = this->view->page->getWidth();
int height = this->view->page->getHeight();
PdfView::drawPage(this->view->xournal->getCache(), popplerPage, cr2, zoom, width, height);
view.drawPage(this->view->page, cr2, false);
cairo_destroy(cr2);
g_mutex_lock(&this->view->drawingMutex);
if (this->view->crBuffer)
{
cairo_surface_destroy(this->view->crBuffer);
}
this->view->crBuffer = crBuffer;
g_mutex_unlock(&this->view->drawingMutex);
doc->unlock();
}
else
{
for (Rectangle* rect : rerenderRects)
{
rerenderRectangle(rect);
}
}
// Schedule a repaint of the widget
repaintWidget(this->view->getXournal()->getWidget());
// delete all rectangles
for (Rectangle* rect : rerenderRects)
{
delete rect;
}
rerenderRects.clear();
}
/**
* Repaint the widget in UI Thread
*/
void RenderJob::repaintWidget(GtkWidget* widget)
{
// "this" is not needed, "widget" is in
// the closure, therefore no sync needed
// Because of this the argument "widget" is needed
Util::execInUiThread([=]() {
gtk_widget_queue_draw(widget);
});
}
JobType RenderJob::getType()
{
XOJ_CHECK_TYPE(RenderJob);
return JOB_TYPE_RENDER;
}