Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/src/hp2graph/draw.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#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
 };

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].