Пример #1
0
static VALUE
rpango_find_base_dir(VALUE self, VALUE text)
{
    StringValue(text);
    return GENUM2RVAL(pango_find_base_dir(RSTRING_PTR(text), RSTRING_LEN(text)), 
                      PANGO_TYPE_DIRECTION);
}
Пример #2
0
const gchar *
common_get_direction_mark (gchar *text)
{
	PangoDirection		pango_direction = PANGO_DIRECTION_NEUTRAL;
	GtkTextDirection	gtk_direction;
	
	if (text)
		pango_direction = pango_find_base_dir (text, -1);
		
	switch (pango_direction) {
		case PANGO_DIRECTION_LTR:
			gtk_direction = GTK_TEXT_DIR_LTR;
			break;
		case PANGO_DIRECTION_RTL:
			gtk_direction = GTK_TEXT_DIR_RTL;
			break;
		default:
			gtk_direction = gtk_widget_get_default_direction ();
			break;
	}

	switch (gtk_direction) {
		case GTK_TEXT_DIR_RTL: 
			return "\342\200\217"; /* U+200F RIGHT-TO-LEFT MARK */
		case GTK_TEXT_DIR_LTR: 
			return "\342\200\216"; /* U+200E LEFT-TO-RIGHT MARK */
		default:
			return "";
	}
}
static void
get_artist_album_templates (const char *artist,
                            const char *album,
                            const char **artist_template,
                            const char **album_template)
{
    PangoDirection tag_dir;
    PangoDirection template_dir;

    /* Translators: by Artist */
    *artist_template = _("by <i>%s</i>");
    /* Translators: from Album */
    *album_template = _("from <i>%s</i>");

    /* find the direction (left-to-right or right-to-left) of the
     * track's tags and the localized templates
     */
    if (artist != NULL && artist[0] != '\0') {
        tag_dir = pango_find_base_dir (artist, -1);
        template_dir = pango_find_base_dir (*artist_template, -1);
    } else if (album != NULL && album[0] != '\0') {
        tag_dir = pango_find_base_dir (album, -1);
        template_dir = pango_find_base_dir (*album_template, -1);
    } else {
        return;
    }

    /* if the track's tags and the localized templates have a different
     * direction, switch to direction-neutral templates in order to improve
     * display.
     * text can have a neutral direction, this condition only applies when
     * both directions are defined and they are conflicting.
     * https://bugzilla.gnome.org/show_bug.cgi?id=609767
     */
    if (((tag_dir == PANGO_DIRECTION_LTR) && (template_dir == PANGO_DIRECTION_RTL)) ||
            ((tag_dir == PANGO_DIRECTION_RTL) && (template_dir == PANGO_DIRECTION_LTR))) {
        /* these strings should not be localized, they must be
         * locale-neutral and direction-neutral
         */
        *artist_template = "<i>%s</i>";
        *album_template = "/ <i>%s</i>";
    }
}
Пример #4
0
/*
 * Returns a string that can be used for the HTML "dir" attribute.
 * Direction is taken from a string, regardless of any language tags.
 */
const gchar *
common_get_text_direction (const gchar *text)
{
	PangoDirection pango_direction = PANGO_DIRECTION_NEUTRAL;
	
	if (text)
		pango_direction = pango_find_base_dir (text, -1);

	if (pango_direction == PANGO_DIRECTION_RTL)
		return ("rtl");
	else
		return ("ltr");
}
Пример #5
0
static gfloat
item_list_title_alignment (gchar *title)
{
	if (!title || strlen(title) == 0)
		return 0.;

	/* debug5 (DEBUG_HTML, "title ***%s*** first bytes %02hhx%02hhx%02hhx pango %d",
		title, title[0], title[1], title[2], pango_find_base_dir (title, -1)); */
	int txt_direction = pango_find_base_dir (title, -1);
  	int app_direction = gtk_widget_get_default_direction ();
	if ((txt_direction == PANGO_DIRECTION_LTR &&
	     app_direction == GTK_TEXT_DIR_LTR) ||
	    (txt_direction == PANGO_DIRECTION_RTL &&
	     app_direction == GTK_TEXT_DIR_RTL))
		return 0.; /* same direction, regular ("left") alignment */
	else
		return 1.;
}
Пример #6
0
static VALUE
rg_s_find_base_dir(G_GNUC_UNUSED VALUE self, VALUE text)
{
    StringValue(text);
    return PANGODIRECTION2RVAL(pango_find_base_dir(RSTRING_PTR(text), RSTRING_LEN(text)));
}
Пример #7
0
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);
}
Пример #8
0
static PyObject *
pango_GetLayoutClusterPos(PyObject *self, PyObject *args) {

	int i, len, w, h, index, prev_index;
	int ltr_flag, rtl_flag;
	double baseline, x, y, width, height, char_width, dx, dy;
	void *LayoutObj;
	PangoLayout *layout;
	PangoLayoutIter *iter;
	PangoLayoutIter *cluster_iter;
	PangoRectangle rect, cluster_rect;
	PangoDirection dir;
	PyObject *ret;
	PyObject *layout_data;
	PyObject *cluster_data;
	PyObject *cluster_range;
	PyObject *cluster_index_data;
	PyObject *cluster_index_range;
	PyObject *glyph_data;

	if (!PyArg_ParseTuple(args, "Oi", &LayoutObj, &len)) {
		return NULL;
	}

	layout = PyCObject_AsVoidPtr(LayoutObj);

	pango_layout_get_size(layout, &w, &h);
	dx = 0.0;
	if (pango_layout_get_alignment(layout) == PANGO_ALIGN_CENTER) {
		dx = -0.5 * ((double) w) / PANGO_SCALE;
	} else if (pango_layout_get_alignment(layout) == PANGO_ALIGN_RIGHT) {
		dx = -1.0 * ((double) w) / PANGO_SCALE;
	}


	ret = PyTuple_New(5);
	layout_data = PyList_New(0);
	cluster_data = PyList_New(0);
	cluster_index_data = PyList_New(0);

	PyTuple_SetItem(ret, 0, layout_data);
	PyTuple_SetItem(ret, 1, cluster_data);
	PyTuple_SetItem(ret, 2, cluster_index_data);

	iter = pango_layout_get_iter(layout);
	cluster_iter = pango_layout_get_iter(layout);

	prev_index = -1;
	rtl_flag = 0;
	ltr_flag = 0;

	dy = ((double) pango_layout_iter_get_baseline(iter)) / PANGO_SCALE;

	for (i = 0; i < len; i++) {
		glyph_data = PyTuple_New(6);

		//Processing EOL

		while (pango_layout_iter_get_baseline(cluster_iter) !=
				pango_layout_iter_get_baseline(iter)) {

			pango_layout_iter_get_char_extents(iter, &rect);

			x = ((double) rect.x) / PANGO_SCALE + dx;
			PyTuple_SetItem(glyph_data, 0, PyFloat_FromDouble(x));

			y = -1.0 * ((double) rect.y) / PANGO_SCALE + dy;
			PyTuple_SetItem(glyph_data, 1, PyFloat_FromDouble(y));

			width = ((double) rect.width) / PANGO_SCALE;
			PyTuple_SetItem(glyph_data, 2, PyFloat_FromDouble(width));

			height = ((double) rect.height) / PANGO_SCALE;
			PyTuple_SetItem(glyph_data, 3, PyFloat_FromDouble(height));

			baseline = -1.0 * ((double) pango_layout_iter_get_baseline(iter))
					/ PANGO_SCALE + dy;
			PyTuple_SetItem(glyph_data, 4, PyFloat_FromDouble(baseline));

			//index processing
			index=pango_layout_iter_get_index(iter);
			prev_index = index;
			PyTuple_SetItem(glyph_data, 5, PyInt_FromLong(index));

			PyList_Append(layout_data, glyph_data);

			pango_layout_iter_next_char(iter);
			i++;
			glyph_data = PyTuple_New(6);
		}

		pango_layout_iter_get_char_extents(iter, &rect);
		pango_layout_iter_get_cluster_extents(cluster_iter, NULL, &cluster_rect);

		//Processing cluster data
		//Layout_data: (x,y,width,height,base_line,byte_index)

		x = ((double) cluster_rect.x) / PANGO_SCALE + dx;
		PyTuple_SetItem(glyph_data, 0, PyFloat_FromDouble(x));

		y = -1.0 * ((double) cluster_rect.y) / PANGO_SCALE + dy;
		PyTuple_SetItem(glyph_data, 1, PyFloat_FromDouble(y));

		width = ((double) cluster_rect.width) / PANGO_SCALE;
		PyTuple_SetItem(glyph_data, 2, PyFloat_FromDouble(width));

		height = ((double) cluster_rect.height) / PANGO_SCALE;
		PyTuple_SetItem(glyph_data, 3, PyFloat_FromDouble(height));

		baseline = -1.0 * ((double) pango_layout_iter_get_baseline(cluster_iter))
				/ PANGO_SCALE + dy;
		PyTuple_SetItem(glyph_data, 4, PyFloat_FromDouble(baseline));

		//index processing
		index=pango_layout_iter_get_index(iter);
		if (prev_index != -1){
			if(index < prev_index){
				rtl_flag=1;
			}else if(index > prev_index){
				ltr_flag=1;
			}
		}
		prev_index = index;
		PyTuple_SetItem(glyph_data, 5, PyInt_FromLong(index));

		PyList_Append(layout_data, glyph_data);

		//Iterating over chars to next cluster

		if(cluster_rect.width > rect.width){
			char_width = rect.width;
			cluster_range = PyTuple_New(2);
			cluster_index_range = PyTuple_New(2);
			PyTuple_SetItem(cluster_range, 0, PyInt_FromLong(i));
			PyTuple_SetItem(cluster_index_range, 0,
					PyInt_FromLong(pango_layout_iter_get_index(iter)));
			while(cluster_rect.width > char_width){
				pango_layout_iter_next_char(iter);
				pango_layout_iter_get_char_extents(iter, &rect);
				char_width = char_width + rect.width;
				i++;
			}
			PyTuple_SetItem(cluster_range, 1, PyInt_FromLong(i + 1));
			PyTuple_SetItem(cluster_index_range, 1,
					PyInt_FromLong(pango_layout_iter_get_index(iter)));
			PyList_Append(cluster_data, cluster_range);
			PyList_Append(cluster_index_data, cluster_index_range);
		}

		pango_layout_iter_next_char(iter);
		pango_layout_iter_next_cluster(cluster_iter);
	}

	pango_layout_iter_free(iter);
	pango_layout_iter_free(cluster_iter);

	if(rtl_flag + ltr_flag == 2){
		PyTuple_SetItem(ret, 3, PyBool_FromLong(1));
	}else{
		PyTuple_SetItem(ret, 3, PyBool_FromLong(0));
	}

	dir = pango_find_base_dir(pango_layout_get_text(layout),-1);
	if(dir == PANGO_DIRECTION_RTL) {
		PyTuple_SetItem(ret, 4, PyBool_FromLong(1));
	} else {
		PyTuple_SetItem(ret, 4, PyBool_FromLong(0));
	}

	return ret;
}