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
|
#endif
|
||||||
#ifdef CAIRO
|
#ifdef CAIRO
|
||||||
"CAIRO",
|
"CAIRO",
|
||||||
|
"XR",
|
||||||
#endif
|
#endif
|
||||||
"NULL",
|
"NULL",
|
||||||
NULL};
|
NULL};
|
||||||
|
|
@ -134,6 +135,7 @@ static bool (*(grInitProcs[]))() = {
|
||||||
#endif
|
#endif
|
||||||
#ifdef CAIRO
|
#ifdef CAIRO
|
||||||
cairoSetDisplay,
|
cairoSetDisplay,
|
||||||
|
cairoSetDisplay,
|
||||||
#endif
|
#endif
|
||||||
nullSetDisplay,
|
nullSetDisplay,
|
||||||
NULL};
|
NULL};
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,6 @@
|
||||||
|
|
||||||
uint8_t **grTCairoStipples;
|
uint8_t **grTCairoStipples;
|
||||||
HashTable grTCairoWindowTable;
|
HashTable grTCairoWindowTable;
|
||||||
cairo_surface_t *grCairoSurface;
|
|
||||||
cairo_t *grCairoContext;
|
|
||||||
XVisualInfo *grVisualInfo;
|
XVisualInfo *grVisualInfo;
|
||||||
|
|
||||||
TCAIRO_CURRENT tcairoCurrent = {(Tk_Font)0, 0, 0, 0, 0,
|
TCAIRO_CURRENT tcairoCurrent = {(Tk_Font)0, 0, 0, 0, 0,
|
||||||
|
|
@ -70,9 +68,11 @@ extern void GrTCairoLock(), GrTCairoUnlock(), GrTCairoIconUpdate();
|
||||||
extern bool GrTCairoInit();
|
extern bool GrTCairoInit();
|
||||||
extern bool GrTCairoEventPending(), GrTCairoCreate(), grtcairoGetCursorPos();
|
extern bool GrTCairoEventPending(), GrTCairoCreate(), grtcairoGetCursorPos();
|
||||||
extern int GrTCairoWindowId();
|
extern int GrTCairoWindowId();
|
||||||
extern char *GrTkWindowName();
|
extern char *GrTkWindowName(); /* Use routine from grTkCommon.c */
|
||||||
|
|
||||||
extern void tcairoSetProjection();
|
extern void tcairoSetProjection();
|
||||||
|
|
||||||
|
extern int grCurColor;
|
||||||
|
|
||||||
/*---------------------------------------------------------
|
/*---------------------------------------------------------
|
||||||
* grtcairoSetWMandC:
|
* grtcairoSetWMandC:
|
||||||
|
|
@ -94,6 +94,7 @@ int c; /* New value for current color */
|
||||||
{
|
{
|
||||||
static int oldColor = -1;
|
static int oldColor = -1;
|
||||||
static int oldMask = -1;
|
static int oldMask = -1;
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
|
|
||||||
int lr, lb, lg;
|
int lr, lb, lg;
|
||||||
float fr, fb, fg, aval;
|
float fr, fb, fg, aval;
|
||||||
|
|
@ -108,9 +109,21 @@ int c; /* New value for current color */
|
||||||
fr = ((float)lr / 255);
|
fr = ((float)lr / 255);
|
||||||
fg = ((float)lg / 255);
|
fg = ((float)lg / 255);
|
||||||
fb = ((float)lb / 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;
|
oldColor = c;
|
||||||
oldMask = mask;
|
oldMask = mask;
|
||||||
|
|
@ -176,8 +189,10 @@ int numstipples; /* Number of stipples */
|
||||||
}
|
}
|
||||||
|
|
||||||
grTCairoStipples[k] = pdata;
|
grTCairoStipples[k] = pdata;
|
||||||
stipplePatterns[k] = cairo_pattern_create_for_surface(cairo_image_surface_create_for_data(pdata, CAIRO_FORMAT_A1, 32, 32,
|
stipplePatterns[k] = cairo_pattern_create_for_surface(
|
||||||
cairo_format_stride_for_width(CAIRO_FORMAT_A1, 32)));
|
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;
|
bool rstatus;
|
||||||
|
|
||||||
tcairoCurrent.window = Tk_MainWindow(magicinterp); // XDefaultRootWindow(grXdpy) ??
|
tcairoCurrent.window = Tk_MainWindow(magicinterp);
|
||||||
if (tcairoCurrent.window == NULL)
|
if (tcairoCurrent.window == NULL)
|
||||||
{
|
{
|
||||||
TxError("No Top-Level Tk window available. . . is Tk running?\n");
|
TxError("No Top-Level Tk window available. . . is Tk running?\n");
|
||||||
|
|
@ -264,13 +279,6 @@ GrTCairoInit ()
|
||||||
grXscrn = grVisualInfo->screen;
|
grXscrn = grVisualInfo->screen;
|
||||||
tcairoCurrent.depth = grVisualInfo->depth;
|
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 */
|
/* Use OpenGL names for colormap and dstyle file types */
|
||||||
grCMapType = "OpenGL";
|
grCMapType = "OpenGL";
|
||||||
grDStyleType = "OpenGL";
|
grDStyleType = "OpenGL";
|
||||||
|
|
@ -328,8 +336,6 @@ GrTCairoFlush ()
|
||||||
*---------------------------------------------------------
|
*---------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define grTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*---------------------------------------------------------
|
*---------------------------------------------------------
|
||||||
* Set the Cairo projection matrix for a window
|
* Set the Cairo projection matrix for a window
|
||||||
|
|
@ -340,12 +346,31 @@ void
|
||||||
tcairoSetProjection(llx, lly, width, height)
|
tcairoSetProjection(llx, lly, width, height)
|
||||||
int llx, lly, width, height;
|
int llx, lly, width, height;
|
||||||
{
|
{
|
||||||
grCairoSurface = cairo_xlib_surface_create(grXdpy, tcairoCurrent.windowid, grVisualInfo->visual, width, height);
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
grCairoContext = cairo_create(grCairoSurface);
|
|
||||||
|
|
||||||
cairo_identity_matrix(grCairoContext);
|
/* Note that offscreen-drawing comes from the Tk Image */
|
||||||
cairo_translate(grCairoContext, 0, height);
|
/* routines in tkCommon.c and does not have an associated */
|
||||||
cairo_scale(grCairoContext, 1.0, -1.0);
|
/* 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_ybot != mw->w_screenArea.r_ybot ||
|
||||||
screenRect.r_ytop != mw->w_screenArea.r_ytop);
|
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 */
|
/* Redraw the window */
|
||||||
|
|
||||||
WindReframe(mw, &screenRect, FALSE, FALSE);
|
WindReframe(mw, &screenRect, FALSE, FALSE);
|
||||||
|
|
@ -881,21 +916,11 @@ char *mouseFileName;
|
||||||
grSetLineStylePtr = grtcairoSetLineStyle;
|
grSetLineStylePtr = grtcairoSetLineStyle;
|
||||||
grSetCharSizePtr = grtcairoSetCharSize;
|
grSetCharSizePtr = grtcairoSetCharSize;
|
||||||
grFillPolygonPtr = grtcairoFillPolygon;
|
grFillPolygonPtr = grtcairoFillPolygon;
|
||||||
/*
|
|
||||||
#ifdef X11_BACKING_STORE
|
|
||||||
GrFreeBackingStorePtr = grtkFreeBackingStore;
|
|
||||||
GrCreateBackingStorePtr = grtkCreateBackingStore;
|
|
||||||
GrGetBackingStorePtr = grtkGetBackingStore;
|
|
||||||
GrPutBackingStorePtr = grtkPutBackingStore;
|
|
||||||
GrScrollBackingStorePtr = grtkScrollBackingStore;
|
|
||||||
#else
|
|
||||||
*/
|
|
||||||
GrFreeBackingStorePtr = grtcairoFreeBackingStore;
|
GrFreeBackingStorePtr = grtcairoFreeBackingStore;
|
||||||
GrCreateBackingStorePtr = grtcairoCreateBackingStore;
|
GrCreateBackingStorePtr = grtcairoCreateBackingStore;
|
||||||
GrGetBackingStorePtr = grtcairoGetBackingStore;
|
GrGetBackingStorePtr = grtcairoGetBackingStore;
|
||||||
GrPutBackingStorePtr = grtcairoPutBackingStore;
|
GrPutBackingStorePtr = grtcairoPutBackingStore;
|
||||||
GrScrollBackingStorePtr = grtcairoScrollBackingStore;
|
GrScrollBackingStorePtr = grtcairoScrollBackingStore;
|
||||||
//#endif
|
|
||||||
|
|
||||||
if (execFailed) {
|
if (execFailed) {
|
||||||
TxError("Execution failed!\n");
|
TxError("Execution failed!\n");
|
||||||
|
|
@ -1009,13 +1034,19 @@ char *name;
|
||||||
if (tkwind != 0)
|
if (tkwind != 0)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
|
TCairoData *tcairodata;
|
||||||
|
|
||||||
GrTCairoFlush();
|
GrTCairoFlush();
|
||||||
|
|
||||||
tcairoCurrent.window = tkwind;
|
tcairoCurrent.window = tkwind;
|
||||||
tcairoCurrent.mw = w;
|
tcairoCurrent.mw = w;
|
||||||
|
|
||||||
|
tcairodata = (TCairoData *)mallocMagic(sizeof(TCairoData));
|
||||||
|
tcairodata->backing_context = NULL;
|
||||||
|
tcairodata->backing_surface = NULL;
|
||||||
|
|
||||||
w->w_grdata = (ClientData) tkwind;
|
w->w_grdata = (ClientData) tkwind;
|
||||||
|
w->w_grdata2 = (ClientData) tcairodata;
|
||||||
|
|
||||||
entry = HashFind(&grTCairoWindowTable, (char *)tkwind);
|
entry = HashFind(&grTCairoWindowTable, (char *)tkwind);
|
||||||
HashSetValue(entry, w);
|
HashSetValue(entry, w);
|
||||||
|
|
@ -1036,8 +1067,16 @@ char *name;
|
||||||
|
|
||||||
wind = Tk_WindowId(tkwind);
|
wind = Tk_WindowId(tkwind);
|
||||||
tcairoCurrent.windowid = wind;
|
tcairoCurrent.windowid = wind;
|
||||||
grCairoSurface = cairo_xlib_surface_create(grXdpy, tcairoCurrent.windowid, grVisualInfo->visual, Tk_Width(tcairoCurrent.window), Tk_Height(tcairoCurrent.window));
|
tcairodata->surface = cairo_xlib_surface_create(grXdpy,
|
||||||
grCairoContext = cairo_create(grCairoSurface);
|
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);
|
Tk_DefineCursor(tkwind, tcairoCurrent.cursor);
|
||||||
GrTCairoIconUpdate(w, w->w_caption);
|
GrTCairoIconUpdate(w, w->w_caption);
|
||||||
|
|
@ -1089,11 +1128,24 @@ MagWindow *w;
|
||||||
{
|
{
|
||||||
Tk_Window xw;
|
Tk_Window xw;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
|
TCairoData *tcairodata;
|
||||||
|
|
||||||
xw = (Tk_Window) w->w_grdata;
|
xw = (Tk_Window) w->w_grdata;
|
||||||
entry = HashLookOnly(&grTCairoWindowTable, (char *)xw);
|
entry = HashLookOnly(&grTCairoWindowTable, (char *)xw);
|
||||||
HashSetValue(entry, NULL);
|
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));
|
Tcl_DeleteCommand(magicinterp, Tk_PathName(xw));
|
||||||
Tk_DestroyWindow(xw);
|
Tk_DestroyWindow(xw);
|
||||||
}
|
}
|
||||||
|
|
@ -1117,12 +1169,18 @@ void
|
||||||
GrTCairoConfigure(w)
|
GrTCairoConfigure(w)
|
||||||
MagWindow *w;
|
MagWindow *w;
|
||||||
{
|
{
|
||||||
|
TCairoData *tcairodata;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
if (w->w_flags & WIND_OFFSCREEN) return;
|
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,
|
Tk_MoveResizeWindow((Tk_Window)w->w_grdata,
|
||||||
w->w_frameArea.r_xbot, grTransYs(w->w_frameArea.r_ytop),
|
w->w_frameArea.r_xbot, grTransYs(w->w_frameArea.r_ytop),
|
||||||
w->w_frameArea.r_xtop - w->w_frameArea.r_xbot,
|
width, height);
|
||||||
w->w_frameArea.r_ytop - w->w_frameArea.r_ybot);
|
tcairodata = (TCairoData *)w->w_grdata2;
|
||||||
|
cairo_xlib_surface_set_size(tcairodata->surface, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1247,7 +1305,6 @@ void
|
||||||
GrTCairoUnlock(w)
|
GrTCairoUnlock(w)
|
||||||
MagWindow *w;
|
MagWindow *w;
|
||||||
{
|
{
|
||||||
/* GR_TCairo_FLUSH_BATCH(); */
|
|
||||||
GrTCairoFlush();
|
GrTCairoFlush();
|
||||||
grSimpleUnlock(w);
|
grSimpleUnlock(w);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,6 @@ char *getenv();
|
||||||
extern char *DBWStyleType;
|
extern char *DBWStyleType;
|
||||||
extern Display *grXdpy;
|
extern Display *grXdpy;
|
||||||
|
|
||||||
extern cairo_t *grCairoContext;
|
|
||||||
extern cairo_surface_t *grCairoSurface;
|
|
||||||
extern cairo_pattern_t *currentStipple;
|
extern cairo_pattern_t *currentStipple;
|
||||||
|
|
||||||
/*---------------------------------------------------------
|
/*---------------------------------------------------------
|
||||||
|
|
@ -75,15 +73,19 @@ grtcairoDrawLines(lines, nb)
|
||||||
Rect lines[];
|
Rect lines[];
|
||||||
int nb;
|
int nb;
|
||||||
{
|
{
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
cairo_save(tcairodata->context);
|
||||||
for (i = 0; i < nb; i++)
|
for (i = 0; i < nb; i++)
|
||||||
{
|
{
|
||||||
cairo_move_to(grCairoContext, lines[i].r_ll.p_x, lines[i].r_ll.p_y);
|
cairo_move_to(tcairodata->context, 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_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_source_rgba(tcairodata->context, r, g, b, a);
|
||||||
// cairo_set_line_width(grCairoContext, width);
|
// cairo_set_line_width(tcairodata->context, width);
|
||||||
cairo_stroke(grCairoContext);
|
cairo_stroke(tcairodata->context);
|
||||||
|
cairo_restore(tcairodata->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------
|
/*---------------------------------------------------------
|
||||||
|
|
@ -141,17 +143,27 @@ grtcairoFillRects(rects, nb)
|
||||||
TCairoRect rects[];
|
TCairoRect rects[];
|
||||||
int nb;
|
int nb;
|
||||||
{
|
{
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
int i;
|
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++)
|
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_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);
|
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);
|
// 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_clip(tcairodata->context);
|
||||||
cairo_mask(grCairoContext, currentStipple);
|
cairo_mask(tcairodata->context, currentStipple);
|
||||||
|
cairo_restore(tcairodata->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------
|
/*---------------------------------------------------------
|
||||||
|
|
@ -203,11 +215,14 @@ grtcairoFillPolygon(tp, np)
|
||||||
Point *tp;
|
Point *tp;
|
||||||
int np;
|
int np;
|
||||||
{
|
{
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
int i;
|
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++)
|
for (i = 1; i < np; i++)
|
||||||
cairo_line_to(grCairoContext, tp[i].p_x, tp[i].p_y);
|
cairo_line_to(tcairodata->context, tp[i].p_x, tp[i].p_y);
|
||||||
cairo_close_path(grCairoContext);
|
cairo_close_path(tcairodata->context);
|
||||||
cairo_fill(grCairoContext);
|
cairo_fill(tcairodata->context);
|
||||||
|
cairo_restore(tcairodata->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,6 @@
|
||||||
#include "database/fonts.h"
|
#include "database/fonts.h"
|
||||||
|
|
||||||
extern Display *grXdpy;
|
extern Display *grXdpy;
|
||||||
extern cairo_t *grCairoContext;
|
|
||||||
extern cairo_surface_t *grCairoSurface;
|
|
||||||
|
|
||||||
static GC grXcopyGC = (GC)NULL;
|
static GC grXcopyGC = (GC)NULL;
|
||||||
|
|
||||||
|
|
@ -69,6 +67,7 @@ Rect *clip; /* a clipping rectangle */
|
||||||
int x, y;
|
int x, y;
|
||||||
int xstart, ystart;
|
int xstart, ystart;
|
||||||
int snum, low, hi, shifted;
|
int snum, low, hi, shifted;
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
|
|
||||||
xsize = prect->r_xtop - prect->r_xbot;
|
xsize = prect->r_xtop - prect->r_xbot;
|
||||||
ysize = prect->r_ytop - prect->r_ybot;
|
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)
|
for (x = xstart; x < (clip->r_xtop + 1) << SUBPIXELBITS; x += xsize)
|
||||||
{
|
{
|
||||||
shifted = x >> SUBPIXELBITS;
|
shifted = x >> SUBPIXELBITS;
|
||||||
cairo_move_to(grCairoContext, shifted, low);
|
cairo_move_to(tcairodata->context, (double)shifted, (double)low);
|
||||||
cairo_line_to(grCairoContext, shifted, hi);
|
cairo_line_to(tcairodata->context, (double)shifted, (double)hi);
|
||||||
snum++;
|
snum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,11 +96,11 @@ Rect *clip; /* a clipping rectangle */
|
||||||
for (y = ystart; y < (clip->r_ytop + 1) << SUBPIXELBITS; y += ysize)
|
for (y = ystart; y < (clip->r_ytop + 1) << SUBPIXELBITS; y += ysize)
|
||||||
{
|
{
|
||||||
shifted = y >> SUBPIXELBITS;
|
shifted = y >> SUBPIXELBITS;
|
||||||
cairo_move_to(grCairoContext, low, shifted);
|
cairo_move_to(tcairodata->context, (double)low, (double)shifted);
|
||||||
cairo_line_to(grCairoContext, hi, shifted);
|
cairo_line_to(tcairodata->context, (double)hi, (double)shifted);
|
||||||
snum++;
|
snum++;
|
||||||
}
|
}
|
||||||
cairo_stroke(grCairoContext);
|
cairo_stroke(tcairodata->context);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,7 +119,8 @@ Rect *clip; /* a clipping rectangle */
|
||||||
bool
|
bool
|
||||||
grtcairoLoadFont()
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,8 +140,9 @@ void
|
||||||
grtcairoSetCharSize (size)
|
grtcairoSetCharSize (size)
|
||||||
int size; /* Width of characters, in pixels (6 or 8). */
|
int size; /* Width of characters, in pixels (6 or 8). */
|
||||||
{
|
{
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
tcairoCurrent.fontSize = size;
|
tcairoCurrent.fontSize = size;
|
||||||
cairo_set_font_size(grCairoContext, size * 4 + 10);
|
cairo_set_font_size(tcairodata->context, size * 4 + 10);
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
case GR_TEXT_DEFAULT:
|
case GR_TEXT_DEFAULT:
|
||||||
|
|
@ -226,16 +227,24 @@ Rect *r;
|
||||||
void
|
void
|
||||||
grtcairoFreeBackingStore(MagWindow *window)
|
grtcairoFreeBackingStore(MagWindow *window)
|
||||||
{
|
{
|
||||||
|
TCairoData *tcairodata;
|
||||||
Pixmap pmap = (Pixmap)window->w_backingStore;
|
Pixmap pmap = (Pixmap)window->w_backingStore;
|
||||||
if (pmap == (Pixmap)NULL) return;
|
if (pmap == (Pixmap)NULL) return;
|
||||||
XFreePixmap(grXdpy, pmap);
|
XFreePixmap(grXdpy, pmap);
|
||||||
window->w_backingStore = (ClientData)NULL;
|
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
|
void
|
||||||
grtcairoCreateBackingStore(MagWindow *w)
|
grtcairoCreateBackingStore(MagWindow *w)
|
||||||
{
|
{
|
||||||
Pixmap pmap;
|
Pixmap pmap;
|
||||||
|
TCairoData *tcairodata;
|
||||||
Tk_Window tkwind = (Tk_Window)w->w_grdata;
|
Tk_Window tkwind = (Tk_Window)w->w_grdata;
|
||||||
Window wind;
|
Window wind;
|
||||||
unsigned int width, height;
|
unsigned int width, height;
|
||||||
|
|
@ -269,45 +278,52 @@ grtcairoCreateBackingStore(MagWindow *w)
|
||||||
|
|
||||||
pmap = XCreatePixmap(grXdpy, wind, width, height, grDepth);
|
pmap = XCreatePixmap(grXdpy, wind, width, height, grDepth);
|
||||||
w->w_backingStore = (ClientData)pmap;
|
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
|
bool
|
||||||
grtcairoGetBackingStore(MagWindow *w, Rect *area)
|
grtcairoGetBackingStore(MagWindow *w, Rect *area)
|
||||||
{
|
{
|
||||||
unsigned int width, height;
|
unsigned int width, height, sheight;
|
||||||
int xbot, ybot;
|
int xbot, ybot;
|
||||||
Rect r;
|
Rect r;
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
|
|
||||||
if (w->w_backingStore == (ClientData)0) return FALSE;
|
if (w->w_backingStore == (ClientData)0) return FALSE;
|
||||||
|
|
||||||
GEO_EXPAND(area, 1, &r);
|
GEO_EXPAND(area, 1, &r);
|
||||||
GeoClip(&r, &(w->w_screenArea));
|
GeoClip(&r, &(w->w_screenArea));
|
||||||
|
|
||||||
width = r.r_xtop - r.r_xbot;
|
|
||||||
height = r.r_ytop - r.r_ybot;
|
|
||||||
|
|
||||||
xbot = r.r_xbot;
|
xbot = r.r_xbot;
|
||||||
ybot = r.r_ybot;
|
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;
|
// Fix Y orientation
|
||||||
int x_return, y_return;
|
ybot = sheight - height - ybot;
|
||||||
unsigned int width_return, height_return;
|
|
||||||
unsigned int border_width_return;
|
|
||||||
unsigned int depth_return;
|
|
||||||
|
|
||||||
Pixmap pmap;
|
cairo_save(tcairodata->context);
|
||||||
pmap = (Pixmap)w->w_backingStore;
|
cairo_identity_matrix(tcairodata->context);
|
||||||
if (pmap == (Pixmap)NULL)
|
cairo_set_source_surface(tcairodata->context, tcairodata->backing_surface,
|
||||||
return FALSE;
|
0.0, 0.0);
|
||||||
|
cairo_rectangle(tcairodata->context, (double)xbot, (double)ybot,
|
||||||
XGetGeometry(grXdpy, pmap, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return);
|
(double)width, (double)height);
|
||||||
|
cairo_set_operator(tcairodata->context, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_surface_t *backingStoreSurface;
|
cairo_fill(tcairodata->context);
|
||||||
backingStoreSurface = cairo_xlib_surface_create(grXdpy, pmap, DefaultVisual(grXdpy, DefaultScreen(grXdpy)), width_return, height_return);
|
cairo_restore(tcairodata->context);
|
||||||
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +332,7 @@ grtcairoGetBackingStore(MagWindow *w, Rect *area)
|
||||||
bool
|
bool
|
||||||
grtcairoScrollBackingStore(MagWindow *w, Point *shift)
|
grtcairoScrollBackingStore(MagWindow *w, Point *shift)
|
||||||
{
|
{
|
||||||
// (copied from grX11su3.c)
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
Pixmap pmap;
|
Pixmap pmap;
|
||||||
unsigned int width, height;
|
unsigned int width, height;
|
||||||
int xorigin, yorigin, xshift, yshift;
|
int xorigin, yorigin, xshift, yshift;
|
||||||
|
|
@ -324,7 +340,7 @@ grtcairoScrollBackingStore(MagWindow *w, Point *shift)
|
||||||
pmap = (Pixmap)w->w_backingStore;
|
pmap = (Pixmap)w->w_backingStore;
|
||||||
if (pmap == (Pixmap)NULL)
|
if (pmap == (Pixmap)NULL)
|
||||||
{
|
{
|
||||||
TxPrintf("grx11ScrollBackingStore %d %d failure\n",
|
TxPrintf("grtcairoScrollBackingStore %d %d failure\n",
|
||||||
shift->p_x, shift->p_y);
|
shift->p_x, shift->p_y);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -336,82 +352,73 @@ grtcairoScrollBackingStore(MagWindow *w, Point *shift)
|
||||||
xshift = shift->p_x;
|
xshift = shift->p_x;
|
||||||
yshift = -shift->p_y;
|
yshift = -shift->p_y;
|
||||||
|
|
||||||
if (xshift > 0)
|
/* Important: Cairo does not watch where memory overlaps exist */
|
||||||
width -= xshift;
|
/* when copying and will erase memory when yshift is positive. */
|
||||||
else if (xshift < 0)
|
|
||||||
{
|
|
||||||
width += xshift;
|
|
||||||
xorigin = -xshift;
|
|
||||||
xshift = 0;
|
|
||||||
}
|
|
||||||
if (yshift > 0)
|
if (yshift > 0)
|
||||||
height -= yshift;
|
|
||||||
else if (yshift < 0)
|
|
||||||
{
|
{
|
||||||
height += yshift;
|
/* Noting that the highlights will be redrawn anyway, use */
|
||||||
yorigin = -yshift;
|
/* the main window surface as an intermediary to copy. */
|
||||||
yshift = 0;
|
|
||||||
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grtcairoPutBackingStore(MagWindow *w, Rect *area)
|
grtcairoPutBackingStore(MagWindow *w, Rect *area)
|
||||||
{
|
{
|
||||||
unsigned int width, height;
|
unsigned int width, height, sheight;
|
||||||
int ybot, xbot;
|
int ybot, xbot;
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
|
|
||||||
if (w->w_backingStore == (ClientData)0) return;
|
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;
|
xbot = area->r_xbot;
|
||||||
|
ybot = area->r_ybot;
|
||||||
|
|
||||||
if (xbot < 0) {
|
width = area->r_xtop - xbot;
|
||||||
width -= xbot;
|
height = area->r_ytop - ybot;
|
||||||
xbot = 0;
|
sheight = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot;
|
||||||
}
|
|
||||||
|
|
||||||
if (ybot < 0) {
|
// Fix Y orientation
|
||||||
height -= ybot;
|
ybot = sheight - height - ybot;
|
||||||
ybot = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Window root_return;
|
cairo_save(tcairodata->backing_context);
|
||||||
int x_return, y_return;
|
cairo_set_source_surface(tcairodata->backing_context, tcairodata->surface,
|
||||||
unsigned int width_return, height_return;
|
0.0, 0.0);
|
||||||
unsigned int border_width_return;
|
cairo_rectangle(tcairodata->backing_context, (double)xbot, (double)ybot,
|
||||||
unsigned int depth_return;
|
(double)width, (double)height);
|
||||||
Pixmap pmap;
|
cairo_set_operator(tcairodata->backing_context, CAIRO_OPERATOR_SOURCE);
|
||||||
|
cairo_fill(tcairodata->backing_context);
|
||||||
pmap = (Pixmap)w->w_backingStore;
|
cairo_restore(tcairodata->backing_context);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -478,9 +485,10 @@ int pixsize;
|
||||||
{
|
{
|
||||||
Point *tp;
|
Point *tp;
|
||||||
int np, nptotal;
|
int np, nptotal;
|
||||||
int i, j;
|
int i;
|
||||||
static int maxnp = 0;
|
static int maxnp = 0;
|
||||||
FontChar *ccur;
|
FontChar *ccur;
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
|
|
||||||
if (pixsize < 5) return; /* Label too small to be useful */
|
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) {
|
for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) {
|
||||||
tp = ccur->fc_points;
|
tp = ccur->fc_points;
|
||||||
np = ccur->fc_numpoints;
|
np = ccur->fc_numpoints;
|
||||||
cairo_move_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++, j += 3) {
|
for (i = 1; i < np; i++) {
|
||||||
cairo_line_to(grCairoContext, tp[0].p_x, tp[0].p_y);
|
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;
|
FontChar *clist;
|
||||||
int cheight, baseline;
|
int cheight, baseline;
|
||||||
float tmp;
|
float tmp;
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
|
|
||||||
cairo_save(grCairoContext);
|
cairo_save(tcairodata->context);
|
||||||
cairo_translate(grCairoContext, pos->p_x, pos->p_y);
|
cairo_translate(tcairodata->context, (double)pos->p_x, (double)pos->p_y);
|
||||||
cairo_rotate(grCairoContext, ((double)rotate) / 360 * 2 * M_PI);
|
// cairo_scale(tcairodata->context, 1.0, -1.0);
|
||||||
|
cairo_rotate(tcairodata->context, ((double)rotate) / 360 * 2 * M_PI);
|
||||||
|
|
||||||
/* Get label size */
|
/* Get label size */
|
||||||
cbbox = &DBFontList[font]->mf_extents;
|
cbbox = &DBFontList[font]->mf_extents;
|
||||||
|
|
||||||
fsize = (uint8_t)size / (uint8_t)cbbox->r_ytop;
|
fsize = (float)size / (float)cbbox->r_ytop;
|
||||||
cairo_scale(grCairoContext, fsize, fsize);
|
cairo_scale(tcairodata->context, (double)fsize, (double)fsize);
|
||||||
|
|
||||||
/* Adjust to baseline */
|
/* Adjust to baseline */
|
||||||
baseline = 0;
|
baseline = 0;
|
||||||
|
|
@ -545,15 +557,16 @@ LinkedRect *obscure; /* List of obscuring areas */
|
||||||
if (cbbox->r_ybot < baseline)
|
if (cbbox->r_ybot < baseline)
|
||||||
baseline = cbbox->r_ybot;
|
baseline = cbbox->r_ybot;
|
||||||
}
|
}
|
||||||
cairo_translate(grCairoContext, 0, -baseline);
|
cairo_translate(tcairodata->context, 0.0, (double)(-baseline));
|
||||||
|
|
||||||
for (tptr = text; *tptr != '\0'; tptr++)
|
for (tptr = text; *tptr != '\0'; tptr++)
|
||||||
{
|
{
|
||||||
DBFontChar(font, *tptr, &clist, &coffset, NULL);
|
DBFontChar(font, *tptr, &clist, &coffset, NULL);
|
||||||
grtcairoDrawCharacter(clist, *tptr, size);
|
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 */
|
#endif /* VECTOR_FONTS */
|
||||||
|
|
@ -593,6 +606,7 @@ LinkedRect *obscure; /* A list of obscuring rectangles */
|
||||||
void grTCairoGeoSub();
|
void grTCairoGeoSub();
|
||||||
int i;
|
int i;
|
||||||
float tscale;
|
float tscale;
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
|
|
||||||
GrTCairoTextSize(text, tcairoCurrent.fontSize, &textrect);
|
GrTCairoTextSize(text, tcairoCurrent.fontSize, &textrect);
|
||||||
|
|
||||||
|
|
@ -615,14 +629,16 @@ LinkedRect *obscure; /* A list of obscuring rectangles */
|
||||||
overlap = location;
|
overlap = location;
|
||||||
GeoClip(&overlap, clip);
|
GeoClip(&overlap, clip);
|
||||||
|
|
||||||
/* copy the text to the color screen */
|
|
||||||
if ((overlap.r_xbot < overlap.r_xtop) && (overlap.r_ybot <= overlap.r_ytop))
|
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_save(tcairodata->context);
|
||||||
cairo_clip(grCairoContext);
|
cairo_move_to(tcairodata->context, (double)location.r_xbot,
|
||||||
cairo_move_to(grCairoContext, location.r_xbot, location.r_ybot);
|
(double)location.r_ybot);
|
||||||
cairo_show_text(grCairoContext, text);
|
/* The cairo coordinate system is upside-down, so invert */
|
||||||
cairo_fill(grCairoContext);
|
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 <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <cairo/cairo-xlib.h>
|
||||||
|
|
||||||
#include "tcltk/tclmagic.h"
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
extern Display *grXdpy;
|
extern Display *grXdpy;
|
||||||
extern int grXscrn;
|
extern int grXscrn;
|
||||||
extern HashTable grTCairoWindowTable;
|
extern HashTable grTCairoWindowTable;
|
||||||
extern cairo_t *grCairoContext;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -53,6 +52,7 @@ Point *p; /* screen pos of lower left corner */
|
||||||
Rect bBox;
|
Rect bBox;
|
||||||
bool anyObscure;
|
bool anyObscure;
|
||||||
LinkedRect *ob;
|
LinkedRect *ob;
|
||||||
|
TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
|
||||||
|
|
||||||
GR_CHECK_LOCK();
|
GR_CHECK_LOCK();
|
||||||
|
|
||||||
|
|
@ -91,21 +91,20 @@ Point *p; /* screen pos of lower left corner */
|
||||||
/* Note: mask has traditionally been 0-127 */
|
/* Note: mask has traditionally been 0-127 */
|
||||||
if (thisp != lastp) {
|
if (thisp != lastp) {
|
||||||
if (lastp != -1) {
|
if (lastp != -1) {
|
||||||
cairo_fill(grCairoContext);
|
cairo_fill(tcairodata->context);
|
||||||
//glEnd();
|
|
||||||
}
|
}
|
||||||
mask = GrStyleTable[thisp].mask << 1;
|
mask = GrStyleTable[thisp].mask << 1;
|
||||||
color = GrStyleTable[thisp].color;
|
color = GrStyleTable[thisp].color;
|
||||||
GrGetColor(color, &red, &green, &blue);
|
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;
|
x1 = bBox.r_xbot + x;
|
||||||
cairo_rectangle(grCairoContext, x1, y1, 1, 1);
|
cairo_rectangle(tcairodata->context, x1, y1, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lastp != -1) {
|
if (lastp != -1) {
|
||||||
cairo_fill(grCairoContext);
|
cairo_fill(tcairodata->context);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* do pixel by pixel clipping */
|
/* do pixel by pixel clipping */
|
||||||
|
|
@ -151,10 +150,10 @@ Point *p; /* screen pos of lower left corner */
|
||||||
mask = GrStyleTable[*pixelp].mask << 1;
|
mask = GrStyleTable[*pixelp].mask << 1;
|
||||||
color = GrStyleTable[*pixelp].color;
|
color = GrStyleTable[*pixelp].color;
|
||||||
GrGetColor(color, &red, &green, &blue);
|
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_rectangle(tcairodata->context, startx, yloc, 1, 1);
|
||||||
cairo_fill(grCairoContext);
|
cairo_fill(tcairodata->context);
|
||||||
}
|
}
|
||||||
pixelp++;
|
pixelp++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
#define TCAIRO_BATCH_SIZE 10000
|
#define TCAIRO_BATCH_SIZE 10000
|
||||||
|
|
||||||
|
/* Inverted Y axis definition */
|
||||||
|
#define grTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n))
|
||||||
|
|
||||||
/* Current settings for X function parameters */
|
/* Current settings for X function parameters */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Tk_Font font;
|
Tk_Font font;
|
||||||
|
|
@ -31,17 +34,22 @@ typedef struct {
|
||||||
MagWindow *mw;
|
MagWindow *mw;
|
||||||
} TCAIRO_CURRENT;
|
} TCAIRO_CURRENT;
|
||||||
|
|
||||||
#ifdef Cairo_SERVER_SIDE_ONLY
|
/* Per-window data held in MagWindow w->w_grdata2 */
|
||||||
typedef Rect TCairoRect;
|
|
||||||
#else
|
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 */
|
/* Used for vertex arrays */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Point r_ll, r_ul, r_ur, r_lr;
|
Point r_ll, r_ul, r_ur, r_lr;
|
||||||
} TCairoRect;
|
} TCairoRect;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern TCAIRO_CURRENT tcairoCurrent;
|
extern TCAIRO_CURRENT tcairoCurrent;
|
||||||
|
|
||||||
extern bool grtcairoGetCursorPos();
|
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_flags = WIND_OFFSCREEN;
|
||||||
tmpmw.w_grdata = (ClientData)instancePtr->pixmap;
|
tmpmw.w_grdata = (ClientData)instancePtr->pixmap;
|
||||||
|
tmpmw.w_grdata2 = (ClientData)NULL;
|
||||||
tmpmw.w_allArea = r;
|
tmpmw.w_allArea = r;
|
||||||
tmpmw.w_clipAgainst = NULL;
|
tmpmw.w_clipAgainst = NULL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,7 @@ WindCreate(client, frameArea, isHint, argc, argv)
|
||||||
w->w_stippleOrigin.p_y = 0;
|
w->w_stippleOrigin.p_y = 0;
|
||||||
w->w_bbox = NULL;
|
w->w_bbox = NULL;
|
||||||
w->w_grdata = (ClientData) NULL;
|
w->w_grdata = (ClientData) NULL;
|
||||||
|
w->w_grdata2 = (ClientData) NULL;
|
||||||
w->w_backingStore = (ClientData)NULL;
|
w->w_backingStore = (ClientData)NULL;
|
||||||
w->w_redrawAreas = (ClientData) NULL;
|
w->w_redrawAreas = (ClientData) NULL;
|
||||||
w->w_iconname = NULL;
|
w->w_iconname = NULL;
|
||||||
|
|
|
||||||
|
|
@ -183,8 +183,13 @@ typedef struct WIND_S1 {
|
||||||
* Set at window creation time.
|
* Set at window creation time.
|
||||||
*/
|
*/
|
||||||
ClientData w_grdata; /* Data private to the graphics package. (G)
|
ClientData w_grdata; /* Data private to the graphics package. (G)
|
||||||
* Often used to contain variables needed to
|
* Generally references an X11 or Tk window.
|
||||||
* interface to SUNs window package.
|
*/
|
||||||
|
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
|
ClientData w_backingStore; /* Specific data private to the graphics
|
||||||
* package. Used to save and restore the
|
* package. Used to save and restore the
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue