#if HAVE_LIBXPM
#include <X11/xpm.h>
-#include "pixmaps/pixmaps.h"
#define IMAGE_EXT "xpm"
#else
#define IMAGE_EXT "xim"
-#include "bitmaps/bitmaps.h"
#endif
#include "bitmaps/icon_white.bm"
#include "engineoutput.h"
#include "usystem.h"
#include "gettext.h"
+#include "draw.h"
#ifdef __EMX__
RETSIGTYPE CmailSigHandler P((int sig));
RETSIGTYPE IntSigHandler P((int sig));
RETSIGTYPE TermSizeSigHandler P((int sig));
-static void CreateGCs P((int redo));
-static void CreateAnyPieces P((void));
-void CreateXIMPieces P((void));
-void CreateXPMPieces P((void));
-void CreatePNGPieces P((void));
-void CreateXPMBoard P((char *s, int n));
-void CreatePieces P((void));
Widget CreateMenuBar P((Menu *mb, int boardWidth));
#if ENABLE_NLS
char *InsertPxlSize P((char *pattern, int targetPxlSize));
#endif
void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
u_int wreq, u_int hreq));
-void CreateGrid P((void));
void EventProc P((Widget widget, caddr_t unused, XEvent *event));
void DelayedDrag P((void));
static void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
Display *xDisplay;
Window xBoardWindow;
Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
- highlightSquareColor, premoveHighlightColor, dialogColor, buttonColor;
-Pixel lowTimeWarningColor;
-GC lightSquareGC, darkSquareGC, lineGC, wdPieceGC, wlPieceGC,
- bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
- prelineGC, countGC;
+ highlightSquareColor, premoveHighlightColor; // used in graphics
+Pixel lowTimeWarningColor, dialogColor, buttonColor; // used in widgets
Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
Widget shellWidget, formWidget, boardWidget, titleWidget, dropMenu, menuBarWidget;
Option *optList; // contains all widgets of main window
-XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
#if ENABLE_NLS
XFontSet fontSet, clockFontSet;
#else
WindowPlacement wpTags;
-#define SOLID 0
-#define OUTLINE 1
-Boolean cairoAnimate;
-static cairo_surface_t *csBoardWindow, *csBoardBackup, *csDualBoard;
-static cairo_surface_t *pngPieceBitmaps[2][(int)BlackPawn]; // scaled pieces as used
-static cairo_surface_t *pngPieceBitmaps2[2][(int)BlackPawn+4]; // scaled pieces in store
-static cairo_surface_t *pngBoardBitmap[2];
-Pixmap pieceBitmap[2][(int)BlackPawn];
-Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
-Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
-Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
-Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
-Pixmap xpmBoardBitmap[2];
-int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
-XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
-Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
-Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
-XImage *ximLightSquare, *ximDarkSquare;
-XImage *xim_Cross;
-
-#define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
-#define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
-
-#define White(piece) ((int)(piece) < (int)BlackPawn)
-
-/* Bitmaps for use as masks when drawing XPM pieces.
- Need one for each black and white piece. */
-static Pixmap xpmMask[BlackKing + 1];
-
/* This magic number is the number of intermediate frames used
in each half of the animation. For short moves it's reduced
by 1. The total number of frames will be factor * 2 + 1. */
}
void
-SwitchWindow ()
-{
- extern Option dualOptions[];
- static Window dual;
- Window tmp = xBoardWindow;
- cairo_surface_t *cstmp = csBoardWindow;
- if(!dual) dual = XtWindow(dualOptions[3].handle); // must be first call
- xBoardWindow = dual; // swap them
- dual = tmp;
- csBoardWindow = csDualBoard;
- if(!csDualBoard && cstmp) {
- int boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
- int boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
- csBoardWindow = cairo_xlib_surface_create(xDisplay, xBoardWindow, DefaultVisual(xDisplay, 0), boardWidth, boardHeight);
- }
-}
-
-void
PopUpStartupDialog ()
{ // start menu not implemented in XBoard
}
//--------------------------------------------------------------------------------------------
void
-NewSurfaces ()
+ResizeBoardWindow (int w, int h, int inhibit)
{
- // delete surfaces after size becomes invalid, so they will be recreated
- if(csBoardWindow) cairo_surface_destroy(csBoardWindow);
- if(csBoardBackup) cairo_surface_destroy(csBoardBackup);
- if(csDualBoard) cairo_surface_destroy(csDualBoard);
- csBoardWindow = csBoardBackup = csDualBoard = NULL;
-}
-
-#define BoardSize int
-void
-InitDrawingSizes (BoardSize boardSize, int flags)
-{ // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
- Dimension boardWidth, boardHeight, w, h;
- int i;
- static Dimension oldWidth, oldHeight;
- static VariantClass oldVariant;
- static int oldMono = -1, oldTwoBoards = 0;
-
- if(!formWidget) return;
-
- if(oldTwoBoards && !twoBoards) PopDown(DummyDlg);
- oldTwoBoards = twoBoards;
-
- if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
- boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
- boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
-
- if(boardWidth != oldWidth || boardHeight != oldHeight) { // do resizing stuff only if size actually changed
-
- oldWidth = boardWidth; oldHeight = boardHeight;
- CreateGrid();
- NewSurfaces();
-
- /*
- * Inhibit shell resizing.
- */
- shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + 1; // [HGM] not sure why the +1 is (sometimes) needed...
- shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
+ w += marginW + 1; // [HGM] not sure why the +1 is (sometimes) needed...
+ h += marginH;
+ shellArgs[0].value = w;
+ shellArgs[1].value = h;
shellArgs[4].value = shellArgs[2].value = w;
shellArgs[5].value = shellArgs[3].value = h;
- XtSetValues(shellWidget, &shellArgs[0], cairoAnimate ? 2 : 6);
+ XtSetValues(shellWidget, &shellArgs[0], inhibit ? 6 : 2);
XSync(xDisplay, False);
- DelayedDrag();
- }
-
- // [HGM] pieces: tailor piece bitmaps to needs of specific variant
- // (only for xpm)
-
- if(gameInfo.variant != oldVariant) { // and only if variant changed
-
- if(useImages) {
- for(i=0; i<4; i++) {
- int p;
- for(p=0; p<=(int)WhiteKing; p++)
- xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
- if(gameInfo.variant == VariantShogi) {
- xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
- xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
- xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
- xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
- xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
- }
-#ifdef GOTHIC
- if(gameInfo.variant == VariantGothic) {
- xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
- }
-#endif
- if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
- xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
- xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
- }
-#if !HAVE_LIBXPM
- // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
- for(p=0; p<=(int)WhiteKing; p++)
- ximMaskPm[p] = ximMaskPm2[p]; // defaults
- if(gameInfo.variant == VariantShogi) {
- ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
- ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
- ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
- ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
- ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
- }
-#ifdef GOTHIC
- if(gameInfo.variant == VariantGothic) {
- ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
- }
-#endif
- if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
- ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
- ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
- }
-#endif
- }
- } else {
- for(i=0; i<2; i++) {
- int p;
- for(p=0; p<=(int)WhiteKing; p++)
- pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
- if(gameInfo.variant == VariantShogi) {
- pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
- pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
- pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
- pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
- pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
- }
-#ifdef GOTHIC
- if(gameInfo.variant == VariantGothic) {
- pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
- }
-#endif
- if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
- pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
- pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
- }
- }
- }
- for(i=0; i<2; i++) {
- int p;
- for(p=0; p<=(int)WhiteKing; p++)
- pngPieceBitmaps[i][p] = pngPieceBitmaps2[i][p]; // defaults
- if(gameInfo.variant == VariantShogi) {
- pngPieceBitmaps[i][(int)WhiteCannon] = pngPieceBitmaps2[i][(int)WhiteKing+1];
- pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhiteKing+2];
- pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteKing+3];
- pngPieceBitmaps[i][(int)WhiteGrasshopper] = pngPieceBitmaps2[i][(int)WhiteKing+4];
- pngPieceBitmaps[i][(int)WhiteQueen] = pngPieceBitmaps2[i][(int)WhiteLance];
- }
- if(gameInfo.variant == VariantGothic) {
- pngPieceBitmaps[i][(int)WhiteMarshall] = pngPieceBitmaps2[i][(int)WhiteSilver];
- }
- if(gameInfo.variant == VariantSChess) {
- pngPieceBitmaps[i][(int)WhiteAngel] = pngPieceBitmaps2[i][(int)WhiteFalcon];
- pngPieceBitmaps[i][(int)WhiteMarshall] = pngPieceBitmaps2[i][(int)WhiteAlfil];
- }
- }
- oldMono = -10; // kludge to force recreation of animation masks
- oldVariant = gameInfo.variant;
- }
-#if HAVE_LIBXPM
- if(appData.monoMode != oldMono || cairoAnimate)
- CreateAnimVars();
-#endif
- oldMono = appData.monoMode;
}
static int
return False;
}
-static int
+int
MakeColors ()
{ // [HGM] taken out of main(), so it can be called from BoardOptions dialog
int forceMono = False;
return forceMono;
}
-static void
-CreateAnyPieces ()
-{ // [HGM] taken out of main
-#if HAVE_LIBXPM
- if (appData.monoMode && // [HGM] no sense to go on to certain doom
- (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
- appData.bitmapDirectory = strdup(DEF_BITMAP_DIR);
-
- if (appData.bitmapDirectory[0] != NULLCHAR) {
- CreatePieces();
- } else {
- CreateXPMPieces();
- CreateXPMBoard(appData.liteBackTextureFile, 1);
- CreateXPMBoard(appData.darkBackTextureFile, 0);
- }
- if (appData.pngDirectory[0] != NULLCHAR) { // for now do in parallel
- CreatePNGPieces();
- }
-#else
- CreateXIMPieces();
- /* Create regular pieces */
- if (!useImages) CreatePieces();
-#endif
-}
-
-void
-InitDrawingParams ()
-{
- MakeColors(); CreateGCs(True);
- CreateAnyPieces();
-}
-
void
InitializeFonts (int clockFontPxlSize, int coordFontPxlSize, int fontPxlSize)
{ // detervtomine what fonts to use, and create them
/*
* Inhibit shell resizing.
*/
-
- CreateAnyPieces();
- cairoAnimate = *appData.pngDirectory && useTexture == 3
- && strstr(appData.liteBackTextureFile, ".png") && strstr(appData.darkBackTextureFile, ".png");
-
shellArgs[0].value = (XtArgVal) &w;
shellArgs[1].value = (XtArgVal) &h;
XtGetValues(shellWidget, shellArgs, 2);
shellArgs[4].value = shellArgs[2].value = w;
shellArgs[5].value = shellArgs[3].value = h;
- if(!cairoAnimate) XtSetValues(shellWidget, &shellArgs[2], 4);
+ if(!CreateAnyPieces()) XtSetValues(shellWidget, &shellArgs[2], 4);
marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
marginH = h - boardHeight;
#endif
void
-DeleteGCs ()
-{ // [HGM] deletes GCs that are to be remade, to prevent resource leak;
- // must be called before all non-first callse to CreateGCs()
- XtReleaseGC(shellWidget, highlineGC);
- XtReleaseGC(shellWidget, lightSquareGC);
- XtReleaseGC(shellWidget, darkSquareGC);
- XtReleaseGC(shellWidget, lineGC);
- if (appData.monoMode) {
- if (DefaultDepth(xDisplay, xScreen) == 1) {
- XtReleaseGC(shellWidget, wbPieceGC);
- } else {
- XtReleaseGC(shellWidget, bwPieceGC);
- }
- } else {
- XtReleaseGC(shellWidget, prelineGC);
- XtReleaseGC(shellWidget, wdPieceGC);
- XtReleaseGC(shellWidget, wlPieceGC);
- XtReleaseGC(shellWidget, bdPieceGC);
- XtReleaseGC(shellWidget, blPieceGC);
- }
-}
-
-static GC
-CreateOneGC (XGCValues *gc_values, Pixel foreground, Pixel background)
-{
- XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
- | GCBackground | GCFunction | GCPlaneMask;
- gc_values->foreground = foreground;
- gc_values->background = background;
- return XtGetGC(shellWidget, value_mask, gc_values);
-}
-
-static void
-CreateGCs (int redo)
-{
- XGCValues gc_values;
- GC copyInvertedGC;
- Pixel white = XWhitePixel(xDisplay, xScreen);
- Pixel black = XBlackPixel(xDisplay, xScreen);
-
- gc_values.plane_mask = AllPlanes;
- gc_values.line_width = lineGap;
- gc_values.line_style = LineSolid;
- gc_values.function = GXcopy;
-
- if(redo) {
- DeleteGCs(); // called a second time; clean up old GCs first
- } else { // [HGM] grid and font GCs created on first call only
- coordGC = CreateOneGC(&gc_values, black, white);
- XSetFont(xDisplay, coordGC, coordFontID);
-
- // [HGM] make font for holdings counts (white on black)
- countGC = CreateOneGC(&gc_values, white, black);
- XSetFont(xDisplay, countGC, countFontID);
- }
- lineGC = CreateOneGC(&gc_values, black, black);
-
- if (appData.monoMode) {
-
- highlineGC = CreateOneGC(&gc_values, white, white);
- lightSquareGC = wbPieceGC = CreateOneGC(&gc_values, white, black);
- darkSquareGC = bwPieceGC = CreateOneGC(&gc_values, black, white);
-
- if (DefaultDepth(xDisplay, xScreen) == 1) {
- /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
- gc_values.function = GXcopyInverted;
- copyInvertedGC = CreateOneGC(&gc_values, black, white);
- gc_values.function = GXcopy;
- if (XBlackPixel(xDisplay, xScreen) == 1) {
- bwPieceGC = darkSquareGC;
- wbPieceGC = copyInvertedGC;
- } else {
- bwPieceGC = copyInvertedGC;
- wbPieceGC = lightSquareGC;
- }
- }
- } else {
-
- highlineGC = CreateOneGC(&gc_values, highlightSquareColor, highlightSquareColor);
- prelineGC = CreateOneGC(&gc_values, premoveHighlightColor, premoveHighlightColor);
- lightSquareGC = CreateOneGC(&gc_values, lightSquareColor, darkSquareColor);
- darkSquareGC = CreateOneGC(&gc_values, darkSquareColor, lightSquareColor);
- wdPieceGC = CreateOneGC(&gc_values, whitePieceColor, darkSquareColor);
- wlPieceGC = CreateOneGC(&gc_values, whitePieceColor, lightSquareColor);
- bdPieceGC = CreateOneGC(&gc_values, blackPieceColor, darkSquareColor);
- blPieceGC = CreateOneGC(&gc_values, blackPieceColor, lightSquareColor);
- }
-}
-
-void
-loadXIM (XImage *xim, XImage *xmask, char *filename, Pixmap *dest, Pixmap *mask)
-{
- int x, y, w, h, p;
- FILE *fp;
- Pixmap temp;
- XGCValues values;
- GC maskGC;
-
- fp = fopen(filename, "rb");
- if (!fp) {
- fprintf(stderr, _("%s: error loading XIM!\n"), programName);
- exit(1);
- }
-
- w = fgetc(fp);
- h = fgetc(fp);
-
- for (y=0; y<h; ++y) {
- for (x=0; x<h; ++x) {
- p = fgetc(fp);
-
- switch (p) {
- case 0:
- XPutPixel(xim, x, y, blackPieceColor);
- if (xmask)
- XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
- break;
- case 1:
- XPutPixel(xim, x, y, darkSquareColor);
- if (xmask)
- XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
- break;
- case 2:
- XPutPixel(xim, x, y, whitePieceColor);
- if (xmask)
- XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
- break;
- case 3:
- XPutPixel(xim, x, y, lightSquareColor);
- if (xmask)
- XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
- break;
- }
- }
- }
-
- fclose(fp);
-
- /* create Pixmap of piece */
- *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
- w, h, xim->depth);
- XPutImage(xDisplay, *dest, lightSquareGC, xim,
- 0, 0, 0, 0, w, h);
-
- /* create Pixmap of clipmask
- Note: We assume the white/black pieces have the same
- outline, so we make only 6 masks. This is okay
- since the XPM clipmask routines do the same. */
- if (xmask) {
- temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
- w, h, xim->depth);
- XPutImage(xDisplay, temp, lightSquareGC, xmask,
- 0, 0, 0, 0, w, h);
-
- /* now create the 1-bit version */
- *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
- w, h, 1);
-
- values.foreground = 1;
- values.background = 0;
-
- /* Don't use XtGetGC, not read only */
- maskGC = XCreateGC(xDisplay, *mask,
- GCForeground | GCBackground, &values);
- XCopyPlane(xDisplay, temp, *mask, maskGC,
- 0, 0, squareSize, squareSize, 0, 0, 1);
- XFreePixmap(xDisplay, temp);
- }
-}
-
-
-char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
-
-void
-CreateXIMPieces ()
-{
- int piece, kind;
- char buf[MSG_SIZ];
- u_int ss;
- static char *ximkind[] = { "ll", "ld", "dl", "dd" };
- XImage *ximtemp;
-
- ss = squareSize;
-
- /* The XSynchronize calls were copied from CreatePieces.
- Not sure if needed, but can't hurt */
- XSynchronize(xDisplay, True); /* Work-around for xlib/xt
- buffering bug */
-
- /* temp needed by loadXIM() */
- ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
- 0, 0, ss, ss, AllPlanes, XYPixmap);
-
- if (strlen(appData.pixmapDirectory) == 0) {
- useImages = 0;
- } else {
- useImages = 1;
- if (appData.monoMode) {
- DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
- 0, 2);
- ExitEvent(2);
- }
- fprintf(stderr, _("\nLoading XIMs...\n"));
- /* Load pieces */
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
- fprintf(stderr, "%d", piece+1);
- for (kind=0; kind<4; kind++) {
- fprintf(stderr, ".");
- snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
- ExpandPathName(appData.pixmapDirectory),
- piece <= (int) WhiteKing ? "" : "w",
- pieceBitmapNames[piece],
- ximkind[kind], ss);
- ximPieceBitmap[kind][piece] =
- XGetImage(xDisplay, DefaultRootWindow(xDisplay),
- 0, 0, ss, ss, AllPlanes, XYPixmap);
- if (appData.debugMode)
- fprintf(stderr, _("(File:%s:) "), buf);
- loadXIM(ximPieceBitmap[kind][piece],
- ximtemp, buf,
- &(xpmPieceBitmap2[kind][piece]),
- &(ximMaskPm2[piece]));
- if(piece <= (int)WhiteKing)
- xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
- }
- fprintf(stderr," ");
- }
- /* Load light and dark squares */
- /* If the LSQ and DSQ pieces don't exist, we will
- draw them with solid squares. */
- snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
- if (access(buf, 0) != 0) {
- useImageSqs = 0;
- } else {
- useImageSqs = 1;
- fprintf(stderr, _("light square "));
- ximLightSquare=
- XGetImage(xDisplay, DefaultRootWindow(xDisplay),
- 0, 0, ss, ss, AllPlanes, XYPixmap);
- if (appData.debugMode)
- fprintf(stderr, _("(File:%s:) "), buf);
-
- loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
- fprintf(stderr, _("dark square "));
- snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
- ExpandPathName(appData.pixmapDirectory), ss);
- if (appData.debugMode)
- fprintf(stderr, _("(File:%s:) "), buf);
- ximDarkSquare=
- XGetImage(xDisplay, DefaultRootWindow(xDisplay),
- 0, 0, ss, ss, AllPlanes, XYPixmap);
- loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
- xpmJailSquare = xpmLightSquare;
- }
- fprintf(stderr, _("Done.\n"));
- }
- XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
-}
-
-static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
-
-#if HAVE_LIBXPM
-void
-CreateXPMBoard (char *s, int kind)
-{
- XpmAttributes attr;
- attr.valuemask = 0;
- if(!appData.useBitmaps || s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
- if(strstr(s, ".png")) {
- cairo_surface_t *img = cairo_image_surface_create_from_png (s);
- if(img) {
- useTexture |= kind + 1; pngBoardBitmap[kind] = img;
- textureW[kind] = cairo_image_surface_get_width (img);
- textureH[kind] = cairo_image_surface_get_height (img);
- }
- } else
- if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
- useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
- }
-}
-
-void
-FreeXPMPieces ()
-{ // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
- // thisroutine has to be called t free the old piece pixmaps
- int piece, kind;
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
- for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
- if(useImageSqs) {
- XFreePixmap(xDisplay, xpmLightSquare);
- XFreePixmap(xDisplay, xpmDarkSquare);
- }
-}
-
-void
-CreateXPMPieces ()
-{
- int piece, kind, r;
- char buf[MSG_SIZ];
- u_int ss = squareSize;
- XpmAttributes attr;
- static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
- XpmColorSymbol symbols[4];
- static int redo = False;
-
- if(redo) FreeXPMPieces(); else redo = 1;
-
- /* The XSynchronize calls were copied from CreatePieces.
- Not sure if needed, but can't hurt */
- XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
-
- /* Setup translations so piece colors match square colors */
- symbols[0].name = "light_piece";
- symbols[0].value = appData.whitePieceColor;
- symbols[1].name = "dark_piece";
- symbols[1].value = appData.blackPieceColor;
- symbols[2].name = "light_square";
- symbols[2].value = appData.lightSquareColor;
- symbols[3].name = "dark_square";
- symbols[3].value = appData.darkSquareColor;
-
- attr.valuemask = XpmColorSymbols;
- attr.colorsymbols = symbols;
- attr.numsymbols = 4;
-
- if (appData.monoMode) {
- DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
- 0, 2);
- ExitEvent(2);
- }
- if (strlen(appData.pixmapDirectory) == 0) {
- XpmPieces* pieces = builtInXpms;
- useImages = 1;
- /* Load pieces */
- while (pieces->size != squareSize && pieces->size) pieces++;
- if (!pieces->size) {
- fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
- exit(1);
- }
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
- for (kind=0; kind<4; kind++) {
-
- if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
- pieces->xpm[piece][kind],
- &(xpmPieceBitmap2[kind][piece]),
- NULL, &attr)) != 0) {
- fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
- r, buf);
- exit(1);
- }
- if(piece <= (int) WhiteKing)
- xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
- }
- }
- useImageSqs = 0;
- xpmJailSquare = xpmLightSquare;
- } else {
- useImages = 1;
-
- fprintf(stderr, _("\nLoading XPMs...\n"));
-
- /* Load pieces */
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
- fprintf(stderr, "%d ", piece+1);
- for (kind=0; kind<4; kind++) {
- snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
- ExpandPathName(appData.pixmapDirectory),
- piece > (int) WhiteKing ? "w" : "",
- pieceBitmapNames[piece],
- xpmkind[kind], ss);
- if (appData.debugMode) {
- fprintf(stderr, _("(File:%s:) "), buf);
- }
- if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
- &(xpmPieceBitmap2[kind][piece]),
- NULL, &attr)) != 0) {
- if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
- // [HGM] missing: read of unorthodox piece failed; substitute King.
- snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
- ExpandPathName(appData.pixmapDirectory),
- xpmkind[kind], ss);
- if (appData.debugMode) {
- fprintf(stderr, _("(Replace by File:%s:) "), buf);
- }
- r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
- &(xpmPieceBitmap2[kind][piece]),
- NULL, &attr);
- }
- if (r != 0) {
- fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
- r, buf);
- exit(1);
- }
- }
- if(piece <= (int) WhiteKing)
- xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
- }
- }
- /* Load light and dark squares */
- /* If the LSQ and DSQ pieces don't exist, we will
- draw them with solid squares. */
- fprintf(stderr, _("light square "));
- snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
- if (access(buf, 0) != 0) {
- useImageSqs = 0;
- } else {
- useImageSqs = 1;
- if (appData.debugMode)
- fprintf(stderr, _("(File:%s:) "), buf);
-
- if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
- &xpmLightSquare, NULL, &attr)) != 0) {
- fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
- exit(1);
- }
- fprintf(stderr, _("dark square "));
- snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
- ExpandPathName(appData.pixmapDirectory), ss);
- if (appData.debugMode) {
- fprintf(stderr, _("(File:%s:) "), buf);
- }
- if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
- &xpmDarkSquare, NULL, &attr)) != 0) {
- fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
- exit(1);
- }
- }
- xpmJailSquare = xpmLightSquare;
- fprintf(stderr, _("Done.\n"));
- }
- oldVariant = -1; // kludge to force re-makig of animation masks
- XSynchronize(xDisplay, False); /* Work-around for xlib/xt
- buffering bug */
-}
-#endif /* HAVE_LIBXPM */
-
-char *pngPieceNames[] = // must be in same order as internal piece encoding
-{ "Pawn", "Knight", "Bishop", "Rook", "Queen", "Advisor", "Elephant", "Archbishop", "Marshall", "Gold", "Commoner",
- "Canon", "Nightrider", "CrownedBishop", "CrownedRook", "Princess", "Chancellor", "Hawk", "Lance", "Cobra", "Unicorn", "King",
- "GoldKnight", "GoldLance", "GoldPawn", "GoldSilver", NULL
-};
-
-void
-ScaleOnePiece (char *name, int color, int piece)
-{
- int w, h;
- char buf[MSG_SIZ];
- cairo_surface_t *img, *cs;
- cairo_t *cr;
- static cairo_surface_t *pngPieceImages[2][(int)BlackPawn+4]; // png 256 x 256 images
-
- if((img = pngPieceImages[color][piece]) == NULL) { // if PNG file for this piece was not yet read, read it now and store it
- snprintf(buf, MSG_SIZ, "%s/%s%s.png", appData.pngDirectory, color ? "Black" : "White", pngPieceNames[piece]);
- pngPieceImages[color][piece] = img = cairo_image_surface_create_from_png (buf);
- w = cairo_image_surface_get_width (img);
- h = cairo_image_surface_get_height (img);
- if(w != 64 || h != 64) { printf("Bad png size %dx%d in %s\n", w, h, buf); exit(1); }
- }
- // create new bitmap to hold scaled piece image (and remove any old)
- if(pngPieceBitmaps2[color][piece]) cairo_surface_destroy (pngPieceBitmaps2[color][piece]);
- pngPieceBitmaps2[color][piece] = cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
- if(piece <= WhiteKing) pngPieceBitmaps[color][piece] = cs;
- // scaled copying of the raw png image
- cr = cairo_create(cs);
- cairo_scale(cr, squareSize/64., squareSize/64.);
- cairo_set_source_surface (cr, img, 0, 0);
- cairo_paint (cr);
- cairo_destroy (cr);
-}
-
-void
-CreatePNGPieces ()
-{
- int p;
-
- for(p=0; pngPieceNames[p]; p++) {
- ScaleOnePiece(pngPieceNames[p], 0, p);
- ScaleOnePiece(pngPieceNames[p], 1, p);
- }
-}
-
-#if HAVE_LIBXPM
-/* No built-in bitmaps */
-void CreatePieces()
-{
- int piece, kind;
- char buf[MSG_SIZ];
- u_int ss = squareSize;
-
- XSynchronize(xDisplay, True); /* Work-around for xlib/xt
- buffering bug */
-
- for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
- snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
- pieceBitmapNames[piece],
- ss, kind == SOLID ? 's' : 'o');
- ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
- if(piece <= (int)WhiteKing)
- pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
- }
- }
-
- XSynchronize(xDisplay, False); /* Work-around for xlib/xt
- buffering bug */
-}
-#else
-/* With built-in bitmaps */
-void
-CreatePieces ()
-{
- BuiltInBits* bib = builtInBits;
- int piece, kind;
- char buf[MSG_SIZ];
- u_int ss = squareSize;
-
- XSynchronize(xDisplay, True); /* Work-around for xlib/xt
- buffering bug */
-
- while (bib->squareSize != ss && bib->squareSize != 0) bib++;
-
- for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
- for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
- snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
- pieceBitmapNames[piece],
- ss, kind == SOLID ? 's' : 'o');
- ReadBitmap(&pieceBitmap2[kind][piece], buf,
- bib->bits[kind][piece], ss, ss);
- if(piece <= (int)WhiteKing)
- pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
- }
- }
-
- XSynchronize(xDisplay, False); /* Work-around for xlib/xt
- buffering bug */
-}
-#endif
-
-void
ReadBitmap (Pixmap *pm, String name, unsigned char bits[], u_int wreq, u_int hreq)
{
int x_hot, y_hot;
}
void
-CreateGrid ()
-{
- int i, j;
-
- if (lineGap == 0) return;
-
- /* [HR] Split this into 2 loops for non-square boards. */
-
- for (i = 0; i < BOARD_HEIGHT + 1; i++) {
- gridSegments[i].x1 = 0;
- gridSegments[i].x2 =
- lineGap + BOARD_WIDTH * (squareSize + lineGap);
- gridSegments[i].y1 = gridSegments[i].y2
- = lineGap / 2 + (i * (squareSize + lineGap));
- }
-
- for (j = 0; j < BOARD_WIDTH + 1; j++) {
- gridSegments[j + i].y1 = 0;
- gridSegments[j + i].y2 =
- lineGap + BOARD_HEIGHT * (squareSize + lineGap);
- gridSegments[j + i].x1 = gridSegments[j + i].x2
- = lineGap / 2 + (j * (squareSize + lineGap));
- }
-}
-
-void
MarkMenuItem (char *menuRef, int state)
{
MenuItem *item = MenuNameToItem(menuRef);
}
void
-DoDrawBorder (cairo_surface_t *cs, int x, int y, int type)
-{
- cairo_t *cr;
- DrawSeekOpen();
- char *col;
-
- switch(type) {
- case 0: col = "#000000"; break;
- case 1: col = appData.highlightSquareColor; break;
- case 2: col = appData.premoveHighlightColor; break;
- }
- cr = cairo_create(cs);
- cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
- cairo_rectangle(cr, x, y, squareSize+lineGap, squareSize+lineGap);
- SetPen(cr, lineGap, col, 0);
- cairo_stroke(cr);
-}
-
-void
-DrawBorder (int x, int y, int type)
-{
- DoDrawBorder(csBoardWindow, x, y, type);
- DoDrawBorder(csBoardBackup, x, y, type);
-}
-
-static int
-CutOutSquare (int x, int y, int *x0, int *y0, int kind)
-{
- int W = BOARD_WIDTH, H = BOARD_HEIGHT;
- int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
- *x0 = 0; *y0 = 0;
- if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
- if(textureW[kind] < W*squareSize)
- *x0 = (textureW[kind] - squareSize) * nx/(W-1);
- else
- *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
- if(textureH[kind] < H*squareSize)
- *y0 = (textureH[kind] - squareSize) * ny/(H-1);
- else
- *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
- return 1;
-}
-
-void
-DrawLogo (void *handle, void *logo)
-{
- cairo_surface_t *img, *cs;
- cairo_t *cr;
- int w, h;
-
- if(!logo || !handle) return;
- cs = cairo_xlib_surface_create(xDisplay, XtWindow(handle), DefaultVisual(xDisplay, 0), appData.logoSize, appData.logoSize/2);
- img = cairo_image_surface_create_from_png (logo);
- w = cairo_image_surface_get_width (img);
- h = cairo_image_surface_get_height (img);
- cr = cairo_create(cs);
- cairo_scale(cr, (float)appData.logoSize/w, appData.logoSize/(2.*h));
- cairo_set_source_surface (cr, img, 0, 0);
- cairo_paint (cr);
- cairo_destroy (cr);
- cairo_surface_destroy (img);
- cairo_surface_destroy (cs);
-}
-
-static void
-BlankSquare (int x, int y, int color, ChessSquare piece, Drawable dest, int fac)
-{ // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
- int x0, y0;
- if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
- if(pngBoardBitmap[color]) {
- cairo_t *cr;
- if(!fac && !cairoAnimate) return;
- DrawSeekOpen();
- cr = cairo_create (fac ? csBoardWindow : (cairo_surface_t *) dest);
- cairo_set_source_surface (cr, pngBoardBitmap[color], x*fac - x0, y*fac - y0);
- cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
- cairo_rectangle (cr, x*fac, y*fac, squareSize, squareSize);
- cairo_fill (cr);
- cairo_destroy (cr);
- if(fac) {
- cr = cairo_create (csBoardBackup);
- cairo_set_source_surface (cr, pngBoardBitmap[color], x*fac - x0, y*fac - y0);
- cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
- cairo_rectangle (cr, x*fac, y*fac, squareSize, squareSize);
- cairo_fill (cr);
- cairo_destroy (cr);
- }
- } else
- XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
- squareSize, squareSize, x*fac, y*fac);
- } else
- if(csBoardWindow) {
- cairo_t *cr = cairo_create (csBoardWindow);
- char *col;
- switch (color) {
- case 0: col = appData.darkSquareColor; break;
- case 1: col = appData.lightSquareColor; break;
- case 2: col = "#000000"; break;
- }
- SetPen(cr, 2.0, col, 0);
- cairo_rectangle (cr, x, y, squareSize, squareSize);
- cairo_fill (cr);
- cairo_destroy (cr);
- cr = cairo_create (csBoardBackup);
- SetPen(cr, 2.0, col, 0);
- cairo_rectangle (cr, x, y, squareSize, squareSize);
- cairo_fill (cr);
- cairo_destroy (cr);
- } else
- if (useImages && useImageSqs) {
- Pixmap pm;
- switch (color) {
- case 1: /* light */
- pm = xpmLightSquare;
- break;
- case 0: /* dark */
- pm = xpmDarkSquare;
- break;
- case 2: /* neutral */
- default:
- pm = xpmJailSquare; // [HGM] this is wrong, but apparently never used?
- break;
- }
- XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
- squareSize, squareSize, x*fac, y*fac);
- } else {
- GC gc;
- switch (color) {
- case 1: /* light */
- gc = lightSquareGC;
- break;
- case 0: /* dark */
- gc = darkSquareGC;
- break;
- case 2: /* neutral */
- default:
- gc = lineGC;
- break;
- }
- XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
- }
-}
-
-/*
- I split out the routines to draw a piece so that I could
- make a generic flash routine.
-*/
-static void
-monoDrawPiece_1bit (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
- /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
- switch (square_color) {
- case 1: /* light */
- case 2: /* neutral */
- default:
- XCopyArea(xDisplay, (int) piece < (int) BlackPawn
- ? *pieceToOutline(piece)
- : *pieceToSolid(piece),
- dest, bwPieceGC, 0, 0,
- squareSize, squareSize, x, y);
- break;
- case 0: /* dark */
- XCopyArea(xDisplay, (int) piece < (int) BlackPawn
- ? *pieceToSolid(piece)
- : *pieceToOutline(piece),
- dest, wbPieceGC, 0, 0,
- squareSize, squareSize, x, y);
- break;
- }
-}
-
-static void
-monoDrawPiece (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
- switch (square_color) {
- case 1: /* light */
- case 2: /* neutral */
- default:
- XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
- ? *pieceToOutline(piece)
- : *pieceToSolid(piece),
- dest, bwPieceGC, 0, 0,
- squareSize, squareSize, x, y, 1);
- break;
- case 0: /* dark */
- XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
- ? *pieceToSolid(piece)
- : *pieceToOutline(piece),
- dest, wbPieceGC, 0, 0,
- squareSize, squareSize, x, y, 1);
- break;
- }
-}
-
-static void
-colorDrawPiece (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
- if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
- switch (square_color) {
- case 1: /* light */
- XCopyPlane(xDisplay, *pieceToSolid(piece),
- dest, (int) piece < (int) BlackPawn
- ? wlPieceGC : blPieceGC, 0, 0,
- squareSize, squareSize, x, y, 1);
- break;
- case 0: /* dark */
- XCopyPlane(xDisplay, *pieceToSolid(piece),
- dest, (int) piece < (int) BlackPawn
- ? wdPieceGC : bdPieceGC, 0, 0,
- squareSize, squareSize, x, y, 1);
- break;
- case 2: /* neutral */
- default:
- break; // should never contain pieces
- }
-}
-
-static void
-colorDrawPieceImage (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
- int kind, p = piece;
-
- switch (square_color) {
- case 1: /* light */
- case 2: /* neutral */
- default:
- if ((int)piece < (int) BlackPawn) {
- kind = 0;
- } else {
- kind = 2;
- piece -= BlackPawn;
- }
- break;
- case 0: /* dark */
- if ((int)piece < (int) BlackPawn) {
- kind = 1;
- } else {
- kind = 3;
- piece -= BlackPawn;
- }
- break;
- }
- if(appData.upsideDown && flipView) { kind ^= 2; p += p < BlackPawn ? BlackPawn : -BlackPawn; }// swap white and black pieces
- if(useTexture & square_color+1) {
- BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
- XSetClipMask(xDisplay, wlPieceGC, xpmMask[p]);
- XSetClipOrigin(xDisplay, wlPieceGC, x, y);
- XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, squareSize, squareSize, x, y);
- XSetClipMask(xDisplay, wlPieceGC, None);
- XSetClipOrigin(xDisplay, wlPieceGC, 0, 0);
- } else
- XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
- dest, wlPieceGC, 0, 0,
- squareSize, squareSize, x, y);
-}
-
-static void
-pngDrawPiece (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
- int kind, p = piece;
- cairo_t *cr;
-
- if ((int)piece < (int) BlackPawn) {
- kind = 0;
- } else {
- kind = 1;
- piece -= BlackPawn;
- }
- if(appData.upsideDown && flipView) { p += p < BlackPawn ? BlackPawn : -BlackPawn; }// swap white and black pieces
- BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
- DrawSeekOpen();
- cr = cairo_create (csBoardWindow);
- cairo_set_source_surface (cr, pngPieceBitmaps[kind][piece], x, y);
- cairo_paint(cr);
- cairo_destroy (cr);
- cr = cairo_create (csBoardBackup);
- cairo_set_source_surface (cr, pngPieceBitmaps[kind][piece], x, y);
- cairo_paint(cr);
- cairo_destroy (cr);
-}
-
-typedef void (*DrawFunc)();
-
-DrawFunc
-ChooseDrawFunc ()
-{
- if (appData.monoMode) {
- if (DefaultDepth(xDisplay, xScreen) == 1) {
- return monoDrawPiece_1bit;
- } else {
- return monoDrawPiece;
- }
- } else if(appData.pngDirectory[0]) {
- return pngDrawPiece;
- } else {
- if (useImages)
- return colorDrawPieceImage;
- else
- return colorDrawPiece;
- }
-}
-
-void
-DoDrawDot (int marker, int x, int y, int r, cairo_surface_t *cs)
-{
- cairo_t *cr;
- DrawSeekOpen();
- cr = cairo_create(cs);
- cairo_arc(cr, x+r/2, y+r/2, r/2, 0.0, 2*M_PI);
- if(appData.monoMode) {
- SetPen(cr, 2, marker == 2 ? "#000000" : "#FFFFFF", 0);
- cairo_stroke_preserve(cr);
- SetPen(cr, 2, marker == 2 ? "#FFFFFF" : "#000000", 0);
- } else {
- SetPen(cr, 2, marker == 2 ? "#FF0000" : "#FFFF00", 0);
- }
- cairo_fill(cr);
- cairo_stroke(cr);
-
- cairo_destroy(cr);
-}
-
-void
-DrawDot (int marker, int x, int y, int r)
-{
- DoDrawDot(marker, x, y, r, csBoardWindow);
- DoDrawDot(marker, x, y, r, csBoardBackup);
-}
-
-void
-DrawOneSquare (int x, int y, ChessSquare piece, int square_color, int marker, char *string, int align)
-{ // basic front-end board-draw function: takes care of everything that can be in square:
- // piece, background, coordinate/count, marker dot
- int direction, font_ascent, font_descent;
- XCharStruct overall;
- DrawFunc drawfunc;
-
- if (piece == EmptySquare) {
- BlankSquare(x, y, square_color, piece, xBoardWindow, 1);
- } else {
- drawfunc = ChooseDrawFunc();
- drawfunc(piece, square_color, x, y, xBoardWindow);
- }
-
- if(align) { // square carries inscription (coord or piece count)
- int xx = x, yy = y;
- GC hGC = align < 3 ? coordGC : countGC;
- // first calculate where it goes
- XTextExtents(countFontStruct, string, 1, &direction,
- &font_ascent, &font_descent, &overall);
- if (align == 1) {
- xx += squareSize - overall.width - 2;
- yy += squareSize - font_descent - 1;
- } else if (align == 2) {
- xx += 2, yy += font_ascent + 1;
- } else if (align == 3) {
- xx += squareSize - overall.width - 2;
- yy += font_ascent + 1;
- } else if (align == 4) {
- xx += 2, yy += font_ascent + 1;
- }
- // then draw it
- if (appData.monoMode) {
- XDrawImageString(xDisplay, xBoardWindow, hGC, xx, yy, string, 1);
- } else {
- if(*appData.pngDirectory) {
- cairo_t *cr = cairo_create (csBoardWindow);
- cairo_select_font_face (cr, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_set_font_size (cr, squareSize/4);
-
- cairo_move_to (cr, xx-1, yy);
- if(align < 3) cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
- else cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
- cairo_show_text (cr, string);
- cairo_destroy (cr);
- cr = cairo_create (csBoardBackup);
- cairo_select_font_face (cr, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_set_font_size (cr, squareSize/4);
-
- cairo_move_to (cr, xx-1, yy);
- if(align < 3) cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
- else cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
- cairo_show_text (cr, string);
- cairo_destroy (cr);
- } else
- XDrawString(xDisplay, xBoardWindow, hGC, xx, yy, string, 1);
- }
- }
-
- if(marker) { // print fat marker dot, if requested
- DrawDot(marker, x + squareSize/4, y+squareSize/4, squareSize/2);
- }
-}
-
-void
FlashDelay (int flash_delay)
{
XSync(xDisplay, False);
DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other
}
-// [HGM] seekgraph: some low-level drawing routines (by JC, mostly)
-
-float
-Color (char *col, int n)
-{
- int c;
- sscanf(col, "#%x", &c);
- c = c >> 4*n & 255;
- return c/255.;
-}
-
-void
-SetPen (cairo_t *cr, float w, char *col, int dash)
-{
- static const double dotted[] = {4.0, 4.0};
- static int len = sizeof(dotted) / sizeof(dotted[0]);
- cairo_set_line_width (cr, w);
- cairo_set_source_rgba (cr, Color(col, 4), Color(col, 2), Color(col, 0), 1.0);
- if(dash) cairo_set_dash (cr, dotted, len, 0.0);
-}
-
-void DrawSeekAxis( int x, int y, int xTo, int yTo )
-{
- cairo_t *cr;
-
- /* get a cairo_t */
- cr = cairo_create (csBoardWindow);
-
- cairo_move_to (cr, x, y);
- cairo_line_to(cr, xTo, yTo );
-
- SetPen(cr, 2, "#000000", 0);
- cairo_stroke(cr);
-
- /* free memory */
- cairo_destroy (cr);
-}
-
-void DrawSeekBackground( int left, int top, int right, int bottom )
-{
- cairo_t *cr = cairo_create (csBoardWindow);
-
- cairo_rectangle (cr, left, top, right-left, bottom-top);
-
- cairo_set_source_rgba(cr, 0.8, 0.8, 0.4,1.0);
- cairo_fill(cr);
-
- /* free memory */
- cairo_destroy (cr);
-}
-
-void DrawSeekText(char *buf, int x, int y)
-{
- cairo_t *cr = cairo_create (csBoardWindow);
-
- cairo_select_font_face (cr, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
-
- cairo_set_font_size (cr, 12.0);
-
- cairo_move_to (cr, x, y+4);
- cairo_set_source_rgba(cr, 0, 0, 0,1.0);
- cairo_show_text( cr, buf);
-
- /* free memory */
- cairo_destroy (cr);
-}
-
-void DrawSeekDot(int x, int y, int colorNr)
-{
- cairo_t *cr = cairo_create (csBoardWindow);
- int square = colorNr & 0x80;
- colorNr &= 0x7F;
-
- if(square)
- cairo_rectangle (cr, x-squareSize/9, y-squareSize/9, 2*(squareSize/9), 2*(squareSize/9));
- else
- cairo_arc(cr, x, y, squareSize/9, 0.0, 2*M_PI);
-
- SetPen(cr, 2, "#000000", 0);
- cairo_stroke_preserve(cr);
- switch (colorNr) {
- case 0: cairo_set_source_rgba(cr, 1.0, 0, 0,1.0); break;
- case 1: cairo_set_source_rgba (cr, 0.0, 0.7, 0.2, 1.0); break;
- default: cairo_set_source_rgba (cr, 1.0, 1.0, 0.0, 1.0); break;
- }
- cairo_fill(cr);
-
- /* free memory */
- cairo_destroy (cr);
-}
-
-void
-DrawSeekOpen ()
-{
- int boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
- int boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
- if(!csBoardWindow) {
- csBoardWindow = cairo_xlib_surface_create(xDisplay, xBoardWindow, DefaultVisual(xDisplay, 0), boardWidth, boardHeight);
- csBoardBackup = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, boardWidth, boardHeight);
- }
-}
-
-void
-DrawSeekClose ()
-{
-}
-
-void
-DoDrawGrid(cairo_surface_t *cs)
-{
- /* draws a grid starting around Nx, Ny squares starting at x,y */
- int i;
- cairo_t *cr;
-
- DrawSeekOpen();
- /* get a cairo_t */
- cr = cairo_create (cs);
-
- cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
- SetPen(cr, lineGap, "#000000", 0);
-
- /* lines in X */
- for (i = 0; i < BOARD_WIDTH + BOARD_HEIGHT + 2; i++)
- {
- cairo_move_to (cr, gridSegments[i].x1, gridSegments[i].y1);
- cairo_line_to (cr, gridSegments[i].x2, gridSegments[i].y2);
- cairo_stroke (cr);
- }
-
- /* free memory */
- cairo_destroy (cr);
-
- return;
-}
-
-void
-DrawGrid()
-{
- DoDrawGrid(csBoardWindow);
- DoDrawGrid(csBoardBackup);
-}
-
/*
* event handler for redrawing the board
*/
is->xid = 0;
}
-/**** Animation code by Hugh Fisher, DCS, ANU. ****/
-
-/* Masks for XPM pieces. Black and white pieces can have
- different shapes, but in the interest of retaining my
- sanity pieces must have the same outline on both light
- and dark squares, and all pieces must use the same
- background square colors/images. */
-
-static int xpmDone = 0;
-static Pixmap animBufs[3*NrOfAnims]; // newBuf, saveBuf
-static GC animGCs[3*NrOfAnims]; // blitGC, pieceGC, outlineGC;
-static cairo_surface_t *c_animBufs[3*NrOfAnims]; // newBuf, saveBuf
-
-static void
-CreateAnimMasks (int pieceDepth)
-{
- ChessSquare piece;
- Pixmap buf;
- GC bufGC, maskGC;
- int kind, n;
- unsigned long plane;
- XGCValues values;
-
- /* Need a bitmap just to get a GC with right depth */
- buf = XCreatePixmap(xDisplay, xBoardWindow,
- 8, 8, 1);
- values.foreground = 1;
- values.background = 0;
- /* Don't use XtGetGC, not read only */
- maskGC = XCreateGC(xDisplay, buf,
- GCForeground | GCBackground, &values);
- XFreePixmap(xDisplay, buf);
-
- buf = XCreatePixmap(xDisplay, xBoardWindow,
- squareSize, squareSize, pieceDepth);
- values.foreground = XBlackPixel(xDisplay, xScreen);
- values.background = XWhitePixel(xDisplay, xScreen);
- bufGC = XCreateGC(xDisplay, buf,
- GCForeground | GCBackground, &values);
-
- for (piece = WhitePawn; piece <= BlackKing; piece++) {
- /* Begin with empty mask */
- if(!xpmDone) // [HGM] pieces: keep using existing
- xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
- squareSize, squareSize, 1);
- XSetFunction(xDisplay, maskGC, GXclear);
- XFillRectangle(xDisplay, xpmMask[piece], maskGC,
- 0, 0, squareSize, squareSize);
-
- /* Take a copy of the piece */
- if (White(piece))
- kind = 0;
- else
- kind = 2;
- XSetFunction(xDisplay, bufGC, GXcopy);
- XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
- buf, bufGC,
- 0, 0, squareSize, squareSize, 0, 0);
-
- /* XOR the background (light) over the piece */
- XSetFunction(xDisplay, bufGC, GXxor);
- if (useImageSqs)
- XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
- 0, 0, squareSize, squareSize, 0, 0);
- else {
- XSetForeground(xDisplay, bufGC, lightSquareColor);
- XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
- }
-
- /* We now have an inverted piece image with the background
- erased. Construct mask by just selecting all the non-zero
- pixels - no need to reconstruct the original image. */
- XSetFunction(xDisplay, maskGC, GXor);
- plane = 1;
- /* Might be quicker to download an XImage and create bitmap
- data from it rather than this N copies per piece, but it
- only takes a fraction of a second and there is a much
- longer delay for loading the pieces. */
- for (n = 0; n < pieceDepth; n ++) {
- XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
- 0, 0, squareSize, squareSize,
- 0, 0, plane);
- plane = plane << 1;
- }
- }
- /* Clean up */
- XFreePixmap(xDisplay, buf);
- XFreeGC(xDisplay, bufGC);
- XFreeGC(xDisplay, maskGC);
-}
-
-static void
-InitAnimState (AnimNr anr, XWindowAttributes *info)
-{
- XtGCMask mask;
- XGCValues values;
-
- if(cairoAnimate) {
- DrawSeekOpen(); // set cs to board widget
- if(c_animBufs[anr]) cairo_surface_destroy (c_animBufs[anr]);
- if(c_animBufs[anr+2]) cairo_surface_destroy (c_animBufs[anr+2]);
- c_animBufs[anr+4] = csBoardWindow;
- c_animBufs[anr+2] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
- c_animBufs[anr] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
- }
-
- /* Each buffer is square size, same depth as window */
- animBufs[anr+4] = xBoardWindow;
- animBufs[anr+2] = XCreatePixmap(xDisplay, xBoardWindow,
- squareSize, squareSize, info->depth);
- animBufs[anr] = XCreatePixmap(xDisplay, xBoardWindow,
- squareSize, squareSize, info->depth);
-
- /* Create a plain GC for blitting */
- mask = GCForeground | GCBackground | GCFunction |
- GCPlaneMask | GCGraphicsExposures;
- values.foreground = XBlackPixel(xDisplay, xScreen);
- values.background = XWhitePixel(xDisplay, xScreen);
- values.function = GXcopy;
- values.plane_mask = AllPlanes;
- values.graphics_exposures = False;
- animGCs[anr] = XCreateGC(xDisplay, xBoardWindow, mask, &values);
-
- /* Piece will be copied from an existing context at
- the start of each new animation/drag. */
- animGCs[anr+2] = XCreateGC(xDisplay, xBoardWindow, 0, &values);
-
- /* Outline will be a read-only copy of an existing */
- animGCs[anr+4] = None;
-}
-
-void
-CreateAnimVars ()
-{
- XWindowAttributes info;
-
- if (!cairoAnimate && xpmDone && gameInfo.variant == oldVariant) return;
- if(xpmDone) oldVariant = gameInfo.variant; // first time pieces might not be created yet
- XGetWindowAttributes(xDisplay, xBoardWindow, &info);
-
- InitAnimState(Game, &info);
- InitAnimState(Player, &info);
-
- /* For XPM pieces, we need bitmaps to use as masks. */
- if (useImages & !xpmDone)
- CreateAnimMasks(info.depth), xpmDone = 1;
-}
-
#ifndef HAVE_USLEEP
static Boolean frameWaiting;
#endif
static void
-SelectGCMask (ChessSquare piece, GC *clip, GC *outline, Pixmap *mask)
-{
- GC source;
-
- /* Bitmap for piece being moved. */
- if (appData.monoMode) {
- *mask = *pieceToSolid(piece);
- } else if (useImages) {
-#if HAVE_LIBXPM
- *mask = xpmMask[piece];
-#else
- *mask = ximMaskPm[piece];
-#endif
- } else {
- *mask = *pieceToSolid(piece);
- }
-
- /* GC for piece being moved. Square color doesn't matter, but
- since it gets modified we make a copy of the original. */
- if (White(piece)) {
- if (appData.monoMode)
- source = bwPieceGC;
- else
- source = wlPieceGC;
- } else {
- if (appData.monoMode)
- source = wbPieceGC;
- else
- source = blPieceGC;
- }
- XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
-
- /* Outline only used in mono mode and is not modified */
- if (White(piece))
- *outline = bwPieceGC;
- else
- *outline = wbPieceGC;
-}
-
-static void
-OverlayPiece (ChessSquare piece, GC clip, GC outline, Drawable dest)
-{
- int kind;
-
- if (!useImages) {
- /* Draw solid rectangle which will be clipped to shape of piece */
- XFillRectangle(xDisplay, dest, clip,
- 0, 0, squareSize, squareSize);
- if (appData.monoMode)
- /* Also draw outline in contrasting color for black
- on black / white on white cases */
- XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
- 0, 0, squareSize, squareSize, 0, 0, 1);
- } else {
- /* Copy the piece */
- if (White(piece))
- kind = 0;
- else
- kind = 2;
- if(appData.upsideDown && flipView) kind ^= 2;
- XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
- dest, clip,
- 0, 0, squareSize, squareSize,
- 0, 0);
- }
-}
-
-static void
-CairoOverlayPiece (ChessSquare piece, cairo_surface_t *dest)
-{
- static cairo_t *pieceSource;
- pieceSource = cairo_create (dest);
- cairo_set_source_surface (pieceSource, pngPieceBitmaps[!White(piece)][piece % BlackPawn], 0, 0);
- if(doubleClick) cairo_paint_with_alpha (pieceSource, 0.6);
- else cairo_paint(pieceSource);
- cairo_destroy (pieceSource);
-}
-
-void
-InsertPiece (AnimNr anr, ChessSquare piece)
-{
- if(cairoAnimate) {
- CairoOverlayPiece(piece, c_animBufs[anr]);
- } else
- OverlayPiece(piece, animGCs[anr+2], animGCs[anr+4], animBufs[anr]);
-}
-
-void
-DrawBlank (AnimNr anr, int x, int y, int startColor)
-{
- if(cairoAnimate)
- BlankSquare(x, y, startColor, EmptySquare, (Drawable) c_animBufs[anr+2], 0);
- else
- BlankSquare(x, y, startColor, EmptySquare, animBufs[anr+2], 0);
-}
-
-void CopyRectangle (AnimNr anr, int srcBuf, int destBuf,
- int srcX, int srcY, int width, int height, int destX, int destY)
-{
- if(cairoAnimate) {
- cairo_t *cr;// = cairo_create (c_animBufs[anr+destBuf]);
- cr = cairo_create (c_animBufs[anr+destBuf]);
- if(c_animBufs[anr+srcBuf] == csBoardWindow)
- cairo_set_source_surface (cr, csBoardBackup, destX - srcX, destY - srcY);
- else
- cairo_set_source_surface (cr, c_animBufs[anr+srcBuf], destX - srcX, destY - srcY);
- cairo_rectangle (cr, destX, destY, width, height);
- cairo_fill (cr);
- cairo_destroy (cr);
- if(c_animBufs[anr+destBuf] == csBoardWindow) {
- cr = cairo_create (csBoardBackup); // also draw to backup
- cairo_set_source_surface (cr, c_animBufs[anr+srcBuf], destX - srcX, destY - srcY);
- cairo_rectangle (cr, destX, destY, width, height);
- cairo_fill (cr);
- cairo_destroy (cr);
- }
- } else
- XCopyArea(xDisplay, animBufs[anr+srcBuf], animBufs[anr+destBuf], animGCs[anr],
- srcX, srcY, width, height, destX, destY);
-}
-
-void
-SetDragPiece (AnimNr anr, ChessSquare piece)
-{
- Pixmap mask;
- if(cairoAnimate) return;
- /* The piece will be drawn using its own bitmap as a matte */
- SelectGCMask(piece, &animGCs[anr+2], &animGCs[anr+4], &mask);
- XSetClipMask(xDisplay, animGCs[anr+2], mask);
-}
-
-/* [AS] Arrow highlighting support */
-
-void
-DoDrawPolygon (cairo_surface_t *cs, Pnt arrow[], int nr)
-{
- cairo_t *cr;
- int i;
- cr = cairo_create (cs);
- cairo_move_to (cr, arrow[nr-1].x, arrow[nr-1].y);
- for (i=0;i<nr;i++) {
- cairo_line_to(cr, arrow[i].x, arrow[i].y);
- }
- if(appData.monoMode) { // should we always outline arrow?
- cairo_line_to(cr, arrow[0].x, arrow[0].y);
- SetPen(cr, 2, "#000000", 0);
- cairo_stroke_preserve(cr);
- }
- SetPen(cr, 2, appData.highlightSquareColor, 0);
- cairo_fill(cr);
-
- /* free memory */
- cairo_destroy (cr);
-}
-
-void
-DrawPolygon (Pnt arrow[], int nr)
-{
- DoDrawPolygon(csBoardWindow, arrow, nr);
- DoDrawPolygon(csBoardBackup, arrow, nr);
-}
-
-static void
LoadLogo (ChessProgramState *cps, int n, Boolean ics)
{
char buf[MSG_SIZ], *logoName = buf;