home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / VOGLE.ZIP / VOGLE / DRIVERS / GRX.C < prev    next >
C/C++ Source or Header  |  2000-02-11  |  13KB  |  661 lines

  1. /*
  2.  * GRX driver for VOGL c1993 by Gary Murphy (garym@virtual.rose.utoronto.ca)
  3.  * 
  4.  * To compile:
  5.  * 
  6.  * 1) add GRX to device.c and mash-up your makefiles for MsDOS 2) compile with
  7.  * DOBJ=-DPOSTSCRIPT -DHPGL -DGRX and MFLAGS=-O2
  8.  * 
  9.  * To run:
  10.  * 
  11.  * set VDEVICE=grx
  12.  * 
  13.  * grateful thanks to Lance Norskog (thinman@netcom.com) and Bernie Kirby
  14.  * (bernie@ecr.mu.oz.au) --- should either of you be in my neighbourhood, my
  15.  * offer of an Ice Beer is still open! (Things in #ifdef BLART disabled by
  16.  * bernie...)
  17.  */
  18. #define VOGLE 1
  19.  
  20. #include <stdio.h>
  21. #undef DBG
  22. #ifdef DBG
  23. FILE    *dfp = NULL;
  24. #endif
  25. #include <assert.h>
  26.  
  27. #include <stdlib.h>
  28. #include <memory.h>
  29. #include <grx.h>
  30. #include <mousex.h>
  31.  
  32. #define MSG( m ) fprintf(stderr, "\n%s: %d: %s", __FILE__, __LINE__, (m))
  33. #define ERROR1( m, p ) fprintf(stderr, "\n%s: %d: " m, __FILE__, __LINE__, (p))
  34.  
  35. #ifdef VOGLE
  36. #include    "vogle.h"
  37. #else
  38. #include    "vogl.h"
  39. #endif
  40.  
  41. #ifndef TRUE
  42. #define TRUE    1
  43. #endif
  44.  
  45. #ifndef FALSE
  46. #define FALSE    0
  47. #endif
  48.  
  49. #define MAXCOLOR 256
  50.  
  51. static struct {
  52.  
  53.     GR_graphics_modes old_mode;
  54.  
  55.     int             width, height, planes;
  56.     unsigned        scrsize;/* size of buffer in long words */
  57.     GrContext      *cbuf;    /* current context */
  58.     GrContext      *fbuf;
  59.     GrContext      *bbuf;
  60.  
  61.     int             palette[8];
  62.  
  63.     GrLineOption    lopt;    /* pen drawing options */
  64.     int             fg;    /* foreground/background colours */
  65.     int             bg;
  66.  
  67.     int             has_mouse;
  68.  
  69.     GrFont         *font;    /* Current font */
  70.     GrFont         *lfont;    /* Preloaded small font */
  71.     GrFont         *sfont;    /* Preloaded large font */
  72.     char           *fname;    /* Fontname */
  73.     GrTextOption   to;    /* Other text stuff */
  74.  
  75.     int             cx;
  76.     int             cy;
  77.  
  78. } grx;
  79.  
  80. /*
  81.  * access functions: *
  82.  * 
  83. /* I'm going to need this to fudge in stereo graphics ...
  84.  */
  85.  
  86. GrContext      *
  87. setBackBuffer(GrContext * newBB)
  88. {
  89.     GrContext      *oldBB = grx.bbuf;
  90.     assert(newBB != NULL);
  91.  
  92.     grx.bbuf = newBB;
  93.     return oldBB;
  94. }
  95.  
  96. static int
  97. grx_init()
  98. {
  99. #ifdef DBG
  100.     dfp = fopen("grx.dbg", "w");
  101. #endif
  102.     grx.old_mode = GrCurrentMode();
  103.     GrSetMode(GR_default_graphics);
  104.  
  105. #ifndef VOGLE
  106.     vdevice.devname = "Grx";
  107. #endif
  108.  
  109.     /* set the VOGL device */
  110.     vdevice.sizeX = GrSizeY();    /* square max, was GrScreenX(); */
  111.     vdevice.sizeY = GrSizeY();
  112.  
  113.     grx.width = vdevice.sizeSx = GrScreenX();
  114.     grx.height = vdevice.sizeSy = GrScreenY();
  115.     grx.planes = vdevice.depth = GrNumPlanes();
  116.  
  117.     grx.scrsize = (GrPlaneSize(grx.width, grx.height) * grx.planes) / sizeof(long);
  118.  
  119.     /* setup default palette */
  120.     GrSetRGBcolorMode();
  121.     grx.lopt.lno_color = grx.fg = GrWhite();
  122.     grx.bg = GrBlack();
  123.  
  124.     grx.palette[BLACK] = GrAllocColor(0, 0, 0);
  125.     grx.palette[RED] = GrAllocColor(255, 0, 0);
  126.     grx.palette[GREEN] = GrAllocColor(0, 255, 0);
  127.     grx.palette[YELLOW] = GrAllocColor(255, 255, 0);
  128.     grx.palette[BLUE] = GrAllocColor(0, 0, 255);
  129.     grx.palette[MAGENTA] = GrAllocColor(255, 0, 255);
  130.     grx.palette[CYAN] = GrAllocColor(0, 255, 255);
  131.     grx.palette[WHITE] = GrAllocColor(255, 255, 255);
  132.  
  133.     /*
  134.      * setup back/front buffers: frontbuffer is the current screen, back
  135.      * is a ram context
  136.      */
  137.     grx.cbuf = grx.fbuf = GrSaveContext(NULL);
  138.     grx.bbuf = NULL;
  139.  
  140.     /* initialize mouse */
  141.     if ((grx.has_mouse = MouseDetect()) == TRUE) {
  142.         /* dare I do interrupts? ... */
  143.         MouseEventMode(1);
  144.         MouseInit();
  145.  
  146.         /* no keyboard (use getch) */
  147.         MouseEventEnable(0, 1);
  148.  
  149.         /* cheezy mouse speed algorithm (blame Lance for the pun) */
  150.         if (grx.width * grx.height < 100000)
  151.             MouseSetSpeed(6);
  152.         else if (grx.width * grx.height < 200000)
  153.             MouseSetSpeed(4);
  154.         else if (grx.width * grx.height < 500000)
  155.             MouseSetSpeed(3);
  156.         else
  157.             MouseSetSpeed(2);
  158.  
  159.         MouseWarp(1, 1);
  160.         MouseDisplayCursor();
  161.     };
  162.  
  163.     /* initial drawing style to thin solid lines */
  164.     grx.lopt.lno_width = 1;
  165.     grx.lopt.lno_pattlen = 0;
  166.     grx.lopt.lno_dashpat = NULL;
  167.     /* load initial fonts */
  168.     if (getenv("GRXFONT") == NULL)
  169.         GrSetFontPath("fonts");
  170.  
  171.     grx.font = grx.sfont = GrLoadFont(vdevice.dev.small);
  172. #ifdef DBG
  173.     if (!grx.font) {
  174.         fprintf(dfp, "GrLoadFont failed");
  175.         fflush(dfp);
  176.     }
  177. #endif
  178.  
  179.     grx.lfont = GrLoadFont(vdevice.dev.large);
  180. #ifdef DBG
  181.     if (!grx.lfont) {
  182.         fprintf(dfp, "GrLoadFont failed");
  183.         fflush(dfp);
  184.     }
  185. #endif
  186.  
  187.     grx.to.txo_font = grx.font;
  188.     grx.to.txo_xmag = grx.to.txo_ymag = 1;
  189.     grx.to.txo_direct = GR_TEXT_RIGHT;
  190.     grx.to.txo_xalign = grx.to.txo_xalign = GR_ALIGN_DEFAULT;
  191.     grx.to.txo_fgcolor = 0;
  192.  
  193.     grx.fname = vdevice.dev.small;
  194.     vdevice.hwidth = 8.0;
  195.     vdevice.hheight = 8.0;
  196.  
  197.     return (1);
  198. }
  199.  
  200. /*
  201.  * grx_frontbuffer, grx_backbuffer, grx_swapbuffers
  202.  * 
  203.  */
  204. static
  205. int 
  206. grx_frontbuffer()
  207. {
  208.     grx.cbuf = grx.fbuf;
  209.     GrSetContext(grx.fbuf);
  210.     return (0);
  211. }
  212.  
  213. static
  214. int 
  215. grx_backbuffer()
  216. {
  217.     /* if they want a backbuffer, we'd better make one ... */
  218.  
  219.     if (grx.bbuf == NULL)
  220.         grx.bbuf = GrCreateContext(GrSizeX(), GrSizeY(), NULL, NULL);
  221.  
  222.     assert(grx.bbuf != NULL);
  223.  
  224.     grx.cbuf = grx.bbuf;
  225.     GrSetContext(grx.bbuf);
  226.     return (0);
  227. }
  228.  
  229. static
  230. int 
  231. grx_swapbuffers()
  232. {
  233.     if (grx.cbuf == grx.fbuf)
  234.         grx_backbuffer();
  235.     else {
  236.         /*
  237.          * there are rumours of a portable VGA backbuffer using VESA
  238.          * but I've yet to track it down.
  239.          * 
  240.          * the following copies by long words from back to front buffer
  241.          * modify this for regions by triming the first x-limit and
  242.          * y-limit and upping the pointers to the start of your
  243.          * subcontext
  244.          */
  245.  
  246.         MouseEraseCursor();
  247.  
  248.         /* WARNING WILL ROBINSON - WARNING WILL ROBINSON */
  249.         /*
  250.          * We're using the NC version so I can copy a 2W by H/2
  251.          * backbuffer in my stereo graphics 'interlaced' mode
  252.          */
  253.  
  254.         GrBitBltNC(grx.fbuf, 0, 0,
  255.                grx.bbuf, 0, 0,
  256.                grx.bbuf->gc_xmax, grx.bbuf->gc_ymax, GrWRITE);
  257.  
  258.         MouseDisplayCursor();
  259.  
  260.  
  261.     }
  262.  
  263.     return (0);
  264. }
  265.  
  266. #ifdef VOGLE
  267. /*
  268.  * grx_vclear
  269.  * 
  270.  * Clear the screen to current colour
  271.  */
  272. grx_vclear()
  273. {
  274.     grx.to.txo_bgcolor = grx.fg;
  275.     GrClearContext(grx.fg);
  276.  
  277. }
  278.  
  279. #else
  280.  
  281. /*
  282.  * grx_vclear
  283.  * 
  284.  * Clear the viewport to current colour
  285.  */
  286. static int
  287. grx_vclear()
  288. {
  289.     unsigned int    vw = vdevice.maxVx - vdevice.minVx;
  290.     unsigned int    vh = vdevice.maxVy - vdevice.minVy;
  291.  
  292.     grx.to.txo_bgcolor = grx.fg;
  293.     if ((vdevice.sizeSx == vw) && (vdevice.sizeSy == vh)) {
  294.         GrClearContext(grx.fg);    /* full screen */
  295.     } else
  296.         GrFilledBox(
  297.                 vdevice.minVx,
  298.                 vdevice.sizeSy - vdevice.maxVy,
  299.                 grx.width,
  300.                 grx.height,
  301.                 grx.fg);
  302.  
  303.     return (1);
  304. }
  305.  
  306. #endif
  307.  
  308. /*
  309.  * grx_exit
  310.  * 
  311.  * Sets the display back to text mode.
  312.  */
  313. static
  314. grx_exit()
  315. {
  316.     MouseUnInit();        /* disable mouse/keyboard interrupts */
  317.  
  318.     GrSetMode(grx.old_mode);
  319.     GrDestroyContext(grx.bbuf);
  320.  
  321.     return (1);
  322. }
  323.  
  324. static int 
  325. grx_sync()
  326. {
  327. };
  328.  
  329. static int
  330. noop()
  331. {
  332.     return (-1);
  333. }
  334.  
  335. /*
  336.  * grx_font : load either of the fonts
  337.  */
  338. static int
  339. grx_font(char *name)
  340. {
  341. #ifdef DBG
  342.     fprintf(dfp, "fontname=%s\n", name);
  343.     fflush(dfp);
  344. #endif
  345.     /*
  346.      * Hacky way to quicky test for small or large font
  347.      * ... see of they are the same pointers.... this
  348.      * assumes that they have been called from the main
  349.      * library routine with *vdevice.Vfont(vdevice.smallfont);
  350.      */
  351.     if (name == vdevice.dev.small) {
  352.         grx.font = grx.sfont;
  353.         grx.to.txo_font = grx.font;
  354.         vdevice.hheight = grx.font->fnt_height;
  355.         vdevice.hwidth = grx.font->fnt_width;
  356.         grx.fname = name;
  357. #ifdef DBG
  358.         fprintf(dfp, "w, h: %f %f\n", vdevice.hheight, vdevice.hwidth);
  359.         fflush(dfp);
  360. #endif
  361.         return(1);
  362.     } else if (name == vdevice.dev.large) {
  363.         grx.font = grx.lfont;
  364.         grx.to.txo_font = grx.font;
  365.         vdevice.hheight = grx.font->fnt_height;
  366.         vdevice.hwidth = grx.font->fnt_width;
  367.         grx.fname = name;
  368. #ifdef DBG
  369.         fprintf(dfp, "w, h: %f %f\n", vdevice.hheight, vdevice.hwidth);
  370.         fflush(dfp);
  371. #endif
  372.         return(1);
  373.     } else
  374.  
  375.     /* 
  376.      * It must be a completely different font (ala vogle possibility).
  377.      */
  378.     if (strcmp(name, grx.fname)) {
  379.         if (grx.font != grx.sfont && grx.font != grx.lfont)
  380.             GrUnloadFont(grx.font);
  381.  
  382.         if (grx.fname) {
  383.             free(grx.fname);
  384.             grx.fname = (char *)malloc(strlen(name) + 1);
  385.             strcpy(grx.fname, name);
  386.         }
  387.  
  388.         if (!(grx.font = GrLoadFont(name))) {
  389.             return(0);
  390.         }
  391.  
  392.         grx.to.txo_font = grx.font;
  393.  
  394.         vdevice.hheight = grx.font->fnt_height;
  395.         vdevice.hwidth = grx.font->fnt_width;
  396. #ifdef DBG
  397.         fprintf(dfp, "w, h: %f %f\n", vdevice.hheight, vdevice.hwidth);
  398.         fflush(dfp);
  399. #endif
  400.     }
  401.  
  402.     return (1);
  403. }
  404.  
  405. static
  406. int 
  407. grx_char(int c)
  408. {
  409.     GrDrawChar(c, vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy - vdevice.hheight, &grx.to);
  410.     vdevice.cpVx += vdevice.hwidth;
  411.  
  412.     return (1);
  413. };
  414.  
  415. static int
  416. grx_string(char *s)
  417. {
  418.     int    len = strlen(s);
  419.     GrDrawString(s, len, vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy - vdevice.hheight, &grx.to);
  420.     vdevice.cpVx += vdevice.hwidth * len;
  421.     return (1);
  422. }
  423.  
  424.  
  425. /*
  426.  * Everything is supposed to have been through the higher up clippers in
  427.  * vogl.. so no need to clip here..
  428.  * 
  429.  * Draw a solid 1 pixel wide line... libgrx checks for horizontal and vertical
  430.  * lines for us.
  431.  */
  432. static int
  433. grx_solid(int x, int y)
  434. {
  435.  
  436.     GrLineNC(x, vdevice.sizeSy - y,
  437.          vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
  438.          grx.fg
  439.     );
  440.  
  441.     vdevice.cpVx = x;
  442.     vdevice.cpVy = y;
  443.  
  444.     return (0);
  445. }
  446.  
  447. /*
  448.  * Draw a patterned and/or > 1 pixel wide line. (Waiting for libgrx to
  449.  * actually implement this...)
  450.  */
  451. static int
  452. grx_pattern(int x, int y)
  453. {
  454.     GrCustomLine(vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
  455.              x, vdevice.sizeSy - y,
  456.              &grx.lopt
  457.     );
  458.  
  459.     vdevice.cpVx = x;
  460.     vdevice.cpVy = y;
  461.  
  462.     return (0);
  463. };
  464.  
  465. static int
  466. grx_colour(int i)
  467. {
  468.  
  469.     if (i < MAXCOLOR)
  470.         grx.fg = grx.palette[i];    /* for now */
  471.     else
  472.         grx.fg = GrBlack();
  473.  
  474.     grx.lopt.lno_color = grx.fg;
  475.  
  476.     grx.to.txo_fgcolor = grx.fg;
  477.     return (0);
  478. };
  479.  
  480. /*
  481.  * grx_mapcolor
  482.  * 
  483.  * change index i in the color map to the appropriate r, g, b, value.
  484.  */
  485. static int
  486. grx_mapcolor(int c, int r, int g, int b)
  487. {
  488.     int             j;
  489.  
  490.     if (c >= MAXCOLOR || vdevice.depth == 1)
  491.         return (-1);
  492.  
  493.     grx.palette[c] = GrAllocColor(r, g, b);
  494.  
  495. }
  496.  
  497.  
  498. static int
  499. grx_fill(int sides, int *x, int *y)
  500. {
  501.     int             i, j;
  502.     int             points[sides][2];
  503.  
  504.     for (i = 0; i < sides; i++) {
  505.         points[i][0] = x[i];
  506.         points[i][1] = grx.height - y[i];
  507.     }
  508.  
  509.     GrFilledPolygon(sides, points, grx.fg);
  510.  
  511.     return (0);
  512. };
  513.  
  514. static int
  515. grx_checkkey()
  516. {
  517.     char            c;
  518.  
  519.     if (kbhit()) {
  520.         if ((c = getkey()) == 3) {    /* control-c */
  521.             grx_exit();
  522.             /* don't call vexit(), avoid back-refs */
  523.             exit(0);
  524.         } else
  525.             return c;
  526.     } else
  527.         return 0;
  528. }
  529.  
  530. static int
  531. grx_locator(int *x, int *y)
  532. {
  533.     MouseEvent      mEv;
  534.     static          ox = 0, oy = 0, obuttons = 0;
  535.  
  536.     if (!grx.has_mouse) {
  537.         *x = *y = 0;
  538.         return (-1);
  539.     }
  540.     /*
  541.      * if (MousePendingEvent()) {
  542.      */
  543.     MouseGetEvent(M_MOTION | M_BUTTON_CHANGE | M_POLL, &mEv);
  544.  
  545.     if (mEv.flags & M_MOTION) {
  546.         ox = mEv.x;
  547.         oy = vdevice.sizeSy - mEv.y;
  548.     }
  549.     /*
  550.      * HACK... the RIGHT button is the second button and we want it to
  551.      * return 2...
  552.      */
  553.  
  554.     if (mEv.flags & M_BUTTON_CHANGE) {
  555.         obuttons = ((mEv.buttons & M_LEFT) ? 1 : 0) |
  556.             ((mEv.buttons & M_MIDDLE) ? 2 : 0) |
  557.             ((mEv.buttons & M_RIGHT) ? 2 : 0);
  558.     }
  559.     /*
  560.      * }
  561.      */
  562.  
  563.     *x = ox;
  564.     *y = oy;
  565.  
  566.     return (obuttons);
  567. }
  568.  
  569. static
  570. int 
  571. grx_lwidth(int w)
  572. {
  573.  
  574.     grx.lopt.lno_width = w;
  575.     if (w == 1 && grx.lopt.lno_pattlen == 0)
  576.         vdevice.dev.Vdraw = grx_solid;
  577.     else
  578.         vdevice.dev.Vdraw = grx_pattern;
  579. }
  580.  
  581. static
  582. int 
  583. grx_lstyle(int s)
  584. {
  585.  
  586.     static unsigned char dashes[16];
  587.     unsigned        ls = s;
  588.     int             i, n, a, b;
  589.  
  590.     if (grx.lopt.lno_width == 1 && (ls == 0 || ls == 0xffff)) {
  591.         vdevice.dev.Vdraw = grx_solid;
  592.         grx.lopt.lno_pattlen = 0;
  593.         return;
  594.     }
  595.     for (i = 0; i < 16; i++)
  596.         dashes[i] = 0;
  597.  
  598. #define    ON    1
  599. #define    OFF    0
  600.  
  601.     a = b = OFF;
  602.     if (ls & (1 << 0))
  603.         a = b = ON;
  604.  
  605.     n = 0;
  606.     for (i = 0; i < 16; i++) {    /* Over 16 bits */
  607.         if (ls & (1 << i))
  608.             a = ON;
  609.         else
  610.             a = OFF;
  611.  
  612.         if (a != b) {
  613.             b = a;
  614.             n++;
  615.         }
  616.         dashes[n]++;
  617.     }
  618.  
  619.     grx.lopt.lno_pattlen = 16;
  620.     grx.lopt.lno_dashpat = dashes;
  621.     vdevice.dev.Vdraw = grx_pattern;
  622. }
  623.  
  624. static DevEntry grxdev = {
  625.     "grx",
  626.     "@:pc8x16.fnt",        /* Large font */
  627.     "@:pc8x8.fnt",        /* Small font */
  628.     grx_backbuffer,        /* backbuffer */
  629.     grx_char,        /* hardware char */
  630.     grx_checkkey,        /* keyhit */
  631.     grx_vclear,        /* clear viewport to current colour */
  632.     grx_colour,        /* set current colour */
  633.     grx_solid,        /* draw line */
  634.     grx_exit,        /* close graphics & exit */
  635.     grx_fill,        /* fill polygon */
  636.     grx_font,        /* set hardware font */
  637.     grx_frontbuffer,    /* front buffer */
  638.     getkey,            /* wait for and get key */
  639.     grx_init,        /* begin graphics */
  640.     grx_locator,        /* get mouse position */
  641.     grx_mapcolor,        /* map colour (set indices) */
  642. #ifndef VOGLE
  643.     grx_lstyle,        /* set linestyle */
  644. #endif
  645.     grx_lwidth,        /* set line width */
  646.     grx_string,        /* draw string of chars */
  647.     grx_swapbuffers,    /* swap buffers */
  648.     grx_sync        /* sync display */
  649. };
  650.  
  651. /*
  652.  * _grx_devcpy
  653.  * 
  654.  * copy the pc device into vdevice.dev. (as listed in drivers.c)
  655.  */
  656. _grx_devcpy()
  657. {
  658.     vdevice.dev = grxdev;
  659.     return (0);
  660. }
  661.