From 405a237c21d370f80e243ca5907e889a36c76418 Mon Sep 17 00:00:00 2001
From: Yevgen Muntyan <17531749+muntyan@users.noreply.github.com>
Date: Mon, 27 Mar 2006 19:27:57 -0600
Subject: [PATCH] Print styles and colors
---
moo.kdevelop | 10 +-
moo/mooedit/mootextprint.c | 396 ++++++++++++++++++++++++++++++++++---
moo/mooedit/mootextprint.h | 4 +
3 files changed, 381 insertions(+), 29 deletions(-)
diff --git a/moo.kdevelop b/moo.kdevelop
index 120b2ad2..fca252dc 100644
--- a/moo.kdevelop
+++ b/moo.kdevelop
@@ -36,7 +36,7 @@
gtk-print
- medit
+ ./medit
executable
/
@@ -288,16 +288,16 @@
-
+
A new empty GAP source file
-
+
A new empty C++ file.
-
+
A new empty header file for C/C++.
-
+
A new empty C file.
diff --git a/moo/mooedit/mootextprint.c b/moo/mooedit/mootextprint.c
index 9554392b..5766f3e9 100644
--- a/moo/mooedit/mootextprint.c
+++ b/moo/mooedit/mootextprint.c
@@ -42,7 +42,13 @@ G_DEFINE_TYPE(MooPrintOperation, moo_print_operation, GTK_TYPE_PRINT_OPERATION)
enum {
PROP_0,
- PROP_DOC
+ PROP_DOC,
+ PROP_BUFFER,
+ PROP_WRAP,
+ PROP_WRAP_MODE,
+ PROP_ELLIPSIZE,
+ PROP_FONT,
+ PROP_USE_STYLES
};
@@ -74,6 +80,36 @@ moo_print_operation_set_property (GObject *object,
moo_print_operation_set_doc (print, g_value_get_object (value));
break;
+ case PROP_BUFFER:
+ moo_print_operation_set_buffer (print, g_value_get_object (value));
+ break;
+
+ case PROP_WRAP:
+ print->wrap = g_value_get_boolean (value) != 0;
+ g_object_notify (object, "wrap");
+ break;
+
+ case PROP_WRAP_MODE:
+ print->wrap_mode = g_value_get_enum (value);
+ g_object_notify (object, "wrap-mode");
+ break;
+
+ case PROP_ELLIPSIZE:
+ print->ellipsize = g_value_get_boolean (value) != 0;
+ g_object_notify (object, "ellipsize");
+ break;
+
+ case PROP_FONT:
+ g_free (print->font);
+ print->font = g_value_dup_string (value);
+ g_object_notify (object, "font");
+ break;
+
+ case PROP_USE_STYLES:
+ print->use_styles = g_value_get_boolean (value);
+ g_object_notify (object, "use-styles");
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -94,6 +130,30 @@ moo_print_operation_get_property (GObject *object,
g_value_set_object (value, print->doc);
break;
+ case PROP_BUFFER:
+ g_value_set_object (value, print->buffer);
+ break;
+
+ case PROP_WRAP:
+ g_value_set_boolean (value, print->wrap);
+ break;
+
+ case PROP_WRAP_MODE:
+ g_value_set_enum (value, print->wrap_mode);
+ break;
+
+ case PROP_ELLIPSIZE:
+ g_value_set_boolean (value, print->ellipsize);
+ break;
+
+ case PROP_FONT:
+ g_value_set_string (value, print->font);
+ break;
+
+ case PROP_USE_STYLES:
+ g_value_set_boolean (value, print->use_styles);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -120,7 +180,56 @@ moo_print_operation_class_init (MooPrintOperationClass *klass)
"doc",
"doc",
GTK_TYPE_TEXT_VIEW,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_BUFFER,
+ g_param_spec_object ("buffer",
+ "buffer",
+ "buffer",
+ GTK_TYPE_TEXT_BUFFER,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_FONT,
+ g_param_spec_string ("font",
+ "font",
+ "font",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_WRAP,
+ g_param_spec_boolean ("wrap",
+ "wrap",
+ "wrap",
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_WRAP_MODE,
+ g_param_spec_enum ("wrap-mode",
+ "wrap-mode",
+ "wrap-mode",
+ PANGO_TYPE_WRAP_MODE,
+ PANGO_WRAP_WORD_CHAR,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_ELLIPSIZE,
+ g_param_spec_boolean ("ellipsize",
+ "ellipsize",
+ "ellipsize",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_USE_STYLES,
+ g_param_spec_boolean ("use-styles",
+ "use-styles",
+ "use-styles",
+ TRUE,
+ G_PARAM_READWRITE));
}
@@ -128,6 +237,7 @@ static void
moo_print_operation_init (MooPrintOperation *print)
{
load_default_settings ();
+
gtk_print_operation_set_print_settings (GTK_PRINT_OPERATION (print),
print_settings);
@@ -136,8 +246,10 @@ moo_print_operation_init (MooPrintOperation *print)
page_setup);
print->last_line = -1;
- print->wrap = FALSE;
- print->ellipsize = TRUE;
+ print->wrap = TRUE;
+ print->wrap_mode = PANGO_WRAP_WORD_CHAR;
+ print->ellipsize = FALSE;
+ print->use_styles = TRUE;
}
@@ -148,6 +260,9 @@ moo_print_operation_set_doc (MooPrintOperation *print,
g_return_if_fail (MOO_IS_PRINT_OPERATION (print));
g_return_if_fail (!doc || GTK_IS_TEXT_VIEW (doc));
+ if (print->doc == doc)
+ return;
+
if (print->doc)
g_object_unref (print->doc);
if (print->buffer)
@@ -165,6 +280,36 @@ moo_print_operation_set_doc (MooPrintOperation *print,
{
print->buffer = NULL;
}
+
+ g_object_freeze_notify (G_OBJECT (print));
+ g_object_notify (G_OBJECT (print), "doc");
+ g_object_notify (G_OBJECT (print), "buffer");
+ g_object_thaw_notify (G_OBJECT (print));
+}
+
+
+void
+moo_print_operation_set_buffer (MooPrintOperation *print,
+ GtkTextBuffer *buffer)
+{
+ g_return_if_fail (MOO_IS_PRINT_OPERATION (print));
+ g_return_if_fail (!buffer || GTK_IS_TEXT_BUFFER (buffer));
+
+ if (print->buffer == buffer)
+ return;
+
+ if (print->doc)
+ g_object_unref (print->doc);
+ if (print->buffer)
+ g_object_unref (print->buffer);
+
+ print->doc = NULL;
+ print->buffer = buffer;
+
+ if (print->buffer)
+ g_object_ref (print->buffer);
+
+ g_object_notify (G_OBJECT (print), "buffer");
}
@@ -221,7 +366,7 @@ moo_print_operation_begin_print (GtkPrintOperation *operation,
GtkTextIter iter, print_end;
GTimer *timer;
- g_return_if_fail (print->doc != NULL);
+ g_return_if_fail (print->buffer != NULL);
g_return_if_fail (print->first_line >= 0);
g_return_if_fail (print->last_line < 0 || print->last_line >= print->first_line);
g_return_if_fail (print->first_line < gtk_text_buffer_get_line_count (print->buffer));
@@ -239,7 +384,7 @@ moo_print_operation_begin_print (GtkPrintOperation *operation,
if (print->font)
font = pango_font_description_from_string (print->font);
- if (!font)
+ if (!font && print->doc)
{
PangoContext *widget_ctx;
@@ -259,7 +404,7 @@ moo_print_operation_begin_print (GtkPrintOperation *operation,
if (print->wrap)
{
pango_layout_set_width (print->layout, print->page.width * PANGO_SCALE);
- pango_layout_set_wrap (print->layout, PANGO_WRAP_CHAR);
+ pango_layout_set_wrap (print->layout, print->wrap_mode);
}
else if (print->ellipsize)
{
@@ -355,6 +500,221 @@ moo_print_operation_begin_print (GtkPrintOperation *operation,
}
+static GSList *
+iter_get_attrs (GtkTextIter *iter,
+ const GtkTextIter *limit)
+{
+ GtkTextIter end;
+ GtkTextAttributes values;
+ gboolean has_attributes = FALSE;
+ GSList *attrs = NULL, *tags;
+ PangoAttribute *bg = NULL, *fg = NULL, *style = NULL, *ul = NULL;
+ PangoAttribute *weight = NULL, *st = NULL;
+
+ tags = gtk_text_iter_get_tags (iter);
+ gtk_text_iter_forward_to_tag_toggle (iter, NULL);
+
+ if (gtk_text_iter_compare (iter, limit) > 0)
+ *iter = *limit;
+
+ while (tags)
+ {
+ GtkTextTag *tag = tags->data;
+ gboolean bg_set, fg_set, style_set, ul_set, weight_set, st_set;
+
+ g_object_get (tag,
+ "background-set", &bg_set,
+ "foreground-set", &fg_set,
+ "style-set", &style_set,
+ "underline-set", &ul_set,
+ "weight-set", &weight_set,
+ "strikethrough-set", &st_set,
+ NULL);
+
+ if (bg_set)
+ {
+ GdkColor *color = NULL;
+ if (bg) pango_attribute_destroy (bg);
+ g_object_get (tag, "background-gdk", &color, NULL);
+ bg = pango_attr_background_new (color->red, color->green, color->blue);
+ gdk_color_free (color);
+ }
+
+ if (fg_set)
+ {
+ GdkColor *color = NULL;
+ if (fg) pango_attribute_destroy (fg);
+ g_object_get (tag, "foreground-gdk", &color, NULL);
+ fg = pango_attr_foreground_new (color->red, color->green, color->blue);
+ gdk_color_free (color);
+ }
+
+ if (style_set)
+ {
+ PangoStyle style_value;
+ if (style) pango_attribute_destroy (style);
+ g_object_get (tag, "style", &style_value, NULL);
+ style = pango_attr_style_new (style_value);
+ }
+
+ if (ul_set)
+ {
+ PangoUnderline underline;
+ if (ul) pango_attribute_destroy (ul);
+ g_object_get (tag, "underline", &underline, NULL);
+ ul = pango_attr_underline_new (underline);
+ }
+
+ if (weight_set)
+ {
+ PangoWeight weight_value;
+ if (weight) pango_attribute_destroy (weight);
+ g_object_get (tag, "weight", &weight_value, NULL);
+ weight = pango_attr_weight_new (weight_value);
+ }
+
+ if (st_set)
+ {
+ gboolean strikethrough;
+ if (st) pango_attribute_destroy (st);
+ g_object_get (tag, "strikethrough", &strikethrough, NULL);
+ st = pango_attr_strikethrough_new (strikethrough);
+ }
+
+ tags = g_slist_delete_link (tags, tags);
+ }
+
+ if (bg)
+ attrs = g_slist_prepend (attrs, bg);
+ if (fg)
+ attrs = g_slist_prepend (attrs, fg);
+ if (style)
+ attrs = g_slist_prepend (attrs, style);
+ if (ul)
+ attrs = g_slist_prepend (attrs, ul);
+ if (weight)
+ attrs = g_slist_prepend (attrs, weight);
+ if (st)
+ attrs = g_slist_prepend (attrs, st);
+
+ return attrs;
+}
+
+
+static void
+fill_layout (PangoLayout *layout,
+ const GtkTextIter *start,
+ const GtkTextIter *end)
+{
+ char *text;
+ PangoAttrList *attr_list;
+ GtkTextIter segm_start, segm_end;
+ int start_index;
+
+ text = gtk_text_iter_get_text (start, end);
+ pango_layout_set_text (layout, text, -1);
+
+ attr_list = NULL;
+ segm_start = *start;
+ start_index = gtk_text_iter_get_line_index (start);
+
+ while (gtk_text_iter_compare (&segm_start, end) < 0)
+ {
+ GSList *attrs;
+
+ segm_end = segm_start;
+ attrs = iter_get_attrs (&segm_end, end);
+
+ if (attrs)
+ {
+ int si, ei;
+
+ si = gtk_text_iter_get_line_index (&segm_start) - start_index;
+ ei = gtk_text_iter_get_line_index (&segm_end) - start_index;
+
+ while (attrs)
+ {
+ PangoAttribute *a = attrs->data;
+
+ a->start_index = si;
+ a->end_index = ei;
+
+ if (!attr_list)
+ attr_list = pango_attr_list_new ();
+
+ pango_attr_list_insert (attr_list, a);
+
+ attrs = g_slist_delete_link (attrs, attrs);
+ }
+ }
+
+ segm_start = segm_end;
+ }
+
+ pango_layout_set_attributes (layout, attr_list);
+
+ if (attr_list)
+ pango_attr_list_unref (attr_list);
+}
+
+
+static void
+print_page (MooPrintOperation *print,
+ const GtkTextIter *start,
+ const GtkTextIter *end,
+ cairo_t *cr)
+{
+ char *text;
+ GtkTextIter line_start, line_end;
+ double offset;
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+
+ if (!print->use_styles)
+ {
+ text = gtk_text_buffer_get_text (print->buffer, start, end, FALSE);
+ pango_layout_set_text (print->layout, text, -1);
+ g_free (text);
+
+ cairo_move_to (cr, print->page.x, print->page.y);
+ pango_cairo_show_layout (cr, print->layout);
+
+ return;
+ }
+
+ line_start = *start;
+ offset = 0;
+
+ while (gtk_text_iter_compare (&line_start, end) < 0)
+ {
+ PangoRectangle line_rect;
+
+ if (gtk_text_iter_ends_line (&line_start))
+ {
+ pango_layout_set_text (print->layout, "", 0);
+ pango_layout_set_attributes (print->layout, NULL);
+ }
+ else
+ {
+ line_end = line_start;
+ gtk_text_iter_forward_to_line_end (&line_end);
+
+ if (gtk_text_iter_compare (&line_end, end) > 0)
+ line_end = *end;
+
+ fill_layout (print->layout,&line_start, &line_end);
+ }
+
+ cairo_move_to (cr, 0, offset);
+ pango_cairo_show_layout (cr, print->layout);
+
+ pango_layout_get_pixel_extents (print->layout, NULL, &line_rect);
+ offset += line_rect.height;
+ gtk_text_iter_forward_line (&line_start);
+ }
+}
+
+
static void
moo_print_operation_draw_page (GtkPrintOperation *operation,
GtkPrintContext *context,
@@ -366,7 +726,7 @@ moo_print_operation_draw_page (GtkPrintOperation *operation,
MooPrintOperation *print = MOO_PRINT_OPERATION (operation);
GTimer *timer;
- g_return_if_fail (print->doc != NULL);
+ g_return_if_fail (print->buffer != NULL);
g_return_if_fail (print->pages != NULL);
g_return_if_fail (print->layout != NULL);
g_return_if_fail (page_nr < print->pages->len);
@@ -374,7 +734,6 @@ moo_print_operation_draw_page (GtkPrintOperation *operation,
timer = g_timer_new ();
cr = gtk_print_context_get_cairo (context);
- cairo_set_source_rgb (cr, 0, 0, 0);
start = g_array_index (print->pages, GtkTextIter, page_nr);
@@ -383,12 +742,7 @@ moo_print_operation_draw_page (GtkPrintOperation *operation,
else
gtk_text_buffer_get_end_iter (print->buffer, &end);
- text = gtk_text_buffer_get_text (print->buffer, &start, &end, FALSE);
- pango_layout_set_text (print->layout, text, -1);
- g_free (text);
-
- cairo_move_to (cr, print->page.x, print->page.y);
- pango_cairo_show_layout (cr, print->layout);
+ print_page (print, &start, &end, cr);
g_message ("page %d: %f s", page_nr, g_timer_elapsed (timer, NULL));
g_timer_destroy (timer);
@@ -401,7 +755,7 @@ moo_print_operation_end_print (GtkPrintOperation *operation,
{
MooPrintOperation *print = MOO_PRINT_OPERATION (operation);
- g_return_if_fail (print->doc != NULL);
+ g_return_if_fail (print->buffer != NULL);
g_object_unref (print->layout);
g_array_free (print->pages, TRUE);
@@ -425,17 +779,11 @@ moo_edit_print (GtkTextView *view,
print = g_object_new (MOO_TYPE_PRINT_OPERATION, "doc", view, NULL);
- {
- GtkTextIter start, end;
- GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
- gtk_text_buffer_get_bounds (buffer, &start, &end);
- g_assert (strlen (gtk_text_buffer_get_text (buffer, &start, &end, FALSE)) > 0);
- g_assert (MOO_PRINT_OPERATION(print)->last_line < 0);
- }
-
if (!parent)
parent = GTK_WIDGET (view);
+
parent = gtk_widget_get_toplevel (parent);
+
if (GTK_WIDGET_TOPLEVEL (parent))
parent_window = GTK_WINDOW (parent);
diff --git a/moo/mooedit/mootextprint.h b/moo/mooedit/mootextprint.h
index 8a701ec8..123e3037 100644
--- a/moo/mooedit/mootextprint.h
+++ b/moo/mooedit/mootextprint.h
@@ -41,7 +41,9 @@ struct _MooPrintOperation
int last_line; /* -1 to print everything after first_line */
char *font; /* overrides font set in the doc */
gboolean wrap;
+ PangoWrapMode wrap_mode;
gboolean ellipsize;
+ gboolean use_styles;
/* aux stuff */
GArray *pages; /* GtkTextIter's pointing to pages start */
@@ -65,6 +67,8 @@ GType moo_print_operation_get_type (void) G_GNUC_CONST;
void moo_print_operation_set_doc (MooPrintOperation *print,
GtkTextView *doc);
+void moo_print_operation_set_buffer (MooPrintOperation *print,
+ GtkTextBuffer *buffer);
void moo_edit_page_setup (GtkTextView *view,
GtkWidget *parent);