#include <text_view.h>
Public Member Functions | |
TextView (TextModel *m) | |
Constructors and destructors. | |
~TextView () | |
void | initialize () |
Initialize pango related stuff. | |
void | deinitialize () |
Release pango related stuff. | |
void | set_controller (TextController *c) |
TextController * | get_controller () |
bool | paginate (const Position &start_pos) |
Pagination. | |
void | clear_pages () |
Reset the page table. | |
Position | render (unsigned char *bmp, const Position &start_pos) |
Render a page start with start_pos. | |
const TextModel * | get_model () const |
int | get_font_size () const |
Get font size. | |
bool | set_font_size (int font_size) |
Set font size. | |
const std::string & | get_font_family () const |
Get font family. | |
void | set_font_family (const std::string &font_family) |
Set font family. | |
void | get_display_size (int &width, int &height) |
Get output display size. | |
void | set_display_size (unsigned int width, unsigned int height) |
Set output display size. | |
unsigned int | get_DPI () |
Get dpi settings. | |
void | set_DPI (unsigned int dpi) |
Set dpi. | |
unsigned int | get_color_depth () |
Get color depth. | |
void | set_color_depth (unsigned int color_depth) |
Set color depth. | |
int | get_page_count () |
void | check_page_table (const Position &rendering_pos) |
Check if re-pagination is needed given by anchor to be rendered. | |
bool | get_anchor_by_page (unsigned int page_index, Position &pos) |
Get start anchor of specified page. | |
unsigned int | get_page_index_by_anchor (const Position &anchor) |
Get page index given by anchor. | |
Position | get_page_anchor_by_anchor (const Position &anchor) |
Get the start anchor of page which contains the specified anchor. | |
unsigned int | get_current_page_index () |
Get current page index. | |
bool | map_doc_pos_to_view_pos (const Position &page_anchor, const Position &doc_pos, ViewPosition &view_pos, bool trailing) |
Find view position given by document position (anchor). | |
bool | map_view_pos_to_doc_pos (const Position &page_anchor, const ViewPosition &view_pos, Position &doc_pos) |
Find doc position (anchor) given by view position. | |
bool | get_bounding_rectangles (const Position &page_anchor, std::vector< Rect > &bounding_rect, const Range &range) |
Get bounding rectangels given by range. | |
bool | calculate_next_page_pos (const Position &in_pos, Position &out_pos) |
Calculate start position of next page. | |
bool | calculate_prev_page_pos (const Position &in_pos, Position &out_pos) |
Calculate start position of previous page. | |
bool | need_repagination () |
Check if repagination is needed. | |
Data Fields | |
utils::Signal< unsigned int > | pagination_start_signal |
signals. | |
utils::Signal< unsigned int, unsigned int > | pagination_end_signal |
utils::Signal< unsigned int, const Position &, const Position &, void * > | render_done_signal |
Definition at line 49 of file text_view.h.
text::TextView::TextView | ( | TextModel * | m | ) |
Constructors and destructors.
Definition at line 39 of file text_view.cpp.
References DEFAULT_CHINESE_FONT, text::TextModel::get_encoding(), and initialize().
00040 : model(m), 00041 ctrl(0), 00042 font_family(DEFAULT_ASCII_FONT), 00043 font_size(DEFAULT_FONT_SIZE), 00044 display_width(DEFAULT_SURFACE_WIDTH), 00045 display_height(DEFAULT_SURFACE_HEIGHT), 00046 dpi(DEFAULT_DPI), 00047 color_depth(DEFAULT_COLOR_DEPTH), 00048 line_height(0), 00049 lines_per_page(0), 00050 left_margin(DEFAULT_LEFT_MARGIN), 00051 right_margin(DEFAULT_RIGHT_MARGIN), 00052 top_margin(DEFAULT_TOP_MARGIN), 00053 bottom_margin(DEFAULT_BOTTOM_MARGIN), 00054 client_width(display_width - left_margin - right_margin), 00055 client_height(display_height - top_margin - bottom_margin), 00056 pango_context(0), 00057 pango_mutex(0), 00058 font_hash_code(0), 00059 is_repagination_needed(false), 00060 blank_lines(0) 00061 { 00062 // Special handling for Chinese font. 00063 const char *enc = model->get_encoding().c_str(); 00064 #ifdef WIN32 00065 if (_stricmp(enc, "GB2312") == 0 || _stricmp(enc, "GBK") == 0) 00066 #else 00067 if (strcasecmp(enc, "GB2312") == 0 || strcasecmp(enc, "GBK") == 0) 00068 #endif 00069 { 00070 font_family = DEFAULT_CHINESE_FONT; 00071 } 00072 initialize(); 00073 }
text::TextView::~TextView | ( | ) |
Definition at line 75 of file text_view.cpp.
References deinitialize().
00076 { 00077 deinitialize(); 00078 }
Calculate start position of next page.
in_pos | start position of current page | |
out_pos | start position of next page |
Check if we can get next page anchor from page table.
Definition at line 341 of file text_view.cpp.
References text::TextModel::get_paragraph(), text::TextModel::get_paragraph_count(), text::Position::offset, text::Position::paragraph, and text::SafeDeque< T >::size().
Referenced by paginate().
00342 { 00343 /// Check if we can get next page anchor from page table. 00344 size_t page_count = pages.size(); 00345 for (unsigned int i=0; i<page_count; i++) 00346 { 00347 if (pages[i].start == in_pos) 00348 { 00349 out_pos = pages[i].end; 00350 return out_pos != Position(0, 0); 00351 } 00352 } 00353 00354 unsigned int start_paragraph = in_pos.paragraph; 00355 unsigned int start_offset = in_pos.offset; 00356 unsigned int total_lines = 0; 00357 00358 g_mutex_lock(pango_mutex); 00359 PangoLayout *layout = NULL; 00360 while (total_lines < lines_per_page) 00361 { 00362 if (start_paragraph >= model->get_paragraph_count()) 00363 { 00364 break; 00365 } 00366 00367 if (layout != NULL) 00368 { 00369 g_object_unref(layout); 00370 layout = NULL; 00371 } 00372 const std::string *str = model->get_paragraph(start_paragraph); 00373 layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00374 00375 int line_count = pango_layout_get_line_count(layout); 00376 int line_offset = 0; 00377 if (start_offset != 0) 00378 { 00379 // We are calculating from the second half part of a paragraph 00380 int x_pos; 00381 pango_layout_index_to_line_x(layout, start_offset, FALSE, &line_offset, &x_pos); 00382 line_count -= line_offset; 00383 } 00384 00385 if (total_lines + line_count < lines_per_page) 00386 { 00387 // We have enough space to load more paragraphs for current page 00388 total_lines += line_count; 00389 start_paragraph++; 00390 start_offset = 0; 00391 } 00392 else if (total_lines + line_count == lines_per_page) 00393 { 00394 if (++start_paragraph < model->get_paragraph_count()) 00395 { 00396 out_pos.paragraph = start_paragraph; 00397 out_pos.offset = 0; 00398 } 00399 break; 00400 } 00401 else 00402 { 00403 // The remained space is not enough for current paragraph 00404 PangoLayoutIter *iter = pango_layout_get_iter(layout); 00405 for (unsigned int i=0; i<lines_per_page-total_lines+line_offset; i++) 00406 { 00407 pango_layout_iter_next_line(iter); 00408 } 00409 00410 out_pos.offset = pango_layout_iter_get_index(iter); 00411 out_pos.paragraph = start_paragraph; 00412 pango_layout_iter_free(iter); 00413 break; 00414 } 00415 } 00416 00417 if (layout != NULL) 00418 { 00419 g_object_unref(layout); 00420 layout = NULL; 00421 } 00422 g_mutex_unlock(pango_mutex); 00423 return (start_paragraph < model->get_paragraph_count()); 00424 }
Calculate start position of previous page.
in_pos | start position of current page | |
out_pos | start position of previous page |
Definition at line 245 of file text_view.cpp.
References text::TextModel::get_paragraph(), text::Position::offset, text::Position::paragraph, and text::SafeDeque< T >::size().
Referenced by paginate().
00246 { 00247 // Check if we are already the first page. 00248 if (in_pos == Position(0, 0)) 00249 { 00250 return false; 00251 } 00252 00253 // Check if we can get next page anchor from page table. 00254 size_t page_count = pages.size(); 00255 for (unsigned int i=0; i<page_count; i++) 00256 { 00257 if (pages[i].end == in_pos) 00258 { 00259 out_pos = pages[i].start; 00260 return true; 00261 } 00262 } 00263 00264 g_mutex_lock(pango_mutex); 00265 unsigned int start_paragraph = in_pos.paragraph; 00266 unsigned int start_offset = in_pos.offset; 00267 PangoLayout *layout = NULL; 00268 if (start_offset == 0) 00269 { 00270 start_paragraph--; 00271 } 00272 00273 unsigned int total_lines = 0; 00274 while (total_lines < lines_per_page) 00275 { 00276 if (static_cast<int>(start_paragraph) < 0) 00277 { 00278 if (in_pos > Position(0, 0)) 00279 { 00280 blank_lines = lines_per_page - total_lines; 00281 } 00282 break; 00283 } 00284 00285 if (layout != NULL) 00286 { 00287 g_object_unref(layout); 00288 layout = NULL; 00289 } 00290 const std::string *str = model->get_paragraph(start_paragraph); 00291 layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00292 00293 int line_count = pango_layout_get_line_count(layout); 00294 if (start_offset != 0) 00295 { 00296 // We are calculating from the second half part of a paragraph 00297 int line_offset, x_pos; 00298 pango_layout_index_to_line_x(layout, start_offset, FALSE, &line_offset, &x_pos); 00299 line_count = line_offset; 00300 } 00301 00302 if (total_lines + line_count < lines_per_page) 00303 { 00304 // We have enough space to load more paragraphs for current page 00305 total_lines += line_count; 00306 start_paragraph--; 00307 start_offset = 0; 00308 } 00309 else if (total_lines + line_count == lines_per_page) 00310 { 00311 out_pos.paragraph = start_paragraph; 00312 out_pos.offset = 0; 00313 break; 00314 } 00315 else 00316 { 00317 // The remained space is not enough for current paragraph 00318 PangoLayoutIter *iter = pango_layout_get_iter(layout); 00319 unsigned int line_index = line_count - (lines_per_page - total_lines); 00320 for (unsigned int i=0; i<line_index; i++) 00321 { 00322 pango_layout_iter_next_line(iter); 00323 } 00324 00325 out_pos.paragraph = start_paragraph; 00326 out_pos.offset = pango_layout_iter_get_index(iter); 00327 pango_layout_iter_free(iter); 00328 break; 00329 } 00330 } 00331 00332 if (layout != NULL) 00333 { 00334 g_object_unref(layout); 00335 layout = NULL; 00336 } 00337 g_mutex_unlock(pango_mutex); 00338 return (static_cast<int>(start_paragraph) >= 0); 00339 }
void text::TextView::check_page_table | ( | const Position & | rendering_pos | ) |
Check if re-pagination is needed given by anchor to be rendered.
Definition at line 426 of file text_view.cpp.
References text::SafeDeque< T >::size().
Referenced by text::TextController::render(), and text::TextController::restart_pagination().
00427 { 00428 size_t page_count = pages.size(); 00429 for (unsigned int i=0; i<page_count; i++) 00430 { 00431 if (pages[i].start == rendering_pos) 00432 { 00433 return; 00434 } 00435 } 00436 00437 // Can't find page boundaries for specified anchor. 00438 // Re-pagination is needed. 00439 is_repagination_needed = true; 00440 }
void text::TextView::clear_pages | ( | ) | [inline] |
Reset the page table.
Definition at line 80 of file text_view.h.
References text::SafeDeque< T >::clear().
void text::TextView::deinitialize | ( | ) |
Release pango related stuff.
Definition at line 91 of file text_view.cpp.
Referenced by text::DeinitializationTask::execute(), and ~TextView().
00092 { 00093 // Release pango stuff 00094 pango_context_final(); 00095 g_mutex_free(pango_mutex); 00096 }
bool text::TextView::get_anchor_by_page | ( | unsigned int | page_index, | |
Position & | pos | |||
) |
Get start anchor of specified page.
Definition at line 181 of file text_view.cpp.
References text::SafeDeque< T >::size().
Referenced by text::TextController::render().
00182 { 00183 if (pages.size() == 0) 00184 { 00185 // Pagination hasn't been started yet. 00186 if (page_index == 0) 00187 { 00188 // We can render page 0 despite pagination is not ready. 00189 pos = Position(0, 0); 00190 return true; 00191 } 00192 else 00193 { 00194 return false; 00195 } 00196 } 00197 else 00198 { 00199 // Pagination starts, but maybe partial is successful. 00200 if (page_index >= pages.size()) 00201 { 00202 return false; 00203 } 00204 else 00205 { 00206 pos = pages[page_index].start; 00207 return true; 00208 } 00209 } 00210 }
bool text::TextView::get_bounding_rectangles | ( | const Position & | page_anchor, | |
std::vector< Rect > & | bounding_rect, | |||
const Range & | range | |||
) |
Get bounding rectangels given by range.
Definition at line 863 of file text_view.cpp.
References DEFAULT_LINE_SPACING, text::Range::end, map_doc_pos_to_view_pos(), text::Range::start, text::ViewPosition::x, and text::ViewPosition::y.
Referenced by text::PluginViewImpl::get_bounding_rectangles_from_range_impl(), and main().
00866 { 00867 // A flag indicating that the start position and end position of specified 00868 // range is in different pages. 00869 bool span_pages = false; 00870 ViewPosition view_pos_start, view_pos_end; 00871 00872 if (!map_doc_pos_to_view_pos(page_anchor, range.start, view_pos_start, false)) 00873 { 00874 // The range's start position is not inside the page which starts with 00875 // page_anchor. 00876 return false; 00877 } 00878 00879 if (!map_doc_pos_to_view_pos(page_anchor, range.end, view_pos_end, true)) 00880 { 00881 // The range's end position is not inside the page which starts with 00882 // page_anchor. 00883 span_pages = true; 00884 } 00885 00886 unsigned int line_height_with_spacing = line_height + DEFAULT_LINE_SPACING; 00887 00888 // Check if thhe start position and end position are in the same line. 00889 if (view_pos_start.y == view_pos_end.y) 00890 { 00891 // The start position and end position are in the same line. 00892 bounding_rect.push_back(Rect(view_pos_start.x, 00893 view_pos_start.y + DEFAULT_LINE_SPACING, 00894 view_pos_end.x - view_pos_start.x, 00895 line_height)); 00896 } 00897 else 00898 { 00899 // More lines. 00900 bounding_rect.push_back(Rect(view_pos_start.x, 00901 view_pos_start.y + DEFAULT_LINE_SPACING, 00902 display_width - view_pos_start.x - right_margin, 00903 line_height)); 00904 00905 for (unsigned int y_offset = view_pos_start.y+line_height_with_spacing; 00906 static_cast<int>(y_offset) < view_pos_end.y && 00907 y_offset < top_margin + line_height_with_spacing * lines_per_page; 00908 y_offset += line_height_with_spacing) 00909 { 00910 bounding_rect.push_back(Rect(left_margin, 00911 y_offset + DEFAULT_LINE_SPACING, 00912 client_width, 00913 line_height)); 00914 } 00915 00916 if (!span_pages) 00917 { 00918 bounding_rect.push_back(Rect(left_margin, 00919 view_pos_end.y + DEFAULT_LINE_SPACING, 00920 view_pos_end.x - left_margin, 00921 line_height)); 00922 } 00923 } 00924 00925 return true; 00926 }
unsigned int text::TextView::get_color_depth | ( | ) | [inline] |
TextController* text::TextView::get_controller | ( | ) | [inline] |
Definition at line 68 of file text_view.h.
unsigned int text::TextView::get_current_page_index | ( | ) |
Get current page index.
Definition at line 484 of file text_view.cpp.
References get_page_index_by_anchor().
Referenced by text::PaginationTask::execute(), and text::TextController::pause_pagination().
00485 { 00486 return get_page_index_by_anchor(rendering_pos); 00487 }
void text::TextView::get_display_size | ( | int & | width, | |
int & | height | |||
) | [inline] |
Get output display size.
Definition at line 116 of file text_view.h.
unsigned int text::TextView::get_DPI | ( | ) | [inline] |
const std::string& text::TextView::get_font_family | ( | ) | const [inline] |
int text::TextView::get_font_size | ( | ) | const [inline] |
Get font size.
Definition at line 95 of file text_view.h.
Referenced by widget_event_handler().
const TextModel* text::TextView::get_model | ( | ) | const [inline] |
Definition at line 89 of file text_view.h.
Referenced by widget_event_handler().
Get the start anchor of page which contains the specified anchor.
Check if we can get next page anchor from page table.
Definition at line 464 of file text_view.cpp.
References text::Position::paragraph, and text::SafeDeque< T >::size().
00465 { 00466 /// Check if we can get next page anchor from page table. 00467 size_t page_count = pages.size(); 00468 for (unsigned int i=0; i<page_count; i++) 00469 { 00470 if (pages[i].end > anchor && pages[i].start <= anchor) 00471 { 00472 return pages[i].start; 00473 } 00474 } 00475 00476 if (page_count>0 && pages[page_count-1].end == Position(0, 0)) 00477 { 00478 return pages[page_count-1].start; 00479 } 00480 00481 return Position(anchor.paragraph, 0); 00482 }
int text::TextView::get_page_count | ( | ) | [inline] |
Definition at line 149 of file text_view.h.
Referenced by text::PaginationTask::execute(), main(), text::TextController::pause_pagination(), and widget_event_handler().
00152 { 00153 if (!pages.empty() && pages.back().end == Position(0, 0)) 00154 { 00155 return static_cast<int>(pages.size()); 00156 }
unsigned int text::TextView::get_page_index_by_anchor | ( | const Position & | anchor | ) |
Get page index given by anchor.
Check if we can get next page anchor from page table.
Definition at line 442 of file text_view.cpp.
References text::SafeDeque< T >::size().
Referenced by get_current_page_index().
00443 { 00444 /// Check if we can get next page anchor from page table. 00445 size_t page_count = pages.size(); 00446 00447 // Always return 0 if pagination is not complete. 00448 if (page_count == 0 || pages[page_count-1].end != Position(0, 0)) 00449 { 00450 return 0; 00451 } 00452 00453 for (unsigned int i=0; i<page_count; i++) 00454 { 00455 if (pages[i].end > anchor && pages[i].start <= anchor) 00456 { 00457 return i; 00458 } 00459 } 00460 00461 return static_cast<unsigned int>(page_count-1); 00462 }
void text::TextView::initialize | ( | ) |
Initialize pango related stuff.
Definition at line 80 of file text_view.cpp.
Referenced by text::InitializationTask::execute(), main(), and TextView().
00081 { 00082 // Create mutex for synchronous access to pango stuff. 00083 pango_mutex = g_mutex_new(); 00084 00085 // Initialize pango context. 00086 pango_context_init(); 00087 00088 calculate_lines_per_page(); 00089 }
bool text::TextView::map_doc_pos_to_view_pos | ( | const Position & | page_anchor, | |
const Position & | doc_pos, | |||
ViewPosition & | view_pos, | |||
bool | trailing | |||
) |
Find view position given by document position (anchor).
page_anchor | Start anchor of current page. | |
doc_pos | Input anchor. | |
view_pos | Output view position (x,y). |
Definition at line 687 of file text_view.cpp.
References DEFAULT_LINE_SPACING, text::TextModel::get_paragraph(), text::Position::offset, text::Position::paragraph, text::ViewPosition::x, and text::ViewPosition::y.
Referenced by get_bounding_rectangles().
00691 { 00692 if (doc_pos < page_anchor) 00693 { 00694 return false; 00695 } 00696 00697 unsigned int line_height_with_spacing = line_height + DEFAULT_LINE_SPACING; 00698 00699 // Calculate the line offset and x offset inside layout corresponding to doc pos. 00700 const std::string *str = model->get_paragraph(doc_pos.paragraph); 00701 PangoLayout *layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00702 00703 int line_offset_pos, x_offset_pos; 00704 pango_layout_index_to_line_x(layout, doc_pos.offset, trailing, &line_offset_pos, &x_offset_pos); 00705 00706 unsigned int total_lines = 0; 00707 unsigned int start_paragraph = page_anchor.paragraph; 00708 unsigned int start_offset = page_anchor.offset; 00709 if (start_paragraph == 0 && start_offset == 0) 00710 { 00711 total_lines += blank_lines; 00712 } 00713 00714 if (start_offset != 0) 00715 { 00716 // The page does not start with a new paragraph. 00717 if (layout != NULL) 00718 { 00719 g_object_unref(layout); 00720 layout = NULL; 00721 } 00722 const std::string *str = model->get_paragraph(start_paragraph); 00723 layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00724 00725 int line_offset_start, x_pos; 00726 pango_layout_index_to_line_x(layout, start_offset, FALSE, &line_offset_start, &x_pos); 00727 00728 if (doc_pos.paragraph == start_paragraph) 00729 { 00730 total_lines = line_offset_pos - line_offset_start; 00731 goto MapEnd; 00732 } 00733 else 00734 { 00735 total_lines = pango_layout_get_line_count(layout) - line_offset_start; 00736 start_paragraph++; 00737 } 00738 } 00739 00740 for (; start_paragraph != doc_pos.paragraph; start_paragraph++) 00741 { 00742 if (layout != NULL) 00743 { 00744 g_object_unref(layout); 00745 layout = NULL; 00746 } 00747 const std::string *str = model->get_paragraph(start_paragraph); 00748 layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00749 00750 total_lines += pango_layout_get_line_count(layout); 00751 } 00752 00753 total_lines += line_offset_pos; 00754 00755 MapEnd: 00756 if (layout != NULL) 00757 { 00758 g_object_unref(layout); 00759 layout = NULL; 00760 } 00761 if (total_lines < lines_per_page) 00762 { 00763 view_pos.x = PANGO_PIXELS(x_offset_pos) + left_margin; 00764 view_pos.y = top_margin + line_height_with_spacing * total_lines; 00765 return true; 00766 } 00767 else 00768 { 00769 return false; 00770 } 00771 }
bool text::TextView::map_view_pos_to_doc_pos | ( | const Position & | page_anchor, | |
const ViewPosition & | view_pos, | |||
Position & | doc_pos | |||
) |
Find doc position (anchor) given by view position.
page_anchor | Start anchor of current page. | |
view_pos | Input view position. | |
doc_pos | Output anchor. |
Definition at line 773 of file text_view.cpp.
References DEFAULT_LINE_SPACING, text::TextModel::get_paragraph(), text::TextModel::get_paragraph_count(), text::Position::offset, text::Position::paragraph, text::ViewPosition::x, and text::ViewPosition::y.
Referenced by text::PluginViewImpl::get_anchor_from_coordinates_impl(), and widget_event_handler().
00776 { 00777 int x_offset_pos = view_pos.x - left_margin; 00778 int y_offset_pos = view_pos.y - top_margin; 00779 00780 unsigned int start_paragraph = page_anchor.paragraph; 00781 unsigned int start_offset = page_anchor.offset; 00782 unsigned int line_height_with_spacing = line_height + DEFAULT_LINE_SPACING; 00783 00784 if (start_paragraph == 0 && start_offset == 0) 00785 { 00786 y_offset_pos -= blank_lines * line_height_with_spacing; 00787 } 00788 00789 PangoLayout *layout = NULL; 00790 bool found = false; 00791 00792 if (start_offset != 0) 00793 { 00794 const std::string *str = model->get_paragraph(start_paragraph); 00795 layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00796 00797 int line_offset_start, x_pos; 00798 pango_layout_index_to_line_x(layout, start_offset, FALSE, &line_offset_start, &x_pos); 00799 00800 int lines_left = pango_layout_get_line_count(layout) - line_offset_start; 00801 if (static_cast<int>(lines_left * line_height_with_spacing) > y_offset_pos) 00802 { 00803 // The corresponding doc pos is inside this paragraph. 00804 doc_pos.paragraph = start_paragraph; 00805 00806 // Calculate offset. 00807 int bytes_index, trailing; 00808 pango_layout_xy_to_index(layout, 00809 x_offset_pos * PANGO_SCALE, 00810 (line_offset_start*line_height_with_spacing+y_offset_pos) * PANGO_SCALE, 00811 &bytes_index, &trailing); 00812 doc_pos.offset = bytes_index; 00813 found = true; 00814 goto MapEnd; 00815 } 00816 else 00817 { 00818 y_offset_pos -= lines_left * line_height_with_spacing; 00819 start_paragraph++; 00820 } 00821 } 00822 00823 for (; start_paragraph < model->get_paragraph_count(); start_paragraph++) 00824 { 00825 if (layout != NULL) 00826 { 00827 g_object_unref(layout); 00828 layout = NULL; 00829 } 00830 const std::string *str = model->get_paragraph(start_paragraph); 00831 layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00832 00833 int line_count = pango_layout_get_line_count(layout); 00834 if (static_cast<int>(line_count * line_height_with_spacing) > y_offset_pos) 00835 { 00836 break; 00837 } 00838 else 00839 { 00840 y_offset_pos -= line_count * line_height_with_spacing; 00841 } 00842 } 00843 00844 if (start_paragraph == model->get_paragraph_count()) 00845 { 00846 goto MapEnd; 00847 } 00848 00849 int bytes_index, trailing; 00850 pango_layout_xy_to_index(layout, x_offset_pos * PANGO_SCALE, y_offset_pos * PANGO_SCALE, &bytes_index, &trailing); 00851 doc_pos.paragraph = start_paragraph; 00852 doc_pos.offset = bytes_index; 00853 found = true; 00854 00855 MapEnd: 00856 if (layout) 00857 { 00858 g_object_unref(layout); 00859 } 00860 return found; 00861 }
bool text::TextView::need_repagination | ( | ) | [inline] |
bool text::TextView::paginate | ( | const Position & | start_pos | ) |
Pagination.
start_pos | If page table is empty, then this parameter tells the view from which position the pagination starts. |
Definition at line 139 of file text_view.cpp.
References text::SafeDeque< T >::back(), calculate_next_page_pos(), calculate_prev_page_pos(), text::Range::end, text::SafeDeque< T >::front(), text::SafeDeque< T >::push_back(), text::SafeDeque< T >::push_front(), text::SafeDeque< T >::size(), and text::Range::start.
Referenced by text::PaginationTask::execute(), and main().
00140 { 00141 00142 Position in_pos(0, 0); 00143 Position out_pos; 00144 bool forward = true; 00145 00146 size_t page_count = pages.size(); 00147 if (page_count == 0) 00148 { 00149 in_pos = start_pos; 00150 } 00151 else if (pages.back().end != Position(0, 0)) 00152 { 00153 // The forward pagination is not finished yet. 00154 in_pos = pages.back().end; 00155 } 00156 else if (pages.front().start != Position(0, 0)) 00157 { 00158 // The backward pagination is not finished yet. 00159 in_pos = pages.front().start; 00160 forward = false; 00161 } 00162 else 00163 { 00164 // The pagination is complete. 00165 return true; 00166 } 00167 00168 if (forward) 00169 { 00170 calculate_next_page_pos(in_pos, out_pos); 00171 pages.push_back(PageInfo(in_pos, out_pos)); 00172 } 00173 else 00174 { 00175 calculate_prev_page_pos(in_pos, out_pos); 00176 pages.push_front(PageInfo(out_pos, in_pos)); 00177 } 00178 return false; 00179 }
Render a page start with start_pos.
Definition at line 489 of file text_view.cpp.
References text::SafeDeque< T >::clear(), DEFAULT_LINE_SPACING, text::TextModel::get_paragraph(), text::Position::offset, text::TextController::paginate(), text::Position::paragraph, and render_single_line().
Referenced by text::RenderTask::execute(), main(), and widget_event_handler().
00490 { 00491 if (is_repagination_needed) 00492 { 00493 pages.clear(); 00494 blank_lines = 0; 00495 ctrl->paginate(start_pos, true /* Send start notification */); 00496 is_repagination_needed = false; 00497 } 00498 00499 g_mutex_lock(pango_mutex); 00500 unsigned int start_paragraph = start_pos.paragraph; 00501 unsigned int start_offset = start_pos.offset; 00502 PangoLayout *layout = NULL; 00503 00504 rendering_pos = start_pos; 00505 00506 unsigned int total_lines = 0; 00507 if (start_pos == Position(0, 0)) 00508 { 00509 total_lines = blank_lines; 00510 } 00511 int y_offset = (line_height + DEFAULT_LINE_SPACING)*total_lines*PANGO_SCALE; 00512 00513 // If we don't start with a new paragraph, then we must render the 00514 // remained part of current paragraph first. 00515 if (start_offset != 0) 00516 { 00517 if (layout != NULL) 00518 { 00519 g_object_unref(layout); 00520 layout = NULL; 00521 } 00522 const std::string *str = model->get_paragraph(start_paragraph); 00523 layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00524 00525 PangoLayoutIter *iter = pango_layout_get_iter(layout); 00526 00527 int line_offset, x_pos; 00528 pango_layout_index_to_line_x(layout, start_offset, FALSE, &line_offset, &x_pos); 00529 y_offset = (line_height + DEFAULT_LINE_SPACING)*line_offset*PANGO_SCALE; 00530 00531 int baseline = 0; 00532 for (int i=0; i<line_offset; i++) 00533 { 00534 pango_layout_iter_next_line(iter); 00535 } 00536 00537 do 00538 { 00539 baseline = pango_layout_iter_get_baseline(iter) - y_offset; 00540 PangoLayoutLine *pango_line = pango_layout_iter_get_line_readonly(iter); 00541 render_single_line(bmp, 00542 pango_line, 00543 font_hash_code, 00544 left_margin * PANGO_SCALE, 00545 baseline+top_margin*PANGO_SCALE, 00546 (display_width+3)/4*4); 00547 if (++total_lines == lines_per_page) 00548 { 00549 // Calculate the offset of the rightmost character. 00550 int index, trailing; 00551 pango_layout_line_x_to_index(pango_line, client_width - 1, &index, &trailing); 00552 start_offset = index; 00553 pango_layout_iter_free(iter); 00554 goto RenderEnd; 00555 } 00556 } while (pango_layout_iter_next_line(iter)); 00557 00558 // Release iter since we finish with it. 00559 pango_layout_iter_free(iter); 00560 00561 start_paragraph++; 00562 y_offset = (line_height + DEFAULT_LINE_SPACING)*total_lines*PANGO_SCALE; 00563 } 00564 00565 // Render the remained paragraphs 00566 while (start_paragraph < model->get_paragraph_count()) 00567 { 00568 // Render current paragraph 00569 if (layout != NULL) 00570 { 00571 g_object_unref(layout); 00572 layout = NULL; 00573 } 00574 const std::string *str = model->get_paragraph(start_paragraph); 00575 layout = create_layout(str->c_str(), static_cast<int>(str->size())); 00576 00577 PangoLayoutIter *iter = pango_layout_get_iter(layout); 00578 int baseline = 0; 00579 do 00580 { 00581 baseline = pango_layout_iter_get_baseline(iter) + y_offset; 00582 PangoLayoutLine *pango_line = pango_layout_iter_get_line_readonly(iter); 00583 render_single_line(bmp, 00584 pango_line, 00585 font_hash_code, 00586 left_margin * PANGO_SCALE, 00587 baseline+top_margin*PANGO_SCALE, 00588 (display_width+3)/4*4); 00589 if (++total_lines == lines_per_page) 00590 { 00591 int index, trailing; 00592 pango_layout_line_x_to_index(pango_line, client_width - 1, &index, &trailing); 00593 start_offset = index; 00594 pango_layout_iter_free(iter); 00595 goto RenderEnd; 00596 } 00597 } while (pango_layout_iter_next_line(iter)); 00598 pango_layout_iter_free(iter); 00599 00600 start_paragraph++; 00601 y_offset = (line_height + DEFAULT_LINE_SPACING)*total_lines*PANGO_SCALE; 00602 } 00603 00604 RenderEnd: 00605 // Release pango layout generated by render. 00606 if (layout != NULL) 00607 { 00608 g_object_unref(layout); 00609 layout = NULL; 00610 } 00611 g_mutex_unlock(pango_mutex); 00612 00613 return Position(start_paragraph, start_offset); 00614 }
void text::TextView::set_color_depth | ( | unsigned int | color_depth | ) | [inline] |
void text::TextView::set_controller | ( | TextController * | c | ) | [inline] |
Definition at line 63 of file text_view.h.
Referenced by text::TextController::TextController().
void text::TextView::set_display_size | ( | unsigned int | width, | |
unsigned int | height | |||
) |
Set output display size.
Definition at line 658 of file text_view.cpp.
References LOGPRINTF.
Referenced by widget_event_handler().
00659 { 00660 LOGPRINTF("\n\nwidth=%d, height=%d\n\n", width, height); 00661 if (width == display_width && height == display_height) 00662 { 00663 return; 00664 } 00665 00666 g_mutex_lock(pango_mutex); 00667 if (height != display_height) 00668 { 00669 // Display height changed. The current layout can be reused. 00670 // But we need to re-calculate lines per page. 00671 display_height = height; 00672 client_height = display_height - top_margin - bottom_margin; 00673 calculate_lines_per_page(); 00674 } 00675 00676 if (width != display_width) 00677 { 00678 display_width = width; 00679 client_width = display_width - left_margin - right_margin; 00680 } 00681 00682 // Change the repagination flag to true. 00683 is_repagination_needed = true; 00684 g_mutex_unlock(pango_mutex); 00685 }
void text::TextView::set_DPI | ( | unsigned int | dpi | ) | [inline] |
void text::TextView::set_font_family | ( | const std::string & | font_family | ) | [inline] |
bool text::TextView::set_font_size | ( | int | font_size | ) |
Set font size.
Definition at line 616 of file text_view.cpp.
References FontCache::clear(), FontCache::instance(), and make_hash_code().
Referenced by widget_event_handler().
00617 { 00618 if (this->font_size == font_size) 00619 { 00620 return true; 00621 } 00622 00623 this->font_size = font_size; 00624 00625 g_mutex_lock(pango_mutex); 00626 00627 // Release font caches in font map. 00628 PangoFT2FontMap* font_map = PANGO_FT2_FONT_MAP(pango_context_get_font_map(pango_context)); 00629 pango_ft2_font_map_substitute_changed(font_map); 00630 00631 // Create new pango font description and copy it to pango context. 00632 PangoFontDescription* font_desc = pango_font_description_new(); 00633 pango_font_description_set_family(font_desc, font_family.c_str()); 00634 pango_font_description_set_size(font_desc, font_size * PANGO_SCALE); 00635 pango_context_set_font_description(pango_context, font_desc); 00636 00637 char *desc_str = pango_font_description_to_string(font_desc); 00638 font_hash_code = make_hash_code(desc_str, 00639 static_cast<unsigned int>(strlen(desc_str))); 00640 g_free(desc_str); 00641 00642 // Since pango_context has copied the font description from us, 00643 // our font description can be freed safely. 00644 pango_font_description_free(font_desc); 00645 calculate_lines_per_page(); 00646 00647 // Change the repagination flag to true. 00648 is_repagination_needed = true; 00649 00650 // Clear font cache. 00651 FontCache& font_cache = FontCache::instance(); 00652 font_cache.clear(); 00653 00654 g_mutex_unlock(pango_mutex); 00655 return true; 00656 }
utils::Signal<unsigned int, unsigned int> text::TextView::pagination_end_signal |
Definition at line 222 of file text_view.h.
Referenced by text::PaginationTask::execute(), main(), text::TextController::paginate(), text::TextController::pause_pagination(), and text::PluginViewImpl::PluginViewImpl().
utils::Signal<unsigned int> text::TextView::pagination_start_signal |
signals.
Definition at line 221 of file text_view.h.
Referenced by text::PaginationTask::execute(), main(), and text::PluginViewImpl::PluginViewImpl().
utils::Signal<unsigned int, const Position&, const Position&, void *> text::TextView::render_done_signal |
Definition at line 226 of file text_view.h.
Referenced by text::RenderTask::execute(), main(), and text::PluginViewImpl::PluginViewImpl().