static VALUE rpango_reorder_items_body(VALUE value) { struct rpango_reorder_items_args *args = (struct rpango_reorder_items_args *)value; long i; GList *result; for (i = 0; i < args->n; i++) args->result = g_list_append(args->result, RVAL2PANGOITEM(RARRAY_PTR(args->ary)[i])); result = pango_reorder_items(args->result); g_list_free(args->result); return GLIST2ARY2(result, PANGO_TYPE_ITEM); }
static void text_to_glyphs (cairo_t *cr, const gchar *text, cairo_glyph_t **glyphs, int *num_glyphs) { PangoAttribute *fallback_attr; PangoAttrList *attr_list; PangoContext *context; PangoDirection base_dir; GList *items; GList *visual_items; FT_Face ft_face; hb_font_t *hb_font; gdouble x = 0, y = 0; gint i; gdouble x_scale, y_scale; *num_glyphs = 0; *glyphs = NULL; base_dir = pango_find_base_dir (text, -1); cairo_scaled_font_t *cr_font = cairo_get_scaled_font (cr); ft_face = cairo_ft_scaled_font_lock_face (cr_font); hb_font = hb_ft_font_create (ft_face, NULL); cairo_surface_t *target = cairo_get_target (cr); cairo_surface_get_device_scale (target, &x_scale, &y_scale); /* We abuse pango itemazation to split text into script and direction * runs, since we use our fonts directly no through pango, we don't * bother changing the default font, but we disable font fallback as * pango will split runs at font change */ context = pango_cairo_create_context (cr); attr_list = pango_attr_list_new (); fallback_attr = pango_attr_fallback_new (FALSE); pango_attr_list_insert (attr_list, fallback_attr); items = pango_itemize_with_base_dir (context, base_dir, text, 0, strlen (text), attr_list, NULL); g_object_unref (context); pango_attr_list_unref (attr_list); /* reorder the items in the visual order */ visual_items = pango_reorder_items (items); while (visual_items) { PangoItem *item; PangoAnalysis analysis; hb_buffer_t *hb_buffer; hb_glyph_info_t *hb_glyphs; hb_glyph_position_t *hb_positions; gint n; item = visual_items->data; analysis = item->analysis; hb_buffer = hb_buffer_create (); hb_buffer_add_utf8 (hb_buffer, text, -1, item->offset, item->length); hb_buffer_set_script (hb_buffer, hb_glib_script_to_script (analysis.script)); hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis.language), -1)); hb_buffer_set_direction (hb_buffer, analysis.level % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); hb_shape (hb_font, hb_buffer, NULL, 0); n = hb_buffer_get_length (hb_buffer); hb_glyphs = hb_buffer_get_glyph_infos (hb_buffer, NULL); hb_positions = hb_buffer_get_glyph_positions (hb_buffer, NULL); *glyphs = g_renew (cairo_glyph_t, *glyphs, *num_glyphs + n); for (i = 0; i < n; i++) { (*glyphs)[*num_glyphs + i].index = hb_glyphs[i].codepoint; (*glyphs)[*num_glyphs + i].x = x + (hb_positions[i].x_offset / (64. * x_scale)); (*glyphs)[*num_glyphs + i].y = y - (hb_positions[i].y_offset / (64. * y_scale)); x += (hb_positions[i].x_advance / (64. * x_scale)); y -= (hb_positions[i].y_advance / (64. * y_scale)); } *num_glyphs += n; hb_buffer_destroy (hb_buffer); visual_items = visual_items->next; } g_list_free_full (visual_items, (GDestroyNotify) pango_item_free); g_list_free_full (items, (GDestroyNotify) pango_item_free); hb_font_destroy (hb_font); cairo_ft_scaled_font_unlock_face (cr_font); }