2 * draw.c -- drawing routines for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
56 #include <cairo/cairo.h>
57 #include <cairo/cairo-xlib.h>
62 #else /* not STDC_HEADERS */
63 extern char *getenv();
66 # else /* not HAVE_STRING_H */
68 # endif /* not HAVE_STRING_H */
69 #endif /* not STDC_HEADERS */
76 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
80 #include "pixmaps/pixmaps.h"
82 #include "bitmaps/bitmaps.h"
87 #include "xevalgraph.h"
99 #define usleep(t) _sleep2(((t)+500)/1000)
103 # define _(s) gettext (s)
104 # define N_(s) gettext_noop (s)
112 Boolean cairoAnimate;
113 static cairo_surface_t *csBoardWindow, *csBoardBackup, *csDualBoard;
114 static cairo_surface_t *pngPieceImages[2][(int)BlackPawn+4]; // png 256 x 256 images
115 static cairo_surface_t *pngPieceBitmaps[2][(int)BlackPawn]; // scaled pieces as used
116 static cairo_surface_t *pngPieceBitmaps2[2][(int)BlackPawn+4]; // scaled pieces in store
117 static cairo_surface_t *pngBoardBitmap[2];
118 int useTexture, textureW[2], textureH[2];
120 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
121 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
123 #define White(piece) ((int)(piece) < (int)BlackPawn)
127 } gridSegments[BOARD_RANKS + BOARD_FILES + 2];
134 cairo_surface_t *cstmp = csBoardWindow;
135 csBoardWindow = csDualBoard;
138 csBoardWindow = GetOutputSurface(&dualOptions[3], 0, 0);
148 // delete surfaces after size becomes invalid, so they will be recreated
149 if(csBoardWindow) cairo_surface_destroy(csBoardWindow);
150 if(csBoardBackup) cairo_surface_destroy(csBoardBackup);
151 if(csDualBoard) cairo_surface_destroy(csDualBoard);
152 csBoardWindow = csBoardBackup = csDualBoard = NULL;
155 #define BoardSize int
157 InitDrawingSizes (BoardSize boardSize, int flags)
158 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
159 int boardWidth, boardHeight;
161 static int oldWidth, oldHeight;
162 static VariantClass oldVariant;
163 static int oldMono = -1, oldTwoBoards = 0;
164 extern Widget formWidget;
166 if(!formWidget) return;
168 if(oldTwoBoards && !twoBoards) PopDown(DummyDlg);
169 oldTwoBoards = twoBoards;
171 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
172 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
173 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
175 if(boardWidth != oldWidth || boardHeight != oldHeight) { // do resizing stuff only if size actually changed
177 oldWidth = boardWidth; oldHeight = boardHeight;
182 * Inhibit shell resizing.
184 ResizeBoardWindow(boardWidth, boardHeight, 0);
189 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
192 if(gameInfo.variant != oldVariant) { // and only if variant changed
196 for(p=0; p<=(int)WhiteKing; p++)
197 pngPieceBitmaps[i][p] = pngPieceBitmaps2[i][p]; // defaults
198 if(gameInfo.variant == VariantShogi) {
199 pngPieceBitmaps[i][(int)WhiteCannon] = pngPieceBitmaps2[i][(int)WhiteKing+1];
200 pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhiteKing+2];
201 pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteKing+3];
202 pngPieceBitmaps[i][(int)WhiteGrasshopper] = pngPieceBitmaps2[i][(int)WhiteKing+4];
203 pngPieceBitmaps[i][(int)WhiteQueen] = pngPieceBitmaps2[i][(int)WhiteLance];
206 if(gameInfo.variant == VariantGothic) {
207 pngPieceBitmaps[i][(int)WhiteMarshall] = pngPieceBitmaps2[i][(int)WhiteSilver];
210 if(gameInfo.variant == VariantSChess) {
211 pngPieceBitmaps[i][(int)WhiteAngel] = pngPieceBitmaps2[i][(int)WhiteFalcon];
212 pngPieceBitmaps[i][(int)WhiteMarshall] = pngPieceBitmaps2[i][(int)WhiteAlfil];
215 oldMono = -10; // kludge to force recreation of animation masks
216 oldVariant = gameInfo.variant;
219 oldMono = appData.monoMode;
223 CreatePNGBoard (char *s, int kind)
225 if(!appData.useBitmaps || s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
226 if(strstr(s, ".png")) {
227 cairo_surface_t *img = cairo_image_surface_create_from_png (s);
229 useTexture |= kind + 1; pngBoardBitmap[kind] = img;
230 textureW[kind] = cairo_image_surface_get_width (img);
231 textureH[kind] = cairo_image_surface_get_height (img);
236 char *pngPieceNames[] = // must be in same order as internal piece encoding
237 { "Pawn", "Knight", "Bishop", "Rook", "Queen", "Advisor", "Elephant", "Archbishop", "Marshall", "Gold", "Commoner",
238 "Canon", "Nightrider", "CrownedBishop", "CrownedRook", "Princess", "Chancellor", "Hawk", "Lance", "Cobra", "Unicorn", "King",
239 "GoldKnight", "GoldLance", "GoldPawn", "GoldSilver", NULL
243 ConvertPixmap (int color, int piece)
245 int i, j, stride, f, colcode[10], w, b;
247 cairo_surface_t *res;
248 XpmPieces *p = builtInXpms + 10;
249 char **pixels = p->xpm[piece % BlackPawn][2*color];
251 sscanf(pixels[0], "%*d %*d %d", &f);
252 sscanf(appData.whitePieceColor+1, "%x", &w);
253 sscanf(appData.blackPieceColor+1, "%x", &b);
254 res = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, p->size, p->size);
255 stride = cairo_image_surface_get_stride(res);
256 buf = (int *) cairo_image_surface_get_data(res);
258 ch[i] = pixels[i+1][0];
260 if(strstr(pixels[i+1], "black")) colcode[i] = 0xFF000000; // 0xFF000000 + (color ? b : 0);
261 if(strstr(pixels[i+1], "white")) colcode[i] = 0xFFFFFFCC; // 0xFF000000 + w;
263 for(i=0; i<p->size; i++) {
264 for(j=0; j<p->size; j++) {
265 char c = pixels[i+f+1][j];
267 for(k=0; ch[k] != c && k < f; k++);
268 buf[i*p->size + j] = colcode[k];
271 cairo_surface_mark_dirty(res);
276 ScaleOnePiece (char *name, int color, int piece)
280 cairo_surface_t *img, *cs;
283 if((img = pngPieceImages[color][piece]) == NULL) { // if PNG file for this piece was not yet read, read it now and store it
284 if(!*appData.pngDirectory) img = ConvertPixmap(color, piece); else {
285 snprintf(buf, MSG_SIZ, "%s/%s%s.png", appData.pngDirectory, color ? "Black" : "White", pngPieceNames[piece]);
286 img = cairo_image_surface_create_from_png (buf);
287 if(cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) img = ConvertPixmap(color, piece);
290 pngPieceImages[color][piece] = img;
291 // create new bitmap to hold scaled piece image (and remove any old)
292 if(pngPieceBitmaps2[color][piece]) cairo_surface_destroy (pngPieceBitmaps2[color][piece]);
293 pngPieceBitmaps2[color][piece] = cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
294 if(piece <= WhiteKing) pngPieceBitmaps[color][piece] = cs;
295 // scaled copying of the raw png image
296 cr = cairo_create(cs);
297 w = cairo_image_surface_get_width (img);
298 h = cairo_image_surface_get_height (img);
299 cairo_scale(cr, squareSize/w, squareSize/h);
300 cairo_set_source_surface (cr, img, 0, 0);
303 { // operate on bitmap to color it (king-size hack...)
304 int stride = cairo_image_surface_get_stride(cs)/4;
305 int *buf = (int *) cairo_image_surface_get_data(cs);
307 sscanf(color ? appData.blackPieceColor+1 : appData.whitePieceColor+1, "%x", &p); // replacement color
308 cairo_surface_flush(cs);
309 for(i=0; i<squareSize; i++) for(j=0; j<squareSize; j++) {
312 unsigned int c = buf[i*stride + j];
313 a = c >> 24; r = c >> 16 & 255; // alpha and red, where red is the 'white' weight, since white is #FFFFCC in the source images
314 f = (color ? a - r : r)/255.; // fraction of black or white in the mix that has to be replaced
315 buf[i*stride + j] = c & 0xFF000000; // alpha channel is kept at same opacity
316 buf[i*stride + j] += ((int)(f*(p&0xFF0000)) & 0xFF0000) + ((int)(f*(p&0xFF00)) & 0xFF00) + (int)(f*(p&0xFF)); // add desired fraction of new color
317 if(color) buf[i*stride + j] += r | r << 8 | r << 16; // details on black pieces get their weight added in pure white
319 cairo_surface_mark_dirty(cs);
328 for(p=0; pngPieceNames[p]; p++) {
329 ScaleOnePiece(pngPieceNames[p], 0, p);
330 ScaleOnePiece(pngPieceNames[p], 1, p);
336 { // [HGM] taken out of main
338 CreatePNGBoard(appData.liteBackTextureFile, 1);
339 CreatePNGBoard(appData.darkBackTextureFile, 0);
343 InitDrawingParams (int reloadPieces)
348 for(i=0; i<2; i++) for(p=0; p<BlackPawn+4; p++) {
349 if(pngPieceImages[i][p]) cairo_surface_destroy(pngPieceImages[i][p]);
350 pngPieceImages[i][p] = NULL;
355 // [HGM] seekgraph: some low-level drawing routines (by JC, mostly)
358 Color (char *col, int n)
361 sscanf(col, "#%x", &c);
367 SetPen (cairo_t *cr, float w, char *col, int dash)
369 static const double dotted[] = {4.0, 4.0};
370 static int len = sizeof(dotted) / sizeof(dotted[0]);
371 cairo_set_line_width (cr, w);
372 cairo_set_source_rgba (cr, Color(col, 4), Color(col, 2), Color(col, 0), 1.0);
373 if(dash) cairo_set_dash (cr, dotted, len, 0.0);
376 void DrawSeekAxis( int x, int y, int xTo, int yTo )
381 cr = cairo_create (csBoardWindow);
383 cairo_move_to (cr, x, y);
384 cairo_line_to(cr, xTo, yTo );
386 SetPen(cr, 2, "#000000", 0);
393 void DrawSeekBackground( int left, int top, int right, int bottom )
395 cairo_t *cr = cairo_create (csBoardWindow);
397 cairo_rectangle (cr, left, top, right-left, bottom-top);
399 cairo_set_source_rgba(cr, 0.8, 0.8, 0.4,1.0);
406 void DrawSeekText(char *buf, int x, int y)
408 cairo_t *cr = cairo_create (csBoardWindow);
410 cairo_select_font_face (cr, "Sans",
411 CAIRO_FONT_SLANT_NORMAL,
412 CAIRO_FONT_WEIGHT_NORMAL);
414 cairo_set_font_size (cr, 12.0);
416 cairo_move_to (cr, x, y+4);
417 cairo_set_source_rgba(cr, 0, 0, 0,1.0);
418 cairo_show_text( cr, buf);
424 void DrawSeekDot(int x, int y, int colorNr)
426 cairo_t *cr = cairo_create (csBoardWindow);
427 int square = colorNr & 0x80;
431 cairo_rectangle (cr, x-squareSize/9, y-squareSize/9, 2*(squareSize/9), 2*(squareSize/9));
433 cairo_arc(cr, x, y, squareSize/9, 0.0, 2*M_PI);
435 SetPen(cr, 2, "#000000", 0);
436 cairo_stroke_preserve(cr);
438 case 0: cairo_set_source_rgba(cr, 1.0, 0, 0,1.0); break;
439 case 1: cairo_set_source_rgba (cr, 0.0, 0.7, 0.2, 1.0); break;
440 default: cairo_set_source_rgba (cr, 1.0, 1.0, 0.0, 1.0); break;
451 csBoardWindow = (cairo_surface_t *) mainOptions[W_BOARD].choice;
464 if (lineGap == 0) return;
466 /* [HR] Split this into 2 loops for non-square boards. */
468 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
469 gridSegments[i].x1 = 0;
471 lineGap + BOARD_WIDTH * (squareSize + lineGap);
472 gridSegments[i].y1 = gridSegments[i].y2
473 = lineGap / 2 + (i * (squareSize + lineGap));
476 for (j = 0; j < BOARD_WIDTH + 1; j++) {
477 gridSegments[j + i].y1 = 0;
478 gridSegments[j + i].y2 =
479 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
480 gridSegments[j + i].x1 = gridSegments[j + i].x2
481 = lineGap / 2 + (j * (squareSize + lineGap));
488 /* draws a grid starting around Nx, Ny squares starting at x,y */
494 cr = cairo_create (csBoardWindow);
496 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
497 SetPen(cr, lineGap, "#000000", 0);
500 for (i = 0; i < BOARD_WIDTH + BOARD_HEIGHT + 2; i++)
502 cairo_move_to (cr, gridSegments[i].x1, gridSegments[i].y1);
503 cairo_line_to (cr, gridSegments[i].x2, gridSegments[i].y2);
514 DrawBorder (int x, int y, int type)
521 case 0: col = "#000000"; break;
522 case 1: col = appData.highlightSquareColor; break;
523 case 2: col = appData.premoveHighlightColor; break;
525 cr = cairo_create(csBoardWindow);
526 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
527 cairo_rectangle(cr, x, y, squareSize+lineGap, squareSize+lineGap);
528 SetPen(cr, lineGap, col, 0);
531 DrawExpose(NULL, x, y, squareSize+2*lineGap, squareSize+2*lineGap);
535 CutOutSquare (int x, int y, int *x0, int *y0, int kind)
537 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
538 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
540 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
541 if(textureW[kind] < W*squareSize)
542 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
544 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
545 if(textureH[kind] < H*squareSize)
546 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
548 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
553 DrawLogo (void *handle, void *logo)
555 cairo_surface_t *img, *cs;
559 if(!logo || !handle) return;
560 cs = GetOutputSurface(handle, appData.logoSize, appData.logoSize/2);
561 img = cairo_image_surface_create_from_png (logo);
562 w = cairo_image_surface_get_width (img);
563 h = cairo_image_surface_get_height (img);
564 cr = cairo_create(cs);
565 cairo_scale(cr, (float)appData.logoSize/w, appData.logoSize/(2.*h));
566 cairo_set_source_surface (cr, img, 0, 0);
569 cairo_surface_destroy (img);
570 cairo_surface_destroy (cs);
574 BlankSquare (cairo_surface_t *dest, int x, int y, int color, ChessSquare piece, int fac)
575 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
579 cr = cairo_create (dest);
581 if ((useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
582 cairo_set_source_surface (cr, pngBoardBitmap[color], x*fac - x0, y*fac - y0);
583 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
584 cairo_rectangle (cr, x*fac, y*fac, squareSize, squareSize);
587 } else { // evenly colored squares
590 case 0: col = appData.darkSquareColor; break;
591 case 1: col = appData.lightSquareColor; break;
592 case 2: col = "#000000"; break;
594 SetPen(cr, 2.0, col, 0);
595 cairo_rectangle (cr, x, y, squareSize, squareSize);
602 pngDrawPiece (cairo_surface_t *dest, ChessSquare piece, int square_color, int x, int y)
607 if ((int)piece < (int) BlackPawn) {
613 if(appData.upsideDown && flipView) { p += p < BlackPawn ? BlackPawn : -BlackPawn; }// swap white and black pieces
614 BlankSquare(dest, x, y, square_color, piece, 1); // erase previous contents with background
615 cr = cairo_create (dest);
616 cairo_set_source_surface (cr, pngPieceBitmaps[kind][piece], x, y);
622 DoDrawDot (cairo_surface_t *cs, int marker, int x, int y, int r)
626 cr = cairo_create(cs);
627 cairo_arc(cr, x+r/2, y+r/2, r/2, 0.0, 2*M_PI);
628 if(appData.monoMode) {
629 SetPen(cr, 2, marker == 2 ? "#000000" : "#FFFFFF", 0);
630 cairo_stroke_preserve(cr);
631 SetPen(cr, 2, marker == 2 ? "#FFFFFF" : "#000000", 0);
633 SetPen(cr, 2, marker == 2 ? "#FF0000" : "#FFFF00", 0);
641 DrawDot (int marker, int x, int y, int r)
642 { // used for atomic captures; no need to draw on backup
644 DoDrawDot(csBoardWindow, marker, x, y, r);
648 DrawOneSquare (int x, int y, ChessSquare piece, int square_color, int marker, char *string, int align)
649 { // basic front-end board-draw function: takes care of everything that can be in square:
650 // piece, background, coordinate/count, marker dot
655 if (piece == EmptySquare) {
656 BlankSquare(csBoardWindow, x, y, square_color, piece, 1);
658 pngDrawPiece(csBoardWindow, piece, square_color, x, y);
661 if(align) { // square carries inscription (coord or piece count)
663 cairo_text_extents_t te;
665 cr = cairo_create (csBoardWindow);
666 cairo_select_font_face (cr, "Sans",
667 CAIRO_FONT_SLANT_NORMAL,
668 CAIRO_FONT_WEIGHT_BOLD);
670 cairo_set_font_size (cr, squareSize/4);
671 // calculate where it goes
672 cairo_text_extents (cr, string, &te);
675 xx += squareSize - te.width - te.x_bearing - 1;
676 yy += squareSize - te.height - te.y_bearing - 1;
677 } else if (align == 2) {
678 xx += te.x_bearing + 1, yy += -te.y_bearing + 1;
679 } else if (align == 3) {
680 xx += squareSize - te.width -te.x_bearing - 1;
681 yy += -te.y_bearing + 3;
682 } else if (align == 4) {
683 xx += te.x_bearing + 1, yy += -te.y_bearing + 3;
686 cairo_move_to (cr, xx-1, yy);
687 if(align < 3) cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
688 else cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
689 cairo_show_text (cr, string);
693 if(marker) { // print fat marker dot, if requested
694 DoDrawDot(csBoardWindow, marker, x + squareSize/4, y+squareSize/4, squareSize/2);
698 /**** Animation code by Hugh Fisher, DCS, ANU. ****/
700 /* Masks for XPM pieces. Black and white pieces can have
701 different shapes, but in the interest of retaining my
702 sanity pieces must have the same outline on both light
703 and dark squares, and all pieces must use the same
704 background square colors/images. */
706 static cairo_surface_t *c_animBufs[3*NrOfAnims]; // newBuf, saveBuf
709 InitAnimState (AnimNr anr)
711 DrawSeekOpen(); // set cs to board widget
712 if(c_animBufs[anr]) cairo_surface_destroy (c_animBufs[anr]);
713 if(c_animBufs[anr+2]) cairo_surface_destroy (c_animBufs[anr+2]);
714 c_animBufs[anr+4] = csBoardWindow;
715 c_animBufs[anr+2] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
716 c_animBufs[anr] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
723 InitAnimState(Player);
727 CairoOverlayPiece (ChessSquare piece, cairo_surface_t *dest)
729 static cairo_t *pieceSource;
730 pieceSource = cairo_create (dest);
731 cairo_set_source_surface (pieceSource, pngPieceBitmaps[!White(piece)][piece % BlackPawn], 0, 0);
732 if(doubleClick) cairo_paint_with_alpha (pieceSource, 0.6);
733 else cairo_paint(pieceSource);
734 cairo_destroy (pieceSource);
738 InsertPiece (AnimNr anr, ChessSquare piece)
740 CairoOverlayPiece(piece, c_animBufs[anr]);
744 DrawBlank (AnimNr anr, int x, int y, int startColor)
746 BlankSquare(c_animBufs[anr+2], x, y, startColor, EmptySquare, 0);
749 void CopyRectangle (AnimNr anr, int srcBuf, int destBuf,
750 int srcX, int srcY, int width, int height, int destX, int destY)
752 cairo_t *cr = cairo_create (c_animBufs[anr+destBuf]);
753 cairo_set_source_surface (cr, c_animBufs[anr+srcBuf], destX - srcX, destY - srcY);
754 cairo_rectangle (cr, destX, destY, width, height);
757 if(c_animBufs[anr+destBuf] == csBoardWindow)
758 DrawExpose(NULL, destX, destY, squareSize, squareSize);
762 SetDragPiece (AnimNr anr, ChessSquare piece)
766 /* [AS] Arrow highlighting support */
769 DoDrawPolygon (cairo_surface_t *cs, Pnt arrow[], int nr)
773 cr = cairo_create (cs);
774 cairo_move_to (cr, arrow[nr-1].x, arrow[nr-1].y);
776 cairo_line_to(cr, arrow[i].x, arrow[i].y);
778 if(appData.monoMode) { // should we always outline arrow?
779 cairo_line_to(cr, arrow[0].x, arrow[0].y);
780 SetPen(cr, 2, "#000000", 0);
781 cairo_stroke_preserve(cr);
783 SetPen(cr, 2, appData.highlightSquareColor, 0);
791 DrawPolygon (Pnt arrow[], int nr)
793 DoDrawPolygon(csBoardWindow, arrow, nr);
794 // if(!dual) DoDrawPolygon(csBoardBackup, arrow, nr);