diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-06-26 11:23:38 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-07-04 11:17:28 -0400 |
commit | aedb2cc9a3aed2f60f6df09513288cbc8bbfa5ff (patch) | |
tree | 808ae56142946550cd0307c98234cccec5dfdc38 | |
parent | f51d318abbb9e67fd362129a2f2af81e77b9d691 (diff) | |
download | pango-aedb2cc9a3aed2f60f6df09513288cbc8bbfa5ff.tar.gz |
Update examples in the docs
Sucks that we have to do this manually.
-rw-r--r-- | docs/first_steps.md | 25 | ||||
-rw-r--r-- | docs/migrating.md | 4 | ||||
-rw-r--r-- | docs/pango_cairo.md | 37 | ||||
-rw-r--r-- | docs/pango_layout.md | 100 | ||||
-rw-r--r-- | docs/pango_user.md | 433 |
5 files changed, 328 insertions, 271 deletions
diff --git a/docs/first_steps.md b/docs/first_steps.md index a863fc33..7e369a5d 100644 --- a/docs/first_steps.md +++ b/docs/first_steps.md @@ -22,29 +22,29 @@ Useful next steps would be: ``` #include <math.h> -#include <pango/pangocairo.h> +#include <pango2/pangocairo.h> #define SIZE 150 static void draw_text (cairo_t *cr) { - PangoLayout *layout; - PangoFontDescription *desc; + Pango2Layout *layout; + Pango2FontDescription *desc; - /* Create a PangoLayout */ - layout = pango_cairo_create_layout (cr); + /* Create a Pango2Layout */ + layout = pango2_cairo_create_layout (cr); /* Set the text */ - pango_layout_set_text (layout, "Text", -1); + pango2_layout_set_text (layout, "Text", -1); /* Set a font for the layout */ - desc = pango_font_description_from_string ("Sans Bold 20"); - pango_layout_set_font_description (layout, desc); - pango_font_description_free (desc); + desc = pango2_font_description_from_string ("Sans Bold 20"); + pango2_layout_set_font_description (layout, desc); + pango2_font_description_free (desc); /* Show the layout */ - pango_cairo_show_layout (cr, layout); + pango2_cairo_show_layout (cr, layout); /* Free the layout object */ g_object_unref (layout); @@ -85,7 +85,12 @@ main (int argc, char **argv) cairo_destroy (cr); +#ifdef CAIRO_HAS_PNG_FUNCTIONS status = cairo_surface_write_to_png (surface, filename); +#else + status = CAIRO_STATUS_PNG_ERROR; /* Not technically correct, but... */ +#endif + cairo_surface_destroy (surface); if (status != CAIRO_STATUS_SUCCESS) diff --git a/docs/migrating.md b/docs/migrating.md index 7c1e3b37..a7e7a5d7 100644 --- a/docs/migrating.md +++ b/docs/migrating.md @@ -46,8 +46,8 @@ prefix as well: The big advantage of this change is that the two libraries can be used side-by-side in the same process without symbol or type clashes. The downside -is, of course, that you have to adapt your code to change all uses of -Pango API. Thankfully, this is largely a mechanical change. +is, of course, that you have to adapt all uses of Pango API in your code. +Thankfully, this is largely a mechanical change. ### Build setup changes diff --git a/docs/pango_cairo.md b/docs/pango_cairo.md index 309b7d02..afd59ae9 100644 --- a/docs/pango_cairo.md +++ b/docs/pango_cairo.md @@ -32,7 +32,7 @@ point units used in Cairo divide by `PANGO_SCALE`. ``` #include <math.h> -#include <pango/pangocairo.h> +#include <pango2/pangocairo.h> #define RADIUS 150 #define N_WORDS 10 @@ -41,21 +41,21 @@ point units used in Cairo divide by `PANGO_SCALE`. static void draw_text (cairo_t *cr) { - PangoLayout *layout; - PangoLines *lines; - PangoFontDescription *desc; + Pango2Layout *layout; + Pango2Lines *lines; + Pango2FontDescription *desc; int i; /* Center coordinates on the middle of the region we are drawing */ cairo_translate (cr, RADIUS, RADIUS); - /* Create a PangoLayout, set the font and text */ - layout = pango_cairo_create_layout (cr); + /* Create a Pango2Layout, set the font and text */ + layout = pango2_cairo_create_layout (cr); - pango_layout_set_text (layout, "Text", -1); - desc = pango_font_description_from_string (FONT); - pango_layout_set_font_description (layout, desc); - pango_font_description_free (desc); + pango2_layout_set_text (layout, "Text", -1); + desc = pango2_font_description_from_string (FONT); + pango2_layout_set_font_description (layout, desc); + pango2_font_description_free (desc); /* Draw the layout N_WORDS times in a circle */ for (i = 0; i < N_WORDS; i++) @@ -72,14 +72,14 @@ draw_text (cairo_t *cr) cairo_rotate (cr, angle * G_PI / 180.); - /* Inform Pango to re-layout the text with the new transformation */ - pango_cairo_update_layout (cr, layout); + /* Inform Pango2 to re-layout the text with the new transformation */ + pango2_cairo_update_layout (cr, layout); - lines = pango_layout_get_lines (layout); + lines = pango2_layout_get_lines (layout); - pango_lines_get_size (lines, &width, &height); - cairo_move_to (cr, - ((double) width / PANGO_SCALE) / 2, - RADIUS); - pango_cairo_show_layout (cr, layout); + pango2_lines_get_size (lines, &width, &height); + cairo_move_to (cr, - ((double) width / PANGO2_SCALE) / 2, - RADIUS); + pango2_cairo_show_layout (cr, layout); cairo_restore (cr); } @@ -113,7 +113,12 @@ main (int argc, char **argv) draw_text (cr); cairo_destroy (cr); +#ifdef CAIRO_HAS_PNG_FUNCTIONS status = cairo_surface_write_to_png (surface, filename); +#else + status = CAIRO_STATUS_PNG_ERROR; /* Not technically correct, but... */ +#endif + cairo_surface_destroy (surface); if (status != CAIRO_STATUS_SUCCESS) diff --git a/docs/pango_layout.md b/docs/pango_layout.md index a4d8e122..e723c659 100644 --- a/docs/pango_layout.md +++ b/docs/pango_layout.md @@ -4,75 +4,74 @@ Title: Complex layout # Complex layout -The central object in high-level Pango API is [class@Pango.Layout]. +The central object in high-level Pango API is [class@Pango2.Layout]. It is well-suited for breaking text into lines that fill a rectangular area, since that is commonly how paragraphs are formatted in books. But in real-life situations, text does not always fit in a box. Examples of more complicated requirements are fitting text around an image, or flowing text between multiple frames. -For cases like these, it is better to use [class@Pango.LineBreaker] -directly instead of `PangoLayout` (`PangoLayout` is using a line -breaker internally). The way `PangoLineBreaker` works is to let +For cases like these, it is better to use [class@Pango2.LineBreaker] +directly instead of `Pango2Layout` (`Pango2Layout` is using a line +breaker internally). The way `Pango2LineBreaker` works is to let applications access the formatted result one line at a time, place it, and change parameters such as the line width before requesting the next one. -The following example shows how to use `PangoLineBreaker` to +The following example shows how to use `Pango2LineBreaker` to produce an unusually shaped paragraph with a hole in the middle. -## Using GtkLineBreaker +## Using Pango2LineBreaker ``` -#include <pango/pango.h> -#include <pango/pangocairo.h> +#include <pango2/pangocairo.h> -static PangoLines * +static Pango2Lines * format_text (const char *text) { - PangoContext *context; - PangoLineBreaker *breaker; - PangoLines *lines; + Pango2Context *context; + Pango2LineBreaker *breaker; + Pango2Lines *lines; int x, y, width; int inc, m, w, w2; - context = pango_font_map_create_context (pango_font_map_get_default ()); - breaker = pango_line_breaker_new (context); + context = pango2_context_new (); + breaker = pango2_line_breaker_new (context); - pango_line_breaker_add_text (breaker, text, -1, NULL); + pango2_line_breaker_add_text (breaker, text, -1, NULL); - lines = pango_lines_new (); + lines = pango2_lines_new (); m = 200; w = 10; w2 = -200; inc = 40; - y = 40 * PANGO_SCALE; - x = (m - w / 2) * PANGO_SCALE; - width = w * PANGO_SCALE; + y = 40 * PANGO2_SCALE; + x = (m - w / 2) * PANGO2_SCALE; + width = w * PANGO2_SCALE; - while (pango_line_breaker_has_line (breaker)) + while (pango2_line_breaker_has_line (breaker)) { - PangoLine *line; - PangoRectangle ext; + Pango2Line *line; + Pango2Rectangle ext; gboolean ltr; - line = pango_line_breaker_next_line (breaker, + line = pango2_line_breaker_next_line (breaker, x, width, - PANGO_WRAP_CHAR, - PANGO_ELLIPSIZE_NONE); + PANGO2_WRAP_CHAR, + PANGO2_ELLIPSIZE_NONE); - pango_line_get_extents (line, NULL, &ext); - line = pango_line_justify (line, width); - pango_lines_add_line (lines, line, x, y - ext.y); + pango2_line_get_extents (line, NULL, &ext); + line = pango2_line_justify (line, width); + pango2_lines_add_line (lines, line, x, y - ext.y); - ltr = pango_line_breaker_get_direction (breaker) == PANGO_DIRECTION_LTR; + ltr = pango2_line_breaker_get_direction (breaker) == PANGO2_DIRECTION_LTR; - if (w2 > 0 && ltr && x <= m * PANGO_SCALE) - x = (m + w2 / 2) * PANGO_SCALE; - else if (w2 > 0 && !ltr && x > m * PANGO_SCALE) - x = (m - w2 / 2) * PANGO_SCALE; + if (w2 > 0 && ltr && x <= m * PANGO2_SCALE) + x = (m + w2 / 2) * PANGO2_SCALE; + else if (w2 > 0 && !ltr && x > m * PANGO2_SCALE) + x = (m - w2 / 2) * PANGO2_SCALE; else { y += ext.height; @@ -83,14 +82,14 @@ format_text (const char *text) inc = - inc; if (w2 > 0) - width = ((w - w2) / 2) * PANGO_SCALE; + width = ((w - w2) / 2) * PANGO2_SCALE; else - width = w * PANGO_SCALE; + width = w * PANGO2_SCALE; if (ltr) - x = (m - w / 2) * PANGO_SCALE; + x = (m - w / 2) * PANGO2_SCALE; else - x = (m + w / 2) * PANGO_SCALE; + x = (m + w / 2) * PANGO2_SCALE; } } @@ -101,18 +100,18 @@ format_text (const char *text) } static void -draw_lines (cairo_t *cr, PangoLines *lines) +draw_lines (cairo_t *cr, Pango2Lines *lines) { - for (int i = 0; i < pango_lines_get_line_count (lines); i++) + for (int i = 0; i < pango2_lines_get_line_count (lines); i++) { - PangoLine *line = pango_lines_get_lines (lines)[i]; + Pango2Line *line = pango2_lines_get_lines (lines)[i]; int x, y; - pango_lines_get_line_position (lines, i, &x, &y); + pango2_lines_get_line_position (lines, i, &x, &y); cairo_save (cr); - cairo_move_to (cr, x / (double)PANGO_SCALE, y / (double)PANGO_SCALE); - pango_cairo_show_line (cr, line); + cairo_move_to (cr, x / (double)PANGO2_SCALE, y / (double)PANGO2_SCALE); + pango2_cairo_show_line (cr, line); cairo_restore (cr); } } @@ -121,12 +120,13 @@ int main (int argc, char *argv[]) { const char *filename; - PangoLines *lines; + Pango2Lines *lines; cairo_surface_t *surface; cairo_t *cr; char *text; gsize length; GError *error = NULL; + cairo_status_t status; if (argc != 3) { @@ -152,8 +152,16 @@ main (int argc, char *argv[]) draw_lines (cr, lines); g_object_unref (lines); - cairo_surface_write_to_png (surface, filename); - g_print ("Output written to %s\n", filename); +#ifdef CAIRO_HAS_PNG_FUNCTIONS + status = cairo_surface_write_to_png (surface, filename); +#else + status = CAIRO_STATUS_PNG_ERROR; /* Not technically correct, but... */ +#endif + + if (status != CAIRO_STATUS_SUCCESS) + g_printerr ("Could not save png to '%s'\n", filename); + else + g_print ("Output written to %s\n", filename); cairo_surface_destroy (surface); cairo_destroy (cr); diff --git a/docs/pango_user.md b/docs/pango_user.md index c1e0f985..760b20a8 100644 --- a/docs/pango_user.md +++ b/docs/pango_user.md @@ -11,173 +11,121 @@ not support. And sometimes, it is more convenient to use a drawing API to render glyphs on-the-spot, maybe with fancy effects. For these cases, Pango provides the [class@Pango2.UserFace] implementation of -`PangoFontFace` that uses callbacks for its functionality. This lets you embed +`Pango2FontFace` that uses callbacks for its functionality. This lets you embed custom drawing into your text, fully integrated with Pango's text layout capabilities. ## A user font example ``` +#include <stdlib.h> #include <stdio.h> -#include <string.h> - -#include <pango/pangocairo.h> - -#define BULLET "•" -#define HEART "♥" - -const char text[] = -"The GNOME project provides three things:\n" -"\n" -" • The GNOME desktop environment\n" -" • The GNOME development platform\n" -" • Planet GNOME\n" -" ♥ Lots of love"; - -typedef struct { - double width, height; - const char *path; -} MiniSvg; - -static MiniSvg GnomeFootLogo = { - 96.2152, 118.26, - "M 86.068,1 C 61.466,0 56.851,35.041 70.691,35.041 C 84.529,35.041 110.671,0 86.068,0 z " - "M 45.217,30.699 C 52.586,31.149 60.671,2.577 46.821,4.374 C 32.976,6.171 37.845,30.249 45.217,30.699 z " - "M 11.445,48.453 C 16.686,46.146 12.12,23.581 3.208,29.735 C -5.7,35.89 6.204,50.759 11.445,48.453 z " - "M 26.212,36.642 C 32.451,35.37 32.793,9.778 21.667,14.369 C 10.539,18.961 19.978,37.916 26.212,36.642 L 26.212,36.642 z " - "M 58.791,93.913 C 59.898,102.367 52.589,106.542 45.431,101.092 C 22.644,83.743 83.16,75.088 79.171,51.386 C 75.86,31.712 15.495,37.769 8.621,68.553 C 3.968,89.374 27.774,118.26 52.614,118.26 C 64.834,118.26 78.929,107.226 81.566,93.248 C 83.58,82.589 57.867,86.86 58.791,93.913 L 58.791,93.913 z " - "\0" -}; - -static void -mini_svg_render (MiniSvg *shape, cairo_t *cr) -{ - double x, y; - char op[2]; - int len; - double x1, y1, x2, y2, x3, y3; - const char *p; - - cairo_get_current_point (cr, &x, &y); - cairo_translate (cr, x, y); - - for (p = shape->path; sscanf (p, "%1s %n", op, &len), p += len, *p;) - switch (*op) - { - case 'M': - sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len; - cairo_move_to (cr, x, y); - break; - case 'L': - sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len; - cairo_line_to (cr, x, y); - break; - case 'C': - sscanf (p, "%lf,%lf %lf,%lf %lf,%lf %n", &x1, &y1, &x2, &y2, &x3, &y3, &len); p += len; - cairo_curve_to (cr, x1, y1, x2, y2, x3, y3); - break; - case 'z': - cairo_close_path (cr); - break; - default: - g_warning ("Invalid MiniSvg operation '%c'", *op); - break; - } - - cairo_fill (cr); -} - -static PangoLayout * -get_layout (cairo_t *cr) -{ - PangoLayout *layout; - PangoAttrList *attrs; - PangoFontDescription *font_desc; - const char *p; - /* Create a PangoLayout, set the font and text */ - layout = pango_cairo_create_layout (cr); - pango_layout_set_text (layout, text, -1); +#include <pango2/pangocairo.h> - font_desc = pango_font_description_from_string ("Cantarell 12"); - pango_layout_set_font_description (layout, font_desc); - pango_font_description_free (font_desc); - - attrs = pango_attr_list_new (); - - font_desc = pango_font_description_from_string ("Bullets 12"); - - for (p = text; (p = strstr (p, BULLET)); p += strlen (BULLET)) - { - PangoAttribute *attr; - - attr = pango_attr_font_desc_new (font_desc); - attr->start_index = p - text; - attr->end_index = attr->start_index + strlen (BULLET); - pango_attr_list_insert (attrs, attr); - } - - for (p = text; (p = strstr (p, HEART)); p += strlen (HEART)) - { - PangoAttribute *attr; - - attr = pango_attr_font_desc_new (font_desc); - attr->start_index = p - text; - attr->end_index = attr->start_index + strlen (HEART); - pango_attr_list_insert (attrs, attr); - } +static Pango2FontMap *fontmap; - pango_font_description_free (font_desc); +#define END_GLYPH 0 +#define STROKE 126 +#define CLOSE 127 - pango_layout_set_attributes (layout, attrs); - pango_attr_list_unref (attrs); +/* Simple glyph definition: 1 - 15 means lineto (or moveto for first + * point) for one of the points on this grid: + * + * 1 2 3 + * 4 5 6 + * 7 8 9 + * ----10 11 12----(baseline) + * 13 14 15 + */ +typedef struct +{ + gunichar ucs4; + int width; + char data[16]; +} test_scaled_font_glyph_t; + +/* Simple glyph definition: 1 - 15 means lineto (or moveto for first + * point) for one of the points on this grid: + * + * 1 2 3 + * 4 5 6 + * 7 8 9 + * ----10 11 12----(baseline) + * 13 14 15 + */ +static const test_scaled_font_glyph_t glyphs [] = { + { 'a', 3, { 4, 6, 12, 10, 7, 9, STROKE, END_GLYPH } }, + { 'c', 3, { 6, 4, 10, 12, STROKE, END_GLYPH } }, + { 'e', 3, { 12, 10, 4, 6, 9, 7, STROKE, END_GLYPH } }, + { 'f', 3, { 3, 2, 11, STROKE, 4, 6, STROKE, END_GLYPH } }, + { 'g', 3, { 12, 10, 4, 6, 15, 13, STROKE, END_GLYPH } }, + { 'h', 3, { 1, 10, STROKE, 7, 5, 6, 12, STROKE, END_GLYPH } }, + { 'i', 1, { 1, 1, STROKE, 4, 10, STROKE, END_GLYPH } }, + { 'l', 1, { 1, 10, STROKE, END_GLYPH } }, + { 'n', 3, { 10, 4, STROKE, 7, 5, 6, 12, STROKE, END_GLYPH } }, + { 'o', 3, { 4, 10, 12, 6, CLOSE, END_GLYPH } }, + { 'p', 3, { 4, 10, 12, 6, CLOSE, 4, 13, STROKE, END_GLYPH } }, + { 'r', 3, { 4, 10, STROKE, 7, 5, 6, STROKE, END_GLYPH } }, + { 's', 3, { 6, 4, 7, 9, 12, 10, STROKE, END_GLYPH } }, + { 't', 3, { 2, 11, 12, STROKE, 4, 6, STROKE, END_GLYPH } }, + { 'u', 3, { 4, 10, 12, 6, STROKE, END_GLYPH } }, + { 'y', 3, { 4, 10, 12, 6, STROKE, 12, 15, 13, STROKE, END_GLYPH } }, + { 'z', 3, { 4, 6, 10, 12, STROKE, END_GLYPH } }, + { ' ', 1, { END_GLYPH } }, + { '-', 2, { 7, 8, STROKE, END_GLYPH } }, + { '.', 1, { 10, 10, STROKE, END_GLYPH } }, + { 0xe000, 3, { 3, 2, 11, STROKE, 4, 6, STROKE, 3, 3, STROKE, 6, 12, STROKE, END_GLYPH } }, /* fi */ + { -1, 0, { END_GLYPH } }, +}; - return layout; -} +const char text[] = "finally... pango user-font"; -static void -measure_text (cairo_t *cr, int *width, int *height) +static Pango2Layout * +get_layout (void) { - PangoLayout *layout = get_layout (cr); - PangoLines *lines = pango_layout_get_lines (layout); - PangoRectangle ext; + Pango2Context *context; + Pango2Layout *layout; + Pango2FontDescription *desc; - pango_lines_get_extents (lines, NULL, &ext); - pango_extents_to_pixels (&ext, NULL); + /* Create a Pango2Layout, set the font and text */ + context = pango2_context_new_with_font_map (fontmap); + layout = pango2_layout_new (context); + g_object_unref (context); - *width = ext.width + 20; - *height = ext.height + 20; -} + pango2_layout_set_text (layout, text, -1); -static void -draw_text (cairo_t *cr) -{ - PangoLayout *layout = get_layout (cr); - PangoLines *lines = pango_layout_get_lines (layout); + desc = pango2_font_description_from_string ("Userfont 20"); + pango2_layout_set_font_description (layout, desc); + pango2_font_description_free (desc); - cairo_move_to (cr, 10, 10); - pango_cairo_show_lines (cr, lines); + pango2_layout_write_to_file (layout, "out.layout"); - g_object_unref (layout); + return layout; } static gboolean -glyph_cb (PangoUserFace *face, +glyph_cb (Pango2UserFace *face, hb_codepoint_t unicode, hb_codepoint_t *glyph, - gpointer data) + gpointer user_data) { - if (unicode == 0x2022 || unicode == 0x2665) + test_scaled_font_glyph_t *glyphs = user_data; + + for (int i = 0; glyphs[i].ucs4 != (gunichar) -1; i++) { - *glyph = unicode; - return TRUE; + if (glyphs[i].ucs4 == unicode) + { + *glyph = i; + return TRUE; + } } return FALSE; } static gboolean -glyph_info_cb (PangoUserFace *face, +glyph_info_cb (Pango2UserFace *face, int size, hb_codepoint_t glyph, hb_glyph_extents_t *extents, @@ -186,99 +134,179 @@ glyph_info_cb (PangoUserFace *face, gboolean *is_color, gpointer user_data) { - if (glyph == 0x2022 || glyph == 0x2665) + test_scaled_font_glyph_t *glyphs = user_data; + + extents->x_bearing = 0; + extents->y_bearing = 0.75 * size; + extents->width = glyphs[glyph].width / 4.0 * size; + extents->height = - size; + + *h_advance = *v_advance = glyphs[glyph].width / 4.0 * size; + + *is_color = FALSE; + + return TRUE; +} + +static gboolean +shape_cb (Pango2UserFace *face, + int size, + const char *text, + int length, + const Pango2Analysis *analysis, + Pango2GlyphString *glyphs, + Pango2ShapeFlags flags, + gpointer user_data) +{ + int n_chars; + const char *p; + int cluster = 0; + int i, j; + int last_cluster; + gboolean is_color; + hb_glyph_extents_t ext; + hb_position_t dummy; + + n_chars = g_utf8_strlen (text, length); + + pango2_glyph_string_set_size (glyphs, n_chars); + + last_cluster = -1; + + p = text; + j = 0; + for (i = 0; i < n_chars; i++) { - extents->x_bearing = 0; - extents->y_bearing = - size; - extents->width = size; - extents->height = size; + gunichar wc; + Pango2Glyph glyph = 0; + Pango2Rectangle logical_rect; + + wc = g_utf8_get_char (p); + + if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK) + cluster = p - text; + + /* Handle the fi ligature */ + if (p[0] == 'f' && p[1] == 'i') + { + p = g_utf8_next_char (p); + i++; + glyph_cb (face, 0xe000, &glyph, user_data); + } + else if (pango2_is_zero_width (wc)) + glyph = PANGO2_GLYPH_EMPTY; + else if (!glyph_cb (face, wc, &glyph, user_data)) + glyph = PANGO2_GET_UNKNOWN_GLYPH (wc); + + glyph_info_cb (face, size, glyph, &ext, &dummy, &dummy, &is_color, user_data); + pango2_font_get_glyph_extents (pango2_analysis_get_font (analysis), glyph, NULL, &logical_rect); + + glyphs->glyphs[j].glyph = glyph; + + glyphs->glyphs[j].attr.is_cluster_start = cluster != last_cluster; + glyphs->glyphs[j].attr.is_color = is_color; - *h_advance = size; - *v_advance = size; - *is_color = glyph == 0x2665; + glyphs->glyphs[j].geometry.x_offset = 0; + glyphs->glyphs[j].geometry.y_offset = 0; + glyphs->glyphs[j].geometry.width = logical_rect.width; - return TRUE; + glyphs->log_clusters[j] = cluster; + + j++; + + last_cluster = cluster; + + p = g_utf8_next_char (p); } - return FALSE; + glyphs->num_glyphs = j; + +#if 0 + /* FIXME export this */ + if (analysis->level & 1) + pango2_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs); +#endif + + return TRUE; } static gboolean -font_info_cb (PangoUserFace *face, +font_info_cb (Pango2UserFace *face, int size, hb_font_extents_t *extents, gpointer user_data) { - extents->ascender = size; - extents->descender = 0; + extents->ascender = 0.75 * size; + extents->descender = - 0.25 * size; extents->line_gap = 0; return TRUE; } static gboolean -render_cb (PangoUserFace *face, +render_cb (Pango2UserFace *face, int size, hb_codepoint_t glyph, gpointer user_data, const char *backend_id, gpointer backend_data) { + test_scaled_font_glyph_t *glyphs = user_data; cairo_t *cr = backend_data; + const char *data; + div_t d; + double x, y; if (strcmp (backend_id, "cairo") != 0) return FALSE; - if (glyph == 0x2022) - { - MiniSvg *shape = &GnomeFootLogo; - - cairo_move_to (cr, 0, -1); - cairo_scale (cr, 1. / shape->width, 1. / shape->height); + cairo_set_line_width (cr, 0.1); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - mini_svg_render (shape, cr); - - return TRUE; - } - else if (glyph == 0x2665) + data = glyphs[glyph].data; + for (int i = 0; data[i] != END_GLYPH; i++) { - cairo_set_source_rgb (cr, 1., 0., 0.); - - cairo_move_to (cr, .5, .0); - cairo_line_to (cr, .9, -.4); - cairo_curve_to (cr, 1.1, -.8, .5, -.9, .5, -.5); - cairo_curve_to (cr, .5, -.9, -.1, -.8, .1, -.4); - cairo_close_path (cr); - cairo_fill (cr); - - return TRUE; + switch (data[i]) + { + case STROKE: + cairo_new_sub_path (cr); + break; + + case CLOSE: + cairo_close_path (cr); + break; + + default: + d = div (data[i] - 1, 3); + x = d.rem / 4.0 + 0.125; + y = d.quot / 5.0 + 0.4 - 1.0; + cairo_line_to (cr, x, y); + } } - return FALSE; + cairo_stroke (cr); + + return TRUE; } static void -setup_fontmap (void) +setup_fontmap (Pango2FontMap *fontmap) { - PangoFontMap *fontmap = pango_font_map_get_default (); - PangoFontDescription *desc; - PangoUserFace *face; - - desc = pango_font_description_new (); - pango_font_description_set_family (desc, "Bullets"); + Pango2FontDescription *desc; + Pango2UserFace *face; - /* Create our fancy user font, "Bullets Black" */ - face = pango_user_face_new (font_info_cb, + desc = pango2_font_description_new (); + pango2_font_description_set_family (desc, "Userfont"); + face = pango2_user_face_new (font_info_cb, glyph_cb, glyph_info_cb, - NULL, + shape_cb, render_cb, - NULL, NULL, "Black", desc); - - /* And add it to the default fontmap */ - pango_font_map_add_face (fontmap, PANGO_FONT_FACE (face)); - - pango_font_description_free (desc); + (gpointer) glyphs, NULL, + "Black", desc); + pango2_font_map_add_face (fontmap, PANGO2_FONT_FACE (face)); + pango2_font_description_free (desc); } int @@ -288,36 +316,47 @@ main (int argc, char **argv) char *filename; cairo_status_t status; cairo_surface_t *surface; - int width, height; + Pango2Layout *layout; + Pango2Rectangle ext; if (argc != 2) { - g_printerr ("Usage: cairoshape OUTPUT_FILENAME\n"); + g_printerr ("Usage: userfont OUTPUT_FILENAME\n"); return 1; } filename = argv[1]; - setup_fontmap (); + fontmap = PANGO2_FONT_MAP (pango2_font_map_new_default ()); + setup_fontmap (PANGO2_FONT_MAP (fontmap)); - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); - cr = cairo_create (surface); - measure_text (cr, &width, &height); - cairo_destroy (cr); - cairo_surface_destroy (surface); + layout = get_layout (); + + pango2_lines_get_extents (pango2_layout_get_lines (layout), NULL, &ext); + pango2_extents_to_pixels (&ext, NULL); /* Now create the final surface and draw to it. */ - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ext.width + 20, ext.height + 20); cr = cairo_create (surface); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_paint (cr); cairo_set_source_rgb (cr, 0.0, 0.0, 0.5); - draw_text (cr); + + cairo_move_to (cr, 10, 10); + pango2_cairo_show_layout (cr, layout); + cairo_destroy (cr); + g_object_unref (layout); + /* Write out the surface as PNG */ +#ifdef CAIRO_HAS_PNG_FUNCTIONS status = cairo_surface_write_to_png (surface, filename); +#else + status = CAIRO_STATUS_PNG_ERROR; /* Not technically correct, but... */ +#endif + cairo_surface_destroy (surface); if (status != CAIRO_STATUS_SUCCESS) |