diff options
author | Owen Taylor <otaylor@src.gnome.org> | 2000-01-13 04:12:07 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2000-01-13 04:12:07 +0000 |
commit | 282fb5fc9f9d01c4d933a6eb6bee6ae9f0d512c7 (patch) | |
tree | 0b19c69692a2fe52a1b33d5e27c97b26a64417e3 /pango/mapping.c | |
parent | 66ae87f9fc45f5f564acf5014e9bd1341d052958 (diff) | |
download | pango-282fb5fc9f9d01c4d933a6eb6bee6ae9f0d512c7.tar.gz |
Initial revision
Diffstat (limited to 'pango/mapping.c')
-rw-r--r-- | pango/mapping.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/pango/mapping.c b/pango/mapping.c new file mode 100644 index 00000000..bd0cb3de --- /dev/null +++ b/pango/mapping.c @@ -0,0 +1,275 @@ +/* Pango + * itemize.c: + * + * Copyright (C) 1999 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* The initial implementation here is script independent, + * but it might actually need to be virtualized into the + * rendering modules. Otherwise, we probably will end up + * enforcing unnatural cursor behavior for some languages. + * + * The only distinction that Uniscript makes is whether + * cursor positioning is allowed within clusters or not. + */ + +#include <pango.h> +#include <unicode.h> + +/** + * pango_cp_to_x: + * @text: the text for the run + * @length: the number of bytes (not characters) in @text. + * @analysis: the analysis information return from pango_itemize() + * @glyphs: the glyphs return from pango_shape() + * @char_pos: the character position + * @trailing: whether we should compute the result for the beginning + * or end of the character (or cluster - the decision + * for which may be script dependent). + * @x_pos: location to store result + * + * Converts from character position to x position. (X position + * is measured from the left edge of the run) + */ + +void +pango_cp_to_x (gchar *text, + gint length, + PangoAnalysis *analysis, + PangoGlyphString *glyphs, + gint char_pos, + gboolean trailing, + gint *x_pos) +{ + gint i; + gint start_xpos = 0; + gint end_xpos = 0; + gint width = 0; + + gint start_char = -1; + gint end_char = -1; + + g_return_if_fail (glyphs != NULL); + g_return_if_fail (length >= 0); + g_return_if_fail (length == 0 || text != NULL); + + if (!x_pos) /* Allow the user to do the useless */ + return; + + if (glyphs->num_glyphs == 0) + { + *x_pos = 0; + return; + } + + /* Calculate the starting and ending character positions + * and x positions for the cluster + */ + if (analysis->level % 2) /* Right to left */ + { + for (i = glyphs->num_glyphs - 1; i >= 0; i--) + width += glyphs->geometry[i].width; + + for (i = glyphs->num_glyphs - 1; i >= 0; i--) + { + if (glyphs->log_clusters[i] > char_pos) + { + end_char = glyphs->log_clusters[i]; + end_xpos = width; + break; + } + + if (start_char == -1 || glyphs->log_clusters[i] != start_char) + { + start_char = glyphs->log_clusters[i]; + start_xpos = width; + } + + width -= glyphs->geometry[i].width; + } + } + else /* Left to right */ + { + for (i = 0; i < glyphs->num_glyphs; i++) + { + if (glyphs->log_clusters[i] > char_pos) + { + end_char = glyphs->log_clusters[i]; + end_xpos = width; + break; + } + + if (start_char == -1 || glyphs->log_clusters[i] != start_char) + { + start_char = glyphs->log_clusters[i]; + start_xpos = width; + } + + width += glyphs->geometry[i].width; + } + } + + /* We need the character index of one past the end of the + * string, and so we have to recalculate the entire length + * of the string... + */ + if (end_char == -1) + { + end_char = unicode_strlen (text, length); + end_xpos = (analysis->level % 2) ? 0 : width; + } + + /* Now interpolate the result. For South Asian languages + * we actually shouldn't iterpolate + */ + + if (trailing) + char_pos += 1; + + *x_pos = (((double)(end_char - char_pos)) * start_xpos + + ((double)(char_pos - start_char)) * end_xpos) / + (end_char - start_char); +} + +/** + * pango_x_to_cp: + * @text: the text for the run + * @length: the number of bytes (not characters) in text. + * @analysis: the analysis information return from pango_itemize() + * @glyphs: the glyphs return from pango_shape() + * @x_pos: location to store the returned x character position + * @char_pos: location to store calculated character position. + * @trailing: location to store a integer indicating where + * in the cluster the user clicked. If the script + * allows positioning within the cluster, it is either + * 0 or 1; otherwise it is either 0 or the number + * of characters in the cluster. In either case + * 0 represents the trailing edge of the cluster. + * + * Converts from x position to x character. (X position + * is measured from the left edge of the run) + */ +void +pango_x_to_cp (gchar *text, + gint length, + PangoAnalysis *analysis, + PangoGlyphString *glyphs, + gint x_pos, + gint *char_pos, + gint *trailing) +{ + gint i; + gint start_xpos = 0; + gint end_xpos = 0; + gint width = 0; + + gint start_char = -1; + gint end_char = -1; + + gboolean found = FALSE; + + /* Find the cluster containing the position */ + + width = 0; + + if (analysis->level % 2) /* Right to left */ + { + for (i = glyphs->num_glyphs - 1; i >= 0; i--) + width += glyphs->geometry[i].width; + + for (i = glyphs->num_glyphs - 1; i >= 0; i--) + { + if (start_char == -1 || glyphs->log_clusters[i] != start_char) + { + if (found) + { + end_char = glyphs->log_clusters[i]; + end_xpos = width; + break; + } + else + { + start_char = glyphs->log_clusters[i]; + start_xpos = width; + } + } + + width -= glyphs->geometry[i].width; + + if (width <= x_pos && x_pos < width + glyphs->geometry[i].width) + found = TRUE; + } + } + else /* Left to right */ + { + for (i = 0; i < glyphs->num_glyphs; i++) + { + if (start_char == -1 || glyphs->log_clusters[i] != start_char) + { + if (found) + { + end_char = glyphs->log_clusters[i]; + end_xpos = width; + break; + } + else + { + start_char = glyphs->log_clusters[i]; + start_xpos = width; + } + } + + if (width <= x_pos && x_pos < width + glyphs->geometry[i].width) + found = TRUE; + + width += glyphs->geometry[i].width; + } + } + + /* We need the character index of one past the end of the + * string, and so we have to recalculate the entire length + * of the string... + */ + if (end_char == -1) + { + end_char = unicode_strlen (text, length); + end_xpos = (analysis->level % 2) ? 0 : width; + } + + if (start_xpos == end_xpos) + { + if (char_pos) + *char_pos = start_char; + if (trailing) + trailing = 0; + } + else + { + double cp = (((double)(end_xpos - x_pos)) * start_char + + ((double)(x_pos - start_xpos)) * end_char) / + (end_xpos - start_xpos); + + if (char_pos) + *char_pos = (int)cp; + if (trailing) + *trailing = (cp - (int)cp) > 0.5 ? 1 : 0; + } +} + + + |