2008-10-09 [colin] 3.6.0cvs18
[claws.git] / src / gtk / gtksourceprintjob.c
index 87cafad9725b9d06bc05dd354fe68863e1d205fb..e36ef728d3b34ecc8a22edf2ebf76475b68a93d4 100644 (file)
@@ -12,7 +12,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -21,9 +21,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, 
- * Boston, MA 02111-1307, USA. 
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
  
 #ifdef HAVE_CONFIG_H
 #include <time.h>
 
 #include "gtksourceprintjob.h"
+#include "image_viewer.h"
 
 #include <glib/gi18n.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtktextview.h>
+#include <gtk/gtk.h>
 #include <libgnomeprint/gnome-print-pango.h>
 
 #ifdef ENABLE_PROFILE
@@ -79,6 +77,7 @@ struct _TextSegment
        TextSegment             *next;
        TextStyle               *style;
        gchar                   *text;
+       GdkPixbuf               *image;
 };
 
 /* a printable line */
@@ -982,8 +981,6 @@ text_style_new (GtkSourcePrintJob *job, GtkTextTag *tag)
 {
        TextStyle *style;
        gboolean bg_set, fg_set;
-       gdouble scale;
-       PangoFontDescription *font_desc;
        
        g_return_val_if_fail (tag != NULL && GTK_IS_TEXT_TAG (tag), NULL);
 
@@ -1118,6 +1115,7 @@ get_text_with_style (GtkSourcePrintJob *job,
 {
        GtkTextIter limit, next_toggle;
        gboolean have_toggle;
+       GdkPixbuf *image = NULL;
        
        /* make sure the region to print is highlighted */
        /*_gtk_source_buffer_highlight_region (job->priv->buffer, start, end, TRUE); */
@@ -1160,11 +1158,13 @@ get_text_with_style (GtkSourcePrintJob *job,
                        if (style != seg->style)
                        {
                                TextSegment *new_seg;
-                               
                                /* style has changed, thus we need to
                                 * create a new segment */
                                /* close the current segment */
                                seg->text = gtk_text_iter_get_slice (start, &next_toggle);
+                               if ((image = gtk_text_iter_get_pixbuf(start)) != NULL)
+                                       seg->image = image;
+                               
                                *start = next_toggle;
                                
                                new_seg = g_new0 (TextSegment, 1);
@@ -1179,6 +1179,8 @@ get_text_with_style (GtkSourcePrintJob *job,
                /* close the line */
                seg->next = NULL;
                seg->text = gtk_text_iter_get_slice (start, &limit);
+               if ((image = gtk_text_iter_get_pixbuf(start)) != NULL)
+                       seg->image = image;
 
                /* add the line of text to the job */
                job->priv->paragraphs = g_slist_prepend (job->priv->paragraphs, para);
@@ -1268,16 +1270,17 @@ add_attribute_to_list (PangoAttribute *attr,
        pango_attr_list_insert (list, attr);
 }
 
-static PangoLayout *
+static void *
 create_layout_for_para (GtkSourcePrintJob *job,
-                       Paragraph         *para)
+                       Paragraph         *para,
+                       gboolean          *is_image)
 {
        GString *text;
        PangoLayout *layout;
        PangoAttrList *attrs;
        TextSegment *seg;
        gint index;
-
+       GdkPixbuf *image = NULL;
        text = g_string_new (NULL);
        attrs = pango_attr_list_new ();
        
@@ -1331,14 +1334,22 @@ create_layout_for_para (GtkSourcePrintJob *job,
                        }
                }
 
+               if (seg->image) {
+                       image = seg->image;
+               }
+
                index += seg_len;
                seg = seg->next;
        }
 
+       if (image != NULL) {
+               *is_image = TRUE;
+               return image;
+       }
+
        layout = pango_layout_new (job->priv->pango_context);
        
-/*     if (job->priv->wrap_mode != GTK_WRAP_NONE)*/
-               pango_layout_set_width (layout, job->priv->text_width * PANGO_SCALE);
+       pango_layout_set_width (layout, job->priv->text_width * PANGO_SCALE);
        
        switch (job->priv->wrap_mode)   {
        case GTK_WRAP_CHAR:
@@ -1373,6 +1384,7 @@ create_layout_for_para (GtkSourcePrintJob *job,
        
        pango_layout_set_text (layout, text->str, text->len);
        pango_layout_set_attributes (layout, attrs);
+       *is_image = FALSE;
 
        /* FIXME: <horrible-hack> 
         * For empty paragraphs, pango_layout_iter_get_baseline() returns 0,
@@ -1412,34 +1424,61 @@ paginate_paragraph (GtkSourcePrintJob *job,
        PangoRectangle logical_rect;
        gdouble max;
        gdouble page_skip;
+       GdkPixbuf *image;
+       void *tmp;
+       gboolean is_image = FALSE;
+       
+       tmp = create_layout_for_para (job, para, &is_image);
+       if (!is_image) {
+               layout = (PangoLayout *)tmp;
+               image  = NULL;
+       } else {
+               image  = (GdkPixbuf *)tmp;
+               layout = NULL;
+       }
 
-       layout = create_layout_for_para (job, para);
-
-       iter = pango_layout_get_iter (layout);
+       if (image == NULL) {
+               iter = pango_layout_get_iter (layout);
 
-       max = 0;
-       page_skip = 0;
+               max = 0;
+               page_skip = 0;
 
-       do
-       {
-               pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
-               max = (gdouble) (logical_rect.y + logical_rect.height) / PANGO_SCALE;
-               
-               if (max - page_skip > job->priv->available_height)
+               do
                {
-                       /* "create" a new page */
+                       pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+                       max = (gdouble) (logical_rect.y + logical_rect.height) / PANGO_SCALE;
+
+                       if (max - page_skip > job->priv->available_height)
+                       {
+                               /* "create" a new page */
+                               job->priv->page_count++;
+                               job->priv->available_height = job->priv->text_height;
+                               page_skip = (gdouble) logical_rect.y / PANGO_SCALE;
+                       }
+
+               }
+               while (pango_layout_iter_next_line (iter));
+               job->priv->available_height -= max - page_skip;
+               pango_layout_iter_free (iter);
+               g_object_unref (layout);
+       } else {
+               gint max_height = job->priv->available_height;
+               gint image_height = gdk_pixbuf_get_height(image);
+               gint image_width = gdk_pixbuf_get_width(image);
+               gint scaled_height = 0, scaled_width = 0;
+               image_viewer_get_resized_size(image_width,
+                                        image_height,
+                                        job->priv->text_width, 
+                                        job->priv->text_height,
+                                        &scaled_width, &scaled_height);
+               if (scaled_height > max_height) {
                        job->priv->page_count++;
-                       job->priv->available_height = job->priv->text_height;
-                       page_skip = (gdouble) logical_rect.y / PANGO_SCALE;
+                       job->priv->available_height = job->priv->text_height - scaled_height;
+               } else {
+                       job->priv->available_height -= scaled_height;
                }
-
        }
-       while (pango_layout_iter_next_line (iter));
 
-       job->priv->available_height -= max - page_skip;
-       
-       pango_layout_iter_free (iter);
-       g_object_unref (layout);
 }
 
 static gboolean 
@@ -1530,53 +1569,113 @@ print_paragraph (GtkSourcePrintJob *job,
        gdouble page_skip;
        gdouble baseline;
        int result = -1;
-       
-       layout = create_layout_for_para (job, para);
+       GdkPixbuf *image;
+       void *tmp;
+       gboolean is_image;
+
+       tmp = create_layout_for_para (job, para, &is_image);
+       if (!is_image) {
+               layout = (PangoLayout *)tmp;
+               image  = NULL;
+       } else {
+               image  = (GdkPixbuf *)tmp;
+               layout = NULL;
+       }
 
-       iter = pango_layout_get_iter (layout);
+       if (!is_image) {
+               iter = pango_layout_get_iter (layout);
 
-       /* Skip over lines already printed on previous page(s) */
-       for (current_line = 0; current_line < start_line; current_line++)
-               pango_layout_iter_next_line (iter);
+               /* Skip over lines already printed on previous page(s) */
+               for (current_line = 0; current_line < start_line; current_line++)
+                       pango_layout_iter_next_line (iter);
 
-       max = 0;
-       page_skip = 0;
-       
-       do
-       {
-               pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
-               max = (gdouble) (logical_rect.y + logical_rect.height) / PANGO_SCALE;
-               
-               if (current_line == start_line)
-                       page_skip = (gdouble) logical_rect.y / PANGO_SCALE;
+               max = 0;
+               page_skip = 0;
 
-               if (max - page_skip > job->priv->available_height)
+               do
                {
-                       result = current_line; /* Save position for next page */
-                       break;
-               }
+                       pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+                       max = (gdouble) (logical_rect.y + logical_rect.height) / PANGO_SCALE;
 
-               baseline = (gdouble) pango_layout_iter_get_baseline (iter) / PANGO_SCALE;
-               baseline = *y + page_skip - baseline; /* Adjust to global coordinates */
-               if (current_line == 0)
-                       *baseline_out = baseline;
-               
-               gnome_print_moveto (job->priv->print_ctxt,
-                                   x + (gdouble) logical_rect.x / PANGO_SCALE,
-                                   baseline);
-               gnome_print_pango_layout_line (job->priv->print_ctxt,
-                                              pango_layout_iter_get_line (iter));
+                       if (current_line == start_line)
+                               page_skip = (gdouble) logical_rect.y / PANGO_SCALE;
 
-               current_line++;
-       }
-       while (pango_layout_iter_next_line (iter));
+                       if (max - page_skip > job->priv->available_height)
+                       {
+                               result = current_line; /* Save position for next page */
+                               break;
+                       }
 
-       job->priv->available_height -= max - page_skip;
-       *y -= max - page_skip;
+                       baseline = (gdouble) pango_layout_iter_get_baseline (iter) / PANGO_SCALE;
+                       baseline = *y + page_skip - baseline; /* Adjust to global coordinates */
+                       if (current_line == 0)
+                               *baseline_out = baseline;
 
-       pango_layout_iter_free (iter);
-       g_object_unref (layout);
-       
+                       gnome_print_moveto (job->priv->print_ctxt,
+                                           x + (gdouble) logical_rect.x / PANGO_SCALE,
+                                           baseline);
+                       gnome_print_pango_layout_line (job->priv->print_ctxt,
+                                                      pango_layout_iter_get_line (iter));
+
+                       current_line++;
+               }
+               while (pango_layout_iter_next_line (iter));
+
+               job->priv->available_height -= max - page_skip;
+               *y -= max - page_skip;
+
+               pango_layout_iter_free (iter);
+               g_object_unref (layout);
+       } else {
+               gint max_height = job->priv->available_height;
+               gint image_height = gdk_pixbuf_get_height(image);
+               gint image_width = gdk_pixbuf_get_width(image);
+               gint scaled_height = 0, scaled_width = 0;
+               GdkPixbuf *scaled_image = NULL;
+               image_viewer_get_resized_size(image_width,
+                                        image_height,
+                                        job->priv->text_width, 
+                                        job->priv->text_height,
+                                        &scaled_width, &scaled_height);
+
+               if (scaled_height > max_height) {
+                       /* next page */
+                       return 0;
+               } else {
+                       scaled_image = gdk_pixbuf_scale_simple
+                                       (image, scaled_width, scaled_height, 
+                                        GDK_INTERP_BILINEAR);
+
+                       gnome_print_moveto(job->priv->print_ctxt,
+                                           x, (gdouble)*y);
+                       gnome_print_gsave(job->priv->print_ctxt);
+                       gnome_print_translate(job->priv->print_ctxt, 
+                                             x, *y - scaled_height);
+                       gnome_print_scale(job->priv->print_ctxt, 
+                                         scaled_width,
+                                         scaled_height);
+
+                       if (gdk_pixbuf_get_has_alpha(image))
+                               gnome_print_rgbaimage  (job->priv->print_ctxt,
+                                                       gdk_pixbuf_get_pixels    (scaled_image),
+                                                       gdk_pixbuf_get_width     (scaled_image),
+                                                       gdk_pixbuf_get_height    (scaled_image),
+                                                       gdk_pixbuf_get_rowstride (scaled_image));
+                       else
+                               gnome_print_rgbimage  (job->priv->print_ctxt,
+                                                      gdk_pixbuf_get_pixels    (scaled_image),
+                                                      gdk_pixbuf_get_width     (scaled_image),
+                                                      gdk_pixbuf_get_height    (scaled_image),
+                                                      gdk_pixbuf_get_rowstride (scaled_image));
+                       g_object_unref(scaled_image);
+                       gnome_print_grestore(job->priv->print_ctxt);
+
+                       job->priv->available_height -= scaled_height;
+                       *y -= scaled_height;
+                       return -1;
+
+               }
+       }
        return result;
 }
 
@@ -1605,7 +1704,7 @@ print_page (GtkSourcePrintJob *job)
        while (l != NULL)
        {
                Paragraph *para = l->data;
-               gdouble baseline;
+               gdouble baseline = 0;
                gint last_line = line;
                
                line = print_paragraph (job, para, line, x, &y, &baseline, force_fit);
@@ -2715,10 +2814,11 @@ evaluate_format_string (GtkSourcePrintJob *job, const gchar *format)
        const struct tm *tm;
        time_t now;
        gunichar ch;
-       
+       struct tm lt;
+
        /* get time */
        time (&now);
-       tm = localtime (&now);
+       tm = localtime_r(&now, &lt);
 
        /* analyze format string and replace the codes we know */
        eval = g_string_new_len (NULL, strlen (format));