#include "hp2graph.h" #include "format.h" #include "output.h" #include "draw.h" #define USE_FONT 1 static double xOffset = 30; static double yOffset = 30; static double drawscale = 0.4; static int landscape = 1; static void DrawScale(double f) { drawscale = f; } static void DrawPortrait(void) { landscape = 0; } static void DrawLandscape(void) { landscape = 1; } static DrawPoint ll; static DrawPoint ur; static void pointZero(void) { ll.x = ll.y = 2000000000; ur.x = ur.y = -2000000000; } static DrawPoint pointInc(DrawPoint p) { p.x++; p.y++; return p; } static DrawPoint pointBound(DrawPoint p) { if(p.x < ll.x) ll.x = p.x; if(p.y < ll.y) ll.y = p.y; if(p.x > ur.x) ur.x = p.x; if(p.y > ur.y) ur.y = p.y; return p; } static DrawPoint point(double x,double y) { DrawPoint p; if(landscape) { p.x = (int)MM((xOffset+x)*drawscale); p.y = (int)MM((yOffset+y)*drawscale); } else { p.x = (int)MM((yOffset+y)*drawscale); p.y = (int)MM((xOffset+x)*drawscale); } return pointBound(p); } static void DrawPrelude(double scale,int embedded) { DrawFileHeader dfh; dfh.magic = 'D' | ('r'<<8) | ('a'<<16) | ('w'<<24); dfh.major = 201; dfh.minor = 0; strncpy(dfh.creator,"hp2draw ",12); dfh.bounding.lowerLeft = point(0.0,0.0); dfh.bounding.upperRight = point(291.0,211.0); fwrite(&dfh,sizeof(dfh),1,outFile); } #define MAXPATHSIZE 1024 static char *DrawBuffer; static int DrawBufferSize; static char *DrawBufferPos; static double DrawPosX,DrawPosY; static Kind DrawKind; #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif static void buffer(void *object,int size) { if(size+DrawBufferPos >= &DrawBuffer[DrawBufferSize]) { int used = DrawBufferPos-DrawBuffer; DrawBufferSize+=max(size,MAXPATHSIZE); DrawBuffer = realloc(DrawBuffer,DrawBufferSize); if(!DrawBuffer) { fprintf(stderr,"DrawBuffer couldn't grow to %d bytes!\n",DrawBufferSize); exit(-1); } DrawBufferPos = &DrawBuffer[used]; } memcpy(DrawBufferPos,object,size); DrawBufferPos += size; } #define BUFFER(object) buffer(&object,sizeof(object)) #define BUFFERSIZE(object,size) buffer(&object,size) /* Draw Path */ static void DrawPathNew(Kind kind,int size) { DrawPathObject dpo; size = size; /* Don't care */ DrawBufferPos = DrawBuffer; DrawPosX = DrawPosY = 0; DrawKind = kind; dpo.header.type = DRAW_PATHOBJECT; dpo.header.size = 0; /* size not known yte */ dpo.bounding.lowerLeft = point(0.0,0.0); dpo.bounding.upperRight = point(0.0,0.0); dpo.fill.colour = TRANSPARENT; dpo.outline.colour = BLACK; dpo.outlineWidth = 0; dpo.pathStyle.joinStyle = mitredJoind; dpo.pathStyle.endCapStyle = buttCap; dpo.pathStyle.startCapStyle = buttCap; dpo.pathStyle.evenOddWinding = 0; dpo.pathStyle.useDashPattern = 0; dpo.pathStyle.unused = 0; dpo.pathStyle.triCapWidth = 0; dpo.pathStyle.triCapLength = 0; BUFFER(dpo); pointZero(); } static void DrawPathWidth(double lw) { ((DrawPathObject *)DrawBuffer)->outlineWidth = (int)(16*lw); /* ??? */ } static unsigned int colours[] = { COLOUR( 0, 0,255), COLOUR( 0,255, 0), COLOUR(255, 0, 0), COLOUR(127, 0,255), COLOUR( 0, 0,127), COLOUR( 0,127, 0), COLOUR(200, 0, 0), COLOUR(127, 0,127), COLOUR(127, 0,255), COLOUR(127,127, 0), COLOUR(127,255,255), COLOUR(127,127,127), COLOUR(255,255,255), COLOUR( 0,255, 0), COLOUR( 0, 0,255), COLOUR(255, 0, 0), COLOUR( 0,255, 0), COLOUR( 0, 0, 0) }; static void DrawPathFill(int fill) { ((DrawPathObject *)DrawBuffer)->fill.colour = colours[fill%22]; } static void DrawPathEnd(void) { DrawPathObject0 end; end.type = DRAWPATH_END; BUFFER(end); } static void DrawPathStroke(void) { if(DrawKind == Closed) { DrawPathObject0 close; close.type = DRAWPATH_CLOSE; BUFFER(close); } DrawPathEnd(); ((DrawPathObject *)DrawBuffer)->header.size = (DrawBufferPos - DrawBuffer); ((DrawPathObject *)DrawBuffer)->bounding.lowerLeft = ll; ((DrawPathObject *)DrawBuffer)->bounding.upperRight = pointInc(ur); fwrite(DrawBuffer,DrawBufferPos - DrawBuffer,1,outFile); } static void DrawPathLine(double x,double y) { DrawPathObject1 draw; DrawPosX += x; DrawPosY += y; draw.type = DRAWPATH_DRAW; draw.p[0] = point(DrawPosX,DrawPosY); BUFFER(draw); } static void DrawPathLineTo(double x,double y) { DrawPathObject1 draw; DrawPosX = x; DrawPosY = y; draw.type = DRAWPATH_DRAW; draw.p[0] = point(DrawPosX,DrawPosY); BUFFER(draw); } static void DrawPathMoveTo(double x,double y) { DrawPathObject1 draw; DrawPosX = x; DrawPosY = y; draw.type = DRAWPATH_MOVE; draw.p[0] = point(x,y); BUFFER(draw); } /* Text */ static void DrawTextNew(double x,double y, int font) { DrawTextObject dto; DrawBufferPos = DrawBuffer; DrawPosX = DrawPosY = 0; dto.header.type = DRAW_TEXTOBJECT; dto.header.size = 0; /* size not known yet */ dto.bounding.lowerLeft = point(0.0,0.0); dto.bounding.upperRight = point(0.0,0.0); dto.forground.colour = BLACK; dto.background.colour = WHITE; dto.fontNumber = USE_FONT; dto.xSize = dto.ySize = 640*FontSize(font); dto.start = point(x,y); BUFFER(dto); pointZero(); } static void DrawTextAdd(char *str) { BUFFERSIZE(str[0],strlen(str)); } TransMat idTrans(void) { TransMat t; t.xfx = t.yfy = 1<<16; t.xfy = t.yfx = 0<<16; t.tx = t.ty = 0; return t; } TransMat rot90Trans(TransMat x) { x.xfx = 0<<16; x.xfy = 1<<16; x.yfx = -1<<16; x.yfy = 0<<16; return x; } static void DrawTextRotate90(void) { DrawTransTextObject *dto = (DrawTransTextObject *)DrawBuffer; if(dto->header.type == DRAW_TEXTOBJECT) { char *dst = DrawBufferPos + TRANS_SIZE; char *src = DrawBufferPos; while(src >= DrawBuffer) *dst-- = *src--; dto->header.type = DRAW_TRANSTEXTOBJECT; dto->fontFlag = 0; dto->trans = idTrans(); DrawBufferPos += TRANS_SIZE; } dto->trans = rot90Trans(dto->trans); } static void DrawTextStroke(void) { char str[4]; int pad = (unsigned int)DrawBufferPos; DrawTextObject *dto = (DrawTextObject *)DrawBuffer; DrawTextObject *dtto = (DrawTextObject *)DrawBuffer; str[0] = str[1] = str[2] = str[3] = 0; BUFFERSIZE(str[0],4-(3 & pad)); dto->header.size = (DrawBufferPos - DrawBuffer); if(dto->header.type == DRAW_TRANSTEXTOBJECT) dtto = (DrawTextObject *)(DrawBuffer+TRANS_SIZE); dto->bounding.lowerLeft.x = dtto->start.x + 0; dto->bounding.lowerLeft.y = dtto->start.y + 0; dto->bounding.upperRight.x = dtto->start.x + 1*2560; dto->bounding.upperRight.y = dtto->start.y + strlen(DrawBuffer+sizeof(DrawTextObject))*2560; fwrite(DrawBuffer,DrawBufferPos - DrawBuffer,1,outFile); } /* Font Table */ static void DrawFontTableNew(void) { DrawFontTableObject dfto; DrawBufferPos = DrawBuffer; DrawPosX = DrawPosY = 0; dfto.header.type = DRAW_FONTTABLEOBJECT; dfto.header.size = 0; /* size not known yte */ BUFFER(dfto); pointZero(); } static void DrawFontTableAdd(unsigned char fontnumber, char *fontname) { char str[4]; int pad = (unsigned int)DrawBufferPos; BUFFERSIZE(fontnumber,1); BUFFERSIZE(fontname[0],strlen(fontname)); str[0] = str[1] = str[2] = str[3] = 0; BUFFERSIZE(str[0],4-(3 & pad)); } static void DrawFontTableStroke(void) { DrawFontTableObject *dfto = (DrawFontTableObject *)DrawBuffer; dfto->header.size = (DrawBufferPos - DrawBuffer); fwrite(DrawBuffer,DrawBufferPos - DrawBuffer,1,outFile); } static void DrawFonts(void) { DrawFontTableNew(); DrawFontTableAdd(USE_FONT,"Homerton.Medium"); DrawFontTableStroke(); } static void DrawText(Justify just,double x,double y,int font,char *str) { switch(just) { case JustifyLeft: break; case JustifyCenter: x -= stringSize(str)/2; break; case JustifyRight: x -= stringSize(str); break; case JustifyVertical: y -= stringSize(str); break; } DrawTextNew(x,y,font); DrawTextAdd(str); if(just == JustifyVertical) DrawTextRotate90(); DrawTextStroke(); } static void DrawPrologue(void) { return; } Format DrawOutput = {".draw" ,DrawPrelude ,DrawPrologue ,DrawScale ,DrawLandscape ,DrawPortrait ,DrawFonts ,DrawText ,DrawPathNew ,DrawPathMoveTo ,DrawPathLineTo ,DrawPathLine ,DrawPathFill ,DrawPathWidth ,DrawPathStroke };