📄 pango-utils.c
字号:
* @mirrored_ch: location to store the mirrored character * * If @ch has the Unicode mirrored property and there is another Unicode * character that typically has a glyph that is the mirror image of @ch's * glyph, puts that character in the address pointed to by @mirrored_ch. * * Use g_unichar_get_mirror_char() instead; the docs for that function * provide full details. * * Return value: %TRUE if @ch has a mirrored character and @mirrored_ch is * filled in, %FALSE otherwise **/gbooleanpango_get_mirror_char (gunichar ch, gunichar *mirrored_ch){ return g_unichar_get_mirror_char (ch, mirrored_ch);}static guintalias_hash (struct PangoAlias *alias){ return g_str_hash (alias->alias);}static gbooleanalias_equal (struct PangoAlias *alias1, struct PangoAlias *alias2){ return g_str_equal (alias1->alias, alias2->alias);}static voidalias_free (struct PangoAlias *alias){ int i; g_free (alias->alias); for (i = 0; i < alias->n_families; i++) g_free (alias->families[i]); g_free (alias->families); g_slice_free (struct PangoAlias, alias);}static voidhandle_alias_line (GString *line_buffer, char **errstring){ GString *tmp_buffer1; GString *tmp_buffer2; const char *pos; struct PangoAlias alias_key; struct PangoAlias *alias; gboolean append = FALSE; char **new_families; int n_new; int i; tmp_buffer1 = g_string_new (NULL); tmp_buffer2 = g_string_new (NULL); pos = line_buffer->str; if (!pango_skip_space (&pos)) return; if (!pango_scan_string (&pos, tmp_buffer1) || !pango_skip_space (&pos)) { *errstring = g_strdup ("Line is not of the form KEY=VALUE or KEY+=VALUE"); goto error; } if (*pos == '+') { append = TRUE; pos++; } if (*(pos++) != '=') { *errstring = g_strdup ("Line is not of the form KEY=VALUE or KEY+=VALUE"); goto error; } if (!pango_scan_string (&pos, tmp_buffer2)) { *errstring = g_strdup ("Error parsing value string"); goto error; } if (pango_skip_space (&pos)) { *errstring = g_strdup ("Junk after value string"); goto error; } alias_key.alias = g_ascii_strdown (tmp_buffer1->str, -1); /* Remove any existing values */ alias = g_hash_table_lookup (pango_aliases_ht, &alias_key); if (!alias) { alias = g_slice_new0 (struct PangoAlias); alias->alias = alias_key.alias; g_hash_table_insert (pango_aliases_ht, alias, alias); } else g_free (alias_key.alias); new_families = g_strsplit (tmp_buffer2->str, ",", -1); n_new = 0; while (new_families[n_new]) n_new++; if (alias->families && append) { alias->families = g_realloc (alias->families, sizeof (char *) *(n_new + alias->n_families)); for (i = 0; i < n_new; i++) alias->families[alias->n_families + i] = new_families[i]; g_free (new_families); alias->n_families += n_new; } else { for (i = 0; i < alias->n_families; i++) g_free (alias->families[i]); g_free (alias->families); alias->families = new_families; alias->n_families = n_new; } error: g_string_free (tmp_buffer1, TRUE); g_string_free (tmp_buffer2, TRUE);}#ifdef G_OS_WIN32static const char *builtin_aliases[] = { "courier = \"courier new\"", "\"segoe ui\" = \"segoe ui,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", "tahoma = \"tahoma,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", /* It sucks to use the same GulimChe, MS Gothic, Sylfaen, Kartika, * Latha, Mangal and Raavi fonts for all three of sans, serif and * mono, but it isn't like there would be much choice. For most * non-Latin scripts that Windows includes any font at all for, it * has ony one. One solution is to install the free DejaVu fonts * that are popular on Linux. They are listed here first. */ "sans = \"dejavu sans,tahoma,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", "sans-serif = \"dejavu sans,tahoma,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", "serif = \"dejavu serif,georgia,angsana new,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", "mono = \"dejavu sans mono,courier new,courier monothai,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", "monospace = \"dejavu sans mono,courier new,courier monothai,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\""};static voidread_builtin_aliases (void){ GString *line_buffer; char *errstring = NULL; int line; line_buffer = g_string_new (NULL); for (line = 0; line < G_N_ELEMENTS (builtin_aliases) && errstring == NULL; line++) { g_string_assign (line_buffer, builtin_aliases[line]); handle_alias_line (line_buffer, &errstring); } if (errstring) { g_error ("error in built-in aliases:%d: %s\n", line, errstring); g_free (errstring); } g_string_free (line_buffer, TRUE);}#endifstatic voidread_alias_file (const char *filename){ FILE *file; GString *line_buffer; char *errstring = NULL; int line = 0; file = g_fopen (filename, "r"); if (!file) return; line_buffer = g_string_new (NULL); while (pango_read_line (file, line_buffer) && errstring == NULL) { line++; handle_alias_line (line_buffer, &errstring); } if (errstring == NULL && ferror (file)) errstring = g_strdup (g_strerror(errno)); if (errstring) { g_warning ("error reading alias file: %s:%d: %s\n", filename, line, errstring); g_free (errstring); } g_string_free (line_buffer, TRUE); fclose (file);}static voidpango_load_aliases (void){ char *filename; const char *home; pango_aliases_ht = g_hash_table_new_full ((GHashFunc)alias_hash, (GEqualFunc)alias_equal, (GDestroyNotify)alias_free, NULL);#ifdef G_OS_WIN32 read_builtin_aliases ();#endif filename = g_strconcat (pango_get_sysconf_subdirectory (), G_DIR_SEPARATOR_S "pango.aliases", NULL); read_alias_file (filename); g_free (filename); home = g_get_home_dir (); if (home && *home) { filename = g_strconcat (home, G_DIR_SEPARATOR_S ".pango.aliases", NULL); read_alias_file (filename); g_free (filename); }}/** * pango_lookup_aliases: * @fontname: an ascii string * @families: will be set to an array of font family names. * this array is owned by pango and should not be freed. * @n_families: will be set to the length of the @families array. * * Look up all user defined aliases for the alias @fontname. * The resulting font family names will be stored in @families, * and the number of families in @n_families. **/voidpango_lookup_aliases (const char *fontname, char ***families, int *n_families){ struct PangoAlias alias_key; struct PangoAlias *alias; if (pango_aliases_ht == NULL) pango_load_aliases (); alias_key.alias = g_ascii_strdown (fontname, -1); alias = g_hash_table_lookup (pango_aliases_ht, &alias_key); g_free (alias_key.alias); if (alias) { *families = alias->families; *n_families = alias->n_families; } else { *families = NULL; *n_families = 0; }}/** * pango_find_base_dir: * @text: the text to process * @length: length of @text in bytes (may be -1 if @text is nul-terminated) * * Searches a string the first character that has a strong * direction, according to the Unicode bidirectional algorithm. * * Return value: The direction corresponding to the first strong character. * If no such character is found, then %PANGO_DIRECTION_NEUTRAL is returned. * * Since: 1.4 */PangoDirectionpango_find_base_dir (const gchar *text, gint length){ PangoDirection dir = PANGO_DIRECTION_NEUTRAL; const gchar *p; g_return_val_if_fail (text != NULL || length == 0, PANGO_DIRECTION_NEUTRAL); p = text; while ((length < 0 || p < text + length) && *p) { gunichar wc = g_utf8_get_char (p); dir = pango_unichar_direction (wc); if (dir != PANGO_DIRECTION_NEUTRAL) break; p = g_utf8_next_char (p); } return dir;}/** * pango_is_zero_width: * @ch: a Unicode character * * Checks @ch to see if it is a character that should not be * normally rendered on the screen. This includes all Unicode characters * with "ZERO WIDTH" in their name, as well as <firstterm>bidi</firstterm> formatting characters, and * a few other ones. This is totally different from g_unichar_iszerowidth() * and is at best misnamed. * * Return value: %TRUE if @ch is a zero-width character, %FALSE otherwise * * Since: 1.10 */gbooleanpango_is_zero_width (gunichar ch){/* Zero Width characters: * * 00AD SOFT HYPHEN * 034F COMBINING GRAPHEME JOINER * * 200B ZERO WIDTH SPACE * 200C ZERO WIDTH NON-JOINER * 200D ZERO WIDTH JOINER * 200E LEFT-TO-RIGHT MARK * 200F RIGHT-TO-LEFT MARK * * 2028 LINE SEPARATOR * * 202A LEFT-TO-RIGHT EMBEDDING * 202B RIGHT-TO-LEFT EMBEDDING * 202C POP DIRECTIONAL FORMATTING * 202D LEFT-TO-RIGHT OVERRIDE * 202E RIGHT-TO-LEFT OVERRIDE * * 2060 WORD JOINER * 2061 FUNCTION APPLICATION * 2062 INVISIBLE TIMES * 2063 INVISIBLE SEPARATOR * * FEFF ZERO WIDTH NO-BREAK SPACE */ return ((ch & ~(gunichar)0x007F) == 0x2000 && ( (ch >= 0x200B && ch <= 0x200F) || (ch >= 0x202A && ch <= 0x202E) || (ch >= 0x2060 && ch <= 0x2063) || (ch == 0x2028) )) || G_UNLIKELY (ch == 0x00AD || ch == 0x034F || ch == 0xFEFF);}/** * pango_quantize_line_geometry: * @thickness: pointer to the thickness of a line, in Pango units * @position: corresponding position * * Quantizes the thickness and position of a line, typically an * underline or strikethrough, to whole device pixels, that is integer * multiples of %PANGO_SCALE. The purpose of this function is to avoid * such lines looking blurry. * * Care is taken to make sure @thickness is at least one pixel when this * function returns, but returned @position may become zero as a result * of rounding. * * Since: 1.12 */voidpango_quantize_line_geometry (int *thickness, int *position){ int thickness_pixels = (*thickness + PANGO_SCALE / 2) / PANGO_SCALE; if (thickness_pixels == 0) thickness_pixels = 1; if (thickness_pixels & 1) { int new_center = ((*position - *thickness / 2) & ~(PANGO_SCALE - 1)) + PANGO_SCALE / 2; *position = new_center + (PANGO_SCALE * thickness_pixels) / 2; } else { int new_center = ((*position - *thickness / 2 + PANGO_SCALE / 2) & ~(PANGO_SCALE - 1)); *position = new_center + (PANGO_SCALE * thickness_pixels) / 2; } *thickness = thickness_pixels * PANGO_SCALE;}/** * pango_units_from_double: * @d: double floating-point value * * Converts a floating-point number to Pango units: multiplies * it by %PANGO_SCALE and rounds to nearest integer. * * Return value: the value in Pango units. * * Since: 1.16 */intpango_units_from_double (double d){ return (int)floor (d * PANGO_SCALE + 0.5);}/** * pango_units_to_double: * @i: value in Pango units * * Converts a number in Pango units to floating-point: divides * it by %PANGO_SCALE. * * Return value: the double value. * * Since: 1.16 */doublepango_units_to_double (int i){ return (double)i / PANGO_SCALE;}/** * pango_extents_to_pixels: * @inclusive: rectangle to round to pixels inclusively, or %NULL. * @nearest: rectangle to round to nearest pixels, or %NULL. * * Converts extents from Pango units to device units, dividing by the * %PANGO_SCALE factor and performing rounding. * * The @inclusive rectangle is converted by flooring the x/y coordinates and extending * width/height, such that the final rectangle completely includes the original * rectangle. * * The @nearest rectangle is converted by rounding the coordinates * of the rectangle to the nearest device unit (pixel). * * The rule to which argument to use is: if you want the resulting device-space * rectangle to completely contain the original rectangle, pass it in as @inclusive. * If you want two touching-but-not-overlapping rectangles stay * touching-but-not-overlapping after rounding to device units, pass them in * as @nearest. * * Since: 1.16 **/voidpango_extents_to_pixels (PangoRectangle *inclusive, PangoRectangle *nearest){ if (inclusive) { int orig_x = inclusive->x; int orig_y = inclusive->y; inclusive->x = PANGO_PIXELS_FLOOR (inclusive->x); inclusive->y = PANGO_PIXELS_FLOOR (inclusive->y); inclusive->width = PANGO_PIXELS_CEIL (orig_x + inclusive->width ) - inclusive->x; inclusive->height = PANGO_PIXELS_CEIL (orig_y + inclusive->height) - inclusive->y; } if (nearest) { int orig_x = nearest->x; int orig_y = nearest->y; nearest->x = PANGO_PIXELS (nearest->x); nearest->y = PANGO_PIXELS (nearest->y); nearest->width = PANGO_PIXELS (orig_x + nearest->width ) - nearest->x; nearest->height = PANGO_PIXELS (orig_y + nearest->height) - nearest->y; }}/********************************************************* * Some internal functions for handling PANGO_ATTR_SHAPE * ********************************************************/void_pango_shape_shape (const char *text, gint n_chars, PangoRectangle *shape_ink, PangoRectangle *shape_logical, PangoGlyphString *glyphs){ int i; const char *p; pango_glyph_string_set_size (glyphs, n_chars); for (i=0, p = text; i < n_chars; i++, p = g_utf8_next_char (p)) { glyphs->glyphs[i].glyph = PANGO_GLYPH_EMPTY; glyphs->glyphs[i].geometry.x_offset = 0; glyphs->glyphs[i].geometry.y_offset = 0; glyphs->glyphs[i].geometry.width = shape_logical->width; glyphs->glyphs[i].attr.is_cluster_start = 1; glyphs->log_clusters[i] = p - text; }}void_pango_shape_get_extents (gint n_chars, PangoRectangle *shape_ink, PangoRectangle *shape_logical, PangoRectangle *ink_rect, PangoRectangle *logical_rect){ if (n_chars > 0) { if (ink_rect) { ink_rect->x = MIN (shape_ink->x, shape_ink->x + shape_logical->width * (n_chars - 1)); ink_rect->width = MAX (shape_ink->width, shape_ink->width + shape_logical->width * (n_chars - 1)); ink_rect->y = shape_ink->y; ink_rect->height = shape_ink->height; } if (logical_rect) { logical_rect->x = MIN (shape_logical->x, shape_logical->x + shape_logical->width * (n_chars - 1)); logical_rect->width = MAX (shape_logical->width, shape_logical->width + shape_logical->width * (n_chars - 1)); logical_rect->y = shape_logical->y; logical_rect->height = shape_logical->height; } } else { if (ink_rect) { ink_rect->x = 0; ink_rect->y = 0; ink_rect->width = 0; ink_rect->height = 0; } if (logical_rect) { logical_rect->x = 0; logical_rect->y = 0; logical_rect->width = 0; logical_rect->height = 0; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -