images/plugin_impl/document_impl.cpp

Go to the documentation of this file.
00001 /*
00002  * File Name: document_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 "document_impl.h"
00029 #include "view_impl.h"
00030 #include "collection_impl.h"
00031 #include "string_impl.h"
00032 #include "marker_entry_impl.h"
00033 #include "log.h"
00034 
00035 namespace images
00036 {
00037 
00038 utils::ObjectTable<PluginDocImpl> PluginDocImpl::g_instances_table;
00039 
00040 PluginDocImpl::PluginDocImpl()
00041 {
00042     LOGPRINTF("entry");
00043 
00044     // IPluginUnknown
00045     query_interface = query_interface_impl;
00046     release         = release_impl;
00047 
00048     // IPluginDocument
00049     open        = open_impl;
00050     is_open     = is_open_impl;
00051     close       = close_impl;
00052     create_view = create_view_impl;
00053 
00054     // IPluginDocNavigator
00055     get_initial_anchor      = get_initial_anchor_impl;
00056     get_object_from_anchor  = get_object_from_anchor_impl;
00057     get_type_of_object      = get_type_of_object_impl;
00058     get_words_from_range    = get_words_from_range_impl;
00059     get_text_from_range     = get_text_from_range_impl;
00060     is_anchor_in_current_document = is_anchor_in_current_document_impl;
00061     get_file_name_from_anchor = get_file_name_from_anchor_impl;
00062     get_file_position_from_anchor = get_file_position_from_anchor_impl;
00063     compare_anchor_location = compare_anchor_location_impl;
00064 
00065     // IPluginDocAttributes
00066     get_attribute = get_attribute_impl;
00067     set_attribute = set_attribute_impl;
00068 
00069     // IPluginEventBroadcaster
00070     add_event_receiver      = add_event_receiver_impl;
00071     remove_event_receiver   = remove_event_receiver_impl;
00072 
00073     // IPluginDocHyperlink
00074     is_hyperlink                = is_hyperlink_impl;
00075     get_target_from_hyperlink   = get_target_from_hyperlink_impl;
00076 
00077     // IPluginDocDictionary
00078     is_dictionary = is_dictionary_impl;
00079 
00080     // IPluginDocMarker
00081     get_supported_marker_types  = get_supported_marker_types_impl;
00082     request_marker_trees        = request_marker_trees_impl;
00083 
00084     // Initialize interface and object table.
00085     g_instances_table.add_interface<IPluginUnknown>(this);
00086     g_instances_table.add_interface<IPluginDocument>(this);
00087     g_instances_table.add_interface<IPluginDocNavigator>(this);
00088     g_instances_table.add_interface<IPluginDocAttributes>(this);
00089     g_instances_table.add_interface<IPluginEventBroadcaster>(this);
00090     g_instances_table.add_interface<IPluginDocHyperlink>(this);
00091     g_instances_table.add_interface<IPluginDocDictionary>(this);
00092 
00093     // Initialize document attributes map.
00094     init_doc_attributes();
00095 }
00096 
00097 void PluginDocImpl::init_doc_attributes()
00098 {
00099     doc_attr_map.insert(std::make_pair("fixed-page", "yes"));
00100     doc_attr_map.insert(std::make_pair("virtual-document", "yes"));
00101     doc_attr_map.insert(std::make_pair("disable-directory-scanning", "no"));
00102 }
00103 
00104 PluginDocImpl::~PluginDocImpl()
00105 {
00106     LOGPRINTF("entry");
00107 
00108     remove_slots();
00109     g_instances_table.remove(this);
00110 }
00111 
00112 unsigned int PluginDocImpl::get_page_count()
00113 {
00114     LOGPRINTF("%d", document.page_count());
00115 
00116     return document.page_count();
00117 }
00118 
00119 unsigned int PluginDocImpl::get_page_number(const std::string & anchor)
00120 {
00121     LOGPRINTF("%s", anchor.c_str());
00122 
00123     return document.get_position(anchor);
00124 }
00125 
00126 bool PluginDocImpl::get_page_name(const std::string & anchor,
00127                                   std::string & name)
00128 {
00129     return document.get_page_name(anchor, name);
00130 }
00131 
00132 int PluginDocImpl::get_page(const std::string & anchor)
00133 {
00134     unsigned int page_number = get_page_number(anchor);
00135 
00136     LOGPRINTF("%s %d", anchor.c_str(), page_number);
00137 
00138     return page_number;
00139 }
00140 
00141 bool PluginDocImpl::get_anchor_of_page(const unsigned int page_number,
00142                                        std::string & anchor)
00143 {
00144     LOGPRINTF("%d", page_number);
00145 
00146     return document.get_anchor_of_page(page_number, anchor);
00147 }
00148 
00149 bool PluginDocImpl::get_prev_page(std::string & anchor)
00150 {
00151     LOGPRINTF("%s", anchor.c_str());
00152 
00153     return document.get_prev_page(anchor);
00154 }
00155 
00156 bool PluginDocImpl::get_next_page(std::string & anchor)
00157 {
00158     LOGPRINTF("%s", anchor.c_str());
00159 
00160     return document.get_next_page(anchor);
00161 }
00162 
00163 ImagesDocument * PluginDocImpl::get_doc(void)
00164 {
00165     LOGPRINTF("entry");
00166 
00167     return &document;
00168 }
00169 
00170 bool PluginDocImpl::get_original_size(const std::string &anchor,
00171                                       unsigned int &width,
00172                                       unsigned int &height)
00173 {
00174     return document.get_original_size(anchor, width, height);
00175 }
00176 
00177 bool PluginDocImpl::get_original_rotation(const std::string &anchor,
00178                                           PluginRotationDegree &rotation)
00179 {
00180     return document.get_original_rotation(anchor, rotation);
00181 }
00182 
00183 PluginStatus 
00184 PluginDocImpl::query_interface_impl(IPluginUnknown    *thiz,
00185                                     const UDSString   *id, 
00186                                     void              **ptr )
00187 {
00188     LOGPRINTF("entry");
00189 
00190     // check object. 
00191     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00192 
00193     // check interface.
00194     if (g_instances_table.query_interface(instance, 
00195                                           id->get_buffer(id), 
00196                                           ptr))
00197     {
00198         return PLUGIN_OK;
00199     }
00200     return PLUGIN_FAIL;
00201 }
00202 
00203 int 
00204 PluginDocImpl::release_impl(IPluginUnknown  *thiz )
00205 {
00206     LOGPRINTF("entry");
00207 
00208     // Check object. 
00209     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00210     instance->release_signal.safe_broadcast(instance);
00211     return 0;
00212 }
00213 
00214 
00215 PluginStatus
00216 PluginDocImpl::open_impl(IPluginUnknown    *thiz, 
00217                          const UDSString   *path)
00218 {
00219     LOGPRINTF("%s", path->get_buffer(path));
00220 
00221     // Check object. 
00222     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00223     
00224     // Check document has been opened or not.
00225     assert(!instance->document.is_open());
00226 
00227     bool disable_directory_scanning = false;
00228 
00229     const StringImpl key("disable-directory-scanning");
00230     StringImpl value;
00231     if (get_attribute_impl(thiz, &key, &value) == PLUGIN_OK)
00232     {
00233         const StringImpl tmp("yes");
00234         disable_directory_scanning = (value == tmp);
00235     }
00236     
00237     if (instance->document.open_document(path->get_buffer(path), 
00238                                         !disable_directory_scanning))
00239     {
00240         return PLUGIN_OK;
00241     }
00242     return PLUGIN_FAIL;    
00243 }
00244 
00245 PluginBool
00246 PluginDocImpl::is_open_impl(IPluginUnknown    *thiz)
00247 {
00248     LOGPRINTF("entry");
00249 
00250     // Check object. 
00251     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00252     
00253     // Check document has been opened or not.
00254     if (instance->document.is_open())
00255     {
00256         return PLUGIN_TRUE;
00257     }
00258     return PLUGIN_FALSE;
00259 }
00260 
00261 PluginStatus
00262 PluginDocImpl::close_impl(IPluginUnknown   *thiz)
00263 {
00264     LOGPRINTF("entry");
00265 
00266     // Check object. 
00267     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00268     
00269     // Stop the render/pre-render thread firstly.
00270     ViewsIter begin = instance->views.begin();
00271     ViewsIter end   = instance->views.end();
00272     for(ViewsIter iter = begin; iter != end; ++iter)
00273     {
00274         (*iter)->stop_renderer();
00275     }
00276     
00277     // Check document has been opened or not.
00278     assert(instance->document.is_open());
00279     if (instance->document.close_document())
00280     {
00281         return PLUGIN_OK;
00282     }
00283     return PLUGIN_FAIL;
00284 }
00285 
00286 IPluginUnknown *
00287 PluginDocImpl::create_view_impl(IPluginUnknown   *thiz)
00288 {
00289     LOGPRINTF("entry");
00290 
00291     // Check object. 
00292     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00293     
00294     // Create the view.
00295     ViewPtr ptr = new PluginViewImpl(instance);
00296     assert(ptr);
00297     instance->views.push_back(ptr);
00298     ptr->release_signal.add_slot(instance, 
00299                                  &PluginDocImpl::on_view_released);
00300     return static_cast<IPluginUnknown *>(ptr);
00301 }
00302 
00303 PluginStatus 
00304 PluginDocImpl::get_initial_anchor_impl(IPluginUnknown   *thiz,
00305                                        UDSString        *anchor)
00306 {
00307     LOGPRINTF("entry");
00308 
00309     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00310 
00311     // Use first page as the initial anchor.
00312     int page_num = instance->document.get_initial_page_num();
00313 
00314     std::string temp;
00315     if (instance->document.get_anchor_of_page(page_num, temp))
00316     {
00317         anchor->assign(anchor, temp.c_str());
00318         return PLUGIN_OK;
00319     }
00320     return PLUGIN_FAIL;
00321 }
00322 
00323 PluginStatus 
00324 PluginDocImpl::get_object_from_anchor_impl(IPluginUnknown  *thiz,
00325                                            const UDSString *anchor, 
00326                                            PluginRange     *range)
00327 {
00328     LOGPRINTF("entry");
00329 
00330     // Alawys return PLUGIN_FAIL
00331     return PLUGIN_FAIL;
00332 }
00333 
00334 PluginDocObjectType 
00335 PluginDocImpl::get_type_of_object_impl(IPluginUnknown      *thiz,
00336                                        const PluginRange   *range)
00337 {
00338     LOGPRINTF("entry");
00339 
00340     return PLUGIN_DOC_OBJECT_IMAGE;
00341 }
00342     
00343 PluginStatus 
00344 PluginDocImpl::get_words_from_range_impl(IPluginUnknown      *thiz, 
00345                                         const PluginRange    *chars_range, 
00346                                         PluginRange          *words_range )
00347 {
00348     LOGPRINTF("entry");
00349     return PLUGIN_NOT_SUPPORTED;
00350 }
00351 
00352 PluginStatus 
00353 PluginDocImpl::get_text_from_range_impl(IPluginUnknown        *thiz, 
00354                                         const PluginRange     *range, 
00355                                         UDSString             *result)
00356 {
00357     LOGPRINTF("entry");
00358 
00359     return PLUGIN_FAIL;
00360 }
00361 
00362 PluginBool 
00363 PluginDocImpl::is_anchor_in_current_document_impl(IPluginUnknown    *thiz,
00364                                                   const UDSString   *anchor)
00365 {
00366     LOGPRINTF("entry");
00367 
00368     // check object. 
00369     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00370     
00371     if (instance->document.has_anchor(anchor->get_buffer(anchor)))
00372     {
00373         return PLUGIN_TRUE;
00374     }
00375     return PLUGIN_FALSE;
00376 }
00377 
00378 PluginStatus 
00379 PluginDocImpl::get_file_name_from_anchor_impl(IPluginUnknown    *thiz,
00380                                               const UDSString   *anchor,
00381                                               UDSString         *file_name)
00382 {
00383     if (!thiz || !anchor || !file_name)
00384     {
00385         return PLUGIN_FAIL;
00386     }
00387     
00388     if (is_anchor_in_current_document_impl(thiz, anchor) == PLUGIN_FALSE)
00389     {
00390         return PLUGIN_FAIL;
00391     }
00392     
00393     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00394     
00395     std::string temp;
00396     if (instance->get_page_name(anchor->get_buffer(anchor), temp))
00397     {
00398         file_name->assign(file_name, temp.c_str());
00399         return PLUGIN_OK;
00400     }
00401     
00402     return PLUGIN_FAIL;    
00403 }
00404 
00405 PluginStatus 
00406 PluginDocImpl::get_file_position_from_anchor_impl(IPluginUnknown    *thiz,
00407                                                   const UDSString   *anchor,
00408                                                   signed long long  *position)
00409 {
00410     if (!thiz || !anchor || !position)
00411     {
00412         return PLUGIN_FAIL;
00413     }
00414     
00415     if (is_anchor_in_current_document_impl(thiz, anchor) == PLUGIN_FALSE)
00416     {
00417         return PLUGIN_FAIL;
00418     }
00419     
00420     *position = 0;
00421     return PLUGIN_OK;
00422 }
00423 
00424 int 
00425 PluginDocImpl::compare_anchor_location_impl(IPluginUnknown   *thiz,
00426                                             const UDSString  *anchor_a,
00427                                             const UDSString  *anchor_b)
00428 {
00429     LOGPRINTF("entry");
00430 
00431     // check object. 
00432     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00433     
00434     return instance->document.compare_anchor(anchor_a->get_buffer(anchor_a), 
00435                                           anchor_a->get_buffer(anchor_b));
00436 }
00437 
00438 // Define images attribute.
00439 PluginStatus
00440 PluginDocImpl::get_attribute_impl(IPluginUnknown     *thiz,
00441                                   const UDSString    *key, 
00442                                   UDSString          *value )
00443 {
00444     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00445 
00446     // Check whether the key exists or not.
00447     if (instance->doc_attr_map.find(key->get_buffer(key)) 
00448             == instance->doc_attr_map.end())
00449     {
00450         return PLUGIN_NOT_SUPPORTED;
00451     }
00452     value->assign(value, instance->doc_attr_map[key->get_buffer(key)].c_str());
00453     return PLUGIN_OK;
00454 }
00455 
00456 PluginStatus 
00457 PluginDocImpl::set_attribute_impl(IPluginUnknown     *thiz,
00458                                   const UDSString    *key,
00459                                   const UDSString    *value )
00460 {
00461     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00462 
00463     const char* key_cstr = key->get_buffer(key);
00464     DocAttrMapIter iter = instance->doc_attr_map.find(key_cstr);
00465     if (iter == instance->doc_attr_map.end())
00466     {
00467         return PLUGIN_NOT_SUPPORTED;
00468     }
00469 
00470     iter->second = value->get_buffer(value);
00471     return PLUGIN_OK;
00472 }
00473     
00474 PluginStatus 
00475 PluginDocImpl::add_event_receiver_impl(IPluginUnknown     *thiz,
00476                                        const PluginEvent  plugin_event,
00477                                        EventFunc          callback,
00478                                        void               *user_data,
00479                                        unsigned long      *handler_id)
00480 {
00481     LOGPRINTF("entry");
00482 
00483     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00484     assert(handler_id);
00485     *handler_id = 
00486         instance->listeners.add_listener(plugin_event, callback, user_data);
00487     return PLUGIN_OK;
00488 }
00489 
00490 PluginStatus 
00491 PluginDocImpl::remove_event_receiver_impl(IPluginUnknown  *thiz,
00492                                           unsigned long   handler_id )
00493 {
00494     LOGPRINTF("entry");
00495 
00496     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00497     if (instance->listeners.remove_listener(handler_id))
00498     {
00499         return PLUGIN_OK;
00500     }
00501     return PLUGIN_FAIL;
00502 }
00503 
00504 PluginBool 
00505 PluginDocImpl::is_hyperlink_impl(IPluginUnknown    *thiz,
00506                                  const PluginRange *range )
00507 {
00508     LOGPRINTF("entry");
00509 
00510     // No hyperlink
00511     return PLUGIN_FALSE;
00512 }
00513 
00514 PluginStatus 
00515 PluginDocImpl::get_target_from_hyperlink_impl(IPluginUnknown     *thiz,
00516                                               const PluginRange  *range, 
00517                                               UDSString          *anchor )
00518 {
00519     LOGPRINTF("entry");
00520 
00521     return PLUGIN_FAIL;
00522 }
00523     
00524 PluginBool 
00525 PluginDocImpl::is_dictionary_impl(IPluginUnknown  *thiz )
00526 {
00527     LOGPRINTF("entry");
00528 
00529     return PLUGIN_FALSE;
00530 }
00531 
00532 // The images document supports table of content.
00533 IPluginUnknown* 
00534 PluginDocImpl::get_supported_marker_types_impl(IPluginUnknown  *thiz )
00535 {
00536     LOGPRINTF("entry");
00537 
00538     // Not necessary to check thiz in this kind of document.
00539     // But if the document has different marker type it should
00540     // make necessary check.
00541 
00542     PluginCollectionImpl *collection = 
00543         new PluginCollectionImpl;
00544     collection->create<PluginMarkerType>();
00545     collection->take_data_ref<PluginMarkerType>().push_back(MARKER_TOC);
00546 
00547     // It's not necessary to connect the release signal, because
00548     // the collection can remove the memory itself. Document object
00549     // does not store any pointer data in the collection here.
00550     return static_cast<IPluginUnknown *>(collection);
00551 }
00552 
00553 // For images document, the table of content is the file list.
00554 // Steps to generate marker tree.
00555 // 1. Generate the collection object.
00556 // 2. Add marker tree nodes into the collection.
00557 // 3. Invoke the callback function registered in listeners list.
00558 PluginStatus 
00559 PluginDocImpl::request_marker_trees_impl(IPluginUnknown     *thiz, 
00560                                          const unsigned int uds_private_size )
00561 {
00562     LOGPRINTF("entry");
00563 
00564     PluginDocImpl *instance = g_instances_table.get_object(thiz);
00565 
00566     // Allocate collection object.
00567     PluginCollectionImpl *collection = new PluginCollectionImpl;
00568     collection->create<MarkerEntry *>();
00569 
00570     // Retrieve every page anchor.
00571     MarkerEntry * prev_entry = 0;
00572     unsigned int count = instance->document.page_count();
00573     for(unsigned int i = 1; i <= count; ++i)
00574     {
00575         std::string anchor;
00576         if (instance->document.get_anchor_of_page(i, anchor))
00577         {
00578             MarkerEntry * entry = marker_entry_new(uds_private_size);
00579             entry->type = MARKER_TOC;
00580             entry->anchor = new StringImpl(anchor);
00581             entry->text = new StringImpl(anchor);
00582             entry->uds_private_size = uds_private_size;
00583 
00584             if (i == 1)
00585             {
00586                 collection->take_data_ref<MarkerEntry *>().push_back(entry);
00587             }
00588             
00589             // Update entry.
00590             if (prev_entry)
00591             {
00592                 prev_entry->sibling = entry;
00593             }
00594             prev_entry = entry;
00595         }
00596     }
00597 
00598     // Notify all listeners.
00599     PluginEventAttrs event_data;
00600     event_data.marker_ready.result = static_cast<IPluginUnknown *>(collection);
00601     instance->listeners.broadcast(thiz, EVENT_MARKER_READY, &event_data);
00602     return PLUGIN_OK;
00603 }
00604 
00605 void PluginDocImpl::on_view_released(ViewPtr view)
00606 {
00607     LOGPRINTF("entry");
00608 
00609     ViewsIter iter = std::find(views.begin(), views.end(), view);
00610     if (iter != views.end())
00611     {
00612         delete *iter;
00613         views.erase(iter);
00614     }
00615 }
00616 
00617 void PluginDocImpl::remove_slots(void)
00618 {
00619     for (ViewsIter iter = views.begin(); iter != views.end(); ++iter)
00620     {
00621         if (*iter)
00622         {
00623             LOGPRINTF("Removing the slot of release signal of PluginViewImpl");
00624             (*iter)->release_signal.remove_slot(this, 
00625                     &PluginDocImpl::on_view_released);
00626         }
00627     }
00628 }
00629 
00630 }   // namespace images
00631 
00632 
Generated by  doxygen 1.6.2-20100208