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"
88 #include "xevalgraph.h"
100 #define usleep(t) _sleep2(((t)+500)/1000)
104 # define _(s) gettext (s)
105 # define N_(s) gettext_noop (s)
113 Boolean cairoAnimate;
114 static cairo_surface_t *csBoardWindow, *csBoardBackup, *csDualBoard;
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];
132 cairo_surface_t *cstmp = csBoardWindow;
133 csBoardWindow = csDualBoard;
134 if(!csDualBoard && cstmp) {
135 int boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
136 int boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
137 csBoardWindow = cairo_xlib_surface_create(xDisplay, xBoardWindow, DefaultVisual(xDisplay, 0), boardWidth, boardHeight);
144 // delete surfaces after size becomes invalid, so they will be recreated
145 if(csBoardWindow) cairo_surface_destroy(csBoardWindow);
146 if(csBoardBackup) cairo_surface_destroy(csBoardBackup);
147 if(csDualBoard) cairo_surface_destroy(csDualBoard);
148 csBoardWindow = csBoardBackup = csDualBoard = NULL;
151 #define BoardSize int
153 InitDrawingSizes (BoardSize boardSize, int flags)
154 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
155 int boardWidth, boardHeight;
157 static Dimension oldWidth, oldHeight;
158 static VariantClass oldVariant;
159 static int oldMono = -1, oldTwoBoards = 0;
161 if(!formWidget) return;
163 if(oldTwoBoards && !twoBoards) PopDown(DummyDlg);
164 oldTwoBoards = twoBoards;
166 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
167 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
168 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
170 if(boardWidth != oldWidth || boardHeight != oldHeight) { // do resizing stuff only if size actually changed
172 oldWidth = boardWidth; oldHeight = boardHeight;
177 * Inhibit shell resizing.
179 ResizeBoardWindow(boardWidth, boardHeight, !cairoAnimate);
184 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
187 if(gameInfo.variant != oldVariant) { // and only if variant changed
191 for(p=0; p<=(int)WhiteKing; p++)
192 pngPieceBitmaps[i][p] = pngPieceBitmaps2[i][p]; // defaults
193 if(gameInfo.variant == VariantShogi) {
194 pngPieceBitmaps[i][(int)WhiteCannon] = pngPieceBitmaps2[i][(int)WhiteKing+1];
195 pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhiteKing+2];
196 pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteKing+3];
197 pngPieceBitmaps[i][(int)WhiteGrasshopper] = pngPieceBitmaps2[i][(int)WhiteKing+4];
198 pngPieceBitmaps[i][(int)WhiteQueen] = pngPieceBitmaps2[i][(int)WhiteLance];
201 if(gameInfo.variant == VariantGothic) {
202 pngPieceBitmaps[i][(int)WhiteMarshall] = pngPieceBitmaps2[i][(int)WhiteSilver];
205 if(gameInfo.variant == VariantSChess) {
206 pngPieceBitmaps[i][(int)WhiteAngel] = pngPieceBitmaps2[i][(int)WhiteFalcon];
207 pngPieceBitmaps[i][(int)WhiteMarshall] = pngPieceBitmaps2[i][(int)WhiteAlfil];
210 oldMono = -10; // kludge to force recreation of animation masks
211 oldVariant = gameInfo.variant;
214 oldMono = appData.monoMode;
218 CreatePNGBoard (char *s, int kind)
220 if(!appData.useBitmaps || s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
221 if(strstr(s, ".png")) {
222 cairo_surface_t *img = cairo_image_surface_create_from_png (s);
224 useTexture |= kind + 1; pngBoardBitmap[kind] = img;
225 textureW[kind] = cairo_image_surface_get_width (img);
226 textureH[kind] = cairo_image_surface_get_height (img);
231 char *pngPieceNames[] = // must be in same order as internal piece encoding
232 { "Pawn", "Knight", "Bishop", "Rook", "Queen", "Advisor", "Elephant", "Archbishop", "Marshall", "Gold", "Commoner",
233 "Canon", "Nightrider", "CrownedBishop", "CrownedRook", "Princess", "Chancellor", "Hawk", "Lance", "Cobra", "Unicorn", "King",
234 "GoldKnight", "GoldLance", "GoldPawn", "GoldSilver", NULL
238 ScaleOnePiece (char *name, int color, int piece)
242 cairo_surface_t *img, *cs;
244 static cairo_surface_t *pngPieceImages[2][(int)BlackPawn+4]; // png 256 x 256 images
246 if((img = pngPieceImages[color][piece]) == NULL) { // if PNG file for this piece was not yet read, read it now and store it
247 snprintf(buf, MSG_SIZ, "%s/%s%s.png", appData.pngDirectory, color ? "Black" : "White", pngPieceNames[piece]);
248 pngPieceImages[color][piece] = img = cairo_image_surface_create_from_png (buf);
249 w = cairo_image_surface_get_width (img);
250 h = cairo_image_surface_get_height (img);
251 if(w != 64 || h != 64) { printf("Bad png size %dx%d in %s\n", w, h, buf); exit(1); }
253 // create new bitmap to hold scaled piece image (and remove any old)
254 if(pngPieceBitmaps2[color][piece]) cairo_surface_destroy (pngPieceBitmaps2[color][piece]);
255 pngPieceBitmaps2[color][piece] = cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
256 if(piece <= WhiteKing) pngPieceBitmaps[color][piece] = cs;
257 // scaled copying of the raw png image
258 cr = cairo_create(cs);
259 cairo_scale(cr, squareSize/64., squareSize/64.);
260 cairo_set_source_surface (cr, img, 0, 0);
270 for(p=0; pngPieceNames[p]; p++) {
271 ScaleOnePiece(pngPieceNames[p], 0, p);
272 ScaleOnePiece(pngPieceNames[p], 1, p);
278 { // [HGM] taken out of main
279 if (appData.pngDirectory[0] != NULLCHAR) {
282 CreatePNGBoard(appData.liteBackTextureFile, 1);
283 CreatePNGBoard(appData.darkBackTextureFile, 0);
284 cairoAnimate = *appData.pngDirectory && useTexture == 3
285 && strstr(appData.liteBackTextureFile, ".png") && strstr(appData.darkBackTextureFile, ".png");
296 // [HGM] seekgraph: some low-level drawing routines (by JC, mostly)
299 Color (char *col, int n)
302 sscanf(col, "#%x", &c);
308 SetPen (cairo_t *cr, float w, char *col, int dash)
310 static const double dotted[] = {4.0, 4.0};
311 static int len = sizeof(dotted) / sizeof(dotted[0]);
312 cairo_set_line_width (cr, w);
313 cairo_set_source_rgba (cr, Color(col, 4), Color(col, 2), Color(col, 0), 1.0);
314 if(dash) cairo_set_dash (cr, dotted, len, 0.0);
317 void DrawSeekAxis( int x, int y, int xTo, int yTo )
322 cr = cairo_create (csBoardWindow);
324 cairo_move_to (cr, x, y);
325 cairo_line_to(cr, xTo, yTo );
327 SetPen(cr, 2, "#000000", 0);
334 void DrawSeekBackground( int left, int top, int right, int bottom )
336 cairo_t *cr = cairo_create (csBoardWindow);
338 cairo_rectangle (cr, left, top, right-left, bottom-top);
340 cairo_set_source_rgba(cr, 0.8, 0.8, 0.4,1.0);
347 void DrawSeekText(char *buf, int x, int y)
349 cairo_t *cr = cairo_create (csBoardWindow);
351 cairo_select_font_face (cr, "Sans",
352 CAIRO_FONT_SLANT_NORMAL,
353 CAIRO_FONT_WEIGHT_NORMAL);
355 cairo_set_font_size (cr, 12.0);
357 cairo_move_to (cr, x, y+4);
358 cairo_set_source_rgba(cr, 0, 0, 0,1.0);
359 cairo_show_text( cr, buf);
365 void DrawSeekDot(int x, int y, int colorNr)
367 cairo_t *cr = cairo_create (csBoardWindow);
368 int square = colorNr & 0x80;
372 cairo_rectangle (cr, x-squareSize/9, y-squareSize/9, 2*(squareSize/9), 2*(squareSize/9));
374 cairo_arc(cr, x, y, squareSize/9, 0.0, 2*M_PI);
376 SetPen(cr, 2, "#000000", 0);
377 cairo_stroke_preserve(cr);
379 case 0: cairo_set_source_rgba(cr, 1.0, 0, 0,1.0); break;
380 case 1: cairo_set_source_rgba (cr, 0.0, 0.7, 0.2, 1.0); break;
381 default: cairo_set_source_rgba (cr, 1.0, 1.0, 0.0, 1.0); break;
392 int boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
393 int boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
395 csBoardWindow = cairo_xlib_surface_create(xDisplay, xBoardWindow, DefaultVisual(xDisplay, 0), boardWidth, boardHeight);
396 csBoardBackup = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, boardWidth, boardHeight);
410 if (lineGap == 0) return;
412 /* [HR] Split this into 2 loops for non-square boards. */
414 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
415 gridSegments[i].x1 = 0;
417 lineGap + BOARD_WIDTH * (squareSize + lineGap);
418 gridSegments[i].y1 = gridSegments[i].y2
419 = lineGap / 2 + (i * (squareSize + lineGap));
422 for (j = 0; j < BOARD_WIDTH + 1; j++) {
423 gridSegments[j + i].y1 = 0;
424 gridSegments[j + i].y2 =
425 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
426 gridSegments[j + i].x1 = gridSegments[j + i].x2
427 = lineGap / 2 + (j * (squareSize + lineGap));
432 DoDrawGrid(cairo_surface_t *cs)
434 /* draws a grid starting around Nx, Ny squares starting at x,y */
440 cr = cairo_create (cs);
442 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
443 SetPen(cr, lineGap, "#000000", 0);
446 for (i = 0; i < BOARD_WIDTH + BOARD_HEIGHT + 2; i++)
448 cairo_move_to (cr, gridSegments[i].x1, gridSegments[i].y1);
449 cairo_line_to (cr, gridSegments[i].x2, gridSegments[i].y2);
462 DoDrawGrid(csBoardWindow);
463 DoDrawGrid(csBoardBackup);
467 DoDrawBorder (cairo_surface_t *cs, int x, int y, int type)
474 case 0: col = "#000000"; break;
475 case 1: col = appData.highlightSquareColor; break;
476 case 2: col = appData.premoveHighlightColor; break;
478 cr = cairo_create(cs);
479 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
480 cairo_rectangle(cr, x, y, squareSize+lineGap, squareSize+lineGap);
481 SetPen(cr, lineGap, col, 0);
486 DrawBorder (int x, int y, int type)
488 DoDrawBorder(csBoardWindow, x, y, type);
489 DoDrawBorder(csBoardBackup, x, y, type);
493 CutOutSquare (int x, int y, int *x0, int *y0, int kind)
495 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
496 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
498 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
499 if(textureW[kind] < W*squareSize)
500 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
502 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
503 if(textureH[kind] < H*squareSize)
504 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
506 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
511 DrawLogo (void *handle, void *logo)
513 cairo_surface_t *img, *cs;
517 if(!logo || !handle) return;
518 cs = cairo_xlib_surface_create(xDisplay, XtWindow(handle), DefaultVisual(xDisplay, 0), appData.logoSize, appData.logoSize/2);
519 img = cairo_image_surface_create_from_png (logo);
520 w = cairo_image_surface_get_width (img);
521 h = cairo_image_surface_get_height (img);
522 cr = cairo_create(cs);
523 cairo_scale(cr, (float)appData.logoSize/w, appData.logoSize/(2.*h));
524 cairo_set_source_surface (cr, img, 0, 0);
527 cairo_surface_destroy (img);
528 cairo_surface_destroy (cs);
532 BlankSquare (int x, int y, int color, ChessSquare piece, cairo_surface_t *dest, int fac)
533 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
538 cr = cairo_create (fac ? csBoardWindow : dest);
540 if ((useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
541 cairo_set_source_surface (cr, pngBoardBitmap[color], x*fac - x0, y*fac - y0);
542 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
543 cairo_rectangle (cr, x*fac, y*fac, squareSize, squareSize);
547 cr = cairo_create (csBoardBackup);
548 cairo_set_source_surface (cr, pngBoardBitmap[color], x*fac - x0, y*fac - y0);
549 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
550 cairo_rectangle (cr, x*fac, y*fac, squareSize, squareSize);
554 } else { // evenly colored squares
557 case 0: col = appData.darkSquareColor; break;
558 case 1: col = appData.lightSquareColor; break;
559 case 2: col = "#000000"; break;
561 SetPen(cr, 2.0, col, 0);
562 cairo_rectangle (cr, x, y, squareSize, squareSize);
566 cr = cairo_create (csBoardBackup);
567 SetPen(cr, 2.0, col, 0);
568 cairo_rectangle (cr, x, y, squareSize, squareSize);
576 pngDrawPiece (ChessSquare piece, int square_color, int x, int y, cairo_surface_t *dest)
581 if ((int)piece < (int) BlackPawn) {
587 if(appData.upsideDown && flipView) { p += p < BlackPawn ? BlackPawn : -BlackPawn; }// swap white and black pieces
588 BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
590 cr = cairo_create (csBoardWindow);
591 cairo_set_source_surface (cr, pngPieceBitmaps[kind][piece], x, y);
594 cr = cairo_create (csBoardBackup);
595 cairo_set_source_surface (cr, pngPieceBitmaps[kind][piece], x, y);
601 DoDrawDot (int marker, int x, int y, int r, cairo_surface_t *cs)
605 cr = cairo_create(cs);
606 cairo_arc(cr, x+r/2, y+r/2, r/2, 0.0, 2*M_PI);
607 if(appData.monoMode) {
608 SetPen(cr, 2, marker == 2 ? "#000000" : "#FFFFFF", 0);
609 cairo_stroke_preserve(cr);
610 SetPen(cr, 2, marker == 2 ? "#FFFFFF" : "#000000", 0);
612 SetPen(cr, 2, marker == 2 ? "#FF0000" : "#FFFF00", 0);
621 DrawDot (int marker, int x, int y, int r)
623 DoDrawDot(marker, x, y, r, csBoardWindow);
624 DoDrawDot(marker, x, y, r, csBoardBackup);
628 DrawOneSquare (int x, int y, ChessSquare piece, int square_color, int marker, char *string, int align)
629 { // basic front-end board-draw function: takes care of everything that can be in square:
630 // piece, background, coordinate/count, marker dot
631 int direction, font_ascent, font_descent;
635 if (piece == EmptySquare) {
636 BlankSquare(x, y, square_color, piece, csBoardWindow, 1);
638 pngDrawPiece(piece, square_color, x, y, csBoardWindow);
641 if(align) { // square carries inscription (coord or piece count)
643 // first calculate where it goes
644 XTextExtents(countFontStruct, string, 1, &direction,
645 &font_ascent, &font_descent, &overall);
647 xx += squareSize - overall.width - 2;
648 yy += squareSize - font_descent - 1;
649 } else if (align == 2) {
650 xx += 2, yy += font_ascent + 1;
651 } else if (align == 3) {
652 xx += squareSize - overall.width - 2;
653 yy += font_ascent + 1;
654 } else if (align == 4) {
655 xx += 2, yy += font_ascent + 1;
657 cr = cairo_create (csBoardWindow);
658 cairo_select_font_face (cr, "Sans",
659 CAIRO_FONT_SLANT_NORMAL,
660 CAIRO_FONT_WEIGHT_BOLD);
662 cairo_set_font_size (cr, squareSize/4);
664 cairo_move_to (cr, xx-1, yy);
665 if(align < 3) cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
666 else cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
667 cairo_show_text (cr, string);
670 cr = cairo_create (csBoardBackup);
671 cairo_select_font_face (cr, "Sans",
672 CAIRO_FONT_SLANT_NORMAL,
673 CAIRO_FONT_WEIGHT_BOLD);
675 cairo_set_font_size (cr, squareSize/4);
677 cairo_move_to (cr, xx-1, yy);
678 if(align < 3) cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
679 else cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
680 cairo_show_text (cr, string);
684 if(marker) { // print fat marker dot, if requested
685 DrawDot(marker, x + squareSize/4, y+squareSize/4, squareSize/2);
689 /**** Animation code by Hugh Fisher, DCS, ANU. ****/
691 /* Masks for XPM pieces. Black and white pieces can have
692 different shapes, but in the interest of retaining my
693 sanity pieces must have the same outline on both light
694 and dark squares, and all pieces must use the same
695 background square colors/images. */
697 static cairo_surface_t *c_animBufs[3*NrOfAnims]; // newBuf, saveBuf
700 InitAnimState (AnimNr anr)
702 DrawSeekOpen(); // set cs to board widget
703 if(c_animBufs[anr]) cairo_surface_destroy (c_animBufs[anr]);
704 if(c_animBufs[anr+2]) cairo_surface_destroy (c_animBufs[anr+2]);
705 c_animBufs[anr+4] = csBoardWindow;
706 c_animBufs[anr+2] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
707 c_animBufs[anr] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
714 InitAnimState(Player);
718 CairoOverlayPiece (ChessSquare piece, cairo_surface_t *dest)
720 static cairo_t *pieceSource;
721 pieceSource = cairo_create (dest);
722 cairo_set_source_surface (pieceSource, pngPieceBitmaps[!White(piece)][piece % BlackPawn], 0, 0);
723 if(doubleClick) cairo_paint_with_alpha (pieceSource, 0.6);
724 else cairo_paint(pieceSource);
725 cairo_destroy (pieceSource);
729 InsertPiece (AnimNr anr, ChessSquare piece)
731 CairoOverlayPiece(piece, c_animBufs[anr]);
735 DrawBlank (AnimNr anr, int x, int y, int startColor)
737 BlankSquare(x, y, startColor, EmptySquare, c_animBufs[anr+2], 0);
740 void CopyRectangle (AnimNr anr, int srcBuf, int destBuf,
741 int srcX, int srcY, int width, int height, int destX, int destY)
743 cairo_t *cr;// = cairo_create (c_animBufs[anr+destBuf]);
744 cr = cairo_create (c_animBufs[anr+destBuf]);
745 if(c_animBufs[anr+srcBuf] == csBoardWindow)
746 cairo_set_source_surface (cr, csBoardBackup, destX - srcX, destY - srcY);
748 cairo_set_source_surface (cr, c_animBufs[anr+srcBuf], destX - srcX, destY - srcY);
749 cairo_rectangle (cr, destX, destY, width, height);
752 if(c_animBufs[anr+destBuf] == csBoardWindow) {
753 cr = cairo_create (csBoardBackup); // also draw to backup
754 cairo_set_source_surface (cr, c_animBufs[anr+srcBuf], destX - srcX, destY - srcY);
755 cairo_rectangle (cr, destX, destY, width, height);
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 DoDrawPolygon(csBoardBackup, arrow, nr);