Commit d6d365ea authored by Vivien Kraus's avatar Vivien Kraus

The renderer program renders a game

parent 92b0ed04
Pipeline #96949 passed with stages
in 3 minutes and 56 seconds
......@@ -86,7 +86,7 @@ CLEANFILES =
AM_DISTCHECK_CONFIGURE_FLAGS = \
--enable-silent-rules=yes \
--disable-introspection \
--disable-vapigen
--disable-vala
AM_CPPFLAGS = \
-DLOCALEDIR="\"$(localedir)\"" \
-DSYSCONFDIR="\"$(sysconfdir)\"" \
......@@ -97,6 +97,7 @@ AM_CFLAGS =
AM_YFLAGS = -d
AM_LIBS =
AM_LDADD =
AM_VALAFLAGS =
# Texinfo -> html flags, overriden in doc/Makefile.am
AM_MAKEINFOHTMLFLAGS =
TESTS =
......
......@@ -9,6 +9,7 @@ cd build/
../tarot-$VERSION/configure \
--enable-silent-rules=yes \
--enable-valgrind=yes \
--without-cairo \
|| (cat config.log; exit 1)
make -j 16 check || exit 1
make distclean || exit 1
......@@ -10,6 +10,7 @@ cd build/
--prefix="$PWD/../public" \
--enable-silent-rules=yes \
--enable-valgrind=yes \
--without-cairo \
CFLAGS="-g -fprofile-arcs -ftest-coverage" \
|| (cat config.log; exit 1)
make -j 16 install-html || exit 1
......
......@@ -64,6 +64,16 @@ AS_IF([test "x$with_gobject" != "xno"], [
])
])
AM_CONDITIONAL([WITH_GOBJECT], [test "x$WITH_GOBJECT" != "xno"])
AC_ARG_WITH([cairo], AS_HELP_STRING([--without-cairo], [Do not build the Cairo bindings]))
WITH_CAIRO="no"
AS_IF([test "x$with_cairo" != "xno"], [
PKG_CHECK_MODULES([CAIRO], [cairo cairo-png], [
WITH_CAIRO="yes"
], [
AC_MSG_ERROR([Cairo was not found. Please use --without-cairo.])
])
])
AM_CONDITIONAL([WITH_CAIRO], [test "x$WITH_CAIRO" != "xno"])
AC_SEARCH_LIBS([atan2], [m])
AC_SEARCH_LIBS([sin], [m])
AC_SEARCH_LIBS([cos], [m])
......
......@@ -18,22 +18,30 @@
info_TEXINFOS += %reldir%/tarot.texi
dist_chelp_DATA += %reldir%/tarot.xml
tarotfiguresdir = $(infodir)/tarot-figures
dist_tarotfigures_DATA = \
%reldir%/tarot-figures/example.png
tarotfigureshtmldir = $(htmldir)/tarot.html/tarot-figures
dist_tarotfigureshtml_DATA = %reldir%/tarot-figures/example.png
%canon_reldir%_tarot_TEXINFOS = \
%reldir%/fdl.texi \
%reldir%/invoke-tarot-body.texi
%reldir%/invoke-tarot-body.texi \
%reldir%/invoke-tarot-render-body.texi
AM_MAKEINFOHTMLFLAGS += --css-include $(srcdir)/%reldir%/style.css
EXTRA_DIST += \
%reldir%/ChangeLog \
%reldir%/tarot.org \
%reldir%/invoke-tarot.texi \
%reldir%/setup.el
%reldir%/invoke-tarot-render.texi \
%reldir%/setup.el \
%reldir%/tarot-figures/example.eps
dist_html_DATA += \
%reldir%/style.css
install-html-local: install-dist_htmlDATA
install-html-local: install-dist_htmlDATA install-dist_tarotfigureshtmlDATA
TANGLED += %reldir%/generate-manual src/main.c src/tarot-opts.def
......@@ -64,7 +72,14 @@ $(TANGLED): %reldir%/tarot.org %reldir%/setup.el .version
$(AM_V_GEN) tail -n +3 \
$(srcdir)/%reldir%/invoke-tarot.texi \
> $(srcdir)/%reldir%/invoke-tarot-body.texi
%reldir%/tarot.texi: $(TANGLED) %reldir%/invoke-tarot-body.texi
%reldir%/invoke-tarot-render-body.texi: %reldir%/invoke-tarot-render.texi
$(AM_V_GEN) tail -n +3 \
$(srcdir)/%reldir%/invoke-tarot-render.texi \
> $(srcdir)/%reldir%/invoke-tarot-render-body.texi
%reldir%/tarot.texi: $(TANGLED) \
%reldir%/invoke-tarot-body.texi \
%reldir%/invoke-tarot-render-body.texi \
$(dist_tarotfigures_DATA)
$(MAKE) $(AM_MAKEFLAGS) src/libtarot.la
$(AM_V_GEN) $(srcdir)/%reldir%/generate-manual
......@@ -72,3 +87,10 @@ $(TANGLED): %reldir%/tarot.org %reldir%/setup.el .version
$(AM_V_MAKEINFO) $(MAKEINFO) --docbook -I %reldir% -I $(srcdir)/%reldir% \
-o $(srcdir)/%reldir%/tarot.xml \
$(srcdir)/%reldir%/tarot.texi
%reldir%/tarot-figures/example.png: games/example.xml.png
$(MKDIR_P) $(srcdir)/%reldir%/tarot-figures
$(AM_V_GEN) cp $(srcdir)/games/example.xml.png $(srcdir)/%reldir%/tarot-figures/example.png
%reldir%/tarot-figures/example.eps: %reldir%/tarot-figures/example.png
$(AM_V_GEN) $(CONVERT) $(srcdir)/%reldir%/tarot-figures/example.png $(srcdir)/%reldir%/tarot-figures/example.eps
......@@ -742,6 +742,15 @@ the owners for the trumps, then the owner of the excuse.
play 11T
status with imputation
#+END_EXAMPLE
* Rendering a game
The program =tarot-render= is able to load a game and render it as a
PNG file. It serves as a demonstration for the cairo painting of the
cards.
#+attr_texinfo: :width 1in :alt The representation of a game in the GUI
[[file:tarot-figures/example.png]]
** Invoking tarot-render
#+texinfo: @include invoke-tarot-render-body.texi
* The libtarot API
In this section, we are going to describe the entrypoints of the
libtarot API.
......@@ -2048,8 +2057,12 @@ Of course, we need some vala code to actually do the job.
private static string read_whole_file (GLib.FileStream file) {
char[] ret = new char[0];
while (!file.eof ()) {
ret += (char) file.getc ();
char c = (char) file.getc ();
if (!file.eof ()) {
ret += c;
}
}
ret += '\0';
return (string) ret;
}
private static void print_status (Tarot.Game game) {
......
......@@ -17,6 +17,13 @@
# <http://www.gnu.org/licenses/>.
gamesdir = $(pkgdatadir)/games
dist_games_DATA = %reldir%/example.xml
EXTRA_DIST += %reldir%/example.xml.png
%reldir%/example.xml.png: %reldir%/example.xml
$(MAKE) $(AM_MAKEFLAGS) src/cairo/tarot-render
$(AM_V_GEN) src/cairo/tarot-render %reldir%/example.xml
include %reldir%/fail/Makefile.am
include %reldir%/pass/Makefile.am
<?xml version="1.0"?>
<game>
<setup n-players="5" with-call="yes"/>
<deal to="P5">
<card card="10H"/>
<card card="JH"/>
<card card="CH"/>
<card card="QH"/>
<card card="KH"/>
<card card="11T"/>
<card card="12T"/>
<card card="13T"/>
<card card="14T"/>
<card card="15T"/>
<card card="16T"/>
<card card="17T"/>
<card card="18T"/>
<card card="19T"/>
<card card="EXC"/>
</deal>
<bid bid="take"/>
<bid bid="pass"/>
<bid bid="pass"/>
<bid bid="pass"/>
<bid bid="pass"/>
<decl slam="no"/>
<decl slam="no"/>
<decl slam="no"/>
<decl slam="no"/>
<decl slam="yes"/>
<call card="KC"/>
<dog>
<card card="6H"/>
<card card="7H"/>
<card card="8H"/>
</dog>
<discard/>
<card card="19T"/>
<card card="10T"/>
<card card="20T"/>
<card card="21T"/>
<card card="6C"/>
<card card="AC"/>
<card card="7C"/>
<card card="11T"/>
<card card="9T"/>
</game>
......@@ -7,6 +7,8 @@
- Call: KC
- Dog: 6H, 7H, 8H
- Discard: 7H, 7D, 8S
- Double handful of P1: 1T, 2T, 3T, 4T, 5T, 6T, 7T, 8T, 9T, 10T
- Double handful of P5: 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T, EXC
+---------+---------+---------+---------+---------+
| * P1 | P2 | P3 | P4 * | P5 |
+---------+---------+---------+---------+---------+
......@@ -28,6 +30,8 @@ P1 may play a card from 5C
- Call: KC
- Dog: 6H, 7H, 8H
- Discard: AH, 2H, 3H
- Double handful of P1: 1T, 2T, 3T, 4T, 5T, 6T, 7T, 8T, 9T, 10T
- Double handful of P5: 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T, EXC
+---------+---------+---------+---------+---------+
| * P1 | P2 * | P3 | P4 | P5 |
+---------+---------+---------+---------+---------+
......@@ -58,6 +62,8 @@ P1 may play a card from 5C
- Call: KC
- Dog: 6H, 7H, 8H
- Discard: AH, 2H, 3H
- Double handful of P1: 1T, 2T, 3T, 4T, 5T, 6T, 7T, 8T, 9T, 10T
- Double handful of P5: 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T, EXC
+---------+---------+---------+---------+---------+
| * P1 | P2 * | P3 | P4 | P5 |
+---------+---------+---------+---------+---------+
......
......@@ -7,6 +7,8 @@
- Call: KC
- Dog: 6H, 7H, 8H
- Discard: AH, 2H, 3H
- Double handful of P1: 1T, 2T, 3T, 4T, 5T, 6T, 7T, 8T, 9T, 10T
- Double handful of P5: 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T, EXC
+---------+---------+---------+---------+---------+
| * P1 | P2 * | P3 | P4 | P5 |
+---------+---------+---------+---------+---------+
......@@ -37,6 +39,8 @@
- Call: KC
- Dog: 6H, 7H, 8H
- Discard: AH, 2H, 3H
- Double handful of P1: 1T, 2T, 3T, 4T, 5T, 6T, 7T, 8T, 9T, 10T
- Double handful of P5: 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T, EXC
+---------+---------+---------+---------+---------+
| * P1 | P2 * | P3 | P4 | P5 |
+---------+---------+---------+---------+---------+
......
......@@ -7,6 +7,7 @@
- Call: KC
- Dog: 7H, 8H, 9H
- Discard: AH, 2H, 3H
- Double handful of P5: 1T, 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T
+---------+---------+---------+---------+---------+
| * P1 | P2 * | P3 | P4 | P5 |
+---------+---------+---------+---------+---------+
......@@ -37,6 +38,7 @@
- Call: KC
- Dog: 7H, 8H, 9H
- Discard: AH, 2H, 3H
- Double handful of P5: 1T, 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T
+---------+---------+---------+---------+---------+
| * P1 | P2 * | P3 | P4 | P5 |
+---------+---------+---------+---------+---------+
......
......@@ -7,6 +7,8 @@
- Call: KC
- Dog: 6H, 7H, 8H
- Discard: AH, 2H, 3H
- Double handful of P1: 1T, 2T, 3T, 4T, 5T, 6T, 7T, 8T, 9T, 10T
- Double handful of P5: 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T, EXC
+---------+---------+---------+---------+---------+
| * P1 | P2 * | P3 | P4 | P5 |
+---------+---------+---------+---------+---------+
......@@ -37,6 +39,8 @@
- Call: KC
- Dog: 6H, 7H, 8H
- Discard: AH, 2H, 3H
- Double handful of P1: 1T, 2T, 3T, 4T, 5T, 6T, 7T, 8T, 9T, 10T
- Double handful of P5: 11T, 12T, 13T, 14T, 15T, 16T, 17T, 18T, 19T, EXC
+---------+---------+---------+---------+---------+
| * P1 | P2 * | P3 | P4 | P5 |
+---------+---------+---------+---------+---------+
......
......@@ -28,6 +28,7 @@ dist_vapi_DATA = %reldir%/tarot-1.0.vapi
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --warn-all
VAPIGEN_VAPIS =
EXTRA_DIST += %reldir%/tarot-1.0.vapi.updated
LIBTAROT_VERSION_INFO = 0:0:0
......@@ -143,6 +144,8 @@ endif # not HAVE_INTROSPECTION
if ENABLE_VAPIGEN
%reldir%/tarot-1.0.vapi: %reldir%/Tarot-1.0.gir
%reldir%/tarot-1.0.vapi.updated: %reldir%/tarot-1.0.vapi %reldir%/Tarot-1.0.gir
$(AM_V_GEN) touch $(srcdir)/%reldir%/tarot-1.0.vapi.updated && touch %reldir%/tarot-1.0.vapi
%canon_reldir%_tarot_1_0_vapi_FILES = %reldir%/Tarot-1.0.gir
%canon_reldir%_tarot_1_0_vapi_METADATADIRS = $(srcdir)
VAPIGEN_VAPIS += %reldir%/tarot-1.0.vapi
......@@ -151,6 +154,9 @@ else #not ENABLE_VAPIGEN
%reldir%/tarot-1.0.vapi: %reldir%/Tarot-1.0.gir
@echo "The Vala bindings need to be rebuilt."
false
%reldir%/tarot-1.0.vapi.updated: %reldir%/tarot-1.0.vapi %reldir%/Tarot-1.0.gir
@echo "The Vala bindings need to be rebuilt."
false
endif #not ENABLE_VAPIGEN
$(%canon_reldir%_tarot_OBJECTS): %reldir%/tarot-opts.h
......@@ -177,3 +183,4 @@ include %reldir%/parser/Makefile.am
include %reldir%/cli/Makefile.am
include %reldir%/xml/Makefile.am
include %reldir%/layout/Makefile.am
include %reldir%/cairo/Makefile.am
# Makefile.am
#
# Copyright (C) 2017, 2018 Vivien Kraus <vivien@planete-kraus.eu>
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
# <http://www.gnu.org/licenses/>.
CARDPAINTER_SOURCE_FILES = \
%reldir%/card_painter.vala \
%reldir%/card_painter_default.vala
EXTRA_DIST += %reldir%/tarot_render.vala \
%reldir%/tarot-render-opts.def \
%reldir%/tarot-render-opts.c \
%reldir%/tarot-render-opts.h \
%reldir%/tarot-render-main.c \
%reldir%/tarot-render.1
if WITH_CAIRO
bin_PROGRAMS += %reldir%/tarot-render
dist_man_MANS += %reldir%/tarot-render.6
%canon_reldir%_tarot_render_SOURCES = \
$(CARDPAINTER_SOURCE_FILES) \
%reldir%/tarot_render.vala \
src/tarot-1.0.vapi \
%reldir%/tarot-render-opts.c \
%reldir%/tarot-render-opts.h \
%reldir%/tarot-render-main.c
%canon_reldir%_tarot_render_CFLAGS = \
$(AM_CFLAGS) \
$(GOBJECT_CFLAGS) \
$(CAIRO_CFLAGS) \
$(LIBOPTS_CFLAGS) \
-w
%canon_reldir%_tarot_render_CXXFLAGS = \
$(AM_CXXFLAGS)
%canon_reldir%_tarot_render_CPPFLAGS = \
$(AM_CPPFLAGS)
%canon_reldir%_tarot_render_LDFLAGS = \
$(AM_LDADD)
%canon_reldir%_tarot_render_LDADD = \
src/libtarot.la \
src/libtarot-gobject.la \
lib-program/libgnulibrary.la \
$(LIBOPTS_LDADD) \
$(GOBJECT_LIBS) \
$(CAIRO_LIBS)
$(%canon_reldir%_tarot_render_OBJECTS): %reldir%/tarot-render-opts.h
AM_VALAFLAGS += --pkg cairo
endif # WITH_CAIRO
%reldir%/tarot-render-opts.h: %reldir%/tarot-render-opts.c
%reldir%/tarot-render-opts.c: %reldir%/tarot-render-opts.def
$(AM_V_GEN) (cd $(srcdir)/%reldir% && $(AUTOGEN) --writable tarot-render-opts.def)
%reldir%/tarot-render.1: %reldir%/tarot-render-opts.def
$(AM_V_GEN) (cd $(srcdir)/%reldir% && $(AUTOGEN) --writable -Tagman-cmd.tpl -btarot tarot-render-opts.def)
%reldir%/tarot-render.6: %reldir%/tarot-render.1
$(AM_V_GEN) (cp $(srcdir)/%reldir%/tarot-render.1 $(srcdir)/%reldir%/tarot-render.6)
doc/invoke-tarot-render.texi: %reldir%/tarot-render-opts.def
$(AM_V_GEN) (cd $(srcdir)/doc && $(AUTOGEN) --writable -Tagtexi-cmd.tpl $(abs_top_srcdir)/%reldir%/tarot-render-opts.def)
INDENTED += %reldir%/tarot-render-main.c
AM_CPPFLAGS += -I $(srcdir)/%reldir% -I %reldir%
// file card_painter.vala
//
// Copyright (C) 2017, 2018 Vivien Kraus <vivien@planete-kraus.eu>
//
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// <http://www.gnu.org/licenses/>.
using Cairo;
namespace Tarot {
public interface CardPainter: GLib.Object {
/**
* Paint a card to the cairo context. Usually this is simply
* printing a pixmap of width given by the property
* card_width. The card 78 should be painted as a card back.
* The cards above 78 should not be painted.
*/
public abstract void paint_card (Tarot.Card card, Cairo.Context context);
public abstract double card_width { get; }
public abstract double card_height { get; }
public void paint_game (double view_w,
double view_h,
Tarot.CardArray my_cards,
Tarot.CardArray[] cards_adversaries,
Tarot.CardArray trick,
Tarot.CardArray foreground,
Cairo.Context context) {
size_t n_my_cards = my_cards.size ();
size_t n_adversaries = cards_adversaries.length;
var n_adv_cards = new size_t[n_adversaries];
size_t n_total_adv_cards = 0;
var all_cards = new Tarot.Card[0];
size_t n = 0;
for (int i = 0; i < n_my_cards; i++) {
all_cards += my_cards[i];
}
for (int i = 0; i < cards_adversaries.length; i++) {
n = cards_adversaries[i].size ();
for (int j = 0; j < n; j++) {
all_cards += cards_adversaries[i][j];
}
n_adv_cards[i] = cards_adversaries[i].size ();
n_total_adv_cards += n_adv_cards[i];
}
n = trick.size ();
for (int i = 0; i < n; i++) {
all_cards += trick[i];
}
assert (trick.size () == 1 + n_adversaries);
n = foreground.size ();
for (int i = 0; i < n; i++) {
all_cards += foreground[i];
}
size_t n_foreground = foreground.size ();
size_t total_n_cards = n_my_cards + n_total_adv_cards
+ n_adversaries + 1 + n_foreground;
var positions = new Tarot.Position[total_n_cards];
if (Tarot.layout_position (view_w, view_h, card_width, card_height, n_my_cards,
n_adv_cards, n_foreground, positions) != total_n_cards) {
GLib.Process.abort ();
}
context.save ();
var order = new uint[total_n_cards];
for (uint i = 0; i < total_n_cards; i++) {
order[i] = i;
}
GLib.qsort_with_data<uint> (order, sizeof (uint), (ia, ib) => {
return (positions[ia].z < positions[ib].z ? -1 : 1);
});
for (int i = 0; i < total_n_cards; i++) {
var p = positions[i];
var c = all_cards[i];
context.save ();
context.translate (p.x, p.y);
context.rotate (p.angle);
context.scale (p.scale, p.scale);
paint_card (c, context);
context.restore ();
}
}
}
}
\ No newline at end of file
// file card_painter_default.vala
//
// Copyright (C) 2017, 2018 Vivien Kraus <vivien@planete-kraus.eu>
//
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// <http://www.gnu.org/licenses/>.
using Cairo;
namespace Tarot {
public class DefaultCardPainter: GLib.Object, Tarot.CardPainter {
private double _card_width = 32;
private double _card_height = 48;
public double card_width {
get { return _card_width; }
}
public double card_height {
get { return _card_height; }
}
public double border_width = 1;
private void paint_border (Cairo.Context context) {
context.translate (- card_width / 2, - card_height / 2);
context.rectangle (0, 0, card_width, card_height);
context.set_line_width (border_width);
context.set_source_rgb (1, 1, 1);
context.fill ();
context.move_to (0, 0);
context.line_to (0, card_height);
context.line_to (card_width, card_height);
context.line_to (card_width, 0);
context.line_to (0, 0);
context.set_source_rgb (0, 0, 0);
context.stroke ();
}
private void paint_back (Cairo.Context context) {
paint_border (context);
context.rectangle (0, 0, card_width, card_height);
context.set_source_rgb (0.25, 0.25, 0.25);
context.fill ();
}
public void paint_card (Tarot.Card card, Cairo.Context context) {
// This is debugging information in case you want to debug
// an empty deck; it prints the location of the card
// centers in pixels on the device.
// double x = 0, y = 0;
// context.user_to_device (ref x, ref y);
// stderr.printf ("Printing card %s at (%f, %f)\n", card.to_string (), x, y);
if (card < 78) {
paint_border (context);
// ...
} else if (card == 78) {
paint_back (context);
}
}
}
}
\ No newline at end of file
/**
* file main.c
*
* Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <tarot.h>
#include <tarot-gobject.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "tarot-render-opts.h"
int tarot_render (const char *input_filename, int default_view,
TarotPlayer view, size_t width, size_t height);
int
tarot_run (const char *filename)
{
return tarot_render (filename,
!(HAVE_OPT (AS_PLAYER) && ENABLED_OPT (AS_PLAYER)),
OPT_ARG (AS_PLAYER),
OPT_ARG (WIDTH), OPT_ARG (HEIGHT));
}
Autogen Definitions options;
prog-name = tarot-render;
prog-title = "The Amazing Rules Of TAROT -- Rendering";
long-opts;
gnu-usage; /* GNU style preferred to default */
config-header = "config.h";
argument = "[FILES...]";
main = {
main-type = for-each;
handler-proc = "tarot_run";
};
flag = {
name = as-player;
value = p;
descrip = "View the game as this player";
disable = not;
doc = "Set the player from which we view the cards. If not present or disabled, then use the player that were dealt cards in the game. If the game has a deal for all players, then you have to set this option.";
};
flag = {
name = width;
value = w;
arg-default = 640;
arg-type = number;
descrip = "Width of the output file";
doc = "Set the width for the output image.";
};
flag = {
name = height;
value = h;
arg-default = 480;
arg-type = number;
descrip = "Height of the output file";
doc = "Set the height for the output image.";
};
\ No newline at end of file
// file tarot_render.vala
//
// Copyright (C) 2017, 2018 Vivien Kraus <vivien@planete-kraus.eu>
//
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// <http://www.gnu.org/licenses/>.
namespace Tarot {
private static int read_whole_file (string filename, out string contents) {
var file = GLib.FileStream.open (filename, "r");
contents = "";
if (file == null) {
stderr.printf ("ERROR: could not load file %s\n", filename);
return 1;
} else {
char[] ret = new char[0];
while (!file.eof ()) {
char c = (char) file.getc ();
if (!file.eof ()) {
ret += c;
}
}
ret += '\0';
contents = (string) ret;
return 0;
}
}
public static int render (string input_filename,
bool default_view,
Tarot.Player view,
size_t width,
size_t height) {
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, (int) width, (int) height);
var context = new Cairo.Context (surface);
context.translate (width / 2.0, height / 2.0);
context.scale (1, -1);
var game = new Tarot.Game.alloc ();
string contents;
if (read_whole_file (input_filename, out contents) != 0) {
return 1;
}
if (game.load_from_xml (contents) != 0) {
stderr.printf ("ERROR: This game is not valid.\n");
return 1;
}
size_t n_players = game.n_players ();
if (default_view) {
default_view = false;
var my_deal = new Tarot.CardArray.alloc ();
if (game.get_deal (out view, my_deal) != 0) {
stderr.printf ("ERROR: This game does not have a default player.\n");
return 1;
}
}
var my_cards = new Tarot.CardArray.alloc ();
var cards_adversaries = new Tarot.CardArray[n_players - 1];
var cards_trick = new Tarot.CardArray.alloc ();
var current_trick = game.current_trick ();
var n_tricks = game.n_tricks ();
var foreground = new Tarot.CardArray.alloc ();
Tarot.Card trick_card = 78;
bool cnf, cno, cnu;
if (cards_trick.resize (n_players) != 0) {
GLib.Process.abort ();
}
for (size_t i = 0; i < n_players; i++) {
cards_trick[i] = 79; // Not painted
}
if (game.get_cards (view, my_cards) != 0) {
// Fill with backs
size_t n = game.count_cards (view);
if (my_cards.resize (n) != 0) {
GLib.Process.abort ();
}
for (int i = 0; i < n; i++) {
my_cards[i] = 78;
}
}
if (current_trick < n_tricks
&& game.get_trick_card_of (current_trick, view, out trick_card,
out cnf, out cno, out cnu) == 0) {
cards_trick[0] = trick_card;
}
for (int i = 0; i + 1 < n_players; i++) {
var cards = new Tarot.CardArray.alloc ();
Tarot.Player p = (Tarot.Player) (((size_t) (view + i + 1)) % n_players);
if (game.get_cards (p, cards) != 0) {
// Fill with backs
size_t n = game.count_cards (p);
if (cards.resize (n) != 0) {