/* grOGLsu3.c - * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* * * This file contains additional functions to manipulate an X window system * color display. Included here are device-dependent routines to draw and * erase text and draw a grid. * */ #include #include #include #include #include "misc/magic.h" #include "utils/geometry.h" #include "graphics/graphics.h" #include "windows/windows.h" #include "graphics/graphicsInt.h" #include "textio/textio.h" #include "signals/signals.h" #include "utils/utils.h" #include "utils/hash.h" #include "grOGLInt.h" extern Display *grXdpy; static XFontStruct *grXFonts[4]; #define grSmallFont grXFonts[0] #define grMediumFont grXFonts[1] #define grLargeFont grXFonts[2] #define grXLargeFont grXFonts[3] GLuint grXBases[4]; /*--------------------------------------------------------- * groglDrawGrid: * groglDrawGrid adds a grid to the grid layer, using the current * write mask and color. * * Results: * TRUE is returned normally. However, if the grid gets too small * to be useful, then nothing is drawn and FALSE is returned. * * Side Effects: None. *--------------------------------------------------------- */ bool groglDrawGrid (prect, outline, clip) Rect *prect; /* A rectangle that forms the template * for the grid. Note: in order to maintain * precision for the grid, the rectangle * coordinates are specified in units of * screen coordinates multiplied by 4096. */ int outline; /* the outline style */ Rect *clip; /* a clipping rectangle */ { int xsize, ysize; int x, y; int xstart, ystart; int snum, low, hi, shifted; xsize = prect->r_xtop - prect->r_xbot; ysize = prect->r_ytop - prect->r_ybot; if (GRID_TOO_SMALL(xsize, ysize, GR_NUM_GRIDS)) return FALSE; xstart = prect->r_xbot % xsize; while (xstart < clip->r_xbot<<12) xstart += xsize; ystart = prect->r_ybot % ysize; while (ystart < clip->r_ybot<<12) ystart += ysize; /* ErrPrint("drawing grid\n"); */ groglSetLineStyle(outline); glBegin(GL_LINES); snum = 0; low = clip->r_ybot; hi = clip->r_ytop; for (x = xstart; x < (clip->r_xtop+1)<<12; x += xsize) { if (snum >= GR_NUM_GRIDS) break; shifted = x >> 12; glVertex2i(shifted, low); glVertex2i(shifted, hi); } low = clip->r_xbot; hi = clip->r_xtop; for (y = ystart; y < (clip->r_ytop+1)<<12; y += ysize) { if (snum >= GR_NUM_GRIDS) break; shifted = y >> 12; glVertex2i(low, shifted); glVertex2i(hi, shifted); } glEnd(); /* ErrPrint("done drawing grid\n"); */ return true; } /*--------------------------------------------------------- * groglPreLoadFont * This local routine loads the X fonts used by Magic. * At this time, we need the font information to size * the window (making room for the title at the top), * but with no rendering context set (no window to * draw to) we defer transferring the font bitmaps to * OpenGL display lists until later. * * Results: None. * * Side Effects: None. *--------------------------------------------------------- */ bool groglPreLoadFont() { XFontStruct *fontInfo; int i; char *s; char *unable = "Unable to load font"; static char *fontnames[4] = { X_FONT_SMALL, X_FONT_MEDIUM, X_FONT_LARGE, X_FONT_XLARGE }; static char *optionnames[4] = { "small", "medium", "large", "xlarge"}; /* ErrPrint("Loading Fonts\n"); */ for (i = 0; i < 4; i++) { s = XGetDefault(grXdpy,"magic",optionnames[i]); if (s) fontnames[i] = s; if ((fontInfo = XLoadQueryFont(grXdpy, fontnames[i])) == NULL) { TxError("%s %s\n",unable,fontnames[i]); if ((grXFonts[i]= XLoadQueryFont(grXdpy,GR_DEFAULT_FONT))==NULL) { TxError("%s %s\n",unable,GR_DEFAULT_FONT); return false; } } grXFonts[i] = fontInfo; } return true; } /*--------------------------------------------------------- * groglLoadFont * This local routine transfers the X font bitmaps * into OpenGL display lists for simple text * rendering. * * Results: None. * * Side Effects: None. *--------------------------------------------------------- */ bool groglLoadFont() { XFontStruct *fontInfo; Font id; unsigned int first, last, i; for (i = 0; i < 4; i++) { fontInfo = grXFonts[i]; id = fontInfo->fid; first = fontInfo->min_char_or_byte2; last = fontInfo->max_char_or_byte2; grXBases[i] = glGenLists(last+1); if (grXBases[i] == 0) { TxError("Out of display lists!\n"); return false; } glXUseXFont(id, first, last-first+1, grXBases[i]+first); } return true; } /*--------------------------------------------------------- * groglSetCharSize: * This local routine sets the character size in the display, * if necessary. * * Results: None. * * Side Effects: None. *--------------------------------------------------------- */ Void groglSetCharSize (size) int size; /* Width of characters */ { oglCurrent.fontSize = size; switch (size) { case GR_TEXT_DEFAULT: case GR_TEXT_SMALL: oglCurrent.font = grSmallFont; break; case GR_TEXT_MEDIUM: oglCurrent.font = grMediumFont; break; case GR_TEXT_LARGE: oglCurrent.font = grLargeFont; break; case GR_TEXT_XLARGE: oglCurrent.font = grXLargeFont; break; default: TxError("%s%d\n", "grx11SetCharSize: Unknown character size ", size ); break; break; } } /* * ---------------------------------------------------------------------------- * GrOGLTextSize -- * * Determine the size of a text string. * * Results: * None. * * Side effects: * A rectangle is filled in that is the size of the text in pixels. * The origin (0, 0) of this rectangle is located on the baseline * at the far left side of the string. * ---------------------------------------------------------------------------- */ Void GrOGLTextSize(text, size, r) char *text; int size; Rect *r; { XCharStruct overall; XFontStruct *font; int dir,fa,fd; switch (size) { case GR_TEXT_DEFAULT: case GR_TEXT_SMALL: font = grSmallFont; break; case GR_TEXT_MEDIUM: font = grMediumFont; break; case GR_TEXT_LARGE: font = grLargeFont; break; case GR_TEXT_XLARGE: font = grXLargeFont; break; default: TxError("%s%d\n", "GrX11TextSize: Unknown character size ", size ); break; } if (font == NULL) return; XTextExtents(font, text, strlen(text), &dir, &fa, &fd, &overall); r->r_ytop = overall.ascent; r->r_ybot = -overall.descent; r->r_xtop = overall.width - overall.lbearing; r->r_xbot = -overall.lbearing - 1; /* ErrPrint2("Text font = 0x%x. String = \"%s\"\n", font, text); */ /* ErrPrint4("Bounding box: (%d %d) (%d %d)\n", r->r_xbot, r->r_ybot, r->r_xtop, r->r_ytop); */ } /* * ---------------------------------------------------------------------------- * GrXReadPixel -- * * Read one pixel from the screen. * * Results: * An integer containing the pixel's color. * * Side effects: * none. * * ---------------------------------------------------------------------------- */ int GrOGLReadPixel (w, x, y) MagWindow *w; int x,y; /* the location of a pixel in screen coords */ { return 0; } /* * ---------------------------------------------------------------------------- * GrXBitBlt -- * * Copy information from one part of the screen to the other. * * Results: * None. * * Side effects: * changes the screen. * ---------------------------------------------------------------------------- */ Void GrOGLBitBlt(r, p) Rect *r; Point *p; { /* ErrPrint("Bit block transfer\n"); */ glCopyPixels(r->r_xbot, r->r_ybot, r->r_xtop - r->r_xbot + 1, r->r_ytop - r->r_ybot + 1, GL_COLOR); /* ErrPrint("done Bit block transfer\n"); */ } /*--------------------------------------------------------- * grxPutText: * (modified on SunPutText) * * This routine puts a chunk of text on the screen in the current * color, size, etc. The caller must ensure that it fits on * the screen -- no clipping is done except to the obscuring rectangle * list and the clip rectangle. * * Results: * none. * * Side Effects: * The text is drawn on the screen. * *--------------------------------------------------------- */ Void groglPutText (text, pos, clip, obscure) char *text; /* The text to be drawn. */ Point *pos; /* A point located at the leftmost point of * the baseline for this string. */ Rect *clip; /* A rectangle to clip against */ LinkedRect *obscure; /* A list of obscuring rectangles */ { Rect location; Rect overlap; Rect textrect; LinkedRect *ob; void grOGLGeoSub(); int i; float tscale; GrOGLTextSize(text, oglCurrent.fontSize, &textrect); location.r_xbot = pos->p_x + textrect.r_xbot; location.r_xtop = pos->p_x + textrect.r_xtop; location.r_ybot = pos->p_y + textrect.r_ybot; location.r_ytop = pos->p_y + textrect.r_ytop; /* erase parts of the bitmap that are obscured */ for (ob = obscure; ob != NULL; ob = ob->r_next) { if (GEO_TOUCH(&ob->r_r, &location)) { overlap = location; GeoClip(&overlap, &ob->r_r); grOGLGeoSub(&location, &overlap); } } overlap = location; GeoClip(&overlap, clip); /* copy the text to the color screen */ if ((overlap.r_xbot < overlap.r_xtop)&&(overlap.r_ybot <= overlap.r_ytop)) { glDisable(GL_BLEND); glRasterPos2i(pos->p_x, pos->p_y); glListBase(grXBases[(oglCurrent.fontSize == GR_TEXT_DEFAULT) ? GR_TEXT_SMALL : oglCurrent.fontSize]); glCallLists(strlen(text), GL_UNSIGNED_BYTE, (unsigned char *)text); } } /* grOGLGeoSub: * return the tallest sub-rectangle of r not obscured by area * area must be within r. */ void grOGLGeoSub(r, area) register Rect *r; /* Rectangle to be subtracted from. */ register Rect *area; /* Area to be subtracted. */ { if (r->r_xbot == area->r_xbot) r->r_xbot = area->r_xtop; else if (r->r_xtop == area->r_xtop) r->r_xtop = area->r_xbot; else if (r->r_ybot <= area->r_ybot) r->r_ybot = area->r_ytop; else if (r->r_ytop == area->r_ytop) r->r_ytop = area->r_ybot; else r->r_xtop = area->r_xbot; }