/*------------------------------------------------------------------
Copyright (c) Uisang Hwang 2011
LibTG : Library for Technical Graph v0.01
Tested on
Visual C++ 2005
Visual C++ 2010
Open Watcom C/C++ v1.9
Permission to use, copy, modify, and distribute this software
for any use is hereby granted provided
this notice is kept intact within the source file
Existing Bugs:
1. the disk memory option of Export BMP doesn't work
------------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h> /*... memset() ...*/
#include <stdio.h> /*... fprintf() ...*/
#include <math.h> /*... fabs() ...*/
#include <ctype.h> /*... toupper() ...*/
#include "libtg.h"
#ifdef __cplusplus
extern "C" {
#endif
#define InchToTwip (1270.0f)
#define POINTS 72.0f
#define _pi 3.141592653589793238
#ifndef NULL
#define NULL 0
#endif
#define MAX_DEFAULT_COLOR 17
#define MAX_DEFAULT_SYMBOL 7
#define _to_twip(x) ((x)*InchToTwip)
/*-------------------------------------------------------------------*/
typedef struct TG_PlotAttribute_ /* plot attribute for a line */
{
TG_Real thk; /* Line thickness */
ulong cur_pen_color, prv_pen_color;
}
TG_PlotAttr,
*TG_PlotAttr_Ptr;
/*-------------------------------------------------------------------*/
static const int sym_circle_point = 12;
static const int sym_delta_point = 3;
static const int sym_gradient_point = 3;
static const int sym_rtriangle_point = 3;
static const int sym_ltriangle_point = 3;
static const int sym_diamond_point = 4;
static const int sym_square_point = 4;
static TG_Real sym_circlex[13];
static TG_Real sym_circley[13];
static TG_Real sym_deltax[4];
static TG_Real sym_deltay[4];
static TG_Real sym_gradientx[4];
static TG_Real sym_gradienty[4];
static TG_Real sym_rtrianglex[4];
static TG_Real sym_rtriangley[4];
static TG_Real sym_ltrianglex[4];
static TG_Real sym_ltriangley[4];
static TG_Real sym_diamondx[5];
static TG_Real sym_diamondy[5];
static TG_Real sym_squarex[5];
static TG_Real sym_squarey[5];
static void TG_ComputeCircleSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly);
static void TG_ComputeDeltaSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly);
static void TG_ComputeGradientSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly);
static void TG_ComputeRTriangleSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly);
static void TG_ComputeLTriangleSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly);
static void TG_ComputeDiamondSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly);
static void TG_ComputeSquareSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly);
typedef void(*TG_ComputeSymbol)(TG_Real,TG_Real,TG_Real,TG_Real);
typedef struct TG_SymbolPool_
{
int npoint;
TG_Real line_thk;
TG_Real* pointx;
TG_Real* pointy;
TG_ComputeSymbol TG_ComputeSymbolCoordinate;
}
*TG_SymbolPool_Ptr,
TG_SymbolPool;
TG_SymbolPool symbol_pool[] =
{
{ 12, 0.01f, sym_circlex , sym_circley , TG_ComputeCircleSymbol },
{ 3, 0.01f, sym_deltax , sym_deltay , TG_ComputeDeltaSymbol },
{ 3, 0.01f, sym_gradientx , sym_gradienty , TG_ComputeGradientSymbol },
{ 3, 0.01f, sym_rtrianglex, sym_rtriangley, TG_ComputeRTriangleSymbol },
{ 3, 0.01f, sym_ltrianglex, sym_ltriangley, TG_ComputeLTriangleSymbol },
{ 4, 0.01f, sym_diamondx , sym_diamondy , TG_ComputeDiamondSymbol },
{ 4, 0.01f, sym_squarex , sym_squarey , TG_ComputeSquareSymbol },
/*... User defined symbol ...*/
{ 0, 0.01f, NULL, NULL, NULL },
{ 0, 0.01f, NULL, NULL, NULL }
};
TG_PlotAttr plot_attr;
/*-------------------------------------------------------------------
* W2L : pointer to function for different coordinate system
* the default coordinate system is World whose origin is
* lower left corner. However in pixel coord system the origin
* is upper left corner.
* If you call XXXAPI_ReverseWorld2Length(1), the corner will
* be upper left corner. XXX is BMP or WMF.
*-------------------------------------------------------------------*/
typedef void(*W2L)(TG_PlotZone_Ptr,TG_Point_Ptr,TG_Point_Ptr);
typedef void(*TG_PrintError)(TG_Error);
static TG_PrintError TG_ErrorWriter = NULL;
static char TG_DefaultPaperName[40]="LETTER";
TG_Status TG_GetPaperFormat(const char *paper_name, TG_Paper_Ptr paper);
void TG_DrawLine(TG_PlotZone_Ptr p, int x1, int y1, int x2, int y2, ulong color);
/*-------------------------------------------------------------------*/
void TG_GetSymbolCoordinate(TG_Symbol sym_index, TG_Real x, TG_Real y, TG_Real lx, TG_Real ly)
{
if(sym_index < 0 || sym_index > (MAX_DEFAULT_SYMBOL-1)) return;
symbol_pool[sym_index].TG_ComputeSymbolCoordinate(x,y,lx,ly);
}
void TG_InitPlotAttr(TG_PlotAttr_Ptr p)
{
plot_attr.cur_pen_color = TG_GetColor(TG_BLACK);
plot_attr.prv_pen_color = plot_attr.cur_pen_color;
}
void TG_GetRGB(ulong c, int* r, int* g, int* b)
{
*r = c>>16;
*g = (c>>8)&0x00ff;
*b = c&0x0000ff;
}
ulong TG_GetCustomColor(int r, int g, int b)
{
return (((((ulong)r)<<16)|(((ulong)g)<<8))|(ulong)b);
}
ushort TG_ReverseUShort(ushort s)
{
return ((s>>8)|(s<<8));
}
ulong TG_GetColor(int c)
{
static ulong color_table[] = {
/* dark colors */
0x000000, /* BLACK */
0xff0000, /* RED */
0x00ff00, /* GREEN */
0x0000ff, /* BLUE */
0xffff00, /* YELLOW */
0x00ffff, /* CYAN */
0xff00ff, /* MAGENTA */
0xff8811, /* BROWN */
0x800080, /* PURPLE */
/* light colors */
0xc0c0c0, /* LIGHTGRAY*/
0x808080, /* DARKGRAY */
0x00ccff, /* LIGHTBLUE */
0x00dd33, /* LIGHTGREEN */
0x00ffee, /* LIGHTCYAN */
0xff2200, /* LIGHTRED */
0xff0022, /* LIGHTMAGENTA */
0xffffff, /* WHITE */
};
if( c < 0 || c >= MAX_DEFAULT_COLOR)
{
fprintf(stderr, "Error: Invalid color index at TG_GetColor(%d)\n"
" BLACK color will be returned\n", c);
c = TG_BLACK;
}
return color_table[c];
}
static void TG_DefaultErrorWriter(TG_Error error_number)
{
/*... under development ...*/
}
TG_Workspace_Ptr TG_InitTGLibrary(const char* paper_name)
{
TG_Status status;
TG_Workspace_Ptr workspace = (TG_Workspace_Ptr)calloc(sizeof(TG_Workspace), sizeof(char));
if(!workspace) return NULL;
memset(workspace, 0x00, sizeof(TG_Workspace));
TG_ErrorWriter = TG_DefaultErrorWriter;
status = TG_GetPaperFormat(paper_name, &workspace->paper);
if(status == TG_Fail)
{
fprintf(stderr, "%s will be used for invalid paper", TG_DefaultPaperName);
TG_GetPaperFormat(TG_DefaultPaperName, &workspace->paper);
}
return workspace;
}
void TG_CloseTGLibrary(TG_Workspace_Ptr workspace)
{
if(workspace) { free(workspace); workspace = NULL; }
}
void TG_SetFrame(TG_Frame_Ptr f, TG_Real sx, TG_Real sy, TG_Real width, TG_Real height,
TG_Real minx, TG_Real maxx, TG_Real miny, TG_Real maxy)
{
f->frame_size.sx = sx;
f->frame_size.sy = sy;
f->frame_size.width = width;
f->frame_size.height = height;
f->minx = minx;
f->maxx = maxx;
f->miny = miny;
f->maxy = maxy;
f->fxl = width / (TG_Real)fabs(maxx-minx);
f->fyl = height / (TG_Real)fabs(maxy-miny);
f->fx = (f->fxl>f->fyl?f->fyl:f->fxl);
}
void TG_ToUpper(char *s)
{
while(*s) *s++ = toupper(*s);
}
void TG_FindPaperSeries(const char *paper_name, int *start)
{
int i, len = strlen(paper_name);
*start = -1;
for(i = 0; i < len; i++)
{
if(paper_name[i] == 'A') { *start = 0; break; }
else if(paper_name[i] == 'B') { *start = 13; break; }
else if(paper_name[i] == 'C') { *start = 24; break; }
else if(paper_name[i] == 'L') { *start = 35; break; }
}
}
TG_Error TG_GetPaperFormat(const char *paper_name, TG_Paper_Ptr paper)
{
/* Total number of paper types: 13+11*2+1 = 36 */
static const int total_paper_format = 36;
static TG_Paper paper_library[] =
{
/* A Series Format: 13 */
{ "2A0", 46.75f , 66.25f , 1189.0f, 682.0f }, /* 2A0 46 3/4 �� 66 1/4 1189 ��1682 */
{ "A0" , 33.0f , 46.75f , 841.0f , 1189.0f }, /* A0 33 �� 46 3/4 841 �� 1189 */
{ "A1" , 23.375f, 33.0f , 594.0f , 841.0f }, /* A1 23 3/8 �� 33 594 �� 841 */
{ "4A0", 66.25f , 93.625f, 1682.0f, 378.0f }, /* 4A0 66 1/4 �� 93 5/8 1682 ��2378 */
{ "A2" , 16.5f , 23.375f, 420.0f , 594.0f }, /* A2 16 1/2 �� 23 3/8 420 �� 594 */
{ "A3" , 11.75f , 16.5f , 297.0f , 420.0f }, /* A3 11 3/4 �� 16 1/2 297 �� 420 */
{ "A4" , 8.25f , 11.75f , 210.0f , 297.0f }, /* A4 8 1/4 �� 11 3/4 210 �� 297 */
{ "A5" , 5.875f , 8.25f , 148.0f , 210.0f }, /* A5 5 7/8 �� 8 1/4 148 �� 210 */
{ "A6" , 4.125f , 5.875f , 105.0f , 148.0f }, /* A6 4 1/8 �� 5 7/8 105 �� 148 */
{ "A7" , 2.875f , 4.125f , 74.0f , 105.0f }, /* A7 2 7/8 �� 4 1/8 74 �� 105 */
{ "A8" , 2.0f , 2.875f , 52.0f , 74.0f }, /* A8 2 �� 2 7/8 52 �� 74 */
{ "A9" , 1.5f , 2.0f , 37.0f , 52.0f }, /* A9 1 1/2 �� 2 37 �� 52 */
{ "A10", 1.0f , 1.5f , 26.0f , 37.0f }, /* A10 1 �� 1 1/2 26 �� 37 */
/* B Series Format: 11 */
{ "B0" , 39.375f , 55.75f , 1000.0f, 1414.0f}, /* B0 39 3/8 �� 55 3/4 1000 �� 1414*/
{ "B1" , 27.75f , 39.375f , 707.0f , 1000.0f}, /* B1 27 3/4 �� 39 3/8 707 �� 1000*/
{ "B2" , 19.75f , 27.75f , 500.0f , 707.0f }, /* B2 19 3/4 �� 27 3/4 500 �� 707 */
{ "B3" , 13.875f , 19.75f , 353.0f , 500.0f }, /* B3 13 7/8 �� 19 3/4 353 �� 500 */
{ "B4" , 9.875f , 13.875f , 250.0f , 353.0f }, /* B4 9 7/8 �� 13 7/8 250 �� 353 */
{ "B5" , 7.0f , 9.875f , 176.0f , 250.0f }, /* B5 7 �� 9 7/8 176 �� 250 */
{ "B6" , 4.875f , 7.0f , 125.0f , 176.0f }, /* B6 4 7/8 �� 7 125 �� 176 */
{ "B7" , 3.5f , 4.875f , 88.0f , 125.0f }, /* B7 3 1/2 �� 4 7/8 88 �� 125 */
{ "B8" , 2.5f , 3.5f , 62.0f , 88.0f }, /* B8 2 1/2 �� 3 1/2 62 �� 88 */
{ "B9" , 1.75f , 2.5f , 44.0f , 62.0f }, /* B9 1 3/4 �� 2 1/2 44 �� 62 */
{ "B10", 1.25f , 1.75f , 31.0f , 44.0f }, /* B10 1 1/4 �� 1 3/4 31 �� 44 */
/* C Series Formats: 11 */
{ "C0" , 36.0f , 51.0f , 917.0f, 1297.0f}, /* C0 36 �� 51 917 �� 1297 */
{ "C1" , 25.5f , 36.0f , 648.0f, 917.0f }, /* C1 25 1/2 �� 36 648 �� 917 */
{ "C2" , 18 , 25.5f , 458.0f, 648.0f }, /* C2 18 �� 25 1/2 458 �� 648 */
{ "C3" , 12.75f , 18.0f , 324.0f, 458.0f }, /* C3 12 3/4 �� 18 324 �� 458 */
{ "C4" , 9 , 12.75f , 229.0f, 324.0f }, /* C4 9 �� 12 3/4 229 �� 324 */
{ "C5" , 6.375f , 9.0f , 162.0f, 229.0f }, /* C5 6 3/8 �� 9 162 �� 229 */
{ "C6" , 4.5f , 6.375f , 114.0f, 162.0f }, /* C6 4 1/2 �� 6 3/8 114 �� 162 */
{ "C7" , 3.1875f, 4.5f , 81.0f , 114.0f }, /* C7 3 3/16 �� 4 1/2 81 �� 114 */
{ "C8" , 2.25f , 3.1875f, 57.0f , 81.0f }, /* C8 2 1/4 �� 3 3/16 57 �� 81 */
{ "C9" , 1.625f , 2.25f , 40.0f , 57.0f }, /* C9 1 5/8 �� 2 1/4 40 �� 57 */
{ "C10", 1.125 , 1.625f , 28.0f , 40.0f }, /* C10 1 1/8 �� 1 5/8 28 �� 40 */
/* US: Letter */
{ "LETTER" , 8.5f, 11.0f, 215.8915f, 279.389f}/* Letter 11 ��8.5 */
};
int i, start=-1;
char name_buffer[80];
strcpy(name_buffer, paper_name);
TG_ToUpper(name_buffer);
TG_FindPaperSeries(name_buffer, &start);
if(start < 0) start = total_paper_format-1; /* set Letter as default paper */
for(i = start; i < total_paper_format; i++)
{
if(strcmp(paper_library[i].series_name, paper_name) ==0)
{
strcpy(paper->series_name, paper_library[i].series_name);
paper->width_inch = paper_library[i].width_inch;
paper->height_inch = paper_library[i].height_inch;
paper->width_mm = paper_library[i].width_mm;
paper->height_mm = paper_library[i].height_mm;
return TG_Success;
}
}
return TG_ERROR_INVALID_PAPERNAME; // no appropriate paper exist
}
#ifdef __EXPORT_BMP__
/*
Bitmap file format
http://en.wikipedia.org/wiki/BMP_file_format
*/
/*... BITMAP file header ...*/
#ifdef __TURBOC__
typedef ulong uint32_t;
typedef ushort uint16_t;
#else
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
#endif
/*... Bytes per pixel ...*/
static const int BYTEPP_V3 = 3;
static const int STD_V3BMP_HEADER_SIZE = 54;
typedef struct bmpfile_magic_ {
unsigned char magic[2];
} bmpfile_magic;
typedef struct bmpfile_header_
{
uint32_t filesz;
uint16_t creator1;
uint16_t creator2;
uint32_t bmp_offset;
} bmpfile_header;
typedef struct BitmapFileHeader_
{
bmpfile_magic magicNumber;
bmpfile_header fileHeader;
}
BitmapFileHeader, *BitmapFileHeader_Ptr;
/*... BITMAP info header ...*/
typedef struct BitmapInfoHeader_
{
uint32_t header_sz;
uint32_t width;
uint32_t height;
uint16_t nplanes;
uint16_t bitspp;
uint32_t compress_type;
uint32_t bmp_bytesz;
uint32_t hres;
uint32_t vres;
uint32_t ncolors;
uint32_t nimpcolors;
}
bmp_dib_v3_header_t, BitmapInfoHeader, *BitmapInfoHeader_Ptr;
typedef struct BitmapDevice_
{
BitmapFileHeader file;
BitmapInfoHeader info;
FILE* writer;
int scanline_length;
int prv_x, prv_y;
int mem_disk, mem_disk_fail;
int prv_xpos, prv_ypos;
TG_Real scale_ppi;
ubyte *raw_data;
W2L world2length;
}
BitmapDevice, *BitmapDevice_Ptr;
BitmapDevice bmp_device;
void BMPAPI_World2Length(TG_PlotZone_Ptr p, TG_Point_Ptr w, TG_Point_Ptr l)
{
l->x = (w->x-p->frame.minx) * p->frame.fx;
l->y = p->frame.frame_size.height-(w->y-p->frame.miny) * p->frame.fx;
}
void BMPAPI_ReverseWorld2Length(TG_PlotZone_Ptr p, TG_Point_Ptr w, TG_Point_Ptr l)
{
l->x = (w->x-p->frame.minx) * p->frame.fx;
l->y = (w->y-p->frame.miny) * p->frame.fx;
}
void TG_BMP_SetReverseWorldCoord(int coord)
{
if(coord==0) bmp_device.world2length = BMPAPI_World2Length;
else bmp_device.world2length = BMPAPI_ReverseWorld2Length;
}
void BMPAPI_Length2Pixel(TG_PlotZone_Ptr p, TG_Point_Ptr l, TG_Point_Ptr x)
{
x->x = (l->x) * bmp_device.scale_ppi;
x->y = (l->y) * bmp_device.scale_ppi;
}
void BMPAPI_SetPixel(int x, int y, TG_Color c)
{
int r, g, b;
ulong mem_size=0;
ubyte* mem_ptr=NULL;
TG_GetRGB(c, &r, &g, &b);
if(x < 0 || x >= bmp_device.info.width ||
y < 0 || y >= bmp_device.info.height)
{
/*... the error message make a program slow ...*/
/*fprintf(stderr, "Error: x, y exceeds image size at BMPAPI_SetPixel(%d,%d)\n", x,y);*/
return;
}
if(bmp_device.mem_disk && !bmp_device.mem_disk_fail)
{
mem_size = bmp_device.scanline_length*
(bmp_device.info.height-(y+1))+x*3;
mem_ptr = &bmp_device.raw_data[mem_size];
*mem_ptr++ = b;
*mem_ptr++ = g;
*mem_ptr = r;
}
else {
mem_size = STD_V3BMP_HEADER_SIZE+bmp_device.scanline_length*
(bmp_device.info.height-(y+1))+x*3;
fseek(bmp_device.writer, mem_size, SEEK_SET);
fputc(b, bmp_device.writer);
fputc(g, bmp_device.writer);
fputc(r, bmp_device.writer);
}
return;
}
void BMPAPI_SetPixel1(TG_PlotZone_Ptr p, TG_Real x, TG_Real y, TG_Color c)
{
/* wc: World Coordinate
lc: logical Coordinate
pc: physical Coordinate */
TG_Point wc, lc, pc;
wc.x = x, wc.y = y;
bmp_device.world2length(p, &wc, &lc);
BMPAPI_Length2Pixel(p, &lc, &pc);
BMPAPI_SetPixel(pc.x, pc.y, c);
}
void BMPAPI_SetPixel2(TG_PlotZone_Ptr p, int x, int y, TG_Color c)
{
BMPAPI_SetPixel(x, y, c);
}
void BMPAPI_MakePen(TG_PlotZone_Ptr p, TG_Color c, TG_Real thk)
{
plot_attr.prv_pen_color = plot_attr.cur_pen_color;
plot_attr.cur_pen_color = c;
}
void BMPAPI_DeletePen(void)
{
plot_attr.cur_pen_color = plot_attr.prv_pen_color;
plot_attr.thk = 0;
}
void BMPAPI_MoveTo(TG_PlotZone_Ptr p, TG_Real x, TG_Real y)
{
/* wc: World Coordinate
lc: logical Coordinate
pc: physical Coordinate */
TG_Point wc, lc, pc;
wc.x = x, wc.y = y;
bmp_device.world2length(p, &wc, &lc);
BMPAPI_Length2Pixel(p, &lc, &pc);
bmp_device.prv_xpos = (int)pc.x;
bmp_device.prv_ypos = (int)pc.y;
}
void BMPAPI_LineTo(TG_PlotZone_Ptr p, TG_Real x, TG_Real y)
{
/* wc: World Coordinate
lc: logical Coordinate
pc: physical Coordinate */
TG_Point wc, lc, pc;
wc.x = x, wc.y = y;
bmp_device.world2length(p, &wc, &lc);
BMPAPI_Length2Pixel(p, &lc, &pc);
TG_DrawLine(p, bmp_device.prv_xpos, bmp_device.prv_ypos,
pc.x, pc.y, plot_attr.cur_pen_color);
bmp_device.prv_xpos = (int)pc.x;
bmp_device.prv_ypos = (int)pc.y;
}
void BMPAPI_Line(TG_PlotZone_Ptr p, TG_Real x1, TG_Real y1, TG_Real x2, TG_Real y2, TG_Color color, TG_Real thk)
{
BMPAPI_MakePen(p, color, thk);
BMPAPI_MoveTo(p, x1, y1);
BMPAPI_LineTo(p, x2, y2);
BMPAPI_DeletePen();
}
TG_Color BMPAPI_GetPixel(x,y)
{
ulong mem_size=0;
ubyte* mem_ptr=NULL;
int r,g,b;
int width = bmp_device.info.width;
int height = bmp_device.info.height;
if(x < 0 || x >= width || y < 0 || y >= height)
{
/*... the error message make a program slow ...*/
/*fprintf(stderr, "Error: x, y exceeds image size at BMPAPI_GetPixel(%d,%d)\n", x,y);*/
}
if(x < 0) x = 0;
if(x >= width) x = width-2;
if(y < 0) y = 0;
if(y >= height) y = height-2;
if(bmp_device.mem_disk && !bmp_device.mem_disk_fail)
{
mem_size = bmp_device.scanline_length*
(bmp_device.info.height-(y+1))+x*3;
mem_ptr = &bmp_device.raw_data[mem_size];
b = *mem_ptr++;
g = *mem_ptr++;
r = *mem_ptr;
}
else {
mem_size = STD_V3BMP_HEADER_SIZE+bmp_device.scanline_length*
(bmp_device.info.height-(y+1))+x*3;
fseek(bmp_device.writer, mem_size, SEEK_SET);
b = fgetc(bmp_device.writer);
g = fgetc(bmp_device.writer);
r = fgetc(bmp_device.writer);
}
return TG_GetCustomColor(r,g,b);
}
void BMPAPI_DrawHorizLine(TG_PlotZone_Ptr p, int x1, int x2, int y, TG_Color c)
{
while(x1 <= x2) BMPAPI_SetPixel2(p, x1++, y, c);
}
/* Learning Algorithms in C, Jaekyu Lee 1996 published in South Korea */
int BMPAPI_ScanLeft(int x, int y, TG_Color fc, TG_Color bc)
{
TG_Color v;
v = BMPAPI_GetPixel(x,y);
while( v != fc && v != bc && x >= 0)
v = BMPAPI_GetPixel(--x, y);
x++;
return x;
}
int BMPAPI_ScanRight(int x, int y,TG_Color fc, TG_Color bc)
{
TG_Color v;
v = BMPAPI_GetPixel(x,y);
while( v != fc && v != bc && x < bmp_device.info.width)
v = BMPAPI_GetPixel(++x, y);
x--;
return x;
}
#define NOT_DRAWN 0
#define BELOW_DRAWN 1
#define UPPER_DRAWN 2
int BMPAPI_LineFill(TG_PlotZone_Ptr p, int sx, int sy, TG_Color c, TG_Color bc, int pl, int pr, int flag)
{
int x, y;
TG_Color v;
int xleft, xright;
xleft = xright = sx;
y = sy;
if(sx < 0) return 0;
if(sx >= bmp_device.info.width) return bmp_device.info.width-1;
xleft = BMPAPI_ScanLeft(sx, sy, c, bc);
xright = BMPAPI_ScanRight(sx, sy, c, bc);
BMPAPI_DrawHorizLine(p, xleft, xright, y, c);
if(flag == UPPER_DRAWN)
{
for(x = xleft; x < pl; x++)
{
v = BMPAPI_GetPixel(x, y-1);
if(v != c && v != bc)
x = BMPAPI_LineFill(p, x, y-1, c, bc, xleft, xright, BELOW_DRAWN);
}
for(x = pr+1; x <= xright; x++)
{
v = BMPAPI_GetPixel(x, y-1);
if(v != c && v != bc)
x = BMPAPI_LineFill(p, x, y-1, c, bc, xleft, xright, BELOW_DRAWN);
}
}
else
{
for(x = xleft; x <= xright; x++)
{
v = BMPAPI_GetPixel(x, y-1);
if(v != c && v != bc)
x = BMPAPI_LineFill(p, x, y-1, c, bc, xleft, xright, BELOW_DRAWN);
}
}
if(flag == BELOW_DRAWN)
{
for(x = xleft; x < pl; x++)
{
v = BMPAPI_GetPixel(x, y+1);
if(v != c && v != bc)
x = BMPAPI_LineFill(p, x, y+1, c, bc, xleft, xright, UPPER_DRAWN);
}
for(x = pr+1; x <= xright; x++)
{
v = BMPAPI_GetPixel(x, y+1);
if(v != c && v != bc)
x = BMPAPI_LineFill(p, x, y+1, c, bc, xleft, xright, UPPER_DRAWN);
}
}
else
{
for(x = xleft; x <= xright; x++)
{
v = BMPAPI_GetPixel(x, y+1);
if(v != c && v != bc)
x = BMPAPI_LineFill(p, x, y+1, c, bc, xleft, xright, UPPER_DRAWN);
}
}
return xright;
}
/*... End of Learning Algorithms in C ...*/
/* lc : outline color */
void BMPAPI_Polyline(TG_PlotZone_Ptr p, TG_Real* x, TG_Real* y, int npoint, TG_Color lc, TG_Real lthk)
{
/* wc: World Coordinate
gc: logical Coordinate
pc: physical Coordinate */
TG_Point wc, gc, pc;
int i=0;
int* xx = (int*)malloc(sizeof(int)*npoint);
int* yy = (int*)malloc(sizeof(int)*npoint);
if(!xx || !yy) {
if(xx) free(xx);
if(yy) free(yy);
fprintf(stderr, "Error: not enough memory at BMPAPI_Polygon\n");
return;
}
for(i = 0; i < npoint; i++)
{
wc.x = x[i], wc.y = y[i];
bmp_device.world2length(p, &wc, &gc);
BMPAPI_Length2Pixel(p, &gc, &pc);
xx[i] = pc.x;
yy[i] = pc.y;
}
xx[i] = xx[0];
yy[i] = yy[0];
for(i = 0; i < npoint; i++)
{
TG_DrawLine(p, xx[i], yy[i], xx[i+1], yy[i+1], lc);
}
}
void BMPAPI_Polygon(TG_PlotZone_Ptr p, TG_Real* x, TG_Real* y, int npoint, TG_Color fc)
{
/* wc: World Coordinate
lc: logical Coordinate
pc: physical Coordinate */
TG_Point wc, lc, pc;
TG_Real px,py;
int i = 0;
int* xx = (int*)malloc(sizeof(int)*(npoint+1));
int* yy = (int*)malloc(sizeof(int)*(npoint+1));
if(!xx || !yy) {
if(xx) free(xx);
if(yy) free(yy);
fprintf(stderr, "Error: not enough memory at BMPAPI_Polygon\n");
return;
}
px = py = 0;
for(i = 0; i < npoint; i++)
{
wc.x = x[i], wc.y = y[i];
bmp_device.world2length(p, &wc, &lc);
BMPAPI_Length2Pixel(p, &lc, &pc);
xx[i] = pc.x;
yy[i] = pc.y;
px += pc.x;
py += pc.y;
}
xx[i] = xx[0];
yy[i] = yy[0];
i=0;
while(i < npoint) { TG_DrawLine(p, xx[i], yy[i], xx[i+1], yy[i+1], fc); i++;}
/*... find the cetroid of the polygon ...*/
px /= npoint;
py /= npoint;
BMPAPI_LineFill(p, px, py, fc, fc, 0,0,0);
}
void BMPAPI_Symbol(TG_PlotZone_Ptr p, TG_Real x, TG_Real y, TG_Symbol sym, TG_Real size, TG_Color fc, int fill, TG_Color lc, int line, TG_Real lthk)
{
/* wc: World Coordinate
gc: logical Coordinate
pc: physical Coordinate */
TG_Point wc, gc, pc;
int x1, x2, y1, y2, px, py, i;
int sym_size = (int)(size*p->frame.frame_size.height/p->frame.fx);
if(sym < 0 || sym > (MAX_DEFAULT_SYMBOL-1)) return;
/*... No symbol drawing ...*/
if(fill == 0 && line == 0) return;
TG_GetSymbolCoordinate(sym, sym_size, 1, x, y);
BMPAPI_Polygon (p, symbol_pool[sym].pointx, symbol_pool[sym].pointy, symbol_pool[sym].npoint, TG_GetCustomColor(0x99, 0xcc, 0xcc));
if(fill == 1)
{
for(i = 0; i < symbol_pool[sym].npoint; i++)
{
wc.x = symbol_pool[sym].pointx[i];
wc.y = symbol_pool[sym].pointy[i];
bmp_device.world2length(p, &wc, &gc);
BMPAPI_Length2Pixel(p, &gc, &pc);
x1 = pc.x;
y1 = pc.y;
wc.x = symbol_pool[sym].pointx[i+1];
wc.y = symbol_pool[sym].pointy[i+1];
bmp_device.world2length(p, &wc, &gc);
BMPAPI_Length2Pixel(p, &gc, &pc);
x2 = pc.x;
y2 = pc.y;
TG_DrawLine(p, x1, y1, x2, y2, lc);
}
wc.x = x, wc.y = y;
bmp_device.world2length(p, &wc, &gc);
BMPAPI_Length2Pixel(p, &gc, &pc);
px = pc.x;
py = pc.y;
BMPAPI_LineFill(p, px, py, fc, lc, 0,0,0);
}
}
void BMPAPI_gSave(void)
{
}
void BMPAPI_gRestore(void)
{
}
int TG_BMP_OpenExport(TG_PlotZone* p, const char* file, int wid, int hgt, int memory)
{
int BPP = 24;
int raw_data_size = (int)(((BPP*wid)/32.0)*4);
int remainder = raw_data_size%4;
int padding_size = remainder==0?0:4-remainder;
TG_Real ppix=0, ppiy=0;
int scan_line_size = raw_data_size+padding_size;
int raw_data_length = scan_line_size*hgt;
BitmapFileHeader_Ptr bfh = &bmp_device.file;
BitmapInfoHeader_Ptr bih = &bmp_device.info;
FILE* writer = NULL;
bmp_device.scanline_length = scan_line_size;
bmp_device.writer = fopen(file, "wb");
if(!bmp_device.writer) {
fprintf(stderr, "Error: can't open %s at TG_BMP_OpenExport", file);
return 0;
}
writer = bmp_device.writer;
bfh->magicNumber.magic[0] = 'B';
bfh->magicNumber.magic[1] = 'M';
bfh->fileHeader.filesz = STD_V3BMP_HEADER_SIZE+raw_data_length;
bfh->fileHeader.creator1 = 0;
bfh->fileHeader.creator2 = 0;
bfh->fileHeader.bmp_offset = STD_V3BMP_HEADER_SIZE;
bih->header_sz = sizeof(BitmapInfoHeader);
bih->width = wid;
bih->height = hgt;
bih->nplanes = 1;
bih->bitspp = 24;
bih->compress_type = 0; /* BI_RGB none */
bih->bmp_bytesz = raw_data_length;
/*
72 Dots/Inch
------------* 100 Cm/Meter = 2834.6
2.54 Cm/Inch
*/
bih->hres = 2835;
bih->vres = 2835;
bih->ncolors = 0;
bih->nimpcolors = 0;
/*... WRITE BMP FILE HEADER:14 ...*/
fwrite(bfh->magicNumber.magic , 2, sizeof(ubyte), writer);
fwrite(&bfh->fileHeader.filesz , 4, sizeof(ubyte), writer);
fwrite(&bfh->fileHeader.creator1 , 2, sizeof(ubyte), writer);
fwrite(&bfh->fileHeader.creator2 , 2, sizeof(ubyte), writer);
fwrite(&bfh->fileHeader.bmp_offset, 4, sizeof(ubyte), writer);
/*... WRITE BMP INFO HEADER:40 ...*/
fwrite(&bih->header_sz , 4, sizeof(ubyte), writer);
fwrite(&bih->width , 4, sizeof(ubyte), writer);
fwrite(&bih->height , 4, sizeof(ubyte), writer);
fwrite(&bih->nplanes , 2, sizeof(ubyte), writer);
fwrite(&bih->bitspp , 2, sizeof(ubyte), writer);
fwrite(&bih->compress_type, 4, sizeof(ubyte), writer);
fwrite(&bih->bmp_bytesz , 4, sizeof(ubyte), writer);
fwrite(&bih->hres , 4, sizeof(ubyte), writer);
fwrite(&bih->vres , 4, sizeof(ubyte), writer);
fwrite(&bih->ncolors , 4, sizeof(ubyte), writer);
fwrite(&bih->nimpcolors , 4, sizeof(ubyte), writer);
bmp_device.raw_data = NULL;
bmp_device.mem_disk = memory;
bmp_device.mem_disk_fail = 0;
if(memory) {
bmp_device.raw_data = (ubyte*)calloc(bih->bmp_bytesz, sizeof(ubyte));
if(!bmp_device.raw_data) {
printf("Warning: allocating memory disk, not enough memory\n");
bmp_device.mem_disk_fail = 1;
}
else memset(bmp_device.raw_data, 0xff, bih->bmp_bytesz*sizeof(ubyte));
}
if(!memory || (memory && bmp_device.mem_disk_fail)) {
ubyte dummy=0xff;
fseek(writer, STD_V3BMP_HEADER_SIZE, SEEK_SET);
fwrite(&dummy, bih->bmp_bytesz, sizeof(ubyte), writer);
}
p->plot.makepen = BMPAPI_MakePen;
p->plot.moveto = BMPAPI_MoveTo;
p->plot.line = BMPAPI_Line;
p->plot.lineto = BMPAPI_LineTo;
p->plot.putpixel1 = BMPAPI_SetPixel1;
p->plot.putpixel2 = BMPAPI_SetPixel2;
p->plot.deletepen = BMPAPI_DeletePen;
p->plot.gsave = BMPAPI_gSave;
p->plot.grestore = BMPAPI_gRestore;
p->plot.polyline = BMPAPI_Polyline;
p->plot.polygon = BMPAPI_Polygon;
p->plot.symbol = BMPAPI_Symbol;
bmp_device.prv_xpos = 0;
bmp_device.prv_ypos = 0;
if(p)
{
ppix = wid/p->frame.frame_size.width;
ppiy = hgt/p->frame.frame_size.height;
bmp_device.scale_ppi = ppix > ppiy? ppiy:ppix;
}
TG_InitPlotAttr(&plot_attr);
TG_BMP_SetReverseWorldCoord(0);
return 1;
}
void TG_BMP_CloseExport(void)
{
if(bmp_device.mem_disk && !bmp_device.mem_disk_fail) {
fwrite(bmp_device.raw_data, bmp_device.info.bmp_bytesz,
sizeof(ubyte), bmp_device.writer);
free(bmp_device.raw_data);
bmp_device.mem_disk = 0;
bmp_device.raw_data = NULL;
}
fclose(bmp_device.writer);
bmp_device.mem_disk_fail = 0;
bmp_device.writer=NULL;
}
#endif
/*
Ref:
http://www.gamedev.net/reference/articles/article1275.asp
*/
void TG_DrawLine(TG_PlotZone_Ptr p, int x1, int y1, int x2, int y2, TG_Color color)
{
int x, y, deltax, deltay, xinc1, xinc2, yinc1, yinc2;
int den, num, numadd, curpixel, numpixels;
deltax = abs(x2 - x1); /* The difference between the x's */
deltay = abs(y2 - y1); /* The difference between the y's */
x = x1; /* Start x off at the first pixel */
y = y1; /* Start y off at the first pixel */
if (x2 >= x1) /* The x-values are increasing */
{
xinc1 = 1;
xinc2 = 1;
}
else /* The x-values are decreasing */
{
xinc1 = -1;
xinc2 = -1;
}
if (y2 >= y1) /* The y-values are increasing */
{
yinc1 = 1;
yinc2 = 1;
}
else /* The y-values are decreasing */
{
yinc1 = -1;
yinc2 = -1;
}
if (deltax >= deltay) /* There is at least one x-value for every y-value */
{
xinc1 = 0; /* Don't change the x when numerator >= denominator */
yinc2 = 0; /* Don't change the y for every iteration */
den = deltax;
num = deltax / 2;
numadd = deltay;
numpixels = deltax; /* There are more x-values than y-values */
}
else /* There is at least one y-value for every x-value */
{
xinc2 = 0; /* Don't change the x for every iteration */
yinc1 = 0; /* Don't change the y when numerator >= denominator */
den = deltay;
num = deltay / 2;
numadd = deltax;
numpixels = deltay; /* There are more y-values than x-values */
}
for (curpixel = 0; curpixel <= numpixels; curpixel++)
{
p->plot.putpixel2(p, x, y, color); /* Draw the current pixel */
num += numadd; /* Increase the numerator by the top of the fraction */
if (num >= den) /* Check if numerator >= denominator */
{
num -= den; /* Calculate the new numerator value */
x += xinc1; /* Change the x as appropriate */
y += yinc1; /* Change the y as appropriate */
}
x += xinc2; /* Change the x as appropriate */
y += yinc2; /* Change the y as appropriate */
}
}
/*----------- WINDOWSMETA FILE DEVICE DRIVER ------------*/
#ifdef __EXPORT_WMF__
typedef struct StandardMetaHeader_
{
short FileType; /* 2 */
short HeaderSize; /* +2 = 4 */
short Version; /* +2 = 6 */
ulong FileSize; /* +4 = 10*/
short NumOfObjects; /* +2 = 12*/
ulong MaxRecordSize; /* +4 = 16*/
short NumOfParams; /* +2 = 18*/
}
StandardMetaHeader, *StandardMetaHeader_ptr;
typedef struct PlaceableMetaHeader_
{
ulong MagicNumber; /*... 4 Key ( always 0x9AC6CDD7 ) */
short Handle; /*... +2 Metafile HANDLE number (always 0)*/
short Left; /*... +2 Left coordinate in metafile units*/
short Top; /*... +2 Top " " */
short Right; /*... +2 Right " " */
short Bottom; /*... +2 Bottom " " */
short Inch; /*... +2 Number of metafile units per inch*/
ulong Reserved; /*... +4 Reserved (always 0)*/
short CheckSum; /*... 2 Checksum value for previous 10 words*/
} /* = 22 bytes : placeable header size*/
PlaceableMetaHeader, *PlaceableMetaHeader_ptr;
typedef struct RectWin_
{
TG_Real left, top, right, bottom;
}
RectWin, *RectWin_ptr;
typedef struct WmfHeader_
{
StandardMetaHeader smh;
PlaceableMetaHeader pmh;
}
WmfHeader, *WmfHeader_ptr;
typedef struct MetaRecord_
{
ulong Size;
ushort Function;
ushort *Parameters; /* !Reverse order */
}
MetaRecord, *MetaRecord_ptr;
typedef struct MetaDevice
{
WmfHeader header;
FILE* writer;
/* SetPixel no effect on WMF: draw pixel manually */
/* set the size as 0.001 * height of a frame */
/* I forgot the actual meaning of size and width */
TG_Real pixel_size, pixel_width;
W2L world2length;
int cur_pen, prv_pen;
int cur_brush, prv_brush;
}
MetaDevice, *MetaDevice_ptr;
/*---------- WINDOWS METAFILE HEADER GLOBAL VAR ------------*/
MetaDevice wmf_device;
int nTh_GDI_Object=-1;
static const TG_Real TG_DEFAULT_PIXEL_SIZE = .001;
static const TG_Real TG_DEFAULT_PIXEL_WIDTH = 1;
static const TG_Short TG_META_SETBKCOLOR = 0x0201;
static const TG_Short TG_META_SETBKMODE = 0x0102;
static const TG_Short TG_META_SETMAPMODE = 0x0103;
static const TG_Short TG_META_SETROP2 = 0x0104;
static const TG_Short TG_META_SETRELABS = 0x0105;
static const TG_Short TG_META_SETPOLYFILLMODE = 0x0106;
static const TG_Short TG_META_SETSTRETCHBLTMODE = 0x0107;
static const TG_Short TG_META_SETTEXTCHAREXTRA = 0x0108;
static const TG_Short TG_META_SETTEXTCOLOR = 0x0209;
static const TG_Short TG_META_SETTEXTJUSTIFICATION = 0x020A;
static const TG_Short TG_META_SETWINDOWORG = 0x020B;
static const TG_Short TG_META_SETWINDOWEXT = 0x020C;
static const TG_Short TG_META_SETVIEWPORTORG = 0x020D;
static const TG_Short TG_META_SETVIEWPORTEXT = 0x020E;
static const TG_Short TG_META_OFFSETWINDOWORG = 0x020F;
static const TG_Short TG_META_SCALEWINDOWEXT = 0x0410;
static const TG_Short TG_META_OFFSETVIEWPORTORG = 0x0211;
static const TG_Short TG_META_SCALEVIEWPORTEXT = 0x0412;
static const TG_Short TG_META_LINETO = 0x0213;
static const TG_Short TG_META_MOVETO = 0x0214;
static const TG_Short TG_META_EXCLUDECLIPRECT = 0x0415;
static const TG_Short TG_META_INTERSECTCLIPRECT = 0x0416;
static const TG_Short TG_META_ARC = 0x0817;
static const TG_Short TG_META_ELLIPSE = 0x0418;
static const TG_Short TG_META_FLOODFILL = 0x0419;
static const TG_Short TG_META_PIE = 0x081A;
static const TG_Short TG_META_RECTANGLE = 0x041B;
static const TG_Short TG_META_ROUNDRECT = 0x061C;
static const TG_Short TG_META_PATBLT = 0x061D;
static const TG_Short TG_META_SAVEDC = 0x001E;
static const TG_Short TG_META_SETPIXEL = 0x041F;
static const TG_Short TG_META_OFFSETCLIPRGN = 0x0220;
static const TG_Short TG_META_TEXTOUT = 0x0521;
static const TG_Short TG_META_BITBLT = 0x0922;
static const TG_Short TG_META_STRETCHBLT = 0x0B23;
static const TG_Short TG_META_POLYGON = 0x0324;
static const TG_Short TG_META_POLYLINE = 0x0325;
static const TG_Short TG_META_ESCAPE = 0x0626;
static const TG_Short TG_META_RESTOREDC = 0x0127;
static const TG_Short TG_META_FILLREGION = 0x0228;
static const TG_Short TG_META_FRAMEREGION = 0x0429;
static const TG_Short TG_META_INVERTREGION = 0x012A;
static const TG_Short TG_META_PAINTREGION = 0x012B;
static const TG_Short TG_META_SELECTCLIPREGION = 0x012C;
static const TG_Short TG_META_SELECTOBJECT = 0x012D;
static const TG_Short TG_META_SETTEXTALIGN = 0x012E;
static const TG_Short TG_META_DRAWTEXT = 0x062F;
static const TG_Short TG_META_CHORD = 0x0830;
static const TG_Short TG_META_SETMAPPERFLAGS = 0x0231;
static const TG_Short TG_META_EXTTEXTOUT = 0x0a32;
static const TG_Short TG_META_SETDIBTODEV = 0x0d33;
static const TG_Short TG_META_SELECTPALETTE = 0x0234;
static const TG_Short TG_META_REALIZEPALETTE = 0x0035;
static const TG_Short TG_META_ANIMATEPALETTE = 0x0436;
static const TG_Short TG_META_SETPALENTRIES = 0x0037;
static const TG_Short TG_META_POLYPOLYGON = 0x0538;
static const TG_Short TG_META_RESIZEPALETTE = 0x0139;
static const TG_Short TG_META_DIBBITBLT = 0x0940;
static const TG_Short TG_META_DIBSTRETCHBLT = 0x0b41;
static const TG_Short TG_META_DIBCREATEPATTERNBRUSH = 0x0142;
static const TG_Short TG_META_STRETCHDIB = 0x0f43;
static const TG_Short TG_META_EXTFLOODFILL = 0x0548;
static const TG_Short TG_META_RESETDC = 0x014C;
static const TG_Short TG_META_STARTDOC = 0x014D;
static const TG_Short TG_META_STARTPAGE = 0x004F;
static const TG_Short TG_META_ENDPAGE = 0x0050;
static const TG_Short TG_META_ABORTDOC = 0x0052;
static const TG_Short TG_META_ENDDOC = 0x005E;
static const TG_Short TG_META_DELETEOBJECT = 0x01f0;
static const TG_Short TG_META_CREATEPALETTE = 0x00f7;
static const TG_Short TG_META_CREATEBRUSH = 0x00F8;
static const TG_Short TG_META_CREATEPATTERNBRUSH = 0x01F9;
static const TG_Short TG_META_CREATEPENINDIRECT = 0x02FA;
static const TG_Short TG_META_CREATEFONTINDIRECT = 0x02FB;
static const TG_Short TG_META_CREATEBRUSHINDIRECT = 0x02FC;
static const TG_Short TG_META_CREATEBITMAPINDIRECT = 0x02FD;
static const TG_Short TG_META_CREATEBITMAP = 0x06FE;
static const TG_Short TG_META_CREATEREGION = 0x06FF;
static const TG_Short TG_ALTERNATE = 1;
static const TG_Short TG_WINDING = 2;
static const TG_Short TG_MM_TEXT = 1;
static const TG_Short TG_MM_LOMETRIC = 2;
static const TG_Short TG_MM_HIMETRIC = 3;
static const TG_Short TG_MM_LOENGLISH = 4;
static const TG_Short TG_MM_HIENGLISH = 5;
static const TG_Short TG_MM_TWIPS = 6;
static const TG_Short TG_MM_ISOTROPIC = 7;
static const TG_Short TG_MM_ANISOTROPIC = 8;
static const TG_Short TG_PS_SOLID = 0;
static const TG_Short TG_PS_DASH = 1;
static const TG_Short TG_PS_DOT = 2;
static const TG_Short TG_PS_DASHDOT = 3;
static const TG_Short TG_PS_DASHDOTDOT = 4;
static const TG_Short TG_PS_NULL = 5;
static const TG_Short TG_PS_INSIDEFRAME = 6;
static const TG_Short TG_BS_SOLID = 0;
static const TG_Short TG_BS_NULL = 1;
static const TG_Short TG_BS_HOLLOW = 1; //BS_NULL
static const TG_Short TG_BS_HATCHED = 2;
static const TG_Short TG_BS_PATTERN = 3;
static const TG_Short TG_BS_INDEXED = 4;
static const TG_Short TG_BS_DIBPATTERN = 5;
static const TG_Short TG_META_END = 0x0000;
#ifdef __TURBOC__
static ulong TG_META_MagicNumber = 0x9AC6CDD7;
static ulong TG_META_KeyLow = 0x0000FFFF;
static ulong TG_META_KeyHigh = 0xFFFF0000;
static ulong TG_META_END_SIZE = 0x00000003;
#else
static const int TG_META_MagicNumber = 0x9AC6CDD7;
static const int TG_META_KeyLow = 0x0000FFFF;
static const int TG_META_KeyHigh = 0xFFFF0000;
static const int META_TG_META_END_SIZE = 0x00000003;
#endif
static const int TG_META_KeyShift = 16;
static const int TG_META_DEFAULT_RECORD_SIZE = 3;
static const int TG_META_STANDARD_HEADER_SIZE = 9;
static const int TG_META_PLACEABLE_HEADER_SIZE = 11;
static const short TG_META_RESTORE_DC_PARAM = -1;
void WMFAPI_Polyline(TG_PlotZone_Ptr p, TG_Real* pointx, TG_Real* pointy, int npoint, TG_Color lc, TG_Real lthk);
void WMFAPI_Polygon(TG_PlotZone_Ptr p, TG_Real* pointx, TG_Real* pointy, int npoint, TG_Color fc);
void WMFAPI_SetPolyFillMode(short fillmode);
void WMFAPI_World2Length(TG_PlotZone_Ptr p, TG_Point_Ptr w, TG_Point_Ptr l)
{
l->x = (w->x-p->frame.minx) * p->frame.fx;
l->y = p->frame.frame_size.height-(w->y-p->frame.miny) * p->frame.fx;
}
void WMFAPI_ReverseWorld2Length(TG_PlotZone_Ptr p, TG_Point_Ptr w, TG_Point_Ptr l)
{
l->x = (w->x-p->frame.minx) * p->frame.fx;
l->y = (w->y-p->frame.miny) * p->frame.fx;
}
void TG_WMF_SetReverseWorldCoord(int coord)
{
if(coord==0) wmf_device.world2length = WMFAPI_World2Length;
else wmf_device.world2length = WMFAPI_ReverseWorld2Length;
}
void WMFAPI_InitStandardMetaHeader(StandardMetaHeader_ptr p)
{
memset(p, 0x00, sizeof(StandardMetaHeader));
p->FileType = 0x0001;
p->HeaderSize = 0x0009;
p->Version = 0x0300;
p->FileSize = 18;
p->NumOfObjects = 0;
p->MaxRecordSize = 0;
p->NumOfParams = 0;
}
void WMFAPI_AddFileSize(StandardMetaHeader_ptr p, int size)
{
p->FileSize += size;
}
void WMFAPI_SetMaxRecordSize(StandardMetaHeader_ptr p, int size)
{
p->MaxRecordSize = size;
}
void WMFAPI_SetNumberOfObjects(StandardMetaHeader_ptr p, int num)
{
p->NumOfObjects = (short)num;
}
void WMFAPI_InitPlaceableMetaHeader(PlaceableMetaHeader_ptr p, RectWin* w)
{
memset(p, 0x00, sizeof(PlaceableMetaHeader));
p->MagicNumber = TG_META_MagicNumber;
p->Handle = 0;
p->Left = (short)_to_twip(w->left);
p->Top = (short)_to_twip(w->top);
p->Right = (short)_to_twip(w->right);
p->Bottom = (short)_to_twip(w->bottom);
p->Inch = (short)(1270);
p->Reserved = 0;
p->CheckSum = 0;
p->CheckSum ^= (TG_META_MagicNumber & TG_META_KeyLow);
p->CheckSum ^= (((ulong)(TG_META_MagicNumber & TG_META_KeyHigh)) >> TG_META_KeyShift);
p->CheckSum ^= p->Handle;
p->CheckSum ^= p->Left;
p->CheckSum ^= p->Top;
p->CheckSum ^= p->Right;
p->CheckSum ^= p->Bottom;
p->CheckSum ^= p->Inch;
p->CheckSum ^= (p->Reserved & TG_META_KeyLow);
p->CheckSum ^= (((ulong)(p->Reserved & TG_META_KeyHigh)) >> TG_META_KeyShift);
}
void WMFAPI_WriteHeader(FILE* writer, StandardMetaHeader_ptr smh, PlaceableMetaHeader_ptr pmh)
{
fwrite(&pmh->MagicNumber, 1, 4, writer);
fwrite(&pmh->Handle, 1, 2, writer);
fwrite(&pmh->Left, 1, 2, writer);
fwrite(&pmh->Top, 1, 2, writer);
fwrite(&pmh->Right, 1, 2, writer);
fwrite(&pmh->Bottom, 1, 2, writer);
fwrite(&pmh->Inch, 1, 2, writer);
fwrite(&pmh->Reserved, 1, 4, writer);
fwrite(&pmh->CheckSum, 1, 2, writer);
fwrite(&smh->FileType, 1, 2, writer);
fwrite(&smh->HeaderSize, 1, 2, writer);
fwrite(&smh->Version, 1, 2, writer);
fwrite(&smh->FileSize, 1, 4, writer);
fwrite(&smh->NumOfObjects, 1, 2, writer);
fwrite(&smh->MaxRecordSize, 1, 4, writer);
fwrite(&smh->NumOfParams, 1, 2, writer);
}
void WMFAPI_InitMetaRecord(MetaRecord_ptr p)
{
p->Size = TG_META_DEFAULT_RECORD_SIZE;
p->Function = TG_META_END;
p->Parameters = NULL;
}
void WMFAPI_SetMemory(MetaRecord_ptr p, int nParam)
{
p->Parameters = (ushort*)malloc(sizeof(ushort)*nParam);
}
void WMFAPI_SetMetaRecord1(MetaRecord_ptr p, short function)
{
p->Size = TG_META_DEFAULT_RECORD_SIZE;
p->Function = function;
p->Parameters = NULL;
}
void WMFAPI_SetMetaRecord2(MetaRecord_ptr p, short function, int nParam)
{
p->Size = TG_META_DEFAULT_RECORD_SIZE+nParam;
p->Function = function;
WMFAPI_SetMemory(p, nParam);
}
void WMFAPI_ReleaseMetaRecord(MetaRecord_ptr p)
{
free(p->Parameters);
}
void WMFAPI_SetParam(MetaRecord_ptr p, int nthParam, int param)
{
p->Parameters[nthParam] = (ushort)param;
}
void WMFAPI_SetFunction(MetaRecord_ptr p, ushort Function)
{
p->Function = Function;
}
ushort WMFAPI_GetNumberOfParams(MetaRecord_ptr p)
{
return (ushort)(p->Size - TG_META_DEFAULT_RECORD_SIZE);
}
void WMFAPI_WriteMetaRecord(MetaDevice_ptr dev, MetaRecord_ptr rec, int wparam)
{
int i=0, nParam=0;
fwrite(&rec->Size, 1, sizeof(ulong), dev->writer);
fwrite(&rec->Function, 1, sizeof(ushort), dev->writer);
nParam = WMFAPI_GetNumberOfParams(rec);
if(wparam)
{
for(i = 0; i < nParam; i++)
{
fwrite(&rec->Parameters[i], 1, sizeof(ushort), dev->writer);
}
}
}
void WMFAPI_SetWindowOrg(TG_PlotZone_Ptr p, TG_Real x, TG_Real y)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord2(&rec, TG_META_SETWINDOWORG, 2);
WMFAPI_SetParam(&rec, 0, (ushort)_to_twip(y));
WMFAPI_SetParam(&rec, 1, (ushort)_to_twip(x));
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_SetWindowExt(TG_PlotZone_Ptr p, TG_Real x, TG_Real y)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord2(&rec, TG_META_SETWINDOWEXT, 2);
WMFAPI_SetParam(&rec, 0, (ushort)_to_twip(y));
WMFAPI_SetParam(&rec, 1, (ushort)_to_twip(x));
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_SetMapMode(short mode)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord2(&rec, TG_META_SETMAPMODE, 1);
WMFAPI_SetParam(&rec, 0, mode);
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
}
int WMFAPI_CreatePenIndirect(short style, short x_wid, short y_hgt, TG_Color color)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord2(&rec, TG_META_CREATEPENINDIRECT, 5);
WMFAPI_SetParam(&rec, 0, style);
WMFAPI_SetParam(&rec, 1, x_wid);
WMFAPI_SetParam(&rec, 2, y_hgt);
WMFAPI_SetParam(&rec, 3, TG_ReverseUShort(color>>8));
WMFAPI_SetParam(&rec, 4, (color&0x000000ff));
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
++nTh_GDI_Object;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
wmf_device.header.smh.NumOfObjects++;
return nTh_GDI_Object;
}
void WMFAPI_SelectObject(int _nTh_GDI_Object)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord2(&rec, TG_META_SELECTOBJECT, 1);
WMFAPI_SetParam(&rec, 0, _nTh_GDI_Object);
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_DeleteObject(int _nTh_GDI_Object)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord2(&rec, TG_META_DELETEOBJECT, 1);
WMFAPI_SetParam(&rec, 0, _nTh_GDI_Object);
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
--nTh_GDI_Object;
}
void WMFAPI_SaveDC(void)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord1(&rec, TG_META_SAVEDC);
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 0);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_RestoreDC(void)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord2(&rec, TG_META_RESTOREDC, 1);
WMFAPI_SetParam(&rec, 0, 0xffff);
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_EndRecord(void)
{
MetaRecord rec;
ulong r_size=0;
WMFAPI_SetMetaRecord1(&rec, TG_META_END);
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 0);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_CloseMetafile(void)
{
WMFAPI_EndRecord();
fseek(wmf_device.writer, 0L, SEEK_SET);
WMFAPI_WriteHeader(wmf_device.writer, &wmf_device.header.smh, &wmf_device.header.pmh);
fclose(wmf_device.writer);
wmf_device.writer = NULL;
nTh_GDI_Object = -1;
}
void WMFAPI_GenericSetPixel(TG_PlotZone_Ptr p, TG_Real x, TG_Real y, TG_Color c)
{
TG_Real pixel_size = wmf_device.pixel_size*wmf_device.pixel_width*
p->frame.frame_size.height/p->frame.fx;
TG_ComputeSquareSymbol(pixel_size, 1, x, y);
WMFAPI_Polygon(p, sym_squarex, sym_squarey, sym_square_point, c);
}
void WMFAPI_SetPixel1(TG_PlotZone_Ptr p, TG_Real x, TG_Real y, TG_Color c)
{
WMFAPI_GenericSetPixel(p, x, y, c);
}
void WMFAPI_SetPixel2(TG_PlotZone_Ptr p, int x, int y, TG_Color c)
{
WMFAPI_GenericSetPixel(p, x, y, c);
}
void WMFAPI_MoveTo(TG_PlotZone_Ptr p, TG_Real x, TG_Real y)
{
/* wc: World Coordinate
lc: logical Coordinate */
TG_Point wc, lc;
MetaRecord rec;
ulong r_size = 0;
wc.x = x, wc.y = y;
wmf_device.world2length(p, &wc, &lc);
WMFAPI_SetMetaRecord2(&rec, TG_META_MOVETO, 2);
WMFAPI_SetParam(&rec, 0, (ushort)_to_twip(lc.y));
WMFAPI_SetParam(&rec, 1, (ushort)_to_twip(lc.x));
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_LineTo(TG_PlotZone_Ptr p, TG_Real x, TG_Real y)
{
TG_Point wc, lc;
MetaRecord rec;
ulong r_size = 0;
wc.x = x, wc.y = y;
wmf_device.world2length(p, &wc, &lc);
WMFAPI_SetMetaRecord2(&rec, TG_META_LINETO, 2);
WMFAPI_SetParam(&rec, 0, (ushort)_to_twip(lc.y));
WMFAPI_SetParam(&rec, 1, (ushort)_to_twip(lc.x));
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_MakePen(TG_PlotZone_Ptr p, TG_Color c, TG_Real thk)
{
plot_attr.prv_pen_color = plot_attr.cur_pen_color;
plot_attr.cur_pen_color = c;
plot_attr.thk = _to_twip(thk*p->frame.frame_size.height);
wmf_device.cur_pen = WMFAPI_CreatePenIndirect(TG_PS_SOLID,plot_attr.thk,0,c);
WMFAPI_SelectObject(wmf_device.cur_pen);
}
void WMFAPI_DeletePen(void)
{
WMFAPI_DeleteObject(wmf_device.cur_pen);
plot_attr.cur_pen_color = plot_attr.prv_pen_color;
plot_attr.thk = 0;
}
void WMFAPI_Line(TG_PlotZone_Ptr p, TG_Real x1, TG_Real y1, TG_Real x2, TG_Real y2, TG_Color color, TG_Real thk)
{
WMFAPI_MakePen(p,color,thk);
WMFAPI_MoveTo(p, x1, y1);
WMFAPI_LineTo(p, x2, y2);
WMFAPI_DeletePen();
}
int WMFAPI_CreateBrushIndirect(short style, TG_Color color, short hatch)
{
ulong r_size;
MetaRecord rec;
WMFAPI_SetMetaRecord2(&rec, TG_META_CREATEBRUSHINDIRECT, 4);
WMFAPI_SetParam(&rec, 0, style);
WMFAPI_SetParam(&rec, 1, TG_ReverseUShort(color>>8));
WMFAPI_SetParam(&rec, 2, (color&0x000000ff));
WMFAPI_SetParam(&rec, 3, hatch);
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
wmf_device.header.smh.NumOfObjects++;
++nTh_GDI_Object;
return nTh_GDI_Object;
}
void WMFAPI_Polyline(TG_PlotZone_Ptr p, TG_Real* pointx, TG_Real* pointy, int npoint, TG_Color lc, TG_Real lthk)
{
TG_Point wc, gc;
int i, j;
ulong r_size;
MetaRecord rec;
WMFAPI_SaveDC();
WMFAPI_MakePen(p, lc, lthk);
WMFAPI_SetMetaRecord2(&rec, TG_META_POLYLINE, 1+npoint*2);
WMFAPI_SetParam(&rec, 0, npoint);
for(i = 0, j = 1; i < npoint; i++)
{
wc.x = pointx[i];
wc.y = pointy[i];
wmf_device.world2length(p, &wc, &gc);
WMFAPI_SetParam(&rec, j++, (ushort)_to_twip(gc.x));
WMFAPI_SetParam(&rec, j++, (ushort)_to_twip(gc.y));
}
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
WMFAPI_DeletePen();
WMFAPI_RestoreDC();
}
void WMFAPI_SetPolyFillMode(short fillmode)
{
ulong r_size;
MetaRecord rec;
WMFAPI_SetMetaRecord2(&rec, TG_META_SETPOLYFILLMODE, 1);
WMFAPI_SetParam(&rec, 0, fillmode);
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
}
void WMFAPI_Polygon(TG_PlotZone_Ptr p, TG_Real* pointx, TG_Real* pointy, int npoint, TG_Color fc)
{
TG_Point wc, lc;
int i,j;
ulong r_size;
MetaRecord rec;
if(npoint < 3) return;
wmf_device.cur_pen = WMFAPI_CreatePenIndirect(TG_PS_SOLID, 1, 0, fc);
WMFAPI_SelectObject(wmf_device.cur_pen);
wmf_device.cur_brush = WMFAPI_CreateBrushIndirect(TG_BS_SOLID, fc, TG_BS_SOLID);
WMFAPI_SelectObject(wmf_device.cur_brush);
WMFAPI_SetMetaRecord2(&rec, TG_META_POLYGON, 1+npoint*2);
WMFAPI_SetParam(&rec, 0, npoint);
for(i = 0, j = 1; i < npoint; i++)
{
wc.x = pointx[i];
wc.y = pointy[i];
wmf_device.world2length(p, &wc, &lc);
WMFAPI_SetParam(&rec, j++, (ushort)_to_twip(lc.x));
WMFAPI_SetParam(&rec, j++, (ushort)_to_twip(lc.y));
}
r_size = rec.Size;
if(r_size > wmf_device.header.smh.MaxRecordSize)
wmf_device.header.smh.MaxRecordSize = r_size;
wmf_device.header.smh.FileSize += r_size;
WMFAPI_WriteMetaRecord(&wmf_device, &rec, 1);
WMFAPI_ReleaseMetaRecord(&rec);
WMFAPI_DeleteObject(wmf_device.cur_brush);
WMFAPI_DeleteObject(wmf_device.cur_pen);
}
void WMFAPI_Symbol(TG_PlotZone_Ptr p, TG_Real x, TG_Real y, TG_Symbol sym, TG_Real size, TG_Color fc, int fill, TG_Color lc, int line, TG_Real lthk)
{
TG_Real sym_size = size*p->frame.frame_size.height/p->frame.fx;
if(sym < 0 || sym > (MAX_DEFAULT_SYMBOL-1)) return;
/*... No symbol drawing ...*/
if(fill == 0 && line == 0) return;
TG_GetSymbolCoordinate(sym, sym_size, 1, x, y);
if(fill == 1)
WMFAPI_Polygon(p, symbol_pool[sym].pointx, symbol_pool[sym].pointy, symbol_pool[sym].npoint, fc);
if(line==1 && (fc != lc))
WMFAPI_Polyline(p, symbol_pool[sym].pointx, symbol_pool[sym].pointy, symbol_pool[sym].npoint+1, lc, lthk);
}
int TG_WMF_OpenExport(TG_PlotZone* p, const char* file)
{
RectWin w;
w.left = 0;
w.top = 0;
w.right = p->frame.frame_size.width;
w.bottom = p->frame.frame_size.height;
wmf_device.writer = fopen(file, "wb");
if(!wmf_device.writer) {
fprintf(stderr, "Error: can't open %s at TG_WMF_OpenExport\n", file);
return 0;
}
WMFAPI_InitStandardMetaHeader(&wmf_device.header.smh);
WMFAPI_InitPlaceableMetaHeader(&wmf_device.header.pmh, &w);
WMFAPI_WriteHeader(wmf_device.writer, &wmf_device.header.smh, &wmf_device.header.pmh);
WMFAPI_SetWindowOrg(p, w.left, w.top);
WMFAPI_SetWindowExt(p, w.right, w.bottom);
p->plot.makepen = WMFAPI_MakePen;
p->plot.moveto = WMFAPI_MoveTo;
p->plot.line = WMFAPI_Line;
p->plot.lineto = WMFAPI_LineTo;
p->plot.putpixel1 = WMFAPI_SetPixel1;
p->plot.putpixel2 = WMFAPI_SetPixel2;
p->plot.deletepen = WMFAPI_DeletePen;
p->plot.gsave = WMFAPI_SaveDC;
p->plot.grestore = WMFAPI_RestoreDC;
p->plot.polyline = WMFAPI_Polyline;
p->plot.polygon = WMFAPI_Polygon;
p->plot.symbol = WMFAPI_Symbol;
wmf_device.pixel_size = TG_DEFAULT_PIXEL_SIZE;
wmf_device.pixel_width = TG_DEFAULT_PIXEL_WIDTH;
wmf_device.cur_pen = 0;
wmf_device.prv_pen = 0;
TG_WMF_SetReverseWorldCoord(0);
TG_InitPlotAttr(&plot_attr);
return 1;
}
void TG_WMF_CloseExport(void)
{
WMFAPI_CloseMetafile();
}
#endif
/*-----------------------------------------------------
SYMBOL
-----------------------------------------------------*/
static void TG_ComputeCircleSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly)
{
int i=0;
//TG_Real r= width * size * 0.005; // length
TG_Real r= width * size * 0.5; // length
static const TG_Real pi6 = _pi / 6.0;
static const TG_Real pi3 = _pi / 3.0;
TG_Real zero = 0;
sym_circlex[0] = r ;
sym_circley[0] = zero ;
sym_circlex[3] = zero ;
sym_circley[3] = r ;
sym_circlex[6] = -r ;
sym_circley[6] = zero ;
sym_circlex[9] = zero ;
sym_circley[9] = -r ;
sym_circlex[1] = r*cos(pi6);
sym_circlex[2] = r*cos(pi3);
sym_circley[1] = r*sin(pi6);
sym_circley[2] = r*sin(pi3);
sym_circlex[4] = -sym_circlex[2];
sym_circley[4] = sym_circley[2];
sym_circlex[5] = -sym_circlex[1];
sym_circley[5] = sym_circley[1];
sym_circlex[7] = sym_circlex[5];
sym_circley[7] = -sym_circley[5];
sym_circlex[8] = sym_circlex[4];
sym_circley[8] = -sym_circley[4];
sym_circlex[10] = -sym_circlex[8];
sym_circley[10] = sym_circley[8];
sym_circlex[11] = -sym_circlex[7];
sym_circley[11] = sym_circley[7];
sym_circlex[12] = sym_circlex[0];
sym_circley[12] = sym_circley[0];
while(i <= 12) { sym_circlex[i] += lx; sym_circley[i] += ly; i++;}
}
void TG_ComputeDeltaSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly)
{
TG_Real span= width*size;
TG_Real height = span * 0.866025;
TG_Real hs=span*0.5, hh=height*0.5;
sym_deltax[0] = -hs + lx;
sym_deltay[0] = -hh + ly;
sym_deltax[1] = hs + lx;
sym_deltay[1] = -hh + ly;
sym_deltax[2] = 0 + lx;
sym_deltay[2] = hh + ly;
sym_deltax[3] = sym_deltax[0];
sym_deltay[3] = sym_deltay[0];
}
void TG_ComputeGradientSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly)
{
TG_Real span= width*size;
TG_Real height = span * 0.866025;
TG_Real hs=span*0.5, hh=height*0.51;
sym_gradientx[0] = -hs + lx;
sym_gradienty[0] = hh + ly;
sym_gradientx[1] = hs + lx;
sym_gradienty[1] = hh + ly;
sym_gradientx[2] = 0 + lx;
sym_gradienty[2] = -hh + ly;
sym_gradientx[3] = sym_gradientx[0];
sym_gradienty[3] = sym_gradienty[0];
}
void TG_ComputeRTriangleSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly)
{
TG_Real span= width*size;
TG_Real height = span * 0.866025;
TG_Real hs=span*0.5, hh=height*0.5;
sym_rtrianglex[0] = hh + lx;
sym_rtriangley[0] = hs + ly;
sym_rtrianglex[1] = hh + lx;
sym_rtriangley[1] = -hs + ly;
sym_rtrianglex[2] = -hh + lx;
sym_rtriangley[2] = 0 + ly;
sym_rtrianglex[3] = sym_rtrianglex[0];
sym_rtriangley[3] = sym_rtriangley[0];
}
void TG_ComputeLTriangleSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly)
{
TG_Real span= width*size;
TG_Real height = span * 0.866025;
TG_Real hs=span*0.5, hh=height*0.5;
sym_ltrianglex[0] = -hh + lx;
sym_ltriangley[0] = hs + ly;
sym_ltrianglex[1] = -hh + lx;
sym_ltriangley[1] = -hs + ly;
sym_ltrianglex[2] = hh + lx;
sym_ltriangley[2] = 0 + ly;
sym_ltrianglex[3] = sym_ltrianglex[0];
sym_ltriangley[3] = sym_ltriangley[0];
}
void TG_ComputeDiamondSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly)
{
TG_Real span=width*size;
TG_Real hy=0.546*span, hx=0.546*span;
sym_diamondx[0] = 0 + lx;
sym_diamondy[0] = hy + ly;
sym_diamondx[1] = -hx + lx;
sym_diamondy[1] = 0 + ly;
sym_diamondx[2] = 0 + lx;
sym_diamondy[2] = -hy + ly;
sym_diamondx[3] = hx + lx;
sym_diamondy[3] = 0 + ly;
sym_diamondx[4] = sym_diamondx[0];
sym_diamondy[4] = sym_diamondy[0];
}
void TG_ComputeSquareSymbol(TG_Real size, TG_Real width, TG_Real lx, TG_Real ly)
{
TG_Real hs=width*size*0.5;
sym_squarex[0] = -hs + lx;
sym_squarey[0] = hs + ly;
sym_squarex[1] = -hs + lx;
sym_squarey[1] = -hs + ly;
sym_squarex[2] = hs + lx;
sym_squarey[2] = -hs + ly;
sym_squarex[3] = hs + lx;
sym_squarey[3] = hs + ly;
sym_squarex[4] = sym_squarex[0];
sym_squarey[4] = sym_squarey[0];
}
#ifdef __cplusplus
}
#endif
/*... End of libgt.c ...*/