bool PangoFontInfo::GetSpacingProperties(const string& utf8_char, int* x_bearing, int* x_advance) const { // Convert to equivalent PangoFont structure PangoFont* font = ToPangoFont(); // Find the glyph index in the font for the supplied utf8 character. int total_advance = 0; int min_bearing = 0; // Handle multi-unicode strings by reporting the left-most position of the // x-bearing, and right-most position of the x-advance if the string were to // be rendered. const UNICHAR::const_iterator it_begin = UNICHAR::begin(utf8_char.c_str(), utf8_char.length()); const UNICHAR::const_iterator it_end = UNICHAR::end(utf8_char.c_str(), utf8_char.length()); for (UNICHAR::const_iterator it = it_begin; it != it_end; ++it) { PangoGlyph glyph_index = pango_fc_font_get_glyph( reinterpret_cast<PangoFcFont*>(font), *it); if (!glyph_index) { // Glyph for given unicode character doesn't exist in font. return false; } // Find the ink glyph extents for the glyph PangoRectangle ink_rect, logical_rect; pango_font_get_glyph_extents(font, glyph_index, &ink_rect, &logical_rect); pango_extents_to_pixels(&ink_rect, NULL); pango_extents_to_pixels(&logical_rect, NULL); int bearing = total_advance + PANGO_LBEARING(ink_rect); if (it == it_begin || bearing < min_bearing) { min_bearing = bearing; } total_advance += PANGO_RBEARING(logical_rect); } *x_bearing = min_bearing; *x_advance = total_advance; return true; }
void render_glyph( cairo_t* cr, PangoFontDescription* font_desc, PangoFont* font, const guint code_point, const size_t cell_x, const size_t cell_y, const size_t cell_size, const double tex_size, const int ascent, const int descent, std::ostream& bgm_out ) { PangoLayout *layout = pango_cairo_create_layout(cr); char str[6] = {'\0'}; size_t len = 0; oglplus::aux::ConvertCodePointToUTF8(code_point, str, len); pango_layout_set_font_description(layout, font_desc); pango_layout_set_text(layout, str, len); const int baseline = pango_layout_get_baseline(layout); const double inv_ps = 1.0 / double(PANGO_SCALE); const double font_size = ascent+descent; PangoRectangle ink_rect, log_rect; pango_layout_get_extents( layout, &ink_rect, &log_rect ); // code point number bgm_out << code_point << std::endl; // hex representation of the number bgm_out << std::hex << "0x" << code_point << std::dec << std::endl; // the utf-8 sequence bgm_out << "'" << str << "'" << std::endl; // // vertex[0] logical rectangle metrics // // Left bearing (x) bgm_out << PANGO_LBEARING(log_rect)/font_size << std::endl; // Right bearing (x+width) bgm_out << PANGO_RBEARING(log_rect)/font_size << std::endl; // Ascent bgm_out << (baseline-log_rect.y)/font_size << std::endl; // Descent bgm_out << (log_rect.height+log_rect.y-baseline)/font_size << std::endl; // // vertex[1] ink rectangle metrics // // Left bearing (x) bgm_out << PANGO_LBEARING(ink_rect)/font_size << std::endl; // Right bearing (x+width) bgm_out << PANGO_RBEARING(ink_rect)/font_size << std::endl; // Ascent bgm_out << (baseline-ink_rect.y)/font_size << std::endl; // Descent bgm_out << (ink_rect.y+ink_rect.height-baseline)/font_size << std::endl; // // vertex[2] texture coordinates // // Origin X bgm_out << (cell_x*cell_size+ink_rect.x*inv_ps)/tex_size << std::endl; // Origin Y bgm_out << 1.0-(cell_y*cell_size+baseline*inv_ps)/tex_size << std::endl; // Width bgm_out << ((ink_rect.width)*inv_ps)/tex_size << std::endl; // Height bgm_out << ((ink_rect.height)*inv_ps)/tex_size << std::endl; // separating newline bgm_out << std::endl; cairo_new_path(cr); cairo_move_to(cr, cell_x*cell_size, cell_y*cell_size); cairo_set_line_width(cr, 0.5); pango_cairo_update_layout(cr, layout); pango_cairo_layout_path(cr, layout); cairo_fill(cr); g_object_unref(layout); }
static void draw_string(DiaRenderer *self, const char *text, Point *pos, Alignment alignment, Color *color) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); int len = strlen(text); DIAG_NOTE(g_message("draw_string(%d) %f,%f %s", len, pos->x, pos->y, text)); if (len < 1) return; /* shouldn't this be handled by Dia's core ? */ cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); #ifdef HAVE_PANGOCAIRO_H cairo_save (renderer->cr); /* alignment calculation done by pangocairo? */ pango_layout_set_alignment (renderer->layout, alignment == ALIGN_CENTER ? PANGO_ALIGN_CENTER : alignment == ALIGN_RIGHT ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT); pango_layout_set_text (renderer->layout, text, len); { PangoLayoutIter *iter = pango_layout_get_iter(renderer->layout); int bline = pango_layout_iter_get_baseline(iter); /* although we give the alignment above we need to adjust the start point */ PangoRectangle extents; int shift; pango_layout_iter_get_line_extents (iter, NULL, &extents); shift = alignment == ALIGN_CENTER ? PANGO_RBEARING(extents)/2 : alignment == ALIGN_RIGHT ? PANGO_RBEARING(extents) : 0; cairo_move_to (renderer->cr, pos->x - (double)shift / PANGO_SCALE, pos->y - (double)bline / PANGO_SCALE); pango_layout_iter_free (iter); } /* does this hide bug #341481? */ pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout)); pango_layout_context_changed (renderer->layout); pango_cairo_show_layout (renderer->cr, renderer->layout); cairo_restore (renderer->cr); #else /* using the 'toy API' */ { cairo_text_extents_t extents; double x = 0, y = 0; cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_text_extents (renderer->cr, text, &extents); y = pos->y; /* ?? */ switch (alignment) { case ALIGN_LEFT: x = pos->x; break; case ALIGN_CENTER: x = pos->x - extents.width / 2 + +extents.x_bearing; break; case ALIGN_RIGHT: x = pos->x - extents.width + extents.x_bearing; break; } cairo_move_to (renderer->cr, x, y); cairo_show_text (renderer->cr, text); } #endif DIAG_STATE(renderer->cr) }