#include "stdafx.h"
#include "test_be.h"

#include <windows.h>
#include <gl/gl.h>
//#include <gtk/gtk.h>
#include <cairo.h>
//#include <cairoint.h>
#include <cairo-pdf.h>
#include <cairo-ps.h>
#include <cairo-svg.h>
#include <cairo-glitz.h>
#include <cairo-win32.h>
#include <math.h>
//#include <gdk/gdkkeysyms.h>
#include <glitz.h>
#include <wgl/glitz-wgl.h>

using namespace std;

#define WIDTH  800
#define HEIGHT 600
#define STRIDE WIDTH*4
#define MAX_COORDS 1024

/* This path desribes what will be drawn later 
   The bulk of it is doing the IBM letters by connect the dots
   at the very end, we will get fancy and add a (R) Registered logo.
*/
static void
travel_path (cairo_t *cr)
{
  int pen_radius= 10;

  cairo_set_source_rgb (cr, 1,1,1);
  cairo_paint (cr);

  cairo_set_line_width (cr, pen_radius*2);

  /* Use IBM Blue Pen Color with no ALPHA */
  cairo_set_source_rgba (cr, .3, .42, .69, 1);


  /* This Draws the IBM 8 Lines "I" Logo */
  cairo_move_to (cr, 10, 10);
  cairo_line_to (cr, 160, 10); 

  cairo_move_to (cr, 10, 40);
  cairo_line_to (cr, 160, 40);

  /* NOTE: Narrower Middle: 1/3 width */
  cairo_move_to (cr, 60, 70);
  cairo_line_to (cr, 110, 70);

  cairo_move_to (cr, 60, 100);
  cairo_line_to (cr, 110, 100);

  cairo_move_to (cr, 60, 130);
  cairo_line_to (cr, 110, 130);

  cairo_move_to (cr, 60, 160);
  cairo_line_to (cr, 110, 160);
  /* END Narrower Middle */

  cairo_move_to (cr, 10, 190);
  cairo_line_to (cr, 160, 190);

  cairo_move_to (cr, 10, 220);
  cairo_line_to (cr, 160, 220);
  /* END "I" DRAWING */




  /* This Draws the IBM 8 Lines "B" Logo */
  cairo_move_to (cr, 170, 10);
  cairo_line_to (cr, 340, 10); 

  cairo_move_to (cr, 170, 40);
  cairo_line_to (cr, 360, 40); 

  cairo_move_to (cr, 200, 70);
  cairo_line_to (cr, 250, 70);
  /*B's have holes in them! */
  cairo_move_to (cr, 300, 70); 
  cairo_line_to (cr, 360, 70); 


  cairo_move_to (cr, 210, 100);
  cairo_line_to (cr, 350, 100); 


  cairo_move_to (cr, 210, 130);
  cairo_line_to (cr, 350, 130); 


  cairo_move_to (cr, 200, 160);
  cairo_line_to (cr, 250, 160);
  /*B's have holes in them! */
  cairo_move_to (cr, 300, 160); 
  cairo_line_to (cr, 360, 160); 


  cairo_move_to (cr, 170, 190);
  cairo_line_to (cr, 360, 190); 


  cairo_move_to (cr, 170, 220);
  cairo_line_to (cr, 340, 220); 
  /* END "B" DRAWING */




  /* THE EVER POINTY "M"  */
  cairo_move_to (cr, 370, 10);
  cairo_line_to (cr, 470, 10); 
  cairo_move_to (cr, 560, 10);
  cairo_line_to (cr, 660, 10); 


  cairo_move_to (cr, 370, 40);
  cairo_line_to (cr, 490, 40); 
  cairo_move_to (cr, 540, 40);
  cairo_line_to (cr, 660, 40); 


  cairo_move_to (cr, 400, 70);
  cairo_line_to (cr, 510, 70); 
  cairo_move_to (cr, 520, 70);
  cairo_line_to (cr, 630, 70); 


  cairo_move_to (cr, 400, 100);
  cairo_line_to (cr, 630, 100); 


  cairo_move_to (cr, 400, 130);
  cairo_line_to (cr, 470, 130);
  cairo_move_to (cr, 480, 130);
  cairo_line_to (cr, 550, 130);
  cairo_move_to (cr, 560, 130);
  cairo_line_to (cr, 630, 130); 


  cairo_move_to (cr, 400, 160);
  cairo_line_to (cr, 470, 160);
  cairo_move_to (cr, 490, 160);
  cairo_line_to (cr, 540, 160);
  cairo_move_to (cr, 560, 160);
  cairo_line_to (cr, 630, 160); 


  cairo_move_to (cr, 370, 190);
  cairo_line_to (cr, 470, 190);
  cairo_move_to (cr, 500, 190);
  cairo_line_to (cr, 530, 190);
  cairo_move_to (cr, 560, 190);
  cairo_line_to (cr, 660, 190); 


  cairo_move_to (cr, 370, 220);
  cairo_line_to (cr, 470, 220);
  cairo_move_to (cr, 510, 220);
  cairo_line_to (cr, 520, 220);
  cairo_move_to (cr, 560, 220);
  cairo_line_to (cr, 660, 220); 

  /* END POINTY LETTERS */

  /* We stroke the path so we see everything we just specified
    by connecting the dots
  */
  cairo_stroke(cr);




  /* Let us add a disclaimer and show some fancy cairo: */
  /* We are going to want a nice fine lined circle around the R 
  you need to make sure you have stroked existing things
  that you wanted drawn with the larger pen before continuing. 
  */
  cairo_set_line_width (cr, pen_radius*.5);

  /* Now we will draw the fancy circle around the "R" */
  /* NOTE: The angles are in radians */
  cairo_move_to (cr, 710, 200);
  double angle1 = 0 * (3.14/180.0);  
  double angle2 = 360 * (3.14/180.0);

  /* We draw a large black circle */
  cairo_set_source_rgba (cr, 0, 0, 0, 1);
  cairo_arc (cr, 710, 200, 20, angle1, angle2);
  cairo_stroke (cr);

  /* We draw a smaller white circle centered on it */
  cairo_set_source_rgba (cr, 1, 1, 1, 1);
  cairo_arc (cr, 710, 200, 20, angle1, angle2);
  /* We use the fill operator to fill in the circle! */
  cairo_fill (cr);

  /* We are going to draw the letter "R" with black pen*/

  cairo_move_to (cr, 695,212); /* Bottom left of text at point */
  cairo_set_source_rgba (cr, 0, 0, 0, 1);
  cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
                                     CAIRO_FONT_WEIGHT_BOLD);
  cairo_set_font_size (cr, 40);
  cairo_show_text (cr, "R");

  /* We stroke everything we have just done 
     to actually draw it...
  */ 
  cairo_stroke (cr);	 
}


/* Apply our path to the surface specified */
static void
draw (cairo_surface_t *surface)
{
  cairo_t *cr;
  cr = cairo_create (surface);

  /* Try applying the scale and rotate factors here to examine their effects on the output!*/
  /* cairo_rotate (cr, -M_PI / 4); */
  /* cairo_scale (cr, 2, 1.0);  */

  travel_path (cr);
  cairo_destroy (cr);
}


/* Function needed to draw to gtk window */
//static void
//draw_gtk (GtkWidget      *widget,
//          GdkEventExpose *eev,
//          gpointer        data)
//{
//  cairo_t *cr;
//  cr = gdk_cairo_create (widget->window);
//  travel_path (cr);
//  cairo_destroy (cr);
//}


int
Test::test_glitz (void *hwnd)
{

  return 0;
}

int
Test::test_cairo_win32 (void *hwnd)
{
  cairo_surface_t *surface;

  /* Win32 Backend */
  HDC hdc= GetWindowDC ((HWND)hwnd);

  surface = cairo_win32_surface_create (hdc);
  draw (surface);
  cairo_surface_destroy (surface);

  ReleaseDC((HWND)hwnd, hdc);

  return 0;
}


int
Test::test_cairo_glitz (void *hwnd)
{
  /* Glitz Backend */

  static cairo_surface_t *_crsurface= NULL;
  static glitz_drawable_t *_glzdrawable= 0;
  static glitz_context_t *_glzcontext= 0;
  static glitz_surface_t *_glzsurface= 0;
  static glitz_format_t *_glzformat= 0;
  static glitz_drawable_format_t *_glzdformat= 0;

  static HGLRC _glrc;
  static HDC _hdc;
  static HWND _hwnd= (HWND)hwnd;
  static DWORD _fps_timer= 0;

  //CairoCtx *_cairo;
  //cairo_matrix_t _trmatrix;

  if (!_crsurface)
  {

    static bool inited_wgl= false;
    if (!inited_wgl)
    {
      glitz_wgl_init (NULL);

      inited_wgl= true;
    }

    _glzdformat= glitz_wgl_find_window_format(0, NULL, 0);
    if(!_glzdformat)
      return false;

    _glzdrawable= glitz_wgl_create_drawable_for_window(_glzdformat, _hwnd, WIDTH, HEIGHT);
    if(!_glzdrawable)
      return false;

    _glzformat= glitz_find_standard_format(_glzdrawable, GLITZ_STANDARD_ARGB32);
    if(!_glzformat)
      return false;



    if (_glzsurface)
      glitz_surface_destroy(_glzsurface);  

    glitz_drawable_update_size(_glzdrawable, WIDTH, HEIGHT);

    _glzsurface= glitz_surface_create(_glzdrawable, _glzformat, WIDTH, HEIGHT, 0, NULL);
    if (!_glzsurface)
      throw new exception("could not create glitz surface");

    glitz_surface_attach(_glzsurface, _glzdrawable, GLITZ_DRAWABLE_BUFFER_BACK_COLOR);

    _glzcontext= glitz_context_create(_glzdrawable, _glzdformat);

    if (_crsurface)
      cairo_surface_destroy(_crsurface);

    _crsurface= cairo_glitz_surface_create(_glzsurface);

    _hdc= GetWindowDC(_hwnd);
    _glrc= wglGetCurrentContext();
  }
    // make current
  glitz_context_make_current(_glzcontext, _glzdrawable);
  //wglMakeCurrent(_hdc, _glrc);

  //delete _cairo;
  //_cairo= new CairoCtx(_crsurface);
  //cairo_set_tolerance(_cairo->get_cr(), 0.1);
  //draw (_crsurface);

  cairo_t *cr= cairo_create(_crsurface);

  cairo_rectangle(cr, 0, 0, 100, 100);
  cairo_set_source_rgb(cr, 1, 0, 0);
  cairo_fill(cr);

  int x= cairo_version();

  cairo_destroy(cr);
/*
  glColor3f(0,1,1);
  glBegin(GL_POLYGON);
  glVertex2d(50, 50);
  glVertex2d(200, 50);
  glVertex2d(200, 200);
  glVertex2d(50, 200);
  glVertex2d(50, 50);
  glEnd();
*/
  glitz_drawable_swap_buffers(_glzdrawable);

  //cairo_surface_destroy (_crsurface);

  //ReleaseDC(_hwnd, _hdc);

  return 0;
}

int
Test::test_cairo_pdf ()
{
  cairo_surface_t *surface;

  /* PDF Backend */
  surface = cairo_pdf_surface_create ("test.pdf",
			  WIDTH, HEIGHT);
  draw (surface);
  cairo_surface_destroy (surface);

  return 0;
}

int
Test::test_cairo_ps ()
{
  cairo_surface_t *surface;

  /* Postscript Backend */
  surface = cairo_ps_surface_create ("test.ps",
			  WIDTH, HEIGHT);
  draw (surface);
  cairo_surface_destroy (surface);

  return 0;
}

int
Test::test_cairo_png ()
{
  cairo_surface_t *surface;

  /* Image backend */
  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
				  WIDTH, HEIGHT);
  draw (surface);
  cairo_surface_write_to_png (surface, "test.png");
  cairo_surface_destroy (surface);

  return 0;
}

int
Test::test_cairo_svg ()
{
  cairo_surface_t *surface;

  /* Scalable Vector Graphics Backend */
  surface = cairo_svg_surface_create ("test.svg",
			  WIDTH, HEIGHT);
  draw (surface);
  cairo_surface_destroy (surface);

  return 0;
}

int
Test::test_cairo_gtk ()
{
  //cairo_surface_t *surface;

  ///* GTK Window using Cairo */
  //gtk_init (NULL, NULL);        /* Fire up GTK!       */
  //GtkWidget *mainwin;           /* Make a new windows */
  //GtkWidget *canvas = NULL;     /* Make a new canvas  */

  //mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  //canvas = gtk_drawing_area_new ();
  //gtk_widget_set_size_request (canvas, WIDTH, HEIGHT);     

  //gtk_container_add (GTK_CONTAINER (mainwin), canvas); /* Place the canvas in the window */

  //g_signal_connect (mainwin, "destroy", G_CALLBACK (gtk_main_quit), NULL); /* Quit graphically */

  //* Instead of drawing like usual, we connect the expose event to do the drawing! */
  //g_signal_connect (G_OBJECT (canvas), "expose-event",
  //                  G_CALLBACK (draw_gtk), NULL);

  //gtk_widget_show_all (mainwin); /* Show the window on the screen */
  //gtk_main ();

  return 0;
}



