plaintext/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-plaintext.
00007  *
00008  * uds-plugin-plaintext 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-plaintext 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 "collection_impl.h"
00031 #include "log.h"
00032 namespace text
00033 {
00034 
00035 utils::ObjectTable<PluginViewImpl> PluginViewImpl::g_instances_table;
00036 
00037 PluginViewImpl::PluginViewImpl(PluginDocImpl *doc)
00038 : document(doc)
00039 , view(&document->get_model())
00040 , controller(&document->get_model(), &view)
00041 {
00042     assert(document);
00043 
00044     // IPluginUnknown
00045     query_interface = query_interface_impl;
00046     release         = release_impl;
00047 
00048     // IPluginView
00049     get_page_number         = get_page_number_impl;
00050     get_page_name           = get_page_name_impl;
00051     get_number_of_pages     = get_number_of_pages_impl;
00052     get_anchor_by_page      = get_anchor_by_page_impl;
00053     get_prev_page           = get_prev_page_impl;
00054     get_next_page           = get_next_page_impl;
00055     get_rendered_page_start = get_rendered_page_start_impl;
00056     get_physical_page_start = get_physical_page_start_impl;
00057     get_cover_page          = get_cover_page_impl;
00058 
00059     // IPluginViewSettings
00060     set_display_size    = set_display_size_impl;
00061     set_DPI             = set_DPI_impl;
00062     set_color_depth     = set_color_depth_impl;
00063 
00064     // IPluginRender
00065     render                  = render_impl;
00066     create_render_settings  = create_render_settings_impl;
00067     set_memory_limit        = set_memory_limit_impl;
00068     get_original_size       = get_original_size_impl;
00069     get_page_content_area   = get_page_content_area_impl;
00070 
00071     // IPluginFont
00072     get_font_size   = get_font_size_impl;
00073     set_font_size   = set_font_size_impl;
00074     get_font_family = get_font_family_impl;
00075     set_font_family = set_font_family_impl;
00076 
00077     // IPluginEventBroadcaster
00078     add_event_receiver      = add_event_receiver_impl;
00079     remove_event_receiver   = remove_event_receiver_impl;
00080 
00081     g_instances_table.add_interface<IPluginUnknown>(this);
00082     g_instances_table.add_interface<IPluginView>(this);
00083     g_instances_table.add_interface<IPluginViewSettings>(this);
00084     g_instances_table.add_interface<IPluginRender>(this);
00085     g_instances_table.add_interface<IPluginEventBroadcaster>(this);
00086     g_instances_table.add_interface<IPluginFont>(this);
00087 
00088     // Initialize signals.
00089     view.render_done_signal.add_slot(this,
00090         &PluginViewImpl::on_render_done);
00091     view.pagination_start_signal.add_slot(this,
00092         &PluginViewImpl::on_pagination_start);
00093     view.pagination_end_signal.add_slot(this,
00094         &PluginViewImpl::on_pagination_done);
00095 }
00096 
00097 PluginViewImpl::~PluginViewImpl(void)
00098 {
00099     g_instances_table.remove(this);
00100 }
00101 
00102 PluginStatus 
00103 PluginViewImpl::query_interface_impl(IPluginUnknown    *thiz,
00104                                      const UDSString   *id, 
00105                                      void              **ptr )
00106 {
00107     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00108     if (g_instances_table.query_interface(instance, id->get_buffer(id), ptr))
00109     {
00110         return PLUGIN_OK;
00111     }
00112     return PLUGIN_FAIL;
00113 }
00114 
00115 int 
00116 PluginViewImpl::release_impl(IPluginUnknown  *thiz )
00117 {
00118     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00119     delete instance;
00120     return 0;
00121 }
00122 
00123 int 
00124 PluginViewImpl::get_page_number_impl(IPluginUnknown  *thiz,
00125                                      const UDSString *anchor )
00126 {
00127     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00128     return instance->view.get_page_index_by_anchor(Position(
00129         anchor->get_buffer(anchor))) + 1;
00130 }
00131 
00132 PluginStatus
00133 PluginViewImpl::get_page_name_impl(IPluginUnknown  *thiz,
00134                                    const UDSString *page_start_anchor,
00135                                    UDSString       *name)
00136 {
00137     return PLUGIN_FAIL;
00138 }
00139 
00140 PluginStatus
00141 PluginViewImpl::get_rendered_page_start_impl(IPluginUnknown  *thiz, 
00142                                              const UDSString *anchor, 
00143                                              UDSString       *start_anchor)
00144 {
00145     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00146     Position page_anchor = instance->view.get_page_anchor_by_anchor(
00147         Position(anchor->get_buffer(anchor)));
00148     start_anchor->assign(start_anchor, page_anchor.to_string().c_str());
00149     return PLUGIN_OK;
00150 }
00151 
00152 PluginStatus
00153 PluginViewImpl::get_physical_page_start_impl(IPluginUnknown  *thiz, 
00154                                              const UDSString *anchor, 
00155                                              UDSString       *start_anchor)
00156 {
00157     return get_rendered_page_start_impl(thiz, anchor, start_anchor);
00158 }
00159 
00160 int 
00161 PluginViewImpl::get_number_of_pages_impl(IPluginUnknown *thiz)
00162 {
00163     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00164     return MAX(instance->view.get_page_count(), 1);
00165 }
00166 
00167 PluginStatus 
00168 PluginViewImpl::get_anchor_by_page_impl(IPluginUnknown *thiz,
00169                                         unsigned int page,
00170                                         UDSString *anchor)
00171 {
00172     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00173     Position pos;
00174     if (instance->view.get_anchor_by_page(page-1, pos))
00175     {
00176         std::string str = pos.to_string();
00177         anchor->assign(anchor, str.c_str());
00178         return PLUGIN_OK;
00179     }
00180     return PLUGIN_FAIL;
00181 }
00182 
00183 PluginStatus 
00184 PluginViewImpl::get_prev_page_impl(IPluginUnknown *thiz,
00185                                    UDSString      *anchor)
00186 {
00187     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00188     Position pos(anchor->get_buffer(anchor));
00189     Position new_pos;
00190     if (instance->view.calculate_prev_page_pos(pos, new_pos))
00191     {
00192         anchor->assign(anchor, new_pos.to_string().c_str());
00193         return PLUGIN_OK;
00194     }
00195     return PLUGIN_FAIL;
00196 }
00197 
00198 PluginStatus 
00199 PluginViewImpl::get_next_page_impl(IPluginUnknown *thiz,
00200                                    UDSString      *anchor)
00201 {
00202     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00203     Position pos(anchor->get_buffer(anchor));
00204     Position new_pos;
00205     if (instance->view.calculate_next_page_pos(pos, new_pos))
00206     {
00207         anchor->assign(anchor, new_pos.to_string().c_str());
00208         return PLUGIN_OK;
00209     }
00210     return PLUGIN_FAIL;
00211 }
00212 
00213 PluginStatus
00214 PluginViewImpl::get_cover_page_impl( IPluginUnknown *thiz,
00215                                     const int      width,
00216                                     const int      height,
00217                                     PluginBitmapAttributes *cover_page)
00218 {
00219     return PLUGIN_FAIL;
00220 }
00221 
00222 PluginStatus 
00223 PluginViewImpl::set_display_size_impl(IPluginUnknown *thiz,
00224                                       const int       width,
00225                                       const int       height )
00226 {
00227     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00228     instance->view.set_display_size(width, height);
00229     return PLUGIN_OK;
00230 }
00231 
00232 PluginStatus 
00233 PluginViewImpl::set_DPI_impl(IPluginUnknown        *thiz,
00234                              const unsigned int    dpi )
00235 {
00236     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00237     instance->view.set_DPI(dpi);
00238     return PLUGIN_OK;
00239 }
00240 
00241 PluginStatus 
00242 PluginViewImpl::set_color_depth_impl(IPluginUnknown *thiz,
00243                                      const unsigned int color_depth )
00244 {
00245     return PLUGIN_OK;
00246 }
00247 
00248 PluginStatus 
00249 PluginViewImpl::render_impl(IPluginUnknown      *thiz,
00250                             const UDSString     *anchor,
00251                             const int           page_offset,
00252                             IPluginUnknown      *settings,
00253                             const RenderArea    *area, 
00254                             const unsigned int  id )
00255 {
00256     // Must get proper page anchor, so no page offset allowed
00257     if (page_offset != 0)
00258     {
00259         return PLUGIN_NOT_SUPPORTED;
00260     }
00261 
00262     // No multiple thread support.
00263     // Render image here and invoke callback function immeditately.
00264     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00265     
00266     // Use controller to render.
00267     Position render_pos(anchor->get_buffer(anchor));
00268 
00269     // Pre-allocate render result object first, since in the worker thread we
00270     // don't create any render result objects. This is for thread safe purpose.
00271     PluginBitmapAttributes ba;
00272     instance->view.get_display_size(ba.width, ba.height);
00273     ba.row_stride = (ba.width + 3) / 4 * 4;
00274 
00275     unsigned char* bmp = new unsigned char[ba.row_stride * ba.height];
00276     memset(bmp, 0xFF, ba.row_stride * ba.height);
00277     ba.data = bmp;
00278 
00279     PluginRenderResultImpl * result
00280         = new PluginRenderResultImpl(instance, ba, id, 0);
00281 
00282     result->release_signal.add_slot(instance,
00283         &PluginViewImpl::on_render_result_released);
00284 
00285     instance->render_results.push_back(result);
00286 
00287     instance->view.get_controller()->render(id, render_pos, result, bmp);
00288 
00289     return PLUGIN_OK;
00290 }
00291 
00292 IPluginUnknown * 
00293 PluginViewImpl::create_render_settings_impl(IPluginUnknown  *thiz)
00294 {
00295     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00296     RenderSettingsPtr ptr = new PluginRenderSettingsImpl;
00297     assert(ptr);
00298     instance->render_settings.push_back(ptr);
00299     ptr->release_signal.add_slot(instance, 
00300         &PluginViewImpl::on_render_settings_released);
00301     return static_cast<IPluginUnknown *>(ptr);
00302 }
00303 
00304 PluginStatus 
00305 PluginViewImpl::set_memory_limit_impl(IPluginUnknown       *thiz,
00306                                       const unsigned int   bytes)
00307 {
00308     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00309     
00310     if ( bytes == 0 )
00311     {
00312         instance->view.get_controller()->pause_pagination();
00313     }
00314     else
00315     {
00316         instance->view.get_controller()->restart_pagination();
00317     }
00318     return PLUGIN_OK;
00319 }
00320 
00321 // For plain text plugin, all pages' size are the same.
00322 PluginStatus 
00323 PluginViewImpl::get_original_size_impl(IPluginUnknown       *thiz,
00324                                        const UDSString      *anchor,
00325                                        unsigned int         *width,
00326                                        unsigned int         *height )
00327 {
00328     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00329     int tmp_width, tmp_height;
00330     instance->view.get_display_size(tmp_width, tmp_height);
00331     *width = tmp_width;
00332     *height = tmp_height;
00333     return PLUGIN_OK;
00334 }
00335 
00336 PluginStatus
00337 PluginViewImpl::get_page_content_area_impl(IPluginUnknown       *thiz,
00338                                            const UDSString      *start_of_page_anchor,
00339                                            RenderArea           *area )
00340 {
00341     return PLUGIN_FAIL;
00342 }
00343 
00344 int 
00345 PluginViewImpl::get_font_size_impl(IPluginUnknown   *thiz)
00346 {
00347     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00348     return instance->view.get_font_size();
00349 }
00350 
00351 PluginStatus 
00352 PluginViewImpl::set_font_size_impl(IPluginUnknown      *thiz,
00353                                    const unsigned int  font_size)
00354 {
00355     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00356     return instance->view.set_font_size(font_size) ? PLUGIN_OK : PLUGIN_FAIL;
00357 }
00358 
00359 PluginStatus 
00360 PluginViewImpl::get_font_family_impl(IPluginUnknown    *thiz,
00361                                      UDSString         *font_family)
00362 {
00363     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00364     font_family->assign(font_family, instance->view.get_font_family().c_str());
00365     return PLUGIN_OK;
00366 }
00367 
00368 PluginStatus 
00369 PluginViewImpl::set_font_family_impl(IPluginUnknown    *thiz,
00370                                      const UDSString   *font_family)
00371 {
00372     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00373     instance->view.set_font_family(font_family->get_buffer(font_family));
00374     return PLUGIN_OK;
00375 }
00376 
00377 PluginStatus 
00378 PluginViewImpl::add_event_receiver_impl(IPluginUnknown     *thiz,
00379                                         const PluginEvent  plugin_event,
00380                                         EventFunc          callback,
00381                                         void               *user_data,
00382                                         unsigned long      *handler_id )
00383 {
00384     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00385     assert(handler_id);
00386     *handler_id = 
00387         instance->listeners.add_listener(plugin_event, callback, user_data);
00388     return PLUGIN_OK;
00389 }
00390 
00391 PluginStatus 
00392 PluginViewImpl::remove_event_receiver_impl(IPluginUnknown  *thiz,
00393                                            unsigned long   handler_id)
00394 {
00395     PluginViewImpl *instance = g_instances_table.get_object(thiz);
00396     if (instance->listeners.remove_listener(handler_id))
00397     {
00398         return PLUGIN_OK;
00399     }
00400     return PLUGIN_FAIL;
00401 }
00402 
00403 void 
00404 PluginViewImpl::on_render_settings_released(PluginRenderSettingsImpl *settings)
00405 {
00406     RenderSettingsIter iter = std::find(render_settings.begin(),
00407                                         render_settings.end(),
00408                                         settings);
00409     if (iter != render_settings.end())
00410     {
00411         delete *iter;
00412         render_settings.erase(iter);
00413     }
00414 }
00415 
00416 void 
00417 PluginViewImpl::on_render_result_released(PluginRenderResultImpl * result)
00418 {
00419     RenderResultIter iter = std::find(render_results.begin(),
00420                                       render_results.end(),
00421                                       result);
00422     if (iter != render_results.end())
00423     {
00424         delete *iter;
00425         render_results.erase(iter);
00426     }
00427 }
00428 
00429 void PluginViewImpl::on_render_done(unsigned int id,
00430                                     const Position& start_position,
00431                                     const Position& end_position,
00432                                     void  *data)
00433 {
00434     // TODO. Add render settings to render result.
00435     // PluginRenderSettingsImpl * settings_obj = 
00436     //    PluginRenderSettingsImpl::query_instance(settings);
00437     PluginEventAttrs attrs;
00438     attrs.render_end.result = static_cast<IPluginUnknown *>(data);
00439 
00440     PluginRenderResultImpl* render_result = static_cast<PluginRenderResultImpl *>(data);
00441     render_result->set_render_result_range(start_position, end_position);
00442     attrs.render_end.rid = id;
00443     attrs.render_end.status = RENDER_DONE;
00444     listeners.broadcast(this, EVENT_RENDERING_END, &attrs);
00445 }
00446 
00447 void PluginViewImpl::on_pagination_start(unsigned int total)
00448 {
00449     PluginEventAttrs attrs;
00450     attrs.paginate.current = 1;
00451     attrs.paginate.total = total;
00452     listeners.broadcast(this, EVENT_PAGINATE_START, &attrs);
00453 }
00454 
00455 void PluginViewImpl::on_pagination_done(unsigned int current, unsigned int total)
00456 {
00457     //
00458     // Sending paginate done event to UDS
00459     //
00460     PluginEventAttrs attrs;
00461     attrs.paginate.current = current + 1;
00462     attrs.paginate.total = total;
00463     listeners.broadcast(this, EVENT_PAGINATE_END, &attrs);
00464 }
00465 
00466 PluginStatus PluginViewImpl::get_anchor_from_coordinates_impl(const Position& page_start_pos,
00467                                                               const int       x,
00468                                                               const int       y,
00469                                                               UDSString*      anchor)
00470 {
00471     Position doc_pos;
00472 
00473     ViewPosition view_pos;
00474     view_pos.x = x;
00475     view_pos.y = y;
00476 
00477     if (!view.map_view_pos_to_doc_pos(page_start_pos, view_pos, doc_pos))
00478     {
00479         return PLUGIN_FAIL;
00480     }
00481 
00482     anchor->assign(anchor, doc_pos.to_string().c_str());
00483     return PLUGIN_OK;
00484 }
00485 
00486 IPluginUnknown* PluginViewImpl::get_bounding_rectangles_from_range_impl(const Position&    page_start_pos,
00487                                                                         const PluginRange* range)
00488 {
00489     std::vector<Rect> rects;
00490     Range range_internal(Position(range->start_anchor->get_buffer(range->start_anchor)),
00491                          Position(range->end_anchor->get_buffer(range->end_anchor)));
00492     view.get_bounding_rectangles(page_start_pos, rects, range_internal);
00493 
00494     PluginCollectionImpl *coll_p = new PluginCollectionImpl();
00495     coll_p->create<Rect>();
00496     std::vector<Rect>& data = coll_p->take_data_ref<Rect>();
00497     data.swap(rects);
00498 
00499     return coll_p;
00500 }
00501 
00502 }
00503 
Generated by  doxygen 1.6.2-20100208