Finished the implementation of Cairo 2D graphics (yay!).

Specifically, fixed the initial background, display of text,
reinstated supercolor values, and fixed the backing store
coordinates.
This commit is contained in:
Tim Edwards 2017-09-14 17:03:53 -04:00
parent d9fe6b1573
commit 35c3510ea7
21 changed files with 5468 additions and 991 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
/* grTCairo2.c -
*
* Copyright 2017 Open Circuit Design
*
* This file contains additional functions to manipulate an X
* color display. Included here are rectangle drawing and color map
* loading.
*
* Written by Chuan Chen
*/
#include <stdio.h>
char *getenv();
#include <cairo/cairo-xlib.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.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 "grTCairoInt.h"
#include "textio/txcommands.h"
extern char *DBWStyleType;
extern Display *grXdpy;
extern cairo_pattern_t *currentStipple;
/*---------------------------------------------------------
* GrTCairoSetCMap --
*
* Cairo uses RGB values as read from the colormap file,
* directly, so there is no need to install colors into a
* colormap. Therefore, this is a null routine.
*
* Results: None.
*
* Side Effects: None.
*
*---------------------------------------------------------
*/
void
GrTCairoSetCMap ()
{
}
Rect grtcairoLines[TCAIRO_BATCH_SIZE];
int grtcairoNbLines = 0;
TCairoRect grtcairoRects[TCAIRO_BATCH_SIZE];
int grtcairoNbRects = 0;
Rect grtcairoDiagonal[TCAIRO_BATCH_SIZE];
int grtcairoNbDiagonal = 0;
/*---------------------------------------------------------
* grtcairoDrawLines:
* This routine draws a batch of lines.
*
* Results: None.
*
* Side Effects:
* Draw a bunch of lines.
*---------------------------------------------------------
*/
void
grtcairoDrawLines(lines, nb)
Rect lines[];
int nb;
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
int i;
for (i = 0; i < nb; i++)
{
cairo_move_to(tcairodata->context, lines[i].r_ll.p_x, lines[i].r_ll.p_y);
cairo_line_to(tcairodata->context, lines[i].r_ur.p_x, lines[i].r_ur.p_y);
}
// cairo_set_source_rgba(tcairodata->context, r, g, b, a);
// cairo_set_line_width(tcairodata->context, width);
cairo_stroke(tcairodata->context);
}
/*---------------------------------------------------------
* grtcairoDrawLine:
* This routine draws a line.
*
* Results: None.
*
* Side Effects:
* Draw a line for (x1, y1) to (x2, y2) inclusive.
*---------------------------------------------------------
*/
void
grtcairoDrawLine (x1, y1, x2, y2)
int x1, y1; /* Screen coordinates of first point. */
int x2, y2; /* Screen coordinates of second point. */
{
/* Treat straight and diagonal lines separately. */
/* (Done for OpenGL; possibly not necessary for Cairo) */
if ((x1 == x2) || (y1 == y2))
{
if (grtcairoNbLines == TCAIRO_BATCH_SIZE) GR_TCAIRO_FLUSH_LINES();
grtcairoLines[grtcairoNbLines].r_ll.p_x = x1;
grtcairoLines[grtcairoNbLines].r_ll.p_y = y1;
grtcairoLines[grtcairoNbLines].r_ur.p_x = x2;
grtcairoLines[grtcairoNbLines].r_ur.p_y = y2;
grtcairoNbLines++;
}
else
{
if (grtcairoNbDiagonal == TCAIRO_BATCH_SIZE) GR_TCAIRO_FLUSH_DIAGONAL();
grtcairoDiagonal[grtcairoNbDiagonal].r_ll.p_x = x1;
grtcairoDiagonal[grtcairoNbDiagonal].r_ll.p_y = y1;
grtcairoDiagonal[grtcairoNbDiagonal].r_ur.p_x = x2;
grtcairoDiagonal[grtcairoNbDiagonal].r_ur.p_y = y2;
grtcairoNbDiagonal++;
}
}
/*---------------------------------------------------------
* grtcairoFillRects:
* This routine draws a bunch of solid rectangles.
*
* Results: None.
*
* Side Effects:
* Drawing.
*---------------------------------------------------------
*/
void
grtcairoFillRects(rects, nb)
TCairoRect rects[];
int nb;
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
int i;
for (i = 0; i < nb; i++)
{
cairo_rectangle(tcairodata->context,
rects[i].r_ll.p_x, rects[i].r_ll.p_y,
rects[i].r_ur.p_x-rects[i].r_ll.p_x, rects[i].r_ur.p_y-rects[i].r_ll.p_y);
// TxPrintf("%d %d %d %d \n", rects[i].r_ll.p_x, rects[i].r_ll.p_y, rects[i].r_ur.p_x-rects[i].r_ll.p_x, rects[i].r_ur.p_y-rects[i].r_ll.p_y);
}
cairo_clip(tcairodata->context);
cairo_mask(tcairodata->context, currentStipple);
}
/*---------------------------------------------------------
* grtcairoFillRect:
* This routine draws a solid rectangle.
*
* Results: None.
*
* Side Effects:
* Drawing.
*---------------------------------------------------------
*/
void
grtcairoFillRect(r)
Rect *r; /* Address of a rectangle in screen
* coordinates.
*/
{
if (grtcairoNbRects == TCAIRO_BATCH_SIZE) GR_TCAIRO_FLUSH_RECTS();
grtcairoRects[grtcairoNbRects].r_ll.p_x = r->r_ll.p_x;
grtcairoRects[grtcairoNbRects].r_ll.p_y = r->r_ll.p_y;
grtcairoRects[grtcairoNbRects].r_ur.p_x = r->r_ur.p_x;
grtcairoRects[grtcairoNbRects].r_ur.p_y = r->r_ur.p_y;
grtcairoRects[grtcairoNbRects].r_ul.p_x = r->r_ll.p_x;
grtcairoRects[grtcairoNbRects].r_ul.p_y = r->r_ur.p_y;
grtcairoRects[grtcairoNbRects].r_lr.p_x = r->r_ur.p_x;
grtcairoRects[grtcairoNbRects].r_lr.p_y = r->r_ll.p_y;
grtcairoNbRects++;
}
/*---------------------------------------------------------
* grtcairoFillPolygon:
* This routine draws a solid (convex) polygon
*
* Results: None.
*
* Side Effects:
* Drawing.
*---------------------------------------------------------
*/
void
grtcairoFillPolygon(tp, np)
Point *tp;
int np;
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
int i;
cairo_move_to(tcairodata->context, tp[0].p_x, tp[0].p_y);
for (i = 1; i < np; i++)
cairo_line_to(tcairodata->context, tp[i].p_x, tp[i].p_y);
cairo_close_path(tcairodata->context);
cairo_fill(tcairodata->context);
}

View File

@ -0,0 +1,648 @@
/* grTCairo3.c -
*
* Copyright 2017 Open Circuit Design
*
* 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.
*
* Written by Chuan Chen
*/
#include <stdio.h>
#include <string.h>
#include <cairo/cairo-xlib.h>
#include <math.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/malloc.h"
#include "windows/windows.h"
#include "graphics/graphics.h"
#include "graphics/graphicsInt.h"
#include "dbwind/dbwind.h"
#include "textio/textio.h"
#include "utils/signals.h"
#include "utils/utils.h"
#include "utils/hash.h"
#include "graphics/grTCairoInt.h"
#include "graphics/grTkCommon.h"
#include "database/fonts.h"
extern Display *grXdpy;
static GC grXcopyGC = (GC)NULL;
/* locals */
/*---------------------------------------------------------
* grtcairoDrawGrid:
* grxDrawGrid 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
grtcairoDrawGrid (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 SUBPIXEL.
*/
int outline; /* the outline style */
Rect *clip; /* a clipping rectangle */
{
int xsize, ysize;
int x, y;
int xstart, ystart;
int snum, low, hi, shifted;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
xsize = prect->r_xtop - prect->r_xbot;
ysize = prect->r_ytop - prect->r_ybot;
if (!xsize || !ysize || GRID_TOO_SMALL(xsize, ysize))
return FALSE;
xstart = prect->r_xbot % xsize;
while (xstart < clip->r_xbot << SUBPIXELBITS) xstart += xsize;
ystart = prect->r_ybot % ysize;
while (ystart < clip->r_ybot << SUBPIXELBITS) ystart += ysize;
snum = 0;
low = clip->r_ybot;
hi = clip->r_ytop;
for (x = xstart; x < (clip->r_xtop + 1) << SUBPIXELBITS; x += xsize)
{
shifted = x >> SUBPIXELBITS;
cairo_move_to(tcairodata->context, shifted, low);
cairo_line_to(tcairodata->context, shifted, hi);
snum++;
}
snum = 0;
low = clip->r_xbot;
hi = clip->r_xtop;
for (y = ystart; y < (clip->r_ytop + 1) << SUBPIXELBITS; y += ysize)
{
shifted = y >> SUBPIXELBITS;
cairo_move_to(tcairodata->context, low, shifted);
cairo_line_to(tcairodata->context, hi, shifted);
snum++;
}
cairo_stroke(tcairodata->context);
return TRUE;
}
/*---------------------------------------------------------
* grtcairoLoadFont
* This local routine loads the default ("toy API")
* font for Cairo.
*
* Results: Success/Failure
*
* Side Effects: None.
*---------------------------------------------------------
*/
bool
grtcairoLoadFont()
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
cairo_select_font_face(tcairodata->context, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
return TRUE;
}
/*---------------------------------------------------------
* grtcairoSetCharSize:
* This local routine sets the character size in the display,
* if necessary.
*
* Results: None.
*
* Side Effects: None.
*---------------------------------------------------------
*/
void
grtcairoSetCharSize (size)
int size; /* Width of characters, in pixels (6 or 8). */
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
tcairoCurrent.fontSize = size;
cairo_set_font_size(tcairodata->context, size * 4 + 10);
switch (size)
{
case GR_TEXT_DEFAULT:
case GR_TEXT_SMALL:
tcairoCurrent.font = grSmallFont;
break;
case GR_TEXT_MEDIUM:
tcairoCurrent.font = grMediumFont;
break;
case GR_TEXT_LARGE:
tcairoCurrent.font = grLargeFont;
break;
case GR_TEXT_XLARGE:
tcairoCurrent.font = grXLargeFont;
break;
default:
TxError("%s%d\n", "grtcairoSetCharSize: Unknown character size ",
size );
break;
}
}
/*
* ----------------------------------------------------------------------------
* GrTCairoTextSize --
*
* 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
GrTCairoTextSize(text, size, r)
char *text;
int size;
Rect *r;
{
Tk_FontMetrics overall;
Tk_Font font;
int width;
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", "GrTCairoTextSize: Unknown character size ",
size );
break;
}
if (font == NULL) return;
Tk_GetFontMetrics(font, &overall);
width = Tk_TextWidth(font, text, strlen(text));
/* Hack alert! Tk_TextWidth returns values too small! */
width = width + (width >> 4);
r->r_ytop = overall.ascent;
r->r_ybot = -overall.descent;
r->r_xtop = width;
r->r_xbot = 0;
}
/* Cairo backing store functions (now removed from the X11-based ones) */
void
grtcairoFreeBackingStore(MagWindow *window)
{
TCairoData *tcairodata;
Pixmap pmap = (Pixmap)window->w_backingStore;
if (pmap == (Pixmap)NULL) return;
XFreePixmap(grXdpy, pmap);
window->w_backingStore = (ClientData)NULL;
tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
/* To do: destroy cairo surface and context */
tcairodata->backing_surface = NULL;
tcairodata->backing_context = NULL;
}
void
grtcairoCreateBackingStore(MagWindow *w)
{
Pixmap pmap;
TCairoData *tcairodata;
Tk_Window tkwind = (Tk_Window)w->w_grdata;
Window wind;
unsigned int width, height;
GC gc;
XGCValues gcValues;
int grDepth;
/* Deferred */
if (tkwind == NULL) return;
wind = (Window)Tk_WindowId(tkwind);
/* ignore all windows other than layout */
if (w->w_client != DBWclientID) return;
/* deferred */
if (wind == (Window)NULL) return;
width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot;
height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
if (w->w_backingStore != (ClientData)NULL) grtcairoFreeBackingStore(w);
if (grXcopyGC == (GC)NULL)
{
gcValues.graphics_exposures = FALSE;
grXcopyGC = XCreateGC(grXdpy, wind, GCGraphicsExposures, &gcValues);
}
grDepth = Tk_Depth((Tk_Window)w->w_grdata);
pmap = XCreatePixmap(grXdpy, wind, width, height, grDepth);
w->w_backingStore = (ClientData)pmap;
tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
tcairodata->backing_surface = cairo_xlib_surface_create(grXdpy, pmap,
DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width, height);
tcairodata->backing_context = cairo_create(tcairodata->backing_surface);
}
bool
grtcairoGetBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
int xbot, ybot;
Rect r;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
if (w->w_backingStore == (ClientData)0) return FALSE;
GEO_EXPAND(area, 1, &r);
GeoClip(&r, &(w->w_screenArea));
width = r.r_xtop - r.r_xbot;
height = r.r_ytop - r.r_ybot;
xbot = r.r_xbot;
ybot = r.r_ybot;
Window root_return;
int x_return, y_return;
unsigned int width_return, height_return;
unsigned int border_width_return;
unsigned int depth_return;
Pixmap pmap;
pmap = (Pixmap)w->w_backingStore;
if (pmap == (Pixmap)NULL)
return FALSE;
cairo_set_source_surface(tcairodata->context, tcairodata->backing_surface, 0, 0);
cairo_rectangle(tcairodata->context, xbot, ybot, width, height);
cairo_set_operator(tcairodata->context, CAIRO_OPERATOR_SOURCE);
cairo_fill(tcairodata->context);
return TRUE;
}
bool
grtcairoScrollBackingStore(MagWindow *w, Point *shift)
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
Pixmap pmap;
unsigned int width, height;
int xorigin, yorigin, xshift, yshift;
pmap = (Pixmap)w->w_backingStore;
if (pmap == (Pixmap)NULL)
{
TxPrintf("grx11ScrollBackingStore %d %d failure\n",
shift->p_x, shift->p_y);
return FALSE;
}
width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot;
height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
xorigin = 0;
yorigin = 0;
xshift = shift->p_x;
yshift = -shift->p_y;
if (xshift > 0)
width -= xshift;
else if (xshift < 0)
{
width += xshift;
xorigin = -xshift;
xshift = 0;
}
if (yshift > 0)
height -= yshift;
else if (yshift < 0)
{
height += yshift;
yorigin = -yshift;
yshift = 0;
}
/* TxPrintf("grx11ScrollBackingStore %d %d\n", shift->p_x, shift->p_y); */
cairo_set_source_surface(tcairodata->context, tcairodata->backing_surface,
xshift, yshift);
cairo_rectangle(tcairodata->context, xshift, yshift, width, height);
cairo_set_operator(tcairodata->context, CAIRO_OPERATOR_SOURCE);
cairo_fill(tcairodata->context);
return TRUE;
}
void
grtcairoPutBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
int ybot, xbot;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
if (w->w_backingStore == (ClientData)0) return;
width = area->r_xtop - area->r_xbot;
height = area->r_ytop - area->r_ybot;
ybot = area->r_ybot;
xbot = area->r_xbot;
if (xbot < 0) {
width -= xbot;
xbot = 0;
}
if (ybot < 0) {
height -= ybot;
ybot = 0;
}
cairo_set_source_surface(tcairodata->backing_context, tcairodata->surface,
0.0, 0.0);
cairo_rectangle(tcairodata->backing_context, xbot, ybot, width, height);
cairo_set_operator(tcairodata->backing_context, CAIRO_OPERATOR_SOURCE);
cairo_fill(tcairodata->backing_context);
// cairo_surface_flush(tcairodata->backing_surface);
// w->w_backingStore = (ClientData) cairo_image_surface_get_data(tcairodata->backing_surface);
// cairo_surface_mark_dirty(tcairodata->backing_surface);
}
/*
* ----------------------------------------------------------------------------
* GrTCairoReadPixel --
*
* Read one pixel from the screen.
*
* Results:
* An integer containing the pixel's color.
*
* Side effects:
* none.
*
* ----------------------------------------------------------------------------
*/
int
GrTCairoReadPixel (w, x, y)
MagWindow *w;
int x, y; /* the location of a pixel in screen coords */
{
return 0; /* (unimplemented) */
}
/*
* ----------------------------------------------------------------------------
* GrTCairoBitBlt --
*
* Copy information in bit block transfers.
*
* Results:
* None.
*
* Side effects:
* changes the screen.
* ----------------------------------------------------------------------------
*/
void
GrTCairoBitBlt(r, p)
Rect *r;
Point *p;
{
// (unimplemented)
}
#ifdef VECTOR_FONTS
/*
*----------------------------------------------------------------------
* Draw a text character
* This routine is similar to grtcairoFillPolygon()
*----------------------------------------------------------------------
*/
void
grtcairoDrawCharacter(clist, tc, pixsize)
FontChar *clist;
unsigned char tc;
int pixsize;
{
Point *tp;
int np, nptotal;
int i, j;
static int maxnp = 0;
FontChar *ccur;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
if (pixsize < 5) return; /* Label too small to be useful */
//should we be using cairo_show_glyphs??
for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) {
tp = ccur->fc_points;
np = ccur->fc_numpoints;
cairo_move_to(tcairodata->context, tp[0].p_x, tp[0].p_y);
for (i = 1; i < np; i++, j += 3) {
cairo_line_to(tcairodata->context, tp[0].p_x, tp[0].p_y);
}
}
cairo_fill(tcairodata->context);
}
/*---------------------------------------------------------
* grtcairoFontText:
*
* This routine draws text from font vectors using the
* font vector routines in DBlabel.c. Text is clipped
* to the clipping rectangle.
*
* For speed, should we be transferring the font
* vectors into cairo glyphs?
*
*---------------------------------------------------------
*/
void
grtcairoFontText(text, font, size, rotate, pos, clip, obscure)
char *text; /* The text to be drawn */
int font; /* Font to use from fontList */
int size; /* Pixel size of the font */
int rotate; /* Text rotation */
Point *pos; /* Text base position */
Rect *clip; /* Clipping area */
LinkedRect *obscure; /* List of obscuring areas */
{
char *tptr;
Point *coffset; /* vector to next character */
Rect *cbbox;
float fsize;
FontChar *clist;
int cheight, baseline;
float tmp;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
cairo_save(tcairodata->context);
cairo_translate(tcairodata->context, pos->p_x, pos->p_y);
cairo_rotate(tcairodata->context, ((double)rotate) / 360 * 2 * M_PI);
/* Get label size */
cbbox = &DBFontList[font]->mf_extents;
fsize = (uint8_t)size / (uint8_t)cbbox->r_ytop;
cairo_scale(tcairodata->context, fsize, fsize);
/* Adjust to baseline */
baseline = 0;
for (tptr = text; *tptr != '\0'; tptr++)
{
DBFontChar(font, *tptr, NULL, NULL, &cbbox);
if (cbbox->r_ybot < baseline)
baseline = cbbox->r_ybot;
}
cairo_translate(tcairodata->context, 0, -baseline);
for (tptr = text; *tptr != '\0'; tptr++)
{
DBFontChar(font, *tptr, &clist, &coffset, NULL);
grtcairoDrawCharacter(clist, *tptr, size);
cairo_translate(tcairodata->context, coffset->p_x, coffset->p_y);
}
cairo_restore(tcairodata->context);
}
#endif /* VECTOR_FONTS */
/*---------------------------------------------------------
* grtcairoPutText:
* (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
grtcairoPutText (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 grTCairoGeoSub();
int i;
float tscale;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
GrTCairoTextSize(text, tcairoCurrent.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);
grTCairoGeoSub(&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))
{
cairo_rectangle(tcairodata->context, overlap.r_xbot,
overlap.r_ybot, overlap.r_xtop - overlap.r_xbot,
overlap.r_ytop - overlap.r_ybot);
cairo_clip(tcairodata->context);
cairo_move_to(tcairodata->context, location.r_xbot, location.r_ybot);
cairo_show_text(tcairodata->context, text);
cairo_fill(tcairodata->context);
}
}
/* grTCairoGeoSub:
* return the tallest sub-rectangle of r not obscured by area
* area must be within r.
*/
void
grTCairoGeoSub(r, area)
Rect *r; /* Rectangle to be subtracted from. */
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;
}

View File

@ -0,0 +1,137 @@
/* grTCairo4.c -
*
* Copyright 2017 Open Circuit Design
*
* This file contains functions to manage the graphics tablet associated
* with the X display.
*
* Written by Chuan Chen
*/
#include <signal.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <cairo/cairo-xlib.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "windows/windows.h"
#include "graphics/graphics.h"
#include "graphics/graphicsInt.h"
#include "graphics/grTkCommon.h"
#include "textio/txcommands.h"
#include "grTCairoInt.h"
extern Display *grXdpy;
/*---------------------------------------------------------
* GrTCairoDisableTablet:
* Turns off the cursor.
*
* Results: None.
*
* Side Effects: None.
*---------------------------------------------------------
*/
void
GrTCairoDisableTablet ()
{
/* (Unimplemented) */
}
/*---------------------------------------------------------
* GrTCairoEnableTablet:
* This routine enables the graphics tablet.
*
* Results:
* None.
*
* Side Effects:
* Simply turn on the crosshair.
*---------------------------------------------------------
*/
void
GrTCairoEnableTablet ()
{
/* (Unimplemented) */
}
/*
* ----------------------------------------------------------------------------
* grtcairoGetCursorPos:
* Read the cursor position in magic coordinates.
*
* Results:
* TRUE is returned if the coordinates were succesfully read, FALSE
* otherwise.
*
* Side effects:
* The parameter is filled in with the cursor position, in the form of
* a point in screen coordinates.
* ----------------------------------------------------------------------------
*/
bool
grtcairoGetCursorPos (mw, p)
MagWindow *mw; /* window for which result is given */
Point *p; /* point to be filled in with screen coordinates */
{
int x, y, x1, y1;
unsigned int buttons;
Window win1, win2;
if (mw == (MagWindow *)NULL) mw = tcairoCurrent.mw;
XQueryPointer(grXdpy, Tk_WindowId((Tk_Window)(mw->w_grdata)),
&win1, &win2, &x1, &y1,
&x, &y, &buttons);
p->p_x = x;
p->p_y = grXtransY(mw, y);
return TRUE;
}
/*
* ----------------------------------------------------------------------------
* grtcairoGetCursorRootPos:
* Read the cursor position in sreen root coordinates.
*
* Results:
* TRUE is returned if the coordinates were succesfully read, FALSE
* otherwise.
*
* Side effects:
* The parameter is filled in with the cursor position, in the form of
* a point in screen coordinates.
* ----------------------------------------------------------------------------
*/
bool
grtcairoGetCursorRootPos (mw, p)
MagWindow *mw; /* window for which result is given */
Point *p; /* point to be filled in with screen coordinates */
{
int x, y, x1, y1;
unsigned int buttons;
Window win1, win2;
if (mw == (MagWindow *)NULL) mw = tcairoCurrent.mw;
XQueryPointer(grXdpy, Tk_WindowId((Tk_Window)(mw->w_grdata)),
&win1, &win2, &x1, &y1,
&x, &y, &buttons);
p->p_x = x1;
p->p_y = y1;
return TRUE;
}

View File

@ -0,0 +1,210 @@
/* grTCairo5.c -
*
* Copyright 2017 Open Circuit Design
*
* Manipulate the programable cursor on the graphics display.
*
* Written by Chuan Chen
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <cairo/cairo-xlib.h>
#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);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,213 @@
/* grTCairo2.c -
*
* Copyright 2017 Open Circuit Design
*
* This file contains additional functions to manipulate an X
* color display. Included here are rectangle drawing and color map
* loading.
*
* Written by Chuan Chen
*/
#include <stdio.h>
char *getenv();
#include <cairo/cairo-xlib.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.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 "grTCairoInt.h"
#include "textio/txcommands.h"
extern char *DBWStyleType;
extern Display *grXdpy;
extern cairo_t *grCairoContext;
extern cairo_surface_t *grCairoSurface;
extern cairo_pattern_t *currentStipple;
/*---------------------------------------------------------
* GrTCairoSetCMap --
*
* Cairo uses RGB values as read from the colormap file,
* directly, so there is no need to install colors into a
* colormap. Therefore, this is a null routine.
*
* Results: None.
*
* Side Effects: None.
*
*---------------------------------------------------------
*/
void
GrTCairoSetCMap ()
{
}
Rect grtcairoLines[TCAIRO_BATCH_SIZE];
int grtcairoNbLines = 0;
TCairoRect grtcairoRects[TCAIRO_BATCH_SIZE];
int grtcairoNbRects = 0;
Rect grtcairoDiagonal[TCAIRO_BATCH_SIZE];
int grtcairoNbDiagonal = 0;
/*---------------------------------------------------------
* grtcairoDrawLines:
* This routine draws a batch of lines.
*
* Results: None.
*
* Side Effects:
* Draw a bunch of lines.
*---------------------------------------------------------
*/
void
grtcairoDrawLines(lines, nb)
Rect lines[];
int nb;
{
int i;
for (i = 0; i < nb; i++)
{
cairo_move_to(grCairoContext, lines[i].r_ll.p_x, lines[i].r_ll.p_y);
cairo_line_to(grCairoContext, lines[i].r_ur.p_x, lines[i].r_ur.p_y);
}
// cairo_set_source_rgba(grCairoContext, r, g, b, a);
// cairo_set_line_width(grCairoContext, width);
cairo_stroke(grCairoContext);
}
/*---------------------------------------------------------
* grtcairoDrawLine:
* This routine draws a line.
*
* Results: None.
*
* Side Effects:
* Draw a line for (x1, y1) to (x2, y2) inclusive.
*---------------------------------------------------------
*/
void
grtcairoDrawLine (x1, y1, x2, y2)
int x1, y1; /* Screen coordinates of first point. */
int x2, y2; /* Screen coordinates of second point. */
{
/* Treat straight and diagonal lines separately. */
/* (Done for OpenGL; possibly not necessary for Cairo) */
if ((x1 == x2) || (y1 == y2))
{
if (grtcairoNbLines == TCAIRO_BATCH_SIZE) GR_TCAIRO_FLUSH_LINES();
grtcairoLines[grtcairoNbLines].r_ll.p_x = x1;
grtcairoLines[grtcairoNbLines].r_ll.p_y = y1;
grtcairoLines[grtcairoNbLines].r_ur.p_x = x2;
grtcairoLines[grtcairoNbLines].r_ur.p_y = y2;
grtcairoNbLines++;
}
else
{
if (grtcairoNbDiagonal == TCAIRO_BATCH_SIZE) GR_TCAIRO_FLUSH_DIAGONAL();
grtcairoDiagonal[grtcairoNbDiagonal].r_ll.p_x = x1;
grtcairoDiagonal[grtcairoNbDiagonal].r_ll.p_y = y1;
grtcairoDiagonal[grtcairoNbDiagonal].r_ur.p_x = x2;
grtcairoDiagonal[grtcairoNbDiagonal].r_ur.p_y = y2;
grtcairoNbDiagonal++;
}
}
/*---------------------------------------------------------
* grtcairoFillRects:
* This routine draws a bunch of solid rectangles.
*
* Results: None.
*
* Side Effects:
* Drawing.
*---------------------------------------------------------
*/
void
grtcairoFillRects(rects, nb)
TCairoRect rects[];
int nb;
{
int i;
for (i = 0; i < nb; i++)
{
cairo_rectangle(grCairoContext,
rects[i].r_ll.p_x, rects[i].r_ll.p_y,
rects[i].r_ur.p_x-rects[i].r_ll.p_x, rects[i].r_ur.p_y-rects[i].r_ll.p_y);
// TxPrintf("%d %d %d %d \n", rects[i].r_ll.p_x, rects[i].r_ll.p_y, rects[i].r_ur.p_x-rects[i].r_ll.p_x, rects[i].r_ur.p_y-rects[i].r_ll.p_y);
}
cairo_clip(grCairoContext);
cairo_mask(grCairoContext, currentStipple);
}
/*---------------------------------------------------------
* grtcairoFillRect:
* This routine draws a solid rectangle.
*
* Results: None.
*
* Side Effects:
* Drawing.
*---------------------------------------------------------
*/
void
grtcairoFillRect(r)
Rect *r; /* Address of a rectangle in screen
* coordinates.
*/
{
if (grtcairoNbRects == TCAIRO_BATCH_SIZE) GR_TCAIRO_FLUSH_RECTS();
grtcairoRects[grtcairoNbRects].r_ll.p_x = r->r_ll.p_x;
grtcairoRects[grtcairoNbRects].r_ll.p_y = r->r_ll.p_y;
grtcairoRects[grtcairoNbRects].r_ur.p_x = r->r_ur.p_x;
grtcairoRects[grtcairoNbRects].r_ur.p_y = r->r_ur.p_y;
grtcairoRects[grtcairoNbRects].r_ul.p_x = r->r_ll.p_x;
grtcairoRects[grtcairoNbRects].r_ul.p_y = r->r_ur.p_y;
grtcairoRects[grtcairoNbRects].r_lr.p_x = r->r_ur.p_x;
grtcairoRects[grtcairoNbRects].r_lr.p_y = r->r_ll.p_y;
grtcairoNbRects++;
}
/*---------------------------------------------------------
* grtcairoFillPolygon:
* This routine draws a solid (convex) polygon
*
* Results: None.
*
* Side Effects:
* Drawing.
*---------------------------------------------------------
*/
void
grtcairoFillPolygon(tp, np)
Point *tp;
int np;
{
int i;
cairo_move_to(grCairoContext, tp[0].p_x, tp[0].p_y);
for (i = 1; i < np; i++)
cairo_line_to(grCairoContext, tp[i].p_x, tp[i].p_y);
cairo_close_path(grCairoContext);
cairo_fill(grCairoContext);
}

View File

@ -0,0 +1,647 @@
/* grTCairo3.c -
*
* Copyright 2017 Open Circuit Design
*
* 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.
*
* Written by Chuan Chen
*/
#include <stdio.h>
#include <string.h>
#include <cairo/cairo-xlib.h>
#include <math.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/malloc.h"
#include "windows/windows.h"
#include "graphics/graphics.h"
#include "graphics/graphicsInt.h"
#include "dbwind/dbwind.h"
#include "textio/textio.h"
#include "utils/signals.h"
#include "utils/utils.h"
#include "utils/hash.h"
#include "graphics/grTCairoInt.h"
#include "graphics/grTkCommon.h"
#include "database/fonts.h"
extern Display *grXdpy;
extern cairo_t *grCairoContext;
extern cairo_surface_t *grCairoSurface;
static GC grXcopyGC = (GC)NULL;
/* locals */
/*---------------------------------------------------------
* grtcairoDrawGrid:
* grxDrawGrid 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
grtcairoDrawGrid (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 SUBPIXEL.
*/
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 (!xsize || !ysize || GRID_TOO_SMALL(xsize, ysize))
return FALSE;
xstart = prect->r_xbot % xsize;
while (xstart < clip->r_xbot << SUBPIXELBITS) xstart += xsize;
ystart = prect->r_ybot % ysize;
while (ystart < clip->r_ybot << SUBPIXELBITS) ystart += ysize;
snum = 0;
low = clip->r_ybot;
hi = clip->r_ytop;
for (x = xstart; x < (clip->r_xtop + 1) << SUBPIXELBITS; x += xsize)
{
shifted = x >> SUBPIXELBITS;
cairo_move_to(grCairoContext, shifted, low);
cairo_line_to(grCairoContext, shifted, hi);
snum++;
}
snum = 0;
low = clip->r_xbot;
hi = clip->r_xtop;
for (y = ystart; y < (clip->r_ytop + 1) << SUBPIXELBITS; y += ysize)
{
shifted = y >> SUBPIXELBITS;
cairo_move_to(grCairoContext, low, shifted);
cairo_line_to(grCairoContext, hi, shifted);
snum++;
}
cairo_stroke(grCairoContext);
return TRUE;
}
/*---------------------------------------------------------
* grtcairoLoadFont
* This local routine loads the default ("toy API")
* font for Cairo.
*
* Results: Success/Failure
*
* Side Effects: None.
*---------------------------------------------------------
*/
bool
grtcairoLoadFont()
{
cairo_select_font_face(grCairoContext, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
return TRUE;
}
/*---------------------------------------------------------
* grtcairoSetCharSize:
* This local routine sets the character size in the display,
* if necessary.
*
* Results: None.
*
* Side Effects: None.
*---------------------------------------------------------
*/
void
grtcairoSetCharSize (size)
int size; /* Width of characters, in pixels (6 or 8). */
{
tcairoCurrent.fontSize = size;
cairo_set_font_size(grCairoContext, size * 4 + 10);
switch (size)
{
case GR_TEXT_DEFAULT:
case GR_TEXT_SMALL:
tcairoCurrent.font = grSmallFont;
break;
case GR_TEXT_MEDIUM:
tcairoCurrent.font = grMediumFont;
break;
case GR_TEXT_LARGE:
tcairoCurrent.font = grLargeFont;
break;
case GR_TEXT_XLARGE:
tcairoCurrent.font = grXLargeFont;
break;
default:
TxError("%s%d\n", "grtcairoSetCharSize: Unknown character size ",
size );
break;
}
}
/*
* ----------------------------------------------------------------------------
* GrTCairoTextSize --
*
* 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
GrTCairoTextSize(text, size, r)
char *text;
int size;
Rect *r;
{
Tk_FontMetrics overall;
Tk_Font font;
int width;
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", "GrTCairoTextSize: Unknown character size ",
size );
break;
}
if (font == NULL) return;
Tk_GetFontMetrics(font, &overall);
width = Tk_TextWidth(font, text, strlen(text));
/* Hack alert! Tk_TextWidth returns values too small! */
width = width + (width >> 4);
r->r_ytop = overall.ascent;
r->r_ybot = -overall.descent;
r->r_xtop = width;
r->r_xbot = 0;
}
/* Cairo backing store functions (now removed from the X11-based ones) */
void
grtcairoFreeBackingStore(MagWindow *window)
{
Pixmap pmap = (Pixmap)window->w_backingStore;
if (pmap == (Pixmap)NULL) return;
XFreePixmap(grXdpy, pmap);
window->w_backingStore = (ClientData)NULL;
}
void
grtcairoCreateBackingStore(MagWindow *w)
{
Pixmap pmap;
Tk_Window tkwind = (Tk_Window)w->w_grdata;
Window wind;
unsigned int width, height;
GC gc;
XGCValues gcValues;
int grDepth;
/* Deferred */
if (tkwind == NULL) return;
wind = (Window)Tk_WindowId(tkwind);
/* ignore all windows other than layout */
if (w->w_client != DBWclientID) return;
/* deferred */
if (wind == (Window)NULL) return;
width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot;
height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
if (w->w_backingStore != (ClientData)NULL) grtcairoFreeBackingStore(w);
if (grXcopyGC == (GC)NULL)
{
gcValues.graphics_exposures = FALSE;
grXcopyGC = XCreateGC(grXdpy, wind, GCGraphicsExposures, &gcValues);
}
grDepth = Tk_Depth((Tk_Window)w->w_grdata);
pmap = XCreatePixmap(grXdpy, wind, width, height, grDepth);
w->w_backingStore = (ClientData)pmap;
}
bool
grtcairoGetBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
int xbot, ybot;
Rect r;
if (w->w_backingStore == (ClientData)0) return FALSE;
GEO_EXPAND(area, 1, &r);
GeoClip(&r, &(w->w_screenArea));
width = r.r_xtop - r.r_xbot;
height = r.r_ytop - r.r_ybot;
xbot = r.r_xbot;
ybot = r.r_ybot;
Window root_return;
int x_return, y_return;
unsigned int width_return, height_return;
unsigned int border_width_return;
unsigned int depth_return;
Pixmap pmap;
pmap = (Pixmap)w->w_backingStore;
if (pmap == (Pixmap)NULL)
return FALSE;
XGetGeometry(grXdpy, pmap, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return);
cairo_surface_t *backingStoreSurface;
backingStoreSurface = cairo_xlib_surface_create(grXdpy, pmap, DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width_return, height_return);
cairo_set_source_surface(grCairoContext, backingStoreSurface, 0, 0);
cairo_rectangle(grCairoContext, xbot, ybot, width, height);
cairo_set_operator(grCairoContext, CAIRO_OPERATOR_SOURCE);
cairo_fill(grCairoContext);
return TRUE;
}
bool
grtcairoScrollBackingStore(MagWindow *w, Point *shift)
{
// (copied from grX11su3.c)
Pixmap pmap;
unsigned int width, height;
int xorigin, yorigin, xshift, yshift;
pmap = (Pixmap)w->w_backingStore;
if (pmap == (Pixmap)NULL)
{
TxPrintf("grx11ScrollBackingStore %d %d failure\n",
shift->p_x, shift->p_y);
return FALSE;
}
width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot;
height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
xorigin = 0;
yorigin = 0;
xshift = shift->p_x;
yshift = -shift->p_y;
if (xshift > 0)
width -= xshift;
else if (xshift < 0)
{
width += xshift;
xorigin = -xshift;
xshift = 0;
}
if (yshift > 0)
height -= yshift;
else if (yshift < 0)
{
height += yshift;
yorigin = -yshift;
yshift = 0;
}
/* TxPrintf("grx11ScrollBackingStore %d %d\n", shift->p_x, shift->p_y); */
cairo_surface_t *backingStoreSurface;
backingStoreSurface = cairo_xlib_surface_create(grXdpy, pmap, DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width, height);
cairo_set_source_surface(grCairoContext, backingStoreSurface, xshift, yshift);
cairo_rectangle(grCairoContext, xshift, yshift, width, height);
cairo_set_operator(grCairoContext, CAIRO_OPERATOR_SOURCE);
cairo_fill(grCairoContext);
return TRUE;
}
void
grtcairoPutBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
int ybot, xbot;
if (w->w_backingStore == (ClientData)0) return;
width = area->r_xtop - area->r_xbot;
height = area->r_ytop - area->r_ybot;
ybot = area->r_ybot;
xbot = area->r_xbot;
if (xbot < 0) {
width -= xbot;
xbot = 0;
}
if (ybot < 0) {
height -= ybot;
ybot = 0;
}
Window root_return;
int x_return, y_return;
unsigned int width_return, height_return;
unsigned int border_width_return;
unsigned int depth_return;
Pixmap pmap;
pmap = (Pixmap)w->w_backingStore;
if (pmap == (Pixmap)NULL)
return;
XGetGeometry(grXdpy, pmap, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return);
cairo_surface_t *backingStoreSurface;
backingStoreSurface = cairo_xlib_surface_create(grXdpy, pmap, DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width, height);
cairo_t *tempContext = cairo_create(backingStoreSurface);
cairo_set_source_surface(tempContext, grCairoSurface, 0.0, 0.0);
cairo_rectangle(tempContext, xbot, ybot, width, height);
cairo_set_operator(tempContext, CAIRO_OPERATOR_SOURCE);
cairo_fill(tempContext);
// cairo_surface_flush(backingStoreSurface);
// w->w_backingStore = (ClientData) cairo_image_surface_get_data(backingStoreSurface);
// cairo_surface_mark_dirty(backingStoreSurface);
}
/*
* ----------------------------------------------------------------------------
* GrTCairoReadPixel --
*
* Read one pixel from the screen.
*
* Results:
* An integer containing the pixel's color.
*
* Side effects:
* none.
*
* ----------------------------------------------------------------------------
*/
int
GrTCairoReadPixel (w, x, y)
MagWindow *w;
int x, y; /* the location of a pixel in screen coords */
{
return 0; /* (unimplemented) */
}
/*
* ----------------------------------------------------------------------------
* GrTCairoBitBlt --
*
* Copy information in bit block transfers.
*
* Results:
* None.
*
* Side effects:
* changes the screen.
* ----------------------------------------------------------------------------
*/
void
GrTCairoBitBlt(r, p)
Rect *r;
Point *p;
{
// (unimplemented)
}
#ifdef VECTOR_FONTS
/*
*----------------------------------------------------------------------
* Draw a text character
* This routine is similar to grtcairoFillPolygon()
*----------------------------------------------------------------------
*/
void
grtcairoDrawCharacter(clist, tc, pixsize)
FontChar *clist;
unsigned char tc;
int pixsize;
{
Point *tp;
int np, nptotal;
int i, j;
static int maxnp = 0;
FontChar *ccur;
if (pixsize < 5) return; /* Label too small to be useful */
//should we be using cairo_show_glyphs??
for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) {
tp = ccur->fc_points;
np = ccur->fc_numpoints;
cairo_move_to(grCairoContext, tp[0].p_x, tp[0].p_y);
for (i = 1; i < np; i++, j += 3) {
cairo_line_to(grCairoContext, tp[0].p_x, tp[0].p_y);
}
}
cairo_fill(grCairoContext);
}
/*---------------------------------------------------------
* grtcairoFontText:
*
* This routine draws text from font vectors using the
* font vector routines in DBlabel.c. Text is clipped
* to the clipping rectangle.
*
* For speed, should we be transferring the font
* vectors into cairo glyphs?
*
*---------------------------------------------------------
*/
void
grtcairoFontText(text, font, size, rotate, pos, clip, obscure)
char *text; /* The text to be drawn */
int font; /* Font to use from fontList */
int size; /* Pixel size of the font */
int rotate; /* Text rotation */
Point *pos; /* Text base position */
Rect *clip; /* Clipping area */
LinkedRect *obscure; /* List of obscuring areas */
{
char *tptr;
Point *coffset; /* vector to next character */
Rect *cbbox;
float fsize;
FontChar *clist;
int cheight, baseline;
float tmp;
cairo_save(grCairoContext);
cairo_translate(grCairoContext, pos->p_x, pos->p_y);
cairo_rotate(grCairoContext, ((double)rotate) / 360 * 2 * M_PI);
/* Get label size */
cbbox = &DBFontList[font]->mf_extents;
fsize = (uint8_t)size / (uint8_t)cbbox->r_ytop;
cairo_scale(grCairoContext, fsize, fsize);
/* Adjust to baseline */
baseline = 0;
for (tptr = text; *tptr != '\0'; tptr++)
{
DBFontChar(font, *tptr, NULL, NULL, &cbbox);
if (cbbox->r_ybot < baseline)
baseline = cbbox->r_ybot;
}
cairo_translate(grCairoContext, 0, -baseline);
for (tptr = text; *tptr != '\0'; tptr++)
{
DBFontChar(font, *tptr, &clist, &coffset, NULL);
grtcairoDrawCharacter(clist, *tptr, size);
cairo_translate(grCairoContext, coffset->p_x, coffset->p_y);
}
cairo_restore(grCairoContext);
}
#endif /* VECTOR_FONTS */
/*---------------------------------------------------------
* grtcairoPutText:
* (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
grtcairoPutText (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 grTCairoGeoSub();
int i;
float tscale;
GrTCairoTextSize(text, tcairoCurrent.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);
grTCairoGeoSub(&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))
{
cairo_rectangle(grCairoContext, overlap.r_xbot, overlap.r_ybot, overlap.r_xtop - overlap.r_xbot, overlap.r_ytop - overlap.r_ybot);
cairo_clip(grCairoContext);
cairo_move_to(grCairoContext, location.r_xbot, location.r_ybot);
cairo_show_text(grCairoContext, text);
cairo_fill(grCairoContext);
}
}
/* grTCairoGeoSub:
* return the tallest sub-rectangle of r not obscured by area
* area must be within r.
*/
void
grTCairoGeoSub(r, area)
Rect *r; /* Rectangle to be subtracted from. */
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;
}

View File

@ -0,0 +1,138 @@
/* grTCairo4.c -
*
* Copyright 2017 Open Circuit Design
*
* This file contains functions to manage the graphics tablet associated
* with the X display.
*
* Written by Chuan Chen
*/
#include <signal.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <cairo/cairo-xlib.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/magsgtty.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "windows/windows.h"
#include "graphics/graphics.h"
#include "graphics/graphicsInt.h"
#include "graphics/grTkCommon.h"
#include "textio/txcommands.h"
#include "grTCairoInt.h"
extern Display *grXdpy;
/*---------------------------------------------------------
* GrTCairoDisableTablet:
* Turns off the cursor.
*
* Results: None.
*
* Side Effects: None.
*---------------------------------------------------------
*/
void
GrTCairoDisableTablet ()
{
/* (Unimplemented) */
}
/*---------------------------------------------------------
* GrTCairoEnableTablet:
* This routine enables the graphics tablet.
*
* Results:
* None.
*
* Side Effects:
* Simply turn on the crosshair.
*---------------------------------------------------------
*/
void
GrTCairoEnableTablet ()
{
/* (Unimplemented) */
}
/*
* ----------------------------------------------------------------------------
* grtcairoGetCursorPos:
* Read the cursor position in magic coordinates.
*
* Results:
* TRUE is returned if the coordinates were succesfully read, FALSE
* otherwise.
*
* Side effects:
* The parameter is filled in with the cursor position, in the form of
* a point in screen coordinates.
* ----------------------------------------------------------------------------
*/
bool
grtcairoGetCursorPos (mw, p)
MagWindow *mw; /* window for which result is given */
Point *p; /* point to be filled in with screen coordinates */
{
int x, y, x1, y1;
unsigned int buttons;
Window win1, win2;
if (mw == (MagWindow *)NULL) mw = tcairoCurrent.mw;
XQueryPointer(grXdpy, Tk_WindowId((Tk_Window)(mw->w_grdata)),
&win1, &win2, &x1, &y1,
&x, &y, &buttons);
p->p_x = x;
p->p_y = grXtransY(mw, y);
return TRUE;
}
/*
* ----------------------------------------------------------------------------
* grtcairoGetCursorRootPos:
* Read the cursor position in sreen root coordinates.
*
* Results:
* TRUE is returned if the coordinates were succesfully read, FALSE
* otherwise.
*
* Side effects:
* The parameter is filled in with the cursor position, in the form of
* a point in screen coordinates.
* ----------------------------------------------------------------------------
*/
bool
grtcairoGetCursorRootPos (mw, p)
MagWindow *mw; /* window for which result is given */
Point *p; /* point to be filled in with screen coordinates */
{
int x, y, x1, y1;
unsigned int buttons;
Window win1, win2;
if (mw == (MagWindow *)NULL) mw = tcairoCurrent.mw;
XQueryPointer(grXdpy, Tk_WindowId((Tk_Window)(mw->w_grdata)),
&win1, &win2, &x1, &y1,
&x, &y, &buttons);
p->p_x = x1;
p->p_y = y1;
return TRUE;
}

View File

@ -0,0 +1,211 @@
/* grTCairo5.c -
*
* Copyright 2017 Open Circuit Design
*
* Manipulate the programable cursor on the graphics display.
*
* Written by Chuan Chen
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <cairo/cairo-xlib.h>
#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;
extern cairo_t *grCairoContext;
/*
* ----------------------------------------------------------------------------
* 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;
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(grCairoContext);
//glEnd();
}
mask = GrStyleTable[thisp].mask << 1;
color = GrStyleTable[thisp].color;
GrGetColor(color, &red, &green, &blue);
cairo_set_source_rgba(grCairoContext, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0));
}
x1 = bBox.r_xbot + x;
cairo_rectangle(grCairoContext, x1, y1, 1, 1);
}
}
}
if (lastp != -1) {
cairo_fill(grCairoContext);
}
} 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(grCairoContext, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0));
cairo_rectangle(grCairoContext, startx, yloc, 1, 1);
cairo_fill(grCairoContext);
}
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);
}
}
}

View File

@ -110,6 +110,7 @@ static char *grDisplayTypes[] = {
#endif
#ifdef CAIRO
"CAIRO",
"XR",
#endif
"NULL",
NULL};
@ -134,6 +135,7 @@ static bool (*(grInitProcs[]))() = {
#endif
#ifdef CAIRO
cairoSetDisplay,
cairoSetDisplay,
#endif
nullSetDisplay,
NULL};

View File

@ -47,8 +47,6 @@
uint8_t **grTCairoStipples;
HashTable grTCairoWindowTable;
cairo_surface_t *grCairoSurface;
cairo_t *grCairoContext;
XVisualInfo *grVisualInfo;
TCAIRO_CURRENT tcairoCurrent = {(Tk_Font)0, 0, 0, 0, 0,
@ -70,9 +68,11 @@ extern void GrTCairoLock(), GrTCairoUnlock(), GrTCairoIconUpdate();
extern bool GrTCairoInit();
extern bool GrTCairoEventPending(), GrTCairoCreate(), grtcairoGetCursorPos();
extern int GrTCairoWindowId();
extern char *GrTkWindowName();
extern char *GrTkWindowName(); /* Use routine from grTkCommon.c */
extern void tcairoSetProjection();
extern int grCurColor;
/*---------------------------------------------------------
* grtcairoSetWMandC:
@ -94,6 +94,7 @@ int c; /* New value for current color */
{
static int oldColor = -1;
static int oldMask = -1;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
int lr, lb, lg;
float fr, fb, fg, aval;
@ -108,9 +109,21 @@ int c; /* New value for current color */
fr = ((float)lr / 255);
fg = ((float)lg / 255);
fb = ((float)lb / 255);
aval = ((float)mask / 127.0);
cairo_set_source_rgba(grCairoContext, fr, fg, fb, aval);
if (mask == 127)
{
aval = 1.0;
}
else
{
/* "Supercolor", to counter the gray background */
fr = fr * 2 - 0.8;
fg = fg * 2 - 0.8;
fb = fb * 2 - 0.8;
aval = ((float)mask / 127.0);
}
cairo_set_source_rgba(tcairodata->context, fr, fg, fb, aval);
oldColor = c;
oldMask = mask;
@ -176,7 +189,9 @@ int numstipples; /* Number of stipples */
}
grTCairoStipples[k] = pdata;
stipplePatterns[k] = cairo_pattern_create_for_surface(cairo_image_surface_create_for_data(pdata, CAIRO_FORMAT_A1, 32, 32,
stipplePatterns[k] = cairo_pattern_create_for_surface(
cairo_image_surface_create_for_data(pdata,
CAIRO_FORMAT_A1, 32, 32,
cairo_format_stride_for_width(CAIRO_FORMAT_A1, 32)));
}
}
@ -236,7 +251,7 @@ GrTCairoInit ()
{
bool rstatus;
tcairoCurrent.window = Tk_MainWindow(magicinterp); // XDefaultRootWindow(grXdpy) ??
tcairoCurrent.window = Tk_MainWindow(magicinterp);
if (tcairoCurrent.window == NULL)
{
TxError("No Top-Level Tk window available. . . is Tk running?\n");
@ -264,13 +279,6 @@ GrTCairoInit ()
grXscrn = grVisualInfo->screen;
tcairoCurrent.depth = grVisualInfo->depth;
grCairoSurface = cairo_xlib_surface_create(grXdpy, tcairoCurrent.windowid, grVisualInfo->visual, Tk_Width(tcairoCurrent.window), Tk_Height(tcairoCurrent.window));
grCairoContext = cairo_create(grCairoSurface);
cairo_set_line_width(grCairoContext, 1.0);
cairo_set_source_rgb(grCairoContext, 0, 0, 0);
currentStipple = cairo_pattern_create_rgba(0, 0, 0, 1);
/* Use OpenGL names for colormap and dstyle file types */
grCMapType = "OpenGL";
grDStyleType = "OpenGL";
@ -328,8 +336,6 @@ GrTCairoFlush ()
*---------------------------------------------------------
*/
#define grTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n))
/*
*---------------------------------------------------------
* Set the Cairo projection matrix for a window
@ -340,12 +346,31 @@ void
tcairoSetProjection(llx, lly, width, height)
int llx, lly, width, height;
{
grCairoSurface = cairo_xlib_surface_create(grXdpy, tcairoCurrent.windowid, grVisualInfo->visual, width, height);
grCairoContext = cairo_create(grCairoSurface);
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
cairo_identity_matrix(grCairoContext);
cairo_translate(grCairoContext, 0, height);
cairo_scale(grCairoContext, 1.0, -1.0);
/* Note that offscreen-drawing comes from the Tk Image */
/* routines in tkCommon.c and does not have an associated */
/* surface and context, so we need to make them. */
if (tcairodata == NULL) {
tcairodata = (TCairoData *)mallocMagic(sizeof(TCairoData));
tcairodata->surface = cairo_xlib_surface_create(grXdpy,
tcairoCurrent.windowid, grVisualInfo->visual,
width, height);
tcairodata->context = cairo_create(tcairodata->surface);
tcairodata->backing_context = (ClientData)NULL;
tcairodata->backing_surface = (ClientData)NULL;
tcairoCurrent.mw->w_grdata2 = (ClientData)tcairodata;
cairo_set_line_width(tcairodata->context, 1.0);
/* This should be pulled from STYLE_ERASEALL, not hard-coded */
cairo_set_source_rgb(tcairodata->context, 0.8, 0.8, 0.8);
currentStipple = cairo_pattern_create_rgba(0, 0, 0, 1);
}
cairo_identity_matrix(tcairodata->context);
cairo_translate(tcairodata->context, 0, height);
cairo_scale(tcairodata->context, 1.0, -1.0);
}
@ -719,6 +744,16 @@ keys_and_buttons:
screenRect.r_ybot != mw->w_screenArea.r_ybot ||
screenRect.r_ytop != mw->w_screenArea.r_ytop);
/* Update Cairo surface */
if (need_resize)
{
TCairoData *tcairodata;
tcairodata = (TCairoData *)mw->w_grdata2;
cairo_xlib_surface_set_size(tcairodata->surface, width, height);
}
/* Redraw the window */
WindReframe(mw, &screenRect, FALSE, FALSE);
@ -881,21 +916,11 @@ char *mouseFileName;
grSetLineStylePtr = grtcairoSetLineStyle;
grSetCharSizePtr = grtcairoSetCharSize;
grFillPolygonPtr = grtcairoFillPolygon;
/*
#ifdef X11_BACKING_STORE
GrFreeBackingStorePtr = grtkFreeBackingStore;
GrCreateBackingStorePtr = grtkCreateBackingStore;
GrGetBackingStorePtr = grtkGetBackingStore;
GrPutBackingStorePtr = grtkPutBackingStore;
GrScrollBackingStorePtr = grtkScrollBackingStore;
#else
*/
GrFreeBackingStorePtr = grtcairoFreeBackingStore;
GrCreateBackingStorePtr = grtcairoCreateBackingStore;
GrGetBackingStorePtr = grtcairoGetBackingStore;
GrPutBackingStorePtr = grtcairoPutBackingStore;
GrScrollBackingStorePtr = grtcairoScrollBackingStore;
//#endif
if (execFailed) {
TxError("Execution failed!\n");
@ -1009,13 +1034,19 @@ char *name;
if (tkwind != 0)
{
bool result;
TCairoData *tcairodata;
GrTCairoFlush();
tcairoCurrent.window = tkwind;
tcairoCurrent.mw = w;
tcairodata = (TCairoData *)mallocMagic(sizeof(TCairoData));
tcairodata->backing_context = NULL;
tcairodata->backing_surface = NULL;
w->w_grdata = (ClientData) tkwind;
w->w_grdata2 = (ClientData) tcairodata;
entry = HashFind(&grTCairoWindowTable, (char *)tkwind);
HashSetValue(entry, w);
@ -1036,8 +1067,16 @@ char *name;
wind = Tk_WindowId(tkwind);
tcairoCurrent.windowid = wind;
grCairoSurface = cairo_xlib_surface_create(grXdpy, tcairoCurrent.windowid, grVisualInfo->visual, Tk_Width(tcairoCurrent.window), Tk_Height(tcairoCurrent.window));
grCairoContext = cairo_create(grCairoSurface);
tcairodata->surface = cairo_xlib_surface_create(grXdpy,
tcairoCurrent.windowid, grVisualInfo->visual,
Tk_Width(tcairoCurrent.window),
Tk_Height(tcairoCurrent.window));
tcairodata->context = cairo_create(tcairodata->surface);
cairo_set_line_width(tcairodata->context, 1.0);
/* This should be pulled from STYLE_ERASEALL, not hard-coded */
cairo_set_source_rgb(tcairodata->context, 0.8, 0.8, 0.8);
currentStipple = cairo_pattern_create_rgba(0, 0, 0, 1);
Tk_DefineCursor(tkwind, tcairoCurrent.cursor);
GrTCairoIconUpdate(w, w->w_caption);
@ -1089,11 +1128,24 @@ MagWindow *w;
{
Tk_Window xw;
HashEntry *entry;
TCairoData *tcairodata;
xw = (Tk_Window) w->w_grdata;
entry = HashLookOnly(&grTCairoWindowTable, (char *)xw);
HashSetValue(entry, NULL);
tcairodata = (TCairoData *)w->w_grdata2;
if (tcairodata->backing_surface != NULL)
cairo_destroy_surface(tcairodata->backing_surface);
if (tcairodata->backing_context != NULL)
cairo_destroy(tcairodata->backing_context);
if (tcairodata->surface != NULL)
cairo_destroy_surface(tcairodata->surface);
if (tcairodata->context != NULL)
cairo_destroy(tcairodata->context);
freeMagic(w->w_grdata2);
w->w_grdata2 = (ClientData)NULL;
Tcl_DeleteCommand(magicinterp, Tk_PathName(xw));
Tk_DestroyWindow(xw);
}
@ -1117,12 +1169,18 @@ void
GrTCairoConfigure(w)
MagWindow *w;
{
TCairoData *tcairodata;
int width, height;
if (w->w_flags & WIND_OFFSCREEN) return;
width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot;
height = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot;
Tk_MoveResizeWindow((Tk_Window)w->w_grdata,
w->w_frameArea.r_xbot, grTransYs(w->w_frameArea.r_ytop),
w->w_frameArea.r_xtop - w->w_frameArea.r_xbot,
w->w_frameArea.r_ytop - w->w_frameArea.r_ybot);
width, height);
tcairodata = (TCairoData *)w->w_grdata2;
cairo_xlib_surface_set_size(tcairodata->surface, width, height);
}
/*
@ -1247,7 +1305,6 @@ void
GrTCairoUnlock(w)
MagWindow *w;
{
/* GR_TCairo_FLUSH_BATCH(); */
GrTCairoFlush();
grSimpleUnlock(w);
}

View File

@ -29,8 +29,6 @@ char *getenv();
extern char *DBWStyleType;
extern Display *grXdpy;
extern cairo_t *grCairoContext;
extern cairo_surface_t *grCairoSurface;
extern cairo_pattern_t *currentStipple;
/*---------------------------------------------------------
@ -75,15 +73,19 @@ grtcairoDrawLines(lines, nb)
Rect lines[];
int nb;
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
int i;
cairo_save(tcairodata->context);
for (i = 0; i < nb; i++)
{
cairo_move_to(grCairoContext, lines[i].r_ll.p_x, lines[i].r_ll.p_y);
cairo_line_to(grCairoContext, lines[i].r_ur.p_x, lines[i].r_ur.p_y);
cairo_move_to(tcairodata->context, lines[i].r_ll.p_x, lines[i].r_ll.p_y);
cairo_line_to(tcairodata->context, lines[i].r_ur.p_x, lines[i].r_ur.p_y);
}
// cairo_set_source_rgba(grCairoContext, r, g, b, a);
// cairo_set_line_width(grCairoContext, width);
cairo_stroke(grCairoContext);
// cairo_set_source_rgba(tcairodata->context, r, g, b, a);
// cairo_set_line_width(tcairodata->context, width);
cairo_stroke(tcairodata->context);
cairo_restore(tcairodata->context);
}
/*---------------------------------------------------------
@ -141,17 +143,27 @@ grtcairoFillRects(rects, nb)
TCairoRect rects[];
int nb;
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
int i;
// Diagnostic
Display *disp = cairo_xlib_surface_get_display(tcairodata->surface);
Screen *screen = cairo_xlib_surface_get_screen(tcairodata->surface);
Drawable draw = cairo_xlib_surface_get_drawable(tcairodata->surface);
int w = cairo_xlib_surface_get_width(tcairodata->surface);
int h = cairo_xlib_surface_get_height(tcairodata->surface);
cairo_save(tcairodata->context);
for (i = 0; i < nb; i++)
{
cairo_rectangle(grCairoContext,
cairo_rectangle(tcairodata->context,
rects[i].r_ll.p_x, rects[i].r_ll.p_y,
rects[i].r_ur.p_x-rects[i].r_ll.p_x, rects[i].r_ur.p_y-rects[i].r_ll.p_y);
// TxPrintf("%d %d %d %d \n", rects[i].r_ll.p_x, rects[i].r_ll.p_y, rects[i].r_ur.p_x-rects[i].r_ll.p_x, rects[i].r_ur.p_y-rects[i].r_ll.p_y);
}
cairo_clip(grCairoContext);
cairo_mask(grCairoContext, currentStipple);
cairo_clip(tcairodata->context);
cairo_mask(tcairodata->context, currentStipple);
cairo_restore(tcairodata->context);
}
/*---------------------------------------------------------
@ -203,11 +215,14 @@ grtcairoFillPolygon(tp, np)
Point *tp;
int np;
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
int i;
cairo_move_to(grCairoContext, tp[0].p_x, tp[0].p_y);
cairo_save(tcairodata->context);
cairo_move_to(tcairodata->context, tp[0].p_x, tp[0].p_y);
for (i = 1; i < np; i++)
cairo_line_to(grCairoContext, tp[i].p_x, tp[i].p_y);
cairo_close_path(grCairoContext);
cairo_fill(grCairoContext);
cairo_line_to(tcairodata->context, tp[i].p_x, tp[i].p_y);
cairo_close_path(tcairodata->context);
cairo_fill(tcairodata->context);
cairo_restore(tcairodata->context);
}

View File

@ -33,8 +33,6 @@
#include "database/fonts.h"
extern Display *grXdpy;
extern cairo_t *grCairoContext;
extern cairo_surface_t *grCairoSurface;
static GC grXcopyGC = (GC)NULL;
@ -69,6 +67,7 @@ Rect *clip; /* a clipping rectangle */
int x, y;
int xstart, ystart;
int snum, low, hi, shifted;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
xsize = prect->r_xtop - prect->r_xbot;
ysize = prect->r_ytop - prect->r_ybot;
@ -86,8 +85,8 @@ Rect *clip; /* a clipping rectangle */
for (x = xstart; x < (clip->r_xtop + 1) << SUBPIXELBITS; x += xsize)
{
shifted = x >> SUBPIXELBITS;
cairo_move_to(grCairoContext, shifted, low);
cairo_line_to(grCairoContext, shifted, hi);
cairo_move_to(tcairodata->context, (double)shifted, (double)low);
cairo_line_to(tcairodata->context, (double)shifted, (double)hi);
snum++;
}
@ -97,11 +96,11 @@ Rect *clip; /* a clipping rectangle */
for (y = ystart; y < (clip->r_ytop + 1) << SUBPIXELBITS; y += ysize)
{
shifted = y >> SUBPIXELBITS;
cairo_move_to(grCairoContext, low, shifted);
cairo_line_to(grCairoContext, hi, shifted);
cairo_move_to(tcairodata->context, (double)low, (double)shifted);
cairo_line_to(tcairodata->context, (double)hi, (double)shifted);
snum++;
}
cairo_stroke(grCairoContext);
cairo_stroke(tcairodata->context);
return TRUE;
}
@ -120,7 +119,8 @@ Rect *clip; /* a clipping rectangle */
bool
grtcairoLoadFont()
{
cairo_select_font_face(grCairoContext, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
cairo_select_font_face(tcairodata->context, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
return TRUE;
}
@ -140,8 +140,9 @@ void
grtcairoSetCharSize (size)
int size; /* Width of characters, in pixels (6 or 8). */
{
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
tcairoCurrent.fontSize = size;
cairo_set_font_size(grCairoContext, size * 4 + 10);
cairo_set_font_size(tcairodata->context, size * 4 + 10);
switch (size)
{
case GR_TEXT_DEFAULT:
@ -226,16 +227,24 @@ Rect *r;
void
grtcairoFreeBackingStore(MagWindow *window)
{
TCairoData *tcairodata;
Pixmap pmap = (Pixmap)window->w_backingStore;
if (pmap == (Pixmap)NULL) return;
XFreePixmap(grXdpy, pmap);
window->w_backingStore = (ClientData)NULL;
tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
cairo_surface_destroy(tcairodata->backing_surface);
cairo_destroy(tcairodata->backing_context);
tcairodata->backing_surface = NULL;
tcairodata->backing_context = NULL;
}
void
grtcairoCreateBackingStore(MagWindow *w)
{
Pixmap pmap;
TCairoData *tcairodata;
Tk_Window tkwind = (Tk_Window)w->w_grdata;
Window wind;
unsigned int width, height;
@ -269,45 +278,52 @@ grtcairoCreateBackingStore(MagWindow *w)
pmap = XCreatePixmap(grXdpy, wind, width, height, grDepth);
w->w_backingStore = (ClientData)pmap;
tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
if (tcairodata->backing_surface != NULL)
{
cairo_surface_destroy(tcairodata->backing_surface);
cairo_destroy(tcairodata->backing_context);
}
tcairodata->backing_surface = cairo_xlib_surface_create(grXdpy, pmap,
DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width, height);
tcairodata->backing_context = cairo_create(tcairodata->backing_surface);
cairo_identity_matrix(tcairodata->backing_context);
}
bool
grtcairoGetBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
unsigned int width, height, sheight;
int xbot, ybot;
Rect r;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
if (w->w_backingStore == (ClientData)0) return FALSE;
GEO_EXPAND(area, 1, &r);
GeoClip(&r, &(w->w_screenArea));
width = r.r_xtop - r.r_xbot;
height = r.r_ytop - r.r_ybot;
xbot = r.r_xbot;
ybot = r.r_ybot;
width = r.r_xtop - xbot;
height = r.r_ytop - ybot;
sheight = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
Window root_return;
int x_return, y_return;
unsigned int width_return, height_return;
unsigned int border_width_return;
unsigned int depth_return;
// Fix Y orientation
ybot = sheight - height - ybot;
Pixmap pmap;
pmap = (Pixmap)w->w_backingStore;
if (pmap == (Pixmap)NULL)
return FALSE;
XGetGeometry(grXdpy, pmap, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return);
cairo_surface_t *backingStoreSurface;
backingStoreSurface = cairo_xlib_surface_create(grXdpy, pmap, DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width_return, height_return);
cairo_set_source_surface(grCairoContext, backingStoreSurface, 0, 0);
cairo_rectangle(grCairoContext, xbot, ybot, width, height);
cairo_set_operator(grCairoContext, CAIRO_OPERATOR_SOURCE);
cairo_fill(grCairoContext);
cairo_save(tcairodata->context);
cairo_identity_matrix(tcairodata->context);
cairo_set_source_surface(tcairodata->context, tcairodata->backing_surface,
0.0, 0.0);
cairo_rectangle(tcairodata->context, (double)xbot, (double)ybot,
(double)width, (double)height);
cairo_set_operator(tcairodata->context, CAIRO_OPERATOR_SOURCE);
cairo_fill(tcairodata->context);
cairo_restore(tcairodata->context);
return TRUE;
}
@ -316,7 +332,7 @@ grtcairoGetBackingStore(MagWindow *w, Rect *area)
bool
grtcairoScrollBackingStore(MagWindow *w, Point *shift)
{
// (copied from grX11su3.c)
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
Pixmap pmap;
unsigned int width, height;
int xorigin, yorigin, xshift, yshift;
@ -324,7 +340,7 @@ grtcairoScrollBackingStore(MagWindow *w, Point *shift)
pmap = (Pixmap)w->w_backingStore;
if (pmap == (Pixmap)NULL)
{
TxPrintf("grx11ScrollBackingStore %d %d failure\n",
TxPrintf("grtcairoScrollBackingStore %d %d failure\n",
shift->p_x, shift->p_y);
return FALSE;
}
@ -336,82 +352,73 @@ grtcairoScrollBackingStore(MagWindow *w, Point *shift)
xshift = shift->p_x;
yshift = -shift->p_y;
if (xshift > 0)
width -= xshift;
else if (xshift < 0)
{
width += xshift;
xorigin = -xshift;
xshift = 0;
}
/* Important: Cairo does not watch where memory overlaps exist */
/* when copying and will erase memory when yshift is positive. */
if (yshift > 0)
height -= yshift;
else if (yshift < 0)
{
height += yshift;
yorigin = -yshift;
yshift = 0;
/* Noting that the highlights will be redrawn anyway, use */
/* the main window surface as an intermediary to copy. */
Rect area;
cairo_save(tcairodata->context);
cairo_identity_matrix(tcairodata->context);
cairo_set_source_surface(tcairodata->context,
tcairodata->backing_surface, (double)xshift, (double)yshift);
cairo_rectangle(tcairodata->context, (double)xorigin,
(double)yorigin, (double)width, (double)height);
cairo_set_operator(tcairodata->context, CAIRO_OPERATOR_SOURCE);
cairo_fill(tcairodata->context);
cairo_restore(tcairodata->context);
area.r_xbot = 0;
area.r_xtop = width;
area.r_ybot = 0;
area.r_ytop = height;
grtcairoPutBackingStore(w, &area);
}
else
{
cairo_save(tcairodata->backing_context);
cairo_set_source_surface(tcairodata->backing_context,
tcairodata->backing_surface, (double)xshift, (double)yshift);
cairo_rectangle(tcairodata->backing_context, (double)xorigin,
(double)yorigin, (double)width, (double)height);
cairo_set_operator(tcairodata->backing_context, CAIRO_OPERATOR_SOURCE);
cairo_fill(tcairodata->backing_context);
cairo_restore(tcairodata->backing_context);
}
/* TxPrintf("grx11ScrollBackingStore %d %d\n", shift->p_x, shift->p_y); */
cairo_surface_t *backingStoreSurface;
backingStoreSurface = cairo_xlib_surface_create(grXdpy, pmap, DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width, height);
cairo_set_source_surface(grCairoContext, backingStoreSurface, xshift, yshift);
cairo_rectangle(grCairoContext, xshift, yshift, width, height);
cairo_set_operator(grCairoContext, CAIRO_OPERATOR_SOURCE);
cairo_fill(grCairoContext);
return TRUE;
}
void
grtcairoPutBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
unsigned int width, height, sheight;
int ybot, xbot;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
if (w->w_backingStore == (ClientData)0) return;
width = area->r_xtop - area->r_xbot;
height = area->r_ytop - area->r_ybot;
ybot = area->r_ybot;
xbot = area->r_xbot;
ybot = area->r_ybot;
if (xbot < 0) {
width -= xbot;
xbot = 0;
}
width = area->r_xtop - xbot;
height = area->r_ytop - ybot;
sheight = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
if (ybot < 0) {
height -= ybot;
ybot = 0;
}
// Fix Y orientation
ybot = sheight - height - ybot;
Window root_return;
int x_return, y_return;
unsigned int width_return, height_return;
unsigned int border_width_return;
unsigned int depth_return;
Pixmap pmap;
pmap = (Pixmap)w->w_backingStore;
if (pmap == (Pixmap)NULL)
return;
XGetGeometry(grXdpy, pmap, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return);
cairo_surface_t *backingStoreSurface;
backingStoreSurface = cairo_xlib_surface_create(grXdpy, pmap, DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width, height);
cairo_t *tempContext = cairo_create(backingStoreSurface);
cairo_set_source_surface(tempContext, grCairoSurface, 0.0, 0.0);
cairo_rectangle(tempContext, xbot, ybot, width, height);
cairo_set_operator(tempContext, CAIRO_OPERATOR_SOURCE);
cairo_fill(tempContext);
cairo_surface_flush(backingStoreSurface);
w->w_backingStore = (ClientData) cairo_image_surface_get_data(backingStoreSurface);
cairo_surface_mark_dirty(backingStoreSurface);
cairo_save(tcairodata->backing_context);
cairo_set_source_surface(tcairodata->backing_context, tcairodata->surface,
0.0, 0.0);
cairo_rectangle(tcairodata->backing_context, (double)xbot, (double)ybot,
(double)width, (double)height);
cairo_set_operator(tcairodata->backing_context, CAIRO_OPERATOR_SOURCE);
cairo_fill(tcairodata->backing_context);
cairo_restore(tcairodata->backing_context);
}
@ -478,9 +485,10 @@ int pixsize;
{
Point *tp;
int np, nptotal;
int i, j;
int i;
static int maxnp = 0;
FontChar *ccur;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
if (pixsize < 5) return; /* Label too small to be useful */
@ -488,12 +496,14 @@ int pixsize;
for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) {
tp = ccur->fc_points;
np = ccur->fc_numpoints;
cairo_move_to(grCairoContext, tp[0].p_x, tp[0].p_y);
for (i = 1; i < np; i++, j += 3) {
cairo_line_to(grCairoContext, tp[0].p_x, tp[0].p_y);
cairo_move_to(tcairodata->context, (double)tp[0].p_x, (double)tp[0].p_y);
for (i = 1; i < np; i++) {
cairo_line_to(tcairodata->context, (double)tp[i].p_x,
(double)tp[i].p_y);
}
cairo_close_path(tcairodata->context);
}
cairo_fill(grCairoContext);
cairo_fill(tcairodata->context);
}
/*---------------------------------------------------------
@ -526,16 +536,18 @@ LinkedRect *obscure; /* List of obscuring areas */
FontChar *clist;
int cheight, baseline;
float tmp;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
cairo_save(grCairoContext);
cairo_translate(grCairoContext, pos->p_x, pos->p_y);
cairo_rotate(grCairoContext, ((double)rotate) / 360 * 2 * M_PI);
cairo_save(tcairodata->context);
cairo_translate(tcairodata->context, (double)pos->p_x, (double)pos->p_y);
// cairo_scale(tcairodata->context, 1.0, -1.0);
cairo_rotate(tcairodata->context, ((double)rotate) / 360 * 2 * M_PI);
/* Get label size */
cbbox = &DBFontList[font]->mf_extents;
fsize = (uint8_t)size / (uint8_t)cbbox->r_ytop;
cairo_scale(grCairoContext, fsize, fsize);
fsize = (float)size / (float)cbbox->r_ytop;
cairo_scale(tcairodata->context, (double)fsize, (double)fsize);
/* Adjust to baseline */
baseline = 0;
@ -545,15 +557,16 @@ LinkedRect *obscure; /* List of obscuring areas */
if (cbbox->r_ybot < baseline)
baseline = cbbox->r_ybot;
}
cairo_translate(grCairoContext, 0, -baseline);
cairo_translate(tcairodata->context, 0.0, (double)(-baseline));
for (tptr = text; *tptr != '\0'; tptr++)
{
DBFontChar(font, *tptr, &clist, &coffset, NULL);
grtcairoDrawCharacter(clist, *tptr, size);
cairo_translate(grCairoContext, coffset->p_x, coffset->p_y);
cairo_translate(tcairodata->context, (double)coffset->p_x,
(double)coffset->p_y);
}
cairo_restore(grCairoContext);
cairo_restore(tcairodata->context);
}
#endif /* VECTOR_FONTS */
@ -593,6 +606,7 @@ LinkedRect *obscure; /* A list of obscuring rectangles */
void grTCairoGeoSub();
int i;
float tscale;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
GrTCairoTextSize(text, tcairoCurrent.fontSize, &textrect);
@ -615,14 +629,16 @@ LinkedRect *obscure; /* A list of obscuring rectangles */
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))
{
cairo_rectangle(grCairoContext, overlap.r_xbot, overlap.r_ybot, overlap.r_xtop - overlap.r_xbot, overlap.r_ytop - overlap.r_ybot);
cairo_clip(grCairoContext);
cairo_move_to(grCairoContext, location.r_xbot, location.r_ybot);
cairo_show_text(grCairoContext, text);
cairo_fill(grCairoContext);
cairo_save(tcairodata->context);
cairo_move_to(tcairodata->context, (double)location.r_xbot,
(double)location.r_ybot);
/* The cairo coordinate system is upside-down, so invert */
cairo_scale(tcairodata->context, 1.0, -1.0);
cairo_show_text(tcairodata->context, text);
cairo_fill(tcairodata->context);
cairo_restore(tcairodata->context);
}
}

View File

@ -11,6 +11,7 @@
#include <signal.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <cairo/cairo-xlib.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"

View File

@ -28,7 +28,6 @@
extern Display *grXdpy;
extern int grXscrn;
extern HashTable grTCairoWindowTable;
extern cairo_t *grCairoContext;
/*
@ -53,6 +52,7 @@ Point *p; /* screen pos of lower left corner */
Rect bBox;
bool anyObscure;
LinkedRect *ob;
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
GR_CHECK_LOCK();
@ -91,21 +91,20 @@ Point *p; /* screen pos of lower left corner */
/* Note: mask has traditionally been 0-127 */
if (thisp != lastp) {
if (lastp != -1) {
cairo_fill(grCairoContext);
//glEnd();
cairo_fill(tcairodata->context);
}
mask = GrStyleTable[thisp].mask << 1;
color = GrStyleTable[thisp].color;
GrGetColor(color, &red, &green, &blue);
cairo_set_source_rgba(grCairoContext, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0));
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(grCairoContext, x1, y1, 1, 1);
cairo_rectangle(tcairodata->context, x1, y1, 1, 1);
}
}
}
if (lastp != -1) {
cairo_fill(grCairoContext);
cairo_fill(tcairodata->context);
}
} else {
/* do pixel by pixel clipping */
@ -151,10 +150,10 @@ Point *p; /* screen pos of lower left corner */
mask = GrStyleTable[*pixelp].mask << 1;
color = GrStyleTable[*pixelp].color;
GrGetColor(color, &red, &green, &blue);
cairo_set_source_rgba(grCairoContext, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0));
cairo_set_source_rgba(tcairodata->context, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0));
cairo_rectangle(grCairoContext, startx, yloc, 1, 1);
cairo_fill(grCairoContext);
cairo_rectangle(tcairodata->context, startx, yloc, 1, 1);
cairo_fill(tcairodata->context);
}
pixelp++;
}

View File

@ -19,6 +19,9 @@
#define TCAIRO_BATCH_SIZE 10000
/* Inverted Y axis definition */
#define grTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n))
/* Current settings for X function parameters */
typedef struct {
Tk_Font font;
@ -31,17 +34,22 @@ typedef struct {
MagWindow *mw;
} TCAIRO_CURRENT;
#ifdef Cairo_SERVER_SIDE_ONLY
typedef Rect TCairoRect;
#else
/* Per-window data held in MagWindow w->w_grdata2 */
typedef struct {
/* Window surface and context */
cairo_t *context;
cairo_surface_t *surface;
/* Backing store surface and context */
cairo_t *backing_context;
cairo_surface_t *backing_surface;
} TCairoData;
/* Used for vertex arrays */
typedef struct {
Point r_ll, r_ul, r_ur, r_lr;
} TCairoRect;
#endif
extern TCAIRO_CURRENT tcairoCurrent;
extern bool grtcairoGetCursorPos();

View File

@ -1,812 +0,0 @@
/* grTOGL3.c -
*
* Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd.
*
* 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 <stdio.h>
#include <string.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glu.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/malloc.h"
#include "windows/windows.h"
#include "graphics/graphics.h"
#include "graphics/graphicsInt.h"
#include "dbwind/dbwind.h"
#include "textio/textio.h"
#include "utils/signals.h"
#include "utils/utils.h"
#include "utils/hash.h"
#include "graphics/grTOGLInt.h"
#include "graphics/grTkCommon.h"
#include "database/fonts.h"
extern Display *grXdpy;
/* locals */
GLuint grXBases[4];
/*---------------------------------------------------------
* grtoglDrawGrid:
* grxDrawGrid 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
grtoglDrawGrid (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 SUBPIXEL.
*/
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 (!xsize || !ysize || GRID_TOO_SMALL(xsize, ysize))
return FALSE;
xstart = prect->r_xbot % xsize;
while (xstart < clip->r_xbot << SUBPIXELBITS) xstart += xsize;
ystart = prect->r_ybot % ysize;
while (ystart < clip->r_ybot << SUBPIXELBITS) ystart += ysize;
grtoglSetLineStyle(outline);
glBegin(GL_LINES);
snum = 0;
low = clip->r_ybot;
hi = clip->r_ytop;
for (x = xstart; x < (clip->r_xtop+1) << SUBPIXELBITS; x += xsize)
{
shifted = x >> SUBPIXELBITS;
glVertex2i(shifted, low);
glVertex2i(shifted, hi);
snum++;
}
snum = 0;
low = clip->r_xbot;
hi = clip->r_xtop;
for (y = ystart; y < (clip->r_ytop+1) << SUBPIXELBITS; y += ysize)
{
shifted = y >> SUBPIXELBITS;
glVertex2i(low, shifted);
glVertex2i(hi, shifted);
snum++;
}
glEnd();
return TRUE;
}
/*---------------------------------------------------------
* grtoglLoadFont
* This local routine transfers the X font bitmaps
* into OpenGL display lists for simple text
* rendering.
*
* Results: Success/Failure
*
* Side Effects: None.
*---------------------------------------------------------
*/
bool
grtoglLoadFont()
{
Font id;
unsigned int i;
for (i = 0; i < 4; i++) {
id = Tk_FontId(grTkFonts[i]);
grXBases[i] = glGenLists(256);
if (grXBases[i] == 0) {
TxError("Out of display lists!\n");
return FALSE;
}
glXUseXFont(id, 0, 256, grXBases[i]);
}
return TRUE;
}
/*---------------------------------------------------------
* grtoglSetCharSize:
* This local routine sets the character size in the display,
* if necessary.
*
* Results: None.
*
* Side Effects: None.
*---------------------------------------------------------
*/
void
grtoglSetCharSize (size)
int size; /* Width of characters, in pixels (6 or 8). */
{
toglCurrent.fontSize = size;
switch (size)
{
case GR_TEXT_DEFAULT:
case GR_TEXT_SMALL:
toglCurrent.font = grSmallFont;
break;
case GR_TEXT_MEDIUM:
toglCurrent.font = grMediumFont;
break;
case GR_TEXT_LARGE:
toglCurrent.font = grLargeFont;
break;
case GR_TEXT_XLARGE:
toglCurrent.font = grXLargeFont;
break;
default:
TxError("%s%d\n", "grtoglSetCharSize: Unknown character size ",
size );
break;
}
}
/*
* ----------------------------------------------------------------------------
* GrTOGLTextSize --
*
* 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
GrTOGLTextSize(text, size, r)
char *text;
int size;
Rect *r;
{
Tk_FontMetrics overall;
Tk_Font font;
int width;
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", "GrTOGLTextSize: Unknown character size ",
size );
break;
}
if (font == NULL) return;
Tk_GetFontMetrics(font, &overall);
width = Tk_TextWidth(font, text, strlen(text));
/* Hack alert! Tk_TextWidth returns values too small! */
width = width + (width >> 4);
r->r_ytop = overall.ascent;
r->r_ybot = -overall.descent;
r->r_xtop = width;
r->r_xbot = 0;
}
/* OpenGL backing store functions (now removed from the X11-based ones) */
void
grtoglFreeBackingStore(MagWindow *window)
{
if (window->w_backingStore == (ClientData)NULL) return;
freeMagic(window->w_backingStore);
window->w_backingStore = (ClientData)NULL;
}
void
grtoglCreateBackingStore(MagWindow *w)
{
unsigned int width, height;
/* ignore all windows other than layout */
if (w->w_client != DBWclientID) return;
/* deferred */
if (w->w_grdata == NULL) return;
width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot;
height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
if (w->w_backingStore != (ClientData)NULL) freeMagic(w->w_backingStore);
w->w_backingStore = (ClientData)mallocMagic(width * height * 3);
}
bool
grtoglGetBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
int xbot, ybot;
int xoff, yoff;
Rect r;
GEO_EXPAND(area, 1, &r);
GeoClip(&r, &(w->w_screenArea));
width = r.r_xtop - r.r_xbot;
height = r.r_ytop - r.r_ybot;
xbot = r.r_xbot;
ybot = r.r_ybot;
xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot;
yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop;
glDrawBuffer(GL_FRONT);
glReadBuffer(GL_BACK);
glRasterPos2i((GLint)(xbot - xoff), (GLint)(ybot - yoff));
glCopyPixels(xbot, ybot, width, height, GL_COLOR);
return TRUE;
}
bool
grtoglxGetBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
int ybot, y;
int xoff, yoff;
int swidth, sheight, srow;
int bpos;
Rect r;
if ((GLvoid *)w->w_backingStore == NULL)
return FALSE;
// Get width and height of the backing store
sheight = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
swidth = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot;
srow = swidth * 3;
GEO_EXPAND(area, 1, &r);
GeoClip(&r, &(w->w_screenArea));
width = r.r_xtop - r.r_xbot;
height = r.r_ytop - r.r_ybot;
// ybot = grXtransY(w, r.r_ytop);
ybot = r.r_ybot;
xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot;
yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop;
bpos = ybot * srow + (3 * r.r_xbot);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glDrawBuffer(GL_FRONT);
for (y = ybot; y < ybot + height; y++)
{
// Remove next line once all math is correct. . .
if ((bpos + srow) > (srow * sheight)) break;
glRasterPos2i((GLint)(r.r_xbot - xoff), (GLint)(y - yoff));
glDrawPixels(width, 1, GL_RGB, GL_UNSIGNED_BYTE,
(const GLvoid *)(w->w_backingStore + bpos));
bpos += srow;
}
return TRUE;
}
bool
grtoglScrollBackingStore(MagWindow *w, Point *shift)
{
return TRUE;
}
bool
grtoglxScrollBackingStore(MagWindow *w, Point *shift)
{
unsigned int width, height;
int xorigin, yorigin, xshift, yshift, y, bpos, tpos, srow;
int swidth, sheight;
int memmax;
if (w->w_backingStore == (ClientData)NULL)
return FALSE;
swidth = width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot;
sheight = height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
srow = swidth * 3;
xorigin = 0;
yorigin = 0;
xshift = shift->p_x;
// yshift = -shift->p_y;
yshift = shift->p_y;
if (xshift > 0)
width -= xshift;
else if (xshift < 0)
{
width += xshift;
xorigin = -xshift;
xshift = 0;
}
if (yshift > 0)
height -= yshift;
else if (yshift < 0)
{
height += yshift;
yorigin = -yshift;
yshift = 0;
}
/* To do: shift data within the stream itself. . . */
/* Source stream position */
bpos = yorigin * srow + 3 * xorigin;
/* Target stream position */
tpos = yshift * srow + 3 * xshift;
/* It's easier to do the whole memmove as a single block. */
memmax = (width * height * 3) - ((tpos > bpos) ? tpos : bpos);
memmove((void *)(w->w_backingStore + tpos),
(void *)(w->w_backingStore + bpos),
memmax);
// for (y = yorigin; y < yorigin + height; y++)
// {
// Remove next lines once all math is correct. . .
// if ((bpos + srow) > (srow * height)) break;
// if ((tpos + srow) > (srow * height)) break;
// memmove((void *)(w->w_backingStore + tpos),
// (void *)(w->w_backingStore + bpos), width * 3);
// if (y >= height) break;
// bpos += srow;
// tpos += srow;
// }
return TRUE;
}
void
grtoglPutBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
int ybot, xbot, xoff, yoff;
width = area->r_xtop - area->r_xbot;
height = area->r_ytop - area->r_ybot;
ybot = area->r_ybot;
xbot = area->r_xbot;
xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot;
yoff = w->w_screenArea.r_ytop - w->w_allArea.r_ytop;
glDrawBuffer(GL_BACK);
glReadBuffer(GL_FRONT);
glRasterPos2i((GLint)(xbot - xoff), (GLint)(ybot - yoff));
glCopyPixels(xbot, ybot, width, height, GL_COLOR);
}
void
grtoglxPutBackingStore(MagWindow *w, Rect *area)
{
unsigned int width, height;
int y, ybot, xbot, xoff, yoff;
int swidth, sheight, srow;
int bpos;
if ((GLvoid *)w->w_backingStore == NULL) return;
if (w->w_flags & WIND_OBSCURED)
{
grtoglFreeBackingStore(w);
w->w_backingStore = (ClientData)NULL;
return;
}
// Get width and height of the backing store area
swidth = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot;
sheight = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
srow = swidth * 3;
width = area->r_xtop - area->r_xbot;
height = area->r_ytop - area->r_ybot;
// ybot = grXtransY(w, area->r_ytop);
ybot = area->r_ybot;
xbot = area->r_xbot;
xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot;
yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop;
if (GrPixelCorrect == 0)
{
height--;
width--;
xbot++;
}
// OpenGL has no concept of a 2-dimensional arrangement to the
// data returned, or boundaries, so we have to enforce them.
if (xbot < 0)
{
width += xbot;
xbot = 0;
}
if (ybot < 0)
{
height += ybot;
ybot = 0;
}
if (width > swidth) width = swidth;
bpos = (ybot - yoff) * srow + 3 * (xbot - xoff);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadBuffer(GL_FRONT);
for (y = ybot; y < ybot + height; y++)
{
// Remove next line once all math is correct. . .
if ((bpos + srow) > (srow * sheight)) break;
glReadPixels(xbot, y, width, 1,
GL_RGB, GL_UNSIGNED_BYTE,
(GLvoid *)(w->w_backingStore + bpos));
if (y >= sheight) break;
bpos += srow;
}
}
/*
* ----------------------------------------------------------------------------
* GrTOGLReadPixel --
*
* Read one pixel from the screen.
*
* Results:
* An integer containing the pixel's color.
*
* Side effects:
* none.
*
* ----------------------------------------------------------------------------
*/
int
GrTOGLReadPixel (w, x, y)
MagWindow *w;
int x,y; /* the location of a pixel in screen coords */
{
return 0; /* OpenGL has no such function, so return 0 */
}
/*
* ----------------------------------------------------------------------------
* GrTOGLBitBlt --
*
* Copy information in bit block transfers.
*
* Results:
* None.
*
* Side effects:
* changes the screen.
* ----------------------------------------------------------------------------
*/
void
GrTOGLBitBlt(r, p)
Rect *r;
Point *p;
{
glCopyPixels(r->r_xbot, r->r_ybot, r->r_xtop - r->r_xbot + 1,
r->r_ytop - r->r_ybot + 1, GL_COLOR);
}
#ifdef VECTOR_FONTS
/*
*----------------------------------------------------------------------
*
* Technically, there should be no self-intersecting polygons in outline
* fonts. However, decomposition of bezier curves into line segments
* may occasionally produce one, so it needs to be handled.
*----------------------------------------------------------------------
*/
void
myCombine(GLdouble coords[3], GLdouble *vertex_data[4],
GLfloat weight[4], GLdouble **outData, void *dataptr)
{
/* This needs to be free'd at the end of gluTessEndPolygon()! */
GLdouble *new = (GLdouble *)mallocMagic(2 * sizeof(GLdouble));
new[0] = coords[0];
new[1] = coords[1];
*outData = new;
/* Diagnostic */
TxError("Intersecting polygon in char \"%c\" at %g %g!\n",
*((char *)dataptr), coords[0], coords[1]);
}
/*
*----------------------------------------------------------------------
* Draw a text character
* This routine differs from grtoglFillPolygon() in that it uses the
* glu library to handle non-convex polygons as may appear in font
* outlines.
*----------------------------------------------------------------------
*/
void
grtoglDrawCharacter(clist, tc, pixsize)
FontChar *clist;
unsigned char tc;
int pixsize;
{
Point *tp;
int np, nptotal;
int i, j;
static GLUtesselator *tess = NULL;
static GLdouble *v = NULL;
static int maxnp = 0;
FontChar *ccur;
if (pixsize < 5) return; /* Label too small to be useful */
if (tess == NULL)
{
tess = gluNewTess();
gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin);
gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd);
gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)myCombine);
}
// Boundary-only does not look particularly good. . .
gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
nptotal = 0;
for (ccur = clist; ccur != NULL; ccur = ccur->fc_next)
nptotal += ccur->fc_numpoints;
if (nptotal > maxnp)
{
if (v != NULL) freeMagic((char *)v);
maxnp = nptotal;
v = (GLdouble *)mallocMagic(nptotal * 3 * sizeof(GLdouble));
}
j = 0;
for (ccur = clist; ccur != NULL; ccur = ccur->fc_next)
{
tp = ccur->fc_points;
np = ccur->fc_numpoints;
for (i = 0; i < np; i++, j += 3) {
v[j] = tp[i].p_x;
v[j + 1] = tp[i].p_y;
v[j + 2] = 0;
}
}
gluTessBeginPolygon(tess, (GLvoid *)(&tc));
j = 0;
for (ccur = clist; ccur != NULL; ccur = ccur->fc_next)
{
np = ccur->fc_numpoints;
gluTessBeginContour(tess);
for (i = 0; i < np; i++, j += 3) {
gluTessVertex(tess, &v[j], &v[j]);
}
gluTessEndContour(tess);
}
gluTessEndPolygon(tess);
}
/*---------------------------------------------------------
* grtoglFontText:
*
* This routine draws text from font vectors using the
* font vector routines in DBlabel.c. Text is clipped
* to the clipping rectangle.
*
* For speed, we should be transferring the font
* vectors into OpenGL display lists!
*
*---------------------------------------------------------
*/
void
grtoglFontText(text, font, size, rotate, pos, clip, obscure)
char *text; /* The text to be drawn */
int font; /* Font to use from fontList */
int size; /* Pixel size of the font */
int rotate; /* Text rotation */
Point *pos; /* Text base position */
Rect *clip; /* Clipping area */
LinkedRect *obscure; /* List of obscuring areas */
{
char *tptr;
Point *coffset; /* vector to next character */
Rect *cbbox;
GLfloat fsize, matvals[16];
FontChar *clist;
int cheight, baseline;
float tmp;
/* Keep it simple for now---ignore clip and obscure */
glDisable(GL_BLEND);
glPushMatrix();
glTranslated(pos->p_x, pos->p_y, 0);
glRotated(rotate, 0, 0, 1);
/* Get label size */
cbbox = &DBFontList[font]->mf_extents;
fsize = (GLfloat)size / (GLfloat)cbbox->r_ytop;
glScalef(fsize, fsize, 1.0);
/* Adjust to baseline */
baseline = 0;
for (tptr = text; *tptr != '\0'; tptr++)
{
DBFontChar(font, *tptr, NULL, NULL, &cbbox);
if (cbbox->r_ybot < baseline)
baseline = cbbox->r_ybot;
}
glTranslated(0, -baseline, 0);
for (tptr = text; *tptr != '\0'; tptr++)
{
DBFontChar(font, *tptr, &clist, &coffset, NULL);
grtoglDrawCharacter(clist, *tptr, size);
glTranslated(coffset->p_x, coffset->p_y, 0);
}
glPopMatrix();
}
#endif /* VECTOR_FONTS */
/*---------------------------------------------------------
* grtoglPutText:
* (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
grtoglPutText (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 grTOGLGeoSub();
int i;
float tscale;
GrTOGLTextSize(text, toglCurrent.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);
grTOGLGeoSub(&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))
{
glScissor(overlap.r_xbot, overlap.r_ybot, overlap.r_xtop - overlap.r_xbot,
overlap.r_ytop - overlap.r_ybot);
glEnable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glRasterPos2i(pos->p_x, pos->p_y);
glListBase(grXBases[(toglCurrent.fontSize == GR_TEXT_DEFAULT) ?
GR_TEXT_SMALL : toglCurrent.fontSize]);
glCallLists(strlen(text), GL_UNSIGNED_BYTE, (unsigned char *)text);
glDisable(GL_SCISSOR_TEST);
}
}
/* grTOGLGeoSub:
* return the tallest sub-rectangle of r not obscured by area
* area must be within r.
*/
void
grTOGLGeoSub(r, area)
Rect *r; /* Rectangle to be subtracted from. */
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;
}

View File

@ -1100,6 +1100,7 @@ ImgLayerConfigureInstance(instancePtr)
tmpmw.w_flags = WIND_OFFSCREEN;
tmpmw.w_grdata = (ClientData)instancePtr->pixmap;
tmpmw.w_grdata2 = (ClientData)NULL;
tmpmw.w_allArea = r;
tmpmw.w_clipAgainst = NULL;

View File

@ -287,6 +287,7 @@ WindCreate(client, frameArea, isHint, argc, argv)
w->w_stippleOrigin.p_y = 0;
w->w_bbox = NULL;
w->w_grdata = (ClientData) NULL;
w->w_grdata2 = (ClientData) NULL;
w->w_backingStore = (ClientData)NULL;
w->w_redrawAreas = (ClientData) NULL;
w->w_iconname = NULL;

View File

@ -183,8 +183,13 @@ typedef struct WIND_S1 {
* Set at window creation time.
*/
ClientData w_grdata; /* Data private to the graphics package. (G)
* Often used to contain variables needed to
* interface to SUNs window package.
* Generally references an X11 or Tk window.
*/
ClientData w_grdata2; /* Data private to the graphics packsge. (G)
* Used to contain per-window information
* other than the window itself, since
* various parts of the code have w_grdata
* hard-coded to the window pointer.
*/
ClientData w_backingStore; /* Specific data private to the graphics
* package. Used to save and restore the