summaryrefslogtreecommitdiff
path: root/src/drv/cddgn.c
diff options
context:
space:
mode:
authorscuri <scuri>2008-10-17 06:10:33 +0000
committerscuri <scuri>2008-10-17 06:10:33 +0000
commit7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf (patch)
treed0857278bde2eff784227c57dcaf930346ceb7ac /src/drv/cddgn.c
First commit - moving from LuaForge to SourceForge
Diffstat (limited to 'src/drv/cddgn.c')
-rw-r--r--src/drv/cddgn.c1696
1 files changed, 1696 insertions, 0 deletions
diff --git a/src/drv/cddgn.c b/src/drv/cddgn.c
new file mode 100644
index 0000000..32435b9
--- /dev/null
+++ b/src/drv/cddgn.c
@@ -0,0 +1,1696 @@
+/** \file
+ * \brief DGN driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+
+#include "cd.h"
+#include "cd_private.h"
+#include "cddgn.h"
+
+/* defines */
+
+#define MAX_NUM_VERTEX 101
+#define MAX_NUM_VERTEX_PER_POLYLINE 15000
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+#define END_OF_DGN_FILE 0xffff
+#define DGN_FILE_BLOCK 512
+
+#define NOFILL 0 /* tipos de fill que o driver faz */
+#define CONVEX 1
+#define NORMAL 2
+
+/* macros */
+
+#define SIZE_LINE_STRING(x) (19+4*(x))
+#define SIZE_FILLED_SHAPE(x) (27+4*(x))
+#define SIZE_ARC 40
+#define SIZE_LINE 26
+
+#define IGNORE(x) ((void) x)
+
+
+/* estruturas similares as que o MicroStation usa */
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ unsigned level:6;
+ unsigned :1;
+ unsigned complex:1;
+ unsigned type:7;
+ unsigned :1;
+ } flags;
+ short type_as_word;
+ } type;
+
+ unsigned short words;
+ unsigned long xmin;
+ unsigned long ymin;
+ unsigned long xmax;
+ unsigned long ymax;
+} Elm_hdr;
+
+typedef struct
+{
+ short attindx;
+ union
+ {
+ short s;
+ struct
+ {
+ unsigned /*class*/ :4;
+ unsigned /*res*/ :4;
+ unsigned /*l*/ :1;
+ unsigned /*n*/ :1;
+ unsigned /*m*/ :1;
+ unsigned attributes:1;
+ unsigned /*r*/ :1;
+ unsigned /*p*/ :1;
+ unsigned /*s*/ :1;
+ unsigned /*hole*/ :1;
+ } flags;
+ } props;
+
+ union
+ {
+ short s;
+ struct
+ {
+ unsigned style:3;
+ unsigned weight:5;
+ unsigned color:8;
+ } b;
+ } symb;
+
+} Disp_hdr;
+
+/* tipo de poligono/setor */
+enum
+{
+ FILLED,
+ OPEN
+};
+
+/* grupos de tamanhos de caracter
+ (usado por gettextwidth e cdgetfontdim) */
+
+static long fontsizes[4][8]=
+{
+ {1,2,4,5,6,7,0},
+ {5,3,2,1,0},
+ {8,6,4,3,2,1,0},
+ {5,3,2,1,0}
+};
+
+
+/**********************
+ * contexto do driver *
+ **********************/
+
+struct _cdCtxCanvas
+{
+ cdCanvas* canvas;
+
+ FILE *file; /* arquivo dgn */
+ long int bytes; /* tamanho do arquivo */
+ char level;
+
+ short color, style;
+
+ short alignment;
+ short typeface_index;
+ short symbology;
+ long tl;
+ short is_base; /* setado se texto e' do tipo CD_BASE_... */
+
+ short fill_type; /* como o driver faz fill:
+ NOFILL -> nao faz fill
+ CONVEX -> so faz fill de poligonos convexos
+ NORMAL -> faz fill normalmente */
+
+ long colortable[256]; /* palette */
+ short num_colors;
+
+ short is_complex;
+};
+
+/* prototipos de funcao */
+static void startComplexShape(cdCtxCanvas*, unsigned short,short,unsigned short,
+ unsigned long,unsigned long,
+ unsigned long,unsigned long);
+static void endComplexElement(cdCtxCanvas*);
+
+/******************************
+ * *
+ * funcoes internas do driver *
+ * *
+ ******************************/
+
+/*********************************************************
+ * Obtem o descent do texto (para letras como q,p,g etc) *
+ *********************************************************/
+
+static long get_descent(const char *text, int size_pixel)
+{
+ char *descent="jgyqp";
+ long a=0;
+ long length = strlen(text);
+
+ while(a < length)
+ {
+ if(strchr(descent, text[a]))
+ return size_pixel/2;
+
+ a++;
+ }
+ return 0;
+}
+
+/***********************************************
+ * Calcula a largura da string no MicroStation *
+ ***********************************************/
+
+static long gettextwidth(cdCtxCanvas* ctxcanvas, const char *s, int size_pixel)
+{
+ long a=0,
+ width=0,
+ length = strlen(s);
+
+ short default_size=0;
+
+ static char *fontchars[4][8] =
+ {
+ { /* CD_SYSTEM */
+ "Ww",
+ "jshyut#*-=<>",
+ "iIl[]",
+ ";:.,'|!()`{}",
+ "","","",""
+ },
+
+ { /* CD_COURIER */
+ "Iflrit!();.'",
+ "1|[]\"/`",
+ "BCDEKPRSUVXYbdgkpq&-_",
+ "w#%",
+ "Wm^+=<>~",
+ "@","",""
+ },
+
+ { /* CD_TIMES_ROMAN */
+ "m",
+ "HMUWw",
+ "CSTZLbhknpuvxy23567890e",
+ "fstz1#$-=<>",
+ "Iijl*[]",
+ ";:.,'|!()`{}",
+ "",""
+ },
+
+ { /* CD_HELVETICA */
+ "Ww",
+ "jshyut#*-=<>",
+ "iIl[]",
+ ";:.,'|!()`{}",
+ "","","",""
+ }
+ };
+
+ if (ctxcanvas->typeface_index == 1)
+ default_size=2;
+ else if (ctxcanvas->typeface_index == 2)
+ default_size=5;
+ else if (ctxcanvas->typeface_index == 3)
+ default_size=4;
+ else
+ default_size=4;
+
+ for(a=0,width=0;a < length; a++)
+ {
+ static short size_number;
+ static char letter;
+
+ if(s[a] == ' ')
+ letter = s[a-1];
+ else
+ letter = s[a];
+
+ for(size_number=0;size_number < 8;size_number++)
+ {
+ if(strchr(fontchars[ctxcanvas->typeface_index][size_number], letter))
+ {
+ width+=(ctxcanvas->tl*fontsizes[ctxcanvas->typeface_index][size_number])/6;
+ break;
+ }
+ }
+
+ if(size_number == 8)
+ width+=(ctxcanvas->tl*default_size)/6;
+
+ width+=ctxcanvas->tl/3;
+ }
+
+ width-=ctxcanvas->tl/3;
+
+ if (ctxcanvas->canvas->font_style & CD_ITALIC)
+ width+= (long) ((double)size_pixel*tan(4*atan(1)/8)); /* angulo de 15 graus */
+
+ return width;
+}
+
+/****************************
+ * Salva um byte no arquivo *
+ ****************************/
+
+static void put_byte(cdCtxCanvas* ctxcanvas, unsigned char byte)
+{
+ fputc(byte, ctxcanvas->file);
+}
+
+/************************************
+ * Salva um sequencia de caracteres *
+ ************************************/
+
+static void writec (cdCtxCanvas* ctxcanvas, const char *t, short tam )
+{
+ short i;
+
+ ctxcanvas->bytes += tam;
+ for ( i = 0; i < tam; i++ )
+ fputc ( t[i], ctxcanvas->file );
+}
+
+/******************
+ * Salva uma word *
+ ******************/
+
+static void put_word(cdCtxCanvas* ctxcanvas, unsigned short w)
+{
+ char c;
+
+ c = (char) (w & 0xff);
+ fputc (c, ctxcanvas->file);
+ c = (char) ((w >> 8) & 0xff);
+ fputc (c, ctxcanvas->file);
+ ctxcanvas->bytes += 2;
+}
+
+/****************************
+ * Salva um long no arquivo *
+ ****************************/
+
+static void put_long (cdCtxCanvas* ctxcanvas, unsigned long i)
+{
+ put_word(ctxcanvas, (short) (i >> 16));
+ put_word(ctxcanvas, (short) i);
+}
+
+/*******************
+ * Salva um double *
+ *******************/
+
+static void put_as_double(cdCtxCanvas* ctxcanvas, long i)
+{
+ float dfloat=(float) 4*i;
+
+ put_long(ctxcanvas, *((long *) &dfloat));
+ put_long(ctxcanvas, 0);
+
+ ctxcanvas->bytes+=sizeof(float);
+}
+
+/****************************
+ * Salva uma UOR no arquivo *
+ ****************************/
+
+static void put_uor(cdCtxCanvas* ctxcanvas, long i)
+{
+ put_word(ctxcanvas, (unsigned short)((i >> 16) ^ (1 << 15))); /* troca o bit 31
+ para transformar em uor */
+ put_word(ctxcanvas, (unsigned short)i);
+}
+
+/***************************************
+ * Salva a bounding box de um elemento *
+ ***************************************/
+
+static void put_bound(cdCtxCanvas* ctxcanvas, long xmin, long xmax, long ymin, long ymax)
+{
+ put_uor(ctxcanvas, xmin);
+ put_uor(ctxcanvas, ymin);
+ put_uor(ctxcanvas, 0L);
+ put_uor(ctxcanvas, xmax);
+ put_uor(ctxcanvas, ymax);
+ put_uor(ctxcanvas, 0L);
+}
+
+/******************************************
+ * Calcula a bounding box de uma polyline *
+ ******************************************/
+
+static void line_string_bound(cdPoint *buffer, short num_vertex,
+ unsigned long *xmin, unsigned long *ymin,
+ unsigned long *xmax, unsigned long *ymax)
+{
+ short i;
+ unsigned long v;
+
+ *xmin = *xmax = buffer[0].x;
+ *ymin = *ymax = buffer[0].y;
+
+ for (i = 1; i < num_vertex; i++)
+ {
+ v = buffer[i].x;
+ if (v < *xmin)
+ *xmin = v;
+ else if (v > *xmax)
+ *xmax = v;
+
+ v = (long) buffer[i].y;
+ if (v < *ymin)
+ *ymin = v;
+ else if (v > *ymax)
+ *ymax = v;
+ }
+}
+
+/************************************
+ * Retorna symbology de um elemento *
+ ************************************/
+
+static short symbology(cdCtxCanvas* ctxcanvas)
+{
+ return (short)((ctxcanvas->color << 8) | (ctxcanvas->canvas->line_width << 3) | ctxcanvas->style);
+}
+
+/*****************************************
+ * Salva um Element Header no arquivo *
+ *****************************************/
+
+static void putElementHeader(cdCtxCanvas* ctxcanvas, Elm_hdr *ehdr)
+{
+ ehdr->type.flags.complex = ctxcanvas->is_complex;
+
+ put_word(ctxcanvas, (short)(ehdr->type.flags.type << 8 |
+ ehdr->type.flags.complex << 7 | ehdr->type.flags.level));
+
+
+ put_word(ctxcanvas, ehdr->words);
+ put_bound(ctxcanvas, ehdr->xmin, ehdr->xmax, ehdr->ymin, ehdr->ymax);
+}
+
+/**************************************
+ * Salva um display header no arquivo *
+ **************************************/
+
+static void putDisplayHeader(cdCtxCanvas* ctxcanvas, Disp_hdr *dhdr)
+{
+ put_word(ctxcanvas, 0); /* graphics group */
+ put_word(ctxcanvas, dhdr->attindx); /* index to attributes */
+ put_word(ctxcanvas, dhdr->props.flags.attributes << 11); /* properties */
+ put_word(ctxcanvas, dhdr->symb.s); /* display symbology */
+}
+
+
+/***************************************
+ * completa o arquivo com zeros para *
+ * que o numero de bytes seja multiplo *
+ * de 512 *
+ ***************************************/
+
+static void complete_file(cdCtxCanvas* ctxcanvas)
+{
+ long resto, i;
+
+ put_word(ctxcanvas, END_OF_DGN_FILE);
+
+ resto = DGN_FILE_BLOCK - ctxcanvas->bytes % DGN_FILE_BLOCK;
+
+ /* checa validade do tamanho do arquivo */
+ if (resto%2 != 0) return;
+
+ for (i = 0; i < resto; i+=2)
+ put_word(ctxcanvas, 0);
+}
+
+/*************************************
+ * Salva um elemento arco no arquivo *
+ *************************************/
+
+static void arc (cdCtxCanvas* ctxcanvas, long xc, long yc, long w, long h, double a1, double a2)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=16;
+ ehdr.words=SIZE_ARC-2;
+ ehdr.xmin=xc - w/2;
+ ehdr.xmax=xc + w/2;
+ ehdr.ymin=yc - h/2;
+ ehdr.ymax=yc + h/2;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx = ehdr.words - 14;
+ dhdr.props.flags.attributes = 0;
+ dhdr.symb.s = symbology(ctxcanvas);
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_long(ctxcanvas, (long) a1*360000); /* start angle */
+ put_long(ctxcanvas, (long) (a2-a1)*360000); /* sweep angle */
+ put_as_double(ctxcanvas, w/2); /* primary axis */
+ put_as_double(ctxcanvas, h/2); /* secondary axis */
+ put_long(ctxcanvas, 0); /* rotation angle (sempre 0) */
+ put_as_double(ctxcanvas, xc); /* x origin */
+ put_as_double(ctxcanvas, yc); /* y origin */
+}
+
+/***************************************
+ * Salva um elemento elipse no arquivo *
+ ***************************************/
+
+static void ellipse(cdCtxCanvas* ctxcanvas, long xc, long yc, long w, long h, short type)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=15;
+ ehdr.words=34+((type==FILLED) ? 8 : 0);
+ ehdr.xmin=xc - w/2;
+ ehdr.xmax=xc + w/2;
+ ehdr.ymin=yc - h/2;
+ ehdr.ymax=yc + h/2;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=20;
+ dhdr.props.flags.attributes=(type == FILLED) ? 1 : 0;
+ dhdr.symb.s=symbology(ctxcanvas);
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_as_double(ctxcanvas, w/2); /* primary axis */
+ put_as_double(ctxcanvas, h/2); /* secondary axis */
+ put_long(ctxcanvas, 50); /* rotation angle (sempre 0) */
+ put_as_double(ctxcanvas, xc); /* x origin */
+ put_as_double(ctxcanvas, yc); /* y origin */
+
+ /* salva atributo de fill */
+ if(type == FILLED)
+ {
+ put_word(ctxcanvas, 0x1007);
+ put_word(ctxcanvas, 65);
+ put_word(ctxcanvas, 0x802);
+ put_word(ctxcanvas, 0x0001);
+ put_word(ctxcanvas, ctxcanvas->color);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ }
+}
+
+static short getclosestColor(cdCtxCanvas* ctxcanvas, long color)
+{
+ short count=0, closest=0;
+ long diff=0;
+ unsigned char r = cdRed(color),
+ g = cdGreen(color),
+ b = cdBlue(color);
+ short rd, gd, bd;
+ long newdiff;
+
+ /* procura a cor mais proxima */
+
+ diff = 3*65536; /* inicializa com maior diferenca possivel */
+
+ for(count=0; count < ctxcanvas->num_colors; count++)
+ {
+ rd = r - cdRed(ctxcanvas->colortable[count]);
+ gd = g - cdGreen(ctxcanvas->colortable[count]);
+ bd = b - cdBlue(ctxcanvas->colortable[count]);
+
+ newdiff = rd*rd + gd*gd + bd*bd;
+
+ if(newdiff <= diff)
+ {
+ /* verifica se encontrou a cor */
+ if(newdiff == 0)
+ return count-1;
+
+ diff = newdiff;
+ closest=count-1;
+ }
+ }
+
+ /* nao encontrou a cor, tenta adicionar na palette, ou retorna a mais proxima */
+ if(ctxcanvas->num_colors < 254)
+ {
+ ctxcanvas->colortable[ctxcanvas->num_colors+1] = color;
+ return ctxcanvas->num_colors++;
+ }
+ else
+ return closest;
+}
+
+static void saveColorTable(cdCtxCanvas* ctxcanvas)
+{
+ unsigned char r,g,b;
+ short i;
+
+ put_word(ctxcanvas, (0x05 << 8) | 1); /* colortable */
+ put_word(ctxcanvas, 434);
+
+ put_long(ctxcanvas, 0);
+ put_long(ctxcanvas, 0);
+ put_long(ctxcanvas, 0);
+ put_long(ctxcanvas, 0xffffffff);
+ put_long(ctxcanvas, 0xffffffff);
+ put_long(ctxcanvas, 0xffffffff);
+
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 420);
+ put_word(ctxcanvas, 0x0400);
+ put_word(ctxcanvas, 0x100);
+ put_word(ctxcanvas, 0);
+
+ for(i=0;i<256;i++)
+ {
+ cdDecodeColor(ctxcanvas->colortable[i], &r, &g, &b);
+ put_byte(ctxcanvas, r);
+ put_byte(ctxcanvas, g);
+ put_byte(ctxcanvas, b);
+ }
+
+ put_word(ctxcanvas, 25);
+ for(i=0;i<32;i++)
+ put_word(ctxcanvas, 0x2020);
+}
+
+
+/*****************************
+ * Le uma word de um arquivo *
+ *****************************/
+
+static short file_get_word(FILE *fp)
+{
+ short word=0;
+
+ word = (short)fgetc(fp);
+ word |= ((short)fgetc(fp) << 8) & 0xff00;
+
+ return word;
+}
+
+/********************************
+ * Salva uma word em um arquivo *
+ ********************************/
+
+static void file_put_word (short word, FILE *fp)
+{
+ fputc ((char) (word & 0xff), fp);
+ fputc ((char) ((word >> 8) & 0xff), fp);
+}
+
+/*******************************************
+ * Le elementos de um arquivo DGN e os *
+ * coloca no inicio do arquivo aberto pelo *
+ * driver *
+ *******************************************/
+
+static void dgn_copy (FILE *file, cdCtxCanvas *ctxcanvas)
+{
+ short word=0;
+
+ while ((word = file_get_word(file)) != END_OF_DGN_FILE)
+ {
+ file_put_word(word, ctxcanvas->file); /* type e level do elemento */
+ ctxcanvas->bytes+=2;
+
+ word = file_get_word(file); /* words to follow */
+ file_put_word(word, ctxcanvas->file);
+ ctxcanvas->bytes+=2;
+
+ while (word) /* copia resto do elemento */
+ {
+ file_put_word(file_get_word(file), ctxcanvas->file);
+ word--;
+ ctxcanvas->bytes+=2;
+ }
+ }
+}
+
+
+/*
+ * Funcoes do driver
+ */
+
+static void cdkillcanvas(cdCtxCanvas* ctxcanvas)
+{
+ saveColorTable(ctxcanvas);
+ complete_file(ctxcanvas);
+ fclose (ctxcanvas->file);
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cddeactivate (cdCtxCanvas* ctxcanvas)
+{
+ fflush(ctxcanvas->file);
+}
+
+static void cdflush (cdCtxCanvas* ctxcanvas)
+{
+ fflush(ctxcanvas->file);
+}
+
+
+/******************************************************/
+/* primitives */
+/******************************************************/
+
+static void cdline (cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+ cdPoint buffer[2];
+
+ buffer[0].x=x1;
+ buffer[0].y=y1;
+ buffer[1].x=x2;
+ buffer[1].y=y2;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=3;
+
+ ehdr.words=SIZE_LINE-2;
+
+ line_string_bound(buffer, 2, &ehdr.xmin,
+ &ehdr.ymin,&ehdr.xmax,&ehdr.ymax);
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx = ehdr.words - 14;
+ dhdr.props.flags.attributes = 0;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ /* pontos inicial e final da linha */
+
+ put_long(ctxcanvas, (long) x1);
+ put_long(ctxcanvas, (long) y1);
+ put_long(ctxcanvas, (long) x2);
+ put_long(ctxcanvas, (long) y2);
+}
+
+static void cdbox (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=6;
+ ehdr.words=17+4*5+8;
+ ehdr.xmin=xmin;
+ ehdr.xmax=xmax;
+ ehdr.ymin=ymin;
+ ehdr.ymax=ymax;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=3+4*5;
+ dhdr.props.flags.attributes=1;
+ dhdr.symb.s=symbology(ctxcanvas);
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, 5); /* numero de vertices */
+
+ /* vertices */
+ put_long(ctxcanvas, (long) xmin);
+ put_long(ctxcanvas, (long) ymin);
+
+ put_long(ctxcanvas, (long) xmax);
+ put_long(ctxcanvas, (long) ymin);
+
+ put_long(ctxcanvas, (long) xmax);
+ put_long(ctxcanvas, (long) ymax);
+
+ put_long(ctxcanvas, (long) xmin);
+ put_long(ctxcanvas, (long) ymax);
+
+ put_long(ctxcanvas, (long) xmin);
+ put_long(ctxcanvas, (long) ymin);
+
+ /* atributos de fill */
+
+ put_word(ctxcanvas, 0x1007);
+ put_word(ctxcanvas, 65);
+ put_word(ctxcanvas, 0x802);
+ put_word(ctxcanvas, 0x0001);
+ put_word(ctxcanvas, ctxcanvas->color);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+}
+
+static void cdarc (cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (a2 == a1 + 360)
+ ellipse(ctxcanvas, xc,yc,w,h,OPEN);
+ else
+ arc(ctxcanvas, xc, yc, w, h, a1, a2);
+}
+
+static void cdsector (cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
+{
+ if (a2 == a1 + 360)
+ {
+ ellipse(ctxcanvas, xc,yc,w,h,FILLED);
+ return;
+ }
+
+ startComplexShape(ctxcanvas, 3, 1, SIZE_ARC+SIZE_LINE*2,
+ (unsigned long) xc-w/2, (unsigned long) yc-h/2,
+ (unsigned long) xc+h/2, (unsigned long) yc+h/2);
+
+ arc(ctxcanvas, xc, yc, w, h, a1, a2);
+
+ cdline(ctxcanvas, xc, yc, (int)
+ (((double)w*cos(a1*CD_DEG2RAD)/2.+.5)), (int) (((double)h*sin(a1*CD_DEG2RAD))/2.+.5));
+ cdline(ctxcanvas, xc, yc, (int)
+ (((double)w*cos(a2*CD_DEG2RAD)/2.+.5)), (int) (((double)h*sin(a2*CD_DEG2RAD))/2.+.5));
+
+ endComplexElement(ctxcanvas);
+}
+
+static void cdtext (cdCtxCanvas* ctxcanvas, int x, int y, const char *s)
+{
+ long n=0;
+ long descent=0;
+ short w=0;
+ long hc=0,wc=0;
+ int size_pixel;
+ short italic = (ctxcanvas->canvas->font_style&CD_ITALIC);
+
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ n = strlen(s);
+
+ if(n > 255)
+ n=255;
+
+ w = (short)((n/2)+(n%2));
+ size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size);
+ descent=get_descent(s, size_pixel);
+ hc = size_pixel+descent;
+ wc = gettextwidth(ctxcanvas, s, size_pixel);
+
+ y+=descent;
+
+ switch (ctxcanvas->alignment)
+ {
+ case 12: x = x; y = y; break;
+ case 13: x = x; y = y - (int) (hc/2.0); break;
+ case 14: x = x; y = y - (int) hc; break;
+ case 6: x = x - (int) (wc/2.0); y = y; break;
+ case 7: x = x - (int) (wc/2.0); y = y - (int) (hc/2.0); break;
+ case 8: x = x - (int) (wc/2.0); y = y - (int) hc; break;
+ case 0: x = x - (int) wc; y = y; break;
+ case 1: x = x - (int) wc; y = y - (int) (hc/2.0); break;
+ case 2: x = x - (int) wc; y = y - (int) hc; break;
+ }
+
+ if(ctxcanvas->is_base)
+ y -= (int) (hc/4.0);
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=17;
+ ehdr.words=28+w+((italic) ? 8 : 0);
+ ehdr.xmin=x;
+ ehdr.xmax=x+wc;
+ ehdr.ymin=y-descent;
+ ehdr.ymax=y+hc;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=14+w;
+ dhdr.props.flags.attributes=(italic) ? 1 : 0;
+
+ if (ctxcanvas->canvas->font_style&CD_BOLD)
+ dhdr.symb.s=ctxcanvas->color << 8 | (3 << 3);
+ else
+ dhdr.symb.s=ctxcanvas->color << 8;
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, (ctxcanvas->alignment << 8) | ctxcanvas->typeface_index);
+
+ put_long(ctxcanvas, (long)((1000 * ctxcanvas->tl) / 6) | (1 << 7));
+ put_long(ctxcanvas, (long)((1000 * size_pixel) / 6) | (1 << 7));
+
+ put_long(ctxcanvas, 0);
+ put_long(ctxcanvas, x);
+ put_long(ctxcanvas, y);
+ put_word(ctxcanvas, (unsigned short) n);
+ writec(ctxcanvas, s, (short)(n+(n%2))); /* deve escrever sempre um numero par de caracteres */
+
+ if(italic)
+ {
+ put_word(ctxcanvas, 0x1007); /* atributos e words to follow */
+ put_word(ctxcanvas, 0x80d4); /* tipo de atributo */
+ put_long(ctxcanvas, 0x000865c0);
+ put_long(ctxcanvas, 0x00520000);
+ put_long(ctxcanvas, 0x00000000);
+ }
+}
+
+static void startComplexShape(cdCtxCanvas* ctxcanvas,
+ unsigned short num_elements,
+ short is_fill,
+ unsigned short size,
+ unsigned long xmin,
+ unsigned long ymin,
+ unsigned long xmax,
+ unsigned long ymax)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=14;
+ ehdr.words=22 + ((is_fill) ? 8 : 0);
+ ehdr.xmax = xmax;
+ ehdr.xmin = xmin;
+ ehdr.ymax = ymax;
+ ehdr.ymin = ymin;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=4;
+ dhdr.props.flags.attributes = (is_fill) ? 1 : 0;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, size + 5 + ((is_fill) ? 8 : 0));
+ put_word(ctxcanvas, num_elements);
+
+ put_long(ctxcanvas, 0); /* atributo nulo */
+ put_long(ctxcanvas, 0);
+
+ /* salva atributo de fill */
+ if(is_fill)
+ {
+ put_word(ctxcanvas, 0x1007);
+ put_word(ctxcanvas, 65);
+ put_word(ctxcanvas, 0x802);
+ put_word(ctxcanvas, 0x0001);
+ put_word(ctxcanvas, ctxcanvas->color);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ }
+
+ /* marca inicio de elemento complexo */
+
+ ctxcanvas->is_complex = 1;
+}
+
+
+static void startComplexChain(cdCtxCanvas* ctxcanvas,
+ unsigned short num_elements,
+ unsigned short size,
+ unsigned long xmin,
+ unsigned long ymin,
+ unsigned long xmax,
+ unsigned long ymax)
+
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=12;
+
+ ehdr.words=22;
+ ehdr.xmax = xmax;
+ ehdr.xmin = xmin;
+ ehdr.ymax = ymax;
+ ehdr.ymin = ymin;
+
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=4;
+ dhdr.props.flags.attributes = 1;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, size+5);
+ put_word(ctxcanvas, num_elements);
+
+ put_long(ctxcanvas, 0); /* atributo nulo */
+ put_long(ctxcanvas, 0);
+
+
+ /* marca inicio de elemento complexo */
+
+ ctxcanvas->is_complex = 1;
+}
+
+static void endComplexElement(cdCtxCanvas* ctxcanvas)
+{
+ ctxcanvas->is_complex = 0;
+}
+
+static void putLineString(cdCtxCanvas* ctxcanvas, cdPoint *buffer, short num_vertex)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+ short i=0;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+
+ ehdr.type.flags.type=4;
+
+ ehdr.words=SIZE_LINE_STRING(num_vertex)-2;
+
+ line_string_bound(buffer, num_vertex, &ehdr.xmin,
+ &ehdr.ymin,&ehdr.xmax,&ehdr.ymax);
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=ehdr.words-14;
+ dhdr.props.flags.attributes = 0;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, num_vertex);
+
+ for (i = 0; i < num_vertex; i++)
+ {
+ put_long(ctxcanvas, (long) buffer[i].x);
+ put_long(ctxcanvas, (long) buffer[i].y);
+ }
+}
+
+static void putShape(cdCtxCanvas* ctxcanvas, cdPoint *buffer, short num_vertex)
+{
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+ short i=0;
+
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=6;
+
+ ehdr.words=SIZE_FILLED_SHAPE(num_vertex)-2;
+
+ line_string_bound(buffer, num_vertex, &ehdr.xmin,
+ &ehdr.ymin,&ehdr.xmax,&ehdr.ymax);
+
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=ehdr.words - 14 - 8; /* 8 -> size of attributes */
+ dhdr.props.flags.attributes = 1;
+ dhdr.symb.s=symbology(ctxcanvas);
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, num_vertex);
+
+ for (i = 0; i < num_vertex; i++)
+ {
+ put_long(ctxcanvas, (long) buffer[i].x);
+ put_long(ctxcanvas, (long) buffer[i].y);
+ }
+
+ put_word(ctxcanvas, 0x1007);
+ put_word(ctxcanvas, 65);
+ put_word(ctxcanvas, 0x802);
+ put_word(ctxcanvas, 0x0001);
+ put_word(ctxcanvas, ctxcanvas->color);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+}
+
+static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
+{
+ short is_fill=0;
+
+ if(mode == CD_FILL && ctxcanvas->fill_type == NOFILL)
+ mode = CD_CLOSED_LINES;
+
+ if(n > MAX_NUM_VERTEX_PER_POLYLINE)
+ n = MAX_NUM_VERTEX_PER_POLYLINE;
+
+ /* acerta buffer de pontos */
+ if(mode == CD_FILL || mode == CD_CLOSED_LINES)
+ {
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ }
+
+ /* se fill_type for CONVEX, testa se poligono e' convexo ou concavo */
+ if((ctxcanvas->fill_type == CONVEX) && (n > 3) && (mode == CD_FILL))
+ {
+ short signal=0;
+ short count=0;
+ long vect=0;
+
+ /* calcula sinal do vetorial entre o primeiro lado e o segundo */
+ vect = (poly[1].x - poly[0].x) *
+ (poly[2].y - poly[1].y) -
+ (poly[1].y - poly[0].y) *
+ (poly[2].x - poly[1].x);
+
+ if(vect == 0)
+ mode = CD_CLOSED_LINES; /* ver se precisa mudar */
+ else
+ {
+ signal = (short)(vect/abs(vect));
+
+ for(count=1 ; count< (n-2); count++)
+ {
+ vect = (poly[count+1].x - poly[count].x) *
+ (poly[count+2].y - poly[count+1].y) -
+ (poly[count+1].y - poly[count].y) *
+ (poly[count+2].x - poly[count+1].x);
+
+ if(vect == 0)
+ {
+ mode=CD_CLOSED_LINES;
+ break;
+ }
+
+ if((vect/abs(vect)) != signal)
+ {
+ mode=CD_CLOSED_LINES;
+ break;
+ }
+ }
+ }
+ }
+
+ /* se tiver fill */
+
+ if(mode == CD_FILL)
+ is_fill=1;
+
+ if(n > MAX_NUM_VERTEX) /* tem que usar complex shape ou chain */
+ {
+ short count=0;
+ short num_whole_elements = n / MAX_NUM_VERTEX;
+ short num_whole_vertex = num_whole_elements * MAX_NUM_VERTEX;
+ short rest = n % MAX_NUM_VERTEX;
+ short is_there_rest = (rest > 0) ? 1 : 0;
+ unsigned long xmax, xmin, ymax, ymin;
+ unsigned short size =
+ SIZE_LINE_STRING(MAX_NUM_VERTEX)*num_whole_elements+
+ SIZE_LINE_STRING(rest)*is_there_rest;
+
+ line_string_bound(poly, n, &xmin, &ymin, &xmax, &ymax);
+
+ if(mode == CD_OPEN_LINES)
+ startComplexChain(ctxcanvas, (unsigned short) (num_whole_elements+((rest > 0) ? 1 : 0)),
+ size, xmin, ymin, xmax, ymax);
+ else
+ startComplexShape(ctxcanvas, (unsigned short) (num_whole_elements+((rest > 0) ? 1 : 0)),
+ is_fill, size, xmin, ymin, xmax, ymax);
+
+ for(count=0;count < num_whole_vertex; count+=MAX_NUM_VERTEX, n-=MAX_NUM_VERTEX)
+ putLineString(ctxcanvas, &poly[count], MAX_NUM_VERTEX);
+
+ if(rest)
+ putLineString(ctxcanvas, &poly[num_whole_vertex],n);
+
+ endComplexElement(ctxcanvas);
+ }
+ else
+ {
+ if(is_fill)
+ putShape(ctxcanvas, poly, n);
+ else
+ putLineString(ctxcanvas, poly, n);
+ }
+}
+
+/**************
+ * attributes *
+ **************/
+
+static int cdlinestyle (cdCtxCanvas* ctxcanvas, int style)
+{
+ switch(style)
+ {
+ case CD_CONTINUOUS:
+ ctxcanvas->style = 0;
+ break;
+
+ case CD_DASHED:
+ ctxcanvas->style = 3;
+ break;
+
+ case CD_DOTTED:
+ ctxcanvas->style = 1;
+ break;
+
+ case CD_DASH_DOT:
+ ctxcanvas->style = 4;
+ break;
+
+ case CD_DASH_DOT_DOT:
+ ctxcanvas->style = 6;
+ break;
+ }
+
+ return style;
+}
+
+static int cdlinewidth (cdCtxCanvas* ctxcanvas, int width)
+{
+ (void)ctxcanvas;
+ width = width & 31;
+ return width;
+}
+
+static int cdfont(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size)
+{
+ (void)style;
+ ctxcanvas->tl = (long)(cdGetFontSizePoints(ctxcanvas->canvas, size)/4)*3;
+
+ if (cdStrEqualNoCase(type_face, "Courier"))
+ ctxcanvas->typeface_index=1;
+ else if (cdStrEqualNoCase(type_face, "Times"))
+ ctxcanvas->typeface_index=2;
+ else if (cdStrEqualNoCase(type_face, "Helvetica"))
+ ctxcanvas->typeface_index=3;
+ else if (cdStrEqualNoCase(type_face, "System"))
+ ctxcanvas->typeface_index=0;
+ else
+ return 0;
+
+ return 1;
+}
+
+static void cdgetfontdim (cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent)
+{
+ int size_pixel;
+
+ if(max_width)
+ {
+ int a=0;
+ *max_width=0;
+
+ while(fontsizes[ctxcanvas->typeface_index][a])
+ {
+ if(fontsizes[ctxcanvas->typeface_index][a] > *max_width)
+ *max_width = fontsizes[ctxcanvas->typeface_index][a];
+ a++;
+ }
+ }
+
+ size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size);
+
+ if(height) *height = (size_pixel*3)/2;
+ if(ascent) *ascent = size_pixel;
+ if(descent) *descent = size_pixel/2;
+}
+
+static void cdgettextsize (cdCtxCanvas* ctxcanvas, const char *s, int *width, int *height)
+{
+ int size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size);
+ if(height) *height = size_pixel + get_descent(s, size_pixel);
+ if(width) *width = gettextwidth(ctxcanvas, s, size_pixel);
+}
+
+static int cdtextalignment (cdCtxCanvas* ctxcanvas, int alignment)
+{
+ ctxcanvas->is_base = 0;
+
+ /* DGN guarda posicao do texto em relacao ao ponto */
+
+ switch(alignment)
+ {
+ case CD_NORTH:
+ ctxcanvas->alignment = 8; /* center-bottom */
+ break;
+
+ case CD_SOUTH:
+ ctxcanvas->alignment = 6; /* center-top */
+ break;
+
+ case CD_EAST:
+ ctxcanvas->alignment = 1; /* left-center */
+ break;
+
+ case CD_WEST:
+ ctxcanvas->alignment = 13; /* right-center */
+ break;
+
+ case CD_NORTH_EAST:
+ ctxcanvas->alignment = 2; /* left-bottom */
+ break;
+
+ case CD_NORTH_WEST:
+ ctxcanvas->alignment = 14; /* right-bottom */
+ break;
+
+ case CD_SOUTH_EAST:
+ ctxcanvas->alignment = 0; /* left-top */
+ break;
+
+ case CD_SOUTH_WEST:
+ ctxcanvas->alignment = 12; /* right-top */
+ break;
+
+ case CD_CENTER:
+ ctxcanvas->alignment = 7; /* center-center */
+ break;
+
+ case CD_BASE_LEFT:
+ ctxcanvas->alignment = 13; /* right-center */
+ ctxcanvas->is_base=1;
+ break;
+
+ case CD_BASE_CENTER:
+ ctxcanvas->alignment = 7; /* center-center */
+ ctxcanvas->is_base=1;
+ break;
+
+ case CD_BASE_RIGHT:
+ ctxcanvas->alignment = 1; /* left-center */
+ ctxcanvas->is_base=1;
+ break;
+ }
+
+ return alignment;
+}
+
+/******************************************************/
+/* color */
+/******************************************************/
+
+static void cdpalette (cdCtxCanvas* ctxcanvas, int n, const long int *palette, int mode)
+{
+ int c=0;
+
+ IGNORE(mode);
+
+ for(c=0; c < n; c++)
+ ctxcanvas->colortable[c] = *palette++;
+
+ ctxcanvas->num_colors = n;
+}
+
+static long int cdforeground (cdCtxCanvas* ctxcanvas, long int color)
+{
+ ctxcanvas->color = getclosestColor(ctxcanvas, color);
+ return color;
+}
+
+/******************************************************/
+/* client images */
+/******************************************************/
+
+static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index,
+ const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int i=0,j=0, remainder=iw%2, total_colors;
+ int *ix=NULL,*iy=NULL;
+ Elm_hdr ehdr;
+ Disp_hdr dhdr;
+ unsigned char map_colors[256];
+
+
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=87;
+ ehdr.words=39;
+ ehdr.xmin=x;
+ ehdr.xmax=x+w;
+ ehdr.ymin=y;
+ ehdr.ymax=y+h;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=25;
+ dhdr.symb.s=0;
+
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ /* description of the element */
+ put_long(ctxcanvas, 21+(23+w/2+w%2)*h); /* total length of cell */
+ put_word(ctxcanvas, 0x0714); /* raster flags */
+ put_word(ctxcanvas, 0x0100); /* background e foreground colors
+ (nao usados) */
+ put_word(ctxcanvas, w); /* largura da imagem em pixels */
+ put_word(ctxcanvas, h); /* altura da imagem em pixel */
+ put_long(ctxcanvas, 0); /* resevado */
+ put_as_double(ctxcanvas, 0); /* resolution (nao usado) */
+
+ put_word(ctxcanvas, 0x4080); /* scale */
+ put_long(ctxcanvas, 0);
+ put_word(ctxcanvas, 0);
+
+ put_long(ctxcanvas, x); /* origem */
+ put_long(ctxcanvas, y+h);
+ put_long(ctxcanvas, 0);
+
+ put_word(ctxcanvas, 0); /* no de vertices */
+
+ ctxcanvas->is_complex = 1; /* elemento complexo */
+
+ /* obtem o maior indice usado na imagem */
+
+ total_colors = 0;
+ for (i = 0; i < iw*ih; i++)
+ {
+ if (index[i] > total_colors)
+ total_colors = index[i];
+ }
+ total_colors++;
+
+ /* cria tabela para acelerar match de cor na palette */
+
+ for (i = 0; i < total_colors; i++)
+ {
+ map_colors[i] = (unsigned char)getclosestColor(ctxcanvas, colors[i]);
+ }
+
+ /** salva dados da imagem **/
+
+ /* calcula stretch */
+
+ ix = cdGetZoomTable(w, xmax-xmin+1, xmin);
+ iy = cdGetZoomTable(h, ymax-ymin+1, ymin);
+
+ for(i=h-1; i >= 0; i--)
+ {
+ /* raster header element */
+ ehdr.type.flags.level=ctxcanvas->level;
+ ehdr.type.flags.type=88;
+ ehdr.words=21+w/2+remainder;
+
+ putElementHeader(ctxcanvas, &ehdr);
+
+ /* Display Header */
+ dhdr.attindx=7+w/2+remainder;
+ dhdr.symb.s=0;
+ putDisplayHeader(ctxcanvas, &dhdr);
+
+ put_word(ctxcanvas, 0x0714); /* raster flags */
+ put_word(ctxcanvas, 0x0100); /* background e foreground
+ colors (nao usados) */
+
+ put_word(ctxcanvas, 0); /* x offset da origem */
+ put_word(ctxcanvas, i); /* y offset */
+ put_word(ctxcanvas, w); /* numero de pixels neste elemento */
+
+ for(j=0; j < w; j++)
+ put_byte(ctxcanvas, map_colors[index[(iy[i])*iw + ix[j]]]);
+
+ if(remainder) put_byte(ctxcanvas, 0);
+ }
+
+ ctxcanvas->is_complex = 0;
+
+ free(ix); /* libera memoria alocada */
+ free(iy);
+}
+
+/******************************************************/
+/* server images */
+/******************************************************/
+
+static void cdpixel (cdCtxCanvas* ctxcanvas, int x, int y, long int color)
+{
+ long old_color = cdforeground(ctxcanvas, color);
+ int old_linestyle = cdlinestyle(ctxcanvas, CD_CONTINUOUS);
+ int old_linewidth = cdlinewidth(ctxcanvas, 1);
+
+ cdline(ctxcanvas, x,y,x,y);
+
+ cdforeground(ctxcanvas, old_color);
+ cdlinestyle(ctxcanvas, old_linestyle);
+ cdlinewidth(ctxcanvas, old_linewidth);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ cdCtxCanvas *ctxcanvas;
+ char* strdata = (char*)data;
+ char words[4][256];
+ char filename[10240] = "";
+ char seedfile[10240] = "";
+ int count = 0;
+ double res = 0;
+
+ if (!data) return;
+
+ /* separa palavras da expressao, que e' na forma
+ "filename [mm_wxmm_h] [res] [-f] [-sseedfile]" */
+
+ strdata += cdGetFileName(strdata, filename);
+ if (filename[0] == 0)
+ return;
+
+ sscanf(strdata, "%s %s %s %s", words[0], words[1], words[2], words[3]);
+
+ if(!strlen(filename)) /* se nao pegou filename */
+ return;
+
+ ctxcanvas = (cdCtxCanvas *) malloc(sizeof(cdCtxCanvas));
+
+ /* tenta criar arquivo DGN */
+
+ if((ctxcanvas->file = fopen (filename, "wb"))==NULL)
+ {
+ free(ctxcanvas);
+ return;
+ }
+
+ /* verifica se foi passado tamanho do canvas em mm. Se foi,
+ extrai-o da string */
+
+ if(sscanf(words[0], "%lgx%lg",
+ &canvas->w_mm, &canvas->h_mm) == 2)
+ {
+ count++; /* incrementa contador de palavras */
+
+ if(canvas->w_mm == 0 || canvas->h_mm == 0)
+ {
+ fclose(ctxcanvas->file);
+ free(ctxcanvas);
+ return;
+ }
+ }
+ else
+ canvas->w_mm = canvas->h_mm = 0;
+
+ /* Verifica se foi passada resolucao */
+
+ if(sscanf(words[count], "%lg", &res) == 1)
+ {
+ count++; /* incrementa contador de palavras */
+
+ if(res <= 0) /* verifica validade da resolucao */
+ {
+ fclose(ctxcanvas->file);
+ free(ctxcanvas);
+ return;
+ }
+ }
+ else
+ res = 3.78;
+
+ /* se tamanho em milimetros nao tiver sido inicializado,
+ usa como default o tamanho maximo em pixels para fazer as
+ contas
+ */
+
+ if (canvas->w_mm == 0 || canvas->h_mm == 0)
+ {
+ canvas->w = INT_MAX;
+ canvas->h = INT_MAX;
+
+ canvas->w_mm = canvas->w / res;
+ canvas->h_mm = canvas->h / res;
+ }
+ else
+ {
+ canvas->w = (long) (canvas->w_mm * res);
+ canvas->h = (long) (canvas->h_mm * res);
+ }
+
+ canvas->xres = res;
+ canvas->yres = res;
+ canvas->bpp = 8;
+
+ /* verifica se usuario que alterar metodo de fill */
+
+ if (strcmp(words[count], "-f")==0)
+ {
+ ctxcanvas->fill_type = CONVEX;
+ count++;
+ }
+ else
+ ctxcanvas->fill_type = NORMAL;
+
+ /* se tiver passado seedfile como argumento */
+ if(sscanf(words[count], "-s%s", seedfile) == 1)
+ {
+ FILE *seed=NULL;
+ char *cd_dir = getenv("CDDIR");
+ static char newfilename[512];
+
+ if(cd_dir == NULL)
+ cd_dir = ".";
+
+ sprintf(newfilename, "%s/%s", cd_dir, seedfile);
+
+ count++;
+
+ /* testa concatenando com variavel de ambiente */
+
+ if((seed = fopen (newfilename, "rb"))==NULL)
+ {
+ /* tenta abrir usando string passada pelo usuario
+ diretamente */
+
+ if((seed = fopen (seedfile, "rb"))==NULL)
+ {
+ fclose(ctxcanvas->file);
+ free(ctxcanvas);
+ return;
+ }
+ }
+
+ /* concatena seed */
+
+ fseek(seed, 0, SEEK_SET);
+ fseek(ctxcanvas->file, 0, SEEK_SET);
+
+ ctxcanvas->bytes=0;
+ dgn_copy(seed, ctxcanvas);
+ fclose(seed);
+ }
+
+ ctxcanvas->canvas = canvas;
+ canvas->ctxcanvas = ctxcanvas;
+
+ /* config */
+
+ ctxcanvas->level = 1;
+
+ /** valores default do contexto sao setados **/
+
+ /* texto */
+
+ ctxcanvas->alignment = 12;
+ ctxcanvas->is_base = 1;
+ ctxcanvas->typeface_index = 0;
+ ctxcanvas->tl=12;
+
+ /* cores */
+
+ memset(ctxcanvas->colortable, 0, 1024);
+ ctxcanvas->colortable[0] = CD_BLACK;
+ ctxcanvas->num_colors = 1;
+
+ /* atributos */
+
+ ctxcanvas->color = 1;
+ ctxcanvas->style = 0;
+
+ /* DGN */
+
+ ctxcanvas->is_complex=0;
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ canvas->cxFlush = cdflush;
+ canvas->cxPixel = cdpixel;
+ canvas->cxLine = cdline;
+ canvas->cxPoly = cdpoly;
+ canvas->cxBox = cdbox;
+ canvas->cxArc = cdarc;
+ canvas->cxSector = cdsector;
+ canvas->cxText = cdtext;
+ canvas->cxGetFontDim = cdgetfontdim;
+ canvas->cxGetTextSize = cdgettextsize;
+ canvas->cxPutImageRectMap = cdputimagerectmap;
+
+ canvas->cxLineStyle = cdlinestyle;
+ canvas->cxLineWidth = cdlinewidth;
+ canvas->cxFont = cdfont;
+ canvas->cxTextAlignment = cdtextalignment;
+ canvas->cxPalette = cdpalette;
+ canvas->cxForeground = cdforeground;
+
+ canvas->cxKillCanvas = cdkillcanvas;
+ canvas->cxDeactivate = cddeactivate;
+}
+
+/******************************************************/
+
+static cdContext cdDGNContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB |
+ CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | CD_CAP_RECT |
+ CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD |
+ CD_CAP_IMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE |
+ CD_CAP_HATCH | CD_CAP_STIPPLE | CD_CAP_PATTERN |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB |
+ CD_CAP_FPRIMTIVES | CD_CAP_TEXTORIENTATION),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ NULL,
+ NULL,
+};
+
+cdContext* cdContextDGN(void)
+{
+ return &cdDGNContext;
+}
+
+