void Gtk::ArcballWidget::stext(int size, GLfloat x, GLfloat y, GLfloat z,const char *str)const{ Glib::RefPtr<Pango::Context> widget_context = const_cast<Gtk::ArcballWidget*>(this)->get_pango_context(); Pango::FontDescription font_desc=widget_context->get_font_description(); Pango::Rectangle un,logical_rect; GLfloat text_w, text_h; GLfloat tangent_h; /* Font */ font_desc.set_size(size * PANGO_SCALE); if(!ft2_context)ft2_context=Glib::wrap(pango_ft2_get_context(72,72)); ft2_context->set_font_description(font_desc); /* Text layout */ Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(ft2_context); layout->set_width(PANGO_SCALE * get_width()); layout->set_alignment(Pango::ALIGN_CENTER); layout->set_text(str); /*** OpenGL BEGIN ***/ layout->get_extents(un,logical_rect); text_w = PANGO_PIXELS (logical_rect.get_width()); text_h = PANGO_PIXELS (logical_rect.get_height()); tangent_h = 3 * tan (20 * G_PI / 180.0); tangent_h /= get_height(); glRasterPos3f (x,y,z); /* Render text */ gl_pango_ft2_render_layout (layout); }
int PrintNotesNoteAddin::compute_footer_height(const Glib::RefPtr<Gtk::PrintContext> & context) { Glib::RefPtr<Pango::Layout> layout = create_layout_for_timestamp(context); Pango::Rectangle ink_rect; Pango::Rectangle logical_rect; layout->get_extents(ink_rect, logical_rect); return pango_units_to_double(ink_rect.get_height()) + cm_to_pixel(0.5, context->get_dpi_y()); }
void PrintNotesNoteAddin::on_begin_print(const Glib::RefPtr<Gtk::PrintContext>& context) { m_timestamp_footer = create_layout_for_timestamp(context); // Create and initialize the page margins m_margin_top = cm_to_pixel (1.5, context->get_dpi_y()); m_margin_left = cm_to_pixel (1, context->get_dpi_x()); m_margin_right = cm_to_pixel (1, context->get_dpi_x()); m_margin_bottom = 0; double max_height = pango_units_from_double(context->get_height() - m_margin_top - m_margin_bottom - compute_footer_height(context)); DBG_OUT("margins = %d %d %d %d", m_margin_top, m_margin_left, m_margin_right, m_margin_bottom); m_page_breaks.clear(); Gtk::TextIter position; Gtk::TextIter end_iter; get_buffer()->get_bounds (position, end_iter); double page_height = 0; bool done = position.compare (end_iter) >= 0; while (!done) { Gtk::TextIter line_end = position; if (!line_end.ends_line ()) { line_end.forward_to_line_end (); } int paragraph_number = position.get_line(); int indentation = 0; Glib::RefPtr<Pango::Layout> layout = create_layout_for_paragraph( context, position, line_end, indentation); Pango::Rectangle ink_rect; Pango::Rectangle logical_rect; for(int line_in_paragraph = 0; line_in_paragraph < layout->get_line_count(); line_in_paragraph++) { Glib::RefPtr<Pango::LayoutLine> line = layout->get_line(line_in_paragraph); line->get_extents (ink_rect, logical_rect); if ((page_height + logical_rect.get_height()) >= max_height) { PageBreak(paragraph_number, line_in_paragraph); m_page_breaks.push_back (PageBreak(paragraph_number, line_in_paragraph)); page_height = 0; } page_height += logical_rect.get_height(); } position.forward_line (); done = position.compare (end_iter) >= 0; } m_print_op->set_n_pages(m_page_breaks.size() + 1); }
void ViewDrawingArea::draw_buffer() { #ifdef DEBUG std::cerr << "VA->val:"<<_vadj->get_value() <<" VA->upper:"<<_vadj->get_upper() << std::endl << std::flush; #endif Feed *feed = AppContext::get().get_feed(); if (feed == NULL) return; if (AppContext::get().get_display_type() == FULL) { render_full_article(); return; } // Dimensions of drawing area Gtk::Allocation allocation = get_allocation(); const int width = allocation.get_width(); const int height = allocation.get_height(); // First determine start item Cairo::RefPtr<Cairo::Context> cr = _pixmap->create_cairo_context(); #ifdef DEBUG /// This code was meant to investigate the 500ms delay with pango /// at start of rendering. if (!_layout_prepared) { Glib::Timer sw; sw.start(); Glib::RefPtr<Pango::Layout> pl = Pango::Layout::create (cr); const char *fonts[] = {"Sans 10", "Sans 14"}; for (unsigned i = 0; i < sizeof(fonts)/sizeof(const char*); ++i) { Pango::FontDescription fdesc (fonts[i]); pl->set_font_description (fdesc); pl->set_width (10 * Pango::SCALE); // force line break pl->set_markup ("<b>Show Us Your Freaky Geek Costumes</b>\nHitting the streets in a scary, tech-themed outfit this Halloween? We want to see it. Find out how your Sergey Brin costume (or is it David Duchovny?) could be featured on Wired News. test\n test"); Pango::Rectangle irect, lrect; pl->get_extents (irect, lrect); } _layout_prepared = true; sw.stop(); unsigned long l; sw.elapsed(l); std::cerr << "Time spent rendering: " << l << " us" << std::endl << std::flush; } #endif const item_list_t items = feed->get_items(); item_list_t::const_iterator start_item; const int n_items = items.size(); double y = 0.0; if (n_items == 0) start_item = items.end(); else { // Set start_item and h int start = static_cast<int> (_vadj->get_value()); double h = 0.0; if (_vadj->get_value() > 0 && _vadj->get_value() == _vadj->get_upper()) { // This will give a blank page when pulling the handle // full down. While unusual, it might make sense with // an ever-growing newslist. y = 0.0; start_item = items.end(); } else { start_item = items.begin(); for (int i = 0; i < start; ++i) ++start_item; if (start < 0) start = 0; double prop = _vadj->get_value() - start; if (prop > 0.0) { (*start_item)->make_display_unit(); ItemDisplayUnit *du = (*start_item)->get_display_unit(); du->layout (cr); h = du->get_height(); } y = - h * prop; #ifdef DEBUG std::cerr << "prop:"<<prop <<" y:"<<y << std::endl << std::flush; #endif } } // clip to the area indicated by the expose event so that we only redraw // the portion of the window that needs to be redrawn cr->reset_clip(); cr->rectangle (0.0, 0.0, width, height); cr->clip(); // Black on white cr->set_source_rgb (1.0, 1.0, 1.0); cr->paint(); cr->set_source_rgb (0.0, 0.0, 0.0); // Render text item_list_t::const_iterator it = start_item; _top_item = *start_item; _topitem_y = y; int count = 0; for (; it != items.end() && y < height; ++it, ++count) { (*it)->make_display_unit(); ItemDisplayUnit *du = (*it)->get_display_unit(); du->render (cr, 0, y); y += du->get_height(); } cr->show_page(); // Scrollbar settings can now be specified _vadj->set_upper (n_items); //_vadj->set_page_size (count - 1 + ); _vadj->set_step_increment (1); _vadj->set_page_increment (count); _vadj->changed(); }
static void gl_pango_ft2_render_layout (Glib::RefPtr<Pango::Layout> layout) { Pango::Rectangle unu,logical_rect; FT_Bitmap bitmap; GLvoid *pixels; guint32 *p; GLfloat color[4]; guint32 rgb; GLfloat a; guint8 *row, *row_end; int i; layout->get_extents(unu,logical_rect); if (logical_rect.get_width() == 0 || logical_rect.get_height() == 0) return; bitmap.rows = PANGO_PIXELS (logical_rect.get_height()); bitmap.width = PANGO_PIXELS (logical_rect.get_width()); bitmap.pitch = bitmap.width; bitmap.buffer = (unsigned char*)g_malloc (bitmap.rows * bitmap.width); bitmap.num_grays = 256; bitmap.pixel_mode = ft_pixel_mode_grays; memset (bitmap.buffer, 0, bitmap.rows * bitmap.width); pango_ft2_render_layout (&bitmap, layout->gobj(), PANGO_PIXELS (-logical_rect.get_x()), 0); pixels = g_malloc (bitmap.rows * bitmap.width * 4); p = (guint32 *) pixels; glGetFloatv (GL_CURRENT_COLOR, color); #if !defined(GL_VERSION_1_2) && G_BYTE_ORDER == G_LITTLE_ENDIAN rgb = ((guint32) (color[0] * 255.0)) | (((guint32) (color[1] * 255.0)) << 8) | (((guint32) (color[2] * 255.0)) << 16); #else rgb = (((guint32) (color[0] * 255.0)) << 24) | (((guint32) (color[1] * 255.0)) << 16) | (((guint32) (color[2] * 255.0)) << 8); #endif a = color[3]; row = bitmap.buffer + bitmap.rows * bitmap.width; /* past-the-end */ row_end = bitmap.buffer; /* beginning */ if (a == 1.0) { do { row -= bitmap.width; for (i = 0; i < bitmap.width; i++) #if !defined(GL_VERSION_1_2) && G_BYTE_ORDER == G_LITTLE_ENDIAN *p++ = rgb | (((guint32) row[i]) << 24); #else *p++ = rgb | ((guint32) row[i]); #endif } while (row != row_end); } else { do { row -= bitmap.width; for (i = 0; i < bitmap.width; i++) #if !defined(GL_VERSION_1_2) && G_BYTE_ORDER == G_LITTLE_ENDIAN *p++ = rgb | (((guint32) (a * row[i])) << 24); #else *p++ = rgb | ((guint32) (a * row[i])); #endif } while (row != row_end); } glPixelStorei (GL_UNPACK_ALIGNMENT, 4); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #if !defined(GL_VERSION_1_2) glDrawPixels (bitmap.width, bitmap.rows, GL_RGBA, GL_UNSIGNED_BYTE, pixels); #else glDrawPixels (bitmap.width, bitmap.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, pixels); #endif glDisable (GL_BLEND); g_free (bitmap.buffer); g_free (pixels); }
void PrintNotesNoteAddin::on_draw_page(const Glib::RefPtr<Gtk::PrintContext>& context, guint page_nr) { Cairo::RefPtr<Cairo::Context> cr = context->get_cairo_context(); cr->move_to (m_margin_left, m_margin_top); PageBreak start; if (page_nr != 0) { start = m_page_breaks [page_nr - 1]; } PageBreak end(-1, -1); if (m_page_breaks.size() > page_nr) { end = m_page_breaks [page_nr]; } Gtk::TextIter position; Gtk::TextIter end_iter; get_buffer()->get_bounds (position, end_iter); // Fast-forward to the starting line while (position.get_line() < start.get_paragraph()) { position.forward_line (); } bool done = position.compare (end_iter) >= 0; while (!done) { Gtk::TextIter line_end = position; if (!line_end.ends_line ()) { line_end.forward_to_line_end (); } int paragraph_number = position.get_line(); int indentation; { Glib::RefPtr<Pango::Layout> layout = create_layout_for_paragraph (context,position, line_end, indentation); for(int line_number = 0; line_number < layout->get_line_count() && !done; line_number++) { // Skip the lines up to the starting line in the // first paragraph on this page if ((paragraph_number == start.get_paragraph()) && (line_number < start.get_line())) { continue; } // Break as soon as we hit the end line if ((paragraph_number == end.get_paragraph()) && (line_number == end.get_line())) { done = true; break; } Glib::RefPtr<Pango::LayoutLine> line = layout->get_line(line_number); Pango::Rectangle ink_rect; Pango::Rectangle logical_rect; line->get_extents (ink_rect, logical_rect); double curX, curY; cr->get_current_point(curX, curY); cr->move_to (m_margin_left + indentation, curY); int line_height = pango_units_to_double(logical_rect.get_height()); double x, y; x = m_margin_left + indentation; cr->get_current_point(curX, curY); y = curY + line_height; pango_cairo_show_layout_line(cr->cobj(), line->gobj()); cr->move_to(x, y); } } position.forward_line (); done = done || (position.compare (end_iter) >= 0); } // Print the footer int total_height = context->get_height(); int total_width = context->get_width(); int footer_height = 0; double footer_anchor_x, footer_anchor_y; { Glib::RefPtr<Pango::Layout> pages_footer = create_layout_for_pagenumbers (context, page_nr + 1, m_page_breaks.size() + 1); Pango::Rectangle ink_footer_rect; Pango::Rectangle logical_footer_rect; pages_footer->get_extents(ink_footer_rect, logical_footer_rect); footer_anchor_x = cm_to_pixel(0.5, context->get_dpi_x()); footer_anchor_y = total_height - m_margin_bottom; footer_height = pango_units_to_double(logical_footer_rect.get_height()); cr->move_to(total_width - pango_units_to_double(logical_footer_rect.get_width()) - cm_to_pixel(0.5, context->get_dpi_x()), footer_anchor_y); pango_cairo_show_layout_line(cr->cobj(), (pages_footer->get_line(0))->gobj()); } cr->move_to(footer_anchor_x, footer_anchor_y); pango_cairo_show_layout_line(cr->cobj(), (m_timestamp_footer->get_line(0))->gobj()); cr->move_to(cm_to_pixel(0.5, context->get_dpi_x()), total_height - m_margin_bottom - footer_height); cr->line_to(total_width - cm_to_pixel(0.5, context->get_dpi_x()), total_height - m_margin_bottom - footer_height); cr->stroke(); }