pdf_render_task.cpp

Go to the documentation of this file.
00001 /*
00002  * File Name: pdf_render_task.cpp
00003  */
00004 
00005 /*
00006  * This file is part of uds-plugin-pdf.
00007  *
00008  * uds-plugin-pdf is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * uds-plugin-pdf is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 #include  "log.h"
00028 
00029 #include "pdf_render_task.h"
00030 #include "pdf_library.h"
00031 
00032 namespace pdf
00033 {
00034 
00035 PDFRenderTask::PDFRenderTask(int page_num, const PDFRenderAttributes &attr
00036                              , PDFController *ctrl, PluginRenderResultImpl *render_res
00037                              , int id)
00038 : page(0)
00039 , page_number(page_num)
00040 , page_render_attr(attr)
00041 , doc_ctrl(ctrl)
00042 , ref_id(id)
00043 , render_result(render_res)
00044 {
00045     type = TASK_RENDER;
00046 }
00047 
00048 PDFRenderTask::PDFRenderTask(PagePtr p, const PDFRenderAttributes &attr
00049                              , PDFController *ctrl, PluginRenderResultImpl *render_res
00050                              , int id)
00051 : page(p)
00052 , page_number(page->get_page_num())
00053 , page_render_attr(attr)
00054 , doc_ctrl(ctrl)
00055 , ref_id(id)
00056 , render_result(render_res)
00057 {
00058     type = TASK_RENDER;
00059 }
00060 
00061 PDFRenderTask::~PDFRenderTask()
00062 {
00063 }
00064 
00065 void PDFRenderTask::execute()
00066 {
00067     // don't execute the prerender task if the page is out of date
00068     if (is_page_out_of_date())
00069     {
00070         return;
00071     }
00072 
00073     PDFRenderer *renderer = doc_ctrl->get_renderer();
00074 
00075     // estimate whether the page has been cached
00076     // it is necessary here although there is same estimation
00077     // in main thread, because the same page might be constructed
00078     // in other tasks.
00079     if (page == 0)
00080     {
00081         page = doc_ctrl->get_page(page_number);
00082 
00083         if (page == 0)
00084         {   
00085             page = renderer->gen_page(page_number, page_render_attr);
00086         }
00087     }
00088 
00089     //assert(page);
00090     if (page == 0)
00091     {
00092         ERRORPRINTF("Cannot Create New Page");
00093         return;
00094     }
00095 
00096     // set the reference id, this operation is thread-safe now
00097     // NOTE: this function must be called before setting render attributes
00098     // because the main thread would update the ref id if the render attributes
00099     // changes.
00100     page->set_ref_id(ref_id);
00101 
00102     // if it is ZOOM_AUTO_CROP mode, it means it is necessary to get the content
00103     // area of the page
00104     double real_zoom = page_render_attr.get_real_zoom_value();
00105     if (real_zoom == PLUGIN_ZOOM_TO_CROP_BY_PAGE ||
00106         real_zoom == PLUGIN_ZOOM_TO_CROP_BY_WIDTH)
00107     {
00108         RenderArea content_area;
00109         if (!page->get_content_area(renderer, content_area))
00110         {
00111             ERRORPRINTF("Cannot get content area of page:%d", page_number);
00112             return;
00113         }
00114         PDFRenderAttributes origin_attr = page_render_attr;
00115         renderer->calc_real_zoom(page_number, origin_attr, page_render_attr);
00116         real_zoom = page_render_attr.get_real_zoom_value();
00117     }
00118 
00119     // if the page is cached and the bitmap has been rendered
00120     // calculate the delta value. Becuase the old bitmap would
00121     // be destroyed and new one is going to be rendered in the following
00122     // step
00123     int page_len = static_cast<int>(page->length());
00124 
00125     page_len = static_cast<int>(PDFPage::try_calc_length(real_zoom,
00126                                 doc_ctrl->get_page_crop_width(page_number),
00127                                 doc_ctrl->get_page_crop_height(page_number))) -
00128                page_len;
00129 
00130     PDFPage::RenderStatus cur_status = page->get_render_status();
00131     if (!(page->get_render_attr() == page_render_attr))
00132     {
00133         // if the render attributes change, re-render the page
00134         // DO NOT update the render setting here, because it might
00135         // change the length of page
00136         // DO NOT change the status of page at this moment
00137         cur_status = PDFPage::RENDER_STOP;
00138     }
00139     
00140     bool render_done = true;
00141 
00142     // render bitmap
00143     if (cur_status != PDFPage::RENDER_DONE)
00144     {
00145         LOGPRINTF("Task, Render Page:%d, Ref ID:%d, Current Task:%p", page_number, ref_id, this);
00146         // update the page cache to make sure there is enough memory
00147         // if page_len < 0, it means the page is going to shrink, the memory
00148         // must be enough
00149         // TODO. Add the page number as one parameter for making enough memory
00150         // The pages with lower priorites would be released.
00151         if (page_len > 0 &&
00152             !PDFLibrary::instance().make_enough_memory(doc_ctrl,
00153                                                        page_number,
00154                                                        page_len))
00155         {
00156             WARNPRINTF("Cannot make enough memory to implement rendering");
00157 
00158             // notify uds that it is out of memory that the page rendering
00159             // is aborted
00160             renderer->handle_page_ready(render_result, page, TASK_RENDER_OOM);
00161             return;
00162         }
00163 
00164         // update the render status
00165         page->set_render_status(cur_status);
00166 
00167         // only set the render attributes
00168         page->set_render_attr(page_render_attr);
00169 
00170         render_done = page->render_splash_map(renderer
00171             , static_cast<void*>(this));
00172 
00173         // render the text page when the render is done
00174         if (render_done)
00175         {
00176             page->render_text(renderer);
00177         }
00178     }
00179 
00180     if (render_done)
00181     {
00182         // set the render status at last
00183         page->set_render_status(PDFPage::RENDER_DONE);
00184 
00185         if (render_result != 0)
00186         {
00187             // set the page into render result
00188             render_result->set_page(page);
00189         }
00190 
00191         // notify uds that the page is ready
00192         renderer->handle_page_ready(render_result, page, TASK_RENDER_DONE);
00193     }
00194     else
00195     {
00196         if (render_result != 0 && is_aborted())
00197         {
00198             // if the task is aborted, set the render result to "Discard"
00199             render_result->set_discard(true);
00200         }
00201         else
00202         {
00203             renderer->handle_page_ready(render_result, page, TASK_RENDER_OOM);
00204         }
00205     }
00206 
00207 }
00208 
00209 bool PDFRenderTask::is_page_out_of_date()
00210 {
00211     // check whether the page is in request list
00212     bool out_of_date = !(doc_ctrl->get_prerender_policy()->get_requests().contains(
00213                          page_number));
00214 
00215     if (out_of_date)
00216     {
00217         return out_of_date;
00218     }
00219 
00220     PDFRenderer *renderer = doc_ctrl->get_renderer();
00221     // check the render setting
00222     if (page_render_attr.get_zoom_setting() !=
00223         renderer->get_render_attr().get_zoom_setting() ||
00224         page_render_attr.get_rotate() !=
00225         renderer->get_render_attr().get_rotate())
00226     {
00227         out_of_date = true;
00228     }
00229 
00230     return out_of_date;
00231 }
00232 
00233 void* PDFRenderTask::get_user_data()
00234 {
00235     return doc_ctrl;
00236 }
00237 
00238 unsigned int PDFRenderTask::get_id()
00239 {
00240     return ref_id;
00241 }
00242 
00243 }// namespace pdf
00244 
Generated by  doxygen 1.6.2-20100208