
#include "stdafx.h"

#include "mdc_canvas_view.h"
#include "mdc_canvas_view_printing.h"
#include <glib/gmessages.h>

#ifdef _WIN32
#include <cairo/cairo-win32.h>
#else
#include <cairo/cairo.h>
#endif

using namespace mdc;

CanvasViewExtras::CanvasViewExtras(CanvasView *view)
: _view(view)
{
  _custom_layout= false;
  _orientation= Portrait;
  _print_border= false;
  _print_page_numbers= false;

  _scale= 1;

  _page_width= 0;
  _page_height= 0;

  _margin_top= 0;
  _margin_left= 0;
  _margin_bottom= 0;
  _margin_right= 0;
}


void CanvasViewExtras::set_progress_callback(const sigc::slot<void, int, int> &progress)
{
  _progress_cb= progress;
}


void CanvasViewExtras::enable_custom_layout()
{
}


void CanvasViewExtras::set_show_print_guides(bool flag)
{
}


void CanvasViewExtras::set_page_counts(Count xpages, Count ypages)
{
  _xpages= xpages;
  _ypages= ypages;
}



void CanvasViewExtras::set_paper_size(double width, double height)
{
  _page_width= width;
  _page_height= height;
}


void CanvasViewExtras::set_page_margins(double top, double left, double bottom, double right)
{
  _margin_top= top;
  _margin_bottom= bottom;
  _margin_left= left;
  _margin_right= right;
}



void CanvasViewExtras::set_orientation(PageOrientation orientation)
{
  _orientation= orientation;
}


void CanvasViewExtras::set_print_border(bool flag)
{
  _print_border= flag;
}


void CanvasViewExtras::set_print_page_numbers(bool flag)
{
  _print_page_numbers= flag;
}


void CanvasViewExtras::set_scale(double scale)
{
  _scale= scale;
}


void CanvasViewExtras::set_scale_to_fit()
{
}


void CanvasViewExtras::set_print_area(const Rect &area)
{
}


Size CanvasViewExtras::get_adjusted_paper_size()
{
  Size size(_page_width, _page_height);

  //if (_orientation == Landscape)
  //  std::swap(size.width, size.height);

  return size;
}


Rect CanvasViewExtras::get_adjusted_printable_area()
{
  Rect rect;
  
  rect.pos.x= _margin_left;
  rect.pos.y= _margin_top;
  rect.size= Size(_page_width, _page_height);

  rect.size.width-= _margin_left + _margin_right;
  rect.size.height-= _margin_top + _margin_bottom;

  /*
  if (_orientation == Landscape)
  {
    std::swap(rect.pos.x, rect.pos.y);
    std::swap(rect.size.width, rect.size.height);
  }*/

  return rect;
}


int CanvasViewExtras::print_to_pdf(const std::string &path)
{
  Size paper_size= get_adjusted_paper_size();
  int count;

  _view->lock();

  // 1 pt = 1/72in, 1 mm = 0.039

  PDFSurface surface(path, MM_TO_PT(paper_size.width), MM_TO_PT(paper_size.height));

  {
    Rect bounds;

    CairoCtx ctx(surface);
    ctx.check_state();

    count= render_pages(&ctx, MM_TO_PT(1));

    ctx.check_state();
  }

  _view->unlock();

  return count;
}


int CanvasViewExtras::print_to_ps(const std::string &path)
{
  Size paper_size= get_adjusted_paper_size();
  int count;

  _view->lock();

  PSSurface surface(path, MM_TO_PT(paper_size.width), MM_TO_PT(paper_size.height));

  {
    Rect bounds;

    CairoCtx ctx(surface);
    ctx.check_state();

    count= render_pages(&ctx, MM_TO_PT(1));

    ctx.check_state();
  }

  _view->unlock();

  return count;
}

#ifdef _WIN32
int CanvasViewExtras::print_native(HDC hdc, int width, int height, int page)
{
  Size paper_size= get_adjusted_printable_area().size;
  int count;

  _view->lock();

  Win32Surface surface(hdc, true);

  {
    Rect bounds;

    CairoCtx ctx(surface);
    ctx.check_state();

    ctx.set_color(Color::White());
    ctx.paint();

    double scale= (paper_size.width/width);

    count= render_pages(&ctx, scale*20*_scale, page);

    ctx.check_state();
  }

  _view->unlock();

  return count;
}
#endif

int mdc::CanvasViewExtras::print_page(mdc::CairoCtx *ctx, int width, int height, int page)
{
  mdc::Size paper_size= get_adjusted_printable_area().size;
  int count;

  _view->lock();

  {
    mdc::Rect bounds;

    ctx->check_state();

    ctx->set_color(Color::White());
    ctx->paint();

    const double scale= (paper_size.width/width);

    //count = render_pages(ctx, 1.0/*scale*20*_scale*/, page);
    //g_message("print_native %i %i %f, %f", (int)paper_size.width, (int)width, (float)scale, (float)scale*20*_scale);
    count = render_pages(ctx, 0.95*scale, page);

    ctx->check_state();
  }

  _view->unlock();

  return count;
}


int CanvasViewExtras::render_pages(CairoCtx *cr, double render_scale, int page)
{
  Size paper_size= get_adjusted_paper_size();
  Rect content_area= get_adjusted_printable_area();
  Count xc, yc;
  Rect bounds;
  int count= 0, printed= 0;

  _view->get_page_layout(xc, yc);
 
  bounds.size= content_area.size;
  bounds.size.width= bounds.size.width*_scale;
  bounds.size.height= bounds.size.height*_scale;

  if (_orientation == Landscape)
    std::swap(bounds.size.width, bounds.size.height);

  _view->set_printout_mode(true);

  for (Count y= 0; y < yc; ++y)
  {
    bounds.pos.x= 0;
    for (Count x= 0; x < xc; ++x)
    {
      if (page < 0 || page == count)
      {
        cr->save();

        if (_orientation == Landscape)
        {
          cr->translate(render_scale * paper_size.width/2, render_scale * paper_size.height/2);
          cr->rotate(90*M_PI/180);
          cr->translate(-render_scale * paper_size.height/2, -render_scale * paper_size.width/2);

          cr->translate(render_scale * content_area.xmin(), render_scale * content_area.ymin());
        }
        else
          cr->translate(render_scale * content_area.xmin(), render_scale * content_area.ymin());

        cr->scale(render_scale/_scale, render_scale/_scale);
        _view->render_for_export(bounds, cr);
        cr->restore();

        if (_print_border)
        {
          cr->set_color(Color(0.5, 0.5, 0.5));
          cr->set_line_width(0.1);
          cr->rectangle(render_scale * content_area.xmin(), render_scale * content_area.ymin(),
            render_scale * content_area.width(), render_scale * content_area.height());
          cr->stroke();
        }
        cr->show_page();
        ++printed;

        _progress_cb(x, y);
      }
      ++count;

      bounds.pos.x+= bounds.width();
    }
    bounds.pos.y+= bounds.height();
  }

  _view->set_printout_mode(false);

  return printed;
}




// used in macosx
void CanvasViewExtras::render_page(CairoCtx *cr, int x, int y)
{
  Rect content_area= get_adjusted_printable_area();
  Rect bounds;
    
  bounds.pos.x+= content_area.width() * x;
  bounds.pos.y+= content_area.height() * y;
  
  if (_orientation == Landscape)
    std::swap(content_area.size.width, content_area.size.height);

  bounds.size= content_area.size;
    
  _view->set_printout_mode(true);
    
  cr->save();
  cr->scale(_scale, _scale);
  cr->translate(content_area.xmin(), content_area.ymin());  
  _view->render_for_export(bounds, cr);
  
  cr->restore();
  
  if (_print_border)
  {
    cr->save();
    cr->scale(_scale, _scale);
    cr->set_color(Color(0.5, 0.5, 0.5));
    cr->set_line_width(0.1);
    cr->rectangle(content_area.xmin(), content_area.ymin(),
                  content_area.width(), content_area.height());
    cr->stroke();
    cr->restore();
  }
  
  cr->show_page();
    
  _view->set_printout_mode(false);
}




