/* grSunW3.c - * * This file contains additional functions to manipulate an Sun * color display. Included here are device-dependent routines to draw and * erase text and draw a grid. * * ********************************************************************* * * 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. * * ********************************************************************* */ #ifndef lint static char rcsid[]="$Header: /ufs/repository/magic/graphics/grSunW3.c,v 1.2 2001/01/12 22:12:47 jsolomon Exp $"; #endif #ifdef sun #include #include #undef bool #define Rect MagicRect /* Avoid Sun's definition of Rect. */ #include "misc/magic.h" #include "utils/geometry.h" #include "utils/geofast.h" #include "graphics/graphics.h" #include "windows/windows.h" #include "graphics/graphicsInt.h" #include "textio/textio.h" #include "graphics/grSunWInt.h" #include "signals/signals.h" /* our fonts */ struct pixfont *grSunWFontSmall, *grSunWFontMedium; struct pixfont *grSunWFontLarge, *grSunWFontXLarge, *grSunWFontSys; int sunWCurCharSize = -1; /* Current character size */ struct pixfont * grSunWFont(fontname) char *fontname; { char filename1[100], filename2[100]; struct pixfont *font; sprintf(filename1, "/usr/lib/fonts/fixedwidthfonts/%.30s", fontname); font = pf_open(filename1); if (font == NULL) { sprintf(filename2, "/usr/suntool/fixedwidthfonts/%.30s", fontname); font = pf_open(filename2); if (font == NULL) { TxError("Could not open font file '%s'\nnor '%s'\n", filename1, filename2); MainExit(1); } } return font; } /*--------------------------------------------------------- * grSunWTextInit -- * Initialize the text stuff. * * Results: * none. * * Side Effects: * variables are initialized. *--------------------------------------------------------- */ void grSunWTextInit() { grSunWFontSmall = grSunWFont("screen.r.7"); grSunWFontMedium = grSunWFont("screen.r.11"); grSunWFontLarge = grSunWFont("screen.b.14"); grSunWFontXLarge = grSunWFont("gallant.r.19"); grSunWFontSys = pw_pfsysopen(); } /*--------------------------------------------------------- * sunWDrawGrid -- * sunWDrawGrid 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: * Pixels are added to the grid layer, to draw a dot at each grid point. * Intervals are given by * the dimensions of prect such that a line runs through each side of * the given rectangle. * * Errors: None. *--------------------------------------------------------- */ bool sunWDrawGrid(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; bool useLines; ASSERT(grCurSunWData != NULL, "sunWDrawGrid"); 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; useLines = TRUE; /* Lines are MUCH faster. */ 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; if (useLines) { /* Draw a grid using lines (solid lines, since the Sun has * trouble drawing dashed ones). */ for (x = xstart; x < (clip->r_xtop+1)<<12; x += xsize) { if (SigInterruptPending) return; (*grDrawLinePtr)(x>>12, clip->r_ybot, x>>12, clip->r_ytop); } DIDDLE_LOCK(); for (y = ystart; y < (clip->r_ytop+1)<<12; y += ysize) { if (SigInterruptPending) return; (*grDrawLinePtr)(clip->r_xbot, y>>12, clip->r_xtop, y>>12); } } else { /* Draw a grid using dots at the grid points */ for (x = xstart; x < (clip->r_xtop+1)<<12; x += xsize) { if (SigInterruptPending) return; DIDDLE_LOCK(); for (y = ystart; y < (clip->r_ytop+1)<<12; y += ysize) { pw_put(grCurSunWData->gr_pw, x >> 12, INVERTWY(y >> 12), sunWColor); } } } return TRUE; } /*--------------------------------------------------------- * sunwSetCharSize: * This local routine sets the character size in the display, * if necessary. * * Results: None. * * Side Effects: * If the current display character size isn't already equal to size, * then it is made so. *--------------------------------------------------------- */ Void sunWSetCharSize(size) int size; /* Width of characters, in pixels (6 or 8). */ { sunWCurCharSize = size; } /* * ---------------------------------------------------------------------------- * SunWReadPixel -- * * Read one pixel. * * Results: * An integer containing the pixel, or -1 if an error ocurred. * * Side effects: * none. * ---------------------------------------------------------------------------- */ int SunWReadPixel(w, x, y) MagWindow *w; int x, y; /* a pixel on the screen */ { int val; if (w == (MagWindow *) NULL) { TxError("You must be pointing to a window.\n"); return -1; } GrLock(w, FALSE); GR_CHECK_LOCK(); val = pw_get(grCurSunWData->gr_pw, x, INVERTWY(y)); if (!rl_empty(&grCurSunWData->gr_pw->pw_fixup)) { TxError("Could not read pixel value.\n"); val = -1; } else { val = val & grBitPlaneMask; } GrUnlock(w); return val; } /* * ---------------------------------------------------------------------------- * SunWBitBlt -- * * Copy information from one part of the screen to the other. * * Results: * None. * * Side effects: * changes the screen. * ---------------------------------------------------------------------------- */ void SunWBitBlt(r, p) Rect *r; /* the source of pixels */ Point *p; /* the destination */ { ASSERT(grCurSunWData != NULL, "SunWBitBlt"); /* NOT DEBUGGED */ pw_rop(grCurSunWData->gr_pw, r->r_xbot, INVERTWY(r->r_ybot), r->r_xtop - r->r_xbot + 1, r->r_ytop - r->r_ybot + 1, PIX_SRC, grCurSunWData->gr_pw, p->p_x, INVERTWY(p->p_y)); } /* * ---------------------------------------------------------------------------- * SunWTextSize -- * * 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 SunWTextSize(text, size, r) char *text; int size; Rect *r; { struct pixfont *font; struct pr_size prsize; switch (size) { case GR_TEXT_SMALL: font = grSunWFontSmall; break; case GR_TEXT_MEDIUM: font = grSunWFontMedium; break; case GR_TEXT_LARGE: font = grSunWFontLarge; break; case GR_TEXT_XLARGE: font = grSunWFontXLarge; break; case GR_TEXT_DEFAULT: font = grSunWFontSys; break; default: TxError("Unusual text size (internal error)\n"); font = grSunWFontSys; break; } prsize = pf_textwidth(strlen(text), font, text); r->r_xbot = 0; r->r_ybot = 0; r->r_xtop = prsize.x - 1; r->r_ytop = prsize.y - 1; if (text[0] != '\0') { int xorg, yorg; /* find the baseline origin */ xorg = -font->pf_char[text[0]].pc_home.x; r->r_xbot += xorg; r->r_xtop += xorg; yorg = (-font->pf_char[text[0]].pc_home.y) - (font->pf_char[text[0]].pc_pr->pr_height - 1); r->r_ybot += yorg; r->r_ytop += yorg; } } /*--------------------------------------------------------- * * sunWPutText -- * * This routine puts a chunk of text on the screen. * It is tuned for speed. * * General strategy: * * Figure out how big the clipped text will have to be, and * ensure we have a big enough memory pixrect to hold it. * * Write the text into this region using pf_text (NOTE: this * is NOT transparent text writing). Clipping is enabled. * * Use pw_rop to copy that region to the screen (for B&W * displays) or pw_stencil (for color displays) * * Results: * none. * * Side Effects: * The text is drawn on the screen. * *--------------------------------------------------------- */ /*ARGSUSED*/ Void sunWPutText(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; /* Clip to this area */ LinkedRect *obscure; /* List of obscuring windows (ignored) */ { static struct pixrect *memPixRect = (struct pixrect *) NULL; int offsetx, offsety, clipwidth, clipheight; struct pr_subregion bound; struct pixfont *font; struct pr_prpos where; Rect realClip; int op; /* Which font? */ switch (sunWCurCharSize) { case GR_TEXT_SMALL: font = grSunWFontSmall; break; case GR_TEXT_MEDIUM: font = grSunWFontMedium; break; case GR_TEXT_LARGE: font = grSunWFontLarge; break; case GR_TEXT_XLARGE: font = grSunWFontXLarge; break; case GR_TEXT_DEFAULT: font = grSunWFontSys; break; default: TxError("Unusual text size (internal error)\n"); font = grSunWFontSys; break; } /* Obtain a bounding box for the text in its own coordinate system */ pf_textbound(&bound, strlen(text), font, text); /* * Relocate the resulting area to the place we want to draw the text. * Use the intersection of the text area and the clip area as * the actual clipping area. */ realClip.r_xbot = pos->p_x + bound.pos.x; realClip.r_xtop = realClip.r_xbot + bound.size.x - 1; realClip.r_ytop = pos->p_y - bound.pos.y; realClip.r_ybot = realClip.r_ytop - bound.size.y + 1; GEOCLIP(&realClip, clip); clip = &realClip; /* Origin of new clip area in pixrect coordinates */ offsetx = clip->r_xbot; offsety = INVERTWY(clip->r_ytop); /* Where text goes relative to new clip area's origin */ where.pos.x = pos->p_x - offsetx; where.pos.y = INVERTWY(pos->p_y) - offsety; /* Size of new clip area */ clipwidth = clip->r_xtop - clip->r_xbot + 1; clipheight = clip->r_ytop - clip->r_ybot + 1; /* Done if no work to do */ if (clipwidth <= 0 || clipheight <= 0) return; /* Ensure we have a place big enough to hold the clipped text */ if (memPixRect == NULL || memPixRect->pr_size.x < clipwidth || memPixRect->pr_size.y < clipheight) { if (memPixRect) pr_destroy(memPixRect); memPixRect = mem_create(clipwidth, clipheight, 1); } /* * Write the text into this region using pf_text. * This clips correctly on the bottom and left, but not necessarily * on the top and right since memPixRect may be bigger than needed. */ where.pr = memPixRect; pf_text(where, PIX_SRC, font, text); /* * Use pw_rop to copy only the portion of this region that * will actually appear in the destination into the destination. */ DIDDLE_LOCK(); switch (sunWIntType) { case SUNTYPE_BW: op = sunWColor ? (PIX_SRC|PIX_DST) : (PIX_NOT(PIX_SRC) & PIX_DST); pw_rop(grCurSunWData->gr_pw, offsetx, offsety, clipwidth, clipheight, op, memPixRect, 0, 0); break; case SUNTYPE_110: case SUNTYPE_160: pw_stencil(grCurSunWData->gr_pw, offsetx, offsety, clipwidth, clipheight, PIX_SRC | PIX_COLOR(sunWColor), memPixRect, 0, 0, NULL, 0, 0); break; } } #endif