summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2000-03-08 18:39:49 +0000
committerOwen Taylor <otaylor@src.gnome.org>2000-03-08 18:39:49 +0000
commit773bc55fc9e344f8040809ba8796b0ba2805e4c9 (patch)
tree89e900594294e87b4a4de8f71571762d6ccc8871
parentdd0b4a5064c6f60adcfd2ea02e2d61fb60254d20 (diff)
downloadpango-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--.cvsignore1
-rw-r--r--ChangeLog43
-rw-r--r--ChangeLog.pre-1-043
-rw-r--r--ChangeLog.pre-1-1043
-rw-r--r--ChangeLog.pre-1-243
-rw-r--r--ChangeLog.pre-1-443
-rw-r--r--ChangeLog.pre-1-643
-rw-r--r--ChangeLog.pre-1-843
-rw-r--r--configure.in3
-rw-r--r--docs/tmpl/layout.sgml195
-rw-r--r--examples/HELLO.utf87
-rw-r--r--examples/pango.modules6
-rw-r--r--examples/viewer.c541
-rw-r--r--modules/Makefile.am2
-rw-r--r--modules/basic/tables-big.i3
-rw-r--r--modules/basic/tables-small.i3
-rw-r--r--pango/Makefile.am1
-rw-r--r--pango/glyphstring.c73
-rw-r--r--pango/itemize.c13
-rw-r--r--pango/mapping.c2
-rw-r--r--pango/pango-context.c8
-rw-r--r--pango/pango-glyph.h6
-rw-r--r--pango/pango-layout.c873
-rw-r--r--pango/pango-layout.h71
-rw-r--r--pango/pangox.c106
-rw-r--r--pango/pangox.h45
-rw-r--r--pango/reorder-items.c10
27 files changed, 1713 insertions, 557 deletions
diff --git a/.cvsignore b/.cvsignore
index 850b88e0..f7b688c3 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -5,6 +5,7 @@ config.cache
config.log
config.status
pango.spec
+pango-config
stamp-h
libtool
Makefile
diff --git a/ChangeLog b/ChangeLog
index c3b78dbf..adeda523 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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,
&para, &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)