/***************************************************************************** ** Copyright (C) 1998-2001 Ljubomir Milanovic & Horst Wagner ** This file is part of the g2 library ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ #include #include #include #include "g2_funix.h" #include "g2_virtual_device.h" #include "g2_graphic_pd.h" #include "g2_control_pd.h" #include "g2_util.h" #ifndef PI #define PI 3.14159265358979323846 #endif /* PI */ /* * * Plot (physical device) * */ void g2_plot_pd(g2_physical_device *pd, double x, double y) { int ix, iy; double dx, dy; if(pd->ff[g2_Plot].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); pd->ff[g2_Plot].fun(pd->pid, pd->pdp, ix, iy); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); pd->ff[g2_Plot].fun(pd->pid, pd->pdp, dx, dy); break; } } else { /* emulate ... with .... */ } } /* * * Draw line (low_level) * */ void g2_line_pd(g2_physical_device *pd, double x1, double y1, double x2, double y2) { int ix1, iy1, ix2, iy2; double dx1, dy1, dx2, dy2; if(pd->ff[g2_Line].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x1, y1, &ix1, &iy1); g2_uc2pdc_int(pd, x2, y2, &ix2, &iy2); pd->ff[g2_Line].fun(pd->pid, pd->pdp, ix1, iy1, ix2, iy2); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x1, y1, &dx1, &dy1); g2_uc2pdc_double(pd, x2, y2, &dx2, &dy2); pd->ff[g2_Line].fun(pd->pid, pd->pdp, dx1, dy1, dx2, dy2); break; } } else { /* emulate ... with .... */ } } /* * * Draw poly line (physical device) * */ void g2_poly_line_pd(g2_physical_device *pd, int N, double *points) { int i; int *ipt; double *dpt; if(pd->ff[g2_PolyLine].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: ipt=g2_malloc(2*N*sizeof(int)); for(i=0;i<2*N;i+=2) g2_uc2pdc_int(pd, points[i+0], points[i+1], ipt+i, ipt+i+1); pd->ff[g2_PolyLine].fun(pd->pid, pd->pdp, N, ipt); free(ipt); break; case g2_DoubleCoor: dpt=g2_malloc(2*N*sizeof(double)); for(i=0;i<2*N;i+=2) g2_uc2pdc_double(pd, points[i+0], points[i+1], dpt+i, dpt+i+1); pd->ff[g2_PolyLine].fun(pd->pid, pd->pdp, N, dpt); free(dpt); break; } } else { for (i=0;iff[g2_Triangle].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x1, y1, &ix1, &iy1); g2_uc2pdc_int(pd, x2, y2, &ix2, &iy2); g2_uc2pdc_int(pd, x3, y3, &ix3, &iy3); pd->ff[g2_Triangle].fun(pd->pid, pd->pdp, ix1, iy1, ix2, iy2, ix3, iy3); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x1, y1, &dx1, &dy1); g2_uc2pdc_double(pd, x2, y2, &dx2, &dy2); g2_uc2pdc_double(pd, x3, y3, &dx3, &dy3); pd->ff[g2_Triangle].fun(pd->pid, pd->pdp, dx1, dy1, dx2, dy2, dx3, dy3); } } else { g2_line_pd(pd, x1, y1, x2, y2); /* emulate triangle with lines */ g2_line_pd(pd, x2, y2, x3, y3); g2_line_pd(pd, x3, y3, x1, y1); } } /* * * Filled triangle (physical device) * */ void g2_filled_triangle_pd(g2_physical_device *pd, double x1, double y1, double x2, double y2, double x3, double y3) { int ix1, iy1, ix2, iy2, ix3, iy3; double dx1, dy1, dx2, dy2, dx3, dy3; if(pd->ff[g2_FilledTriangle].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x1, y1, &ix1, &iy1); g2_uc2pdc_int(pd, x2, y2, &ix2, &iy2); g2_uc2pdc_int(pd, x3, y3, &ix3, &iy3); pd->ff[g2_FilledTriangle].fun(pd->pid, pd->pdp, ix1, iy1, ix2, iy2, ix3, iy3); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x1, y1, &dx1, &dy1); g2_uc2pdc_double(pd, x2, y2, &dx2, &dy2); g2_uc2pdc_double(pd, x3, y3, &dx3, &dy3); pd->ff[g2_FilledTriangle].fun(pd->pid, pd->pdp, dx1, dy1, dx2, dy2, dx3, dy3); } } else { double Triangle[6]; /* emulate FilledTriangle with FilledPolygon */ Triangle[0] = x1; Triangle[1] = y1; Triangle[2] = x2; Triangle[3] = y2; Triangle[4] = x3; Triangle[5] = y3; g2_filled_polygon_pd(pd, 3, Triangle); } } /* * * Rectangle (physical device) * */ void g2_rectangle_pd(g2_physical_device *pd, double x1, double y1, double x2, double y2) { int ix1, iy1, ix2, iy2; double dx1, dy1, dx2, dy2; if(pd->ff[g2_Rectangle].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x1, y1, &ix1, &iy1); g2_uc2pdc_int(pd, x2, y2, &ix2, &iy2); g2_sort2_i(&ix1, &ix2); g2_sort2_i(&iy1, &iy2); pd->ff[g2_Rectangle].fun(pd->pid, pd->pdp, ix1, iy1, ix2, iy2); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x1, y1, &dx1, &dy1); g2_uc2pdc_double(pd, x2, y2, &dx2, &dy2); g2_sort2_d(&dx1, &dx2); g2_sort2_d(&dy1, &dy2); pd->ff[g2_Rectangle].fun(pd->pid, pd->pdp, dx1, dy1, dx2, dy2); break; } } else { g2_line_pd(pd, x1, y1, x1, y2); /* emulate rectangle with lines */ g2_line_pd(pd, x1, y1, x2, y1); g2_line_pd(pd, x2, y1, x2, y2); g2_line_pd(pd, x1, y2, x2, y2); } } /* * * Filled rectangle (physical device) * */ void g2_filled_rectangle_pd(g2_physical_device *pd, double x1, double y1, double x2, double y2) { int ix1, iy1, ix2, iy2; double dx1, dy1, dx2, dy2; if(pd->ff[g2_FilledRectangle].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x1, y1, &ix1, &iy1); g2_uc2pdc_int(pd, x2, y2, &ix2, &iy2); g2_sort2_i(&ix1, &ix2); g2_sort2_i(&iy1, &iy2); pd->ff[g2_FilledRectangle].fun(pd->pid, pd->pdp, ix1, iy1, ix2, iy2); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x1, y1, &dx1, &dy1); g2_uc2pdc_double(pd, x2, y2, &dx2, &dy2); g2_sort2_d(&dx1, &dx2); g2_sort2_d(&dy1, &dy2); pd->ff[g2_FilledRectangle].fun(pd->pid, pd->pdp, dx1, dy1, dx2, dy2); break; } } else { double Rectangle[8]; /* emulate FilledRectangle with FilledPolygon */ Rectangle[0] = x1; Rectangle[1] = y1; Rectangle[2] = x2; Rectangle[3] = y1; Rectangle[4] = x2; Rectangle[5] = y2; Rectangle[6] = x1; Rectangle[7] = y2; g2_filled_polygon_pd(pd,4,Rectangle); } } /* * * Polygon (physical device) * */ void g2_polygon_pd(g2_physical_device *pd, int N, double *points) { int i; int *ipt; double *dpt; if(pd->ff[g2_Polygon].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: ipt=g2_malloc(2*N*sizeof(int)); for(i=0;i<2*N;i+=2) g2_uc2pdc_int(pd, points[i+0], points[i+1], ipt+i, ipt+i+1); pd->ff[g2_Polygon].fun(pd->pid, pd->pdp, N, ipt); free(ipt); break; case g2_DoubleCoor: dpt=g2_malloc(2*N*sizeof(double)); for(i=0;i<2*N;i+=2) g2_uc2pdc_double(pd, points[i+0], points[i+1], dpt+i, dpt+i+1); pd->ff[g2_Polygon].fun(pd->pid, pd->pdp, N, dpt); free(dpt); break; } } else { for (i=0;iff[g2_FilledPolygon].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: ipt=g2_malloc(2*N*sizeof(int)); for(i=0;i<2*N;i+=2) g2_uc2pdc_int(pd, points[i+0], points[i+1], ipt+i, ipt+i+1); pd->ff[g2_FilledPolygon].fun(pd->pid, pd->pdp, N, ipt); free(ipt); break; case g2_DoubleCoor: dpt=g2_malloc(2*N*sizeof(double)); for(i=0;i<2*N;i+=2) g2_uc2pdc_double(pd, points[i+0], points[i+1], dpt+i, dpt+i+1); pd->ff[g2_FilledPolygon].fun(pd->pid, pd->pdp, N, dpt); free(dpt); break; } } else { /* emulate filled polygon with .... */ } } /* * * Ellipse (physical device) * */ void g2_ellipse_pd(g2_physical_device *pd, double x, double y, double r1, double r2) { int ix, iy, ir1, ir2; double dx, dy, dr1, dr2; if(pd->ff[g2_Ellipse].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); g2_us2pds_int(pd, r1, r2, &ir1, &ir2); pd->ff[g2_Ellipse].fun(pd->pid, pd->pdp, ix, iy, ir1, ir2); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); g2_us2pds_double(pd, r1, r2, &dr1, &dr2); pd->ff[g2_Ellipse].fun(pd->pid, pd->pdp, dx, dy, dr1, dr2); break; } } else { g2_arc_pd(pd, x, y, r1, r2, 0., 360.); /* emulate ellipse with arc */ } } /* * * Filled ellipse (physical device) * */ void g2_filled_ellipse_pd(g2_physical_device *pd, double x, double y, double r1, double r2) { int ix, iy, ir1, ir2; double dx, dy, dr1, dr2; if(pd->ff[g2_FilledEllipse].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); g2_us2pds_int(pd, r1, r2, &ir1, &ir2); pd->ff[g2_FilledEllipse].fun(pd->pid, pd->pdp, ix, iy, ir1, ir2); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); g2_us2pds_double(pd, r1, r2, &dr1, &dr2); pd->ff[g2_FilledEllipse].fun(pd->pid, pd->pdp, dx, dy, dr1, dr2); break; } } else { g2_filled_arc_pd(pd, /* emulate filledellipse with filled arc */ x, y, r1, r2, 0., 360.); } } /* * * Circle (physical device) * */ void g2_circle_pd(g2_physical_device *pd, double x, double y, double r) { int ix, iy, ir; double dx, dy, dr; if(pd->ff[g2_Circle].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); g2_us2pds_int(pd, r, 0, &ir, NULL); pd->ff[g2_Circle].fun(pd->pid, pd->pdp, ix, iy, ir); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); g2_us2pds_double(pd, r, 0, &dr, NULL); pd->ff[g2_Circle].fun(pd->pid, pd->pdp, dx, dy, dr); break; } } else { g2_ellipse_pd(pd, x, y, r, r); /* emulate circle with ellipse */ } } /* * * Filled circle (physical device) * */ void g2_filled_circle_pd(g2_physical_device *pd, double x, double y, double r) { int ix, iy, ir; double dx, dy, dr; if(pd->ff[g2_FilledCircle].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); g2_us2pds_int(pd, r, 0, &ir, NULL); pd->ff[g2_FilledCircle].fun(pd->pid, pd->pdp, ix, iy, ir); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); g2_us2pds_double(pd, r, 0, &dr, NULL); pd->ff[g2_FilledCircle].fun(pd->pid, pd->pdp, dx, dy, dr); break; } } else { g2_filled_ellipse_pd(pd, x, y, r, r); /* emulate */ } } /* * * Arc (physical device) * */ void g2_arc_pd(g2_physical_device *pd, double x, double y, double r1, double r2, double a1, double a2) { int ix, iy, ir1, ir2; double dx, dy, dr1, dr2; if(pd->ff[g2_Arc].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); g2_us2pds_int(pd, r1, r2, &ir1, &ir2); pd->ff[g2_Arc].fun(pd->pid, pd->pdp, ix, iy, ir1, ir2, a1, a2); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); g2_us2pds_double(pd, r1, r2, &dr1, &dr2); pd->ff[g2_Arc].fun(pd->pid, pd->pdp, dx, dy, dr1, dr2, a1, a2); break; } } else { double a, da, *pt; /* emulate arc */ int N, i; N=(a2==a1)?360:(int)fabs(a2-a1)+8; a=a1*2.*PI/360.; da=((a2>a1)? (a2-a1):360.-(a1-a2))*2.*PI/360./(N-1); pt=g2_malloc(2*N*sizeof(double)); for(i=0;iff[g2_FilledArc].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); g2_us2pds_int(pd, r1, r2, &ir1, &ir2); pd->ff[g2_FilledArc].fun(pd->pid, pd->pdp, ix, iy, ir1, ir2, a1, a2); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); g2_us2pds_double(pd, r1, r2, &dr1, &dr2); pd->ff[g2_FilledArc].fun(pd->pid, pd->pdp, dx, dy, dr1, dr2, a1, a2); break; } } else { double a, da, *pt; /* emulate filled arc */ int N, i; N=(a2==a1)?360:(int)fabs(a2-a1)+8; a=a1*2.*PI/360.; da=((a2>a1)? (a2-a1):360.-(a1-a2))*2.*PI/360./(N-1); pt=g2_malloc(2*(N+2)*sizeof(double)); pt[0]=x; pt[1]=y; for(i=0;iff[g2_String].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); pd->ff[g2_String].fun(pd->pid, pd->pdp, ix, iy, text); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); pd->ff[g2_String].fun(pd->pid, pd->pdp, dx, dy, text); break; } } else { /* emulate ... with .... */ } } void g2_image_pd(g2_physical_device *pd, double x, double y, int x_size, int y_size, int *pens) { int ix, iy; double dx, dy; if(pd->ff[g2_Image].fun!=NULL) { switch(pd->coor_type) { case g2_IntCoor: g2_uc2pdc_int(pd, x, y, &ix, &iy); pd->ff[g2_Image].fun(pd->pid, pd->pdp, ix, iy, x_size, y_size, pens); break; case g2_DoubleCoor: g2_uc2pdc_double(pd, x, y, &dx, &dy); pd->ff[g2_Image].fun(pd->pid, pd->pdp, dx, dy, x_size, y_size, pens); break; } } else { for(ix=0;ix