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