00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "printing.hpp"
00024 #include <sstream>
00025 #include <glibmm/i18n.h>
00026 #include <config.h>
00027
00029 const int PAGE_TOLERANCE = 40;
00030
00032 const int HEADER_SPACING = 10;
00033
00035 const int FOOTER_SPACING = 10;
00036
00038 const int BORDER_SPACING = 10;
00039
00041 const Glib::ustring FOOTER_TEXT = _("Page %1 of %2");
00042
00044 KitPrintOperation::~KitPrintOperation() {
00045
00046 if (m_items)
00047 delete m_items;
00048 }
00049
00051 Glib::RefPtr<KitPrintOperation> KitPrintOperation::create() {
00052 return Glib::RefPtr<KitPrintOperation>(new KitPrintOperation());
00053 }
00054
00060 layout_refptr KitPrintOperation::new_header(const Glib::RefPtr<Gtk::PrintContext>& context) {
00061 Pango::FontDescription header_font("sans 16");
00062 layout_refptr retval = context->create_pango_layout();
00063 retval->set_font_description(header_font);
00064 #ifdef MAEMO
00065 std::ostringstream os;
00066 os << "<b>" << m_page_title << "</b>";
00067 retval->set_markup(os.str());
00068 #else
00069 retval->set_markup(Glib::ustring::compose("<b>%1</b>", m_page_title));
00070 #endif
00071 retval->set_alignment(Pango::ALIGN_CENTER);
00072 retval->set_width(static_cast<int>(context->get_width() * Pango::SCALE));
00073 m_ref_headers.push_back(retval);
00074 return retval;
00075 }
00076
00082 layout_refptr KitPrintOperation::new_footer(const Glib::RefPtr<Gtk::PrintContext>& context) {
00083 Pango::FontDescription font_desc("sans 12");
00084 layout_refptr retval = context->create_pango_layout();
00085 retval->set_font_description(font_desc);
00086 Glib::ustring footer = FOOTER_TEXT;
00087 retval->set_text(footer);
00088 retval->set_alignment(Pango::ALIGN_CENTER);
00089 retval->set_width(static_cast<int>(context->get_width() * Pango::SCALE));
00090 m_ref_footers.push_back(retval);
00091 return retval;
00092 }
00093
00099 void KitPrintOperation::on_begin_print(const Glib::RefPtr<Gtk::PrintContext>& context) {
00100 Pango::FontDescription font_desc("sans 12");
00101 layout_refptr ref_footer = new_footer(context);
00102 layout_refptr ref_header = new_header(context);
00103 m_ref_layout = context->create_pango_layout();
00104 const double width = context->get_width();
00105 double height = context->get_height();
00106 m_ref_layout->set_width(static_cast<int>(width * Pango::SCALE));
00107
00108
00109 int w;
00110 int h;
00111 ref_header->get_size(w, h);
00112 height -= static_cast<int>(h / Pango::SCALE);
00113 ref_footer->get_size(w, h);
00114 height -= static_cast<int>(h / Pango::SCALE);
00115
00116 height -= (HEADER_SPACING + FOOTER_SPACING + PAGE_TOLERANCE + BORDER_SPACING * 2);
00117
00118
00119 Glib::ustring page_text;
00120 for (ItemIter i = m_items->begin(); i != m_items->end(); ++i) {
00121 Item* item = *i;
00122 page_text += item->get_description() + "\n";
00123 }
00124 m_ref_layout->set_text(page_text);
00125 const int line_count = m_ref_layout->get_line_count();
00126
00127 Glib::RefPtr<Pango::LayoutLine> layout_line;
00128 double page_height = 0;
00129 for (int line = 0; line < line_count; ++line) {
00130 Pango::Rectangle ink_rect, logical_rect;
00131 layout_line = m_ref_layout->get_line(line);
00132 layout_line->get_extents(ink_rect, logical_rect);
00133 const double line_height = logical_rect.get_height() / Pango::SCALE;
00134
00135 if (page_height + line_height > height) {
00136
00137 page_height = 0;
00138
00139 m_page_breaks.push_back(line);
00140 ref_header = new_header(context);
00141 ref_footer = new_footer(context);
00142 }
00143 page_height += line_height;
00144 }
00145
00146 const int n_pages = m_page_breaks.size() + 1;
00147 set_n_pages(n_pages);
00148
00149
00150 for (int page_number = 0; page_number < n_pages; page_number++) {
00151
00152 #ifdef MAEMO
00153 std::ostringstream os;
00154 os << "Page " << page_number + 1 << " of " << n_pages;
00155 Glib::ustring footer = os.str();
00156 #else
00157 Glib::ustring footer = Glib::ustring::compose(FOOTER_TEXT,
00158 page_number + 1,
00159 n_pages);
00160 #endif
00161 m_ref_footers[page_number]->set_text(footer);
00162 }
00163 }
00164
00171 void KitPrintOperation::on_draw_page(const Glib::RefPtr<Gtk::PrintContext>& context, int page_number) {
00172 int start_page_line = 0;
00173 int end_page_line = 0;
00174
00175 if (page_number == 0) {
00176 start_page_line = 0;
00177 } else {
00178 start_page_line = m_page_breaks[page_number - 1];
00179 }
00180
00181 if (page_number < static_cast<int>(m_page_breaks.size())) {
00182 end_page_line = m_page_breaks[page_number];
00183 } else {
00184 end_page_line = m_ref_layout->get_line_count();
00185 }
00186
00187
00188 Cairo::RefPtr<Cairo::Context> cairo_ctx = context->get_cairo_context();
00189 cairo_ctx->set_source_rgb(0, 0, 0);
00190
00191 Pango::LayoutIter iter;
00192 double start_pos = 0;
00193 int line_index = 0;
00194 double header_height = 0;
00195
00196
00197 layout_refptr ref_header = m_ref_headers[page_number];
00198 ref_header->get_iter(iter);
00199 do {
00200 Glib::RefPtr<Pango::LayoutLine> header_line = iter.get_line();
00201 Pango::Rectangle hr = iter.get_line_logical_extents();
00202 int bl = iter.get_baseline();
00203 double hx = hr.get_x() / Pango::SCALE;
00204 double hy = bl / Pango::SCALE;
00205 header_height = hy;
00206 cairo_ctx->move_to(hx, hy);
00207 header_line->show_in_cairo_context(cairo_ctx);
00208 } while (iter.next_line());
00209
00210
00211 cairo_ctx->set_line_width(0.5);
00212 cairo_ctx->set_line_cap(Cairo::LINE_CAP_SQUARE);
00213 cairo_ctx->set_line_join(Cairo::LINE_JOIN_MITER);
00214 header_height += BORDER_SPACING;
00215 cairo_ctx->move_to(0.0, header_height);
00216 cairo_ctx->line_to(context->get_width(), header_height);
00217 cairo_ctx->stroke();
00218 header_height += HEADER_SPACING;
00219
00220
00221 m_ref_layout->get_iter(iter);
00222 do {
00223 if (line_index >= start_page_line) {
00224 Glib::RefPtr<Pango::LayoutLine> layout_line = iter.get_line();
00225 Pango::Rectangle logical_rect = iter.get_line_logical_extents();
00226 int baseline = iter.get_baseline();
00227 if (line_index == start_page_line) {
00228 start_pos = logical_rect.get_y() / Pango::SCALE;
00229 }
00230 double x = logical_rect.get_x() / Pango::SCALE;
00231 double y = baseline / Pango::SCALE - start_pos + header_height;
00232 cairo_ctx->move_to(x, y);
00233 layout_line->show_in_cairo_context(cairo_ctx);
00234 }
00235 line_index++;
00236 } while (line_index < end_page_line && iter.next_line());
00237
00238
00239 layout_refptr ref_footer = m_ref_footers[page_number];
00240 int w;
00241 int h;
00242 ref_footer->get_size(w, h);
00243 start_pos = context->get_height() - h / Pango::SCALE - BORDER_SPACING;
00244
00245
00246 cairo_ctx->set_source_rgb(0, 0, 0);
00247 cairo_ctx->set_line_width(0.5);
00248 cairo_ctx->set_line_cap(Cairo::LINE_CAP_SQUARE);
00249 cairo_ctx->set_line_join(Cairo::LINE_JOIN_MITER);
00250 cairo_ctx->move_to(0.0, start_pos);
00251 cairo_ctx->line_to(context->get_width(), start_pos);
00252 cairo_ctx->stroke();
00253 start_pos += BORDER_SPACING;
00254
00255 ref_footer->get_iter(iter);
00256 do {
00257 Glib::RefPtr<Pango::LayoutLine> footer_line = iter.get_line();
00258 Pango::Rectangle fr = iter.get_line_logical_extents();
00259 int bl = iter.get_baseline();
00260 double fx = fr.get_x() / Pango::SCALE;
00261 double fy = bl / Pango::SCALE + start_pos;
00262 cairo_ctx->move_to(fx, fy);
00263 footer_line->show_in_cairo_context(cairo_ctx);
00264 } while (iter.next_line());
00265
00266 }