images/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-images.
00007  *
00008  * uds-plugin-images 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-images 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 #include "log.h"
00031 
00032 namespace images
00033 {
00034 
00035 utils::ObjectTable<PluginViewImpl> PluginViewImpl::g_instances_table;
00036 
00037 PluginViewImpl::PluginViewImpl(PluginDocImpl *doc)
00038 : document(doc)
00039 {
00040     LOGPRINTF("%p", doc);
00041 
00042     assert(document);
00043     renderer = new ImagesRenderer(document->get_doc());
00044     assert(renderer);
00045     renderer->sig_page_ready.add_slot(this, 
00046             &PluginViewImpl::render_page_ready);
00047 
00048     // IPluginUnknown
00049     query_interface = query_interface_impl;
00050     release         = release_impl;
00051 
00052     // IPluginView
00053     get_page_number     = get_page_number_impl;
00054     get_page_name       = get_page_name_impl;
00055     get_number_of_pages = get_number_of_pages_impl;
00056     get_anchor_by_page  = get_anchor_by_page_impl;
00057     get_prev_page       = get_prev_page_impl;
00058     get_next_page       = get_next_page_impl;
00059     get_rendered_page_start = get_rendered_page_start_impl;
00060     get_physical_page_start = get_physical_page_start_impl;
00061     get_cover_page      = get_cover_page_impl;
00062 
00063     // IPluginViewSettings
00064     set_display_size    = set_display_size_impl;
00065     set_DPI             = set_DPI_impl;
00066     set_color_depth     = set_color_depth_impl;
00067 
00068     // IPluginRender
00069     render                  = render_impl;
00070     create_render_settings  = create_render_settings_impl;
00071     set_memory_limit        = set_memory_limit_impl;
00072     get_original_size       = get_original_size_impl;
00073     get_page_content_area   = get_page_content_area_impl;
00074     get_original_rotation   = get_original_rotation_impl;
00075 
00076     // IPluginFont
00077     get_font_size   = get_font_size_impl;
00078     set_font_size   = set_font_size_impl;
00079     get_font_family = get_font_family_impl;
00080     set_font_family = set_font_family_impl;
00081 
00082     // IPluginEventBroadcaster
00083     add_event_receiver      = add_event_receiver_impl;
00084     remove_event_receiver   = remove_event_receiver_impl;
00085 
00086     g_instances_table.add_interface<IPluginUnknown>(this);
00087     g_instances_table.add_interface<IPluginView>(this);
00088     g_instances_table.add_interface<IPluginViewSettings>(this);
00089     g_instances_table.add_interface<IPluginRender>(this);
00090     g_instances_table.add_interface<IPluginEventBroadcaster>(this);
00091 
00092     // The images plugin does not support IPluginFont.
00093     // If want to support IPluginFont, uncomment the following line.
00094     // g_instances_table.add_interface<IPluginFont>(this);
00095 
00096 }
00097 
00098 PluginViewImpl::~PluginViewImpl(void)
00099 {
00100     LOGPRINTF("entry");
00101 
00102     remove_slots();
00103 
00104     delete renderer;
00105     renderer = 0;
00106 
00107     g_instances_table.remove(this);
00108 }
00109 
00110 void PluginViewImpl::stop_renderer(void)
00111 {
00112     if (renderer)
00113     {
00114         renderer->stop();
00115     }
00116 }
00117 
00118 void PluginViewImpl::render_page_ready(ImagePage * page,
00119                                        const unsigned int refId,
00120                                        ImageRenderStatus status,
00121                                        void * user_data)
00122 {
00123     LOGPRINTF("entry");
00124     
00125     // Convert user_data to be PluginRenderResultImpl.
00126     PluginRenderResultImpl * result = 
00127         static_cast<PluginRenderResultImpl *>(user_data);
00128     if (!result) { return; }
00129     
00130     // Set the page for PluginRenderResultImpl.
00131     result->set_page(page);
00132 
00133     // Set all fields of PluginEventAttrs.
00134     PluginEventAttrs attrs;
00135     attrs.render_end.result = static_cast<IPluginUnknown *>(result);
00136     if (status == IMG_RENDER_OK)
00137     {
00138         attrs.render_end.status = RENDER_DONE;
00139     }
00140     else if (status == IMG_RENDER_OOM)
00141     {
00142         attrs.render_end.status = RENDER_OUT_OF_MEMORY;
00143     }
00144     else if (status == IMG_RENDER_INVALID)
00145     {
00146         attrs.render_end.status = RENDER_INVALID_PAGE;        
00147     }
00148     else
00149     {
00150         attrs.render_end.status = RENDER_FAIL;
00151     }
00152     
00153     attrs.render_end.rid = refId;
00154 
00155     // Notify UDS by using the callback function.        
00156     listeners.broadcast( this, EVENT_RENDERING_END, &attrs );
00157 }
00158 
00159 PluginStatus 
00160 PluginViewImpl::query_interface_impl(IPluginUnknown    *thiz,
00161                                      const UDSString   *id, 
00162                                      void              **ptr )
00163 {
00164     LOGPRINTF("entry");
00165 
00166     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00167     if (g_instances_table.query_interface(instance, id->get_buffer(id), ptr))
00168     {
00169         return PLUGIN_OK;
00170     }
00171     return PLUGIN_FAIL;
00172 }
00173 
00174 int 
00175 PluginViewImpl::release_impl(IPluginUnknown  *thiz )
00176 {
00177     LOGPRINTF("entry");
00178 
00179     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00180     instance->release_signal.safe_broadcast(instance);
00181     return 0;
00182 }
00183 
00184 int 
00185 PluginViewImpl::get_page_number_impl(IPluginUnknown  *thiz,
00186                                      const UDSString *anchor )
00187 {
00188     LOGPRINTF("entry");
00189 
00190     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00191     return instance->document->get_page_number(anchor->get_buffer(anchor));
00192 }
00193 
00194 PluginStatus 
00195 PluginViewImpl::get_page_name_impl(IPluginUnknown  *thiz,
00196                                    const UDSString *anchor,
00197                                    UDSString       *name)
00198 {
00199     LOGPRINTF("entry");
00200 
00201     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00202 
00203     std::string temp;
00204     if (instance->document->get_page_name(anchor->get_buffer(anchor), temp))
00205     {
00206         name->assign(name, temp.c_str());
00207         return PLUGIN_OK;
00208     }
00209     return PLUGIN_FAIL;
00210 }
00211 
00212 int 
00213 PluginViewImpl::get_number_of_pages_impl(IPluginUnknown *thiz)
00214 {
00215     LOGPRINTF("entry");
00216 
00217     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00218     return instance->document->get_page_count();
00219 }
00220 
00221 PluginStatus 
00222 PluginViewImpl::get_anchor_by_page_impl(IPluginUnknown *thiz,
00223                                         unsigned int page,
00224                                         UDSString *anchor)
00225 {
00226     LOGPRINTF("entry");
00227 
00228     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00229 
00230     // Use first page as the initial anchor.
00231     std::string temp;
00232     if (instance->document->get_anchor_of_page(page, temp))
00233     {
00234         anchor->assign(anchor, temp.c_str());
00235         return PLUGIN_OK;
00236     }
00237     return PLUGIN_FAIL;
00238 }
00239 
00240 PluginStatus 
00241 PluginViewImpl::get_prev_page_impl(IPluginUnknown *thiz,
00242                                    UDSString      *anchor)
00243 {
00244     LOGPRINTF("entry");
00245 
00246     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00247 
00248     std::string temp(anchor->get_buffer(anchor));
00249     if (instance->document->get_prev_page(temp))
00250     {
00251         anchor->assign(anchor, temp.c_str());
00252         return PLUGIN_OK;
00253     }
00254     return PLUGIN_FAIL;
00255 }
00256 
00257 PluginStatus 
00258 PluginViewImpl::get_next_page_impl(IPluginUnknown *thiz,
00259                                    UDSString      *anchor)
00260 {
00261     LOGPRINTF("entry");
00262 
00263     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00264 
00265     std::string temp(anchor->get_buffer(anchor));
00266     if (instance->document->get_next_page(temp))
00267     {
00268         anchor->assign(anchor, temp.c_str());
00269         return PLUGIN_OK;
00270     }
00271     return PLUGIN_FAIL;
00272 }
00273 
00274 PluginStatus
00275 PluginViewImpl::get_rendered_page_start_impl(IPluginUnknown  *thiz, 
00276                                              const UDSString *anchor, 
00277                                              UDSString       *start_anchor)
00278 {
00279     if (anchor && start_anchor)
00280     {
00281         start_anchor->assign(start_anchor, anchor->get_buffer(anchor));
00282         return PLUGIN_OK;
00283     }
00284     return PLUGIN_FAIL;
00285 }
00286 
00287 PluginStatus
00288 PluginViewImpl::get_physical_page_start_impl(IPluginUnknown  *thiz, 
00289                                              const UDSString *anchor, 
00290                                              UDSString       *start_anchor)
00291 {
00292     return get_rendered_page_start_impl(thiz, anchor, start_anchor);
00293 }
00294 
00295 PluginStatus
00296 PluginViewImpl::get_cover_page_impl( IPluginUnknown *thiz,
00297                                     const int      width,
00298                                     const int      height,
00299                                     PluginBitmapAttributes *cover_page)
00300 {
00301     return PLUGIN_FAIL;
00302 }
00303 
00304 PluginStatus 
00305 PluginViewImpl::set_display_size_impl(IPluginUnknown *thiz,
00306                                       const int       width,
00307                                       const int       height )
00308 {
00309     LOGPRINTF("entry");
00310 
00311     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00312     instance->render_req_attributes.desired_width = width;
00313     instance->render_req_attributes.desired_height = height;
00314     return PLUGIN_OK;
00315 }
00316 
00317 PluginStatus 
00318 PluginViewImpl::set_DPI_impl(IPluginUnknown        *thiz,
00319                              const unsigned int    dpi )
00320 {
00321     LOGPRINTF("entry");
00322 
00323     // Can be ignored.
00324     return PLUGIN_FAIL;
00325 }
00326 
00327 PluginStatus 
00328 PluginViewImpl::set_color_depth_impl(IPluginUnknown *thiz,
00329                                      const unsigned int color_depth )
00330 {
00331     LOGPRINTF("entry");
00332 
00333     return PLUGIN_OK;
00334 }
00335 
00336 PluginStatus 
00337 PluginViewImpl::render_impl(IPluginUnknown      *thiz,
00338                             const UDSString     *anchor,
00339                             const int           page_offset,
00340                             IPluginUnknown      *settings,
00341                             const RenderArea    *area, 
00342                             const unsigned int  refId )
00343 {
00344     LOGPRINTF("entry");
00345 
00346     // Must get proper page anchor, so no page offset allowed
00347     if (page_offset != 0)
00348     {
00349         return PLUGIN_NOT_SUPPORTED;
00350     }
00351 
00352     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00353     assert(instance->renderer);
00354 
00355     // Construct a PluginRenderResultImpl object for this render request.
00356     // We'll set its fields for it later when render is done.
00357     PluginRenderResultImpl *result = new PluginRenderResultImpl();
00358     assert(result);
00359     instance->render_results.push_back(result);
00360     result->release_signal.add_slot(instance, 
00361             &PluginViewImpl::on_render_result_released);
00362    
00363     // render image according to the settings.
00364     PluginRenderSettingsImpl * settings_obj = 
00365         PluginRenderSettingsImpl::query_instance(settings);
00366 
00367     unsigned int orig_width  = 0;
00368     unsigned int orig_height = 0;
00369     instance->document->get_original_size(anchor->get_buffer(anchor), orig_width, orig_height);
00370 
00371     images::ImagePageAttrs attrs;
00372     attrs.original_width  = static_cast<int>(orig_width);
00373     attrs.original_height = static_cast<int>(orig_height);
00374     attrs.desired_width   = instance->render_req_attributes.desired_width;
00375     attrs.desired_height  = instance->render_req_attributes.desired_height;
00376     attrs.zoom            = settings_obj->zoom();
00377     attrs.rotation        = settings_obj->rotation();
00378     
00379     ImageRenderStatus rc = instance->renderer->render(anchor->get_buffer(anchor), 
00380                                                       attrs, refId, result);
00381     if (rc == IMG_RENDER_OK)
00382     {
00383         return PLUGIN_OK;        
00384     }
00385     else if (rc == IMG_RENDER_OOM)
00386     {
00387         return PLUGIN_OUT_OF_MEMORY;        
00388     }
00389     else /* if (rc == IMG_RENDER_INVALID) || (rc == IMG_RENDER_FAIL)) */
00390     {        
00391         return PLUGIN_FAIL;
00392     }
00393 }
00394 
00395 IPluginUnknown * 
00396 PluginViewImpl::create_render_settings_impl(IPluginUnknown  *thiz)
00397 {
00398     LOGPRINTF("entry");
00399 
00400     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00401     RenderSettingsPtr ptr = new PluginRenderSettingsImpl;
00402     assert(ptr);
00403     instance->render_settings.push_back(ptr);
00404     ptr->release_signal.add_slot(instance, 
00405         &PluginViewImpl::on_render_settings_released);
00406     return static_cast<IPluginUnknown *>(ptr);
00407 }
00408 
00409 PluginStatus 
00410 PluginViewImpl::set_memory_limit_impl(IPluginUnknown       *thiz,
00411                                       const unsigned int   bytes)
00412 {
00413     LOGPRINTF("entry");
00414 
00415     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00416     if (instance->renderer)
00417     {
00418         if (instance->renderer->set_memory_limit(bytes))
00419         {
00420             return PLUGIN_OK;
00421         }
00422     }
00423 
00424     return PLUGIN_FAIL;
00425 }
00426 
00427 PluginStatus 
00428 PluginViewImpl::get_original_size_impl(IPluginUnknown   *thiz,
00429                                    const UDSString      *anchor,
00430                                    unsigned int         *width,
00431                                    unsigned int         *height )
00432 {
00433     LOGPRINTF("entry");
00434 
00435     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00436     // When opening an image it doesn't autorotate to the best fit.
00437     // Showing the image as large as possible.
00438     // This is a quick way to fix it in images plugin only.
00439     // Note, this policy is the same as ImagePage.
00440     unsigned int w, h;
00441     if (instance->document->get_original_size(anchor->get_buffer(anchor), w, h))
00442     {
00443         unsigned int display_w = instance->render_req_attributes.desired_width;
00444         unsigned int display_h = instance->render_req_attributes.desired_height;
00445 
00446         PluginRotationDegree autorotate = ImagePage::check_autorotate(w, h, display_w, display_h);
00447         if (   autorotate == Clockwise_Degrees_90
00448             || autorotate == Clockwise_Degrees_270)
00449         {
00450             *width = h;
00451             *height = w;
00452         }
00453         else
00454         {
00455             *width = w;
00456             *height = h;
00457         }
00458         return PLUGIN_OK;
00459     }
00460     return PLUGIN_FAIL;
00461 }
00462 
00463 PluginStatus
00464 PluginViewImpl::get_page_content_area_impl(IPluginUnknown       *thiz,
00465                                            const UDSString      *start_of_page_anchor,
00466                                            RenderArea           *area )
00467 {
00468     area->x_offset = area->y_offset = 0.0f;
00469     area->width    = area->height   = 1.0f;
00470     return PLUGIN_OK;
00471 }
00472 
00473 PluginStatus 
00474 PluginViewImpl::get_original_rotation_impl(IPluginUnknown   *thiz,
00475                                    const UDSString          *anchor,
00476                                    PluginRotationDegree     *rotation)
00477 {
00478     LOGPRINTF("entry");
00479 
00480     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00481     if (instance->document->get_original_rotation(anchor->get_buffer(anchor),
00482                                               *rotation))
00483     {
00484         return PLUGIN_OK;
00485     }
00486     return PLUGIN_FAIL;
00487 }
00488 
00489 int 
00490 PluginViewImpl::get_font_size_impl(IPluginUnknown   *thiz)
00491 {
00492     LOGPRINTF("entry");
00493 
00494     return -1;
00495 }
00496 
00497 PluginStatus 
00498 PluginViewImpl::set_font_size_impl(IPluginUnknown      *thiz,
00499                                    const unsigned int  font_size)
00500 {
00501     LOGPRINTF("entry");
00502 
00503     return PLUGIN_FAIL;
00504 }
00505 
00506 PluginStatus 
00507 PluginViewImpl::get_font_family_impl(IPluginUnknown    *thiz,
00508                                      UDSString         *font_family)
00509 {
00510     LOGPRINTF("entry");
00511 
00512     return PLUGIN_FAIL;
00513 }
00514 
00515 PluginStatus 
00516 PluginViewImpl::set_font_family_impl(IPluginUnknown    *thiz,
00517                                      const UDSString   *font_family)
00518 {
00519     LOGPRINTF("entry");
00520 
00521     return PLUGIN_FAIL;
00522 }
00523 
00524 PluginStatus 
00525 PluginViewImpl::add_event_receiver_impl(IPluginUnknown     *thiz,
00526                                         const PluginEvent  plugin_event,
00527                                         EventFunc          callback,
00528                                         void               *user_data,
00529                                         unsigned long      *handler_id )
00530 {
00531     LOGPRINTF("entry");
00532 
00533     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00534     assert(handler_id);
00535     *handler_id = 
00536         instance->listeners.add_listener(plugin_event, callback, user_data);
00537     return PLUGIN_OK;
00538 }
00539 
00540 PluginStatus 
00541 PluginViewImpl::remove_event_receiver_impl(IPluginUnknown  *thiz,
00542                                            unsigned long   handler_id)
00543 {
00544     LOGPRINTF("entry");
00545 
00546     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00547     if (instance->listeners.remove_listener(handler_id))
00548     {
00549         return PLUGIN_OK;
00550     }
00551     return PLUGIN_FAIL;
00552 }
00553 
00554 void 
00555 PluginViewImpl::on_render_settings_released(PluginRenderSettingsImpl *settings)
00556 {
00557     LOGPRINTF("entry");
00558 
00559     RenderSettingsIter iter = std::find(render_settings.begin(),
00560                                         render_settings.end(),
00561                                         settings);
00562     if (iter != render_settings.end())
00563     {
00564         delete *iter;
00565         render_settings.erase(iter);
00566     }
00567 }
00568 
00569 void 
00570 PluginViewImpl::on_render_result_released(PluginRenderResultImpl * result)
00571 {
00572     LOGPRINTF("entry");
00573 
00574     RenderResultIter iter = std::find(render_results.begin(),
00575                                       render_results.end(),
00576                                       result);
00577     if (iter != render_results.end())
00578     {
00579         delete *iter;
00580         render_results.erase(iter);
00581     }
00582 }
00583 
00584 void PluginViewImpl::remove_slots(void)
00585 {
00586     //
00587     if (renderer)
00588     {
00589         renderer->sig_page_ready.remove_slot(this, 
00590                 &PluginViewImpl::render_page_ready);
00591     }
00592 
00593     // 
00594     for (RenderSettingsIter iter = render_settings.begin();
00595             iter != render_settings.end();
00596             ++iter)
00597     {
00598         if (*iter)
00599         {
00600             LOGPRINTF("Removing the slot of release signal of RenderSettings.");
00601             (*iter)->release_signal.remove_slot(this,
00602                     &PluginViewImpl::on_render_settings_released);
00603         }
00604     }
00605  
00606     //
00607     for (RenderResultIter iter = render_results.begin();
00608             iter != render_results.end();
00609             ++iter)
00610     {
00611         if (*iter)
00612         {
00613             LOGPRINTF("Removing the slot of release signal of RenderResult");
00614             (*iter)->release_signal.remove_slot(this,
00615                     &PluginViewImpl::on_render_result_released);
00616         }
00617     }
00618 }
00619 
00620 }
00621 
00622 
Generated by  doxygen 1.6.2-20100208