/*
 * ext/ClibPDF/ClibPDF.c
 * 
 * by Nakamura Noritsugu
 * from 1998.11.25
 */

#include <stdio.h>
#include <cpdflib.h>
#include "ruby.h"

static VALUE mClibPDF, cPDF, cTBOX, cPDFoutlineEntry,
  cPDFplotDomain, cPDFtimeplotDomain, cPDFaxis , cPDFtimeaxis;

static VALUE
clibpdf_tbox_new(VALUE obj)
{
  CPDFtboxAttr *tbox;

  return Data_Wrap_Struct(cTBOX, 0, 0, tbox);
}

static VALUE
clibpdf_version(VALUE obj)
{
  return rb_str_new2(cpdf_version());
}

static VALUE
clibpdf_platform(VALUE obj)
{
  return rb_str_new2(cpdf_platform());
}

static VALUE
clibpdf_setGlobalDocumentLimits(VALUE obj, VALUE maxPages, VALUE maxFonts, VALUE maxImages, VALUE maxAnnots, VALUE maxObjects)
{
  cpdf_setGlobalDocumentLimits(NUM2INT(maxPages), NUM2INT(maxFonts), NUM2INT(maxImages), NUM2INT(maxAnnots), NUM2INT(maxObjects));
  return Qnil;
}

static VALUE
clibpdf_setViewerPreferences(VALUE pdf, VALUE vP)
{
  CPDFdoc *CPDFdocPtr;
  CPDFviewerPrefs viewerPrefs;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  Check_Type(vP, T_ARRAY);
  if(RARRAY(vP)->len != 8) {
	rb_raise(rb_eArgError, "wrong # of arguments");
  } else {
	viewerPrefs.pageMode = NUM2INT(RARRAY(vP)->ptr[0]);
	viewerPrefs.hideToolbar = NUM2INT(RARRAY(vP)->ptr[1]);
	viewerPrefs.hideMenubar = NUM2INT(RARRAY(vP)->ptr[2]);
	viewerPrefs.hideWindowUI = NUM2INT(RARRAY(vP)->ptr[3]);
	viewerPrefs.fitWindow = NUM2INT(RARRAY(vP)->ptr[4]);
	viewerPrefs.centerWindow = NUM2INT(RARRAY(vP)->ptr[5]);
	viewerPrefs.pageLayout = NUM2INT(RARRAY(vP)->ptr[6]);
	viewerPrefs.nonFSPageMode = NUM2INT(RARRAY(vP)->ptr[7]);
	cpdf_setViewerPreferences(CPDFdocPtr, &viewerPrefs);
  }
  return Qnil;
}

static VALUE
clibpdf_open(VALUE obj, VALUE ary)
{
  int i, len;
  CPDFdoc *CPDFdocPtr;
  CPDFdocLimits *CPDFdocLimitsPtr;
  
  CPDFdocLimitsPtr = ALLOCA_N(CPDFdocLimits, 1);
  len = RARRAY(ary)->len;

  if(len == 1) {
	CPDFdocPtr = cpdf_open(NUM2INT(RARRAY(ary)->ptr[0]), NULL);
	return Data_Wrap_Struct(obj, 0, 0, CPDFdocPtr);
  } else if(len == 6) {
	CPDFdocLimitsPtr[0].nMaxPages = NUM2INT(RARRAY(ary)->ptr[1]);
	CPDFdocLimitsPtr[0].nMaxFonts = NUM2INT(RARRAY(ary)->ptr[2]);
	CPDFdocLimitsPtr[0].nMaxImages = NUM2INT(RARRAY(ary)->ptr[3]);
	CPDFdocLimitsPtr[0].nMaxAnnots = NUM2INT(RARRAY(ary)->ptr[4]);
	CPDFdocLimitsPtr[0].nMaxObjects = NUM2INT(RARRAY(ary)->ptr[5]);
	CPDFdocPtr = cpdf_open(NUM2INT(RARRAY(ary)->ptr[0]), CPDFdocLimitsPtr);
	return Data_Wrap_Struct(obj, 0, 0, CPDFdocPtr);
  } else {
	rb_raise(rb_eArgError, "wrong # of arguments");
  }
}

static VALUE
clibpdf_enableCompression(VALUE pdf, VALUE cmpON)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_enableCompression(CPDFdocPtr, NUM2INT(cmpON));
  return Qnil;
}

static VALUE
clibpdf_useContentMemStream(VALUE pdf, VALUE flag)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_useContentMemStream(CPDFdocPtr, NUM2INT(flag));
  return Qnil;
}

static VALUE
clibpdf_setCompressionFilter(VALUE pdf, VALUE command, VALUE filterlist)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setCompressionFilter(CPDFdocPtr, STR2CSTR(command), STR2CSTR(filterlist));
  return Qnil;
}

static VALUE
clibpdf_setDefaultDomainUnit(VALUE pdf, VALUE defunit)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setDefaultDomainUnit(CPDFdocPtr, (float)NUM2DBL(defunit));
  return Qnil;
}

static VALUE
clibpdf_init(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_init(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_pageInit(VALUE pdf, VALUE pagenum, VALUE rot, VALUE mediaboxstr, VALUE cropboxstr)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_pageInit(CPDFdocPtr, NUM2INT(pagenum), NUM2INT(rot), STR2CSTR(mediaboxstr), STR2CSTR(cropboxstr)));
  
}

static VALUE
clibpdf_finalizeAll(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_finalizeAll(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_savePDFmemoryStreamToFile(VALUE pdf, VALUE file)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_savePDFmemoryStreamToFile(CPDFdocPtr, STR2CSTR(file)));
}

static VALUE
clibpdf_getBufferForPDF(VALUE pdf)
{
  int len;
  int *length;
  CPDFdoc *CPDFdocPtr;
  length = &len;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);

#ifdef hogehoge
  return rb_str_new2(cpdf_getBufferForPDF(RARRAY(length)->ptr));
  return (VALUE)cpdf_getBufferForPDF((int *)RARRAY(length)->ptr);
#endif
  /*  return ary_new3(2, str_new2(cpdf_getBufferForPDF(length)),
				  Data_Wrap_Struct(obj, 0, 0, length));*/
  return rb_ary_new3(2, rb_str_new2(cpdf_getBufferForPDF(CPDFdocPtr, length)),
				  INT2NUM(len));
}

static VALUE
clibpdf_close(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_close(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_launchPreview(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_launchPreview(CPDFdocPtr));
}

static VALUE
clibpdf_openPDFfileInViewer(VALUE pdf, VALUE pdffilepath)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if (NIL_P(pdffilepath)) {
	return INT2NUM(cpdf_openPDFfileInViewer(CPDFdocPtr, NULL));
  } else {
	return INT2NUM(cpdf_openPDFfileInViewer(CPDFdocPtr, STR2CSTR(pdffilepath)));
  }
}

static VALUE
clibpdf_setCreator(VALUE pdf, VALUE pname)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setCreator(CPDFdocPtr, STR2CSTR(pname));
  return Qnil;
}

static VALUE
clibpdf_setTitle(VALUE pdf, VALUE pname)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setTitle(CPDFdocPtr, STR2CSTR(pname));
  return Qnil;
}

static VALUE
clibpdf_setSubject(VALUE pdf, VALUE pname)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setSubject(CPDFdocPtr, STR2CSTR(pname));
  return Qnil;
}

static VALUE
clibpdf_setKeywords(VALUE pdf, VALUE pname)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setKeywords(CPDFdocPtr, STR2CSTR(pname));
  return Qnil;
}

static VALUE
clibpdf_comments(VALUE pdf, VALUE comments)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_comments(CPDFdocPtr, STR2CSTR(comments)));
}


/* Page related public functions */
static VALUE
clibpdf_setCurrentPage(VALUE pdf, VALUE page)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_setCurrentPage(CPDFdocPtr, NUM2INT(page)));
}

static VALUE
clibpdf_finalizePage(VALUE pdf, VALUE page)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_finalizePage(CPDFdocPtr, NUM2INT(page));
  return Qnil;
}

static VALUE
clibpdf_setPageSize(VALUE pdf, VALUE mboxstr, VALUE cboxstr)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setPageSize(CPDFdocPtr, STR2CSTR(mboxstr), STR2CSTR(cboxstr));
  return Qnil;
}

static VALUE
clibpdf_setBoundingBox(VALUE pdf, VALUE LLx, VALUE LLy, VALUE URx, VALUE URy)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setBoundingBox(CPDFdocPtr, NUM2INT(LLx), NUM2INT(LLy), NUM2INT(URx), NUM2INT(URy));
  return Qnil;
}

static VALUE
clibpdf_setMediaBox(VALUE pdf, VALUE LLx, VALUE LLy, VALUE URx, VALUE URy)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setMediaBox(CPDFdocPtr, NUM2INT(LLx), NUM2INT(LLy), NUM2INT(URx), NUM2INT(URy));
  return Qnil;
}

static VALUE
clibpdf_setCropBox(VALUE pdf, VALUE LLx, VALUE LLy, VALUE URx, VALUE URy)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setCropBox(CPDFdocPtr, NUM2INT(LLx), NUM2INT(LLy), NUM2INT(URx), NUM2INT(URy));
  return Qnil;
}


/* page duration and transition */
static VALUE
clibpdf_setPageDuration(VALUE pdf, VALUE seconds)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setPageDuration(CPDFdocPtr, (float)NUM2DBL(seconds));
  return Qnil;
}

static VALUE
clibpdf_setPageTransition(VALUE pdf, VALUE type, VALUE duration, VALUE direction, VALUE hv, VALUE io)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_setPageTransition(CPDFdocPtr, NUM2INT(type), (float)NUM2DBL(duration), (float)NUM2DBL(direction), NUM2INT(hv), NUM2INT(io)));
}


/* Annotation and hyper link functions */
static VALUE
clibpdf_setAnnotation(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE title, VALUE str, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	cpdf_setAnnotation(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(title), STR2CSTR(str), NULL);
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	cpdf_setAnnotation(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(title), STR2CSTR(str), CPDFannotAttribPtr);
  }
  return Qnil;
}

static VALUE
clibpdf_setActionURL(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE linkspec, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	cpdf_setActionURL(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(linkspec), NULL);
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	cpdf_setActionURL(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(linkspec), CPDFannotAttribPtr);
  }
  return Qnil;
}

static VALUE
clibpdf_setLinkAction(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE action_dict, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	cpdf_setLinkAction(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(action_dict), NULL);
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	cpdf_setLinkAction(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(action_dict), CPDFannotAttribPtr);
  }
  return Qnil;
}

static VALUE
clibpdf_setLinkGoToPage(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE page, VALUE fitmode, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	cpdf_setLinkGoToPage(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), NUM2INT(page), STR2CSTR(fitmode), NULL);
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	cpdf_setLinkGoToPage(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), NUM2INT(page), STR2CSTR(fitmode), CPDFannotAttribPtr);
  }
  return Qnil;
}

static VALUE
clibpdf_rawSetLinkGoToPage(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE page, VALUE fitmode, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	cpdf_setLinkGoToPage(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), NUM2INT(page), STR2CSTR(fitmode), NULL);
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	cpdf_setLinkGoToPage(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), NUM2INT(page), STR2CSTR(fitmode), CPDFannotAttribPtr);
  }
  return Qnil;
}

static VALUE
clibpdf_rawSetAnnotation(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE title, VALUE str, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	cpdf_rawSetAnnotation(CPDFdocPtr, (float)NUM2DBL(xll), (float)NUM2DBL(yll), (float)NUM2DBL(xur), (float)NUM2DBL(yur), STR2CSTR(title), STR2CSTR(str), NULL);
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	cpdf_rawSetAnnotation(CPDFdocPtr, (float)NUM2DBL(xll), (float)NUM2DBL(yll), (float)NUM2DBL(xur), (float)NUM2DBL(yur), STR2CSTR(title), STR2CSTR(str), CPDFannotAttribPtr);
  }
  return Qnil;
}

static VALUE
clibpdf_rawSetActionURL(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE linkspec, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	cpdf_rawSetActionURL(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(linkspec), NULL);
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	cpdf_rawSetActionURL(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(linkspec), CPDFannotAttribPtr);
  }
  return Qnil;
}

static VALUE
clibpdf_rawSetLinkAction(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE action_dict, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	cpdf_rawSetLinkAction(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(action_dict), NULL);
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	cpdf_rawSetLinkAction(CPDFdocPtr, NUM2DBL(xll), NUM2DBL(yll), NUM2DBL(xur), NUM2DBL(yur), STR2CSTR(action_dict), CPDFannotAttribPtr);
  }
  return Qnil;
}

static VALUE
clibpdf_includeTextFileAsAnnotation(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE title, VALUE filename, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	return INT2NUM(cpdf_includeTextFileAsAnnotation(CPDFdocPtr, (float)NUM2DBL(xll), (float)NUM2DBL(yll), (float)NUM2DBL(xur), (float)NUM2DBL(yur), STR2CSTR(title), STR2CSTR(filename), NULL));
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	return INT2NUM(cpdf_includeTextFileAsAnnotation(CPDFdocPtr, (float)NUM2DBL(xll), (float)NUM2DBL(yll), (float)NUM2DBL(xur), (float)NUM2DBL(yur), STR2CSTR(title), STR2CSTR(filename), CPDFannotAttribPtr));
  }
}

static VALUE
clibpdf_rawIncludeTextFileAsAnnotation(VALUE pdf, VALUE xll, VALUE yll, VALUE xur, VALUE yur, VALUE title, VALUE filename, VALUE attr)
{
  CPDFdoc *CPDFdocPtr;
  CPDFannotAttrib *CPDFannotAttribPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(attr)) {
	return INT2NUM(cpdf_rawIncludeTextFileAsAnnotation(CPDFdocPtr, (float)NUM2DBL(xll), (float)NUM2DBL(yll), (float)NUM2DBL(xur), (float)NUM2DBL(yur), STR2CSTR(title), STR2CSTR(filename), NULL));
  } else {
	Data_Get_Struct(attr, CPDFannotAttrib, CPDFannotAttribPtr);
	return INT2NUM(cpdf_rawIncludeTextFileAsAnnotation(CPDFdocPtr, (float)NUM2DBL(xll), (float)NUM2DBL(yll), (float)NUM2DBL(xur), (float)NUM2DBL(yur), STR2CSTR(title), STR2CSTR(filename), CPDFannotAttribPtr));
  }
}


/* ==== Text and Font functions ================================================ */
static VALUE
clibpdf_beginText(VALUE pdf, VALUE clipmode)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_beginText(CPDFdocPtr, NUM2INT(clipmode));
  return Qnil;
}

static VALUE
clibpdf_endText(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_endText(CPDFdocPtr);
  return Qnil;
}


/* convenient text functions */
static VALUE
clibpdf_text(VALUE pdf, VALUE x, VALUE y, VALUE orientation, VALUE textstr)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_text(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(orientation), STR2CSTR(textstr));

  return Qnil;
}

static VALUE
clibpdf_rawText(VALUE pdf, VALUE x, VALUE y, VALUE orientation, VALUE textstr)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawText(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(orientation), STR2CSTR(textstr));
  return Qnil;
}

static VALUE
clibpdf_textAligned(VALUE pdf, VALUE x, VALUE y, VALUE orientation, VALUE alignmode, VALUE textstr)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_textAligned(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(orientation), NUM2INT(alignmode), STR2CSTR(textstr));
  return Qnil;
}

static VALUE
clibpdf_rawTextAligned(VALUE pdf, VALUE x, VALUE y, VALUE orientation, VALUE alignmode, VALUE textstr)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawTextAligned(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(orientation), NUM2INT(alignmode), STR2CSTR(textstr));
  return Qnil;
}

static VALUE
clibpdf_textBox(VALUE pdf, VALUE xl, VALUE yl, VALUE width, VALUE height, VALUE angle, VALUE linespace, VALUE tbattr, VALUE text)
{
  CPDFdoc *CPDFdocPtr;
  CPDFtboxAttr tbA;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  Check_Type(tbattr, T_ARRAY);
  if(RARRAY(tbattr)->len != 4) {
	rb_raise(rb_eArgError, "wrong # of arguments");
  } else {
	tbA.alignmode = NUM2INT(RARRAY(tbattr)->ptr[0]);
	tbA.NLmode = NUM2INT(RARRAY(tbattr)->ptr[1]);
	tbA.paragraphSpacing = (float)NUM2DBL(RARRAY(tbattr)->ptr[2]);
	tbA.noMark = NUM2INT(RARRAY(tbattr)->ptr[3]);
  }
  return rb_str_new2(cpdf_textBox(CPDFdocPtr, (float)NUM2DBL(xl), (float)NUM2DBL(yl), (float)NUM2DBL(width), (float)NUM2DBL(height), (float)NUM2DBL(angle), (float)NUM2DBL(linespace), &tbA, STR2CSTR(text)));
}

static VALUE
clibpdf_rawTextBox(VALUE pdf, VALUE xl, VALUE yl, VALUE width, VALUE height, VALUE angle, VALUE linespace, VALUE tbattr, VALUE text)
{
  CPDFdoc *CPDFdocPtr;
  CPDFtboxAttr tbA;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  Check_Type(tbattr, T_ARRAY);
  if(RARRAY(tbattr)->len != 4) {
	rb_raise(rb_eArgError, "wrong # of arguments");
  } else {
	tbA.alignmode = NUM2INT(RARRAY(tbattr)->ptr[0]);
	tbA.NLmode = NUM2INT(RARRAY(tbattr)->ptr[1]);
	tbA.paragraphSpacing = (float)NUM2DBL(RARRAY(tbattr)->ptr[2]);
	tbA.noMark = NUM2INT(RARRAY(tbattr)->ptr[3]);
  }
	return rb_str_new2(cpdf_rawTextBox(CPDFdocPtr, (float)NUM2DBL(xl), (float)NUM2DBL(yl), (float)NUM2DBL(width), (float)NUM2DBL(height), (float)NUM2DBL(angle),  (float)NUM2DBL(linespace), &tbA, STR2CSTR(text)));
}

static VALUE
clibpdf_textBoxFit(VALUE pdf, VALUE xl, VALUE yl, VALUE width, VALUE height, VALUE angle, VALUE inifontsize, VALUE fsdecrement, VALUE linespace, VALUE tbattr, VALUE text)
{
  CPDFdoc *CPDFdocPtr;
  CPDFtboxAttr tbA;
  /*CPDFtboxAttr *CPDFtboxAttrPtr;*/

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  /*Data_Get_Struct(tbattr, CPDFtboxAttr, CPDFtboxAttrPtr);*/
  Check_Type(tbattr, T_ARRAY);
  if(RARRAY(tbattr)->len != 4) {
	rb_raise(rb_eArgError, "wrong # of arguments");
  } else {
	tbA.alignmode = NUM2INT(RARRAY(tbattr)->ptr[0]);
	tbA.NLmode = NUM2INT(RARRAY(tbattr)->ptr[1]);
	tbA.paragraphSpacing = (float)NUM2DBL(RARRAY(tbattr)->ptr[2]);
	tbA.noMark = NUM2INT(RARRAY(tbattr)->ptr[3]);
  }
  return rb_float_new(cpdf_textBoxFit(CPDFdocPtr, (float)NUM2DBL(xl), (float)NUM2DBL(yl), (float)NUM2DBL(width), (float)NUM2DBL(height), (float)NUM2DBL(angle), (float)NUM2DBL(inifontsize), (float)NUM2DBL(fsdecrement), (float)NUM2DBL(linespace), &tbA, STR2CSTR(text)));
}

static VALUE
clibpdf_rawTextBoxFit(VALUE pdf, VALUE xl, VALUE yl, VALUE width, VALUE height, VALUE angle, VALUE inifontsize, VALUE fsdecrement, VALUE linespace, VALUE tbattr, VALUE text)
{
  CPDFdoc *CPDFdocPtr;
  CPDFtboxAttr tbA;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  Check_Type(tbattr, T_ARRAY);
  if(RARRAY(tbattr)->len != 4) {
	rb_raise(rb_eArgError, "wrong # of arguments");
  } else {
	tbA.alignmode = NUM2INT(RARRAY(tbattr)->ptr[0]);
	tbA.NLmode = NUM2INT(RARRAY(tbattr)->ptr[1]);
	tbA.paragraphSpacing = (float)NUM2DBL(RARRAY(tbattr)->ptr[2]);
	tbA.noMark = NUM2INT(RARRAY(tbattr)->ptr[3]);
  }
  return rb_float_new(cpdf_rawTextBoxFit(CPDFdocPtr, (float)NUM2DBL(xl), (float)NUM2DBL(yl), (float)NUM2DBL(width), (float)NUM2DBL(height), (float)NUM2DBL(angle), (float)NUM2DBL(inifontsize), (float)NUM2DBL(fsdecrement), (float)NUM2DBL(linespace), &tbA, STR2CSTR(text)));
}


/* primitive PDF text operator functions */
static VALUE
clibpdf_textShow(VALUE pdf, VALUE txtstr)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_textShow(CPDFdocPtr, STR2CSTR(txtstr));
  return Qnil;
}

static VALUE
clibpdf_textCRLFshow(VALUE pdf, VALUE txtstr)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_textCRLFshow(CPDFdocPtr, STR2CSTR(txtstr));
  return Qnil;
}

static VALUE
clibpdf_textCRLF(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_textCRLF(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_setNextTextLineOffset(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setNextTextLineOffset(CPDFdocPtr, NUM2DBL(x), NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rawSetNextTextLineOffset(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawSetNextTextLineOffset(CPDFdocPtr, NUM2DBL(x), NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_setTextRise(VALUE pdf, VALUE rise)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setTextRise(CPDFdocPtr, (float)NUM2DBL(rise));
  return Qnil;
}

static VALUE
clibpdf_setTextRenderingMode(VALUE pdf, VALUE mode)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setTextRenderingMode(CPDFdocPtr, NUM2INT(mode));
  return Qnil;
}

static VALUE
clibpdf_setTextMatrix(VALUE pdf, VALUE a, VALUE b, VALUE c, VALUE d, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setTextMatrix(CPDFdocPtr, (float)NUM2DBL(a), (float)NUM2DBL(b), (float)NUM2DBL(c), (float)NUM2DBL(d), (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_concatTextMatrix(VALUE pdf, VALUE a, VALUE b, VALUE c, VALUE d, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_concatTextMatrix(CPDFdocPtr, (float)NUM2DBL(a), (float)NUM2DBL(b), (float)NUM2DBL(c), (float)NUM2DBL(d), (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rotateText(VALUE pdf, VALUE degrees)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rotateText(CPDFdocPtr, (float)NUM2DBL(degrees));
  return Qnil;
}

static VALUE
clibpdf_skewText(VALUE pdf, VALUE alpha, VALUE beta)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_skewText(CPDFdocPtr, (float)NUM2DBL(alpha), (float)NUM2DBL(beta));
  return Qnil;
}

static VALUE
clibpdf_setTextPosition(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setTextPosition(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rawSetTextPosition(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawSetTextPosition(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_setTextLeading(VALUE pdf, VALUE leading)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setTextLeading(CPDFdocPtr, (float)NUM2DBL(leading));
  return Qnil;
}

static VALUE
clibpdf_setHorizontalScaling(VALUE pdf, VALUE scale)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setHorizontalScaling(CPDFdocPtr, (float)NUM2DBL(scale));
  return Qnil;
}

static VALUE
clibpdf_setCharacterSpacing(VALUE pdf, VALUE spacing)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setCharacterSpacing(CPDFdocPtr, (float)NUM2DBL(spacing));
  return Qnil;
}

static VALUE
clibpdf_setWordSpacing(VALUE pdf, VALUE spacing)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setWordSpacing(CPDFdocPtr, (float)NUM2DBL(spacing));
  return Qnil;
}

static VALUE
clibpdf_escapeSpecialChars(VALUE obj, VALUE instr)
{
  return rb_str_new2(cpdf_escapeSpecialChars(STR2CSTR(instr)));
}

/* Fonts */
static VALUE
clibpdf_setFont(VALUE pdf, VALUE basefontname, VALUE encodename, VALUE size)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if (NIL_P(encodename)) {
	return INT2NUM(cpdf_setFont(CPDFdocPtr, STR2CSTR(basefontname), NULL, (float)NUM2DBL(size)));
  } else {
	return INT2NUM(cpdf_setFont(CPDFdocPtr, STR2CSTR(basefontname), STR2CSTR(encodename), (float)NUM2DBL(size)));
  }
}

static VALUE
clibpdf_setFontDirectories(VALUE pdf, VALUE pfmdir, VALUE pfbdir)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setFontDirectories(CPDFdocPtr, STR2CSTR(pfmdir), STR2CSTR(pfbdir));
  return Qnil;
}

static VALUE
clibpdf_setFontMapFile(VALUE pdf, VALUE mapfile)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setFontMapFile(CPDFdocPtr, STR2CSTR(mapfile));
  return Qnil;
}

static VALUE
clibpdf_stringWidth(VALUE pdf, VALUE string)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return rb_float_new(cpdf_stringWidth(CPDFdocPtr, STR2CSTR(string)));
}

static VALUE
clibpdf_capHeight(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return rb_float_new(cpdf_capHeight(CPDFdocPtr));
}


/* Plot Domain functions */
static VALUE
clibpdf_createPlotDomain(VALUE obj, VALUE x, VALUE y, VALUE w, VALUE h, VALUE xL, VALUE xH, VALUE yL, VALUE yH, VALUE xtype, VALUE ytype, VALUE reserved)
{
  CPDFplotDomain *CPDFplotDomainPtr;

  CPDFplotDomainPtr = cpdf_createPlotDomain((float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(w), (float)NUM2DBL(h), (float)NUM2DBL(xL), (float)NUM2DBL(xH), (float)NUM2DBL(yL), (float)NUM2DBL(yH), NUM2INT(xtype), NUM2INT(ytype), NUM2INT(reserved));
  return Data_Wrap_Struct(cPDFplotDomain, 0, 0, CPDFplotDomainPtr);
}

static VALUE
clibpdf_createTimePlotDomain(VALUE obj, VALUE x, VALUE y, VALUE w, VALUE h, VALUE xTL, VALUE xTH, VALUE yL, VALUE yH, VALUE xtype, VALUE ytype, VALUE reserved)
{
  CPDFplotDomain *CPDFplotDomainPtr;
  struct tm tm;
  struct tm tm2;

  tm.tm_sec = NUM2INT(rb_funcall(xTL, rb_intern("sec"), 0));
  tm.tm_min = NUM2INT(rb_funcall(xTL, rb_intern("min"), 0));
  tm.tm_hour = NUM2INT(rb_funcall(xTL, rb_intern("hour"), 0));
  tm.tm_mday = NUM2INT(rb_funcall(xTL, rb_intern("mday"), 0));
  tm.tm_mon = NUM2INT(rb_funcall(xTL, rb_intern("mon"), 0)) - 1;
  tm.tm_year = NUM2INT(rb_funcall(xTL, rb_intern("year"), 0)) - 1900;
  if(rb_funcall(xTL, rb_intern("isdst"), 0) == Qtrue) {
	tm.tm_isdst = 1;
  } else {
	tm.tm_isdst = 0;
  }
/*  fprintf(stderr, "%d\n", tm.tm_sec);*/

  tm2.tm_sec = NUM2INT(rb_funcall(xTH, rb_intern("sec"), 0));
  tm2.tm_min = NUM2INT(rb_funcall(xTH, rb_intern("min"), 0));
  tm2.tm_hour = NUM2INT(rb_funcall(xTH, rb_intern("hour"), 0));
  tm2.tm_mday = NUM2INT(rb_funcall(xTH, rb_intern("mday"), 0));
  tm2.tm_mon = NUM2INT(rb_funcall(xTH, rb_intern("mon"), 0)) - 1;
  tm2.tm_year = NUM2INT(rb_funcall(xTH, rb_intern("year"), 0)) - 1900;
  if(rb_funcall(xTH, rb_intern("isdst"), 0) == Qtrue) {
	tm2.tm_isdst = 1;
  } else {
	tm2.tm_isdst = 0;
  }
  
  CPDFplotDomainPtr = cpdf_createTimePlotDomain((float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(w), (float)NUM2DBL(h), &tm, &tm2, (float)NUM2DBL(yL), (float)NUM2DBL(yH), NUM2INT(xtype), NUM2INT(ytype), NUM2INT(reserved));
  return Data_Wrap_Struct(cPDFplotDomain, 0, 0, CPDFplotDomainPtr);
}

static VALUE
clibpdf_freePlotDomain(VALUE aDomain)
{
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_freePlotDomain(CPDFplotDomainPtr);
  return Qnil;
}

static VALUE
clibpdf_setPlotDomain(VALUE aDomain, VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;
  CPDFplotDomain *CPDFplotDomainPtr;
  CPDFplotDomain *CPDFplotDomainPtr2;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  CPDFplotDomainPtr2 = cpdf_setPlotDomain(CPDFdocPtr, CPDFplotDomainPtr);
  return Data_Wrap_Struct(cPDFplotDomain, 0, 0, CPDFplotDomainPtr2);
}

static VALUE
clibpdf_setPlotDomain2(VALUE pdf, VALUE aDomain)
{
  CPDFdoc *CPDFdocPtr;
  CPDFplotDomain *CPDFplotDomainPtr;
  CPDFplotDomain *CPDFplotDomainPtr2;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  CPDFplotDomainPtr2 = cpdf_setPlotDomain(CPDFdocPtr, CPDFplotDomainPtr);
  return Data_Wrap_Struct(cPDFplotDomain, 0, 0, CPDFplotDomainPtr2);
}

static VALUE
clibpdf_clipDomain(VALUE aDomain)
{
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_clipDomain(CPDFplotDomainPtr);
  return Qnil;
}

static VALUE
clibpdf_fillDomainWithGray(VALUE aDomain, VALUE gray)
{
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_fillDomainWithGray(CPDFplotDomainPtr, (float)NUM2DBL(gray));
  return Qnil;
}

static VALUE
clibpdf_fillDomainWithRGBcolor(VALUE aDomain, VALUE r, VALUE g, VALUE b)
{
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_fillDomainWithRGBcolor(CPDFplotDomainPtr, (float)NUM2DBL(r), (float)NUM2DBL(g), (float)NUM2DBL(b));
  return Qnil;
}

static VALUE
clibpdf_setMeshColor(VALUE aDomain, VALUE meshMajorR, VALUE meshMajorG, VALUE meshMajorB, VALUE meshMinorR, VALUE meshMinorG, VALUE meshMinorB)
{
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_setMeshColor(CPDFplotDomainPtr, (float)NUM2DBL(meshMajorR), (float)NUM2DBL(meshMajorG), (float)NUM2DBL(meshMajorB), (float)NUM2DBL(meshMinorR), (float)NUM2DBL(meshMinorG), (float)NUM2DBL(meshMinorB));
  return Qnil;
}

static VALUE
clibpdf_drawMeshForDomain(VALUE aDomain)
{
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_drawMeshForDomain(CPDFplotDomainPtr);
  return Qnil;
}

static VALUE
clibpdf_setLinearMeshParams(VALUE aDomain, VALUE xy, VALUE mesh1ValMajor, VALUE intervalMajor, VALUE mesh1ValMinor, VALUE intervalMinor)
{
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(aDomain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_setLinearMeshParams(CPDFplotDomainPtr, NUM2INT(xy), (float)NUM2DBL(mesh1ValMajor), (float)NUM2DBL(intervalMajor), (float)NUM2DBL(mesh1ValMinor), (float)NUM2DBL(intervalMinor));
  return Qnil;
}

static VALUE
clibpdf_suggestMinMaxForLinearDomain(VALUE obj, VALUE vmin, VALUE vmax)
{
  float recmin, recmax;

  cpdf_suggestMinMaxForLinearDomain((float)NUM2DBL(vmin), (float)NUM2DBL(vmax), &recmin, &recmax);
  return rb_ary_new3(2, rb_float_new(recmin), rb_float_new(recmax));
}

static VALUE
clibpdf_suggestLinearDomainParams(VALUE obj, VALUE vmin, VALUE vmax)
{
  float recmin, recmax, tic1ValMajor, intervalMajor, tic1ValMinor, intervalMinor;

  cpdf_suggestLinearDomainParams((float)NUM2DBL(vmin), (float)NUM2DBL(vmax), &recmin, &recmax, &tic1ValMajor, &intervalMajor, &tic1ValMinor, &intervalMinor);
  return rb_ary_new3(2, rb_float_new(recmin), rb_float_new(recmax), rb_float_new(tic1ValMajor), rb_float_new(intervalMajor), rb_float_new(tic1ValMinor), rb_float_new(intervalMinor));
}

static VALUE
clibpdf_x_Domain2Points(VALUE pdf, VALUE x)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return rb_float_new(x_Domain2Points(CPDFdocPtr, (float)NUM2DBL(x)));
}

static VALUE
clibpdf_y_Domain2Points(VALUE pdf, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return rb_float_new(y_Domain2Points(CPDFdocPtr, (float)NUM2DBL(y)));
}

static VALUE
clibpdf_suggestTimeDomainParams(VALUE obj, VALUE xTL, VALUE xTH, VALUE recTL, VALUE recTH)
{
  
  return Qnil;
}

/* Axis functions */
static VALUE
clibpdf_createAxis(VALUE obj, VALUE angle, VALUE axislength, VALUE typeflag, VALUE valL, VALUE valH)
{
  CPDFaxis *CPDFaxisPtr;

  CPDFaxisPtr = cpdf_createAxis((float)NUM2DBL(angle), (float)NUM2DBL(axislength), NUM2INT(typeflag), (float)NUM2DBL(valL), (float)NUM2DBL(valH));
  return Data_Wrap_Struct(obj, 0, 0, CPDFaxisPtr);
}

static VALUE
clibpdf_createTimeAxis(VALUE obj, VALUE angle, VALUE axislength, VALUE typeflag, VALUE vtl, VALUE vth)
{
  CPDFaxis *CPDFaxisPtr;
  struct tm tm;
  struct tm tm2;

  int i;
  VALUE ary;

  tm.tm_sec = NUM2INT(rb_funcall(vtl, rb_intern("sec"), 0));
  tm.tm_min = NUM2INT(rb_funcall(vtl, rb_intern("min"), 0));
  tm.tm_hour = NUM2INT(rb_funcall(vtl, rb_intern("hour"), 0));
  tm.tm_mday = NUM2INT(rb_funcall(vtl, rb_intern("mday"), 0));
  tm.tm_mon = NUM2INT(rb_funcall(vtl, rb_intern("mon"), 0)) - 1;
  tm.tm_year = NUM2INT(rb_funcall(vtl, rb_intern("year"), 0)) - 1900;
  if(rb_funcall(vtl, rb_intern("isdst"), 0) == Qtrue) {
	tm.tm_isdst = 1;
  } else {
	tm.tm_isdst = 0;
  }

  tm2.tm_sec = NUM2INT(rb_funcall(vth, rb_intern("sec"), 0));
  tm2.tm_min = NUM2INT(rb_funcall(vth, rb_intern("min"), 0));
  tm2.tm_hour = NUM2INT(rb_funcall(vth, rb_intern("hour"), 0));
  tm2.tm_mday = NUM2INT(rb_funcall(vth, rb_intern("mday"), 0));
  tm2.tm_mon = NUM2INT(rb_funcall(vth, rb_intern("mon"), 0)) - 1;
  tm2.tm_year = NUM2INT(rb_funcall(vth, rb_intern("year"), 0)) - 1900;
  if(rb_funcall(vth, rb_intern("isdst"), 0) == Qtrue) {
	tm2.tm_isdst = 1;
  } else {
	tm2.tm_isdst = 0;
  }

/*  ary = rb_funcall(vtl, rb_intern("to_a"), 0);
  tm.tm_min = RARRAY(ary)->ptr[1];
  tm.tm_hour = RARRAY(ary)->ptr[2];
  tm.tm_mday = RARRAY(ary)->ptr[3];
  tm.tm_mon = RARRAY(ary)->ptr[4];
  tm.tm_year = RARRAY(ary)->ptr[5];
  tm.tm_isdst = RARRAY(ary)->ptr[8];

  ary = rb_funcall(vth, rb_intern("to_a"), 0);
  tm2.tm_min = RARRAY(ary)->ptr[1];
  tm2.tm_hour = RARRAY(ary)->ptr[2];
  tm2.tm_mday = RARRAY(ary)->ptr[3];
  tm2.tm_mon = RARRAY(ary)->ptr[4];
  tm2.tm_year = RARRAY(ary)->ptr[5];
  tm2.tm_isdst = RARRAY(ary)->ptr[8];*/

  CPDFaxisPtr = cpdf_createTimeAxis((float)NUM2DBL(angle), (float)NUM2DBL(axislength), NUM2INT(typeflag), &tm, &tm2);
  return Data_Wrap_Struct(obj, 0, 0, CPDFaxisPtr);
}

static VALUE
clibpdf_freeAxis(VALUE anAx)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_freeAxis(CPDFaxisPtr);
  return Qnil;
}

static VALUE
clibpdf_drawAxis(VALUE anAx)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_drawAxis(CPDFaxisPtr);
  return Qnil;
}

static VALUE
clibpdf_attachAxisToDomain(VALUE anAx, VALUE domain, VALUE x, VALUE y)
{
  CPDFaxis *CPDFaxisPtr;
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  Data_Get_Struct(domain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_attachAxisToDomain(CPDFaxisPtr, CPDFplotDomainPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_attachAxisToDomain2(VALUE domain, VALUE anAx, VALUE x, VALUE y)
{
  CPDFaxis *CPDFaxisPtr;
  CPDFplotDomain *CPDFplotDomainPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  Data_Get_Struct(domain, CPDFplotDomain, CPDFplotDomainPtr);
  cpdf_attachAxisToDomain(CPDFaxisPtr, CPDFplotDomainPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_setAxisLineParams(VALUE anAx, VALUE axLineWidth, VALUE ticLenMaj, VALUE ticLenMin, VALUE tickWidMaj, VALUE tickWidMin)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setAxisLineParams(CPDFaxisPtr, (float)NUM2DBL(axLineWidth), (float)NUM2DBL(ticLenMaj), (float)NUM2DBL(ticLenMin), (float)NUM2DBL(tickWidMaj), (float)NUM2DBL(tickWidMin));
  return Qnil;
}

static VALUE
clibpdf_setTicNumEnable(VALUE anAx, VALUE ticEnableMaj, VALUE ticEnableMin, VALUE numEnable)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setTicNumEnable(CPDFaxisPtr, NUM2INT(ticEnableMaj), NUM2INT(ticEnableMin), NUM2INT(numEnable));
  return Qnil;
}

static VALUE
clibpdf_setAxisTicNumLabelPosition(VALUE anAx, VALUE ticPos, VALUE numPos, VALUE horizNum, VALUE horizLabel)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setAxisTicNumLabelPosition(CPDFaxisPtr, NUM2INT(ticPos), NUM2INT(numPos), NUM2INT(horizNum), NUM2INT(horizLabel));
  return Qnil;
}

static VALUE
clibpdf_setAxisNumberFormat(VALUE anAx, VALUE format, VALUE fontName, VALUE fontSize)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setAxisNumberFormat(CPDFaxisPtr, STR2CSTR(format), STR2CSTR(fontName), (float)NUM2DBL(fontSize));
  return Qnil;
}

static VALUE
clibpdf_setTimeAxisNumberFormat(VALUE anAx, VALUE useMonName, VALUE use2DigYear, VALUE fontName, VALUE fontSize)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setTimeAxisNumberFormat(CPDFaxisPtr, NUM2INT(useMonName), NUM2INT(use2DigYear), STR2CSTR(fontName), (float)NUM2DBL(fontSize));
  return Qnil;
}

static VALUE
clibpdf_setAxisLabel(VALUE anAx, VALUE labelstring, VALUE fontName, VALUE encoding, VALUE fontSize)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setAxisLabel(CPDFaxisPtr, STR2CSTR(labelstring), STR2CSTR(fontName), STR2CSTR(encoding), (float)NUM2DBL(fontSize));
  return Qnil;
}

static VALUE
clibpdf_setLinearAxisParams(VALUE anAx, VALUE tic1ValMajor, VALUE intervalMajor, VALUE tic1ValMinor, VALUE intervalMinor)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setLinearAxisParams(CPDFaxisPtr, (float)NUM2DBL(tic1ValMajor), (float)NUM2DBL(intervalMajor), (float)NUM2DBL(tic1ValMinor), (float)NUM2DBL(intervalMinor));
  return Qnil;
}

static VALUE
clibpdf_setLogAxisTickSelector(VALUE anAx, VALUE ticselect)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setLogAxisTickSelector(CPDFaxisPtr, NUM2INT(ticselect));
  return Qnil;
}

static VALUE
clibpdf_setLogAxisNumberSelector(VALUE anAx, VALUE numselect)
{
  CPDFaxis *CPDFaxisPtr;

  Data_Get_Struct(anAx, CPDFaxis, CPDFaxisPtr);
  cpdf_setLogAxisNumberSelector(CPDFaxisPtr, NUM2INT(numselect));
  return Qnil;
}


/* Drawing and path constructions functions */
static VALUE
clibpdf_moveto(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_moveto(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_lineto(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_lineto(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rmoveto(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rmoveto(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rlineto(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rlineto(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_curveto(VALUE pdf, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE x3, VALUE y3)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_curveto(CPDFdocPtr, (float)NUM2DBL(x1), (float)NUM2DBL(y1), (float)NUM2DBL(x2), (float)NUM2DBL(y2), (float)NUM2DBL(x3), (float)NUM2DBL(y3));
  return Qnil;
}

static VALUE
clibpdf_rect(VALUE pdf, VALUE x, VALUE y, VALUE width, VALUE height)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rect(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(width), (float)NUM2DBL(height));
  return Qnil;
}

static VALUE
clibpdf_rectRotated(VALUE pdf, VALUE x, VALUE y, VALUE w, VALUE h, VALUE angle)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rectRotated(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(w), (float)NUM2DBL(h), (float)NUM2DBL(angle));
  return Qnil;
}

static VALUE
clibpdf_quickCircle(VALUE pdf, VALUE xc, VALUE yc, VALUE r)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_quickCircle(CPDFdocPtr, (float)NUM2DBL(xc), (float)NUM2DBL(yc), (float)NUM2DBL(r));
  return Qnil;
}

static VALUE
clibpdf_arc(VALUE pdf, VALUE x, VALUE y, VALUE r, VALUE sangle, VALUE eangle, VALUE moveto0)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_arc(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(r), (float)NUM2DBL(sangle), (float)NUM2DBL(eangle), NUM2INT(moveto0));
  return Qnil;
}

static VALUE
clibpdf_circle(VALUE pdf, VALUE x, VALUE y, VALUE r)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_circle(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(r));
  return Qnil;
}


/* These use raw, point-based coordinate system for (x,y) */
static VALUE
clibpdf_rawMoveto(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawMoveto(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rawLineto(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawLineto(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rawRmoveto(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawRmoveto(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rawRlineto(VALUE pdf, VALUE x, VALUE y)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawRlineto(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y));
  return Qnil;
}

static VALUE
clibpdf_rawCurveto(VALUE pdf, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE x3, VALUE y3)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawCurveto(CPDFdocPtr, (float)NUM2DBL(x1), (float)NUM2DBL(y1), (float)NUM2DBL(x2), (float)NUM2DBL(y2), (float)NUM2DBL(x3), (float)NUM2DBL(y3));
  return Qnil;
}

static VALUE
clibpdf_rawRect(VALUE pdf, VALUE x, VALUE y, VALUE width, VALUE height)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawRect(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(width), (float)NUM2DBL(height));
  return Qnil;
}

static VALUE
clibpdf_rawRectRotated(VALUE pdf, VALUE x, VALUE y, VALUE w, VALUE h, VALUE angle)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawRectRotated(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(w), (float)NUM2DBL(h), (float)NUM2DBL(angle));
  return Qnil;
}

static VALUE
clibpdf_rawQuickCircle(VALUE pdf, VALUE xc, VALUE yc, VALUE r)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawQuickCircle(CPDFdocPtr, (float)NUM2DBL(xc), (float)NUM2DBL(yc), (float)NUM2DBL(r));
  return Qnil;
}

static VALUE
clibpdf_rawArc(VALUE pdf, VALUE x, VALUE y, VALUE r, VALUE sangle, VALUE eangle, VALUE moveto0)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawArc(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(r), (float)NUM2DBL(sangle), (float)NUM2DBL(eangle), NUM2INT(moveto0));
  return Qnil;
}

static VALUE
clibpdf_rawCircle(VALUE pdf, VALUE x, VALUE y, VALUE r)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawCircle(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(r));
  return Qnil;
}

/* Operations on current path */
static VALUE
clibpdf_closepath(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_closepath(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_stroke(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_stroke(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_fill(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_fill(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_eofill(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_eofill(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_fillAndStroke(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_fillAndStroke(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_eofillAndStroke(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_eofillAndStroke(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_clip(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_clip(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_eoclip(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_eoclip(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_newpath(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_newpath(CPDFdocPtr);
  return Qnil;
}

/* Color functions */
static VALUE
clibpdf_setgray(VALUE pdf, VALUE gray)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setgray(CPDFdocPtr, (float)NUM2DBL(gray));
  return Qnil;
}

static VALUE
clibpdf_setrgbcolor(VALUE pdf, VALUE r, VALUE g, VALUE b)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setrgbcolor(CPDFdocPtr, (float)NUM2DBL(r), (float)NUM2DBL(g), (float)NUM2DBL(b));
  return Qnil;
}

static VALUE
clibpdf_setcmykcolor(VALUE pdf, VALUE c, VALUE m, VALUE y, VALUE k)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setcmykcolor(CPDFdocPtr, (float)NUM2DBL(c), (float)NUM2DBL(m), (float)NUM2DBL(y), (float)NUM2DBL(k));
  return Qnil;
}

static VALUE
clibpdf_setgrayFill(VALUE pdf, VALUE gray)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setgrayFill(CPDFdocPtr, (float)NUM2DBL(gray));
  return Qnil;
}

static VALUE
clibpdf_setgrayStroke(VALUE pdf, VALUE gray)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setgrayStroke(CPDFdocPtr, (float)NUM2DBL(gray));
  return Qnil;
}

static VALUE
clibpdf_setrgbcolorFill(VALUE pdf, VALUE r, VALUE g, VALUE b)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setrgbcolorFill(CPDFdocPtr, (float)NUM2DBL(r), (float)NUM2DBL(g), (float)NUM2DBL(b));
  return Qnil;
}

static VALUE
clibpdf_setrgbcolorStroke(VALUE pdf, VALUE r, VALUE g, VALUE b)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setrgbcolorStroke(CPDFdocPtr, (float)NUM2DBL(r), (float)NUM2DBL(g), (float)NUM2DBL(b));
  return Qnil;
}

static VALUE
clibpdf_setcmykcolorFill(VALUE pdf, VALUE c, VALUE m, VALUE y, VALUE k)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setcmykcolorFill(CPDFdocPtr, (float)NUM2DBL(c), (float)NUM2DBL(m), (float)NUM2DBL(y), (float)NUM2DBL(k));
  return Qnil;
}

static VALUE
clibpdf_setcmykcolorStroke(VALUE pdf, VALUE c, VALUE m, VALUE y, VALUE k)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setcmykcolorStroke(CPDFdocPtr, (float)NUM2DBL(c), (float)NUM2DBL(m), (float)NUM2DBL(y), (float)NUM2DBL(k));
  return Qnil;
}


/* Graphics state functions */
static VALUE
clibpdf_gsave(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_gsave(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_grestore(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_grestore(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_setdash(VALUE pdf, VALUE dashspec)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setdash(CPDFdocPtr, STR2CSTR(dashspec));
  return Qnil;
}

static VALUE
clibpdf_nodash(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_nodash(CPDFdocPtr);
  return Qnil;
}

static VALUE
clibpdf_concat(VALUE pdf, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e, VALUE f)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_concat(CPDFdocPtr, (float)NUM2DBL(a), (float)NUM2DBL(b), (float)NUM2DBL(c), (float)NUM2DBL(d), (float)NUM2DBL(e), (float)NUM2DBL(f));
  return Qnil;
}

static VALUE
clibpdf_rawConcat(VALUE pdf, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e, VALUE f)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawConcat(CPDFdocPtr, (float)NUM2DBL(a), (float)NUM2DBL(b), (float)NUM2DBL(c), (float)NUM2DBL(d), (float)NUM2DBL(e), (float)NUM2DBL(f));
  return Qnil;
}

static VALUE
clibpdf_rotate(VALUE pdf, VALUE angle)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rotate(CPDFdocPtr, (float)NUM2DBL(angle));
  return Qnil;
}

static VALUE
clibpdf_translate(VALUE pdf, VALUE xt, VALUE yt)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_translate(CPDFdocPtr, (float)NUM2DBL(xt), (float)NUM2DBL(yt));
  return Qnil;
}

static VALUE
clibpdf_rawTranslate(VALUE pdf, VALUE xt, VALUE yt)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawTranslate(CPDFdocPtr, (float)NUM2DBL(xt), (float)NUM2DBL(yt));
  return Qnil;
}

static VALUE
clibpdf_scale(VALUE pdf, VALUE sx, VALUE sy)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_scale(CPDFdocPtr, (float)NUM2DBL(sx), (float)NUM2DBL(sy));
  return Qnil;
}

static VALUE
clibpdf_setlinewidth(VALUE pdf, VALUE width)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setlinewidth(CPDFdocPtr, (float)NUM2DBL(width));
  return Qnil;
}


static VALUE
clibpdf_setflat(VALUE pdf, VALUE flatness)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setflat(CPDFdocPtr, NUM2INT(flatness));
  return Qnil;
}

static VALUE
clibpdf_setlinecap(VALUE pdf, VALUE linecap)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setlinecap(CPDFdocPtr, NUM2INT(linecap));
  return Qnil;
}

static VALUE
clibpdf_setlinejoin(VALUE pdf, VALUE linejoin)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setlinejoin(CPDFdocPtr, NUM2INT(linejoin));
  return Qnil;
}

static VALUE
clibpdf_setmiterlimit(VALUE pdf, VALUE miterlimit)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setmiterlimit(CPDFdocPtr, NUM2INT(miterlimit));
  return Qnil;
}

static VALUE
clibpdf_setstrokeadjust(VALUE pdf, VALUE flag)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setstrokeadjust(CPDFdocPtr, NUM2INT(flag));
  return Qnil;
}


/* Data point Marker funcitons */
static VALUE
clibpdf_marker(VALUE pdf, VALUE x, VALUE y, VALUE markertype, VALUE size)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_marker(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), NUM2INT(markertype), (float)NUM2DBL(size));
  return Qnil;
}

static VALUE
clibpdf_pointer(VALUE pdf, VALUE x, VALUE y, VALUE direction, VALUE size)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_pointer(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), NUM2INT(direction), (float)NUM2DBL(size));
  return Qnil;
}

static VALUE
clibpdf_errorbar(VALUE pdf, VALUE x, VALUE y1, VALUE y2, VALUE capsize)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_errorbar(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y1), (float)NUM2DBL(y2), (float)NUM2DBL(capsize));
  return Qnil;
}

static VALUE
clibpdf_highLowClose(VALUE pdf, VALUE x, VALUE vhigh, VALUE vlow, VALUE vclose, VALUE ticklen)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_highLowClose(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(vhigh), (float)NUM2DBL(vlow), (float)NUM2DBL(vclose), (float)NUM2DBL(ticklen));
  return Qnil;
}


/* raw (point-based) versions of marker and other plot symbols above */
static VALUE
clibpdf_rawMarker(VALUE pdf, VALUE x, VALUE y, VALUE markertype, VALUE size)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawMarker(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), NUM2INT(markertype), (float)NUM2DBL(size));
  return Qnil;
}

static VALUE
clibpdf_rawPointer(VALUE pdf, VALUE x, VALUE y, VALUE direction, VALUE size)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawPointer(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y), NUM2INT(direction), (float)NUM2DBL(size));
  return Qnil;
}

static VALUE
clibpdf_rawErrorbar(VALUE pdf, VALUE x, VALUE y1, VALUE y2, VALUE capsize)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawErrorbar(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(y1), (float)NUM2DBL(y2), (float)NUM2DBL(capsize));
  return Qnil;
}

static VALUE
clibpdf_rawHighLowClose(VALUE pdf, VALUE x, VALUE vhigh, VALUE vlow, VALUE vclose, VALUE ticklen)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_rawHighLowClose(CPDFdocPtr, (float)NUM2DBL(x), (float)NUM2DBL(vhigh), (float)NUM2DBL(vlow), (float)NUM2DBL(vclose), (float)NUM2DBL(ticklen));
  return Qnil;
}


/* Image related functions */
static VALUE
clibpdf_importImage(VALUE pdf, VALUE imagefile, VALUE type, VALUE x, VALUE y, VALUE angle, VALUE gsave)
{
  CPDFdoc *CPDFdocPtr;
  float width = 0.0, height = 0.0, xscale = 0.0, yscale = 0.0;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_importImage(CPDFdocPtr, STR2CSTR(imagefile), NUM2INT(type), (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(angle), &width, &height, &xscale, &yscale, NUM2INT(gsave)));
}

static VALUE
clibpdf_rawImportImage(VALUE pdf, VALUE imagefile, VALUE type, VALUE x, VALUE y, VALUE angle, VALUE gsave)
{
  CPDFdoc *CPDFdocPtr;
  float width = 0.0, height = 0.0, xscale = 0.0, yscale = 0.0;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_rawImportImage(CPDFdocPtr, STR2CSTR(imagefile), NUM2INT(type), (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(angle), &width, &height, &xscale, &yscale, NUM2INT(gsave)));
}

static VALUE
clibpdf_placeInLineImage(VALUE pdf, VALUE imagedata, VALUE x, VALUE y, VALUE angle, VALUE width, VALUE height, VALUE pixwidth, VALUE pixheight, VALUE bitspercomp, VALUE CSorMask, VALUE gsave)
{
  CPDFdoc *CPDFdocPtr;
  int *ptr;
  int i, len;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  len = RARRAY(imagedata)->len;
  ptr = ALLOCA_N(int, len);
  for(i = 0; i < len; i++) {
	ptr[i] = NUM2INT(RARRAY(imagedata)->ptr[i]);
  }
  return INT2NUM(cpdf_placeInLineImage(CPDFdocPtr, ptr, len, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(angle), (float)NUM2DBL(width), (float)NUM2DBL(height), NUM2INT(pixwidth), NUM2INT(pixheight), NUM2INT(bitspercomp), NUM2INT(CSorMask), NUM2INT(gsave)));
}

static VALUE
clibpdf_rawPlaceInLineImage(VALUE pdf, VALUE imagedata, VALUE x, VALUE y, VALUE angle, VALUE width, VALUE height, VALUE pixwidth, VALUE pixheight, VALUE bitspercomp, VALUE CSorMask, VALUE gsave)
{
  CPDFdoc *CPDFdocPtr;

  int *ptr;
  int i, len;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  len = RARRAY(imagedata)->len;
  ptr = ALLOCA_N(int, len);
  for(i = 0; i < len; i++) {
	ptr[i] = NUM2INT(RARRAY(imagedata)->ptr[i]);
  }
  return INT2NUM(cpdf_rawPlaceInLineImage(CPDFdocPtr, ptr, len, (float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(angle), (float)NUM2DBL(width), (float)NUM2DBL(height), NUM2INT(pixwidth), NUM2INT(pixheight), NUM2INT(bitspercomp), NUM2INT(CSorMask), NUM2INT(gsave)));
}


/* Memory stream:  most are in cpdfMemBuf.c */
static VALUE
clibpdf_openMemoryStream(VALUE obj)
{
  cpdf_openMemoryStream();
  return Qnil;
}

static VALUE
clibpdf_closeMemoryStream(VALUE obj, VALUE memStream)
{
  CPDFmemStream *CPDFmemStreamPtr;

  Data_Get_Struct(memStream, CPDFmemStream, CPDFmemStreamPtr);
  cpdf_closeMemoryStream(CPDFmemStreamPtr);
  return Qnil;
}

static VALUE
clibpdf_writeMemoryStream(VALUE obj, VALUE memStream, VALUE data, VALUE len)
{
  CPDFmemStream *CPDFmemStreamPtr;

  Data_Get_Struct(memStream, CPDFmemStream, CPDFmemStreamPtr);
  return INT2NUM(cpdf_writeMemoryStream(CPDFmemStreamPtr, STR2CSTR(data), NUM2INT(len)));
}

/*static VALUE
clibpdf_getMemoryBuffer(VALUE obj, VALUE memStream, VALUE *streambuf, VALUE *len, VALUE *maxlen)
{
  cpdf_getMemoryBuffer(CPDFmemStream *memStream), RSTRING()->ptr, NUM2INT(*len), NUM2INT(*maxlen));
  return Qnil;
}*/

static VALUE
clibpdf_saveMemoryStreamToFile(VALUE obj, VALUE stream, const VALUE name)
{
  CPDFmemStream *CPDFmemStreamPtr;

  Data_Get_Struct(stream, CPDFmemStream, CPDFmemStreamPtr);
  return INT2NUM(cpdf_saveMemoryStreamToFile(CPDFmemStreamPtr, STR2CSTR(name)));
}

static VALUE
clibpdf_memPutc(VALUE obj, VALUE ch, VALUE memStream)
{
  return INT2NUM(cpdf_memPutc(NUM2INT(ch), (CPDFmemStream *)memStream));
}

static VALUE
clibpdf_memPuts(VALUE obj, VALUE str, VALUE memStream)
{
  CPDFmemStream *CPDFmemStreamPtr;

  Data_Get_Struct(memStream, CPDFmemStream, CPDFmemStreamPtr);
  return INT2NUM(cpdf_memPuts(STR2CSTR(str), CPDFmemStreamPtr));
}

static VALUE
clibpdf_clearMemoryStream(VALUE obj, VALUE aMstrm)
{
  CPDFmemStream *CPDFmemStreamPtr;

  Data_Get_Struct(aMstrm, CPDFmemStream, CPDFmemStreamPtr);
  cpdf_clearMemoryStream(CPDFmemStreamPtr);
  return Qnil;
}


/* Outline (book mark) functions */
static VALUE
clibpdf_addOutlineEntry(VALUE pdf, VALUE afterThis, VALUE sublevel, VALUE open, VALUE page, VALUE title, VALUE mode, VALUE p1, VALUE p2, VALUE p3, VALUE p4)
{
  CPDFdoc *CPDFdocPtr;
  CPDFoutlineEntry *CPDFoutlineEntryPtr;
  CPDFoutlineEntry *CPDFoutlineEntryRetPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(afterThis)) {
	CPDFoutlineEntryRetPtr = cpdf_addOutlineEntry(CPDFdocPtr, NULL, NUM2INT(sublevel), NUM2INT(open), NUM2INT(page), STR2CSTR(title), NUM2INT(mode), NUM2DBL(p1), NUM2DBL(p2), NUM2DBL(p3), NUM2DBL(p4));
  } else {
	Data_Get_Struct(afterThis, CPDFoutlineEntry, CPDFoutlineEntryPtr);
	CPDFoutlineEntryRetPtr = cpdf_addOutlineEntry(CPDFdocPtr, CPDFoutlineEntryPtr, NUM2INT(sublevel), NUM2INT(open), NUM2INT(page), STR2CSTR(title), NUM2INT(mode), NUM2DBL(p1), NUM2DBL(p2), NUM2DBL(p3), NUM2DBL(p4));
  }
  return Data_Wrap_Struct(cPDFoutlineEntry, 0, 0, CPDFoutlineEntryRetPtr);
}

static VALUE
clibpdf_addOutlineAction(VALUE pdf, VALUE afterThis, VALUE sublevel, VALUE open, VALUE action_dict, VALUE title)
{
  CPDFdoc *CPDFdocPtr;
  CPDFoutlineEntry *CPDFoutlineEntryPtr;
  CPDFoutlineEntry *CPDFoutlineEntryRetPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  if(NIL_P(afterThis)) {
	CPDFoutlineEntryRetPtr = cpdf_addOutlineAction(CPDFdocPtr, NULL, NUM2INT(sublevel), NUM2INT(open), STR2CSTR(action_dict), STR2CSTR(title));
  } else {
	Data_Get_Struct(afterThis, CPDFoutlineEntry, CPDFoutlineEntryPtr);
	CPDFoutlineEntryRetPtr = cpdf_addOutlineAction(CPDFdocPtr, CPDFoutlineEntryPtr, NUM2INT(sublevel), NUM2INT(open), STR2CSTR(action_dict), STR2CSTR(title));
  }
  return Data_Wrap_Struct(cPDFoutlineEntry, 0, 0, CPDFoutlineEntryRetPtr);
}


/* Misc functions */
static VALUE
clibpdf_setDocumentID(VALUE pdf, VALUE documentID)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return INT2NUM(cpdf_setDocumentID(CPDFdocPtr, NUM2INT(documentID)));
}

static VALUE
clibpdf_setPDFLevel(VALUE pdf, VALUE major, VALUE minor)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setPDFLevel(CPDFdocPtr, NUM2INT(major), NUM2INT(minor));
  return Qnil;
}

static VALUE
clibpdf_useStdout(VALUE pdf, VALUE flag)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_useStdout(CPDFdocPtr, NUM2INT(flag));
  return Qnil;
}

static VALUE
clibpdf_getOutputFilename(VALUE pdf)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  return rb_str_new2(cpdf_getOutputFilename(CPDFdocPtr));
}

static VALUE
clibpdf_setOutputFilename(VALUE pdf, VALUE file)
{
  CPDFdoc *CPDFdocPtr;

  Data_Get_Struct(pdf, CPDFdoc, CPDFdocPtr);
  cpdf_setOutputFilename(CPDFdocPtr, STR2CSTR(file));
  return Qnil;
}

static VALUE
clibpdf_tm_to_NumDays(VALUE obj, VALUE fromDate, VALUE toDate)
{
  struct tm tm;
  struct tm tm2;

  tm.tm_sec = NUM2INT(rb_funcall(fromDate, rb_intern("sec"), 0));
  tm.tm_min = NUM2INT(rb_funcall(fromDate, rb_intern("min"), 0));
  tm.tm_hour = NUM2INT(rb_funcall(fromDate, rb_intern("hour"), 0));
  tm.tm_mday = NUM2INT(rb_funcall(fromDate, rb_intern("mday"), 0));
  tm.tm_mon = NUM2INT(rb_funcall(fromDate, rb_intern("mon"), 0)) - 1;
  tm.tm_year = NUM2INT(rb_funcall(fromDate, rb_intern("year"), 0)) - 1900;
  if(rb_funcall(fromDate, rb_intern("isdst"), 0) == Qtrue) {
	tm.tm_isdst = 1;
  } else {
	tm.tm_isdst = 0;
  }

  tm2.tm_sec = NUM2INT(rb_funcall(toDate, rb_intern("sec"), 0));
  tm2.tm_min = NUM2INT(rb_funcall(toDate, rb_intern("min"), 0));
  tm2.tm_hour = NUM2INT(rb_funcall(toDate, rb_intern("hour"), 0));
  tm2.tm_mday = NUM2INT(rb_funcall(toDate, rb_intern("mday"), 0));
  tm2.tm_mon = NUM2INT(rb_funcall(toDate, rb_intern("mon"), 0)) - 1;
  tm2.tm_year = NUM2INT(rb_funcall(toDate, rb_intern("year"), 0)) - 1900;
  if(rb_funcall(toDate, rb_intern("isdst"), 0) == Qtrue) {
	tm2.tm_isdst = 1;
  } else {
	tm2.tm_isdst = 0;
  }
  return rb_float_new(tm_to_NumDays(&tm, &tm2));
}

static VALUE
clibpdf_rotate_xyCoordinate(VALUE obj, VALUE x, VALUE y, VALUE angle)
{
  float xrot, yrot;

  rotate_xyCoordinate((float)NUM2DBL(x), (float)NUM2DBL(y), (float)NUM2DBL(angle), &xrot, &yrot);
  return rb_ary_new3(2, rb_float_new(xrot), rb_float_new(yrot));
}

/*static VALUE
clibpdf_setMonthNames(VALUE obj, VALUE mnArray)
{
  return INT2NUM(cpdf_setMonthNames((char *)RARRAY(mnArray)->ptr));
}*/


void
Init_ClibPDF()
{
  int i;
  VALUE ary;

  mClibPDF = rb_define_module("ClibPDF");
  rb_define_module_function(mClibPDF, "version", clibpdf_version, 0);
  rb_define_module_function(mClibPDF, "platform", clibpdf_platform, 0);

  cTBOX = rb_define_class_under(mClibPDF, "TBOX", rb_cObject);
  rb_define_singleton_method(cTBOX, "new", clibpdf_tbox_new, -2);
/*    rb_define_method(cTBOX, "alignmode", clibpdf_tbox_alignmode, 1);*/

  cPDF = rb_define_class_under(mClibPDF, "PDF", rb_cObject);
  rb_define_singleton_method(cPDF, "open", clibpdf_open, -2);
  rb_define_singleton_method(cPDF, "new", clibpdf_open, -2);

  rb_define_method(cPDF, "setGlobalDocumentLimits", clibpdf_setGlobalDocumentLimits, 5);
  rb_define_method(cPDF, "setViewerPreferences", clibpdf_setViewerPreferences, 1);

  rb_define_method(cPDF, "enableCompression", clibpdf_enableCompression, 1);
  rb_define_method(cPDF, "useContentMemStream", clibpdf_useContentMemStream, 1);
  rb_define_method(cPDF, "setCompressionFilter", clibpdf_setCompressionFilter, 2);
  rb_define_method(cPDF, "setDefaultDomainUnit", clibpdf_setDefaultDomainUnit, 1);
  rb_define_method(cPDF, "init", clibpdf_init, 0);
  rb_define_method(cPDF, "pageInit", clibpdf_pageInit, 4);
  rb_define_method(cPDF, "finalizeAll", clibpdf_finalizeAll, 0);
  rb_define_method(cPDF, "savePDFmemoryStreamToFile", clibpdf_savePDFmemoryStreamToFile, 1);
  rb_define_method(cPDF, "getBufferForPDF", clibpdf_getBufferForPDF, 0);
  rb_define_method(cPDF, "close", clibpdf_close, 0);
  rb_define_method(cPDF, "launchPreview", clibpdf_launchPreview, 0);
  rb_define_method(cPDF, "openPDFfileInViewer", clibpdf_openPDFfileInViewer, 1);
  rb_define_method(cPDF, "setCreator", clibpdf_setCreator, 1);
  rb_define_method(cPDF, "setTitle", clibpdf_setTitle, 1);
  rb_define_method(cPDF, "setSubject", clibpdf_setSubject, 1);
  rb_define_method(cPDF, "setKeywords", clibpdf_setKeywords, 1);
  rb_define_method(cPDF, "comments", clibpdf_comments, 1);

  /* Page related public functions */
  rb_define_method(cPDF, "setCurrentPage", clibpdf_setCurrentPage, 1);
  rb_define_method(cPDF, "finalizePage", clibpdf_finalizePage, 1);
  rb_define_method(cPDF, "setPageSize", clibpdf_setPageSize, 2);
  rb_define_method(cPDF, "setBoundingBox", clibpdf_setBoundingBox, 4);
  rb_define_method(cPDF, "setMediaBox", clibpdf_setMediaBox, 4);
  rb_define_method(cPDF, "setCropBox", clibpdf_setCropBox, 4);

  /* page duration and transition */
  rb_define_method(cPDF, "setPageDuration", clibpdf_setPageDuration, 1);
  rb_define_method(cPDF, "setPageTransition", clibpdf_setPageTransition, 5);

  /* Annotation and hyper link functions */
  rb_define_method(cPDF, "setAnnotation", clibpdf_setAnnotation, 6);
  rb_define_method(cPDF, "setActionURL", clibpdf_setActionURL, 5);
  rb_define_method(cPDF, "setLinkAction", clibpdf_setLinkAction, 6);
  rb_define_method(cPDF, "rawSetLinkGoToPage", clibpdf_rawSetLinkGoToPage, 7);
  rb_define_method(cPDF, "rawSetAnnotation", clibpdf_rawSetAnnotation, 6);
  rb_define_method(cPDF, "rawSetActionURL", clibpdf_rawSetActionURL, 6);
  rb_define_method(cPDF, "rawSetLinkAction", clibpdf_rawSetLinkAction, 6);
  rb_define_method(cPDF, "includeTextFileAsAnnotation", clibpdf_includeTextFileAsAnnotation, 6);
  rb_define_method(cPDF, "rawIncludeTextFileAsAnnotation", clibpdf_rawIncludeTextFileAsAnnotation, 6);

  /* ==== Text and Font functions ================================================ */
  rb_define_method(cPDF, "beginText", clibpdf_beginText, 1);
  rb_define_method(cPDF, "endText", clibpdf_endText, 0);

  /* convenient text functions */
  rb_define_method(cPDF, "text", clibpdf_text, 4);
  rb_define_method(cPDF, "rawText", clibpdf_rawText, 4);
  rb_define_method(cPDF, "textAligned", clibpdf_textAligned, 5);
  rb_define_method(cPDF, "rawTextAligned", clibpdf_rawTextAligned, 5);
  rb_define_method(cPDF, "textBox", clibpdf_textBox, 8);
  rb_define_method(cPDF, "rawTextBox", clibpdf_rawTextBox, 8);
  rb_define_method(cPDF, "textBoxFit", clibpdf_textBoxFit, 10);
  rb_define_method(cPDF, "rawTextBoxFit", clibpdf_rawTextBoxFit, 10);

  /* primitive PDF text operator functions */
  rb_define_method(cPDF, "textShow", clibpdf_textShow, 1);
  rb_define_method(cPDF, "textCRLFshow", clibpdf_textCRLFshow, 1);
  rb_define_method(cPDF, "textCRLF", clibpdf_textCRLF, 1);
  rb_define_method(cPDF, "setNextTextLineOffset", clibpdf_setNextTextLineOffset, 2);
  rb_define_method(cPDF, "rawSetNextTextLineOffset", clibpdf_rawSetNextTextLineOffset, 2);
  rb_define_method(cPDF, "setTextRise", clibpdf_setTextRise, 1);
  rb_define_method(cPDF, "setTextRenderingMode", clibpdf_setTextRenderingMode, 1);
  rb_define_method(cPDF, "setTextMatrix", clibpdf_setTextMatrix, 6);
  rb_define_method(cPDF, "concatTextMatrix", clibpdf_concatTextMatrix, 6);
  rb_define_method(cPDF, "rotateText", clibpdf_rotateText, 1);
  rb_define_method(cPDF, "skewText", clibpdf_skewText, 2);
  rb_define_method(cPDF, "setTextPosition", clibpdf_setTextPosition, 2);
  rb_define_method(cPDF, "rawSetTextPosition", clibpdf_rawSetTextPosition, 2);
  rb_define_method(cPDF, "setTextLeading", clibpdf_setTextLeading, 1);
  rb_define_method(cPDF, "setHorizontalScaling", clibpdf_setHorizontalScaling, 1);
  rb_define_method(cPDF, "setCharacterSpacing", clibpdf_setCharacterSpacing, 1);
  rb_define_method(cPDF, "setWordSpacing", clibpdf_setWordSpacing, 1);
  rb_define_module_function(mClibPDF, "escapeSpecialChars", clibpdf_escapeSpecialChars, 1);

  /* Fonts */
  rb_define_method(cPDF, "setFont", clibpdf_setFont, 3);
  rb_define_method(cPDF, "setFontDirectories", clibpdf_setFontDirectories, 2);
  rb_define_method(cPDF, "setFontMapFile", clibpdf_setFontMapFile, 1);
  rb_define_method(cPDF, "stringWidth", clibpdf_stringWidth, 1);
  rb_define_method(cPDF, "capHeight", clibpdf_capHeight, 0);
   /*    rb_define_module_function(mClibPDF, "multiplyCTM", clibpdf_multiplyCTM, 2);*/

  /* Plot Domain functions */
  cPDFplotDomain = rb_define_class_under(mClibPDF, "PlotDomain", rb_cObject);
  rb_define_singleton_method(cPDFplotDomain, "new", clibpdf_createPlotDomain, 11);
  cPDFtimeplotDomain = rb_define_class_under(mClibPDF, "TimePlotDomain", cPDFplotDomain);
  rb_define_singleton_method(cPDFtimeplotDomain, "new", clibpdf_createTimePlotDomain, 11);
  rb_define_method(cPDFplotDomain, "freePlotDomain", clibpdf_freePlotDomain, 0);
  rb_define_method(cPDFplotDomain, "setPlotDomain", clibpdf_setPlotDomain, 1);
  rb_define_method(cPDF, "setPlotDomain", clibpdf_setPlotDomain2, 1);
  rb_define_method(cPDFplotDomain, "clipDomain", clibpdf_clipDomain, 0);
  rb_define_method(cPDFplotDomain, "fillDomainWithGray", clibpdf_fillDomainWithGray, 1);
  rb_define_method(cPDFplotDomain, "fillDomainWithRGBcolor", clibpdf_fillDomainWithRGBcolor, 3);
  rb_define_method(cPDFplotDomain, "setMeshColor", clibpdf_setMeshColor, 6);
  rb_define_method(cPDFplotDomain, "drawMeshForDomain", clibpdf_drawMeshForDomain, 0);
  rb_define_method(cPDFplotDomain, "setLinearMeshParams", clibpdf_setLinearMeshParams, 5);
  rb_define_module_function(mClibPDF, "suggestMinMaxForLinearDomain", clibpdf_suggestMinMaxForLinearDomain, 2);
  rb_define_module_function(mClibPDF, "suggestLinearDomainParams", clibpdf_suggestLinearDomainParams, 8);
  rb_define_method(cPDF, "x_Domain2Points", clibpdf_x_Domain2Points, 1);
  rb_define_method(cPDF, "y_Domain2Points", clibpdf_y_Domain2Points, 1);
  rb_define_module_function(mClibPDF, "suggestTimeDomainParams", clibpdf_suggestTimeDomainParams, 2);

  /* Axis functions */
  cPDFaxis = rb_define_class_under(mClibPDF, "Axis", rb_cObject);
  rb_define_singleton_method(cPDFaxis, "new", clibpdf_createAxis, 5);
  cPDFtimeaxis = rb_define_class_under(mClibPDF, "TimeAxis", cPDFaxis);
  rb_define_singleton_method(cPDFtimeaxis, "new", clibpdf_createTimeAxis, 5);
  rb_define_method(cPDFaxis, "freeAxis", clibpdf_freeAxis, 0);
  rb_define_method(cPDFaxis, "drawAxis", clibpdf_drawAxis, 0);
  rb_define_method(cPDFaxis, "attachAxisToDomain", clibpdf_attachAxisToDomain, 3);
  rb_define_method(cPDFplotDomain, "attachAxisToDomain", clibpdf_attachAxisToDomain2, 3);
  rb_define_method(cPDFaxis, "setAxisLineParams", clibpdf_setAxisLineParams, 5);
  rb_define_method(cPDFaxis, "setTicNumEnable", clibpdf_setTicNumEnable, 3);
  rb_define_method(cPDFaxis, "setAxisTicNumLabelPosition", clibpdf_setAxisTicNumLabelPosition, 4);
  rb_define_method(cPDFaxis, "setAxisNumberFormat", clibpdf_setAxisNumberFormat, 3);
  rb_define_method(cPDFaxis, "setTimeAxisNumberFormat", clibpdf_setTimeAxisNumberFormat, 4);
  rb_define_method(cPDFaxis, "setAxisLabel", clibpdf_setAxisLabel, 4);
  rb_define_method(cPDFaxis, "setLinearAxisParams", clibpdf_setLinearAxisParams, 4);
  rb_define_method(cPDFaxis, "setLogAxisTickSelector", clibpdf_setLogAxisTickSelector, 1);
  rb_define_method(cPDFaxis, "setLogAxisNumberSelector", clibpdf_setLogAxisNumberSelector, 1);

  /* Drawing and path constructions functions */
  /* These functions use current (scaled linear or log) coordinate system for (x, y) */
  rb_define_method(cPDF, "moveto", clibpdf_moveto, 2);
  rb_define_method(cPDF, "lineto", clibpdf_lineto, 2);
  rb_define_method(cPDF, "rmoveto", clibpdf_rmoveto, 2);
  rb_define_method(cPDF, "rlineto", clibpdf_rlineto, 2);
  rb_define_method(cPDF, "curveto", clibpdf_curveto, 6);
  rb_define_method(cPDF, "rect", clibpdf_rect, 4);
  rb_define_method(cPDF, "rectRotated", clibpdf_rectRotated, 5);
  rb_define_method(cPDF, "quickCircle", clibpdf_quickCircle, 3);
  rb_define_method(cPDF, "arc", clibpdf_arc, 6);
  rb_define_method(cPDF, "circle", clibpdf_circle, 3);

  /* These use raw, point-based coordinate system for (x,y) */
  rb_define_method(cPDF, "rawMoveto", clibpdf_rawMoveto, 2);
  rb_define_method(cPDF, "rawLineto", clibpdf_rawLineto, 2);
  rb_define_method(cPDF, "rawRmoveto", clibpdf_rawRmoveto, 2);
  rb_define_method(cPDF, "rawRlineto", clibpdf_rawRlineto, 2);
  rb_define_method(cPDF, "rawCurveto", clibpdf_rawCurveto, 6);
  rb_define_method(cPDF, "rawRect", clibpdf_rawRect, 4);
  rb_define_method(cPDF, "rawRectRotated", clibpdf_rawRectRotated, 5);
  rb_define_method(cPDF, "rawQuickCircle", clibpdf_rawQuickCircle, 3);
  rb_define_method(cPDF, "rawArc", clibpdf_rawArc, 6);
  rb_define_method(cPDF, "rawCircle", clibpdf_rawCircle, 3);

  /* Operations on current path */
  rb_define_method(cPDF, "closepath", clibpdf_closepath, 0);
  rb_define_method(cPDF, "stroke", clibpdf_stroke, 0);
  rb_define_method(cPDF, "fill", clibpdf_fill, 0);
  rb_define_method(cPDF, "eofill", clibpdf_eofill, 0);
  rb_define_method(cPDF, "fillAndStroke", clibpdf_fillAndStroke, 0);
  rb_define_method(cPDF, "eofillAndStroke", clibpdf_eofillAndStroke, 0);
  rb_define_method(cPDF, "clip", clibpdf_clip, 0);
  rb_define_method(cPDF, "eoclip", clibpdf_eoclip, 0);
  rb_define_method(cPDF, "newpath", clibpdf_newpath, 0);

  /* Color functions */
  rb_define_method(cPDF, "setgray", clibpdf_setgray, 1);
  rb_define_method(cPDF, "setrgbcolor", clibpdf_setrgbcolor, 3);
  rb_define_method(cPDF, "setcmykcolor", clibpdf_setcmykcolor, 4);
  rb_define_method(cPDF, "setgrayFill", clibpdf_setgrayFill, 1);
  rb_define_method(cPDF, "setgrayStroke", clibpdf_setgrayStroke, 1);
  rb_define_method(cPDF, "setrgbcolorFill", clibpdf_setrgbcolorFill, 3);
  rb_define_method(cPDF, "setrgbcolorStroke", clibpdf_setrgbcolorStroke, 3);
  rb_define_method(cPDF, "setcmykcolorFill", clibpdf_setcmykcolorFill, 4);
  rb_define_method(cPDF, "setcmykcolorStroke", clibpdf_setcmykcolorStroke, 4);

  /* Graphics state functions */
  rb_define_method(cPDF, "gsave", clibpdf_gsave, 0);
  rb_define_method(cPDF, "grestore", clibpdf_grestore, 0);
  rb_define_method(cPDF, "setdash", clibpdf_setdash, 1);
  rb_define_method(cPDF, "nodash", clibpdf_nodash, 0);
  rb_define_method(cPDF, "concat", clibpdf_concat, 6);
  rb_define_method(cPDF, "rawConcat", clibpdf_rawConcat, 6);
  rb_define_method(cPDF, "rotate", clibpdf_rotate, 1);
  rb_define_method(cPDF, "translate", clibpdf_translate, 2);
  rb_define_method(cPDF, "rawTranslate", clibpdf_rawTranslate, 2);
  rb_define_method(cPDF, "scale", clibpdf_scale, 2);
  rb_define_method(cPDF, "setlinewidth", clibpdf_setlinewidth, 1);
  rb_define_method(cPDF, "setflat", clibpdf_setflat, 1);
  rb_define_method(cPDF, "setlinejoin", clibpdf_setlinejoin, 1);
  rb_define_method(cPDF, "setlinecap", clibpdf_setlinecap, 1);
  rb_define_method(cPDF, "setmiterlimit", clibpdf_setmiterlimit, 1);
  rb_define_method(cPDF, "setstrokeadjust", clibpdf_setstrokeadjust, 1);

  /* Data point Marker funcitons */
  rb_define_method(cPDF, "marker", clibpdf_marker, 4);
  rb_define_method(cPDF, "pointer", clibpdf_pointer, 4);
  rb_define_method(cPDF, "errorbar", clibpdf_errorbar, 4);
  rb_define_method(cPDF, "highLowClose", clibpdf_highLowClose, 5);

  /* raw (point-based) versions of marker and other plot symbols above */
  rb_define_method(cPDF, "rawMarker", clibpdf_rawMarker, 4);
  rb_define_method(cPDF, "rawPointer", clibpdf_rawPointer, 4);
  rb_define_method(cPDF, "rawErrorbar", clibpdf_rawErrorbar, 4);
  rb_define_method(cPDF, "rawHighLowClose", clibpdf_rawHighLowClose, 5);

  /* Image related functions */
  rb_define_method(cPDF, "rawImportImage", clibpdf_rawImportImage, 6);
  rb_define_method(cPDF, "importImage", clibpdf_importImage, 6);
  rb_define_method(cPDF, "placeInLineImage", clibpdf_placeInLineImage, 11);
  rb_define_method(cPDF, "rawPlaceInLineImage", clibpdf_rawPlaceInLineImage, 11);

  /* Memory stream:  most are in cpdfMemBuf.c */
  rb_define_module_function(mClibPDF, "openMemoryStream", clibpdf_openMemoryStream, 0);
  rb_define_module_function(mClibPDF, "closeMemoryStream", clibpdf_closeMemoryStream, 1);
  rb_define_module_function(mClibPDF, "writeMemoryStream", clibpdf_writeMemoryStream, 3);
   /*    rb_define_module_function(mClibPDF, "getMemoryBuffer", clibpdf_getMemoryBuffer, 4);*/
  rb_define_module_function(mClibPDF, "saveMemoryStreamToFile", clibpdf_saveMemoryStreamToFile, 2);
  rb_define_module_function(mClibPDF, "memPutc", clibpdf_memPutc, 2);
  rb_define_module_function(mClibPDF, "memPuts", clibpdf_memPuts, 2);
  rb_define_module_function(mClibPDF, "clearMemoryStream", clibpdf_clearMemoryStream, 1);

  /* Outline (book mark) functions */
  rb_define_method(cPDF, "addOutlineEntry", clibpdf_addOutlineEntry, 10);
  rb_define_method(cPDF, "addOutlineAction", clibpdf_addOutlineAction, 5);

  /* Misc functions */
  rb_define_method(cPDF, "setDocumentID", clibpdf_setDocumentID, 1);
  rb_define_method(cPDF, "setPDFLevel", clibpdf_setPDFLevel, 2);
  rb_define_method(cPDF, "useStdout", clibpdf_useStdout, 1);
  rb_define_method(cPDF, "getOutputFilename", clibpdf_getOutputFilename, 0);
  rb_define_method(cPDF, "setOutputFilename", clibpdf_setOutputFilename, 1);
  rb_define_module_function(mClibPDF, "tm_to_NumDays", clibpdf_tm_to_NumDays, 2);
   /*    rb_define_module_function(mClibPDF, "setMonthNames", clibpdf_setMonthNames, 1);*/
  rb_define_module_function(mClibPDF, "rotate_xyCoordinate", clibpdf_rotate_xyCoordinate, 3);


  rb_define_const(mClibPDF, "NMAXOBJECTS", INT2NUM(NMAXOBJECTS));
  rb_define_const(mClibPDF, "NMAXFONTS", INT2NUM(NMAXFONTS));
  rb_define_const(mClibPDF, "NMAXPAGES", INT2NUM(NMAXPAGES));
  rb_define_const(mClibPDF, "NMAXIMAGES", INT2NUM(NMAXIMAGES));
  rb_define_const(mClibPDF, "NMAXANNOTS", INT2NUM(NMAXANNOTS));

  rb_define_const(mClibPDF, "PI", INT2NUM(PI));

  rb_define_const(mClibPDF, "YES", INT2NUM(YES));
  rb_define_const(mClibPDF, "NO", INT2NUM(NO));

  rb_define_const(mClibPDF, "LINEAR", INT2NUM(LINEAR));
  rb_define_const(mClibPDF, "LOGARITHMIC", INT2NUM(LOGARITHMIC));
  rb_define_const(mClibPDF, "TIME", INT2NUM(TIME));

  rb_define_const(mClibPDF, "MONTH_NUMBER", INT2NUM(MONTH_NUMBER));
  rb_define_const(mClibPDF, "MONTH_NAME", INT2NUM(MONTH_NAME));
  rb_define_const(mClibPDF, "YEAR_FULL", INT2NUM(YEAR_FULL));
  rb_define_const(mClibPDF, "YEAR_4DIGIT", INT2NUM(YEAR_4DIGIT));
  rb_define_const(mClibPDF, "YEAR_2DIGIT", INT2NUM(YEAR_2DIGIT));

  rb_define_const(mClibPDF, "X_MESH", INT2NUM(X_MESH));
  rb_define_const(mClibPDF, "Y_MESH", INT2NUM(Y_MESH));

  rb_define_const(mClibPDF, "PORTRAIT", INT2NUM(PORTRAIT));
  rb_define_const(mClibPDF, "LANDSCAPE", INT2NUM(LANDSCAPE));
  rb_define_const(mClibPDF, "ALTLANDSCAPE", INT2NUM(ALTLANDSCAPE));

  rb_define_const(mClibPDF, "INCH", INT2NUM(inch));
  rb_define_const(mClibPDF, "CM", INT2NUM(cm));
  rb_define_const(mClibPDF, "POINTSPERINCH", INT2NUM(POINTSPERINCH));
  rb_define_const(mClibPDF, "POINTSPERCM", INT2NUM(POINTSPERCM));
  rb_define_const(mClibPDF, "POINTSPERMM", INT2NUM(POINTSPERMM));
  rb_define_const(mClibPDF, "FONTSIZE2HEIGHT", INT2NUM(FONTSIZE2HEIGHT));

  rb_define_const(mClibPDF, "LETTER", rb_str_new2(LETTER));
  rb_define_const(mClibPDF, "LEGAL", rb_str_new2(LEGAL));
  rb_define_const(mClibPDF, "A4", rb_str_new2(A4));
  rb_define_const(mClibPDF, "B5", rb_str_new2(B5));
  rb_define_const(mClibPDF, "C5", rb_str_new2(C5));
  rb_define_const(mClibPDF, "DL", rb_str_new2(DL));
  rb_define_const(mClibPDF, "EXECUTIVE", rb_str_new2(EXECUTIVE));
  rb_define_const(mClibPDF, "COMM10", rb_str_new2(COMM10));
  rb_define_const(mClibPDF, "MONARCH", rb_str_new2(MONARCH));
  rb_define_const(mClibPDF, "FILM35MM", rb_str_new2(FILM35MM));

  rb_define_const(mClibPDF, "DEFAULT_PAGESIZE", rb_str_new2(DEFAULT_PAGESIZE));

  rb_define_const(mClibPDF, "LOGAXSEL_1", INT2NUM(LOGAXSEL_1));
  rb_define_const(mClibPDF, "LOGAXSEL_13", INT2NUM(LOGAXSEL_13));
  rb_define_const(mClibPDF, "LOGAXSEL_125", INT2NUM(LOGAXSEL_125));
  rb_define_const(mClibPDF, "LOGAXSEL_12468", INT2NUM(LOGAXSEL_12468));
  rb_define_const(mClibPDF, "LOGAXSEL_12357", INT2NUM(LOGAXSEL_12357));
  rb_define_const(mClibPDF, "LOGAXSEL_123456789", INT2NUM(LOGAXSEL_123456789));
  rb_define_const(mClibPDF, "LOGAXSEL_MIN", INT2NUM(LOGAXSEL_MIN));
  rb_define_const(mClibPDF, "LOGAXSEL_MAX", INT2NUM(LOGAXSEL_MAX));

  rb_define_const(mClibPDF, "TEXT_FILL", INT2NUM(TEXT_FILL));
  rb_define_const(mClibPDF, "TEXT_STROKE", INT2NUM(TEXT_STROKE));
  rb_define_const(mClibPDF, "TEXT_FILL_STROKE", INT2NUM(TEXT_FILL_STROKE));
  rb_define_const(mClibPDF, "TEXT_INVISIBLE", INT2NUM(TEXT_INVISIBLE));
  rb_define_const(mClibPDF, "TEXT_FILL_CLIP", INT2NUM(TEXT_FILL_CLIP));
  rb_define_const(mClibPDF, "TEXT_STROKE_CLIP", INT2NUM(TEXT_STROKE_CLIP));
  rb_define_const(mClibPDF, "TEXT_FILL_STROKE_CLIP", INT2NUM(TEXT_FILL_STROKE_CLIP));
  rb_define_const(mClibPDF, "TEXT_CLIP", INT2NUM(TEXT_CLIP));

  rb_define_const(mClibPDF, "TEXTPOS_LL", INT2NUM(TEXTPOS_LL));
  rb_define_const(mClibPDF, "TEXTPOS_LM", INT2NUM(TEXTPOS_LM));
  rb_define_const(mClibPDF, "TEXTPOS_LR", INT2NUM(TEXTPOS_LR));
  rb_define_const(mClibPDF, "TEXTPOS_ML", INT2NUM(TEXTPOS_ML));
  rb_define_const(mClibPDF, "TEXTPOS_MM", INT2NUM(TEXTPOS_MM));
  rb_define_const(mClibPDF, "TEXTPOS_MR", INT2NUM(TEXTPOS_MR));
  rb_define_const(mClibPDF, "TEXTPOS_UL", INT2NUM(TEXTPOS_UL));
  rb_define_const(mClibPDF, "TEXTPOS_UM", INT2NUM(TEXTPOS_UM));
  rb_define_const(mClibPDF, "TEXTPOS_UR", INT2NUM(TEXTPOS_UR));

  rb_define_const(mClibPDF, "IMAGE_MASK", INT2NUM(IMAGE_MASK));
  rb_define_const(mClibPDF, "CS_GRAY", INT2NUM(CS_GRAY));
  rb_define_const(mClibPDF, "CS_RGB", INT2NUM(CS_RGB));
  rb_define_const(mClibPDF, "CS_CMYK", INT2NUM(CS_CMYK));

  rb_define_const(mClibPDF, "PTR_RIGHT", INT2NUM(PTR_RIGHT));
  rb_define_const(mClibPDF, "PTR_DOWN", INT2NUM(PTR_DOWN));
  rb_define_const(mClibPDF, "PTR_LEFT", INT2NUM(PTR_LEFT));
  rb_define_const(mClibPDF, "PTR_UP", INT2NUM(PTR_UP));

  rb_define_const(mClibPDF, "TRANS_NONE", INT2NUM(TRANS_NONE));
  rb_define_const(mClibPDF, "TRANS_SPLIT", INT2NUM(TRANS_SPLIT));
  rb_define_const(mClibPDF, "TRANS_BLINDS", INT2NUM(TRANS_BLINDS));
  rb_define_const(mClibPDF, "TRANS_BOX", INT2NUM(TRANS_BOX));
  rb_define_const(mClibPDF, "TRANS_WIPE", INT2NUM(TRANS_WIPE));
  rb_define_const(mClibPDF, "TRANS_DISSOLVE", INT2NUM(TRANS_DISSOLVE));
  rb_define_const(mClibPDF, "TRANS_GLITTER", INT2NUM(TRANS_GLITTER));

  rb_define_const(mClibPDF, "TBOX_LEFT", INT2NUM(TBOX_LEFT));
  rb_define_const(mClibPDF, "TBOX_CENTER", INT2NUM(TBOX_CENTER));
  rb_define_const(mClibPDF, "TBOX_RIGHT", INT2NUM(TBOX_RIGHT));
  rb_define_const(mClibPDF, "TBOX_JUSTIFY", INT2NUM(TBOX_JUSTIFY));

  rb_define_const(mClibPDF, "PM_NONE", INT2NUM(PM_NONE));
  rb_define_const(mClibPDF, "PM_OUTLINES", INT2NUM(PM_OUTLINES));
  rb_define_const(mClibPDF, "PM_THUMBS", INT2NUM(PM_THUMBS));
  rb_define_const(mClibPDF, "PM_FULLSCREEN", INT2NUM(PM_FULLSCREEN));

  rb_define_const(mClibPDF, "PL_SINGLE", INT2NUM(PL_SINGLE));
  rb_define_const(mClibPDF, "PL_1COLUMN", INT2NUM(PL_1COLUMN));
  rb_define_const(mClibPDF, "PL_2LCOLUMN", INT2NUM(PL_2LCOLUMN));
  rb_define_const(mClibPDF, "PL_2RCOLUMN", INT2NUM(PL_2RCOLUMN));

  rb_define_const(mClibPDF, "JPEG_IMG", INT2NUM(JPEG_IMG));
  rb_define_const(mClibPDF, "G4FAX_IMG", INT2NUM(G4FAX_IMG));
  rb_define_const(mClibPDF, "G3FAX_IMG", INT2NUM(G3FAX_IMG));
  rb_define_const(mClibPDF, "TIFF_IMG", INT2NUM(TIFF_IMG));
  rb_define_const(mClibPDF, "GIF_IMG", INT2NUM(GIF_IMG));
  rb_define_const(mClibPDF, "CPDF_IMG", INT2NUM(CPDF_IMG));

  rb_define_const(mClibPDF, "ANNOT_TEXT", INT2NUM(ANNOT_TEXT));
  rb_define_const(mClibPDF, "ANNOT_URL", INT2NUM(ANNOT_URL));
  rb_define_const(mClibPDF, "ANNOT_GOTO", INT2NUM(ANNOT_GOTO));
  rb_define_const(mClibPDF, "ANNOT_ACTION", INT2NUM(ANNOT_ACTION));

  rb_define_const(mClibPDF, "AF_INVISIBLE", INT2NUM(AF_INVISIBLE));
  rb_define_const(mClibPDF, "AF_HIDDEN", INT2NUM(AF_HIDDEN));
  rb_define_const(mClibPDF, "AF_PRINT", INT2NUM(AF_PRINT));
  rb_define_const(mClibPDF, "AF_NOZOOM", INT2NUM(AF_NOZOOM));
  rb_define_const(mClibPDF, "AF_NOROTATE", INT2NUM(AF_NOROTATE));
  rb_define_const(mClibPDF, "AF_NOVIEW", INT2NUM(AF_NOVIEW));
  rb_define_const(mClibPDF, "AF_READONLY", INT2NUM(AF_READONLY));

  rb_define_const(mClibPDF, "DEST_NULL", INT2NUM(DEST_NULL));
  rb_define_const(mClibPDF, "DEST_XYZ", INT2NUM(DEST_XYZ));
  rb_define_const(mClibPDF, "DEST_FIT", INT2NUM(DEST_FIT));
  rb_define_const(mClibPDF, "DEST_FITH", INT2NUM(DEST_FITH));
  rb_define_const(mClibPDF, "DEST_FITV", INT2NUM(DEST_FITV));
  rb_define_const(mClibPDF, "DEST_FITR", INT2NUM(DEST_FITR));
  rb_define_const(mClibPDF, "DEST_FITB", INT2NUM(DEST_FITB));
  rb_define_const(mClibPDF, "DEST_FITBH", INT2NUM(DEST_FITBH));
  rb_define_const(mClibPDF, "DEST_FITBV", INT2NUM(DEST_FITBV));

  rb_define_const(mClibPDF, "OL_SUBENT", INT2NUM(OL_SUBENT));
  rb_define_const(mClibPDF, "OL_SAME", INT2NUM(OL_SAME));
  rb_define_const(mClibPDF, "OL_OPEN", INT2NUM(OL_OPEN));
  rb_define_const(mClibPDF, "OL_CLOSED", INT2NUM(OL_CLOSED));

  rb_define_const(mClibPDF, "JOIN_MITER", INT2NUM(0));
  rb_define_const(mClibPDF, "JOIN_ROUND", INT2NUM(1));
  rb_define_const(mClibPDF, "JOIN_BEVEL", INT2NUM(2));

  rb_define_const(mClibPDF, "CAP_BUTT", INT2NUM(0));
  rb_define_const(mClibPDF, "CAP_ROUND", INT2NUM(1));
  rb_define_const(mClibPDF, "CAP_SQUARE", INT2NUM(2));

  rb_define_const(mClibPDF, "DOMAIN_MAGIC_NUMBER", INT2NUM(DOMAIN_MAGIC_NUMBER));
  rb_define_const(mClibPDF, "AXIS_MAGIC_NUMBER", INT2NUM(AXIS_MAGIC_NUMBER));

  i = 0;
  ary = rb_ary_new();
  do {
	rb_ary_push(ary, rb_str_new2(cpdf_fontnamelist[i]));
	i++;
  } while(strcmp(cpdf_fontnamelist[i], "STSong-Light") != 0);
  rb_define_const(mClibPDF, "FONTNAMELIST", ary);

  i = 0;
  ary = rb_ary_new();
  do {
	rb_ary_push(ary, rb_str_new2(cpdf_fontEncodings[i]));
	i++;
  } while(strcmp(cpdf_fontEncodings[i], "UniKS-UCS2-V") != 0);
  rb_define_const(mClibPDF, "FONTENCODINGS", ary);

}
