/* grTCairo5.c - * * Copyright 2017 Open Circuit Design * * Manipulate the programable cursor on the graphics display. * * Written by Chuan Chen */ #include #include #include #include "tcltk/tclmagic.h" #include "utils/magic.h" #include "utils/styles.h" #include "utils/hash.h" #include "textio/textio.h" #include "utils/geometry.h" #include "graphics/glyphs.h" #include "windows/windows.h" #include "graphics/graphics.h" #include "graphics/graphicsInt.h" #include "grTkCommon.h" #include "grTCairoInt.h" extern Display *grXdpy; extern int grXscrn; extern HashTable grTCairoWindowTable; /* * ---------------------------------------------------------------------------- * GrTCairoDrawGlyph -- * * Draw one glyph on the display. * * Results: * None. * * Side effects: * Draws pixels. * ---------------------------------------------------------------------------- */ void GrTCairoDrawGlyph (gl, p) GrGlyph *gl; /* A single glyph */ Point *p; /* screen pos of lower left corner */ { Rect bBox; bool anyObscure; LinkedRect *ob; TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2; GR_CHECK_LOCK(); /* We're going to change the graphics state without affecting */ /* the standard color and mask saved values, so we had better */ /* flush all rects & lines first. */ GR_TCAIRO_FLUSH_BATCH(); bBox.r_ll = *p; bBox.r_xtop = p->p_x + gl->gr_xsize - 1; bBox.r_ytop = p->p_y + gl->gr_ysize - 1; anyObscure = FALSE; for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { if (GEO_TOUCH( &(ob->r_r), &bBox)) { anyObscure = TRUE; break; } } if ((!anyObscure) && (GEO_SURROUND(&grCurClip, &bBox)) ) { int *pixelp, x, y, thisp, lastp; int color, red, green, blue, mask; /* no clipping, try to go quickly */ pixelp = gl->gr_pixels; thisp = -1; for (y = 0; y < gl->gr_ysize; y++) { int x1, y1; y1 = bBox.r_ybot + y; for (x = 0; x < gl->gr_xsize; x++) { lastp = thisp; thisp = *pixelp++; if (thisp != 0) { /* Note: mask has traditionally been 0-127 */ if (thisp != lastp) { if (lastp != -1) { cairo_fill(tcairodata->context); } mask = GrStyleTable[thisp].mask << 1; color = GrStyleTable[thisp].color; GrGetColor(color, &red, &green, &blue); cairo_set_source_rgba(tcairodata->context, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0)); } x1 = bBox.r_xbot + x; cairo_rectangle(tcairodata->context, x1, y1, 1, 1); } } } if (lastp != -1) { cairo_fill(tcairodata->context); } } else { /* do pixel by pixel clipping */ int y, yloc; yloc = bBox.r_ybot; for (y = 0; y < gl->gr_ysize; y++) { int startx, endx; if ( (yloc <= grCurClip.r_ytop) && (yloc >= grCurClip.r_ybot) ) { int laststartx; laststartx = bBox.r_xbot - 1; for (startx = bBox.r_xbot; startx <= bBox.r_xtop; startx = endx + 1) { int *pixelp; startx = MAX(startx, grCurClip.r_xbot); endx = MIN(bBox.r_xtop, grCurClip.r_xtop); if (anyObscure) { for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { if ( (ob->r_r.r_ybot <= yloc) && (ob->r_r.r_ytop >= yloc) ) { if (ob->r_r.r_xbot <= startx) startx = MAX(startx, ob->r_r.r_xtop + 1); else if (ob->r_r.r_xbot <= endx) endx = MIN(endx, ob->r_r.r_xbot - 1); } } } /* stop if we aren't advancing */ if (startx == laststartx) break; laststartx = startx; if (startx > endx) continue; /* draw a section of this scan line */ pixelp = &( gl->gr_pixels[y * gl->gr_xsize + (startx - bBox.r_xbot)]); for ( ; startx <= endx; startx++) { int color, red, green, blue, mask; if (*pixelp != 0) { mask = GrStyleTable[*pixelp].mask << 1; color = GrStyleTable[*pixelp].color; GrGetColor(color, &red, &green, &blue); cairo_set_source_rgba(tcairodata->context, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0)); cairo_rectangle(tcairodata->context, startx, yloc, 1, 1); cairo_fill(tcairodata->context); } pixelp++; } startx = endx + 1; } } yloc++; } } } /* * ---------------------------------------------------------------------------- * GrTCairoSetCursor: * * Make the cursor be a new pattern, as defined in the display styles file. * * Results: * None. * * Side effects: * When the cursor is turned back on it will take on the new pattern. * ---------------------------------------------------------------------------- */ void GrTCairoSetCursor(cursorNum) int cursorNum; /* The cursor number as defined in the display * styles file. */ { HashEntry *entry; HashSearch hs; Tk_Window tkwind; if (cursorNum >= MAX_CURSORS) { TxError("No such cursor!\n"); return; } tcairoCurrent.cursor = grCursors[cursorNum]; HashStartSearch(&hs); while ((entry = HashNext(&grTCairoWindowTable, &hs))) { if (HashGetValue(entry)) { tkwind = (Tk_Window)entry->h_key.h_ptr; Tk_DefineCursor(tkwind, tcairoCurrent.cursor); } } }