#!/bin/env python

import pygtk
pygtk.require("2.0")
import sys
import math
import cairo
import pango
import gtk


class PrintClass:
    def __init__(self, action=None, data=None, filename=None):
        self.text = data
        self.layout = None
        self.page_breaks = None
        self.font_size=12
        if action==None:
            # By default set the print action to preview
            action = gtk.PRINT_OPERATION_ACTION_PREVIEW
        
        # Paper Size 
        paper_size = gtk.PaperSize(gtk.PAPER_NAME_A4)
        # Available Papers
        # gtk.PAPER_NAME_A3 - Name for the A4 paper size.
        # gtk.PAPER_NAME_A4 - Name for the A4 paper size.
        # gtk.PAPER_NAME_A5 -Name for the A5 paper size.
        # gtk.PAPER_NAME_B5 -Name for the B5 paper size.
        # gtk.PAPER_NAME_LETTER - Name for the Letter paper size.
        # gtk.PAPER_NAME_EXECUTIVE - Name for the Executive paper size.
        # gtk.PAPER_NAME_LEGAL - for the Legal paper size.
        # Page Setup
        setup = gtk.PageSetup()
        setup.set_paper_size(paper_size)

        
        # PrintOperation
        print_ = gtk.PrintOperation()
        print_.set_default_page_setup(setup)
        print_.set_unit(gtk.UNIT_MM)

        print_.connect("begin_print", self.begin_print)
        print_.connect("draw_page", self.draw_page)
  
        if action == gtk.PRINT_OPERATION_ACTION_EXPORT:
            print_.set_export_filename(filename)
        res = print_.run(action)

    def begin_print(self, operation, context):
        width = context.get_width()
        height = context.get_height()
        self.layout = context.create_pango_layout()
        self.layout.set_font_description(pango.FontDescription("Sans " + str(self.font_size)))
        self.layout.set_width(int(width*pango.SCALE))
        self.layout.set_text(self.text)

        num_lines = self.layout.get_line_count()

        page_breaks = []
        page_height = 0

        for line in xrange(num_lines):
            layout_line = self.layout.get_line(line)
            ink_rect, logical_rect = layout_line.get_extents()
            x_bearing, y_bearing, lwidth, lheight = logical_rect

            line_height = lheight / 1024.0 # 1024.0 is float(pango.SCALE)
            page_height += line_height
            # page_height is the current location on a page.
            # It adds the the line height on each pass through the loop
            # Once it is greater then the height supplied by context.get_height
            # it marks the line and sets the current page height back to 0
            if page_height + line_height > height:
                page_breaks.append(line)
                page_height = 0
                page_height += line_height

        operation.set_n_pages(len(page_breaks) + 1)
        self.page_breaks = page_breaks

    def draw_page (self, operation, context, page_number):
        assert isinstance(self.page_breaks, list)
        #print page_number
        if page_number == 0:
            start = 0
        else:
            start = self.page_breaks[page_number - 1]

        try:
            end = self.page_breaks[page_number]
        except IndexError:
            end = self.layout.get_line_count()
        
        cr = context.get_cairo_context()

        cr.set_source_rgb(0, 0, 0)
        
        i = 0
        start_pos = 0
        iter = self.layout.get_iter()
        while 1:
            if i >= start:
                line = iter.get_line()
                _, logical_rect = iter.get_line_extents()
                x_bearing, y_bearing, lwidth, lheight = logical_rect
                baseline = iter.get_baseline()
                if i == start:
                    start_pos = y_bearing / 1024.0 # 1024.0 is float(pango.SCALE)
                cr.move_to(x_bearing / 1024.0, baseline / 1024.0 - start_pos)
                cr.show_layout_line(line)
            i += 1
            if not (i < end and iter.next_line()):
                break

