diff --git a/extensions/fablabchemnitz_render_sudoku/fablabchemnitz_render_sudoku.inx b/extensions/fablabchemnitz_render_sudoku/fablabchemnitz_render_sudoku.inx new file mode 100644 index 00000000..c3a46026 --- /dev/null +++ b/extensions/fablabchemnitz_render_sudoku/fablabchemnitz_render_sudoku.inx @@ -0,0 +1,47 @@ + + + Sudoku + fablabchemnitz.de.sudoku + + + + + + + + + + Layout parameters: + 1 + 1 + Puzzle Dimensions: + + + + + + + + 6 + 1 + + + 255 + 4243148799 + 2290779647 + 3298820351 + 1923076095 + + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz_render_sudoku/fablabchemnitz_render_sudoku.py b/extensions/fablabchemnitz_render_sudoku/fablabchemnitz_render_sudoku.py new file mode 100644 index 00000000..8bf8f12e --- /dev/null +++ b/extensions/fablabchemnitz_render_sudoku/fablabchemnitz_render_sudoku.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +''' +render_sudoku.py +A sudoku generator plugin for Inkscape, but also can be used as a standalone +command line application. + +Copyright (C) 2011 Chris Savery + +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 2 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, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +''' + +__version__ = "0.1" + +import inkex +import subprocess +from lxml import etree +from inkex import Color + +class SVGSudoku (inkex.Effect): + + def __init__(self): + inkex.Effect.__init__(self) + self.arg_parser.add_argument("--tab") + self.arg_parser.add_argument("--difficulty",default="mixed", help='How difficult to make puzzles.') + self.arg_parser.add_argument("--rows", type=int, default=1, help='Number of puzzle rows.') + self.arg_parser.add_argument("--cols", type=int, default=1, help='Number of puzzle columns.') + self.arg_parser.add_argument("--puzzle_size", type=int, default=6, help='The width & height of each puzzle.') + self.arg_parser.add_argument("--puzzle_gap", type=int, default=1, help='The space between puzzles.') + self.arg_parser.add_argument("--color_text", type=Color, default=255, help='Color for given numbers.') + self.arg_parser.add_argument("--color_bkgnd", type=Color, default=4243148799, help='Color for the puzzle background.') + self.arg_parser.add_argument("--color_puzzle",type=Color, default=2290779647, help='Border color for the puzzles.') + self.arg_parser.add_argument("--color_boxes", type=Color, default=3298820351, help='Border color for puzzle boxes.') + self.arg_parser.add_argument("--color_cells", type=Color, default=1923076095, help='Border color for the puzzle cells.') + self.arg_parser.add_argument("--units", help="The unit of the dimensions") + + def draw_grid(self, g_puz, x, y): + bkgnd_style = {'stroke':'none', 'stroke-width':'2', 'fill':self.options.color_bkgnd } + puzzle_style = {'stroke':self.options.color_puzzle, 'stroke-width':'2', 'fill':'none' } + boxes_style = {'stroke':self.options.color_boxes, 'stroke-width':'2', 'fill':'none' } + cells_style = {'stroke':self.options.color_cells, 'stroke-width':'1', 'fill':'none' } + g = etree.SubElement(g_puz, 'g') + self.draw_rect(g, bkgnd_style, self.left+x, self.top+y, self.size, self.size) + self.draw_rect(g, cells_style, self.left+x+self.size/9, self.top+y, self.size/9, self.size) + self.draw_rect(g, cells_style, self.left+x+self.size/3+self.size/9, self.top+y, self.size/9, self.size) + self.draw_rect(g, cells_style, self.left+x+2*self.size/3+self.size/9, self.top+y, self.size/9, self.size) + self.draw_rect(g, cells_style, self.left+x, self.top+y+self.size/9, self.size, self.size/9) + self.draw_rect(g, cells_style, self.left+x, self.top+y+self.size/3+self.size/9, self.size, self.size/9) + self.draw_rect(g, cells_style, self.left+x, self.top+y+2*self.size/3+self.size/9, self.size, self.size/9) + self.draw_rect(g, boxes_style, self.left+x+self.size/3, self.top+y, self.size/3, self.size) + self.draw_rect(g, boxes_style, self.left+x, self.top+y+self.size/3, self.size, self.size/3) + self.draw_rect(g, puzzle_style, self.left+x, self.top+y, self.size, self.size) + + def draw_rect(self, g, style, x, y, w, h): + attribs = {'style':str(inkex.Style(style)), 'x':str(x), 'y':str(y), 'height':str(h), 'width':str(w) } + etree.SubElement(g, inkex.addNS('rect','svg'), attribs) + + def fill_puzzle(self, g_puz, x, y, data): + cellsize = self.size / 9 + txtsize = self.size / 12 + offset = (cellsize + txtsize)/2.25 + g = etree.SubElement(g_puz, 'g') + text_style = {'font-size':str(txtsize), + 'fill':self.options.color_text, + 'font-family':'arial', + 'text-anchor':'middle', 'text-align':'center' } + #inkex.utils.debug(len(data)) + for n in range(len(data)): + #inkex.utils.debug(str(n)) + #inkex.utils.debug("data["+str(n)+"]="+str(data[n])) + if str(data[n]) in "123456789": + attribs = {'style': str(inkex.Style(text_style)), + 'x': str(self.left + x + n%9 * cellsize + cellsize/2 ), 'y': str(self.top + y + n//9 * cellsize + offset ) } + etree.SubElement(g, 'text', attribs).text = str(data[n]) + + + def effect(self): + args = ["qqwing", "--one-line", "--generate", str(self.options.rows * self.options.cols)] + if self.options.difficulty != 'mixed': + args.extend(["--difficulty", self.options.difficulty]) + data = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].splitlines() + #inkex.utils.debug(data) + + parent = self.document.getroot() + self.doc_w = self.svg.unittouu(parent.get('width')) + self.doc_h = self.svg.unittouu(parent.get('height')) + self.size = self.svg.unittouu(str(self.options.puzzle_size) + self.options.units) + self.gap = self.svg.unittouu(str(self.options.puzzle_gap) + self.options.units) + self.shift = self.size + self.gap + self.left = (self.doc_w - (self.options.cols * self.shift - self.gap))/2 + self.top = (self.doc_h - (self.options.rows * self.shift - self.gap))/2 + self.sudoku_g = etree.SubElement(parent, 'g', {'id':'sudoku'}) + for row in range(0, self.options.rows): + for col in range(0, self.options.cols): + g = etree.SubElement(self.sudoku_g, 'g', {'id':'puzzle_'+str(col)+str(row)}) + self.draw_grid(g, col*self.shift, row*self.shift) + self.fill_puzzle(g, col*self.shift, row*self.shift, data[col+row*self.options.cols].decode('UTF-8')) + +SVGSudoku().run() diff --git a/extensions/fablabchemnitz_render_sudoku/qqwing b/extensions/fablabchemnitz_render_sudoku/qqwing new file mode 100644 index 00000000..f76e0c27 --- /dev/null +++ b/extensions/fablabchemnitz_render_sudoku/qqwing @@ -0,0 +1,210 @@ +#! /bin/bash + +# qqwing - temporary wrapper script for .libs/qqwing +# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1.10ubuntu1 +# +# The qqwing program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.2' + notinst_deplibs=' ./libqqwing.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ./libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "qqwing:qqwing:${LINENO}: libtool wrapper (GNU libtool) 2.4.2 Debian-2.4.2-1.10ubuntu1" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "qqwing:qqwing:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "qqwing:qqwing:${LINENO}: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='qqwing' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to LD_LIBRARY_PATH + LD_LIBRARY_PATH="/home/tomate/qqwing-1.3.4/.libs:$LD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` + + export LD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/extensions/fablabchemnitz_render_sudoku/qqwing.exe b/extensions/fablabchemnitz_render_sudoku/qqwing.exe new file mode 100644 index 00000000..b39426ad Binary files /dev/null and b/extensions/fablabchemnitz_render_sudoku/qqwing.exe differ