render_test.cpp

Go to the documentation of this file.
00001 /*
00002  * File Name: render_test.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 <stdio.h>
00028 #include <gtk/gtk.h>
00029 #include <gdk/gdkkeysyms.h>
00030 
00031 #include "text_config.h"
00032 #include "text_model.h"
00033 #include "text_view.h"
00034 
00035 using namespace text;
00036 
00037 unsigned char* bmp = NULL;
00038 GdkPixbuf *pix_buf = NULL;
00039 GtkWidget *top_level_window = NULL;
00040 GdkGC*     xor_gc  = NULL;
00041 
00042 int page_index  = 0;
00043 int total_pages = 0;
00044 int cur_width   = DEFAULT_SURFACE_WIDTH;
00045 int cur_height  = DEFAULT_SURFACE_HEIGHT;
00046 
00047 // Store the search result.
00048 std::vector<Range> result_ranges;
00049 std::vector<BoundingRectangle>  result_rects;
00050 
00051 void fill_pix_buf()
00052 {
00053     if (pix_buf != NULL)
00054     {
00055         g_object_unref(pix_buf);
00056         pix_buf = NULL;
00057     }
00058 
00059     pix_buf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
00060         FALSE,
00061         8,
00062         cur_width,
00063         cur_height);
00064 
00065     guchar *pixels = gdk_pixbuf_get_pixels(pix_buf);
00066     int rowstride = gdk_pixbuf_get_rowstride(pix_buf);
00067     int channels = gdk_pixbuf_get_n_channels(pix_buf);
00068 
00069     guchar *p = NULL;
00070     for (int y=0; y<cur_height; y++)
00071     {
00072         for (int x=0; x<cur_width; x++)
00073         {
00074             p = pixels + y*rowstride + x*channels;
00075             p[0] = p[1] = p[2] = bmp[y*cur_width+x];
00076         }
00077     }
00078 }
00079 
00080 static void destroy(GtkWidget *widget, gpointer data)
00081 {
00082     gtk_main_quit ();
00083 }
00084 
00085 static gboolean widget_event_handler(GtkWidget *widget, GdkEvent *event, gpointer user_data)
00086 {
00087     guint key_code;
00088     GdkEventConfigure *cfg_event = NULL;
00089     GdkEventButton *button_event = NULL;
00090     TextView  *view = (TextView *)user_data;
00091     const TextModel *model = view->get_model();
00092     const char *str = NULL;
00093     std::string tmp;
00094     ViewPosition view_pos;
00095     Position doc_pos;
00096     GtkWidget *dialog;
00097 
00098     switch (event->type)
00099     {
00100         case GDK_KEY_PRESS:
00101             key_code = ((GdkEventKey*)event)->keyval;
00102             if (key_code == GDK_Page_Up)
00103             {
00104                 if (page_index == 0)
00105                 {
00106                     return FALSE;
00107                 }
00108                 --page_index;
00109             }
00110             else if (key_code == GDK_Page_Down)
00111             {
00112                 if (page_index == total_pages-1)
00113                 {
00114                     return FALSE;
00115                 }
00116                 ++page_index;
00117             }
00118             else if (key_code == GDK_equal)
00119             {
00120                 // Increase font size
00121                 view->set_font_size(view->get_font_size()+1);
00122                 total_pages = view->get_page_count();
00123                 page_index = 0;
00124             }
00125             else if (key_code == GDK_minus)
00126             {
00127                 // Decrease font size
00128                 view->set_font_size(view->get_font_size()-1);
00129                 total_pages = view->get_page_count();
00130                 page_index = 0;
00131             }
00132 
00133             // Render specified page
00134             memset(bmp, 0xFF, cur_width * cur_height);
00135             view->render(bmp, page_index);
00136             fill_pix_buf();
00137             gdk_window_invalidate_rect(top_level_window->window, NULL, TRUE);
00138             break;
00139 
00140         case GDK_CONFIGURE:
00141             cfg_event = reinterpret_cast<GdkEventConfigure *>(event);
00142             if (cfg_event->width != cur_width || cfg_event->height != cur_height)
00143             {
00144                 cur_width  = cfg_event->width;
00145                 cur_height = cfg_event->height;
00146                 view->set_display_size(cur_width, cur_height);
00147                 total_pages = view->get_page_count();
00148 
00149                 // Render page 0
00150                 delete[] bmp;
00151                 bmp = new unsigned char[cur_width * cur_height];
00152                 memset(bmp, 0xFF, cur_width * cur_height);
00153                 view->render(bmp, page_index = 0);
00154                 fill_pix_buf();
00155                 gdk_window_invalidate_rect(top_level_window->window, NULL, TRUE);
00156             }
00157             break;
00158 
00159         case GDK_BUTTON_PRESS:
00160             // Record the position inside the widget.
00161             button_event = reinterpret_cast<GdkEventButton *>(event);
00162             view_pos.page_number = page_index;
00163             view_pos.x = static_cast<int>(button_event->x);
00164             view_pos.y = static_cast<int>(button_event->y);
00165             if (view->map_view_pos_to_doc_pos(view_pos, doc_pos))
00166             {
00167                 str = model->get_paragraph(doc_pos.paragraph)->c_str() + doc_pos.offset;
00168                 tmp = std::string(str, g_utf8_next_char(str)-str);
00169             }
00170             else
00171             {
00172                 tmp = "Nothing found!";
00173             }
00174 
00175             dialog = gtk_message_dialog_new(GTK_WINDOW(top_level_window),
00176                                             GTK_DIALOG_MODAL,
00177                                             GTK_MESSAGE_INFO,
00178                                             GTK_BUTTONS_OK,
00179                                             "%s", tmp.c_str());
00180             gtk_dialog_run(GTK_DIALOG(dialog));
00181             gtk_widget_destroy(dialog);
00182             break;
00183 
00184         default:
00185             break;
00186     }
00187     return TRUE;
00188 }
00189 
00190 static gboolean my_expose(GtkWidget *da, GdkEventExpose *event, gpointer data)
00191 {
00192     GdkGC *gc = gdk_gc_new(da->window);
00193     GdkPixbuf** pix_buf = (GdkPixbuf**)data;
00194     gdk_draw_pixbuf(da->window,
00195         gc,
00196         *pix_buf,
00197         0,
00198         0,
00199         0,
00200         0,
00201         -1,
00202         -1,
00203         GDK_RGB_DITHER_NORMAL,
00204         0,
00205         0);
00206 
00207     for (unsigned int i=0; i<result_rects.size(); i++)
00208     {
00209         if (result_rects[i].page_number == page_index)
00210         {
00211             gdk_draw_rectangle(da->window,
00212                 xor_gc,
00213                 TRUE,
00214                 result_rects[i].rect.x,
00215                 result_rects[i].rect.y,
00216                 result_rects[i].rect.width,
00217                 result_rects[i].rect.height);
00218         }
00219     }
00220 
00221     return TRUE;
00222 }
00223 
00224 int main(int argc, char* argv[])
00225 {
00226     gtk_init(&argc, &argv);
00227 
00228     if (argc != 2)
00229     {
00230         fprintf(stderr, "Usage: %s <file_name>.\n", argv[0]);
00231         return -1;
00232     }
00233 
00234     // Render the page 0
00235     TextModel model(argv[1]);
00236     model.open();
00237     model.read_text();
00238     // Dump model
00239     // model.dump();
00240 
00241     // Test search all function.
00242     // Set search criteria.
00243     char search_text[] = "¹ùÐ¥Ìì";
00244     Position from(0, 0);
00245     bool case_sensitive = true;
00246     bool match_whole_word = false;
00247 
00248     // Convert the search text to UTF-8 encoded string.
00249 #ifdef WIN32
00250     const char* in_p = search_text;
00251 #else
00252     char* in_p = search_text;
00253 #endif
00254     size_t in_bytes_left = strlen(search_text);
00255     char out_buf[1024];
00256     char *out_p = out_buf;
00257     size_t out_bytes_left = sizeof(out_buf);
00258 
00259     iconv_t conv = iconv_open("UTF-8", "GB2312");
00260     iconv(conv, &in_p, &in_bytes_left, &out_p, &out_bytes_left);
00261     iconv_close(conv);
00262 
00263     *out_p = 0;
00264     model.search_all(result_ranges, out_buf, case_sensitive, match_whole_word);
00265     // Test search all done.
00266 
00267     g_thread_init(NULL);
00268     TextView view(&model);
00269     view.initialize();
00270     view.paginate(NULL);
00271     total_pages = view.get_page_count();
00272 
00273     for (unsigned int i=0; i<result_ranges.size(); i++)
00274     {
00275         view.get_bounding_rectangles(result_rects, result_ranges[i]);
00276     }
00277 
00278     bmp = new unsigned char[cur_width * cur_height];
00279     memset(bmp, 0xFF, cur_width * cur_height);
00280     view.render(bmp, page_index);
00281     fill_pix_buf();
00282 
00283     // GTK stuff
00284     top_level_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00285     gtk_widget_set_size_request(top_level_window, cur_width, cur_height);
00286 
00287     gtk_widget_set_events (top_level_window,
00288                            GDK_EXPOSURE_MASK | GDK_BUTTON_MOTION_MASK |
00289                            GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
00290                            GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
00291     g_signal_connect(G_OBJECT(top_level_window), "destroy", G_CALLBACK(destroy), NULL);
00292     g_signal_connect(G_OBJECT(top_level_window), "expose_event", G_CALLBACK(my_expose), &pix_buf);
00293     gtk_signal_connect(GTK_OBJECT(top_level_window), "key_press_event", GTK_SIGNAL_FUNC(widget_event_handler), &view);
00294     gtk_signal_connect(GTK_OBJECT(top_level_window), "button_press_event", GTK_SIGNAL_FUNC(widget_event_handler), &view);
00295     gtk_signal_connect(GTK_OBJECT(top_level_window), "configure_event", GTK_SIGNAL_FUNC(widget_event_handler), &view);
00296 
00297     // Show all widget
00298     gtk_widget_show_all(top_level_window);
00299 
00300     // Create xor gc.
00301     xor_gc = gdk_gc_new(top_level_window->window);
00302     gdk_gc_set_function(xor_gc, GDK_XOR);
00303     GdkColor color = {0xffffffff, 0xffff, 0xffff, 0xffff};
00304     gdk_gc_set_foreground(xor_gc, &color);
00305 
00306     gtk_main();
00307 
00308     g_object_unref(pix_buf);
00309     return 0;
00310 }
00311 
Generated by  doxygen 1.6.2-20100208