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:
parent
d9fe6b1573
commit
35c3510ea7
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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,8 +189,10 @@ 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,
|
||||
cairo_format_stride_for_width(CAIRO_FORMAT_A1, 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);
|
||||
w->w_frameArea.r_xbot, grTransYs(w->w_frameArea.r_ytop),
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue