diff options
author | Owen Taylor <otaylor@redhat.com> | 2000-03-08 18:39:49 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2000-03-08 18:39:49 +0000 |
commit | 773bc55fc9e344f8040809ba8796b0ba2805e4c9 (patch) | |
tree | 89e900594294e87b4a4de8f71571762d6ccc8871 | |
parent | dd0b4a5064c6f60adcfd2ea02e2d61fb60254d20 (diff) | |
download | pango-773bc55fc9e344f8040809ba8796b0ba2805e4c9.tar.gz |
First draft of highlevel driver. It currently only handles a paragraph as
Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com>
* libpango/pango-layout.[ch]: First draft of highlevel
driver. It currently only handles a paragraph as a list
of lines, but it is probably necessary to make it handle
2D layout for a paragraph as well
* examples/viewer.c: Move over to new layout driver
(much of the code moved into pango-layout.c)
* libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(),
add pango_glyph_string_get_logical_widths.
* libpango/pango-itemize.c: Handle 0-length text properly.
* libpango/pangox.c: When loading particular sized fonts,
use the original XLFD, since XFree86 doesn't handle wildcards
in aliases properly.
* libpango/pangox.[ch] (pango_x_render_layout_line): Add function
to render an entire PangoLayoutLine.
* libpango/reorder-items.c: Add a note to the effect
that pango_reorder_items() is basically replaced by a
similar function in PangoLayout.
Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com>
* modules/arabic/arconv.c (shapecount): Fix from Karl
Koehler to joining behavior.
* modules/Makefile.am modules/arabic/*: Added arabic
shaper from Karl Koehler <koehler@or.uni-bonn.de>
* modules/basic/tables-{small,big}.i: Remove arabic
from the ranges that the basic shaper marks as "exact".
* examples/HELLO.utf8: Partially alphabetize, add arabic.
-rw-r--r-- | .cvsignore | 1 | ||||
-rw-r--r-- | ChangeLog | 43 | ||||
-rw-r--r-- | ChangeLog.pre-1-0 | 43 | ||||
-rw-r--r-- | ChangeLog.pre-1-10 | 43 | ||||
-rw-r--r-- | ChangeLog.pre-1-2 | 43 | ||||
-rw-r--r-- | ChangeLog.pre-1-4 | 43 | ||||
-rw-r--r-- | ChangeLog.pre-1-6 | 43 | ||||
-rw-r--r-- | ChangeLog.pre-1-8 | 43 | ||||
-rw-r--r-- | configure.in | 3 | ||||
-rw-r--r-- | docs/tmpl/layout.sgml | 195 | ||||
-rw-r--r-- | examples/HELLO.utf8 | 7 | ||||
-rw-r--r-- | examples/pango.modules | 6 | ||||
-rw-r--r-- | examples/viewer.c | 541 | ||||
-rw-r--r-- | modules/Makefile.am | 2 | ||||
-rw-r--r-- | modules/basic/tables-big.i | 3 | ||||
-rw-r--r-- | modules/basic/tables-small.i | 3 | ||||
-rw-r--r-- | pango/Makefile.am | 1 | ||||
-rw-r--r-- | pango/glyphstring.c | 73 | ||||
-rw-r--r-- | pango/itemize.c | 13 | ||||
-rw-r--r-- | pango/mapping.c | 2 | ||||
-rw-r--r-- | pango/pango-context.c | 8 | ||||
-rw-r--r-- | pango/pango-glyph.h | 6 | ||||
-rw-r--r-- | pango/pango-layout.c | 873 | ||||
-rw-r--r-- | pango/pango-layout.h | 71 | ||||
-rw-r--r-- | pango/pangox.c | 106 | ||||
-rw-r--r-- | pango/pangox.h | 45 | ||||
-rw-r--r-- | pango/reorder-items.c | 10 |
27 files changed, 1713 insertions, 557 deletions
@@ -5,6 +5,7 @@ config.cache config.log config.status pango.spec +pango-config stamp-h libtool Makefile @@ -1,3 +1,46 @@ +Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: First draft of highlevel + driver. It currently only handles a paragraph as a list + of lines, but it is probably necessary to make it handle + 2D layout for a paragraph as well + + * examples/viewer.c: Move over to new layout driver + (much of the code moved into pango-layout.c) + + * libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(), + add pango_glyph_string_get_logical_widths. + + * libpango/pango-itemize.c: Handle 0-length text properly. + + * libpango/pangox.c: When loading particular sized fonts, + use the original XLFD, since XFree86 doesn't handle wildcards + in aliases properly. + + * libpango/pangox.[ch] (pango_x_render_layout_line): Add function + to render an entire PangoLayoutLine. + + * libpango/reorder-items.c: Add a note to the effect + that pango_reorder_items() is basically replaced by a + similar function in PangoLayout. + +Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com> + + * modules/arabic/arconv.c (shapecount): Fix from Karl + Koehler to joining behavior. + + * modules/Makefile.am modules/arabic/*: Added arabic + shaper from Karl Koehler <koehler@or.uni-bonn.de> + + * modules/basic/tables-{small,big}.i: Remove arabic + from the ranges that the basic shaper marks as "exact". + + * examples/HELLO.utf8: Partially alphabetize, add arabic. + +Mon Mar 6 21:03:28 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: Started work on highlevel layout driver. + Mon Mar 6 20:55:32 2000 Owen Taylor <otaylor@redhat.com> * libpango/mapping.c example/viewer.c: diff --git a/ChangeLog.pre-1-0 b/ChangeLog.pre-1-0 index c3b78dbf..adeda523 100644 --- a/ChangeLog.pre-1-0 +++ b/ChangeLog.pre-1-0 @@ -1,3 +1,46 @@ +Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: First draft of highlevel + driver. It currently only handles a paragraph as a list + of lines, but it is probably necessary to make it handle + 2D layout for a paragraph as well + + * examples/viewer.c: Move over to new layout driver + (much of the code moved into pango-layout.c) + + * libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(), + add pango_glyph_string_get_logical_widths. + + * libpango/pango-itemize.c: Handle 0-length text properly. + + * libpango/pangox.c: When loading particular sized fonts, + use the original XLFD, since XFree86 doesn't handle wildcards + in aliases properly. + + * libpango/pangox.[ch] (pango_x_render_layout_line): Add function + to render an entire PangoLayoutLine. + + * libpango/reorder-items.c: Add a note to the effect + that pango_reorder_items() is basically replaced by a + similar function in PangoLayout. + +Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com> + + * modules/arabic/arconv.c (shapecount): Fix from Karl + Koehler to joining behavior. + + * modules/Makefile.am modules/arabic/*: Added arabic + shaper from Karl Koehler <koehler@or.uni-bonn.de> + + * modules/basic/tables-{small,big}.i: Remove arabic + from the ranges that the basic shaper marks as "exact". + + * examples/HELLO.utf8: Partially alphabetize, add arabic. + +Mon Mar 6 21:03:28 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: Started work on highlevel layout driver. + Mon Mar 6 20:55:32 2000 Owen Taylor <otaylor@redhat.com> * libpango/mapping.c example/viewer.c: diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10 index c3b78dbf..adeda523 100644 --- a/ChangeLog.pre-1-10 +++ b/ChangeLog.pre-1-10 @@ -1,3 +1,46 @@ +Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: First draft of highlevel + driver. It currently only handles a paragraph as a list + of lines, but it is probably necessary to make it handle + 2D layout for a paragraph as well + + * examples/viewer.c: Move over to new layout driver + (much of the code moved into pango-layout.c) + + * libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(), + add pango_glyph_string_get_logical_widths. + + * libpango/pango-itemize.c: Handle 0-length text properly. + + * libpango/pangox.c: When loading particular sized fonts, + use the original XLFD, since XFree86 doesn't handle wildcards + in aliases properly. + + * libpango/pangox.[ch] (pango_x_render_layout_line): Add function + to render an entire PangoLayoutLine. + + * libpango/reorder-items.c: Add a note to the effect + that pango_reorder_items() is basically replaced by a + similar function in PangoLayout. + +Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com> + + * modules/arabic/arconv.c (shapecount): Fix from Karl + Koehler to joining behavior. + + * modules/Makefile.am modules/arabic/*: Added arabic + shaper from Karl Koehler <koehler@or.uni-bonn.de> + + * modules/basic/tables-{small,big}.i: Remove arabic + from the ranges that the basic shaper marks as "exact". + + * examples/HELLO.utf8: Partially alphabetize, add arabic. + +Mon Mar 6 21:03:28 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: Started work on highlevel layout driver. + Mon Mar 6 20:55:32 2000 Owen Taylor <otaylor@redhat.com> * libpango/mapping.c example/viewer.c: diff --git a/ChangeLog.pre-1-2 b/ChangeLog.pre-1-2 index c3b78dbf..adeda523 100644 --- a/ChangeLog.pre-1-2 +++ b/ChangeLog.pre-1-2 @@ -1,3 +1,46 @@ +Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: First draft of highlevel + driver. It currently only handles a paragraph as a list + of lines, but it is probably necessary to make it handle + 2D layout for a paragraph as well + + * examples/viewer.c: Move over to new layout driver + (much of the code moved into pango-layout.c) + + * libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(), + add pango_glyph_string_get_logical_widths. + + * libpango/pango-itemize.c: Handle 0-length text properly. + + * libpango/pangox.c: When loading particular sized fonts, + use the original XLFD, since XFree86 doesn't handle wildcards + in aliases properly. + + * libpango/pangox.[ch] (pango_x_render_layout_line): Add function + to render an entire PangoLayoutLine. + + * libpango/reorder-items.c: Add a note to the effect + that pango_reorder_items() is basically replaced by a + similar function in PangoLayout. + +Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com> + + * modules/arabic/arconv.c (shapecount): Fix from Karl + Koehler to joining behavior. + + * modules/Makefile.am modules/arabic/*: Added arabic + shaper from Karl Koehler <koehler@or.uni-bonn.de> + + * modules/basic/tables-{small,big}.i: Remove arabic + from the ranges that the basic shaper marks as "exact". + + * examples/HELLO.utf8: Partially alphabetize, add arabic. + +Mon Mar 6 21:03:28 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: Started work on highlevel layout driver. + Mon Mar 6 20:55:32 2000 Owen Taylor <otaylor@redhat.com> * libpango/mapping.c example/viewer.c: diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4 index c3b78dbf..adeda523 100644 --- a/ChangeLog.pre-1-4 +++ b/ChangeLog.pre-1-4 @@ -1,3 +1,46 @@ +Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: First draft of highlevel + driver. It currently only handles a paragraph as a list + of lines, but it is probably necessary to make it handle + 2D layout for a paragraph as well + + * examples/viewer.c: Move over to new layout driver + (much of the code moved into pango-layout.c) + + * libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(), + add pango_glyph_string_get_logical_widths. + + * libpango/pango-itemize.c: Handle 0-length text properly. + + * libpango/pangox.c: When loading particular sized fonts, + use the original XLFD, since XFree86 doesn't handle wildcards + in aliases properly. + + * libpango/pangox.[ch] (pango_x_render_layout_line): Add function + to render an entire PangoLayoutLine. + + * libpango/reorder-items.c: Add a note to the effect + that pango_reorder_items() is basically replaced by a + similar function in PangoLayout. + +Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com> + + * modules/arabic/arconv.c (shapecount): Fix from Karl + Koehler to joining behavior. + + * modules/Makefile.am modules/arabic/*: Added arabic + shaper from Karl Koehler <koehler@or.uni-bonn.de> + + * modules/basic/tables-{small,big}.i: Remove arabic + from the ranges that the basic shaper marks as "exact". + + * examples/HELLO.utf8: Partially alphabetize, add arabic. + +Mon Mar 6 21:03:28 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: Started work on highlevel layout driver. + Mon Mar 6 20:55:32 2000 Owen Taylor <otaylor@redhat.com> * libpango/mapping.c example/viewer.c: diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6 index c3b78dbf..adeda523 100644 --- a/ChangeLog.pre-1-6 +++ b/ChangeLog.pre-1-6 @@ -1,3 +1,46 @@ +Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: First draft of highlevel + driver. It currently only handles a paragraph as a list + of lines, but it is probably necessary to make it handle + 2D layout for a paragraph as well + + * examples/viewer.c: Move over to new layout driver + (much of the code moved into pango-layout.c) + + * libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(), + add pango_glyph_string_get_logical_widths. + + * libpango/pango-itemize.c: Handle 0-length text properly. + + * libpango/pangox.c: When loading particular sized fonts, + use the original XLFD, since XFree86 doesn't handle wildcards + in aliases properly. + + * libpango/pangox.[ch] (pango_x_render_layout_line): Add function + to render an entire PangoLayoutLine. + + * libpango/reorder-items.c: Add a note to the effect + that pango_reorder_items() is basically replaced by a + similar function in PangoLayout. + +Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com> + + * modules/arabic/arconv.c (shapecount): Fix from Karl + Koehler to joining behavior. + + * modules/Makefile.am modules/arabic/*: Added arabic + shaper from Karl Koehler <koehler@or.uni-bonn.de> + + * modules/basic/tables-{small,big}.i: Remove arabic + from the ranges that the basic shaper marks as "exact". + + * examples/HELLO.utf8: Partially alphabetize, add arabic. + +Mon Mar 6 21:03:28 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: Started work on highlevel layout driver. + Mon Mar 6 20:55:32 2000 Owen Taylor <otaylor@redhat.com> * libpango/mapping.c example/viewer.c: diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8 index c3b78dbf..adeda523 100644 --- a/ChangeLog.pre-1-8 +++ b/ChangeLog.pre-1-8 @@ -1,3 +1,46 @@ +Wed Mar 8 13:34:57 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: First draft of highlevel + driver. It currently only handles a paragraph as a list + of lines, but it is probably necessary to make it handle + 2D layout for a paragraph as well + + * examples/viewer.c: Move over to new layout driver + (much of the code moved into pango-layout.c) + + * libpango/glyphs.c libpango/pango-glyphs.h: Fixes to get_extents(), + add pango_glyph_string_get_logical_widths. + + * libpango/pango-itemize.c: Handle 0-length text properly. + + * libpango/pangox.c: When loading particular sized fonts, + use the original XLFD, since XFree86 doesn't handle wildcards + in aliases properly. + + * libpango/pangox.[ch] (pango_x_render_layout_line): Add function + to render an entire PangoLayoutLine. + + * libpango/reorder-items.c: Add a note to the effect + that pango_reorder_items() is basically replaced by a + similar function in PangoLayout. + +Wed Mar 8 10:58:56 2000 Owen Taylor <otaylor@redhat.com> + + * modules/arabic/arconv.c (shapecount): Fix from Karl + Koehler to joining behavior. + + * modules/Makefile.am modules/arabic/*: Added arabic + shaper from Karl Koehler <koehler@or.uni-bonn.de> + + * modules/basic/tables-{small,big}.i: Remove arabic + from the ranges that the basic shaper marks as "exact". + + * examples/HELLO.utf8: Partially alphabetize, add arabic. + +Mon Mar 6 21:03:28 2000 Owen Taylor <otaylor@redhat.com> + + * libpango/pango-layout.[ch]: Started work on highlevel layout driver. + Mon Mar 6 20:55:32 2000 Owen Taylor <otaylor@redhat.com> * libpango/mapping.c example/viewer.c: diff --git a/configure.in b/configure.in index 1ec15e12..1376761c 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl Process this file with autoconf to create configure. AC_INIT(ChangeLog) -AM_INIT_AUTOMAKE(pango, 0.7) +AM_INIT_AUTOMAKE(pango, 0.8) AM_CONFIG_HEADER(config.h) @@ -64,6 +64,7 @@ AC_OUTPUT([ Makefile libpango/Makefile modules/Makefile +modules/arabic/Makefile modules/basic/Makefile modules/hangul/Makefile modules/tamil/Makefile diff --git a/docs/tmpl/layout.sgml b/docs/tmpl/layout.sgml new file mode 100644 index 00000000..aa44fd98 --- /dev/null +++ b/docs/tmpl/layout.sgml @@ -0,0 +1,195 @@ +<!-- ##### SECTION Title ##### --> +Layout Objects + +<!-- ##### SECTION Short_Description ##### --> +Layout driver objects for entire paragraphs. + +<!-- ##### SECTION Long_Description ##### --> +<para> +While complete access to the layout capabilities of Pango is provided +using the detailed interfaces for itemization and shaping, using +that functionality directly involves writing a fairly large amount +of code. The objects and functions in this structure provide a +high-level driver for formatting entire paragraphs of text +at once. +</para> + +<!-- ##### SECTION See_Also ##### --> +<para> + +</para> + +<!-- ##### STRUCT PangoLayout ##### --> +<para> +The #PangoLayout structure represents and entire paragraph +of text. It is initialized with a #PangoContext, UTF-8 string +and set of attirbutes for that string. Once that is done, the +set of formatted lines can be extracted from the object. +</para> + + +<!-- ##### STRUCT PangoLayoutLine ##### --> +<para> +The #PangoLayoutLine structure represents one of the lines resulting +from laying out a paragraph via #PangoLayout. #PangoLayoutLine +structures are obtained by calling pango_layout_get_line() and +are only valid until the text, attributes, or settings of the +parent #PangoLayout are modified. +</para> +<para> +Routines for rendering PangoLayout objects are provided in +code specific to each rendering system. +</para> + +@layout: the parent layout for this line. +@n_chars: the total number of characters in the line. +@length: the length of the line in bytes. +@runs: a list containing the runs of the line in visual order. + +<!-- ##### STRUCT PangoLayoutRun ##### --> +<para> +The #PangoLayoutRun structure represents a single run within +a #PangoLayoutLine. +</para> + +@item: a #PangoItem structure that provides information + about the segment of text in this run. +@glyphs: the glyphs obtained by shaping the text for this item. + +<!-- ##### FUNCTION pango_layout_new ##### --> +<para> + +</para> + +@Returns: + + +<!-- ##### FUNCTION pango_layout_ref ##### --> +<para> + +</para> + +@layout: + + +<!-- ##### FUNCTION pango_layout_unref ##### --> +<para> + +</para> + +@layout: + + +<!-- ##### FUNCTION pango_layout_set_text ##### --> +<para> + +</para> + +@text: +@length: + + +<!-- ##### FUNCTION pango_layout_set_attributes ##### --> +<para> + +</para> + +@layout: +@attrs: + + +<!-- ##### FUNCTION pango_layout_set_width ##### --> +<para> + +</para> + +@layout: +@width: + + +<!-- ##### FUNCTION pango_layout_set_first_line_width ##### --> +<para> + +</para> + +@layout: +@width: + + +<!-- ##### FUNCTION pango_layout_set_justify ##### --> +<para> + +</para> + +@layout: +@justify: + + +<!-- ##### FUNCTION pango_layout_cp_to_line_x ##### --> +<para> + +</para> + +@layout: +@char_pos: +@trailing: +@line: +@x_pos: + + +<!-- ##### FUNCTION pango_layout_get_line_count ##### --> +<para> + +</para> + +@layout: +@Returns: + + +<!-- ##### FUNCTION pango_layout_get_line ##### --> +<para> + +</para> + +@layout: +@line: +@Returns: + + +<!-- ##### FUNCTION pango_layout_line_ref ##### --> +<para> + +</para> + +@line: + + +<!-- ##### FUNCTION pango_layout_line_unref ##### --> +<para> + +</para> + +@line: + + +<!-- ##### FUNCTION pango_layout_line_x_to_cp ##### --> +<para> + +</para> + +@line: +@x_pos: +@char_pos: +@trailing: + + +<!-- ##### FUNCTION pango_layout_line_get_extents ##### --> +<para> + +</para> + +@line: +@ink_rect: +@logical_rect: + + diff --git a/examples/HELLO.utf8 b/examples/HELLO.utf8 index c7f798e7..f0fc95c3 100644 --- a/examples/HELLO.utf8 +++ b/examples/HELLO.utf8 @@ -5,6 +5,8 @@ This is a list of ways to say hello in various languages. Its purpose is to illu (Converted into UTF-8) --------------------------------------------------------- +Arabic السلام عليكم +Czech (česky) Dobrý den Danish (Dansk) Hej, Goddag English Hello Esperanto Saluton @@ -20,12 +22,11 @@ Italiano Ciao, Buon giorno Maltese Ċaw, Saħħa Nederlands, Vlaams Hallo, Dag Norwegian (Norsk) Hei, God dag +Polish Dzień dobry, Hej Russian (Русский) Здравствуйте! +Slovak Dobrý deň Spanish (Español) ¡Hola! Swedish (Svenska) Hej, Goddag -Czech (česky) Dobrý den -Polish Dzień dobry, Hej -Slovak Dobrý deň Thai (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ Turkish (Türkçe) Merhaba diff --git a/examples/pango.modules b/examples/pango.modules deleted file mode 100644 index e945bf29..00000000 --- a/examples/pango.modules +++ /dev/null @@ -1,6 +0,0 @@ -/home/otaylor/devel/pango/modules/./basic/.libs/pango-basic.so BasicScriptEngineLang PangoEngineLang PangoRenderNone 0-687:* 688-767: 896-1423:* 1425-1641:* 7680-8191:* 8192-40959:* 44032-55203:kr 63744-64011:kr 65280-65507:* -/home/otaylor/devel/pango/modules/./basic/.libs/pango-basic.so BasicScriptEngineX PangoEngineShape PangoRenderX 0-687:* 688-767: 896-1423:* 1425-1641:* 7680-8191:* 8192-40959:* 44032-55203:kr 63744-64011:kr 65280-65507:* -/home/otaylor/devel/pango/modules/./hangul/.libs/pango-hangul.so HangulScriptEngineLang PangoEngineLang PangoRenderNone 4352-4607:* 44032-55203:* -/home/otaylor/devel/pango/modules/./hangul/.libs/pango-hangul.so HangulScriptEngineX PangoEngineShape PangoRenderX 4352-4607:* 44032-55203:* -/home/otaylor/devel/pango/modules/./tamil/.libs/pango-tamil.so TamilScriptEngineLang PangoEngineLang PangoRenderNone 2944-3071:* -/home/otaylor/devel/pango/modules/./tamil/.libs/pango-tamil.so TamilScriptEngineX PangoEngineShape PangoRenderX 2944-3071:* diff --git a/examples/viewer.c b/examples/viewer.c index 832a248b..0ff8a503 100644 --- a/examples/viewer.c +++ b/examples/viewer.c @@ -47,12 +47,12 @@ struct _Paragraph { char *text; int length; int height; /* Height, in pixels */ - GList *lines; + PangoLayout *layout; }; /* Structure representing a line */ -struct _Line { + struct _Line { /* List of PangoItems for this paragraph in visual order */ GList *runs; int ascent; /* Ascent of line, in pixels */ @@ -143,7 +143,9 @@ split_paragraphs (char *text) para->text = last_para; para->length = p - last_para; para->height = 0; - para->lines = NULL; + para->layout = pango_layout_new (context); + pango_layout_set_text (para->layout, para->text, para->length); + last_para = next; result = g_list_prepend (result, para); @@ -156,335 +158,42 @@ split_paragraphs (char *text) return g_list_reverse (result); } -static void -get_logical_widths (char *text, PangoItem *item, - PangoGlyphString *glyphs, - PangoGlyphUnit *logical_widths) -{ - int i, j; - int last_cluster = 0; - int width = 0; - int last_cluster_width = 0; - char *p = text + item->offset; - - for (i=0; i<=glyphs->num_glyphs; i++) - { - int index = (item->analysis.level % 2 == 0) ? i : glyphs->num_glyphs - i; - - if (index == glyphs->num_glyphs || - p != text + item->offset + glyphs->log_clusters[index]) - { - gint next_cluster; - - if (index < glyphs->num_glyphs) - { - next_cluster = last_cluster; - while (p < text + item->offset + glyphs->log_clusters[index]) - { - next_cluster++; - p = unicode_next_utf8 (p); - } - } - else - next_cluster = item->num_chars; - - for (j=last_cluster; j<next_cluster; j++) - logical_widths[j] = (width - last_cluster_width) / (next_cluster - last_cluster); - - last_cluster = next_cluster; - last_cluster_width = width; - } - - if (i < glyphs->num_glyphs) - width += glyphs->glyphs[i].geometry.width; - } -} - -/* Break an item into a piece that fits on the current line - * and the remainder. (The remainder, if any is stored into - * 'new_item'. If no piece of the item fits on the current line, - * returns FALSE. - */ - -gboolean -break_run (char *text, - PangoItem *item, - int *remaining_width, - PangoItem **new_item, - int *logical_ascent, - int *logical_descent) -{ - PangoGlyphString *buf; - gboolean result; - PangoRectangle logical_rect; - int width; - - /* First try the entire string to see if it fits. If it - * doesn't, call GStringBreak, then chop off pieces - * from the end until it fits. If it still doesn't - * fit, give up and return FALSE. - */ - - buf = pango_glyph_string_new(); - - pango_shape (text + item->offset, item->length, &item->analysis, buf); - pango_glyph_string_extents (buf, item->analysis.font, NULL, &logical_rect); - width = logical_rect.width; - - result = FALSE; - *new_item = NULL; - - if (width <= 1000 * *remaining_width) - { - result = TRUE; - } - else - { - int length; - int num_chars = item->num_chars; - int new_width; - - PangoLogAttr *log_attrs = g_new (PangoLogAttr, item->num_chars); - PangoGlyphUnit *log_widths = g_new (PangoGlyphUnit, item->num_chars); - - pango_break (text + item->offset, item->length, &item->analysis, - log_attrs); - get_logical_widths (text, item, buf, log_widths); - - new_width = 0; - while (--num_chars > 0) - { - /* Shorten the item by one line break - */ - width -= log_widths[num_chars]; - if (log_attrs[num_chars].is_break && width <= 1000 * *remaining_width) - break; - } - - if (num_chars != 0) - { - char *p; - gint n; - - /* Determine utf8 length corresponding to num_chars. Slow? - */ - n = num_chars; - p = text + item->offset; - while (n-- > 0) - p = unicode_next_utf8 (p); - - length = p - (text + item->offset); - - *new_item = g_new (PangoItem, 1); - (*new_item)->offset = item->offset + length; - (*new_item)->length = item->length - length; - (*new_item)->num_chars = item->num_chars - num_chars; - (*new_item)->analysis = item->analysis; - pango_font_ref ((*new_item)->analysis.font); - - item->length = length; - item->num_chars = num_chars; - - result = TRUE; - } - - g_free (log_attrs); - g_free (log_widths); - } - - pango_shape (text + item->offset, item->length, &item->analysis, buf); - pango_glyph_string_extents (buf, item->analysis.font, NULL, &logical_rect); - - *logical_ascent = PANGO_ASCENT (logical_rect) / 1000; - *logical_descent = PANGO_DESCENT (logical_rect) / 1000; - - if (result) - *remaining_width -= logical_rect.width / 1000; - - pango_glyph_string_free (buf); - - return result; -} - -static void -free_item (PangoItem *item) -{ - pango_font_unref (item->analysis.font); - g_free (item); -} - -static void -free_line (Line *line) -{ - g_list_foreach (line->runs, (GFunc)free_item, NULL); - g_list_free (line->runs); - g_free (line); -} - -static void -para_free_lines (Paragraph *para) -{ - g_list_foreach (para->lines, (GFunc)free_line, NULL); - g_list_free (para->lines); - para->lines = NULL; -} - /* Break a paragraph into a list of lines which fit into * width, and compute the total height of the new paragraph */ void layout_paragraph (Paragraph *para, int width) { - Line *line = NULL; - GList *runs; - int remaining_width; + GSList *line_list; + PangoRectangle logical_rect; int height = 0; - PangoDirection base_dir = pango_context_get_base_dir (context); - PangoAttrList *attrs; - /* Break paragraph into runs with consistent shaping engine - * and direction - */ - attrs = pango_attr_list_new (); - runs = pango_itemize (context, para->text, para->length, attrs); - pango_attr_list_unref (attrs); - - para_free_lines (para); - - /* Break runs to fit on each line - */ - remaining_width = width; - para->lines = NULL; - while (runs) - { - PangoItem *new_item; - gboolean fits; - int logical_ascent; - int logical_descent; - - fits = break_run (para->text, runs->data, &remaining_width, &new_item, - &logical_ascent, &logical_descent); - - if (new_item) - { - /* The item was split, add the remaining portion into our - * lists of runs - */ - GList *node = g_list_alloc(); - - node->data = new_item; - node->next = runs->next; - if (node->next) - node->next->prev = node; - node->prev = runs; - - runs->next = node; - } - - if (fits || !line) - { - /* Either we have a portion that fits on our line, - * or the initial unbreakable portion of the run - * doesn't fit on a complete line, so we just - * add it in anyways. - */ - GList *tmp_list = runs->next; - - if (!line) - { - line = g_new (Line, 1); - line->runs = NULL; - line->ascent = 0; - line->descent = 0; - } - - if (line->runs) - line->runs->prev = runs; - runs->next = line->runs; - line->runs = runs; - - line->ascent = MAX (line->ascent, logical_ascent); - line->descent = MAX (line->descent, logical_descent); - - runs = tmp_list; - if (runs) - runs->prev = NULL; - } - - if (!runs || !fits || remaining_width == 0) - { - /* A complete line, add to our list of lines - */ - GList *visual_list; - - line->offset = (base_dir == PANGO_DIRECTION_RTL) ? remaining_width : 0; - line->runs = g_list_reverse (line->runs); - remaining_width = width; - height += line->ascent + line->descent; - - /* Reorder the runs from logical to visual order - */ - visual_list = pango_reorder_items (line->runs); - g_list_free (line->runs); - line->runs = visual_list; - - para->lines = g_list_append (para->lines, line); - - line = NULL; - } - } - - para->height = height; -} - -/* Given a x position within a run, determine the corresponding - * character offset. - */ -gboolean -runs_x_to_cp (char *text, GList *runs, int x, int *offset) -{ - PangoGlyphString *buf; - int pixels = 0; + pango_layout_set_width (para->layout, width * 1000); + pango_layout_set_first_line_width (para->layout, width * 1000); - buf = pango_glyph_string_new(); - - while (runs) + line_list = pango_layout_get_lines (para->layout); + while (line_list) { - PangoItem *item = runs->data; - PangoRectangle logical_rect; - - pango_shape (text + item->offset, item->length, &item->analysis, buf); - pango_glyph_string_extents (buf, item->analysis.font, NULL, &logical_rect); - - if (x >= pixels && x < pixels + logical_rect.width / 1000) - { - pango_glyph_string_x_to_index (buf, text + item->offset, item->length, - &item->analysis, (x - pixels) * 1000, - offset, NULL); - if (offset) - *offset += item->offset; - - return TRUE; - } + PangoLayoutLine *line = line_list->data; + line_list = line_list->next; - pixels += logical_rect.width / 1000; - runs = runs->next; + pango_layout_line_get_extents (line, NULL, &logical_rect); + height += logical_rect.height; } - pango_glyph_string_free (buf); - - return FALSE; + para->height = height / 1000; } /* Given an x-y position, return the paragraph and offset * within the paragraph of the click. */ gboolean -xy_to_cp (GList *paragraphs, int x, int y, +xy_to_cp (GList *paragraphs, int width, int x, int y, Paragraph **para_return, int *offset) { - GList *para_list, *line_list; + GList *para_list; int height = 0; + PangoDirection base_dir = pango_context_get_base_dir (context); *para_return = NULL; @@ -495,16 +204,27 @@ xy_to_cp (GList *paragraphs, int x, int y, if (height + para->height >= y) { - line_list = para->lines; + PangoRectangle logical_rect; + GSList *line_list = pango_layout_get_lines (para->layout); + while (line_list) { - Line *line = line_list->data; + PangoLayoutLine *line = line_list->data; + int line_y = (y - height) * 1000; + int line_height = 0; + + pango_layout_line_get_extents (line_list->data, NULL, &logical_rect); - if (height + line->ascent + line->descent >= y) + if (line_height + logical_rect.height >= line_y) { - if (runs_x_to_cp (para->text, line->runs, - x - line->offset, - offset)) + int x_offset; + + if (base_dir == PANGO_DIRECTION_RTL) + x_offset = width - logical_rect.width / 1000; + else + x_offset = 0; + + if (pango_layout_line_x_to_index (line, 1000 * (x - x_offset), offset, NULL)) { *para_return = para; return TRUE; @@ -512,7 +232,8 @@ xy_to_cp (GList *paragraphs, int x, int y, else return FALSE; } - height += line->ascent + line->descent; + + line_height += logical_rect.height; line_list = line_list->next; } } @@ -524,67 +245,17 @@ xy_to_cp (GList *paragraphs, int x, int y, return FALSE; } -/* Given a character position within a run, determine the corresponding - * limits of that character in the x position. - */ -void -runs_char_bounds (char *text, GList *runs, int offset, int *x, int *width) -{ - int start_x; - int end_x; - int pixels = 0; - - PangoGlyphString *buf = pango_glyph_string_new(); - - while (runs) - { - PangoItem *item = runs->data; - PangoRectangle logical_rect; - - pango_shape (text + item->offset, item->length, &item->analysis, buf); - - if (offset >= item->offset && - offset < item->offset + item->length) - { - /* Find bounds */ - pango_glyph_string_index_to_x (buf, text + item->offset, item->length, - &item->analysis, offset - item->offset, FALSE, &start_x); - pango_glyph_string_index_to_x (buf, text + item->offset, item->length, - &item->analysis, offset - item->offset, TRUE, &end_x); - - if (start_x < end_x) - { - *x = pixels + start_x / 1000; - *width = (end_x - start_x) / 1000; - } - else - { - *x = pixels + end_x / 1000; - *width = (start_x - end_x) / 1000; - } - - break; - } - - pango_glyph_string_extents (buf, item->analysis.font, NULL, &logical_rect); - pixels += logical_rect.width / 1000; - runs = runs->next; - } - - pango_glyph_string_free (buf); - -} - /* Given a paragraph and offset in that paragraph, find the * bounding rectangle for the character at the offset. */ void -char_bounds (GList *paragraphs, Paragraph *para, int offset, - int *x, int *y, int *width, int *height) +char_bounds (GList *paragraphs, Paragraph *para, int index, + int width, PangoRectangle *rect) { - GList *para_list, *line_list, *run_list; - int pixels = 0; - int chars_seen = 0; + GList *para_list; + + int height = 0; + int bytes_seen = 0; PangoDirection base_dir = pango_context_get_base_dir (context); para_list = paragraphs; @@ -594,36 +265,50 @@ char_bounds (GList *paragraphs, Paragraph *para, int offset, if (cur_para == para) { - line_list = para->lines; + int line_height = 0; + + GSList *line_list = pango_layout_get_lines (para->layout); while (line_list) { - Line *line = line_list->data; - - run_list = line->runs; - while (run_list) - { - chars_seen += ((PangoItem *)run_list->data)->length; - run_list = run_list->next; - } + PangoLayoutLine *line = line_list->data; + PangoRectangle logical_rect; + + pango_layout_line_get_extents (line_list->data, NULL, &logical_rect); - if (offset < chars_seen) + bytes_seen += line->length; + if (index < bytes_seen) { - runs_char_bounds (para->text, line->runs, offset, - x, width); - *y = pixels; - *height = line->ascent + line->descent; + int x0, x1; + + pango_layout_line_index_to_x (line, index, FALSE, &x0); + pango_layout_line_index_to_x (line, index, TRUE, &x1); + + if (x0 <= x1) + { + rect->x = x0 / 1000; + rect->width = (x1 / 1000) - rect->x; + } + else + { + rect->x = x1 / 1000; + rect->width = (x0 / 1000) - rect->x; + } + + rect->y = height + line_height / 1000; + rect->height = logical_rect.height / 1000; + if (base_dir == PANGO_DIRECTION_RTL) - *x += line->offset; + rect->x += width - logical_rect.width / 1000; return; } - pixels += line->ascent + line->descent; + line_height += logical_rect.height; line_list = line_list->next; } } - pixels += cur_para->height; + height += cur_para->height; para_list = para_list->next; } } @@ -635,8 +320,8 @@ xor_char (GtkWidget *layout, GdkRectangle *clip_rect, GList *paragraphs, Paragraph *para, int offset) { static GdkGC *gc; - int x, y, width, height; - + PangoRectangle rect; /* GdkRectangle in 1.2 is too limited + */ if (!gc) { GdkGCValues values; @@ -650,14 +335,14 @@ xor_char (GtkWidget *layout, GdkRectangle *clip_rect, gdk_gc_set_clip_rectangle (gc, clip_rect); - char_bounds (paragraphs, para, offset, - &x, &y, &width, &height); + char_bounds (paragraphs, para, offset, layout->allocation.width, + &rect); - y -= GTK_LAYOUT (layout)->yoffset; + rect.y -= GTK_LAYOUT (layout)->yoffset; - if ((y + height >= 0) && (y < layout->allocation.height)) + if ((rect.y + rect.height >= 0) && (rect.y < layout->allocation.height)) gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, gc, TRUE, - x, y, width, height); + rect.x, rect.y, rect.width, rect.height); } @@ -667,55 +352,30 @@ xor_char (GtkWidget *layout, GdkRectangle *clip_rect, */ void expose_paragraph (Paragraph *para, GdkDrawable *drawable, - GdkGC *gc, int x, int y) + GdkGC *gc, int width, int x, int y) { - GList *line_list; - GList *run_list; - PangoGlyphString *buf; + GSList *line_list; + int line_height = 0; PangoRectangle logical_rect; + PangoDirection base_dir = pango_context_get_base_dir (context); - int x_off; - - buf = pango_glyph_string_new(); - - line_list = para->lines; + line_list = pango_layout_get_lines (para->layout); while (line_list) { - Line *line = line_list->data; - - x_off = line->offset; - run_list = line->runs; - while (run_list) - { - PangoItem *item = run_list->data; - - /* Convert the item into glyphs */ - pango_shape (para->text + item->offset, item->length, - &item->analysis, - buf); - - /* Render the glyphs to the screen */ - pango_x_render (GDK_DISPLAY(), GDK_WINDOW_XWINDOW (drawable), - GDK_GC_XGC (gc), item->analysis.font, buf, x + x_off, - y + line->ascent); + PangoLayoutLine *line = line_list->data; + line_list = line_list->next; - /* Advance to next x position - */ - if (run_list->next) - { - pango_glyph_string_extents (buf, item->analysis.font, NULL, &logical_rect); + pango_layout_line_get_extents (line, NULL, &logical_rect); - x_off += logical_rect.width / 1000; - } - - run_list = run_list = run_list->next; - } + if (base_dir == PANGO_DIRECTION_LTR) + pango_x_render_layout_line (GDK_DISPLAY(), GDK_WINDOW_XWINDOW (drawable), GDK_GC_XGC (gc), + line, x, y + line_height / 1000); + else + pango_x_render_layout_line (GDK_DISPLAY(), GDK_WINDOW_XWINDOW (drawable), GDK_GC_XGC (gc), + line, x + width - logical_rect.width / 1000, y + line_height / 1000); - y += line->ascent + line->descent; - line_list = line_list->next; + line_height += logical_rect.height; } - - pango_glyph_string_free (buf); } /* Handle a size allocation by re-laying-out each paragraph to @@ -774,6 +434,7 @@ draw (GtkWidget *layout, GdkRectangle *area, GList *paragraphs) expose_paragraph (para, GTK_LAYOUT (layout)->bin_window, layout->style->text_gc[layout->state], + layout->allocation.width, 0, height - GTK_LAYOUT (layout)->yoffset); height += para->height; @@ -801,7 +462,8 @@ button_press (GtkWidget *layout, GdkEventButton *event, GList *paragraphs) int offset; gchar *message; - xy_to_cp (paragraphs, event->x, event->y + GTK_LAYOUT (layout)->yoffset, + xy_to_cp (paragraphs, layout->allocation.width, + event->x, event->y + GTK_LAYOUT (layout)->yoffset, ¶, &offset); if (highlight_para) @@ -1081,9 +743,10 @@ main (int argc, char **argv) if (!text) exit(1); + context = pango_x_get_context (GDK_DISPLAY()); + paragraphs = split_paragraphs (text); - context = pango_x_get_context (GDK_DISPLAY()); pango_context_set_lang (context, "en_US"); pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); diff --git a/modules/Makefile.am b/modules/Makefile.am index 3ec1f65d..fd2f7d55 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to create Makefile.in. -SUBDIRS=basic hangul tamil +SUBDIRS=basic hangul tamil arabic install-data-local: $(mkinstalldirs) $(DESTDIR)$(localstatedir)/lib/pango diff --git a/modules/basic/tables-big.i b/modules/basic/tables-big.i index 2069c9f3..72769185 100644 --- a/modules/basic/tables-big.i +++ b/modules/basic/tables-big.i @@ -35,7 +35,8 @@ static PangoEngineRange basic_ranges[] = { { 0x0000, 0x02af, "*" }, { 0x02b0, 0x02ff, "" }, { 0x0380, 0x058f, "*" }, - { 0x0591, 0x0669, "*" }, + { 0x0591, 0x05f4, "*" }, /* Hebrew */ + { 0x060c, 0x06f9, "" }, /* Arabic */ { 0x1e00, 0x1fff, "*" }, { 0x2000, 0x9fff, "*" }, { 0xac00, 0xd7a3, "kr" }, diff --git a/modules/basic/tables-small.i b/modules/basic/tables-small.i index 31139b4b..8af7be2d 100644 --- a/modules/basic/tables-small.i +++ b/modules/basic/tables-small.i @@ -28,7 +28,8 @@ static PangoEngineRange basic_ranges[] = { { 0x0000, 0x02af, "*" }, { 0x02b0, 0x02ff, "" }, { 0x0380, 0x058f, "*" }, - { 0x0591, 0x0669, "*" }, + { 0x0591, 0x05f4, "*" }, /* Hebrew */ + { 0x060c, 0x06f9, "" }, /* Arabic */ { 0x2015, 0x2017, "*" }, }; diff --git a/pango/Makefile.am b/pango/Makefile.am index 3a7803f0..930526cd 100644 --- a/pango/Makefile.am +++ b/pango/Makefile.am @@ -15,6 +15,7 @@ libpango_la_SOURCES = \ pango-attributes.c \ pango-context.c \ pango-coverage.c \ + pango-layout.c \ reorder-items.c \ shape.c \ utils.c \ diff --git a/pango/glyphstring.c b/pango/glyphstring.c index b29efe09..d3030e39 100644 --- a/pango/glyphstring.c +++ b/pango/glyphstring.c @@ -22,6 +22,7 @@ #include <glib.h> #include <pango-glyph.h> #include <pango-font.h> +#include <unicode.h> /** * pango_glyph_string_new: @@ -151,12 +152,12 @@ pango_glyph_string_extents (PangoGlyphString *glyphs, { new_pos = MIN (ink_rect->x, x_pos + glyph_ink.x + geometry->x_offset); ink_rect->width = MAX (ink_rect->x + ink_rect->width, - x_pos + glyph_ink.x + glyph_ink.width + geometry->x_offset) - ink_rect->x; + x_pos + glyph_ink.x + glyph_ink.width + geometry->x_offset) - new_pos; ink_rect->x = new_pos; new_pos = MIN (ink_rect->y, glyph_ink.y + geometry->y_offset); ink_rect->height = MAX (ink_rect->y + ink_rect->height, - glyph_ink.y + glyph_ink.height + geometry->y_offset) - ink_rect->y; + glyph_ink.y + glyph_ink.height + geometry->y_offset) - new_pos; ink_rect->y = new_pos; } @@ -164,12 +165,12 @@ pango_glyph_string_extents (PangoGlyphString *glyphs, { new_pos = MIN (logical_rect->x, x_pos + glyph_logical.x + geometry->x_offset); logical_rect->width = MAX (logical_rect->x + logical_rect->width, - x_pos + glyph_logical.x + glyph_logical.width + geometry->x_offset) - logical_rect->x; + x_pos + glyph_logical.x + glyph_logical.width + geometry->x_offset) - new_pos; logical_rect->x = new_pos; new_pos = MIN (logical_rect->y, glyph_logical.y + geometry->y_offset); logical_rect->height = MAX (logical_rect->y + logical_rect->height, - glyph_logical.y + glyph_logical.height + geometry->y_offset) - logical_rect->y; + glyph_logical.y + glyph_logical.height + geometry->y_offset) - new_pos; logical_rect->y = new_pos; } } @@ -178,3 +179,67 @@ pango_glyph_string_extents (PangoGlyphString *glyphs, } } +/** + * pango_glyph_string_get_logical_widths: + * @glyphs: a #PangoGlyphString + * @text: the text corresponding to the glyphs + * @length: the length of @text, in bytes + * @embedding_level: the embedding level of the string + * @logical_widths: an array whose length is unicode_strlen (text, length) + * to be filled in with the resulting character widths. + * + * Given a #PangoGlyphString resulting from pango_shape() and the corresponding + * text, determine the screen width corresponding to each character. When + * multiple characters compose a single cluster, the width of the entire + * cluster is divided equally among the characters. + **/ +void +pango_glyph_string_get_logical_widths (PangoGlyphString *glyphs, + char *text, + int length, + int embedding_level, + int *logical_widths) +{ + int i, j; + int last_cluster = 0; + int width = 0; + int last_cluster_width = 0; + char *p = text; + + for (i=0; i<=glyphs->num_glyphs; i++) + { + int glyph_index = (embedding_level % 2 == 0) ? i : glyphs->num_glyphs - i - 1; + + if (i == glyphs->num_glyphs || p != text + glyphs->log_clusters[glyph_index]) + { + int next_cluster = last_cluster; + + if (glyph_index < glyphs->num_glyphs) + { + while (p < text + glyphs->log_clusters[glyph_index]) + { + next_cluster++; + p = unicode_next_utf8 (p); + } + } + else + { + while (p < text + length) + { + next_cluster++; + p = unicode_next_utf8 (p); + } + } + + for (j = last_cluster; j < next_cluster; j++) + logical_widths[j] = (width - last_cluster_width) / (next_cluster - last_cluster); + + last_cluster = next_cluster; + last_cluster_width = width; + } + + if (i < glyphs->num_glyphs) + width += glyphs->glyphs[i].geometry.width; + } +} + diff --git a/pango/itemize.c b/pango/itemize.c index bc7c9bd8..0f552915 100644 --- a/pango/itemize.c +++ b/pango/itemize.c @@ -52,10 +52,10 @@ static void add_engines (PangoContext *context, */ GList * pango_itemize (PangoContext *context, - gchar *text, - gint length, - PangoLangRange *lang_info, - gint n_langs) + gchar *text, + gint length, + PangoLangRange *lang_info, + gint n_langs) { guint16 *text_ucs2; gint n_chars; @@ -70,9 +70,10 @@ pango_itemize (PangoContext *context, PangoEngineInfo **lang_engines; g_return_val_if_fail (context != NULL, NULL); - g_return_val_if_fail (text != NULL, NULL); - g_return_val_if_fail (length >= 0, NULL); + g_return_val_if_fail (length == 0 || text != NULL, NULL); + if (length == 0) + return NULL; if (context->direction == PANGO_DIRECTION_RTL) base_dir = FRIBIDI_TYPE_RTL; diff --git a/pango/mapping.c b/pango/mapping.c index d075b9f8..3ad923ee 100644 --- a/pango/mapping.c +++ b/pango/mapping.c @@ -140,10 +140,10 @@ pango_glyph_string_index_to_x (PangoGlyphString *glyphs, p = text + start_index; while (p < text + end_index) { - p = unicode_next_utf8 (p); if (p < text + index) cluster_offset++; cluster_chars++; + p = unicode_next_utf8 (p); } /* Now interpolate the result. For South Asian languages diff --git a/pango/pango-context.c b/pango/pango-context.c index 30902c47..a6b7cccc 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -468,8 +468,8 @@ pango_context_get_base_dir (PangoContext *context) */ GList * pango_itemize (PangoContext *context, - gchar *text, - gint length, + char *text, + int length, PangoAttrList *attrs) { guint16 *text_ucs2; @@ -486,9 +486,11 @@ pango_itemize (PangoContext *context, PangoFont **fonts; g_return_val_if_fail (context != NULL, NULL); - g_return_val_if_fail (text != NULL, NULL); g_return_val_if_fail (length >= 0, NULL); + g_return_val_if_fail (length == 0 || text != NULL, NULL); + if (length == 0) + return NULL; if (context->base_dir == PANGO_DIRECTION_RTL) base_dir = FRIBIDI_TYPE_RTL; diff --git a/pango/pango-glyph.h b/pango/pango-glyph.h index cd9b84f9..433e71f2 100644 --- a/pango/pango-glyph.h +++ b/pango/pango-glyph.h @@ -88,6 +88,12 @@ void pango_glyph_string_extents (PangoGlyphString *glyphs, PangoRectangle *ink_rect, PangoRectangle *logical_rect); +void pango_glyph_string_get_logical_widths (PangoGlyphString *glyphs, + char *text, + int length, + int embedding_level, + int *logical_widths); + void pango_glyph_string_index_to_x (PangoGlyphString *glyphs, char *text, int length, diff --git a/pango/pango-layout.c b/pango/pango-layout.c new file mode 100644 index 00000000..04b440df --- /dev/null +++ b/pango/pango-layout.c @@ -0,0 +1,873 @@ +/* Pango + * pango-layout.c: Highlevel layout driver + * + * Copyright (C) 2000 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. + */ + +#include <pango-layout.h> +#include <pango.h> /* For pango_shape() */ +#include <unicode.h> + +#define LINE_IS_VALID(line) ((line)->layout != NULL) + +typedef struct _PangoLayoutLinePrivate PangoLayoutLinePrivate; + +struct _PangoLayout +{ + guint ref_count; + + PangoContext *context; + PangoAttrList *attrs; + gchar *text; + int length; /* length of text in bytes */ + int width; /* wrap width, in device units */ + int first_line_width; /* wrap width for first line, in device units */ + + GSList *lines; +}; + +struct _PangoLayoutLinePrivate +{ + PangoLayoutLine line; + guint ref_count; +}; + +static void pango_layout_clear_lines (PangoLayout *layout); +static void pango_layout_check_lines (PangoLayout *layout); + +static PangoLayoutLine * pango_layout_line_new (PangoLayout *layout); +static void pango_layout_line_reorder (PangoLayoutLine *line); + +/** + * pango_layout_new: + * @context: a #PangoContext + * + * Create a new #PangoLayout object with attributes initialized to + * default values for a particular #PangoContext. + * + * Return value: a new #PangoLayout, with a reference count of one. + **/ +PangoLayout * +pango_layout_new (PangoContext *context) +{ + PangoLayout *layout; + + g_return_val_if_fail (context != NULL, NULL); + + layout = g_new (PangoLayout, 1); + + layout->ref_count = 1; + + layout->context = context; + pango_context_ref (context); + + layout->attrs = NULL; + layout->text = NULL; + layout->length = 0; + layout->width = -1; + layout->first_line_width = -1; + + layout->lines = NULL; + + return layout; +} + +/** + * pango_layout_ref: + * @layout: a #PangoLayout + * + * Increase the reference count of the #PangoLayout by one. + **/ +void +pango_layout_ref (PangoLayout *layout) +{ + g_return_if_fail (layout != NULL); + + layout->ref_count++; +} + +/** + * pango_layout_unref: + * @layout: + * + * Decrease the reference count of the #PangoLayout by one. If the + * result is zero, free the #PangoLayout and all associated memory. + **/ +void +pango_layout_unref (PangoLayout *layout) +{ + g_return_if_fail (layout != NULL); + g_return_if_fail (layout->ref_count > 0); + + layout->ref_count--; + if (layout->ref_count == 0) + { + pango_layout_clear_lines (layout); + + if (layout->context) + pango_context_unref (layout->context); + + if (layout->attrs) + pango_attr_list_unref (layout->attrs); + if (layout->text) + g_free (layout->text); + } +} + +/** + * pango_layout_set_width: + * @layout: a #PangoLayout. + * @width: the desired width, or -1 to indicate that no wrapping should be + * performed. + * + * Set the width to which the lines of the #PangoLayout should be wrapped. + **/ +void +pango_layout_set_width (PangoLayout *layout, + int width) +{ + g_return_if_fail (layout != NULL); + + layout->width = width; + pango_layout_clear_lines (layout); +} + +/** + * pango_layout_set_first_width: + * @layout: a #PangoLayout. + * @width: the desired width, or -1 to indicate that it should be the same + * as the the width set by pango_layout_set_width(). + * + * Set the width to which the first line of the #PangoLayout should be + * wrapped. + **/ +void +pango_layout_set_first_line_width (PangoLayout *layout, + int width) +{ + g_return_if_fail (layout != NULL); + + layout->first_line_width = width; + pango_layout_clear_lines (layout); +} + +/** + * pango_layout_set_attributes: + * @layout: a #PangoLayout + * @attrs: a #PangoAttrList + * + * Set the text attributes for a layout object + **/ +void +pango_layout_set_attributes (PangoLayout *layout, + PangoAttrList *attrs) +{ + if (layout->attrs) + pango_attr_list_unref (layout->attrs); + + layout->attrs = attrs; + pango_attr_list_ref (layout->attrs); + pango_layout_clear_lines (layout); +} + +/** + * pango_layout_set_text: + * @layout: a #PangoLayout + * @text: a UTF8-string + * @length: the length of @text, in bytes. + * + * Set the text of the layout. + **/ +void +pango_layout_set_text (PangoLayout *layout, + char *text, + int length) +{ + g_return_if_fail (layout != NULL); + g_return_if_fail (length == 0 || text != NULL); + + if (layout->text) + g_free (layout->text); + + layout->length = length; + + if (length > 0) + { + layout->text = g_malloc (length); + memcpy (layout->text, text, length); + } + else + layout->text = NULL; + + pango_layout_clear_lines (layout); +} + +/** + * pango_layout_get_line_count: + * @layout: #PangoLayout + * + * Retrieve the count of lines for the #PangoLayout + * + * Return value: the line count + **/ +int +pango_layout_get_line_count (PangoLayout *layout) +{ + g_return_val_if_fail (layout != NULL, 0); + + pango_layout_check_lines (layout); + + return g_slist_length (layout->lines); +} + +/** + * pango_layout_get_lines: + * @layout: a #PangoLayout + * + * Return the lines of the layout as a list + * + * Return value: a #GSList containing the lines in the layout. This + * points to internal data of the #PangoLayout and must be used with + * care. It will become invalid on any change to the layout's + * text or properties. + **/ +GSList * +pango_layout_get_lines (PangoLayout *layout) +{ + pango_layout_check_lines (layout); + return layout->lines; +} + +/** + * pango_layout_get_line: + * @layout: a #PangoLayout + * @line: the index of a line, which must be between 0 and + * pango_layout_get_line_count(layout) - 1, inclusive. + * + * Retrieve a particular line from a #PangoLayout + * + * Return value: the requested #PangoLayoutLine, or %NULL if the + * index is out of range. This layout line can + * be ref'ed and retained, but will become invalid + * if changes are made to the #PangoLayout. + **/ +PangoLayoutLine * +pango_layout_get_line (PangoLayout *layout, + int line) +{ + g_return_val_if_fail (layout != NULL, NULL); + g_return_val_if_fail (line >= 0, NULL); + + if (line < 0) + return NULL; + + pango_layout_check_lines (layout); + return g_slist_nth (layout->lines, line)->data; +} + +/** + * pango_layout_line_index_to_x: + * @line: a #PangoLayoutLine + * @index: byte offset within the Layout's text + * @trailing: 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. + * @x_pos: location to store the x_offset (in thousandths of a device unit) + * + * Convert index within a line to X pos + * + * + **/ +void +pango_layout_line_index_to_x (PangoLayoutLine *line, + int index, + gboolean trailing, + int *x_pos) +{ + GSList *run_list = line->runs; + int width = 0; + + while (run_list) + { + PangoRectangle logical_rect; + PangoLayoutRun *run = run_list->data; + + if (run->item->offset <= index && run->item->offset + run->item->length > index) + { + pango_glyph_string_index_to_x (run->glyphs, + line->layout->text + run->item->offset, + run->item->length, + &run->item->analysis, + index - run->item->offset, trailing, x_pos); + + if (x_pos) + *x_pos += width; + + return; + } + + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + NULL, &logical_rect); + width += logical_rect.width; + + run_list = run_list->next; + } +} + +/** + * pango_layout_index_to_line_x: + * @layout: a #PangoLayout + * @index: the byte index of the character to find + * @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). + * @line: location to store resulting line index. (which will + * between 0 and pango_layout_get_line_count(layout) - 1) + * @x_pos: location to store resulting position within line + * (in thousandths of a device unit) + * + * Converts from byte index within the layout to line and X position. + * (X position is measured from the left edge of the line) + */ +void +pango_layout_index_to_line_x (PangoLayout *layout, + int index, + gboolean trailing, + int *line, + int *x_pos) +{ + GSList *tmp_list; + int tmp_line = 0; + int bytes_seen = 0; + + g_return_if_fail (line != NULL); + + pango_layout_check_lines (layout); + + tmp_list = layout->lines; + while (tmp_list) + { + PangoLayoutLine *layout_line = tmp_list->data; + + if (bytes_seen + layout_line->length > index) + { + if (line) + *line = tmp_line; + + pango_layout_line_index_to_x (layout_line, index, trailing, x_pos); + return; + } + + tmp_list = tmp_list->next; + bytes_seen += layout_line->length; + } + + if (line) + *line = -1; + if (x_pos) + *x_pos = -1; +} + +static void +pango_layout_clear_lines (PangoLayout *layout) +{ + if (layout->lines) + { + GSList *tmp_list = layout->lines; + while (tmp_list) + { + PangoLayoutLine *line = tmp_list->data; + tmp_list = tmp_list->next; + + line->layout = NULL; + pango_layout_line_unref (line); + } + + g_slist_free (layout->lines); + layout->lines = NULL; + } +} + +/***************** + * Line Breaking * + *****************/ + +static void +insert_run (PangoLayoutLine *line, PangoItem *item, PangoGlyphString *glyphs) +{ + PangoLayoutRun *run = g_new (PangoLayoutRun, 1); + + run->item = item; + run->glyphs = glyphs; + + line->runs = g_slist_prepend (line->runs, run); + line->length += item->length; +} + +static gboolean +process_item (PangoLayoutLine *line, PangoItem *item, char *text, int *remaining_width) +{ + PangoGlyphString *glyphs = pango_glyph_string_new (); + PangoRectangle logical_rect; + int width; + + if (*remaining_width == 0) + return FALSE; + + pango_shape (text + item->offset, item->length, &item->analysis, glyphs); + pango_glyph_string_extents (glyphs, item->analysis.font, NULL, &logical_rect); + width = logical_rect.width; + + if (logical_rect.width < *remaining_width) + { + *remaining_width -= width; + insert_run (line, item, glyphs); + + return TRUE; + } + else + { + int length; + int num_chars = item->num_chars; + int new_width; + + PangoLogAttr *log_attrs = g_new (PangoLogAttr, item->num_chars); + PangoGlyphUnit *log_widths = g_new (PangoGlyphUnit, item->num_chars); + + pango_break (text + item->offset, item->length, &item->analysis, log_attrs); + pango_glyph_string_get_logical_widths (glyphs, text + item->offset, item->length, item->analysis.level, log_widths); + + new_width = 0; + while (--num_chars > 0) + { + /* Shorten the item by one line break + */ + width -= log_widths[num_chars]; + if (log_attrs[num_chars].is_break && width <= *remaining_width) + break; + } + + g_free (log_attrs); + g_free (log_widths); + + if (num_chars != 0) /* Succesfully broke the item */ + { + char *p; + gint n; + + PangoItem *new_item = g_new (PangoItem, 1); + + /* Determine utf8 length corresponding to num_chars. Slow? + */ + n = num_chars; + p = text + item->offset; + while (n-- > 0) + p = unicode_next_utf8 (p); + + length = p - (text + item->offset); + + new_item->offset = item->offset; + new_item->length = length; + new_item->num_chars = num_chars; + + new_item->analysis = item->analysis; + pango_font_ref (new_item->analysis.font); + + item->offset += length; + item->length -= length; + item->num_chars -= num_chars; + + pango_shape (text + new_item->offset, new_item->length, &new_item->analysis, glyphs); + + *remaining_width -= width; + insert_run (line, new_item, glyphs); + + return FALSE; + } + else + { + if (!line->runs) /* Only item, insert it anyways */ + { + *remaining_width = 0; + insert_run (line, item, glyphs); + + return TRUE; + } + else + { + pango_glyph_string_free (glyphs); + return FALSE; + } + } + } +} + +static void +pango_layout_check_lines (PangoLayout *layout) +{ + GList *items, *tmp_list; + + PangoLayoutLine *line; + int remaining_width; + + if (layout->lines) + return; + + line = pango_layout_line_new (layout); + remaining_width = layout->first_line_width; + + /* FIXME, should we force people to set the attrs? */ + if (layout->attrs) + items = pango_itemize (layout->context, layout->text, layout->length, layout->attrs); + else + { + PangoAttrList *attrs = pango_attr_list_new (); + items = pango_itemize (layout->context, layout->text, layout->length, attrs); + pango_attr_list_unref (attrs); + } + + tmp_list = items; + + while (tmp_list) + { + PangoItem *item = tmp_list->data; + gboolean fits; + + fits = process_item (line, item, layout->text, &remaining_width); + + if (fits) + tmp_list = tmp_list->next; + + if (!fits) + { + /* Complete line + */ + line->runs = g_slist_reverse (line->runs); + pango_layout_line_reorder (line); + + layout->lines = g_slist_prepend (layout->lines, line); + + line = pango_layout_line_new (layout); + remaining_width = layout->width; + } + } + + line->runs = g_slist_reverse (line->runs); + pango_layout_line_reorder (line); + + layout->lines = g_slist_prepend (layout->lines, line); + + g_list_free (tmp_list); + layout->lines = g_slist_reverse (layout->lines); +} + +/** + * pango_layout_line_ref: + * @line: a #PangoLayoutLine + * + * Increase the reference count of a #PangoLayoutLine by one. + **/ +void +pango_layout_line_ref (PangoLayoutLine *line) +{ + PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line; + + g_return_if_fail (line != NULL); + + private->ref_count++; +} + +/** + * pango_layout_line_unref: + * @line: + * + * Decrease the reference count of a #PangoLayoutLine by one. + * if the result is zero, the line and all associated memory + * will be freed. + **/ +void +pango_layout_line_unref (PangoLayoutLine *line) +{ + PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line; + + g_return_if_fail (line != NULL); + g_return_if_fail (private->ref_count > 0); + + private->ref_count--; + if (private->ref_count == 0) + { + GSList *tmp_list = line->runs; + + while (tmp_list) + { + PangoLayoutRun *run = tmp_list->data; + + pango_font_unref (run->item->analysis.font); + g_free (run->item); + + pango_glyph_string_free (run->glyphs); + + tmp_list = tmp_list->next; + } + + g_slist_free (line->runs); + g_free (line); + } +} + +/** + * pango_layout_line_x_to_index: + * @line: a #PangoLayoutLine + * @x_pos: the x offset (in thousands of a device unit) + * from the left edge of the line. + * @index: location to store calculated byte offset. + * @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. + * + * Convert from x offset to the byte index of the corresponding + * character within the text of the layout. + * + * Return value: %TRUE if the x index was within the line + */ +gboolean +pango_layout_line_x_to_index (PangoLayoutLine *line, + int x_pos, + int *index, + int *trailing) +{ + GSList *tmp_list; + gint start_pos = 0; + + g_return_val_if_fail (LINE_IS_VALID (line), FALSE); + + if (!LINE_IS_VALID (line)) + return FALSE; + + tmp_list = line->runs; + while (tmp_list) + { + PangoRectangle logical_rect; + PangoLayoutRun *run = tmp_list->data; + + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, NULL, &logical_rect); + + if (x_pos >= start_pos && x_pos < start_pos + logical_rect.width) + { + int pos; + + pango_glyph_string_x_to_index (run->glyphs, + line->layout->text + run->item->offset, run->item->length, + &run->item->analysis, + x_pos - start_pos, + &pos, trailing); + + if (index) + *index = pos + run->item->offset; + + return TRUE; + } + + start_pos += logical_rect.width; + tmp_list = tmp_list->next; + } + + return FALSE; +} + +/** + * pango_layout_line_get_extents: + * @line: a #PangoLayoutLine + * @ink_rect: rectangle used to store the extents of the glyph string as drawn + * or %NULL to indicate that the result is not needed. + * @logical_rect: rectangle used to store the logical extents of the glyph string + * or %NULL to indicate that the result is not needed. + * + * Compute the logical and ink extents of a layout line. See the documentation + * for pango_font_get_glyph_extents() for details about the interpretation + * of the rectangles. + */ +void +pango_layout_line_get_extents (PangoLayoutLine *line, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + GSList *tmp_list; + int x_pos = 0; + + g_return_if_fail (LINE_IS_VALID (line)); + + if (!LINE_IS_VALID (line)) + return; + + 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; + } + + tmp_list = line->runs; + while (tmp_list) + { + PangoLayoutRun *run = tmp_list->data; + int new_pos; + + PangoRectangle run_ink; + PangoRectangle run_logical; + + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + ink_rect ? &run_ink : NULL, + &run_logical); + + if (ink_rect) + { + new_pos = MIN (ink_rect->x, x_pos + run_ink.x); + ink_rect->width = MAX (ink_rect->x + ink_rect->width, + x_pos + run_ink.x + run_ink.width) - new_pos; + ink_rect->x = new_pos; + + new_pos = MIN (ink_rect->y, run_ink.y); + ink_rect->height = MAX (ink_rect->y + ink_rect->height, + run_ink.y + run_ink.height) - new_pos; + ink_rect->y = new_pos; + } + + if (logical_rect) + { + new_pos = MIN (logical_rect->x, x_pos + run_logical.x); + logical_rect->width = MAX (logical_rect->x + logical_rect->width, + x_pos + run_logical.x + run_logical.width) - new_pos; + logical_rect->x = new_pos; + + new_pos = MIN (logical_rect->y, run_logical.y); + logical_rect->height = MAX (logical_rect->y + logical_rect->height, + run_logical.y + run_logical.height) - new_pos; + logical_rect->y = new_pos; + } + + x_pos += run_logical.width; + tmp_list = tmp_list->next; + } +} + +static PangoLayoutLine * +pango_layout_line_new (PangoLayout *layout) +{ + PangoLayoutLinePrivate *private = g_new (PangoLayoutLinePrivate, 1); + + private->ref_count = 1; + private->line.layout = layout; + private->line.runs = 0; + private->line.length = 0; + + return (PangoLayoutLine *) private; +} + + +/* + * NB: The contents of the file implement the exact same algorithm + * reorder-items.c:pango_reorder_items(). + */ + +static GSList * +reorder_runs_recurse (GSList *items, int n_items) +{ + GSList *tmp_list, *level_start_node; + int i, level_start_i; + int min_level = G_MAXINT; + GSList *result = NULL; + + if (n_items == 0) + return NULL; + + tmp_list = items; + for (i=0; i<n_items; i++) + { + PangoLayoutRun *run = tmp_list->data; + + min_level = MIN (min_level, run->item->analysis.level); + + tmp_list = tmp_list->next; + } + + level_start_i = 0; + level_start_node = items; + tmp_list = items; + for (i=0; i<n_items; i++) + { + PangoLayoutRun *run = tmp_list->data; + + if (run->item->analysis.level == min_level) + { + if (min_level % 2) + { + if (i > level_start_i) + result = g_slist_concat (reorder_runs_recurse (level_start_node, i - level_start_i), result); + result = g_slist_prepend (result, run); + } + else + { + if (i > level_start_i) + result = g_slist_concat (result, reorder_runs_recurse (level_start_node, i - level_start_i)); + result = g_slist_append (result, run); + } + + level_start_i = i + 1; + level_start_node = tmp_list->next; + } + + tmp_list = tmp_list->next; + } + + if (min_level % 2) + { + if (i > level_start_i) + result = g_slist_concat (reorder_runs_recurse (level_start_node, i - level_start_i), result); + } + else + { + if (i > level_start_i) + result = g_slist_concat (result, reorder_runs_recurse (level_start_node, i - level_start_i)); + } + + return result; +} + +static void +pango_layout_line_reorder (PangoLayoutLine *line) +{ + GSList *logical_runs = line->runs; + line->runs = reorder_runs_recurse (logical_runs, g_slist_length (logical_runs)); + g_slist_free (logical_runs); +} + diff --git a/pango/pango-layout.h b/pango/pango-layout.h index b9c1ea6f..75e82bad 100644 --- a/pango/pango-layout.h +++ b/pango/pango-layout.h @@ -22,6 +22,10 @@ #ifndef __PANGO_LAYOUT_H__ #define __PANGO_LAYOUT_H__ +#include <pango-attributes.h> +#include <pango-context.h> +#include <pango-glyph.h> + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -33,7 +37,6 @@ typedef struct _PangoLayoutRun PangoLayoutRun; struct _PangoLayoutLine { PangoLayout *layout; - gint n_chars; /* length of line in characters */ gint length; /* length of line in bytes*/ GSList *runs; }; @@ -44,37 +47,43 @@ struct _PangoLayoutRun PangoGlyphString *glyphs; }; -PangoLayout * pango_layout_new (void); -void pango_layout_ref (PangoLayout *layout); -void pango_layout_unref (PangoLayout *layout); -void pango_layout_set_width (PangoLayout *layout, - int width); -void pango_layout_set_justify (PangoLayout *layout, - gboolean justify); -void pango_layout_set_first_line_width (PangoLayout *layout, - int width); -void pango_layout_set_attributes (PangoLayout *layout, - PangoAttrList *attrs); -void pango_layout_set_text (char *text, - int length); -int pango_layout_get_line_count (PangoLayout *layout); -PangoLayoutLine *pango_layout_get_line (PangoLayout *layout, - int line); -void pango_layout_cp_to_line_x (PangoLayout *layout, - gint char_pos, - gboolean trailing, - gint *line, - gint *x_pos); +PangoLayout * pango_layout_new (PangoContext *context); +void pango_layout_ref (PangoLayout *layout); +void pango_layout_unref (PangoLayout *layout); +void pango_layout_set_width (PangoLayout *layout, + int width); +void pango_layout_set_justify (PangoLayout *layout, + gboolean justify); +void pango_layout_set_first_line_width (PangoLayout *layout, + int width); +void pango_layout_set_attributes (PangoLayout *layout, + PangoAttrList *attrs); +void pango_layout_set_text (PangoLayout *layout, + char *text, + int length); +int pango_layout_get_line_count (PangoLayout *layout); +PangoLayoutLine * pango_layout_get_line (PangoLayout *layout, + int line); +GSList * pango_layout_get_lines (PangoLayout *layout); +void pango_layout_index_to_line_x (PangoLayout *layout, + int index, + gboolean trailing, + int *line, + int *x_pos); -void pango_layout_line_ref (PangoLayoutLine *line); -void pango_layout_line_unref (PangoLayoutLine *line); -void pango_layout_line_x_to_cp (PangoLayoutLine *line, - gint x_pos, - gint *char_pos, - gint *trailing); -void pango_layout_line_get_extents (PangoLayoutLine *line, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); +void pango_layout_line_ref (PangoLayoutLine *line); +void pango_layout_line_unref (PangoLayoutLine *line); +gboolean pango_layout_line_x_to_index (PangoLayoutLine *line, + int x_pos, + int *index, + int *trailing); +void pango_layout_line_index_to_x (PangoLayoutLine *line, + int index, + gboolean trailing, + int *x_pos); +void pango_layout_line_get_extents (PangoLayoutLine *line, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); #ifdef __cplusplus } diff --git a/pango/pangox.c b/pango/pangox.c index f6a7d142..423722e5 100644 --- a/pango/pangox.c +++ b/pango/pangox.c @@ -1316,8 +1316,8 @@ pango_x_render (Display *display, GC gc, PangoFont *font, PangoGlyphString *glyphs, - int x, - int y) + int x, + int y) { /* Slow initial implementation. For speed, it should really * collect the characters into runs, and draw multiple @@ -1540,43 +1540,43 @@ pango_x_make_matching_xlfd (PangoXFontMap *xfontmap, char *xlfd, const char *cha if (closest_match) { - char *prefix_end, *p; - char *size_end; - int n_dashes = 0; - - /* OK, we have a match; let's modify it to fit this size and charset */ - - p = closest_match; - while (n_dashes < 6) - { - if (*p == '-') - n_dashes++; - p++; - } - - prefix_end = p - 1; - - while (n_dashes < 9) + if (match_scaleable) { - if (*p == '-') - n_dashes++; - p++; - } + char *prefix_end, *p; + char *size_end; + int n_dashes = 0; + int target_size; + char *prefix; + + /* OK, we have a match; let's modify it to fit this size and charset */ - size_end = p - 1; + p = closest_match; + while (n_dashes < 6) + { + if (*p == '-') + n_dashes++; + p++; + } + + prefix_end = p - 1; + + while (n_dashes < 9) + { + if (*p == '-') + n_dashes++; + p++; + } + + size_end = p - 1; - if (match_scaleable) - { - int target_size = (int)((double)size / xfontmap->resolution + 0.5); - char *prefix = g_strndup (closest_match, prefix_end - closest_match); + target_size = (int)((double)size / xfontmap->resolution + 0.5); + prefix = g_strndup (closest_match, prefix_end - closest_match); result = g_strdup_printf ("%s--%d-*-*-*-*-*-%s", prefix, target_size, charset); g_free (prefix); } else { - char *prefix = g_strndup (closest_match, size_end - closest_match); - result = g_strconcat (prefix, "-*-*-*-*-", charset, NULL); - g_free (prefix); + result = g_strdup (closest_match); } } @@ -2002,3 +2002,47 @@ pango_x_get_unknown_glyph (PangoFont *font) return 0; } +/** + * pango_x_render_layout_line: + * @display: the X display + * @d: the drawable on which to draw string + * @gc: the graphics context + * @line: a #PangoLayoutLine + * @glyphs: the glyph string to draw + * @x: the x position of start of string (in pixels) + * @y: the y position of baseline (in pixels) + * + * Render a #PangoLayoutLine onto an X drawable + */ +void +pango_x_render_layout_line (Display *display, + Drawable d, + GC gc, + PangoLayoutLine *line, + int x, + int y) +{ + GSList *tmp_list = line->runs; + PangoRectangle logical_rect; + + int x_off = 0; + + pango_layout_line_get_extents (line,NULL, &logical_rect); + y += PANGO_ASCENT (logical_rect) / 1000; + + while (tmp_list) + { + PangoLayoutRun *run = tmp_list->data; + tmp_list = tmp_list->next; + + pango_x_render (display, d, gc, run->item->analysis.font, run->glyphs, + x + x_off / 1000, y); + + if (tmp_list) + { + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + NULL, &logical_rect); + x_off += logical_rect.width; + } + } +} diff --git a/pango/pangox.h b/pango/pangox.h index e24c6d0d..2e92347d 100644 --- a/pango/pangox.h +++ b/pango/pangox.h @@ -35,35 +35,22 @@ extern "C" { /* Calls for applications */ -PangoContext *pango_x_get_context (Display *display); - -PangoFont *pango_x_load_font (Display *display, - gchar *spec); -void pango_x_render (Display *display, - Drawable d, - GC gc, - PangoFont *font, - PangoGlyphString *glyphs, - gint x, - gint y); -void pango_x_extents (PangoFont *font, - PangoGlyphString *glyphs, - gint *lbearing, - gint *rbearing, - gint *width, - gint *ascent, - gint *descent, - gint *logical_ascent, - gint *logical_descent); -void pango_x_glyph_extents (PangoFont *font, - PangoGlyph glyph, - gint *lbearing, - gint *rbearing, - gint *width, - gint *ascent, - gint *descent, - gint *logical_ascent, - gint *logical_descent); +PangoContext * pango_x_get_context (Display *display); +PangoFont * pango_x_load_font (Display *display, + gchar *spec); +void pango_x_render (Display *display, + Drawable d, + GC gc, + PangoFont *font, + PangoGlyphString *glyphs, + gint x, + gint y); +void pango_x_render_layout_line (Display *display, + Drawable d, + GC gc, + PangoLayoutLine *line, + int x, + int y); /* API for rendering modules */ diff --git a/pango/reorder-items.c b/pango/reorder-items.c index bbe415b7..18d68ab6 100644 --- a/pango/reorder-items.c +++ b/pango/reorder-items.c @@ -21,6 +21,11 @@ #include <pango.h> +/* + * NB: The contents of the file implement the exact same algorithm + * pango-layout.c:pango_layout_line_reorder(). + */ + static GList *reorder_items_recurse (GList *items, int n_items); /** @@ -32,6 +37,11 @@ static GList *reorder_items_recurse (GList *items, int n_items); * The original list is unmodified. * * Returns a GList of PangoItem structures in visual order. + * + * (Please mail otaylor@redhat.com if you use this function. + * It is not a particularly convenient interface, and the code + * is duplicated elsewhere in Pango for that reason.) + * */ GList * pango_reorder_items (GList *logical_items) |