[pango/pango2: 45/56] docs: Add a complex layout example
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango/pango2: 45/56] docs: Add a complex layout example
- Date: Tue, 14 Jun 2022 03:59:26 +0000 (UTC)
commit 283ebbfb6af90eee690eabf17f34d55bf0bffbf6
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Jun 12 19:18:34 2022 -0400
docs: Add a complex layout example
docs/meson.build | 2 +
docs/pango.toml.in | 2 +
docs/pango_layout.md | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++
docs/parshape.png | Bin 0 -> 48251 bytes
examples/parshape.c | 86 ++++++++++++++------------
5 files changed, 221 insertions(+), 37 deletions(-)
---
diff --git a/docs/meson.build b/docs/meson.build
index 0d320590a..58543b015 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -8,6 +8,7 @@ pango_content_files = [
'pango_bidi.md',
'pango_cairo.md',
'pango_user.md',
+ 'pango_layout.md',
'pango-name.png',
'layout-light.png',
'layout-dark.png',
@@ -56,6 +57,7 @@ pango_content_files = [
'rotated-text.png',
'bullets.png',
'first-steps.png',
+ 'parshape.png',
]
doc_conf = configuration_data()
diff --git a/docs/pango.toml.in b/docs/pango.toml.in
index bb6ff5392..77f73456b 100644
--- a/docs/pango.toml.in
+++ b/docs/pango.toml.in
@@ -51,6 +51,7 @@ content_files = [
"pango_bidi.md",
"pango_cairo.md",
"pango_user.md",
+ "pango_layout.md",
]
content_images = [
@@ -101,6 +102,7 @@ content_images = [
"rotated-text.png",
"bullets.png",
"first-steps.png",
+ "parshape.png",
]
urlmap_file = "urlmap.js"
diff --git a/docs/pango_layout.md b/docs/pango_layout.md
new file mode 100644
index 000000000..a4d8e122b
--- /dev/null
+++ b/docs/pango_layout.md
@@ -0,0 +1,168 @@
+---
+Title: Complex layout
+---
+
+# Complex layout
+
+The central object in high-level Pango API is [class@Pango.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
+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
+produce an unusually shaped paragraph with a hole in the middle.
+
+## Using GtkLineBreaker
+
+```
+#include <pango/pango.h>
+#include <pango/pangocairo.h>
+
+static PangoLines *
+format_text (const char *text)
+{
+ PangoContext *context;
+ PangoLineBreaker *breaker;
+ PangoLines *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);
+
+ pango_line_breaker_add_text (breaker, text, -1, NULL);
+
+ lines = pango_lines_new ();
+
+ m = 200;
+ w = 10;
+ w2 = -200;
+ inc = 40;
+
+ y = 40 * PANGO_SCALE;
+ x = (m - w / 2) * PANGO_SCALE;
+ width = w * PANGO_SCALE;
+
+ while (pango_line_breaker_has_line (breaker))
+ {
+ PangoLine *line;
+ PangoRectangle ext;
+ gboolean ltr;
+
+ line = pango_line_breaker_next_line (breaker,
+ x, width,
+ PANGO_WRAP_CHAR,
+ PANGO_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);
+
+ ltr = pango_line_breaker_get_direction (breaker) == PANGO_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;
+ else
+ {
+ y += ext.height;
+
+ w += inc;
+ w2 += inc;
+ if (w + inc >= 340 || w + inc < 0)
+ inc = - inc;
+
+ if (w2 > 0)
+ width = ((w - w2) / 2) * PANGO_SCALE;
+ else
+ width = w * PANGO_SCALE;
+
+ if (ltr)
+ x = (m - w / 2) * PANGO_SCALE;
+ else
+ x = (m + w / 2) * PANGO_SCALE;
+ }
+ }
+
+ g_object_unref (breaker);
+ g_object_unref (context);
+
+ return lines;
+}
+
+static void
+draw_lines (cairo_t *cr, PangoLines *lines)
+{
+ for (int i = 0; i < pango_lines_get_line_count (lines); i++)
+ {
+ PangoLine *line = pango_lines_get_lines (lines)[i];
+ int x, y;
+
+ pango_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_restore (cr);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ const char *filename;
+ PangoLines *lines;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ char *text;
+ gsize length;
+ GError *error = NULL;
+
+ if (argc != 3)
+ {
+ g_printerr ("Usage: %s INPUT_FILENAME OUTPUT_FILENAME\n", argv[0]);
+ return 1;
+ }
+
+ if (!g_file_get_contents (argv[1], &text, &length, &error))
+ {
+ g_printerr ("%s\n", error->message);
+ return 1;
+ }
+
+ filename = argv[2];
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 400, 600);
+ cr = cairo_create (surface);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+
+ lines = format_text (text);
+ draw_lines (cr, lines);
+ g_object_unref (lines);
+
+ cairo_surface_write_to_png (surface, filename);
+ g_print ("Output written to %s\n", filename);
+
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr);
+
+ return 0;
+}
+```
+
+Once you build and run the example code above, you should see the
+following result:
+
+![Output of the example](parshape.png)
diff --git a/docs/parshape.png b/docs/parshape.png
new file mode 100644
index 000000000..6ac8a05da
Binary files /dev/null and b/docs/parshape.png differ
diff --git a/examples/parshape.c b/examples/parshape.c
index e33f9600f..2fe8cbe97 100644
--- a/examples/parshape.c
+++ b/examples/parshape.c
@@ -1,47 +1,18 @@
#include <pango/pango.h>
#include <pango/pangocairo.h>
-int
-main (int argc, char *argv[])
+static PangoLines *
+format_text (const char *text)
{
- const char *filename;
PangoContext *context;
PangoLineBreaker *breaker;
- int x, y, width;
PangoLines *lines;
+ int x, y, width;
int inc, m, w, w2;
- cairo_surface_t *surface;
- cairo_t *cr;
- char *text;
- gsize length;
- GError *error = NULL;
-
- if (argc != 3)
- {
- g_printerr ("Usage: %s INPUT_FILENAME OUTPUT_FILENAME\n", argv[0]);
- return 1;
- }
-
- if (!g_file_get_contents (argv[1], &text, &length, &error))
- {
- g_printerr ("%s\n", error->message);
- return 1;
- }
-
- filename = argv[2];
context = pango_font_map_create_context (pango_font_map_get_default ());
-
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 400, 600);
- cr = cairo_create (surface);
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_paint (cr);
- cairo_set_source_rgb (cr, 0, 0, 0);
-
breaker = pango_line_breaker_new (context);
- g_print ("Using %s\n", G_OBJECT_TYPE_NAME (breaker));
-
pango_line_breaker_add_text (breaker, text, -1, NULL);
lines = pango_lines_new ();
@@ -97,9 +68,19 @@ main (int argc, char *argv[])
}
}
+ g_object_unref (breaker);
+ g_object_unref (context);
+
+ return lines;
+}
+
+static void
+draw_lines (cairo_t *cr, PangoLines *lines)
+{
for (int i = 0; i < pango_lines_get_line_count (lines); i++)
{
PangoLine *line = pango_lines_get_lines (lines)[i];
+ int x, y;
pango_lines_get_line_position (lines, i, &x, &y);
@@ -108,17 +89,48 @@ main (int argc, char *argv[])
pango_cairo_show_line (cr, line);
cairo_restore (cr);
}
+}
- cairo_surface_write_to_png (surface, filename);
- g_print ("Output written to %s\n", filename);
+int
+main (int argc, char *argv[])
+{
+ const char *filename;
+ PangoLines *lines;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ char *text;
+ gsize length;
+ GError *error = NULL;
+
+ if (argc != 3)
+ {
+ g_printerr ("Usage: %s INPUT_FILENAME OUTPUT_FILENAME\n", argv[0]);
+ return 1;
+ }
+
+ if (!g_file_get_contents (argv[1], &text, &length, &error))
+ {
+ g_printerr ("%s\n", error->message);
+ return 1;
+ }
+ filename = argv[2];
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 400, 600);
+ cr = cairo_create (surface);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+
+ lines = format_text (text);
+ draw_lines (cr, lines);
g_object_unref (lines);
- g_object_unref (breaker);
+
+ cairo_surface_write_to_png (surface, filename);
+ g_print ("Output written to %s\n", filename);
cairo_surface_destroy (surface);
cairo_destroy (cr);
- g_object_unref (context);
-
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]