1 /* grTCairo5.c -
2 *
3 * Copyright 2017 Open Circuit Design
4 *
5 * Manipulate the programable cursor on the graphics display.
6 *
7 * Written by Chuan Chen
8 */
9
10 #include <stdio.h>
11 #include <X11/Xlib.h>
12
13 #include <cairo/cairo-xlib.h>
14
15 #include "tcltk/tclmagic.h"
16 #include "utils/magic.h"
17 #include "utils/styles.h"
18 #include "utils/hash.h"
19 #include "textio/textio.h"
20 #include "utils/geometry.h"
21 #include "graphics/glyphs.h"
22 #include "windows/windows.h"
23 #include "graphics/graphics.h"
24 #include "graphics/graphicsInt.h"
25 #include "grTkCommon.h"
26 #include "grTCairoInt.h"
27
28 extern Display *grXdpy;
29 extern int grXscrn;
30 extern HashTable grTCairoWindowTable;
31
32
33 /*
34 * ----------------------------------------------------------------------------
35 * GrTCairoDrawGlyph --
36 *
37 * Draw one glyph on the display.
38 *
39 * Results:
40 * None.
41 *
42 * Side effects:
43 * Draws pixels.
44 * ----------------------------------------------------------------------------
45 */
46
47 void
GrTCairoDrawGlyph(gl,p)48 GrTCairoDrawGlyph (gl, p)
49 GrGlyph *gl; /* A single glyph */
50 Point *p; /* screen pos of lower left corner */
51 {
52 Rect bBox;
53 bool anyObscure;
54 LinkedRect *ob;
55 TCairoData *tcairodata = (TCairoData *)tcairoCurrent.mw->w_grdata2;
56
57 GR_CHECK_LOCK();
58
59 /* We're going to change the graphics state without affecting */
60 /* the standard color and mask saved values, so we had better */
61 /* flush all rects & lines first. */
62 GR_TCAIRO_FLUSH_BATCH();
63
64 bBox.r_ll = *p;
65 bBox.r_xtop = p->p_x + gl->gr_xsize - 1;
66 bBox.r_ytop = p->p_y + gl->gr_ysize - 1;
67
68 anyObscure = FALSE;
69 for (ob = grCurObscure; ob != NULL; ob = ob->r_next) {
70 if (GEO_TOUCH( &(ob->r_r), &bBox)) {
71 anyObscure = TRUE;
72 break;
73 }
74 }
75 if ((!anyObscure) && (GEO_SURROUND(&grCurClip, &bBox)) ) {
76 int *pixelp, x, y, thisp, lastp;
77 int color, red, green, blue, mask;
78
79 /* no clipping, try to go quickly */
80 pixelp = gl->gr_pixels;
81 thisp = -1;
82 for (y = 0; y < gl->gr_ysize; y++) {
83 int x1, y1;
84
85 y1 = bBox.r_ybot + y;
86 for (x = 0; x < gl->gr_xsize; x++) {
87 lastp = thisp;
88 thisp = *pixelp++;
89 if (thisp != 0)
90 {
91 /* Note: mask has traditionally been 0-127 */
92 if (thisp != lastp) {
93 if (lastp != -1) {
94 cairo_fill(tcairodata->context);
95 }
96 mask = GrStyleTable[thisp].mask << 1;
97 color = GrStyleTable[thisp].color;
98 GrGetColor(color, &red, &green, &blue);
99 cairo_set_source_rgba(tcairodata->context, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0));
100 }
101 x1 = bBox.r_xbot + x;
102 cairo_rectangle(tcairodata->context, x1, y1, 1, 1);
103 }
104 }
105 }
106 if (lastp != -1) {
107 cairo_fill(tcairodata->context);
108 }
109 } else {
110 /* do pixel by pixel clipping */
111 int y, yloc;
112
113 yloc = bBox.r_ybot;
114 for (y = 0; y < gl->gr_ysize; y++) {
115 int startx, endx;
116 if ( (yloc <= grCurClip.r_ytop) && (yloc >= grCurClip.r_ybot) ) {
117 int laststartx;
118 laststartx = bBox.r_xbot - 1;
119 for (startx = bBox.r_xbot; startx <= bBox.r_xtop;
120 startx = endx + 1) {
121 int *pixelp;
122
123 startx = MAX(startx, grCurClip.r_xbot);
124 endx = MIN(bBox.r_xtop, grCurClip.r_xtop);
125
126 if (anyObscure) {
127 for (ob = grCurObscure; ob != NULL; ob = ob->r_next) {
128 if ( (ob->r_r.r_ybot <= yloc) &&
129 (ob->r_r.r_ytop >= yloc) ) {
130 if (ob->r_r.r_xbot <= startx)
131 startx = MAX(startx, ob->r_r.r_xtop + 1);
132 else if (ob->r_r.r_xbot <= endx)
133 endx = MIN(endx, ob->r_r.r_xbot - 1);
134 }
135 }
136 }
137
138 /* stop if we aren't advancing */
139 if (startx == laststartx) break;
140 laststartx = startx;
141 if (startx > endx) continue;
142
143 /* draw a section of this scan line */
144 pixelp = &( gl->gr_pixels[y * gl->gr_xsize +
145 (startx - bBox.r_xbot)]);
146 for ( ; startx <= endx; startx++) {
147 int color, red, green, blue, mask;
148 if (*pixelp != 0)
149 {
150 mask = GrStyleTable[*pixelp].mask << 1;
151 color = GrStyleTable[*pixelp].color;
152 GrGetColor(color, &red, &green, &blue);
153 cairo_set_source_rgba(tcairodata->context, ((float)red / 255), ((float)green / 255), ((float)blue / 255), ((float)mask / 127.0));
154
155 cairo_rectangle(tcairodata->context, startx, yloc, 1, 1);
156 cairo_fill(tcairodata->context);
157 }
158 pixelp++;
159 }
160 startx = endx + 1;
161 }
162 }
163 yloc++;
164 }
165 }
166 }
167
168
169 /*
170 * ----------------------------------------------------------------------------
171 * GrTCairoSetCursor:
172 *
173 * Make the cursor be a new pattern, as defined in the display styles file.
174 *
175 * Results:
176 * None.
177 *
178 * Side effects:
179 * When the cursor is turned back on it will take on the new pattern.
180 * ----------------------------------------------------------------------------
181 */
182
183 void
GrTCairoSetCursor(cursorNum)184 GrTCairoSetCursor(cursorNum)
185 int cursorNum; /* The cursor number as defined in the display
186 * styles file.
187 */
188 {
189 HashEntry *entry;
190 HashSearch hs;
191 Tk_Window tkwind;
192
193 if (cursorNum >= MAX_CURSORS)
194 {
195 TxError("No such cursor!\n");
196 return;
197 }
198
199 tcairoCurrent.cursor = grCursors[cursorNum];
200
201 HashStartSearch(&hs);
202 while (entry = HashNext(&grTCairoWindowTable, &hs))
203 {
204 if (HashGetValue(entry))
205 {
206 tkwind = (Tk_Window)entry->h_key.h_ptr;
207 Tk_DefineCursor(tkwind, tcairoCurrent.cursor);
208 }
209 }
210 }
211