public void OnDrawPage (object sender, Gtk.DrawPageArgs args) { using (Cairo.Context cr = args.Context.CairoContext) { cr.MoveTo (margin_left, margin_top); PageBreak start; if (args.PageNr == 0) { start = new PageBreak (0, 0); } else { start = page_breaks [args.PageNr - 1]; } PageBreak end; if (args.PageNr < page_breaks.Count) { end = page_breaks [args.PageNr]; } else { end = new PageBreak (-1, -1); } Gtk.PrintContext context = args.Context; Gtk.TextIter position; Gtk.TextIter end_iter; Buffer.GetBounds (out position, out end_iter); // Fast-forward to the right starting paragraph while (position.Line < start.Paragraph) { position.ForwardLine (); } bool done = position.Compare (end_iter) >= 0; while (!done) { Gtk.TextIter line_end = position; if (!line_end.EndsLine ()) line_end.ForwardToLineEnd (); int paragraph_number = position.Line; int indentation; using (Pango.Layout layout = CreateParagraphLayout ( context, position, line_end, out indentation)) { for (int line_number = 0; line_number < layout.LineCount && !done; line_number++) { // Skip the lines up to the starting line in the // first paragraph on this page if ((paragraph_number == start.Paragraph) && (line_number < start.Line)) { continue; } // Break as soon as we hit the end line if ((paragraph_number == end.Paragraph) && (line_number == end.Line)) { done = true; break; } Pango.LayoutLine line = layout.Lines [line_number]; Pango.Rectangle ink_rect = Pango.Rectangle.Zero; Pango.Rectangle logical_rect = Pango.Rectangle.Zero; line.GetExtents (ref ink_rect, ref logical_rect); cr.MoveTo (margin_left + indentation, cr.CurrentPoint.Y); int line_height = Pango.Units.ToPixels (logical_rect.Height); Cairo.PointD new_line_point = new Cairo.PointD ( margin_left + indentation, cr.CurrentPoint.Y + line_height); Pango.CairoHelper.ShowLayoutLine (cr, line); cr.MoveTo (new_line_point); } } position.ForwardLine (); done = done || position.Compare (end_iter) >= 0; } int total_height = (int) args.Context.Height; int total_width = (int) args.Context.Width; int footer_height = 0; Cairo.PointD footer_anchor; using (Pango.Layout pages_footer = CreatePagenumbersLayout ( args.Context, args.PageNr + 1, page_breaks.Count + 1)) { Pango.Rectangle ink_footer_rect; Pango.Rectangle logical_footer_rect; pages_footer.GetExtents (out ink_footer_rect, out logical_footer_rect); footer_anchor = new Cairo.PointD ( CmToPixel (0.5, args.Context.DpiX), total_height - margin_bottom); footer_height = Pango.Units.ToPixels (logical_footer_rect.Height); cr.MoveTo ( total_width - Pango.Units.ToPixels (logical_footer_rect.Width) - CmToPixel (0.5, args.Context.DpiX), footer_anchor.Y); Pango.CairoHelper.ShowLayoutLine (cr, pages_footer.Lines [0]); } cr.MoveTo (footer_anchor); Pango.CairoHelper.ShowLayoutLine (cr, timestamp_footer.Lines [0]); cr.MoveTo (CmToPixel (0.5, args.Context.DpiX), total_height - margin_bottom - footer_height); cr.LineTo (total_width - CmToPixel (0.5, args.Context.DpiX), total_height - margin_bottom - footer_height); cr.Stroke (); } }
public void OnDrawPage(object sender, Gtk.DrawPageArgs args) { using (Cairo.Context cr = args.Context.CairoContext) { cr.MoveTo(margin_left, margin_top); PageBreak start; if (args.PageNr == 0) { start = new PageBreak(0, 0); } else { start = page_breaks [args.PageNr - 1]; } PageBreak end; if (args.PageNr < page_breaks.Count) { end = page_breaks [args.PageNr]; } else { end = new PageBreak(-1, -1); } Gtk.PrintContext context = args.Context; Gtk.TextIter position; Gtk.TextIter end_iter; Buffer.GetBounds(out position, out end_iter); // Fast-forward to the right starting paragraph while (position.Line < start.Paragraph) { position.ForwardLine(); } bool done = position.Compare(end_iter) >= 0; while (!done) { Gtk.TextIter line_end = position; if (!line_end.EndsLine()) { line_end.ForwardToLineEnd(); } int paragraph_number = position.Line; int indentation; using (Pango.Layout layout = CreateParagraphLayout( context, position, line_end, out indentation)) { for (int line_number = 0; line_number < layout.LineCount && !done; line_number++) { // Skip the lines up to the starting line in the // first paragraph on this page if ((paragraph_number == start.Paragraph) && (line_number < start.Line)) { continue; } // Break as soon as we hit the end line if ((paragraph_number == end.Paragraph) && (line_number == end.Line)) { done = true; break; } Pango.LayoutLine line = layout.Lines [line_number]; Pango.Rectangle ink_rect = Pango.Rectangle.Zero; Pango.Rectangle logical_rect = Pango.Rectangle.Zero; line.GetExtents(ref ink_rect, ref logical_rect); cr.MoveTo(margin_left + indentation, cr.CurrentPoint.Y); int line_height = Pango.Units.ToPixels(logical_rect.Height); Cairo.PointD new_line_point = new Cairo.PointD( margin_left + indentation, cr.CurrentPoint.Y + line_height); Pango.CairoHelper.ShowLayoutLine(cr, line); cr.MoveTo(new_line_point); } } position.ForwardLine(); done = done || position.Compare(end_iter) >= 0; } int total_height = (int)args.Context.Height; int total_width = (int)args.Context.Width; int footer_height = 0; Cairo.PointD footer_anchor; using (Pango.Layout pages_footer = CreatePagenumbersLayout( args.Context, args.PageNr + 1, page_breaks.Count + 1)) { Pango.Rectangle ink_footer_rect; Pango.Rectangle logical_footer_rect; pages_footer.GetExtents(out ink_footer_rect, out logical_footer_rect); footer_anchor = new Cairo.PointD( CmToPixel(0.5, args.Context.DpiX), total_height - margin_bottom); footer_height = Pango.Units.ToPixels(logical_footer_rect.Height); cr.MoveTo( total_width - Pango.Units.ToPixels(logical_footer_rect.Width) - CmToPixel(0.5, args.Context.DpiX), footer_anchor.Y); Pango.CairoHelper.ShowLayoutLine(cr, pages_footer.Lines [0]); } cr.MoveTo(footer_anchor); Pango.CairoHelper.ShowLayoutLine(cr, timestamp_footer.Lines [0]); cr.MoveTo(CmToPixel(0.5, args.Context.DpiX), total_height - margin_bottom - footer_height); cr.LineTo(total_width - CmToPixel(0.5, args.Context.DpiX), total_height - margin_bottom - footer_height); cr.Stroke(); } }
private void OnBeginPrint (object sender, Gtk.BeginPrintArgs args) { Gtk.PrintOperation op = (Gtk.PrintOperation) sender; Gtk.PrintContext context = args.Context; timestamp_footer = CreateTimestampLayout (context); // FIXME: These should be configurable settings later (UI Change) margin_top = CmToPixel (1.5, context.DpiY); margin_left = CmToPixel (1, context.DpiX); margin_right = CmToPixel (1, context.DpiX); margin_bottom = 0; double max_height = Pango.Units.FromPixels ((int) context.Height - margin_top - margin_bottom - ComputeFooterHeight (context)); Gtk.TextIter position; Gtk.TextIter end_iter; Buffer.GetBounds (out position, out end_iter); double page_height = 0; bool done = position.Compare (end_iter) >= 0; while (!done) { Gtk.TextIter line_end = position; if (!line_end.EndsLine ()) line_end.ForwardToLineEnd (); int paragraph_number = position.Line; int indentation; using (Pango.Layout layout = CreateParagraphLayout ( context, position, line_end, out indentation)) { Pango.Rectangle ink_rect = Pango.Rectangle.Zero; Pango.Rectangle logical_rect = Pango.Rectangle.Zero; for (int line_in_paragraph = 0; line_in_paragraph < layout.LineCount; line_in_paragraph++) { Pango.LayoutLine line = layout.GetLine (line_in_paragraph); line.GetExtents (ref ink_rect, ref logical_rect); if (page_height + logical_rect.Height >= max_height) { PageBreak page_break = new PageBreak ( paragraph_number, line_in_paragraph); page_breaks.Add (page_break); page_height = 0; } page_height += logical_rect.Height; } position.ForwardLine (); done = position.Compare (end_iter) >= 0; } } op.NPages = page_breaks.Count + 1; }