[gnote] Fix print formatting issues. (Tomboy bug #572024) (tb-backport)



commit bfbd7507957fbe87dfa1691dd83d6ee01927c7f3
Author: Hubert Figuiere <hub figuiere net>
Date:   Thu Jul 16 21:23:28 2009 -0400

    Fix print formatting issues. (Tomboy bug #572024) (tb-backport)

 src/addins/printnotes/printnotesnoteaddin.cpp |  253 +++++++++++++------------
 src/addins/printnotes/printnotesnoteaddin.hpp |   51 +++--
 2 files changed, 157 insertions(+), 147 deletions(-)
---
diff --git a/src/addins/printnotes/printnotesnoteaddin.cpp b/src/addins/printnotes/printnotesnoteaddin.cpp
index bf905ab..67bcc79 100644
--- a/src/addins/printnotes/printnotesnoteaddin.cpp
+++ b/src/addins/printnotes/printnotesnoteaddin.cpp
@@ -60,7 +60,7 @@ namespace printnotes {
   }
   const char * PrintNotesModule::version() const
   {
-    return "0.3";
+    return "0.4";
   }
 
   void PrintNotesNoteAddin::initialize()
@@ -140,11 +140,14 @@ namespace printnotes {
 
   void PrintNotesNoteAddin::get_paragraph_attributes(const Glib::RefPtr<Pango::Layout> & layout,
                                                      double dpiX, 
-                                                     PrintMargins & margins,
+                                                     int & indentation,
                                                      Gtk::TextIter & position, 
-                                                     Gtk::TextIter & limit,
+                                                     const Gtk::TextIter & limit,
                                                      std::list<Pango::Attribute> & attributes)
   {
+    attributes.clear();
+    indentation = 0;
+
     Glib::SListHandle<Glib::RefPtr<Gtk::TextTag> > tags = position.get_tags();
     position.forward_to_tag_toggle(Glib::RefPtr<Gtk::TextTag>(NULL));
     if (position.compare (limit) > 0) {
@@ -175,10 +178,10 @@ namespace printnotes {
         layout->set_indent(tag->property_indent());
       }
       if (tag->property_left_margin_set()) {                                        
-        margins.left = (int)(tag->property_left_margin() / screen_dpiX * dpiX);
+        indentation = (int)(tag->property_left_margin() / screen_dpiX * dpiX);
       }
       if (tag->property_right_margin_set()) {
-        margins.right = (int)(tag->property_right_margin() / screen_dpiX * dpiX);
+        indentation = (int)(tag->property_right_margin() / screen_dpiX * dpiX);
       }
 //      if (tag->property_font_desc()) {
       attributes.push_back(
@@ -231,13 +234,14 @@ namespace printnotes {
   PrintNotesNoteAddin::create_layout_for_paragraph(const Glib::RefPtr<Gtk::PrintContext> & context, 
                                                    Gtk::TextIter p_start,
                                                    Gtk::TextIter p_end,
-                                                   PrintMargins & margins)
+                                                   int & indentation)
   {
     Glib::RefPtr<Pango::Layout> layout = context->create_pango_layout();
 
     layout->set_font_description(
       get_window()->editor()->get_style()->get_font());
     int start_index = p_start.get_line_index();
+    indentation = 0;
 
     {
       Pango::AttrList attr_list;
@@ -250,7 +254,7 @@ namespace printnotes {
       while (segm_start.compare (p_end) < 0) {
         segm_end = segm_start;
         std::list<Pango::Attribute> attrs;
-        get_paragraph_attributes (layout, dpiX, margins,
+        get_paragraph_attributes (layout, dpiX, indentation,
                                   segm_end, p_end, attrs);
 
         guint si = (guint) (segm_start.get_line_index() - start_index);
@@ -271,8 +275,8 @@ namespace printnotes {
     }
 
     layout->set_width(pango_units_from_double((int)context->get_width() -
-                                            margins.horizontal_margins() -
-                                            m_page_margins.horizontal_margins()));
+                                              m_margin_left - m_margin_right - indentation));
+    layout->set_wrap (Pango::WRAP_WORD_CHAR);
     layout->set_text (get_buffer()->get_slice (p_start, p_end, false));
     return layout;
   }
@@ -302,6 +306,8 @@ namespace printnotes {
   Glib::RefPtr<Pango::Layout> 
   PrintNotesNoteAddin::create_layout_for_timestamp(const Glib::RefPtr<Gtk::PrintContext> & context)
   {
+    std::string timestamp = sharp::DateTime::now().to_string ("%c");
+
     Glib::RefPtr<Pango::Layout> layout = context->create_pango_layout ();
     Pango::FontDescription font_desc = get_window()->editor()->get_style()->get_font();
     font_desc.set_style(Pango::STYLE_NORMAL);
@@ -310,40 +316,36 @@ namespace printnotes {
     layout->set_width(pango_units_from_double((int) context->get_width()));
 
     layout->set_alignment(Pango::ALIGN_RIGHT);
-    layout->set_text (m_timestamp);
+    layout->set_text (timestamp);
 
     return layout;
   }
 
+  int PrintNotesNoteAddin::compute_footer_height(const Glib::RefPtr<Gtk::PrintContext> & context)
+  {
+    Glib::RefPtr<Pango::Layout> layout = create_layout_for_timestamp(context);
+    Pango::Rectangle ink_rect;
+    Pango::Rectangle logical_rect;
+    layout->get_extents(ink_rect, logical_rect);
+    return pango_units_to_double(ink_rect.get_height()) 
+      + cm_to_pixel(0.5, context->get_dpi_y());
+  }
+
 
   void PrintNotesNoteAddin::on_begin_print(const Glib::RefPtr<Gtk::PrintContext>& context)
   {
+    m_timestamp_footer = create_layout_for_timestamp(context);
     // Create and initialize the page margins
-    m_page_margins.top = cm_to_pixel (1.5, context->get_dpi_y());
-    m_page_margins.left = cm_to_pixel (1, context->get_dpi_x());
-    m_page_margins.right = cm_to_pixel (1, context->get_dpi_x());
-    m_page_margins.bottom = 0;
-
-    DBG_OUT("margins = %d %d %d %d", m_page_margins.top, m_page_margins.left,
-            m_page_margins.right, m_page_margins.bottom);
-			
-    // Compute the footer height to define the bottom margin 
-    m_timestamp = sharp::DateTime::now().to_string ("%c");
-    Glib::RefPtr<Pango::Layout> date_time_footer;
-    date_time_footer = create_layout_for_timestamp (context);
-    Pango::Rectangle footer_ink_rect;
-    Pango::Rectangle footer_logical_rect;
-    date_time_footer->get_extents (footer_ink_rect, footer_logical_rect);
-			
-    m_footer_offset = cm_to_pixel (0.5, context->get_dpi_y());
-			
-    /* Set the bottom margin to the height of the footer + a constant 
-     * offset for the separation line */  
-    m_page_margins.bottom += pango_units_to_double(footer_logical_rect.get_height()) + m_footer_offset;
-
-    double height = pango_units_from_double ((int) context->get_height() 
-                                          - m_page_margins.vertical_margins ());
-    double page_height = 0;
+    m_margin_top = cm_to_pixel (1.5, context->get_dpi_y());
+    m_margin_left = cm_to_pixel (1, context->get_dpi_x());
+    m_margin_right = cm_to_pixel (1, context->get_dpi_x());
+    m_margin_bottom = 0;
+    double max_height = pango_units_from_double(context->get_height()
+                                                - m_margin_top - m_margin_bottom
+                                                - compute_footer_height(context));
+
+    DBG_OUT("margins = %d %d %d %d", m_margin_top, m_margin_left,
+            m_margin_right, m_margin_bottom);
 
     m_page_breaks.clear();
 
@@ -351,32 +353,35 @@ namespace printnotes {
     Gtk::TextIter end_iter;
     get_buffer()->get_bounds (position, end_iter);
 
+    double page_height = 0;
     bool done = position.compare (end_iter) >= 0;
     while (!done) {
-      int line_number = position.get_line();
-
       Gtk::TextIter line_end = position;
       if (!line_end.ends_line ()) {
         line_end.forward_to_line_end ();
       }
 
-      PrintMargins margins;
-
+      int paragraph_number = position.get_line();
+      int indentation = 0;
       Glib::RefPtr<Pango::Layout> layout = create_layout_for_paragraph(
-        context, position, line_end, margins);
+        context, position, line_end, indentation);
 
       Pango::Rectangle ink_rect;
       Pango::Rectangle logical_rect;
-      layout->get_extents (ink_rect, logical_rect);
-
-      if ((page_height + logical_rect.get_height()) > height) {
-        m_page_breaks.push_back (line_number);
-        page_height = 0;
-      }
-
-      page_height += logical_rect.get_height();
+      for(int line_in_paragraph = 0;  line_in_paragraph < layout->get_line_count();
+          line_in_paragraph++) {
+        Glib::RefPtr<Pango::LayoutLine> line = layout->get_line(line_in_paragraph);
+        line->get_extents (ink_rect, logical_rect);
+
+        if ((page_height + logical_rect.get_height()) >= max_height) {
+          PageBreak(paragraph_number, line_in_paragraph);
+          m_page_breaks.push_back (PageBreak(paragraph_number, line_in_paragraph));
+          page_height = 0;
+        }
 
+        page_height += logical_rect.get_height();
 
+      }
       position.forward_line ();
       done = position.compare (end_iter) >= 0;
     }
@@ -385,106 +390,65 @@ namespace printnotes {
   }
 
 
-  void PrintNotesNoteAddin::print_footer(const Glib::RefPtr<Gtk::PrintContext> & context,
-                                         guint page_nr)
-  {
-    int total_height = pango_units_from_double ((int)context->get_height());
-    int total_width = pango_units_from_double ((int)context->get_width());
-
-    Cairo::RefPtr<Cairo::Context> cr = context->get_cairo_context();
-    cr->move_to(cm_to_pixel(0.5, context->get_dpi_x()), 
-                pango_units_to_double(total_height)
-                - m_page_margins.bottom + m_footer_offset);
-    cr->line_to(pango_units_to_double(total_width)
-                - cm_to_pixel(0.5, context->get_dpi_x()), 
-                pango_units_to_double(total_height) - m_page_margins.bottom 
-                + m_footer_offset);
-    cr->stroke ();
-
-    Glib::RefPtr<Pango::Layout> date_time_footer = create_layout_for_timestamp (context);
-
-    DBG_ASSERT(date_time_footer, "layout is NULL");
-
-    Pango::Rectangle ink_rect;
-    Pango::Rectangle logical_rect;
-    date_time_footer->get_extents (ink_rect, logical_rect);
-				
-    double x,y;
-    x = cm_to_pixel(0.5, context->get_dpi_x());
-    y = pango_units_to_double (total_height) - m_page_margins.bottom  
-      + m_footer_offset + pango_units_to_double(logical_rect.get_height());
-
-    cr->move_to(pango_units_to_double(total_width 
-                                        - logical_rect.get_width())
-                - cm_to_pixel (0.5, context->get_dpi_x()), y);
-      
-    pango_cairo_show_layout_line(cr->cobj(), 
-                                 (*date_time_footer->get_lines().begin())->gobj());
-				
-    cr->move_to(x, y);
-
-    Glib::RefPtr<Pango::Layout> pages_footer 
-      = create_layout_for_pagenumbers (context, page_nr + 1, 
-                                       m_page_breaks.size() + 1);
-    pango_cairo_show_layout_line(cr->cobj(), 
-                                 (*pages_footer->get_lines().begin())->gobj()); 
-  }
-
-
-
 
   void PrintNotesNoteAddin::on_draw_page(const Glib::RefPtr<Gtk::PrintContext>& context, guint page_nr)
   {
     Cairo::RefPtr<Cairo::Context> cr = context->get_cairo_context();
-    cr->move_to (m_page_margins.left, m_page_margins.top);
+    cr->move_to (m_margin_left, m_margin_top);
 
-    int start_line = 0;
+    PageBreak start;
     if (page_nr != 0) {
-      start_line = m_page_breaks [page_nr - 1];
+      start = m_page_breaks [page_nr - 1];
     }
 
-    int last_line = -1;
+    PageBreak end(-1, -1);
     if (m_page_breaks.size() > page_nr) {
-      last_line = m_page_breaks [page_nr] - 1;
+      end = m_page_breaks [page_nr];
     }
 
     Gtk::TextIter position;
     Gtk::TextIter end_iter;
     get_buffer()->get_bounds (position, end_iter);
 
-    bool done = position.compare (end_iter) >= 0;
-    int line_number = position.get_line();
-
     // Fast-forward to the starting line
-    while (!done && line_number < start_line) {
-      Gtk::TextIter line_end = position;
-      if (!line_end.ends_line ()) {
-        line_end.forward_to_line_end ();
-      }
-
+    while (position.get_line() < start.get_paragraph()) {
       position.forward_line ();
-      done = position.compare (end_iter) >= 0;
-      line_number = position.get_line();
     }
 
-    // Print the current page's content
-    while (!done && ((last_line == -1) || (line_number < last_line))) {
-      line_number = position.get_line();
-
+    bool done = position.compare (end_iter) >= 0;
+    while (!done) {
       Gtk::TextIter line_end = position;
       if (!line_end.ends_line ()) {
         line_end.forward_to_line_end ();
       }
 
-      PrintMargins margins;
+
+      int paragraph_number = position.get_line();
+      int indentation;
+
       {
         Glib::RefPtr<Pango::Layout> layout =
-          create_layout_for_paragraph (context,position, line_end, margins);
-        Pango::SListHandle_LayoutLine lines(layout->get_lines());
-        for(Pango::SListHandle_LayoutLine::const_iterator iter = lines.begin();
-            iter != lines.end(); ++iter) {
-
-          Glib::RefPtr<Pango::LayoutLine> line = *iter;
+          create_layout_for_paragraph (context,position, line_end, indentation);
+
+        for(int line_number = 0;
+            line_number < layout->get_line_count() && !done;
+            line_number++) {
+          // Skip the lines up to the starting line in the
+          // first paragraph on this page
+          if ((paragraph_number == start.get_paragraph()) &&
+              (line_number < start.get_line())) {
+            continue;
+          }
+          // Break as soon as we hit the end line
+          if ((paragraph_number == end.get_paragraph()) &&
+              (line_number == end.get_line())) {
+            done = true;
+            break;
+          }
+
+
+
+          Glib::RefPtr<Pango::LayoutLine> line = layout->get_line(line_number);
           
           Pango::Rectangle ink_rect;
           Pango::Rectangle logical_rect;
@@ -492,10 +456,11 @@ namespace printnotes {
 
           double curX, curY;
           cr->get_current_point(curX, curY);
-          cr->move_to (margins.left + m_page_margins.left, curY);
+          cr->move_to (m_margin_left + indentation, curY);
           int line_height = pango_units_to_double(logical_rect.get_height());
+
           double x, y;
-          x = margins.left + m_page_margins.left;
+          x = m_margin_left + indentation;
           cr->get_current_point(curX, curY);
           y = curY + line_height;
           pango_cairo_show_layout_line(cr->cobj(), line->gobj());
@@ -504,17 +469,53 @@ namespace printnotes {
       }
 
       position.forward_line ();
-      done = position.compare (end_iter) >= 0;
+      done = done || (position.compare (end_iter) >= 0);
     }
 
     // Print the footer
-    print_footer (context, page_nr);
+    int total_height = context->get_height();
+    int total_width = context->get_width();
+    int footer_height = 0;
+
+    double footer_anchor_x, footer_anchor_y;
+
+    {
+      Glib::RefPtr<Pango::Layout> pages_footer 
+        = create_layout_for_pagenumbers (context, page_nr + 1, 
+                                         m_page_breaks.size() + 1);
+
+      Pango::Rectangle ink_footer_rect;
+      Pango::Rectangle logical_footer_rect;
+      pages_footer->get_extents(ink_footer_rect, logical_footer_rect);
+      
+      footer_anchor_x = cm_to_pixel(0.5, context->get_dpi_x());
+      footer_anchor_y = total_height - m_margin_bottom;
+      footer_height = pango_units_to_double(logical_footer_rect.get_height());
+      
+      cr->move_to(total_width - pango_units_to_double(logical_footer_rect.get_width()) - cm_to_pixel(0.5, context->get_dpi_x()), footer_anchor_y);
+                                                      
+      pango_cairo_show_layout_line(cr->cobj(), 
+                                   (pages_footer->get_line(0))->gobj());
+
+    }
+
+    cr->move_to(footer_anchor_x, footer_anchor_y);
+    pango_cairo_show_layout_line(cr->cobj(), 
+                                 (m_timestamp_footer->get_line(0))->gobj());
+
+    cr->move_to(cm_to_pixel(0.5, context->get_dpi_x()), 
+                total_height - m_margin_bottom - footer_height);
+    cr->line_to(total_width - cm_to_pixel(0.5, context->get_dpi_x()),
+                total_height - m_margin_bottom - footer_height);
+    cr->stroke();
   }
 
 
   void PrintNotesNoteAddin::on_end_print(const Glib::RefPtr<Gtk::PrintContext>&)
   {
     m_page_breaks.clear ();
+    // clear the RefPtr<>
+    m_timestamp_footer.clear();
   }
 
 }
diff --git a/src/addins/printnotes/printnotesnoteaddin.hpp b/src/addins/printnotes/printnotesnoteaddin.hpp
index e329d04..25a8072 100644
--- a/src/addins/printnotes/printnotesnoteaddin.hpp
+++ b/src/addins/printnotes/printnotesnoteaddin.hpp
@@ -52,31 +52,33 @@ public:
 
 DECLARE_MODULE(PrintNotesModule);
 
-struct PrintMargins
+class PageBreak
 {
-  int top;
-  int left;
-  int right;
-  int bottom;
-
-  PrintMargins()
-    : top(0), left(0), right(0), bottom(0)
+public:
+  PageBreak(int paragraph, int line)
+    : m_break_paragraph(paragraph)
+    , m_break_line(line)
     {
     }
-  void clear()
+  PageBreak()
+    : m_break_paragraph(0)
+    , m_break_line(0)
     {
-      top = left = right = bottom = 0;
     }
-  int vertical_margins()
+  int get_paragraph() const
     {
-      return top + bottom;
+      return m_break_paragraph;
     }
-  int horizontal_margins()
+  int get_line() const
     {
-      return left + right;
+      return m_break_line;
     }
+private:
+  int m_break_paragraph;
+  int m_break_line;
 };
 
+
 class PrintNotesNoteAddin
   : public gnote::NoteAddin
 {
@@ -93,19 +95,24 @@ public:
 		{
 			return (int) (cm * dpi / 2.54);
 		}
+  static int inch_to_pixel(double inch, double dpi)
+		{
+			return (int) (inch * dpi);
+		}
 
 private:
   void get_paragraph_attributes(const Glib::RefPtr<Pango::Layout> & layout,
-                                double dpiX, PrintMargins & margins,
+                                double dpiX, int & indentation,
                                 Gtk::TextIter & position, 
-                                Gtk::TextIter & limit,
+                                const Gtk::TextIter & limit,
                                 std::list<Pango::Attribute> & attributes);
   Glib::RefPtr<Pango::Layout> create_layout_for_paragraph(const Glib::RefPtr<Gtk::PrintContext> & context, 
                                                           Gtk::TextIter p_start,
                                                           Gtk::TextIter p_end,
-                                                          PrintMargins & margins);
+                                                          int & indentation);
   Glib::RefPtr<Pango::Layout> create_layout_for_pagenumbers(const Glib::RefPtr<Gtk::PrintContext> & context, int page_number, int total_pages);
   Glib::RefPtr<Pango::Layout> create_layout_for_timestamp(const Glib::RefPtr<Gtk::PrintContext> & context);
+  int compute_footer_height(const Glib::RefPtr<Gtk::PrintContext> & context);
   void on_begin_print(const Glib::RefPtr<Gtk::PrintContext>&);
   void print_footer(const Glib::RefPtr<Gtk::PrintContext>&, guint);
 
@@ -114,11 +121,13 @@ private:
 /////
   void print_button_clicked();
   Gtk::ImageMenuItem * m_item;
-  PrintMargins         m_page_margins;
-  int                  m_footer_offset;
-  std::vector<int>     m_page_breaks;
+  int                  m_margin_top;
+  int                  m_margin_left;
+  int                  m_margin_right;
+  int                  m_margin_bottom;
+  std::vector<PageBreak> m_page_breaks;
   Glib::RefPtr<Gtk::PrintOperation> m_print_op;
-  std::string          m_timestamp;
+  Glib::RefPtr<Pango::Layout> m_timestamp_footer;
 };
 
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]