pdf/plugin_impl/view_impl.cpp

Go to the documentation of this file.
00001 /*
00002  * File Name: view_impl.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 <cassert>
00028 #include "view_impl.h"
00029 #include "document_impl.h"
00030 
00031 #include "pdf_library.h"
00032 
00033 namespace pdf
00034 {
00035 
00036 utils::ObjectTable<PluginViewImpl> PluginViewImpl::g_instances_table;
00037 
00038 PluginViewImpl::PluginViewImpl(PluginDocImpl *doc)
00039 : document(doc)
00040 , render_settings()
00041 , render_results()
00042 , listeners()
00043 , renderer(doc->get_renderer())
00044 {
00045     assert(document);
00046 
00047     // IPluginUnknown
00048     query_interface = query_interface_impl;
00049     release         = release_impl;
00050 
00051     // IPluginView
00052     get_page_number         = get_page_number_impl;
00053     get_page_name           = get_page_name_impl;
00054     get_rendered_page_start = get_rendered_page_start_impl;
00055     get_physical_page_start = get_physical_page_start_impl;
00056     get_number_of_pages     = get_number_of_pages_impl;
00057     get_anchor_by_page      = get_anchor_by_page_impl;
00058     get_prev_page           = get_prev_page_impl;
00059     get_next_page           = get_next_page_impl;
00060     get_cover_page          = get_cover_page_impl;
00061 
00062     // IPluginViewSettings
00063     set_display_size    = set_display_size_impl;
00064     set_DPI             = set_DPI_impl;
00065     set_color_depth     = set_color_depth_impl;
00066 
00067     // IPluginRender
00068     render                  = render_impl;
00069     create_render_settings  = create_render_settings_impl;
00070     set_memory_limit        = set_memory_limit_impl;
00071     get_original_size       = get_original_size_impl;
00072     get_page_content_area   = get_page_content_area_impl;
00073     get_original_rotation   = get_original_rotation_impl;
00074 
00075     // IPluginFont
00076     get_font_size   = get_font_size_impl;
00077     set_font_size   = set_font_size_impl;
00078     get_font_family = get_font_family_impl;
00079     set_font_family = set_font_family_impl;
00080 
00081     // IPluginEventBroadcaster
00082     add_event_receiver      = add_event_receiver_impl;
00083     remove_event_receiver   = remove_event_receiver_impl;
00084 
00085     g_instances_table.add_interface<IPluginUnknown>(this);
00086     g_instances_table.add_interface<IPluginView>(this);
00087     g_instances_table.add_interface<IPluginViewSettings>(this);
00088     g_instances_table.add_interface<IPluginRender>(this);
00089     g_instances_table.add_interface<IPluginEventBroadcaster>(this);
00090 
00091     // add the slots of handling render results onto the document
00092     document->doc_ctrl.sig_page_ready.add_slot(this
00093         , &PluginViewImpl::handle_page_ready);
00094 
00095 }
00096 
00097 PluginViewImpl::~PluginViewImpl(void)
00098 {
00099     document->doc_ctrl.sig_page_ready.remove_slot(this
00100         , &PluginViewImpl::handle_page_ready);
00101 
00102     g_instances_table.remove(this);
00103 }
00104 
00105 PluginStatus 
00106 PluginViewImpl::query_interface_impl(IPluginUnknown    *thiz,
00107                                      const UDSString   *id, 
00108                                      void              **ptr )
00109 {
00110     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00111     if (g_instances_table.query_interface(instance, id->get_buffer(id), ptr))
00112     {
00113         return PLUGIN_OK;
00114     }
00115     return PLUGIN_FAIL;
00116 }
00117 
00118 int 
00119 PluginViewImpl::release_impl(IPluginUnknown  *thiz )
00120 {
00121     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00122     instance->release_signal.safe_broadcast(instance);
00123     return 0;
00124 }
00125 
00126 int 
00127 PluginViewImpl::get_page_number_impl(IPluginUnknown  *thiz,
00128                                      const UDSString *anchor )
00129 {
00130     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00131     return instance->document->get_page_number(anchor->get_buffer(anchor));
00132 }
00133 
00134 int 
00135 PluginViewImpl::get_number_of_pages_impl(IPluginUnknown *thiz)
00136 {
00137     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00138     return instance->document->get_page_count();
00139 }
00140 
00141 PluginStatus 
00142 PluginViewImpl::get_anchor_by_page_impl(IPluginUnknown *thiz,
00143                                         unsigned int page,
00144                                         UDSString *anchor)
00145 {
00146     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00147 
00148     // Use first page as the initial anchor.
00149     std::string temp;
00150     if (instance->document->get_anchor_of_page(page, temp))
00151     {
00152         anchor->assign(anchor, temp.c_str());
00153         return PLUGIN_OK;
00154     }
00155     return PLUGIN_FAIL;
00156 }
00157 
00158 PluginStatus 
00159 PluginViewImpl::get_prev_page_impl(IPluginUnknown *thiz,
00160                                    UDSString      *anchor)
00161 {
00162     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00163 
00164     std::string temp(anchor->get_buffer(anchor));
00165     if (instance->document->get_prev_page(temp))
00166     {
00167         anchor->assign(anchor, temp.c_str());
00168         return PLUGIN_OK;
00169     }
00170     return PLUGIN_FAIL;
00171 }
00172 
00173 PluginStatus 
00174 PluginViewImpl::get_next_page_impl(IPluginUnknown *thiz,
00175                                    UDSString      *anchor)
00176 {
00177     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00178 
00179     std::string temp(anchor->get_buffer(anchor));
00180     if (instance->document->get_next_page(temp))
00181     {
00182         anchor->assign(anchor, temp.c_str());
00183         return PLUGIN_OK;
00184     }
00185     return PLUGIN_FAIL;
00186 }
00187 
00188 PluginStatus
00189 PluginViewImpl::get_cover_page_impl(IPluginUnknown *thiz,
00190                                     const int      width,
00191                                     const int      height,
00192                                     PluginBitmapAttributes *cover_page)
00193 {
00194     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00195 
00196     if (instance->renderer->render_cover_page(width, height, cover_page))
00197     {
00198         return PLUGIN_OK;
00199     }
00200     return PLUGIN_FAIL;
00201 }
00202 
00203 PluginStatus 
00204 PluginViewImpl::set_display_size_impl(IPluginUnknown *thiz,
00205                                       const int       width,
00206                                       const int       height )
00207 {
00208     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00209 
00210     instance->renderer->get_view_attr().set_display_width(width);
00211     instance->renderer->get_view_attr().set_display_height(height);
00212 
00213     return PLUGIN_OK;
00214 }
00215 
00216 PluginStatus 
00217 PluginViewImpl::set_DPI_impl(IPluginUnknown        *thiz,
00218                              const unsigned int    dpi )
00219 {
00220     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00221 
00222     instance->renderer->get_view_attr().set_device_dpi_v(dpi);
00223     instance->renderer->get_view_attr().set_device_dpi_h(dpi);
00224 
00225     return PLUGIN_OK;
00226 }
00227 
00228 PluginStatus 
00229 PluginViewImpl::set_color_depth_impl(IPluginUnknown *thiz,
00230                                      const unsigned int color_depth )
00231 {
00232     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00233 
00234     instance->renderer->get_view_attr().set_color_depth(color_depth);
00235 
00236     return PLUGIN_OK;
00237 }
00238 
00239 PluginStatus 
00240 PluginViewImpl::render_impl(IPluginUnknown      *thiz,
00241                             const UDSString     *start_of_page_anchor,
00242                             const int           page_offset,
00243                             IPluginUnknown      *settings,
00244                             const RenderArea    *area, 
00245                             const unsigned int  refId )
00246 {
00247     // Must get proper page anchor, so no page offset allowed
00248     if (page_offset != 0)
00249     {
00250         return PLUGIN_NOT_SUPPORTED;
00251     }
00252 
00253     // support multi-thread
00254     // send render request
00255     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00256     
00257     unsigned int page_num = instance->document->get_page_number(
00258         start_of_page_anchor->get_buffer(start_of_page_anchor));
00259 
00260     // construct the render setting attributes
00261     PluginRenderSettingsImpl * settings_obj = 
00262         PluginRenderSettingsImpl::query_instance(settings);
00263     
00264     // send render request
00265     instance->send_render_request(page_num, settings_obj->get_render_attr()
00266         , area, refId);
00267                               
00268     return PLUGIN_OK;
00269 }
00270 
00271 IPluginUnknown * 
00272 PluginViewImpl::create_render_settings_impl(IPluginUnknown  *thiz)
00273 {
00274     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00275     RenderSettingsPtr ptr = new PluginRenderSettingsImpl;
00276     if (ptr == 0)
00277     {
00278         return 0;
00279     }
00280 
00281     instance->render_settings.push_back(ptr);
00282     ptr->release_signal.add_slot(instance, 
00283         &PluginViewImpl::on_render_settings_released);
00284     return static_cast<IPluginUnknown *>(ptr);
00285 }
00286 
00287 PluginStatus 
00288 PluginViewImpl::set_memory_limit_impl(IPluginUnknown       *thiz,
00289                                       const unsigned int   bytes)
00290 {
00291     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00292     if (instance->document->get_doc_ctrl().set_memory_limit(bytes))
00293     {
00294         return PLUGIN_OK;
00295     }
00296     return PLUGIN_FAIL;
00297 }
00298 
00299 PluginStatus 
00300 PluginViewImpl::get_original_size_impl(IPluginUnknown       *thiz,
00301                                        const UDSString      *start_of_page_anchor,
00302                                        unsigned int         *width,
00303                                        unsigned int         *height )
00304 {
00305     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00306     if (instance->document->get_original_size(start_of_page_anchor->get_buffer(start_of_page_anchor),
00307                                               *width,
00308                                               *height))
00309     {
00310         return PLUGIN_OK;
00311     }
00312     return PLUGIN_FAIL;
00313 }
00314 
00315 PluginStatus
00316 PluginViewImpl::get_page_content_area_impl(IPluginUnknown       *thiz,
00317                                            const UDSString      *start_of_page_anchor,
00318                                            RenderArea           *area )
00319 {
00320     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00321     if (instance->document->get_content_area(
00322         start_of_page_anchor->get_buffer(start_of_page_anchor),
00323         *area))
00324     {
00325         return PLUGIN_OK;
00326     }
00327     return PLUGIN_FAIL;
00328 }
00329 
00330 PluginStatus 
00331 PluginViewImpl::add_event_receiver_impl(IPluginUnknown     *thiz,
00332                                         const PluginEvent  plugin_event,
00333                                         EventFunc          callback,
00334                                         void               *user_data,
00335                                         unsigned long      *handler_id )
00336 {
00337     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00338     if (handler_id == 0)
00339     {
00340         return PLUGIN_FAIL;
00341     }
00342 
00343     *handler_id = 
00344         instance->listeners.add_listener(plugin_event, callback, user_data);
00345     return PLUGIN_OK;
00346 }
00347 
00348 PluginStatus 
00349 PluginViewImpl::remove_event_receiver_impl(IPluginUnknown  *thiz,
00350                                            unsigned long   handler_id)
00351 {
00352     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00353     if (instance->listeners.remove_listener(handler_id))
00354     {
00355         return PLUGIN_OK;
00356     }
00357     return PLUGIN_FAIL;
00358 }
00359 
00360 PluginStatus
00361 PluginViewImpl::get_original_rotation_impl(IPluginUnknown  *thiz,
00362                                            const UDSString *start_of_page_anchor,
00363                                            PluginRotationDegree *rotation)
00364 {
00365     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00366 
00367     PluginRotationDegree res = instance->document->get_page_original_rotation(
00368         start_of_page_anchor->get_buffer(start_of_page_anchor) );
00369 
00370     if (res < 0)
00371     {
00372         return PLUGIN_FAIL;
00373     }
00374 
00375     *rotation = res;
00376     return PLUGIN_OK;
00377 }
00378 
00379 PluginStatus
00380 PluginViewImpl::get_page_name_impl(IPluginUnknown        *thiz, 
00381                                    const UDSString       *page_start_anchor,
00382                                    UDSString             *name)
00383 {
00384     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00385 
00386     unsigned int page_num = instance->document->get_page_number(
00387         page_start_anchor->get_buffer(page_start_anchor));
00388 
00389     char buf[32] = {0};
00390     pdf_printf(buf, "%d", page_num);
00391 
00392     name->assign(name, buf);
00393 
00394     return PLUGIN_OK;
00395 }
00396 
00397 PluginStatus
00398 PluginViewImpl::get_rendered_page_start_impl(IPluginUnknown    *thiz, 
00399                                           const UDSString      *anchor,
00400                                           UDSString            *start_anchor )
00401 {
00402     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00403 
00404     unsigned int page_num = instance->document->get_page_number(
00405         anchor->get_buffer(anchor));
00406 
00407     PDFAnchor param;
00408     param.page_num = page_num;
00409     //param.file_name = instance->document->get_file_name();
00410     start_anchor->assign(start_anchor, param.get_string().c_str());
00411 
00412     return PLUGIN_OK;
00413 }
00414 
00415 
00416 PluginStatus
00417 PluginViewImpl::get_physical_page_start_impl(IPluginUnknown  *thiz,
00418                                              const UDSString *anchor,
00419                                              UDSString       *start_anchor)
00420 {
00421     return get_rendered_page_start_impl(thiz, anchor, start_anchor);
00422 }
00423 
00424 
00425 void 
00426 PluginViewImpl::on_render_settings_released(PluginRenderSettingsImpl *settings)
00427 {
00428     RenderSettingsIter iter = std::find(render_settings.begin(),
00429                                         render_settings.end(),
00430                                         settings);
00431     if (iter != render_settings.end())
00432     {
00433         delete *iter;
00434         render_settings.erase(iter);
00435     }
00436 }
00437 
00438 void 
00439 PluginViewImpl::on_render_result_released(PluginRenderResultImpl * result)
00440 {
00441     RenderResultIter iter = std::find(render_results.begin(),
00442                                       render_results.end(),
00443                                       result);
00444     if (iter != render_results.end())
00445     {
00446         delete *iter;
00447         render_results.erase(iter);
00448     }
00449 }
00450 
00451 void PluginViewImpl::send_render_request(int page_num
00452                                          , const PDFRenderAttributes &page_attr
00453                                          , const RenderArea *area
00454                                          , const unsigned int  refId)
00455 {
00456     // TODO. support clip rendering by input render area
00457     // 1. find the discarded render result object
00458     RenderResultPtr result = 0;
00459     RenderResultIter idx = render_results.begin();
00460     for (; idx != render_results.end(); ++idx)
00461     {
00462         RenderResultPtr p = *idx;
00463         if (p->is_discard())
00464         {
00465             result = p;
00466             break;
00467         }
00468     }
00469 
00470     // 2. reset the render result object
00471     if (result)
00472     {
00473         result->set_page_number(page_num);
00474         result->set_ref_id(refId);
00475         // reset the status to be "USABLE"
00476         result->set_discard(false);
00477     }
00478     else
00479     {
00480         result = new PluginRenderResultImpl(page_num, refId);
00481 
00482         // add the result into list
00483         render_results.push_back(result);
00484         result->release_signal.add_slot(this, &PluginViewImpl::on_render_result_released);
00485     }
00486 
00487     renderer->post_render_task(page_num, page_attr, result, refId);
00488 }
00489 
00490 void PluginViewImpl::handle_page_ready(RenderResultPtr result, RenderStatus stat)
00491 {
00492     if (result == 0)
00493     {
00494         // the render result cannot be NULL
00495         return;
00496     }
00497 
00498     PluginEventAttrs attrs;
00499 
00500     // set reference id
00501     attrs.render_end.rid = result->get_ref_id();
00502 
00503     // set render result
00504     attrs.render_end.result = static_cast<IPluginUnknown *>(result);
00505 
00506     switch (stat)
00507     {
00508     case TASK_RENDER_DONE:
00509         {
00510             // render done
00511             attrs.render_end.status = RENDER_DONE;
00512         }
00513         break;
00514     case TASK_RENDER_OOM:
00515         {
00516             // out of memory
00517             attrs.render_end.status = RENDER_OUT_OF_MEMORY;
00518 
00519             WARNPRINTF("Tell UDS out of memory, task %ld is aborted", attrs.render_end.rid);
00520         }
00521         break;
00522     case TASK_RENDER_INVALID_PAGE:
00523         {
00524             // it is an invalid page
00525             attrs.render_end.status = RENDER_INVALID_PAGE;
00526 
00527             ERRORPRINTF("Cannot render an invalid page");
00528         }
00529     default:
00530         break;
00531     }
00532 
00533     listeners.broadcast(this, EVENT_RENDERING_END, &attrs);
00534 }
00535 
00536 // Functions that are not supported now
00537 int 
00538 PluginViewImpl::get_font_size_impl(IPluginUnknown   *thiz)
00539 {
00540     return -1;
00541 }
00542 
00543 PluginStatus 
00544 PluginViewImpl::set_font_size_impl(IPluginUnknown      *thiz,
00545                                    const unsigned int  font_size)
00546 {
00547     return PLUGIN_FAIL;
00548 }
00549 
00550 PluginStatus 
00551 PluginViewImpl::get_font_family_impl(IPluginUnknown    *thiz,
00552                                      UDSString         *font_family)
00553 {
00554     return PLUGIN_FAIL;
00555 }
00556 
00557 PluginStatus 
00558 PluginViewImpl::set_font_family_impl(IPluginUnknown    *thiz,
00559                                      const UDSString   *font_family)
00560 {
00561     return PLUGIN_FAIL;
00562 }
00563 
00564 } // namespace pdf
00565 
Generated by  doxygen 1.6.2-20100208