#include<stdio.h>
#include<stdlib.h>  /* exit() */
#include<stdarg.h>
#include<string.h>

#include "fig2pdf.h"
#include "fig_fonts.h"
#include "bmp2eps.h"  /* BINARY and PAGE constants */

void write_font(char *fontname);

extern int obj_max,obj_count;

extern struct img_obj images;

extern char *extra_fonts;
extern char *extra_xobjs;
extern char *egstate;

double bb[4]={1e9,1e9,-1e9,-1e9};

void bb_fix(double x,double y,double width){
    width*=0.5;
    if (x-width<bb[0]) bb[0]=x-width;
    if (x+width>bb[2]) bb[2]=x+width;
    if (y-width<bb[1]) bb[1]=y-width;
    if (y+width>bb[3]) bb[3]=y+width;
}

void write_pdf_head(char* title){

  xref[0]=fprintf(pdf,"%%PDF-1.3\n");
  if (flags&BINARY)
    xref[0]+=fprintf(pdf,"%%%c%c%c\n",0xbc,0xba,0xc0);
  cref=0;


  /* Info object */

  OBJ_PRN("<</Producer (fig2pdf)\n"
          "/Title (%s)\n>>\nendobj\n\n",title);

}

void add_obj(int no, int depth){
  void *p;

  if (obj_count>=(obj_max-10)){
    obj_max+=100;
    p=realloc(objects,obj_max*sizeof(struct pdf_obj));
    if (!p){
      fprintf(stderr,"Malloc failed\n");
      exit(1);
    }
    objects=p;
    p=realloc(xref,obj_max*sizeof(int));
    if (!p){
      fprintf(stderr,"Malloc failed for xref\n");
      exit(1);
    }
    xref=p;
  }
  objects[obj_count].no=no;
  objects[obj_count].depth=depth;
  objects[obj_count].child=-1;
  obj_count++;
}

int obj_comp(const void *p1, const void *p2){
  const struct pdf_obj *obj1,*obj2;

  obj1=p1;
  obj2=p2;

  if (obj1->depth<obj2->depth) return 1;
  if (obj1->depth>obj2->depth) return -1;
  return 0;
}

void write_pdf_tail(double border,int background){
  int pdf_font,pdf_contents,i;
  char buffer[100];

  if ((bb[0]==1e9)||(bb[1]==1e9)||(bb[2]==-1e9)||(bb[3]==-1e9)){
    bb[0]=bb[1]=0;
    bb[2]=pg[0];
    bb[3]=pg[1];
  }
  else{
    bb[0]-=border;
    bb[1]-=border;
    bb[2]+=border;
    bb[3]+=border;
  }

  /* We might want an extra objects for co-ordinate shifts etc.
   * Note valid depths in a fig file are 0 to 999, so our use of
   * depths outside this range will not clash.
   */

  if (background!=-1){ /* Using pre-shift co-ords */
    i=sprintf(buffer,"q %.3f %.3f %.3f rg\n",
	      (background&0xff0000)/(double)(0xff0000),
	      (background&0xff00)/(double)(0xff00),
	      (background&0xff)/(double)(0xff));
    i+=sprintf(buffer+i,"%.2f %.2f %.2f %.2f re f Q",bb[0]-1,bb[1]-1,
	       bb[2]-bb[0]+1,bb[3]-bb[1]+1);
      OBJ_PRN("<</Length %d>> stream\n%s\nendstream\nendobj\n\n",i,buffer);
      add_obj(cref,999999);
  }

  if (!(flags&PAGE)){
    if ((bb[0]!=0)||(bb[1]!=0)){
      i=sprintf(buffer,"1 0 0 1 %.2f %.2f cm",-bb[0],-bb[1]);
      bb[2]-=bb[0];
      bb[3]-=bb[1];
      bb[0]=bb[1]=0;
      OBJ_PRN("<</Length %d>> stream\n%s\nendstream\nendobj\n\n",i,buffer);
      add_obj(cref,1000000);
    }
  }


  /* Fonts */

  for(i=0;i<35;i++){
    if (fontmap[i]){
      if(!pdffonts[i]){
	fontmap[i]=cref+1;
	write_font(psfonts[i]);
      }
    }
  }

  OBJ_PRN("<<\n");
  for(i=0;i<35;i++)
    if (fontmap[i]){
      if (pdffonts[i])
	xref[cref]+=fprintf(pdf,"  /F%d"
			    " << /Type /Font /Subtype"
			    " /Type1 /BaseFont /%s >>\n",
			    i,psfonts[i]);
      else
	xref[cref]+=fprintf(pdf,"  /F%d %d 0 R\n",i,fontmap[i]);
    }

  if(extra_fonts) xref[cref]+=fprintf(pdf," %s",extra_fonts);
  xref[cref]+=fprintf(pdf,">>\nendobj\n\n");
  pdf_font=cref;


  /* Contents array */

  /* write out with correct depths */

  qsort(objects,obj_count,sizeof(struct pdf_obj),obj_comp);

  OBJ_PRN("[\n");
  for(i=0;i<obj_count;i++){
    xref[cref]+=fprintf(pdf,"  %d 0 R\n",objects[i].no);
    if (objects[i].child!=-1)
      xref[cref]+=fprintf(pdf,"  %d 0 R\n",objects[i].child);
  }
  xref[cref]+=fprintf(pdf,"]\nendobj\n\n");
  pdf_contents=cref;


  /* Root object */

  OBJ_PRN("<</Type /Catalog\n"
          "/Pages %d 0 R\n"
          ">>\nendobj\n\n",cref+1);
  pdf_root_obj=cref;


  /* Root of page tree */

  OBJ_PRN("<</Type /Pages\n"
          "/Count 1\n/Kids [%d 0 R]\n"
          ">>\nendobj\n\n",cref+1);

  /* This page */

  OBJ_PRN("<</Type /Page\n"
          "/Parent %d 0 R\n"
	  "/Resources <<\n"
	  "  /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n"
          "  /Font %d 0 R\n",cref-1,pdf_font);

  if ((images.dict)||(extra_xobjs)){ /* We have at least one image */
    struct img_obj *img;
    int count;

    img=&images;
    count=0;

    xref[cref]+=fprintf(pdf,"  /XObject <<\n");
    if (images.dict){
    while((img)&&(img->dict)){
        xref[cref]+=fprintf(pdf,"    /Img%d %d 0 R\n",count,img->dict);
        img=img->next;
        count++;
      }
    }
    if (extra_xobjs) xref[cref]+=fprintf(pdf,"    %s\n",extra_xobjs);
    xref[cref]+=fprintf(pdf,"  >>\n");
  }

  if (egstate)
    xref[cref]+=fprintf(pdf,"  /ExtGState <<%s>>\n",egstate);

  xref[cref]+=fprintf(pdf,">>\n");

  if (flags&PAGE)
    xref[cref]+=fprintf(pdf,"/MediaBox [0 0 %d %d]\n",pg[0],pg[1]);
  else
    xref[cref]+=fprintf(pdf,"/MediaBox [%d %d %d %d]\n",
                        (int)bb[0],(int)bb[1],1+(int)bb[2],1+(int)bb[3]);
  xref[cref]+=fprintf(pdf,"/Contents %d 0 R\n"
		      ">>\nendobj\n\n",pdf_contents);



}

