summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamiro Estrugo <ramiro@src.gnome.org>2001-02-14 02:14:36 +0000
committerRamiro Estrugo <ramiro@src.gnome.org>2001-02-14 02:14:36 +0000
commita9818eb54f3fe55ecee300b4f863e867be459140 (patch)
tree0a5da46f46f6158c0d385b549203df51d9f92d00
parenteb847de035fb7681b63645f64f81320ca83f5836 (diff)
downloadnautilus-a9818eb54f3fe55ecee300b4f863e867be459140.tar.gz
reviewed by: Arik Devens <arik@eazel.com>
* libnautilus-extensions/Makefile.am: * libnautilus-extensions/nautilus-label.c: * libnautilus-extensions/nautilus-scalable-font.c: * libnautilus-extensions/nautilus-scalable-font.h: * libnautilus-extensions/nautilus-text-layout.c: * libnautilus-extensions/nautilus-text-layout.h: * test/test-nautilus-font.c: Move the text layout code to its own place. No real code changes.
-rw-r--r--libnautilus-extensions/Makefile.am2
-rw-r--r--libnautilus-extensions/nautilus-label.c1
-rw-r--r--libnautilus-extensions/nautilus-scalable-font.c322
-rw-r--r--libnautilus-extensions/nautilus-scalable-font.h45
-rw-r--r--libnautilus-extensions/nautilus-text-layout.c350
-rw-r--r--libnautilus-extensions/nautilus-text-layout.h84
-rw-r--r--libnautilus-private/Makefile.am2
-rw-r--r--libnautilus-private/nautilus-label.c1
-rw-r--r--libnautilus-private/nautilus-scalable-font.c322
-rw-r--r--libnautilus-private/nautilus-scalable-font.h45
-rw-r--r--libnautilus-private/nautilus-text-layout.c350
-rw-r--r--libnautilus-private/nautilus-text-layout.h84
-rw-r--r--test/test-nautilus-font.c1
13 files changed, 877 insertions, 732 deletions
diff --git a/libnautilus-extensions/Makefile.am b/libnautilus-extensions/Makefile.am
index 945735da5..771e2bf72 100644
--- a/libnautilus-extensions/Makefile.am
+++ b/libnautilus-extensions/Makefile.am
@@ -147,6 +147,7 @@ libnautilus_extensions_la_SOURCES = \
nautilus-string.c \
nautilus-tabs.c \
nautilus-text-caption.c \
+ nautilus-text-layout.c \
nautilus-theme.c \
nautilus-thumbnails.c \
nautilus-trash-directory.c \
@@ -267,6 +268,7 @@ noinst_HEADERS = \
nautilus-string.h \
nautilus-tabs.h \
nautilus-text-caption.h \
+ nautilus-text-layout.h \
nautilus-theme.h \
nautilus-thumbnails.h \
nautilus-trash-directory.h \
diff --git a/libnautilus-extensions/nautilus-label.c b/libnautilus-extensions/nautilus-label.c
index bb19e61fc..3629b17e9 100644
--- a/libnautilus-extensions/nautilus-label.c
+++ b/libnautilus-extensions/nautilus-label.c
@@ -33,6 +33,7 @@
#include "nautilus-gdk-pixbuf-extensions.h"
#include "nautilus-art-gtk-extensions.h"
#include "nautilus-string.h"
+#include "nautilus-text-layout.h"
#include "nautilus-debug-drawing.h"
/* These are arbitrary constants to catch insane values */
diff --git a/libnautilus-extensions/nautilus-scalable-font.c b/libnautilus-extensions/nautilus-scalable-font.c
index af074599d..7780dfe4a 100644
--- a/libnautilus-extensions/nautilus-scalable-font.c
+++ b/libnautilus-extensions/nautilus-scalable-font.c
@@ -34,6 +34,7 @@
#include "nautilus-glib-extensions.h"
#include "nautilus-string-map.h"
#include "nautilus-lib-self-check-functions.h"
+#include "nautilus-glyph.h"
#include <librsvg/rsvg-ft.h>
@@ -1413,327 +1414,6 @@ nautilus_scalable_font_get_rsvg_context (const NautilusScalableFont *font)
return global_rsvg_ft_context;
}
-/*
- * The following text_layout stuff was shamelessly plundered
- * from libgnomeui/gnome-icon-text.[ch] by Federico Mena.
- *
- * It was hacked to use NautilusScalableFont and GdkPixbuf
- * instead of GdkFont and GdkDrawable. We want to use the
- * same layout algorithm in Nautilus so that both the smooth
- * and not smooth text rendering cases have predictably
- * similar result.
- *
- * I also made some minor Nautilus-like style changes. -re
- *
- */
-static void
-text_layout_free_row (gpointer data,
- gpointer user_data)
-{
- NautilusTextLayoutRow *row;
-
- if (data) {
- row = data;
- g_free (row->text);
- g_free (row);
- }
-}
-
-/**
- * nautilus_text_layout_free:
- * @ti: An icon text info structure.
- *
- * Frees a &NautilusTextLayout structure. You should call this instead of
- * freeing the structure yourself.
- */
-void
-nautilus_text_layout_free (NautilusTextLayout *text_layout)
-{
- g_list_foreach (text_layout->rows, text_layout_free_row, NULL);
- g_list_free (text_layout->rows);
- g_free (text_layout);
-}
-
-/**
- * nautilus_text_layout_new:
- * @font: Name of the font that will be used to render the text.
- * @text: Text to be formatted.
- * @separators: Separators used for word wrapping, can be NULL.
- * @max_width: Width in pixels to be used for word wrapping.
- * @confine: Whether it is mandatory to wrap at @max_width.
- *
- * Creates a new &NautilusTextLayout structure by wrapping the specified
- * text. If non-NULL, the @separators argument defines a set of characters
- * to be used as word delimiters for performing word wrapping. If it is
- * NULL, then only spaces will be used as word delimiters.
- *
- * The @max_width argument is used to specify the width at which word
- * wrapping will be performed. If there is a very long word that does not
- * fit in a single line, the @confine argument can be used to specify
- * whether the word should be unconditionally split to fit or whether
- * the maximum width should be increased as necessary.
- *
- * Return value: A newly-created &NautilusTextLayout structure.
- */
-NautilusTextLayout *
-nautilus_text_layout_new (const NautilusScalableFont *font,
- int font_size,
- const char *text,
- const char *separators,
- int max_width,
- gboolean confine)
-{
- NautilusTextLayout *text_layout;
- NautilusTextLayoutRow *row;
- const char *row_end;
- const char *s, *word_start, *word_end, *old_word_end;
- char *sub_text;
- int i, w_len;
- int w;
- const char *text_iter;
- int text_len, separators_len;
-
- g_return_val_if_fail (font != NULL, NULL);
- g_return_val_if_fail (font_size > 0, NULL);
- g_return_val_if_fail (text != NULL, NULL);
- g_return_val_if_fail (nautilus_strlen (text) > 0, NULL);
-
- if (!separators)
- separators = " ";
-
- text_len = strlen (text);
-
- separators_len = strlen (separators);
-
- text_layout = g_new (NautilusTextLayout, 1);
-
- text_layout->rows = NULL;
- text_layout->font = font;
- text_layout->font_size = font_size;
- text_layout->width = 0;
- text_layout->height = 0;
- text_layout->baseline_skip = font_size;
-
- word_end = NULL;
-
- text_iter = text;
- while (*text_iter) {
- for (row_end = text_iter; *row_end != 0 && *row_end != '\n'; row_end++);
-
- /* Accumulate words from this row until they don't fit in the max_width */
-
- s = text_iter;
-
- while (s < row_end) {
- word_start = s;
- old_word_end = word_end;
- for (word_end = word_start; *word_end; word_end++) {
- const char *p;
- for (p = separators; *p; p++) {
- if (*word_end == *p)
- goto found;
- }
- }
- found:
- if (word_end < row_end)
- word_end++;
-
- if (nautilus_scalable_font_text_width (font, font_size, font_size, text_iter, word_end - text_iter) > max_width) {
- if (word_start == text_iter) {
- if (confine) {
- /* We must force-split the word. Look for a proper
- * place to do it.
- */
-
- w_len = word_end - word_start;
-
- for (i = 1; i < w_len; i++) {
- w = nautilus_scalable_font_text_width (font, font_size, font_size, word_start, i);
- if (w > max_width) {
- if (i == 1)
- /* Shit, not even a single character fits */
- max_width = w;
- else
- break;
- }
- }
-
- /* Create sub-row with the chars that fit */
-
- sub_text = g_strndup (word_start, i - 1);
-
- row = g_new (NautilusTextLayoutRow, 1);
- row->text = sub_text;
- row->text_length = i - 1;
- row->width = nautilus_scalable_font_text_width (font, font_size, font_size,
- sub_text,
- strlen (sub_text));
-
- text_layout->rows = g_list_append (text_layout->rows, row);
-
- if (row->width > text_layout->width)
- text_layout->width = row->width;
-
- text_layout->height += text_layout->baseline_skip;
-
- /* Bump the text pointer */
-
- text_iter += i - 1;
- s = text_iter;
-
- continue;
- } else
- max_width = nautilus_scalable_font_text_width (font, font_size, font_size, word_start, word_end - word_start);
-
- continue; /* Retry split */
- } else {
- word_end = old_word_end; /* Restore to region that does fit */
- break; /* Stop the loop because we found something that doesn't fit */
- }
- }
-
- s = word_end;
- }
-
- /* Append row */
-
- if (text_iter == row_end) {
- /* We are on a newline, so append an empty row */
-
- text_layout->rows = g_list_append (text_layout->rows, NULL);
- text_layout->height += text_layout->baseline_skip / 2;
-
- /* Next! */
-
- text_iter = row_end + 1;
- } else {
- /* Create subrow and append it to the list */
-
- int sub_len;
- sub_len = word_end - text_iter;
-
- sub_text = g_strndup (text_iter, sub_len);
-
- row = g_new (NautilusTextLayoutRow, 1);
- row->text = sub_text;
- row->text_length = sub_len;
- row->width = nautilus_scalable_font_text_width (font, font_size, font_size, sub_text, sub_len);
-
- text_layout->rows = g_list_append (text_layout->rows, row);
-
- if (row->width > text_layout->width)
- text_layout->width = row->width;
-
- text_layout->height += text_layout->baseline_skip;
-
- /* Next! */
-
- text_iter = word_end;
- }
- }
-
- return text_layout;
-}
-
-/**
- * nautilus_text_layout_paint:
- * @ti: An icon text info structure.
- * @drawable: Target drawable.
- * @gc: GC used to render the string.
- * @x: Left coordinate for text.
- * @y: Upper coordinate for text.
- * @just: Justification for text.
- *
- * Paints the formatted text in the icon text info structure onto a drawable.
- * This is just a sample implementation; applications can choose to use other
- * rendering functions.
- */
-void
-nautilus_text_layout_paint (const NautilusTextLayout *text_layout,
- GdkPixbuf *destination_pixbuf,
- int x,
- int y,
- GtkJustification justification,
- guint32 color,
- gboolean underlined)
-{
- GList *item;
- const NautilusTextLayoutRow *row;
- int xpos;
-
- g_return_if_fail (text_layout != NULL);
- g_return_if_fail (destination_pixbuf != NULL);
- g_return_if_fail (justification >= GTK_JUSTIFY_LEFT && justification <= GTK_JUSTIFY_FILL);
-
- /* FIXME bugzilla.eazel.com 5087: Make sure the color we are fed is opaque. The real solution is
- * to fix the callers.
- */
- color = NAUTILUS_RGBA_COLOR_PACK (NAUTILUS_RGBA_COLOR_GET_R (color),
- NAUTILUS_RGBA_COLOR_GET_G (color),
- NAUTILUS_RGBA_COLOR_GET_B (color),
- NAUTILUS_OPACITY_FULLY_OPAQUE);
-
- for (item = text_layout->rows; item; item = item->next) {
- if (item->data) {
- row = item->data;
-
- switch (justification) {
- case GTK_JUSTIFY_LEFT:
- xpos = 0;
- break;
-
- case GTK_JUSTIFY_RIGHT:
- xpos = text_layout->width - row->width;
- break;
-
- case GTK_JUSTIFY_CENTER:
- xpos = (text_layout->width - row->width) / 2;
- break;
-
- default:
- /* Anyone care to implement GTK_JUSTIFY_FILL? */
- g_warning ("Justification type %d not supported. Using left-justification.",
- (int) justification);
- xpos = 0;
- }
-
- nautilus_scalable_font_draw_text (text_layout->font,
- destination_pixbuf,
- x + xpos,
- y,
- NULL,
- text_layout->font_size,
- text_layout->font_size,
- row->text,
- row->text_length,
- color,
- NAUTILUS_OPACITY_FULLY_OPAQUE);
-
- /* Underline the text if needed */
- if (underlined) {
- ArtIRect underline_rect;
-
- /* FIXME bugzilla.eazel.com 2865: This underlining code should
- * take into account the baseline for the rendered string rather
- * that doing the '-2' nonsense.
- */
- nautilus_art_irect_assign (&underline_rect,
- x + xpos,
- y + text_layout->font_size - 2,
- row->width,
- 1);
-
- nautilus_gdk_pixbuf_fill_rectangle_with_color (destination_pixbuf,
- &underline_rect,
- color);
- }
-
- y += text_layout->baseline_skip;
- } else
- y += text_layout->baseline_skip / 2;
- }
-}
-
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
void
diff --git a/libnautilus-extensions/nautilus-scalable-font.h b/libnautilus-extensions/nautilus-scalable-font.h
index b982d60b2..cbef1e42e 100644
--- a/libnautilus-extensions/nautilus-scalable-font.h
+++ b/libnautilus-extensions/nautilus-scalable-font.h
@@ -152,51 +152,6 @@ gboolean nautilus_scalable_font_query_font (c
NautilusStringList **set_widths);
NautilusScalableFont *nautilus_scalable_font_make_bold (NautilusScalableFont *font);
-/*
- * The following text_layout stuff was shamelessly plundered
- * from libgnomeui/gnome-icon-text.[ch] by Federico Mena.
- *
- * It was hacked to use NautilusScalableFont and GdkPixbuf
- * instead of GdkFont and GdkDrawable. We want to use the
- * same layout algorithm in Nautilus so that both the smooth
- * and not smooth text rendering cases have predictably
- * similar result.
- *
- * I also made some minor Nautilus-like style changes. -re
-
- */
-typedef struct
-{
- char *text;
- int width;
- guint text_length;
-} NautilusTextLayoutRow;
-
-typedef struct
-{
- GList *rows;
- const NautilusScalableFont *font;
- int font_size;
- int width;
- int height;
- int baseline_skip;
-} NautilusTextLayout;
-
-NautilusTextLayout *nautilus_text_layout_new (const NautilusScalableFont *font,
- int font_size,
- const char *text,
- const char *separators,
- int max_width,
- gboolean confine);
-void nautilus_text_layout_paint (const NautilusTextLayout *text_info,
- GdkPixbuf *pixbuf,
- int x,
- int y,
- GtkJustification justification,
- guint32 color,
- gboolean underlined);
-void nautilus_text_layout_free (NautilusTextLayout *text_info);
-
END_GNOME_DECLS
#endif /* NAUTILUS_SCALABLE_FONT_H */
diff --git a/libnautilus-extensions/nautilus-text-layout.c b/libnautilus-extensions/nautilus-text-layout.c
new file mode 100644
index 000000000..2c54607eb
--- /dev/null
+++ b/libnautilus-extensions/nautilus-text-layout.c
@@ -0,0 +1,350 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-text-layout.c - Functions to layout text.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ The Gnome 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.
+
+ The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Ramiro Estrugo <ramiro@eazel.com>
+*/
+
+#include <config.h>
+#include "nautilus-text-layout.h"
+#include "nautilus-string.h"
+#include "nautilus-gdk-extensions.h"
+#include "nautilus-gdk-pixbuf-extensions.h"
+
+/*
+ * The following text_layout stuff was shamelessly plundered
+ * from libgnomeui/gnome-icon-text.[ch] by Federico Mena.
+ *
+ * It was hacked to use NautilusScalableFont and GdkPixbuf
+ * instead of GdkFont and GdkDrawable. We want to use the
+ * same layout algorithm in Nautilus so that both the smooth
+ * and not smooth text rendering cases have predictably
+ * similar result.
+ *
+ * I also made some minor Nautilus-like style changes. -re
+ *
+ */
+static void
+text_layout_free_row (gpointer data,
+ gpointer user_data)
+{
+ NautilusTextLayoutRow *row;
+
+ if (data) {
+ row = data;
+ g_free (row->text);
+ g_free (row);
+ }
+}
+
+/**
+ * nautilus_text_layout_free:
+ * @ti: An icon text info structure.
+ *
+ * Frees a &NautilusTextLayout structure. You should call this instead of
+ * freeing the structure yourself.
+ */
+void
+nautilus_text_layout_free (NautilusTextLayout *text_layout)
+{
+ g_list_foreach (text_layout->rows, text_layout_free_row, NULL);
+ g_list_free (text_layout->rows);
+ g_free (text_layout);
+}
+
+/**
+ * nautilus_text_layout_new:
+ * @font: Name of the font that will be used to render the text.
+ * @text: Text to be formatted.
+ * @separators: Separators used for word wrapping, can be NULL.
+ * @max_width: Width in pixels to be used for word wrapping.
+ * @confine: Whether it is mandatory to wrap at @max_width.
+ *
+ * Creates a new &NautilusTextLayout structure by wrapping the specified
+ * text. If non-NULL, the @separators argument defines a set of characters
+ * to be used as word delimiters for performing word wrapping. If it is
+ * NULL, then only spaces will be used as word delimiters.
+ *
+ * The @max_width argument is used to specify the width at which word
+ * wrapping will be performed. If there is a very long word that does not
+ * fit in a single line, the @confine argument can be used to specify
+ * whether the word should be unconditionally split to fit or whether
+ * the maximum width should be increased as necessary.
+ *
+ * Return value: A newly-created &NautilusTextLayout structure.
+ */
+NautilusTextLayout *
+nautilus_text_layout_new (const NautilusScalableFont *font,
+ int font_size,
+ const char *text,
+ const char *separators,
+ int max_width,
+ gboolean confine)
+{
+ NautilusTextLayout *text_layout;
+ NautilusTextLayoutRow *row;
+ const char *row_end;
+ const char *s, *word_start, *word_end, *old_word_end;
+ char *sub_text;
+ int i, w_len;
+ int w;
+ const char *text_iter;
+ int text_len, separators_len;
+
+ g_return_val_if_fail (font != NULL, NULL);
+ g_return_val_if_fail (font_size > 0, NULL);
+ g_return_val_if_fail (text != NULL, NULL);
+ g_return_val_if_fail (nautilus_strlen (text) > 0, NULL);
+
+ if (!separators)
+ separators = " ";
+
+ text_len = strlen (text);
+
+ separators_len = strlen (separators);
+
+ text_layout = g_new (NautilusTextLayout, 1);
+
+ text_layout->rows = NULL;
+ text_layout->font = font;
+ text_layout->font_size = font_size;
+ text_layout->width = 0;
+ text_layout->height = 0;
+ text_layout->baseline_skip = font_size;
+
+ word_end = NULL;
+
+ text_iter = text;
+ while (*text_iter) {
+ for (row_end = text_iter; *row_end != 0 && *row_end != '\n'; row_end++);
+
+ /* Accumulate words from this row until they don't fit in the max_width */
+
+ s = text_iter;
+
+ while (s < row_end) {
+ word_start = s;
+ old_word_end = word_end;
+ for (word_end = word_start; *word_end; word_end++) {
+ const char *p;
+ for (p = separators; *p; p++) {
+ if (*word_end == *p)
+ goto found;
+ }
+ }
+ found:
+ if (word_end < row_end)
+ word_end++;
+
+ if (nautilus_scalable_font_text_width (font, font_size, font_size, text_iter, word_end - text_iter) > max_width) {
+ if (word_start == text_iter) {
+ if (confine) {
+ /* We must force-split the word. Look for a proper
+ * place to do it.
+ */
+
+ w_len = word_end - word_start;
+
+ for (i = 1; i < w_len; i++) {
+ w = nautilus_scalable_font_text_width (font, font_size, font_size, word_start, i);
+ if (w > max_width) {
+ if (i == 1)
+ /* Shit, not even a single character fits */
+ max_width = w;
+ else
+ break;
+ }
+ }
+
+ /* Create sub-row with the chars that fit */
+
+ sub_text = g_strndup (word_start, i - 1);
+
+ row = g_new (NautilusTextLayoutRow, 1);
+ row->text = sub_text;
+ row->text_length = i - 1;
+ row->width = nautilus_scalable_font_text_width (font, font_size, font_size,
+ sub_text,
+ strlen (sub_text));
+
+ text_layout->rows = g_list_append (text_layout->rows, row);
+
+ if (row->width > text_layout->width)
+ text_layout->width = row->width;
+
+ text_layout->height += text_layout->baseline_skip;
+
+ /* Bump the text pointer */
+
+ text_iter += i - 1;
+ s = text_iter;
+
+ continue;
+ } else
+ max_width = nautilus_scalable_font_text_width (font, font_size, font_size, word_start, word_end - word_start);
+
+ continue; /* Retry split */
+ } else {
+ word_end = old_word_end; /* Restore to region that does fit */
+ break; /* Stop the loop because we found something that doesn't fit */
+ }
+ }
+
+ s = word_end;
+ }
+
+ /* Append row */
+
+ if (text_iter == row_end) {
+ /* We are on a newline, so append an empty row */
+
+ text_layout->rows = g_list_append (text_layout->rows, NULL);
+ text_layout->height += text_layout->baseline_skip / 2;
+
+ /* Next! */
+
+ text_iter = row_end + 1;
+ } else {
+ /* Create subrow and append it to the list */
+
+ int sub_len;
+ sub_len = word_end - text_iter;
+
+ sub_text = g_strndup (text_iter, sub_len);
+
+ row = g_new (NautilusTextLayoutRow, 1);
+ row->text = sub_text;
+ row->text_length = sub_len;
+ row->width = nautilus_scalable_font_text_width (font, font_size, font_size, sub_text, sub_len);
+
+ text_layout->rows = g_list_append (text_layout->rows, row);
+
+ if (row->width > text_layout->width)
+ text_layout->width = row->width;
+
+ text_layout->height += text_layout->baseline_skip;
+
+ /* Next! */
+
+ text_iter = word_end;
+ }
+ }
+
+ return text_layout;
+}
+
+/**
+ * nautilus_text_layout_paint:
+ * @ti: An icon text info structure.
+ * @drawable: Target drawable.
+ * @gc: GC used to render the string.
+ * @x: Left coordinate for text.
+ * @y: Upper coordinate for text.
+ * @just: Justification for text.
+ *
+ * Paints the formatted text in the icon text info structure onto a drawable.
+ * This is just a sample implementation; applications can choose to use other
+ * rendering functions.
+ */
+void
+nautilus_text_layout_paint (const NautilusTextLayout *text_layout,
+ GdkPixbuf *destination_pixbuf,
+ int x,
+ int y,
+ GtkJustification justification,
+ guint32 color,
+ gboolean underlined)
+{
+ GList *item;
+ const NautilusTextLayoutRow *row;
+ int xpos;
+
+ g_return_if_fail (text_layout != NULL);
+ g_return_if_fail (destination_pixbuf != NULL);
+ g_return_if_fail (justification >= GTK_JUSTIFY_LEFT && justification <= GTK_JUSTIFY_FILL);
+
+ /* FIXME bugzilla.eazel.com 5087: Make sure the color we are fed is opaque. The real solution is
+ * to fix the callers.
+ */
+ color = NAUTILUS_RGBA_COLOR_PACK (NAUTILUS_RGBA_COLOR_GET_R (color),
+ NAUTILUS_RGBA_COLOR_GET_G (color),
+ NAUTILUS_RGBA_COLOR_GET_B (color),
+ NAUTILUS_OPACITY_FULLY_OPAQUE);
+
+ for (item = text_layout->rows; item; item = item->next) {
+ if (item->data) {
+ row = item->data;
+
+ switch (justification) {
+ case GTK_JUSTIFY_LEFT:
+ xpos = 0;
+ break;
+
+ case GTK_JUSTIFY_RIGHT:
+ xpos = text_layout->width - row->width;
+ break;
+
+ case GTK_JUSTIFY_CENTER:
+ xpos = (text_layout->width - row->width) / 2;
+ break;
+
+ default:
+ /* Anyone care to implement GTK_JUSTIFY_FILL? */
+ g_warning ("Justification type %d not supported. Using left-justification.",
+ (int) justification);
+ xpos = 0;
+ }
+
+ nautilus_scalable_font_draw_text (text_layout->font,
+ destination_pixbuf,
+ x + xpos,
+ y,
+ NULL,
+ text_layout->font_size,
+ text_layout->font_size,
+ row->text,
+ row->text_length,
+ color,
+ NAUTILUS_OPACITY_FULLY_OPAQUE);
+
+ /* Underline the text if needed */
+ if (underlined) {
+ ArtIRect underline_rect;
+
+ /* FIXME bugzilla.eazel.com 2865: This underlining code should
+ * take into account the baseline for the rendered string rather
+ * that doing the '-2' nonsense.
+ */
+ nautilus_art_irect_assign (&underline_rect,
+ x + xpos,
+ y + text_layout->font_size - 2,
+ row->width,
+ 1);
+
+ nautilus_gdk_pixbuf_fill_rectangle_with_color (destination_pixbuf,
+ &underline_rect,
+ color);
+ }
+
+ y += text_layout->baseline_skip;
+ } else
+ y += text_layout->baseline_skip / 2;
+ }
+}
diff --git a/libnautilus-extensions/nautilus-text-layout.h b/libnautilus-extensions/nautilus-text-layout.h
new file mode 100644
index 000000000..02a419828
--- /dev/null
+++ b/libnautilus-extensions/nautilus-text-layout.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-text-layout.h - Functions to layout text.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ The Gnome 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.
+
+ The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Ramiro Estrugo <ramiro@eazel.com>
+*/
+
+#ifndef NAUTILUS_TEXT_LAYOUT_H
+#define NAUTILUS_TEXT_LAYOUT_H
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <libgnome/gnome-defs.h>
+#include <libnautilus-extensions/nautilus-scalable-font.h>
+#include <libart_lgpl/art_rect.h>
+
+BEGIN_GNOME_DECLS
+
+/*
+ * The following text_layout stuff was shamelessly plundered
+ * from libgnomeui/gnome-icon-text.[ch] by Federico Mena.
+ *
+ * It was hacked to use NautilusScalableFont and GdkPixbuf
+ * instead of GdkFont and GdkDrawable. We want to use the
+ * same layout algorithm in Nautilus so that both the smooth
+ * and not smooth text rendering cases have predictably
+ * similar result.
+ *
+ * I also made some minor Nautilus-like style changes. -re
+
+ */
+typedef struct
+{
+ char *text;
+ int width;
+ guint text_length;
+} NautilusTextLayoutRow;
+
+typedef struct
+{
+ GList *rows;
+ const NautilusScalableFont *font;
+ int font_size;
+ int width;
+ int height;
+ int baseline_skip;
+} NautilusTextLayout;
+
+NautilusTextLayout *nautilus_text_layout_new (const NautilusScalableFont *font,
+ int font_size,
+ const char *text,
+ const char *separators,
+ int max_width,
+ gboolean confine);
+void nautilus_text_layout_paint (const NautilusTextLayout *text_info,
+ GdkPixbuf *pixbuf,
+ int x,
+ int y,
+ GtkJustification justification,
+ guint32 color,
+ gboolean underlined);
+void nautilus_text_layout_free (NautilusTextLayout *text_info);
+
+END_GNOME_DECLS
+
+#endif /* NAUTILUS_TEXT_LAYOUT_H */
+
+
diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am
index 945735da5..771e2bf72 100644
--- a/libnautilus-private/Makefile.am
+++ b/libnautilus-private/Makefile.am
@@ -147,6 +147,7 @@ libnautilus_extensions_la_SOURCES = \
nautilus-string.c \
nautilus-tabs.c \
nautilus-text-caption.c \
+ nautilus-text-layout.c \
nautilus-theme.c \
nautilus-thumbnails.c \
nautilus-trash-directory.c \
@@ -267,6 +268,7 @@ noinst_HEADERS = \
nautilus-string.h \
nautilus-tabs.h \
nautilus-text-caption.h \
+ nautilus-text-layout.h \
nautilus-theme.h \
nautilus-thumbnails.h \
nautilus-trash-directory.h \
diff --git a/libnautilus-private/nautilus-label.c b/libnautilus-private/nautilus-label.c
index bb19e61fc..3629b17e9 100644
--- a/libnautilus-private/nautilus-label.c
+++ b/libnautilus-private/nautilus-label.c
@@ -33,6 +33,7 @@
#include "nautilus-gdk-pixbuf-extensions.h"
#include "nautilus-art-gtk-extensions.h"
#include "nautilus-string.h"
+#include "nautilus-text-layout.h"
#include "nautilus-debug-drawing.h"
/* These are arbitrary constants to catch insane values */
diff --git a/libnautilus-private/nautilus-scalable-font.c b/libnautilus-private/nautilus-scalable-font.c
index af074599d..7780dfe4a 100644
--- a/libnautilus-private/nautilus-scalable-font.c
+++ b/libnautilus-private/nautilus-scalable-font.c
@@ -34,6 +34,7 @@
#include "nautilus-glib-extensions.h"
#include "nautilus-string-map.h"
#include "nautilus-lib-self-check-functions.h"
+#include "nautilus-glyph.h"
#include <librsvg/rsvg-ft.h>
@@ -1413,327 +1414,6 @@ nautilus_scalable_font_get_rsvg_context (const NautilusScalableFont *font)
return global_rsvg_ft_context;
}
-/*
- * The following text_layout stuff was shamelessly plundered
- * from libgnomeui/gnome-icon-text.[ch] by Federico Mena.
- *
- * It was hacked to use NautilusScalableFont and GdkPixbuf
- * instead of GdkFont and GdkDrawable. We want to use the
- * same layout algorithm in Nautilus so that both the smooth
- * and not smooth text rendering cases have predictably
- * similar result.
- *
- * I also made some minor Nautilus-like style changes. -re
- *
- */
-static void
-text_layout_free_row (gpointer data,
- gpointer user_data)
-{
- NautilusTextLayoutRow *row;
-
- if (data) {
- row = data;
- g_free (row->text);
- g_free (row);
- }
-}
-
-/**
- * nautilus_text_layout_free:
- * @ti: An icon text info structure.
- *
- * Frees a &NautilusTextLayout structure. You should call this instead of
- * freeing the structure yourself.
- */
-void
-nautilus_text_layout_free (NautilusTextLayout *text_layout)
-{
- g_list_foreach (text_layout->rows, text_layout_free_row, NULL);
- g_list_free (text_layout->rows);
- g_free (text_layout);
-}
-
-/**
- * nautilus_text_layout_new:
- * @font: Name of the font that will be used to render the text.
- * @text: Text to be formatted.
- * @separators: Separators used for word wrapping, can be NULL.
- * @max_width: Width in pixels to be used for word wrapping.
- * @confine: Whether it is mandatory to wrap at @max_width.
- *
- * Creates a new &NautilusTextLayout structure by wrapping the specified
- * text. If non-NULL, the @separators argument defines a set of characters
- * to be used as word delimiters for performing word wrapping. If it is
- * NULL, then only spaces will be used as word delimiters.
- *
- * The @max_width argument is used to specify the width at which word
- * wrapping will be performed. If there is a very long word that does not
- * fit in a single line, the @confine argument can be used to specify
- * whether the word should be unconditionally split to fit or whether
- * the maximum width should be increased as necessary.
- *
- * Return value: A newly-created &NautilusTextLayout structure.
- */
-NautilusTextLayout *
-nautilus_text_layout_new (const NautilusScalableFont *font,
- int font_size,
- const char *text,
- const char *separators,
- int max_width,
- gboolean confine)
-{
- NautilusTextLayout *text_layout;
- NautilusTextLayoutRow *row;
- const char *row_end;
- const char *s, *word_start, *word_end, *old_word_end;
- char *sub_text;
- int i, w_len;
- int w;
- const char *text_iter;
- int text_len, separators_len;
-
- g_return_val_if_fail (font != NULL, NULL);
- g_return_val_if_fail (font_size > 0, NULL);
- g_return_val_if_fail (text != NULL, NULL);
- g_return_val_if_fail (nautilus_strlen (text) > 0, NULL);
-
- if (!separators)
- separators = " ";
-
- text_len = strlen (text);
-
- separators_len = strlen (separators);
-
- text_layout = g_new (NautilusTextLayout, 1);
-
- text_layout->rows = NULL;
- text_layout->font = font;
- text_layout->font_size = font_size;
- text_layout->width = 0;
- text_layout->height = 0;
- text_layout->baseline_skip = font_size;
-
- word_end = NULL;
-
- text_iter = text;
- while (*text_iter) {
- for (row_end = text_iter; *row_end != 0 && *row_end != '\n'; row_end++);
-
- /* Accumulate words from this row until they don't fit in the max_width */
-
- s = text_iter;
-
- while (s < row_end) {
- word_start = s;
- old_word_end = word_end;
- for (word_end = word_start; *word_end; word_end++) {
- const char *p;
- for (p = separators; *p; p++) {
- if (*word_end == *p)
- goto found;
- }
- }
- found:
- if (word_end < row_end)
- word_end++;
-
- if (nautilus_scalable_font_text_width (font, font_size, font_size, text_iter, word_end - text_iter) > max_width) {
- if (word_start == text_iter) {
- if (confine) {
- /* We must force-split the word. Look for a proper
- * place to do it.
- */
-
- w_len = word_end - word_start;
-
- for (i = 1; i < w_len; i++) {
- w = nautilus_scalable_font_text_width (font, font_size, font_size, word_start, i);
- if (w > max_width) {
- if (i == 1)
- /* Shit, not even a single character fits */
- max_width = w;
- else
- break;
- }
- }
-
- /* Create sub-row with the chars that fit */
-
- sub_text = g_strndup (word_start, i - 1);
-
- row = g_new (NautilusTextLayoutRow, 1);
- row->text = sub_text;
- row->text_length = i - 1;
- row->width = nautilus_scalable_font_text_width (font, font_size, font_size,
- sub_text,
- strlen (sub_text));
-
- text_layout->rows = g_list_append (text_layout->rows, row);
-
- if (row->width > text_layout->width)
- text_layout->width = row->width;
-
- text_layout->height += text_layout->baseline_skip;
-
- /* Bump the text pointer */
-
- text_iter += i - 1;
- s = text_iter;
-
- continue;
- } else
- max_width = nautilus_scalable_font_text_width (font, font_size, font_size, word_start, word_end - word_start);
-
- continue; /* Retry split */
- } else {
- word_end = old_word_end; /* Restore to region that does fit */
- break; /* Stop the loop because we found something that doesn't fit */
- }
- }
-
- s = word_end;
- }
-
- /* Append row */
-
- if (text_iter == row_end) {
- /* We are on a newline, so append an empty row */
-
- text_layout->rows = g_list_append (text_layout->rows, NULL);
- text_layout->height += text_layout->baseline_skip / 2;
-
- /* Next! */
-
- text_iter = row_end + 1;
- } else {
- /* Create subrow and append it to the list */
-
- int sub_len;
- sub_len = word_end - text_iter;
-
- sub_text = g_strndup (text_iter, sub_len);
-
- row = g_new (NautilusTextLayoutRow, 1);
- row->text = sub_text;
- row->text_length = sub_len;
- row->width = nautilus_scalable_font_text_width (font, font_size, font_size, sub_text, sub_len);
-
- text_layout->rows = g_list_append (text_layout->rows, row);
-
- if (row->width > text_layout->width)
- text_layout->width = row->width;
-
- text_layout->height += text_layout->baseline_skip;
-
- /* Next! */
-
- text_iter = word_end;
- }
- }
-
- return text_layout;
-}
-
-/**
- * nautilus_text_layout_paint:
- * @ti: An icon text info structure.
- * @drawable: Target drawable.
- * @gc: GC used to render the string.
- * @x: Left coordinate for text.
- * @y: Upper coordinate for text.
- * @just: Justification for text.
- *
- * Paints the formatted text in the icon text info structure onto a drawable.
- * This is just a sample implementation; applications can choose to use other
- * rendering functions.
- */
-void
-nautilus_text_layout_paint (const NautilusTextLayout *text_layout,
- GdkPixbuf *destination_pixbuf,
- int x,
- int y,
- GtkJustification justification,
- guint32 color,
- gboolean underlined)
-{
- GList *item;
- const NautilusTextLayoutRow *row;
- int xpos;
-
- g_return_if_fail (text_layout != NULL);
- g_return_if_fail (destination_pixbuf != NULL);
- g_return_if_fail (justification >= GTK_JUSTIFY_LEFT && justification <= GTK_JUSTIFY_FILL);
-
- /* FIXME bugzilla.eazel.com 5087: Make sure the color we are fed is opaque. The real solution is
- * to fix the callers.
- */
- color = NAUTILUS_RGBA_COLOR_PACK (NAUTILUS_RGBA_COLOR_GET_R (color),
- NAUTILUS_RGBA_COLOR_GET_G (color),
- NAUTILUS_RGBA_COLOR_GET_B (color),
- NAUTILUS_OPACITY_FULLY_OPAQUE);
-
- for (item = text_layout->rows; item; item = item->next) {
- if (item->data) {
- row = item->data;
-
- switch (justification) {
- case GTK_JUSTIFY_LEFT:
- xpos = 0;
- break;
-
- case GTK_JUSTIFY_RIGHT:
- xpos = text_layout->width - row->width;
- break;
-
- case GTK_JUSTIFY_CENTER:
- xpos = (text_layout->width - row->width) / 2;
- break;
-
- default:
- /* Anyone care to implement GTK_JUSTIFY_FILL? */
- g_warning ("Justification type %d not supported. Using left-justification.",
- (int) justification);
- xpos = 0;
- }
-
- nautilus_scalable_font_draw_text (text_layout->font,
- destination_pixbuf,
- x + xpos,
- y,
- NULL,
- text_layout->font_size,
- text_layout->font_size,
- row->text,
- row->text_length,
- color,
- NAUTILUS_OPACITY_FULLY_OPAQUE);
-
- /* Underline the text if needed */
- if (underlined) {
- ArtIRect underline_rect;
-
- /* FIXME bugzilla.eazel.com 2865: This underlining code should
- * take into account the baseline for the rendered string rather
- * that doing the '-2' nonsense.
- */
- nautilus_art_irect_assign (&underline_rect,
- x + xpos,
- y + text_layout->font_size - 2,
- row->width,
- 1);
-
- nautilus_gdk_pixbuf_fill_rectangle_with_color (destination_pixbuf,
- &underline_rect,
- color);
- }
-
- y += text_layout->baseline_skip;
- } else
- y += text_layout->baseline_skip / 2;
- }
-}
-
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
void
diff --git a/libnautilus-private/nautilus-scalable-font.h b/libnautilus-private/nautilus-scalable-font.h
index b982d60b2..cbef1e42e 100644
--- a/libnautilus-private/nautilus-scalable-font.h
+++ b/libnautilus-private/nautilus-scalable-font.h
@@ -152,51 +152,6 @@ gboolean nautilus_scalable_font_query_font (c
NautilusStringList **set_widths);
NautilusScalableFont *nautilus_scalable_font_make_bold (NautilusScalableFont *font);
-/*
- * The following text_layout stuff was shamelessly plundered
- * from libgnomeui/gnome-icon-text.[ch] by Federico Mena.
- *
- * It was hacked to use NautilusScalableFont and GdkPixbuf
- * instead of GdkFont and GdkDrawable. We want to use the
- * same layout algorithm in Nautilus so that both the smooth
- * and not smooth text rendering cases have predictably
- * similar result.
- *
- * I also made some minor Nautilus-like style changes. -re
-
- */
-typedef struct
-{
- char *text;
- int width;
- guint text_length;
-} NautilusTextLayoutRow;
-
-typedef struct
-{
- GList *rows;
- const NautilusScalableFont *font;
- int font_size;
- int width;
- int height;
- int baseline_skip;
-} NautilusTextLayout;
-
-NautilusTextLayout *nautilus_text_layout_new (const NautilusScalableFont *font,
- int font_size,
- const char *text,
- const char *separators,
- int max_width,
- gboolean confine);
-void nautilus_text_layout_paint (const NautilusTextLayout *text_info,
- GdkPixbuf *pixbuf,
- int x,
- int y,
- GtkJustification justification,
- guint32 color,
- gboolean underlined);
-void nautilus_text_layout_free (NautilusTextLayout *text_info);
-
END_GNOME_DECLS
#endif /* NAUTILUS_SCALABLE_FONT_H */
diff --git a/libnautilus-private/nautilus-text-layout.c b/libnautilus-private/nautilus-text-layout.c
new file mode 100644
index 000000000..2c54607eb
--- /dev/null
+++ b/libnautilus-private/nautilus-text-layout.c
@@ -0,0 +1,350 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-text-layout.c - Functions to layout text.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ The Gnome 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.
+
+ The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Ramiro Estrugo <ramiro@eazel.com>
+*/
+
+#include <config.h>
+#include "nautilus-text-layout.h"
+#include "nautilus-string.h"
+#include "nautilus-gdk-extensions.h"
+#include "nautilus-gdk-pixbuf-extensions.h"
+
+/*
+ * The following text_layout stuff was shamelessly plundered
+ * from libgnomeui/gnome-icon-text.[ch] by Federico Mena.
+ *
+ * It was hacked to use NautilusScalableFont and GdkPixbuf
+ * instead of GdkFont and GdkDrawable. We want to use the
+ * same layout algorithm in Nautilus so that both the smooth
+ * and not smooth text rendering cases have predictably
+ * similar result.
+ *
+ * I also made some minor Nautilus-like style changes. -re
+ *
+ */
+static void
+text_layout_free_row (gpointer data,
+ gpointer user_data)
+{
+ NautilusTextLayoutRow *row;
+
+ if (data) {
+ row = data;
+ g_free (row->text);
+ g_free (row);
+ }
+}
+
+/**
+ * nautilus_text_layout_free:
+ * @ti: An icon text info structure.
+ *
+ * Frees a &NautilusTextLayout structure. You should call this instead of
+ * freeing the structure yourself.
+ */
+void
+nautilus_text_layout_free (NautilusTextLayout *text_layout)
+{
+ g_list_foreach (text_layout->rows, text_layout_free_row, NULL);
+ g_list_free (text_layout->rows);
+ g_free (text_layout);
+}
+
+/**
+ * nautilus_text_layout_new:
+ * @font: Name of the font that will be used to render the text.
+ * @text: Text to be formatted.
+ * @separators: Separators used for word wrapping, can be NULL.
+ * @max_width: Width in pixels to be used for word wrapping.
+ * @confine: Whether it is mandatory to wrap at @max_width.
+ *
+ * Creates a new &NautilusTextLayout structure by wrapping the specified
+ * text. If non-NULL, the @separators argument defines a set of characters
+ * to be used as word delimiters for performing word wrapping. If it is
+ * NULL, then only spaces will be used as word delimiters.
+ *
+ * The @max_width argument is used to specify the width at which word
+ * wrapping will be performed. If there is a very long word that does not
+ * fit in a single line, the @confine argument can be used to specify
+ * whether the word should be unconditionally split to fit or whether
+ * the maximum width should be increased as necessary.
+ *
+ * Return value: A newly-created &NautilusTextLayout structure.
+ */
+NautilusTextLayout *
+nautilus_text_layout_new (const NautilusScalableFont *font,
+ int font_size,
+ const char *text,
+ const char *separators,
+ int max_width,
+ gboolean confine)
+{
+ NautilusTextLayout *text_layout;
+ NautilusTextLayoutRow *row;
+ const char *row_end;
+ const char *s, *word_start, *word_end, *old_word_end;
+ char *sub_text;
+ int i, w_len;
+ int w;
+ const char *text_iter;
+ int text_len, separators_len;
+
+ g_return_val_if_fail (font != NULL, NULL);
+ g_return_val_if_fail (font_size > 0, NULL);
+ g_return_val_if_fail (text != NULL, NULL);
+ g_return_val_if_fail (nautilus_strlen (text) > 0, NULL);
+
+ if (!separators)
+ separators = " ";
+
+ text_len = strlen (text);
+
+ separators_len = strlen (separators);
+
+ text_layout = g_new (NautilusTextLayout, 1);
+
+ text_layout->rows = NULL;
+ text_layout->font = font;
+ text_layout->font_size = font_size;
+ text_layout->width = 0;
+ text_layout->height = 0;
+ text_layout->baseline_skip = font_size;
+
+ word_end = NULL;
+
+ text_iter = text;
+ while (*text_iter) {
+ for (row_end = text_iter; *row_end != 0 && *row_end != '\n'; row_end++);
+
+ /* Accumulate words from this row until they don't fit in the max_width */
+
+ s = text_iter;
+
+ while (s < row_end) {
+ word_start = s;
+ old_word_end = word_end;
+ for (word_end = word_start; *word_end; word_end++) {
+ const char *p;
+ for (p = separators; *p; p++) {
+ if (*word_end == *p)
+ goto found;
+ }
+ }
+ found:
+ if (word_end < row_end)
+ word_end++;
+
+ if (nautilus_scalable_font_text_width (font, font_size, font_size, text_iter, word_end - text_iter) > max_width) {
+ if (word_start == text_iter) {
+ if (confine) {
+ /* We must force-split the word. Look for a proper
+ * place to do it.
+ */
+
+ w_len = word_end - word_start;
+
+ for (i = 1; i < w_len; i++) {
+ w = nautilus_scalable_font_text_width (font, font_size, font_size, word_start, i);
+ if (w > max_width) {
+ if (i == 1)
+ /* Shit, not even a single character fits */
+ max_width = w;
+ else
+ break;
+ }
+ }
+
+ /* Create sub-row with the chars that fit */
+
+ sub_text = g_strndup (word_start, i - 1);
+
+ row = g_new (NautilusTextLayoutRow, 1);
+ row->text = sub_text;
+ row->text_length = i - 1;
+ row->width = nautilus_scalable_font_text_width (font, font_size, font_size,
+ sub_text,
+ strlen (sub_text));
+
+ text_layout->rows = g_list_append (text_layout->rows, row);
+
+ if (row->width > text_layout->width)
+ text_layout->width = row->width;
+
+ text_layout->height += text_layout->baseline_skip;
+
+ /* Bump the text pointer */
+
+ text_iter += i - 1;
+ s = text_iter;
+
+ continue;
+ } else
+ max_width = nautilus_scalable_font_text_width (font, font_size, font_size, word_start, word_end - word_start);
+
+ continue; /* Retry split */
+ } else {
+ word_end = old_word_end; /* Restore to region that does fit */
+ break; /* Stop the loop because we found something that doesn't fit */
+ }
+ }
+
+ s = word_end;
+ }
+
+ /* Append row */
+
+ if (text_iter == row_end) {
+ /* We are on a newline, so append an empty row */
+
+ text_layout->rows = g_list_append (text_layout->rows, NULL);
+ text_layout->height += text_layout->baseline_skip / 2;
+
+ /* Next! */
+
+ text_iter = row_end + 1;
+ } else {
+ /* Create subrow and append it to the list */
+
+ int sub_len;
+ sub_len = word_end - text_iter;
+
+ sub_text = g_strndup (text_iter, sub_len);
+
+ row = g_new (NautilusTextLayoutRow, 1);
+ row->text = sub_text;
+ row->text_length = sub_len;
+ row->width = nautilus_scalable_font_text_width (font, font_size, font_size, sub_text, sub_len);
+
+ text_layout->rows = g_list_append (text_layout->rows, row);
+
+ if (row->width > text_layout->width)
+ text_layout->width = row->width;
+
+ text_layout->height += text_layout->baseline_skip;
+
+ /* Next! */
+
+ text_iter = word_end;
+ }
+ }
+
+ return text_layout;
+}
+
+/**
+ * nautilus_text_layout_paint:
+ * @ti: An icon text info structure.
+ * @drawable: Target drawable.
+ * @gc: GC used to render the string.
+ * @x: Left coordinate for text.
+ * @y: Upper coordinate for text.
+ * @just: Justification for text.
+ *
+ * Paints the formatted text in the icon text info structure onto a drawable.
+ * This is just a sample implementation; applications can choose to use other
+ * rendering functions.
+ */
+void
+nautilus_text_layout_paint (const NautilusTextLayout *text_layout,
+ GdkPixbuf *destination_pixbuf,
+ int x,
+ int y,
+ GtkJustification justification,
+ guint32 color,
+ gboolean underlined)
+{
+ GList *item;
+ const NautilusTextLayoutRow *row;
+ int xpos;
+
+ g_return_if_fail (text_layout != NULL);
+ g_return_if_fail (destination_pixbuf != NULL);
+ g_return_if_fail (justification >= GTK_JUSTIFY_LEFT && justification <= GTK_JUSTIFY_FILL);
+
+ /* FIXME bugzilla.eazel.com 5087: Make sure the color we are fed is opaque. The real solution is
+ * to fix the callers.
+ */
+ color = NAUTILUS_RGBA_COLOR_PACK (NAUTILUS_RGBA_COLOR_GET_R (color),
+ NAUTILUS_RGBA_COLOR_GET_G (color),
+ NAUTILUS_RGBA_COLOR_GET_B (color),
+ NAUTILUS_OPACITY_FULLY_OPAQUE);
+
+ for (item = text_layout->rows; item; item = item->next) {
+ if (item->data) {
+ row = item->data;
+
+ switch (justification) {
+ case GTK_JUSTIFY_LEFT:
+ xpos = 0;
+ break;
+
+ case GTK_JUSTIFY_RIGHT:
+ xpos = text_layout->width - row->width;
+ break;
+
+ case GTK_JUSTIFY_CENTER:
+ xpos = (text_layout->width - row->width) / 2;
+ break;
+
+ default:
+ /* Anyone care to implement GTK_JUSTIFY_FILL? */
+ g_warning ("Justification type %d not supported. Using left-justification.",
+ (int) justification);
+ xpos = 0;
+ }
+
+ nautilus_scalable_font_draw_text (text_layout->font,
+ destination_pixbuf,
+ x + xpos,
+ y,
+ NULL,
+ text_layout->font_size,
+ text_layout->font_size,
+ row->text,
+ row->text_length,
+ color,
+ NAUTILUS_OPACITY_FULLY_OPAQUE);
+
+ /* Underline the text if needed */
+ if (underlined) {
+ ArtIRect underline_rect;
+
+ /* FIXME bugzilla.eazel.com 2865: This underlining code should
+ * take into account the baseline for the rendered string rather
+ * that doing the '-2' nonsense.
+ */
+ nautilus_art_irect_assign (&underline_rect,
+ x + xpos,
+ y + text_layout->font_size - 2,
+ row->width,
+ 1);
+
+ nautilus_gdk_pixbuf_fill_rectangle_with_color (destination_pixbuf,
+ &underline_rect,
+ color);
+ }
+
+ y += text_layout->baseline_skip;
+ } else
+ y += text_layout->baseline_skip / 2;
+ }
+}
diff --git a/libnautilus-private/nautilus-text-layout.h b/libnautilus-private/nautilus-text-layout.h
new file mode 100644
index 000000000..02a419828
--- /dev/null
+++ b/libnautilus-private/nautilus-text-layout.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-text-layout.h - Functions to layout text.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ The Gnome 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.
+
+ The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Ramiro Estrugo <ramiro@eazel.com>
+*/
+
+#ifndef NAUTILUS_TEXT_LAYOUT_H
+#define NAUTILUS_TEXT_LAYOUT_H
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <libgnome/gnome-defs.h>
+#include <libnautilus-extensions/nautilus-scalable-font.h>
+#include <libart_lgpl/art_rect.h>
+
+BEGIN_GNOME_DECLS
+
+/*
+ * The following text_layout stuff was shamelessly plundered
+ * from libgnomeui/gnome-icon-text.[ch] by Federico Mena.
+ *
+ * It was hacked to use NautilusScalableFont and GdkPixbuf
+ * instead of GdkFont and GdkDrawable. We want to use the
+ * same layout algorithm in Nautilus so that both the smooth
+ * and not smooth text rendering cases have predictably
+ * similar result.
+ *
+ * I also made some minor Nautilus-like style changes. -re
+
+ */
+typedef struct
+{
+ char *text;
+ int width;
+ guint text_length;
+} NautilusTextLayoutRow;
+
+typedef struct
+{
+ GList *rows;
+ const NautilusScalableFont *font;
+ int font_size;
+ int width;
+ int height;
+ int baseline_skip;
+} NautilusTextLayout;
+
+NautilusTextLayout *nautilus_text_layout_new (const NautilusScalableFont *font,
+ int font_size,
+ const char *text,
+ const char *separators,
+ int max_width,
+ gboolean confine);
+void nautilus_text_layout_paint (const NautilusTextLayout *text_info,
+ GdkPixbuf *pixbuf,
+ int x,
+ int y,
+ GtkJustification justification,
+ guint32 color,
+ gboolean underlined);
+void nautilus_text_layout_free (NautilusTextLayout *text_info);
+
+END_GNOME_DECLS
+
+#endif /* NAUTILUS_TEXT_LAYOUT_H */
+
+
diff --git a/test/test-nautilus-font.c b/test/test-nautilus-font.c
index c0bfe070c..43c2b476f 100644
--- a/test/test-nautilus-font.c
+++ b/test/test-nautilus-font.c
@@ -4,6 +4,7 @@
#include "test.h"
#include <libnautilus-extensions/nautilus-scalable-font.h>
+#include <libnautilus-extensions/nautilus-text-layout.h>
int
main (int argc, char* argv[])