diff options
author | Owen Taylor <otaylor@redhat.com> | 2004-05-28 22:53:24 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2004-05-28 22:53:24 +0000 |
commit | 31e0850c421fcc777c452121eb5c68fcf2ce3cda (patch) | |
tree | 3ff00cfd6e238df998bcf3c1b95fc059582ab1ce /pango/pangoft2.c | |
parent | 3ef5e7edc246615f45accafca5d83739b14ca66b (diff) | |
download | pango-31e0850c421fcc777c452121eb5c68fcf2ce3cda.tar.gz |
Add PangoMatrix type for affine transforms.
Fri May 28 11:39:39 2004 Owen Taylor <otaylor@redhat.com>
* pango/pango-types.h pango/pango-utils.c: Add PangoMatrix
type for affine transforms.
* configure.in pango.pc.in pango/Makefile.am: Add a -lm
dependency for PangoMatrix operations.
* pango/pango-context.[ch]: Add pango_context_set/get_matrix().
* pango/pangoft2-render.c pango/pangoft2-private.h: Add
code for drawing antialiased transformed rectangles and
squiggly error underlines.
* pango/pangoft2.[ch]: Add pango_ft2_render_transformed(),
pango_ft2_render_layout_subpixel(),
pango_ft2_render_layout_line_subpixel(), implement transformed
rendering.
* pango/pangofc-font.c: Pass any transformation matrix on to
fontconfig when creating the pattern for a PangoFcFont.
Diffstat (limited to 'pango/pangoft2.c')
-rw-r--r-- | pango/pangoft2.c | 359 |
1 files changed, 248 insertions, 111 deletions
diff --git a/pango/pangoft2.c b/pango/pangoft2.c index 4693a9f3..5de9ca7e 100644 --- a/pango/pangoft2.c +++ b/pango/pangoft2.c @@ -158,6 +158,25 @@ load_fallback_face (PangoFT2Font *ft2font, FcPatternDestroy (matched); } +static void +set_transform (PangoFT2Font *ft2font) +{ + PangoFcFont *fcfont = (PangoFcFont *)ft2font; + FcMatrix *fc_matrix; + + if (FcPatternGetMatrix (fcfont->font_pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch) + { + FT_Matrix ft_matrix; + + ft_matrix.xx = 0x10000L * fc_matrix->xx; + ft_matrix.yy = 0x10000L * fc_matrix->yy; + ft_matrix.xy = 0x10000L * fc_matrix->xy; + ft_matrix.yx = 0x10000L * fc_matrix->yx; + + FT_Set_Transform (ft2font->face, &ft_matrix, NULL); + } +} + /** * pango_ft2_font_get_face: * @font: a #PangoFont @@ -228,6 +247,8 @@ pango_ft2_font_get_face (PangoFont *font) g_assert (ft2font->face); + set_transform (ft2font); + error = FT_Set_Char_Size (ft2font->face, PANGO_PIXELS_26_6 (ft2font->size), PANGO_PIXELS_26_6 (ft2font->size), @@ -337,23 +358,45 @@ pango_ft2_font_render_glyph (PangoFont *font, return rendered; } +static void +transform_point (PangoMatrix *matrix, + int x, + int y, + int *x_out_pixels, + int *y_out_pixels) +{ + double x_out = (matrix->xx * x + matrix->xy * y) / PANGO_SCALE + matrix->x0; + double y_out = (matrix->yx * x + matrix->yy * y) / PANGO_SCALE + matrix->y0; + + *x_out_pixels = floor (x_out + 0.5); + *y_out_pixels = floor (y_out + 0.5); +} /** - * pango_ft2_render: + * pango_ft2_render_transformed: * @bitmap: the FreeType2 bitmap onto which to draw the string * @font: the font in which to draw the string + * @matrix: a #PangoMatrix, or %NULL to use an identity transformation * @glyphs: the glyph string to draw - * @x: the x position of the start of the string (in pixels) - * @y: the y position of the baseline (in pixels) + * @x: the x position of the start of the string (in Pango + * units in user space coordinates) + * @y: the y position of the baseline (in Pango units + * in user space coordinates) * - * Renders a PangoGlyphString onto a FreeType2 bitmap. + * Renders a #PangoGlyphString onto a FreeType2 bitmap, possibly + * transforming the layed-out coordinates through a transformation + * matrix. Note that the transformation matrix for @font is not + * changed, so to produce correct rendering results, the @font + * must have been loaded using a #PangoContext with an identical + * transformation matrix to that passed in to this function. **/ void -pango_ft2_render (FT_Bitmap *bitmap, - PangoFont *font, - PangoGlyphString *glyphs, - int x, - int y) +pango_ft2_render_transformed (FT_Bitmap *bitmap, + PangoMatrix *matrix, + PangoFont *font, + PangoGlyphString *glyphs, + int x, + int y) { FT_UInt glyph_index; int i; @@ -384,9 +427,19 @@ pango_ft2_render (FT_Bitmap *bitmap, rendered_glyph = pango_ft2_font_render_glyph (font, glyph_index); add_glyph_to_cache = TRUE; } - - ixoff = x + PANGO_PIXELS (x_position + gi->geometry.x_offset); - iyoff = y + PANGO_PIXELS (gi->geometry.y_offset); + + if (matrix) + { + transform_point (matrix, + x + x_position + gi->geometry.x_offset, + y + gi->geometry.y_offset, + &ixoff, &iyoff); + } + else + { + ixoff = PANGO_PIXELS (x + x_position + gi->geometry.x_offset); + iyoff = PANGO_PIXELS (y + gi->geometry.y_offset); + } x_start = MAX (0, - (ixoff + rendered_glyph->bitmap_left)); x_limit = MIN (rendered_glyph->bitmap.width, @@ -483,6 +536,26 @@ pango_ft2_render (FT_Bitmap *bitmap, } } +/** + * pango_ft2_render: + * @bitmap: the FreeType2 bitmap onto which to draw the string + * @font: the font in which to draw the string + * @glyphs: the glyph string to draw + * @x: the x position of the start of the string (in pixels) + * @y: the y position of the baseline (in pixels) + * + * Renders a #PangoGlyphString onto a FreeType2 bitmap. + **/ +void +pango_ft2_render (FT_Bitmap *bitmap, + PangoFont *font, + PangoGlyphString *glyphs, + int x, + int y) +{ + pango_ft2_render_transformed (bitmap, NULL, font, glyphs, x * PANGO_SCALE, y * PANGO_SCALE); +} + static FT_Glyph_Metrics * pango_ft2_get_per_char (PangoFont *font, guint32 glyph_index) @@ -715,59 +788,113 @@ pango_ft2_get_unknown_glyph (PangoFont *font) return 0; } - static void -pango_ft2_draw_hline (FT_Bitmap *bitmap, - int y, - int start, - int end) +draw_underline (FT_Bitmap *bitmap, + PangoMatrix *matrix, + PangoFontMetrics *metrics, + PangoUnderline uline, + int x, + int width, + int base_y, + int descent) { - unsigned char *p; - int ix; + int underline_thickness = pango_font_metrics_get_underline_thickness (metrics); + int underline_position = pango_font_metrics_get_underline_position (metrics); + int y_off = 0; /* Quiet GCC */ - if (y < 0 || y >= bitmap->rows) - return; + switch (uline) + { + case PANGO_UNDERLINE_NONE: + g_assert_not_reached(); + break; + case PANGO_UNDERLINE_SINGLE: + y_off = - underline_position; + break; + case PANGO_UNDERLINE_DOUBLE: + y_off = - underline_position; + break; + case PANGO_UNDERLINE_LOW: + y_off = underline_thickness + descent; + break; + case PANGO_UNDERLINE_ERROR: + { + _pango_ft2_draw_error_underline (bitmap, matrix, + x, + base_y - underline_position, + width, + 3 * underline_thickness); + return; + } + } - if (end <= 0 || start >= bitmap->width) - return; - - if (start < 0) - start = 0; + _pango_ft2_draw_rect (bitmap, matrix, + x, + base_y + y_off, + width, + underline_thickness); - if (end >= bitmap->width) - end = bitmap->width; + if (uline == PANGO_UNDERLINE_DOUBLE) + { + y_off += 2 * underline_thickness; + + _pango_ft2_draw_rect (bitmap, matrix, + x, + base_y + y_off, + width, + underline_thickness); + } +} - p = bitmap->buffer + y * bitmap->pitch + start; - - for (ix = 0; ix < end - start; ix++) - *p++ = 0xff; +static void +draw_strikethrough (FT_Bitmap *bitmap, + PangoMatrix *matrix, + PangoFontMetrics *metrics, + int x, + int width, + int base_y) +{ + int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics); + int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics); + + _pango_ft2_draw_rect (bitmap, matrix, + x, + base_y - strikethrough_position, + width, + strikethrough_thickness); } /** - * pango_ft2_render_layout_line: + * pango_ft2_render_layout_line_subpixel: * @bitmap: a FT_Bitmap to render the line onto * @line: a #PangoLayoutLine - * @x: the x position of start of string (in pixels) - * @y: the y position of baseline (in pixels) + * @x: the x position of start of string (in pango units) + * @y: the y position of baseline (in pango units) * - * Render a #PangoLayoutLine onto a FreeType2 bitmap + * Render a #PangoLayoutLine onto a FreeType2 bitmap, with he + * location specified in fixed-point pango units rather than + * pixels. (Using this will avoid extra inaccuracies from + * rounding to integer pixels multiple times, even if the + * final glyph positions are integers.) */ void -pango_ft2_render_layout_line (FT_Bitmap *bitmap, - PangoLayoutLine *line, - int x, - int y) +pango_ft2_render_layout_line_subpixel (FT_Bitmap *bitmap, + PangoLayoutLine *line, + int x, + int y) { GSList *tmp_list = line->runs; PangoRectangle logical_rect; PangoRectangle ink_rect; int x_off = 0; + PangoMatrix *matrix; + + matrix = pango_context_get_matrix (pango_layout_get_context (line->layout)); while (tmp_list) { PangoUnderline uline = PANGO_UNDERLINE_NONE; gboolean strike, shape_set; - gint rise, risen_y; + gint rise; PangoLayoutRun *run = tmp_list->data; tmp_list = tmp_list->next; @@ -776,92 +903,84 @@ pango_ft2_render_layout_line (FT_Bitmap *bitmap, &uline, &strike, &rise, &shape_set, &ink_rect, &logical_rect); - risen_y = y - PANGO_PIXELS (rise); - if (!shape_set) { - if (uline == PANGO_UNDERLINE_NONE) + if (uline == PANGO_UNDERLINE_NONE && !strike) pango_glyph_string_extents (run->glyphs, run->item->analysis.font, NULL, &logical_rect); else pango_glyph_string_extents (run->glyphs, run->item->analysis.font, &ink_rect, &logical_rect); + + pango_ft2_render_transformed (bitmap, matrix, + run->item->analysis.font, run->glyphs, + x + x_off, y - rise); - pango_ft2_render (bitmap, run->item->analysis.font, run->glyphs, - x + PANGO_PIXELS (x_off), risen_y); - } + if (uline != PANGO_UNDERLINE_NONE || strike) + { + PangoFontMetrics *metrics = pango_font_get_metrics (run->item->analysis.font, + run->item->analysis.language); + + if (uline != PANGO_UNDERLINE_NONE) + draw_underline (bitmap, matrix, metrics, + uline, + x_off + ink_rect.x, + ink_rect.width, + y - rise, + ink_rect.y + ink_rect.height); + + if (strike) + draw_strikethrough (bitmap, matrix, metrics, + x_off + ink_rect.x, + ink_rect.width, + y - rise); - switch (uline) - { - case PANGO_UNDERLINE_NONE: - break; - case PANGO_UNDERLINE_DOUBLE: - pango_ft2_draw_hline (bitmap, - risen_y + 4, - x + PANGO_PIXELS (x_off + ink_rect.x), - x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); - /* Fall through */ - case PANGO_UNDERLINE_SINGLE: - pango_ft2_draw_hline (bitmap, - risen_y + 2, - x + PANGO_PIXELS (x_off + ink_rect.x), - x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); - break; - case PANGO_UNDERLINE_ERROR: - { - int point_x; - int counter = 0; - int end_x = x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width); - - for (point_x = x + PANGO_PIXELS (x_off + ink_rect.x) - 1; - point_x <= end_x; - point_x += 2) - { - if (counter) - pango_ft2_draw_hline (bitmap, - risen_y + 2, - point_x, MIN (point_x + 1, end_x)); - else - pango_ft2_draw_hline (bitmap, - risen_y + 3, - point_x, MIN (point_x + 1, end_x)); - - counter = (counter + 1) % 2; - } - } - break; - case PANGO_UNDERLINE_LOW: - pango_ft2_draw_hline (bitmap, - risen_y + PANGO_PIXELS (ink_rect.y + ink_rect.height), - x + PANGO_PIXELS (x_off + ink_rect.x), - x + PANGO_PIXELS (x_off + ink_rect.x + ink_rect.width)); - break; + pango_font_metrics_unref (metrics); + } } - if (strike) - pango_ft2_draw_hline (bitmap, - risen_y + PANGO_PIXELS (logical_rect.y + logical_rect.height / 2), - x + PANGO_PIXELS (x_off + logical_rect.x), - x + PANGO_PIXELS (x_off + logical_rect.x + logical_rect.width)); - x_off += logical_rect.width; } } + /** - * pango_ft2_render_layout: + * pango_ft2_render_layout_line: + * @bitmap: a FT_Bitmap to render the line onto + * @line: a #PangoLayoutLine + * @x: the x position of start of string (in pixels) + * @y: the y position of baseline (in pixels) + * + * Render a #PangoLayoutLine onto a FreeType2 bitmap + */ +void +pango_ft2_render_layout_line (FT_Bitmap *bitmap, + PangoLayoutLine *line, + int x, + int y) +{ + pango_ft2_render_layout_line_subpixel (bitmap, line, x * PANGO_SCALE, y * PANGO_SCALE); +} + + +/** + * pango_ft2_render_layout_subpixel: * @bitmap: a FT_Bitmap to render the layout onto * @layout: a #PangoLayout - * @x: the X position of the left of the layout (in pixels) - * @y: the Y position of the top of the layout (in pixels) + * @x: the X position of the left of the layout (in Pango units) + * @y: the Y position of the top of the layout (in Pango units) * - * Render a #PangoLayout onto a FreeType2 bitmap + * Render a #PangoLayout onto a FreeType2 bitmap, with he + * location specified in fixed-point pango units rather than + * pixels. (Using this will avoid extra inaccuracies from + * rounding to integer pixels multiple times, even if the + * final glyph positions are integers.) */ void -pango_ft2_render_layout (FT_Bitmap *bitmap, - PangoLayout *layout, - int x, - int y) +pango_ft2_render_layout_subpixel (FT_Bitmap *bitmap, + PangoLayout *layout, + int x, + int y) { PangoLayoutIter *iter; @@ -880,17 +999,35 @@ pango_ft2_render_layout (FT_Bitmap *bitmap, pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); baseline = pango_layout_iter_get_baseline (iter); - - pango_ft2_render_layout_line (bitmap, - line, - x + PANGO_PIXELS (logical_rect.x), - y + PANGO_PIXELS (baseline)); + + pango_ft2_render_layout_line_subpixel (bitmap, + line, + x + logical_rect.x, + y + baseline); } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); } +/** + * pango_ft2_render_layout: + * @bitmap: a FT_Bitmap to render the layout onto + * @layout: a #PangoLayout + * @x: the X position of the left of the layout (in pixels) + * @y: the Y position of the top of the layout (in pixels) + * + * Render a #PangoLayout onto a FreeType2 bitmap + */ +void +pango_ft2_render_layout (FT_Bitmap *bitmap, + PangoLayout *layout, + int x, + int y) +{ + pango_ft2_render_layout_subpixel (bitmap, layout, x * PANGO_SCALE, y * PANGO_SCALE); +} + /* This utility function is duplicated here and in pango-layout.c; should it be * public? Trouble is - what is the appropriate set of properties? */ |