forked from len0rd/rockbox
puzzles: resync with upstream 262f709.
This is the first resync with a fully unmodified upstream repo. This includes a new scanline polygon renderer in the upstream puzzles distribution. This allows us to get rid of the monstrosity of a polygon renderer we had been shipping in rockbox.c. Change-Id: I23628c74bb5ff7a9e7932bf16d68a1c867c49969
This commit is contained in:
parent
903e8c5b32
commit
ea0e3704a8
15 changed files with 700 additions and 683 deletions
|
@ -4,11 +4,6 @@ Introduction
|
||||||
This is the readme for the Rockbox port of Simon Tatham's Portable
|
This is the readme for the Rockbox port of Simon Tatham's Portable
|
||||||
Puzzle Collection.
|
Puzzle Collection.
|
||||||
|
|
||||||
The upstream version used is subject to change, as it should be
|
|
||||||
relatively trivial to update it to a newer version. Simply copying the
|
|
||||||
upstream repo's contents into src/ and running genhelp.sh ought to do
|
|
||||||
it (watch out for API changes, though!).
|
|
||||||
|
|
||||||
Source structure
|
Source structure
|
||||||
================
|
================
|
||||||
|
|
||||||
|
@ -44,16 +39,8 @@ to Untangle and Palisade). These divergent changes complicated
|
||||||
maintenance of this port, as merge conflicts often arose when upstream
|
maintenance of this port, as merge conflicts often arose when upstream
|
||||||
changes to these games conflicted with our changes. To remedy this, I
|
changes to these games conflicted with our changes. To remedy this, I
|
||||||
sent most of these patches back upstream in summer 2024, and since
|
sent most of these patches back upstream in summer 2024, and since
|
||||||
then, Simon has merged the majority of them into his tree.
|
then, Simon has merged them into his repo. We are now able to run with
|
||||||
|
a fully unmodified puzzles source tree.
|
||||||
This leaves us with a very small set of places where our branch of the
|
|
||||||
puzzles source diverges from Simon's. That branch lives here:
|
|
||||||
|
|
||||||
https://github.com/built1n/puzzles/tree/rockbox-devel
|
|
||||||
|
|
||||||
Notably, there are several hacks which work around Rockbox's lack of a
|
|
||||||
proper polygon filling algorithm. Eliminating this deficiency would
|
|
||||||
enable us to use a totally unmodified upstream source tree.
|
|
||||||
|
|
||||||
Maintenance
|
Maintenance
|
||||||
===========
|
===========
|
||||||
|
@ -62,7 +49,7 @@ Simon's upstream tree sees continued development. The port is
|
||||||
structured so that integrating new upstream versions is
|
structured so that integrating new upstream versions is
|
||||||
straightforward: all the upstream sources live in the src/
|
straightforward: all the upstream sources live in the src/
|
||||||
subdirectory; all of the Rockbox frontend lives in the root
|
subdirectory; all of the Rockbox frontend lives in the root
|
||||||
apps/pluginspuzzles/ directory.
|
apps/plugins/puzzles/ directory.
|
||||||
|
|
||||||
The `resync.sh' shell script automates the resyncing process. It
|
The `resync.sh' shell script automates the resyncing process. It
|
||||||
copies the upstream sources (point it to a local copy of the
|
copies the upstream sources (point it to a local copy of the
|
||||||
|
@ -77,9 +64,7 @@ The LZ4 library and GCC are necessary as well.
|
||||||
Wishlist
|
Wishlist
|
||||||
========
|
========
|
||||||
|
|
||||||
- Proper polygon filling algorithm. The current algorithm is a hack
|
- Nothing!
|
||||||
that uses overdrawn triangles. This will enable us to eliminate the
|
|
||||||
last of the Rockbox-specific modifications.
|
|
||||||
|
|
||||||
Kudos to Simon (duh), and Frank, for telling me about it.
|
Kudos to Simon (duh), and Frank, for telling me about it.
|
||||||
|
|
||||||
|
@ -120,3 +105,6 @@ Implement user preferences menu. Introduced "Mosaic".
|
||||||
|
|
||||||
August 2024: Resync to ee5e327 (branched from Simon's
|
August 2024: Resync to ee5e327 (branched from Simon's
|
||||||
1c1899e). Changes default Map stipple size to "Small".
|
1c1899e). Changes default Map stipple size to "Small".
|
||||||
|
|
||||||
|
August 2024: Resync to Simon's 262f709 (unmodified). Uses new scanline
|
||||||
|
polygon filling algorithm. Updates drawing API.
|
||||||
|
|
|
@ -7,6 +7,7 @@ lz4tiny.c
|
||||||
/* puzzles core sources */
|
/* puzzles core sources */
|
||||||
src/combi.c
|
src/combi.c
|
||||||
src/divvy.c
|
src/divvy.c
|
||||||
|
src/draw-poly.c
|
||||||
src/drawing.c
|
src/drawing.c
|
||||||
src/dsf.c
|
src/dsf.c
|
||||||
src/findloop.c
|
src/findloop.c
|
||||||
|
|
|
@ -6,148 +6,148 @@
|
||||||
|
|
||||||
struct style_text help_text_style[] = {
|
struct style_text help_text_style[] = {
|
||||||
{ 0, TEXT_CENTER | C_RED },
|
{ 0, TEXT_CENTER | C_RED },
|
||||||
{ 88, TEXT_CENTER | C_RED },
|
{ 87, TEXT_CENTER | C_RED },
|
||||||
{ 209, TEXT_CENTER | C_RED },
|
{ 208, TEXT_CENTER | C_RED },
|
||||||
|
{ 225, TEXT_UNDERLINE },
|
||||||
{ 226, TEXT_UNDERLINE },
|
{ 226, TEXT_UNDERLINE },
|
||||||
{ 227, TEXT_UNDERLINE },
|
{ 237, TEXT_UNDERLINE },
|
||||||
{ 238, TEXT_UNDERLINE },
|
{ 269, TEXT_UNDERLINE },
|
||||||
{ 270, TEXT_UNDERLINE },
|
|
||||||
LAST_STYLE_ITEM
|
LAST_STYLE_ITEM
|
||||||
};
|
};
|
||||||
|
|
||||||
/* orig 1917 comp 1289 ratio 0.672405 level 10 saved 628 */
|
/* orig 1881 comp 1282 ratio 0.681552 level 10 saved 599 */
|
||||||
const char help_text[] = {
|
const char help_text[] = {
|
||||||
0xf0, 0x02, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20,
|
0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20,
|
||||||
0x34, 0x30, 0x3a, 0x20, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x06,
|
0x34, 0x30, 0x3a, 0x20, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x73,
|
||||||
0x00, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x00, 0x2d, 0x01, 0x00,
|
0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x19, 0x00, 0x00, 0x00,
|
||||||
0x04, 0xf0, 0x19, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00,
|
0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69,
|
||||||
0x61, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00,
|
0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64,
|
||||||
0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00,
|
0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65,
|
||||||
0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73,
|
0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x11, 0x00, 0x51,
|
||||||
0x6f, 0x6d, 0x65, 0x11, 0x00, 0x51, 0x77, 0x68, 0x69, 0x63,
|
0x77, 0x68, 0x69, 0x63, 0x68, 0x2b, 0x00, 0xf1, 0x04, 0x66,
|
||||||
0x68, 0x2b, 0x00, 0xd0, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64,
|
0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x77, 0x69, 0x74, 0x68,
|
||||||
0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x74, 0x68, 0x00, 0x21,
|
0x00, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x00, 0x74, 0x62, 0x00,
|
||||||
0x00, 0x74, 0x68, 0x00, 0x11, 0x2e, 0x4d, 0x00, 0xf2, 0x05,
|
0x11, 0x2e, 0x4d, 0x00, 0xf2, 0x05, 0x6e, 0x65, 0x65, 0x64,
|
||||||
0x6e, 0x65, 0x65, 0x64, 0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f,
|
0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
|
||||||
0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x00, 0x74, 0x68, 0x65,
|
0x74, 0x65, 0x00, 0x74, 0x68, 0x65, 0x21, 0x00, 0x70, 0x00,
|
||||||
0x21, 0x00, 0x70, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x41,
|
0x66, 0x72, 0x6f, 0x6d, 0x00, 0x41, 0x1d, 0x00, 0x91, 0x42,
|
||||||
0x1d, 0x00, 0x91, 0x42, 0x00, 0x73, 0x6f, 0x00, 0x74, 0x68,
|
0x00, 0x73, 0x6f, 0x00, 0x74, 0x68, 0x61, 0x74, 0x1e, 0x00,
|
||||||
0x61, 0x74, 0x1e, 0x00, 0xf1, 0x06, 0x72, 0x6f, 0x77, 0x73,
|
0xf1, 0x06, 0x72, 0x6f, 0x77, 0x73, 0x00, 0x61, 0x6e, 0x64,
|
||||||
0x00, 0x61, 0x6e, 0x64, 0x00, 0x63, 0x6f, 0x6c, 0x75, 0x6d,
|
0x00, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x00, 0x63,
|
||||||
0x6e, 0x73, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x58, 0x00, 0xe0,
|
0x6f, 0x6e, 0x74, 0x58, 0x00, 0xe0, 0x68, 0x65, 0x00, 0x73,
|
||||||
0x68, 0x65, 0x00, 0x73, 0x61, 0x6d, 0x65, 0x00, 0x6e, 0x75,
|
0x61, 0x6d, 0x65, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
|
||||||
0x6d, 0x62, 0x65, 0x72, 0x87, 0x00, 0x02, 0x4a, 0x00, 0xb1,
|
0x87, 0x00, 0x02, 0x4a, 0x00, 0xb1, 0x73, 0x65, 0x67, 0x6d,
|
||||||
0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x61,
|
0x65, 0x6e, 0x74, 0x73, 0x00, 0x61, 0x73, 0x93, 0x00, 0xa3,
|
||||||
0x73, 0x93, 0x00, 0xa3, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61,
|
0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x00,
|
||||||
0x74, 0x65, 0x64, 0x00, 0x36, 0x00, 0x50, 0x63, 0x6c, 0x75,
|
0x36, 0x00, 0x50, 0x63, 0x6c, 0x75, 0x65, 0x73, 0x6a, 0x00,
|
||||||
0x65, 0x73, 0x6a, 0x00, 0x01, 0x7e, 0x00, 0x21, 0x6f, 0x70,
|
0x01, 0x7e, 0x00, 0x21, 0x6f, 0x70, 0x5f, 0x00, 0x51, 0x72,
|
||||||
0x5f, 0x00, 0x51, 0x72, 0x69, 0x67, 0x68, 0x74, 0x45, 0x00,
|
0x69, 0x67, 0x68, 0x74, 0x45, 0x00, 0x21, 0x68, 0x65, 0xe9,
|
||||||
0x21, 0x68, 0x65, 0xe9, 0x00, 0x91, 0x2e, 0x00, 0x00, 0x00,
|
0x00, 0x91, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x68, 0x65, 0x72,
|
||||||
0x54, 0x68, 0x65, 0x72, 0x65, 0x45, 0x00, 0x60, 0x6f, 0x6e,
|
0x65, 0x45, 0x00, 0x60, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x73,
|
||||||
0x6c, 0x79, 0x00, 0x73, 0xd2, 0x00, 0x00, 0x27, 0x00, 0x00,
|
0xd2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x31, 0x00, 0xf1, 0x08,
|
||||||
0x31, 0x00, 0xf1, 0x08, 0x39, 0x30, 0x00, 0x64, 0x65, 0x67,
|
0x39, 0x30, 0x00, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x00,
|
||||||
0x72, 0x65, 0x65, 0x00, 0x63, 0x75, 0x72, 0x76, 0x65, 0x64,
|
0x63, 0x75, 0x72, 0x76, 0x65, 0x64, 0x00, 0x72, 0x61, 0x69,
|
||||||
0x00, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x2c, 0x1c, 0x00, 0x06,
|
0x6c, 0x73, 0x2c, 0x1c, 0x00, 0x06, 0xd7, 0x00, 0xf1, 0x05,
|
||||||
0xd7, 0x00, 0xf1, 0x05, 0x6d, 0x61, 0x79, 0x00, 0x6e, 0x6f,
|
0x6d, 0x61, 0x79, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x63, 0x72,
|
||||||
0x74, 0x00, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x00, 0x69, 0x74,
|
0x6f, 0x73, 0x73, 0x00, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66,
|
||||||
0x73, 0x65, 0x6c, 0x66, 0x5a, 0x00, 0x01, 0x1c, 0x01, 0x02,
|
0x5a, 0x00, 0x01, 0x16, 0x01, 0x32, 0x00, 0x77, 0x61, 0xd1,
|
||||||
0x84, 0x01, 0x32, 0x00, 0x77, 0x61, 0xd7, 0x00, 0x40, 0x72,
|
0x00, 0x40, 0x72, 0x69, 0x62, 0x75, 0xa2, 0x00, 0x01, 0x95,
|
||||||
0x69, 0x62, 0x75, 0xa8, 0x00, 0x01, 0x9b, 0x00, 0x20, 0x69,
|
0x00, 0x20, 0x69, 0x73, 0xed, 0x00, 0xf0, 0x08, 0x6c, 0x65,
|
||||||
0x73, 0xf3, 0x00, 0xf0, 0x08, 0x6c, 0x65, 0x63, 0x74, 0x69,
|
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a,
|
||||||
0x6f, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65,
|
0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65,
|
||||||
0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x43, 0x00,
|
0x79, 0x3d, 0x00, 0x44, 0x34, 0x30, 0x2e, 0x31, 0xba, 0x01,
|
||||||
0x4a, 0x34, 0x30, 0x2e, 0x31, 0xcc, 0x01, 0x01, 0x44, 0x00,
|
0x01, 0x3e, 0x00, 0xf4, 0x1c, 0x6f, 0x6c, 0x73, 0x20, 0x00,
|
||||||
0xf4, 0x1c, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x4c,
|
0x00, 0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69,
|
||||||
0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x69,
|
0x63, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x6f, 0x6e, 0x00, 0x61,
|
||||||
0x6e, 0x67, 0x00, 0x6f, 0x6e, 0x00, 0x61, 0x6e, 0x00, 0x65,
|
0x6e, 0x00, 0x65, 0x64, 0x67, 0x65, 0x00, 0x62, 0x65, 0x74,
|
||||||
0x64, 0x67, 0x65, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65,
|
0x77, 0x65, 0x65, 0x6e, 0x00, 0x74, 0x77, 0x6f, 0xbd, 0x01,
|
||||||
0x6e, 0x00, 0x74, 0x77, 0x6f, 0xc9, 0x01, 0x7a, 0x00, 0x61,
|
0x7a, 0x00, 0x61, 0x64, 0x64, 0x73, 0x00, 0x61, 0x34, 0x01,
|
||||||
0x64, 0x64, 0x73, 0x00, 0x61, 0x40, 0x01, 0x06, 0x29, 0x00,
|
0x06, 0x29, 0x00, 0x28, 0x68, 0x65, 0x2d, 0x00, 0x30, 0x2e,
|
||||||
0x28, 0x68, 0x65, 0x2d, 0x00, 0x30, 0x2e, 0x00, 0x52, 0x04,
|
0x00, 0x52, 0xf8, 0x00, 0x0f, 0x5c, 0x00, 0x02, 0x03, 0x48,
|
||||||
0x01, 0x0f, 0x5c, 0x00, 0x02, 0x03, 0x48, 0x00, 0x02, 0xed,
|
0x00, 0x02, 0xe1, 0x00, 0x12, 0x6f, 0x3b, 0x00, 0x00, 0x19,
|
||||||
0x00, 0x12, 0x6f, 0x3b, 0x00, 0x00, 0x19, 0x00, 0x14, 0x2c,
|
0x00, 0x14, 0x2c, 0x79, 0x01, 0x00, 0x30, 0x00, 0x23, 0x6e,
|
||||||
0x85, 0x01, 0x00, 0x30, 0x00, 0x23, 0x6e, 0x6f, 0x69, 0x00,
|
0x6f, 0x69, 0x00, 0xa1, 0x69, 0x73, 0x00, 0x70, 0x6f, 0x73,
|
||||||
0xa1, 0x69, 0x73, 0x00, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62,
|
0x73, 0x69, 0x62, 0x6c, 0xfd, 0x01, 0x3d, 0x72, 0x65, 0x2e,
|
||||||
0x6c, 0x09, 0x02, 0x3d, 0x72, 0x65, 0x2e, 0xb8, 0x00, 0x10,
|
0xb8, 0x00, 0x10, 0x69, 0x6b, 0x02, 0x02, 0x79, 0x00, 0x05,
|
||||||
0x69, 0x77, 0x02, 0x02, 0x79, 0x00, 0x05, 0x5d, 0x00, 0x54,
|
0x5d, 0x00, 0x54, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x51, 0x00,
|
||||||
0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x51, 0x00, 0x70, 0x6f, 0x72,
|
0x70, 0x6f, 0x72, 0x00, 0x73, 0x68, 0x6f, 0x77, 0x2c, 0x00,
|
||||||
0x00, 0x73, 0x68, 0x6f, 0x77, 0x2c, 0x00, 0x01, 0x33, 0x02,
|
0x01, 0x27, 0x02, 0x82, 0x79, 0x6f, 0x75, 0x00, 0x6b, 0x6e,
|
||||||
0x82, 0x79, 0x6f, 0x75, 0x00, 0x6b, 0x6e, 0x6f, 0x77, 0x1f,
|
0x6f, 0x77, 0x13, 0x02, 0x02, 0x39, 0x00, 0x45, 0x6d, 0x75,
|
||||||
0x02, 0x02, 0x39, 0x00, 0x45, 0x6d, 0x75, 0x73, 0x74, 0x37,
|
0x73, 0x74, 0x2b, 0x02, 0x03, 0xe6, 0x00, 0x30, 0x2c, 0x00,
|
||||||
0x02, 0x03, 0xe6, 0x00, 0x30, 0x2c, 0x00, 0x65, 0xd4, 0x02,
|
0x65, 0xc8, 0x02, 0x21, 0x69, 0x66, 0x32, 0x00, 0x52, 0x64,
|
||||||
0x21, 0x69, 0x66, 0x32, 0x00, 0x52, 0x64, 0x6f, 0x6e, 0x27,
|
0x6f, 0x6e, 0x27, 0x74, 0x38, 0x00, 0x02, 0xbf, 0x02, 0x00,
|
||||||
0x74, 0x38, 0x00, 0x02, 0xcb, 0x02, 0x00, 0xb5, 0x00, 0x00,
|
0xb5, 0x00, 0x00, 0xa3, 0x01, 0x02, 0xcb, 0x00, 0x6d, 0x65,
|
||||||
0xaf, 0x01, 0x02, 0xcb, 0x00, 0x6d, 0x65, 0x73, 0x00, 0x79,
|
0x73, 0x00, 0x79, 0x65, 0x74, 0xf9, 0x00, 0x0e, 0x9d, 0x00,
|
||||||
0x65, 0x74, 0xf9, 0x00, 0x0e, 0x9d, 0x00, 0x04, 0xe7, 0x01,
|
0x04, 0xdb, 0x01, 0x06, 0xed, 0x00, 0x15, 0x69, 0x7a, 0x00,
|
||||||
0x06, 0xed, 0x00, 0x15, 0x69, 0x7a, 0x00, 0x16, 0x73, 0xf9,
|
0x16, 0x73, 0xf9, 0x00, 0x03, 0x62, 0x01, 0x05, 0xef, 0x00,
|
||||||
0x00, 0x03, 0x62, 0x01, 0x05, 0xef, 0x00, 0x32, 0x00, 0x6f,
|
0x32, 0x00, 0x6f, 0x72, 0x74, 0x02, 0x60, 0x2d, 0x64, 0x72,
|
||||||
0x72, 0x80, 0x02, 0x60, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x67,
|
0x61, 0x67, 0x67, 0x38, 0x00, 0x04, 0x7d, 0x01, 0x05, 0xa2,
|
||||||
0x38, 0x00, 0x04, 0x7d, 0x01, 0x05, 0xa2, 0x01, 0x20, 0x6c,
|
0x01, 0x20, 0x6c, 0x6c, 0xfd, 0x02, 0x00, 0xad, 0x00, 0x86,
|
||||||
0x6c, 0x09, 0x03, 0x00, 0xad, 0x00, 0x86, 0x74, 0x6f, 0x00,
|
0x74, 0x6f, 0x00, 0x6c, 0x61, 0x79, 0x00, 0x61, 0x83, 0x02,
|
||||||
0x6c, 0x61, 0x79, 0x00, 0x61, 0x8f, 0x02, 0x31, 0x6c, 0x69,
|
0x31, 0x6c, 0x69, 0x6e, 0x7b, 0x03, 0x32, 0x69, 0x73, 0x2d,
|
||||||
0x6e, 0x87, 0x03, 0x32, 0x69, 0x73, 0x2d, 0x61, 0x00, 0x20,
|
0x61, 0x00, 0x20, 0x6f, 0x72, 0x0c, 0x00, 0x33, 0x6e, 0x6f,
|
||||||
0x6f, 0x72, 0x0c, 0x00, 0x33, 0x6e, 0x6f, 0x74, 0x10, 0x00,
|
0x74, 0x10, 0x00, 0x05, 0x2d, 0x01, 0xd1, 0x73, 0x2c, 0x00,
|
||||||
0x05, 0x2d, 0x01, 0xd1, 0x73, 0x2c, 0x00, 0x75, 0x73, 0x65,
|
0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x00, 0x66, 0x6f, 0x72,
|
||||||
0x66, 0x75, 0x6c, 0x00, 0x66, 0x6f, 0x72, 0xad, 0x03, 0x03,
|
0xa1, 0x03, 0x03, 0xc9, 0x00, 0x01, 0x5b, 0x03, 0x25, 0x6f,
|
||||||
0xc9, 0x00, 0x01, 0x67, 0x03, 0x25, 0x6f, 0x72, 0x66, 0x03,
|
0x72, 0x5a, 0x03, 0x85, 0x74, 0x6f, 0x00, 0x6d, 0x61, 0x74,
|
||||||
0x85, 0x74, 0x6f, 0x00, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x31,
|
0x63, 0x68, 0x25, 0x03, 0x00, 0xad, 0x00, 0x41, 0x28, 0x41,
|
||||||
0x03, 0x00, 0xad, 0x00, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x11,
|
0x6c, 0x6c, 0x11, 0x00, 0x11, 0x61, 0x8f, 0x02, 0x92, 0x73,
|
||||||
0x00, 0x11, 0x61, 0x95, 0x02, 0x92, 0x73, 0x00, 0x64, 0x65,
|
0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x4f, 0x03,
|
||||||
0x73, 0x63, 0x72, 0x69, 0x62, 0x5b, 0x03, 0x13, 0x73, 0xab,
|
0x13, 0x73, 0xa5, 0x02, 0x41, 0x32, 0x2e, 0x31, 0x00, 0x13,
|
||||||
0x02, 0x41, 0x32, 0x2e, 0x31, 0x00, 0x13, 0x01, 0xf2, 0x00,
|
0x01, 0xf2, 0x00, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61,
|
||||||
0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,
|
0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0xad, 0x02,
|
||||||
0x62, 0x6c, 0x65, 0x2e, 0x29, 0xb3, 0x02, 0x1a, 0x32, 0xb3,
|
0x14, 0x32, 0xad, 0x02, 0xb2, 0x70, 0x61, 0x72, 0x61, 0x6d,
|
||||||
0x02, 0xb2, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
|
0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x5e, 0x03, 0x36, 0x73,
|
||||||
0x72, 0x73, 0x20, 0x70, 0x03, 0x36, 0x73, 0x65, 0x00, 0x14,
|
0x65, 0x00, 0x14, 0x00, 0x02, 0x42, 0x00, 0x04, 0x3d, 0x00,
|
||||||
0x00, 0x02, 0x48, 0x00, 0x04, 0x43, 0x00, 0x02, 0x24, 0x04,
|
0x02, 0x12, 0x04, 0x00, 0x7a, 0x00, 0xe1, 0x60, 0x43, 0x75,
|
||||||
0x00, 0x80, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f,
|
0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f,
|
||||||
0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x76, 0x00,
|
0x70, 0x70, 0x00, 0x03, 0x68, 0x02, 0xb0, 0x60, 0x54, 0x79,
|
||||||
0x03, 0x6e, 0x02, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27,
|
0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xac, 0x00,
|
||||||
0x00, 0x6d, 0x65, 0x6e, 0x75, 0xb2, 0x00, 0x91, 0x57, 0x69,
|
0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65,
|
||||||
0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x28, 0x01, 0x68,
|
0x22, 0x01, 0x68, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x65, 0xd3,
|
||||||
0x00, 0x00, 0x53, 0x69, 0x7a, 0x65, 0xe5, 0x03, 0x00, 0x99,
|
0x03, 0x00, 0x93, 0x02, 0x06, 0xd3, 0x02, 0xf3, 0x01, 0x00,
|
||||||
0x02, 0x06, 0xd9, 0x02, 0xf3, 0x01, 0x00, 0x00, 0x44, 0x69,
|
0x00, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74,
|
||||||
0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x00, 0x00,
|
0x79, 0x00, 0x00, 0x00, 0x43, 0x49, 0x03, 0x01, 0x2e, 0x00,
|
||||||
0x00, 0x43, 0x4f, 0x03, 0x01, 0x2e, 0x00, 0x16, 0x64, 0x1a,
|
0x16, 0x64, 0x1a, 0x00, 0x04, 0x40, 0x00, 0x41, 0x65, 0x6e,
|
||||||
0x00, 0x04, 0x40, 0x00, 0x41, 0x65, 0x6e, 0x65, 0x72, 0x58,
|
0x65, 0x72, 0x46, 0x04, 0xf3, 0x0b, 0x70, 0x75, 0x7a, 0x7a,
|
||||||
0x04, 0xf3, 0x0b, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x3a,
|
0x6c, 0x65, 0x3a, 0x00, 0x61, 0x74, 0x00, 0x54, 0x72, 0x69,
|
||||||
0x00, 0x61, 0x74, 0x00, 0x54, 0x72, 0x69, 0x63, 0x6b, 0x79,
|
0x63, 0x6b, 0x79, 0x00, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x2c,
|
||||||
0x00, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x2c, 0x00, 0x79, 0x41,
|
0x00, 0x79, 0x2f, 0x05, 0x82, 0x72, 0x65, 0x71, 0x75, 0x69,
|
||||||
0x05, 0x82, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
|
0x72, 0x65, 0x64, 0x51, 0x01, 0xc3, 0x6b, 0x65, 0x00, 0x6d,
|
||||||
0x57, 0x01, 0xc3, 0x6b, 0x65, 0x00, 0x6d, 0x6f, 0x72, 0x65,
|
0x6f, 0x72, 0x65, 0x00, 0x64, 0x65, 0x64, 0x75, 0x43, 0x01,
|
||||||
0x00, 0x64, 0x65, 0x64, 0x75, 0x49, 0x01, 0x60, 0x72, 0x65,
|
0x60, 0x72, 0x65, 0x67, 0x61, 0x72, 0x64, 0x86, 0x01, 0x36,
|
||||||
0x67, 0x61, 0x72, 0x64, 0x8c, 0x01, 0x36, 0x64, 0x69, 0x73,
|
0x64, 0x69, 0x73, 0x0d, 0x00, 0x52, 0x6d, 0x6f, 0x76, 0x65,
|
||||||
0x0d, 0x00, 0x52, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0xd9, 0x02,
|
0x73, 0xd3, 0x02, 0x91, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00,
|
||||||
0x91, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x6c, 0x65, 0x61,
|
0x6c, 0x65, 0x61, 0x45, 0x00, 0x25, 0x69, 0x6d, 0x34, 0x03,
|
||||||
0x45, 0x00, 0x25, 0x69, 0x6d, 0x3a, 0x03, 0x01, 0x73, 0x02,
|
0x01, 0x6d, 0x02, 0xa2, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x6c,
|
||||||
0xa2, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x6c, 0x61, 0x74, 0x65,
|
0x61, 0x74, 0x65, 0x72, 0xc6, 0x00, 0x11, 0x73, 0x2a, 0x02,
|
||||||
0x72, 0xc6, 0x00, 0x11, 0x73, 0x30, 0x02, 0x00, 0x11, 0x04,
|
0x00, 0x0b, 0x04, 0xb2, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69,
|
||||||
0xb2, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x20,
|
0x76, 0x65, 0x20, 0x31, 0x20, 0xe6, 0x04, 0x07, 0xd8, 0x00,
|
||||||
0x31, 0x20, 0xf8, 0x04, 0x07, 0xd8, 0x00, 0x30, 0x77, 0x68,
|
0x30, 0x77, 0x68, 0x65, 0x72, 0x03, 0x01, 0xce, 0x00, 0x03,
|
||||||
0x65, 0x78, 0x03, 0x01, 0xce, 0x00, 0x09, 0x91, 0x04, 0x35,
|
0x7f, 0x04, 0x35, 0x67, 0x61, 0x6d, 0xda, 0x00, 0x00, 0x57,
|
||||||
0x67, 0x61, 0x6d, 0xe0, 0x00, 0x00, 0x5d, 0x01, 0x71, 0x70,
|
0x01, 0x71, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x73, 0xfb,
|
||||||
0x65, 0x72, 0x6d, 0x69, 0x74, 0x73, 0x07, 0x04, 0x50, 0x61,
|
0x03, 0x50, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x14, 0x04, 0x0f,
|
||||||
0x64, 0x6a, 0x61, 0x63, 0x20, 0x04, 0x0f, 0x33, 0x02, 0x00,
|
0x27, 0x02, 0x00, 0x81, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61,
|
||||||
0x81, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x31, 0x32,
|
0x00, 0x31, 0x26, 0x02, 0x10, 0x2c, 0x1d, 0x00, 0x05, 0x3a,
|
||||||
0x02, 0x10, 0x2c, 0x1d, 0x00, 0x05, 0x3a, 0x00, 0x02, 0xcb,
|
0x00, 0x02, 0xb3, 0x05, 0x06, 0x30, 0x00, 0x04, 0x40, 0x01,
|
||||||
0x05, 0x06, 0x30, 0x00, 0x04, 0x46, 0x01, 0x01, 0xa1, 0x02,
|
0x01, 0x95, 0x02, 0xbd, 0x27, 0x73, 0x00, 0x65, 0x6e, 0x64,
|
||||||
0xbd, 0x27, 0x73, 0x00, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
|
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x00, 0xc2, 0x2e, 0x00,
|
||||||
0x6e, 0x74, 0x47, 0x00, 0xc2, 0x2e, 0x00, 0x42, 0x79, 0x00,
|
0x42, 0x79, 0x00, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
|
||||||
0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x17, 0x05, 0x21,
|
0x05, 0x05, 0x21, 0x69, 0x73, 0x3b, 0x05, 0x02, 0x5b, 0x00,
|
||||||
0x69, 0x73, 0x53, 0x05, 0x02, 0x5b, 0x00, 0x60, 0x74, 0x65,
|
0x60, 0x74, 0x65, 0x64, 0x2c, 0x00, 0x74, 0x5d, 0x02, 0x86,
|
||||||
0x64, 0x2c, 0x00, 0x74, 0x69, 0x02, 0x86, 0x6f, 0x69, 0x64,
|
0x6f, 0x69, 0x64, 0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x0c, 0x03,
|
||||||
0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x18, 0x03, 0x30, 0x62, 0x6f,
|
0x30, 0x62, 0x6f, 0x72, 0x40, 0x01, 0x05, 0xf9, 0x05, 0x05,
|
||||||
0x72, 0x46, 0x01, 0x05, 0x11, 0x06, 0x05, 0x23, 0x06, 0x00,
|
0x0b, 0x06, 0x00, 0x8c, 0x05, 0x01, 0x82, 0x01, 0x01, 0xc2,
|
||||||
0xa4, 0x05, 0x01, 0x88, 0x01, 0x01, 0xc8, 0x01, 0x01, 0x58,
|
0x01, 0x01, 0x46, 0x05, 0x01, 0x8c, 0x01, 0x71, 0x74, 0x77,
|
||||||
0x05, 0x01, 0x92, 0x01, 0x71, 0x74, 0x77, 0x69, 0x64, 0x64,
|
0x69, 0x64, 0x64, 0x6c, 0x79, 0x20, 0x00, 0x70, 0x69, 0x6e,
|
||||||
0x6c, 0x79, 0x20, 0x00, 0x70, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
0x74, 0x65, 0x72, 0x65, 0x73, 0xba, 0x03, 0x32, 0x2e, 0x00,
|
||||||
0x65, 0x73, 0xc6, 0x03, 0x32, 0x2e, 0x00, 0x49, 0x28, 0x04,
|
0x49, 0x1c, 0x04, 0x22, 0x77, 0x61, 0xa1, 0x00, 0x00, 0x18,
|
||||||
0x22, 0x77, 0x61, 0xa1, 0x00, 0x00, 0x18, 0x00, 0x22, 0x6f,
|
0x00, 0x22, 0x6f, 0x72, 0x3f, 0x00, 0x02, 0x83, 0x01, 0xb2,
|
||||||
0x72, 0x3f, 0x00, 0x02, 0x89, 0x01, 0xb2, 0x69, 0x6c, 0x69,
|
0x69, 0x6c, 0x69, 0x74, 0x79, 0x2c, 0x00, 0x74, 0x75, 0x72,
|
||||||
0x74, 0x79, 0x2c, 0x00, 0x74, 0x75, 0x72, 0x6e, 0xa5, 0x00,
|
0x6e, 0xa5, 0x00, 0x03, 0x91, 0x02, 0x50, 0x6f, 0x66, 0x66,
|
||||||
0x03, 0x97, 0x02, 0x50, 0x6f, 0x66, 0x66, 0x2e, 0x00,
|
0x2e, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned short help_text_len = 1917;
|
const unsigned short help_text_len = 1881;
|
||||||
const unsigned short help_text_words = 339;
|
const unsigned short help_text_words = 337;
|
||||||
const char quick_help_text[] = "Fill in the railway track according to the clues.";
|
const char quick_help_text[] = "Fill in the railway track according to the clues.";
|
||||||
|
|
|
@ -753,7 +753,7 @@ static void rb_color(int n)
|
||||||
|
|
||||||
/* clipping is implemented through viewports and offsetting
|
/* clipping is implemented through viewports and offsetting
|
||||||
* coordinates */
|
* coordinates */
|
||||||
static void rb_clip(void *handle, int x, int y, int w, int h)
|
static void rb_clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
if(!zoom_enabled)
|
if(!zoom_enabled)
|
||||||
{
|
{
|
||||||
|
@ -783,7 +783,7 @@ static void rb_clip(void *handle, int x, int y, int w, int h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_unclip(void *handle)
|
static void rb_unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
if(!zoom_enabled)
|
if(!zoom_enabled)
|
||||||
{
|
{
|
||||||
|
@ -800,7 +800,7 @@ static void rb_unclip(void *handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_draw_text(void *handle, int x, int y, int fonttype,
|
static void rb_draw_text(drawing *dr, int x, int y, int fonttype,
|
||||||
int fontsize, int align, int color, const char *text)
|
int fontsize, int align, int color, const char *text)
|
||||||
{
|
{
|
||||||
(void) fontsize;
|
(void) fontsize;
|
||||||
|
@ -865,7 +865,7 @@ static void rb_draw_text(void *handle, int x, int y, int fonttype,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_draw_rect(void *handle, int x, int y, int w, int h, int color)
|
static void rb_draw_rect(drawing *dr, int x, int y, int w, int h, int color)
|
||||||
{
|
{
|
||||||
rb_color(color);
|
rb_color(color);
|
||||||
if(!zoom_enabled)
|
if(!zoom_enabled)
|
||||||
|
@ -1007,7 +1007,7 @@ static void draw_antialiased_line(fb_data *fb, int w, int h, int x0, int y0, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
static void rb_draw_line(drawing *dr, int x1, int y1, int x2, int y2,
|
||||||
int color)
|
int color)
|
||||||
{
|
{
|
||||||
rb_color(color);
|
rb_color(color);
|
||||||
|
@ -1035,349 +1035,7 @@ static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static void rb_draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
/*
|
|
||||||
* draw filled polygon
|
|
||||||
* originally by Sebastian Leonhardt (ulmutul)
|
|
||||||
* 'count' : number of coordinate pairs
|
|
||||||
* 'pxy': array of coordinates. pxy[0]=x0,pxy[1]=y0,...
|
|
||||||
* note: provide space for one extra coordinate, because the starting point
|
|
||||||
* will automatically be inserted as end point.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* helper function:
|
|
||||||
* find points of intersection between polygon and scanline
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAX_INTERSECTION 32
|
|
||||||
|
|
||||||
static void fill_poly_line(int scanline, int count, int *pxy)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
int num_of_intersects;
|
|
||||||
int direct, old_direct;
|
|
||||||
//intersections of every line with scanline (y-coord)
|
|
||||||
int intersection[MAX_INTERSECTION];
|
|
||||||
/* add starting point as ending point */
|
|
||||||
pxy[count*2] = pxy[0];
|
|
||||||
pxy[count*2+1] = pxy[1];
|
|
||||||
|
|
||||||
old_direct=0;
|
|
||||||
num_of_intersects=0;
|
|
||||||
for (i=0; i<count*2; i+=2) {
|
|
||||||
int x1=pxy[i];
|
|
||||||
int y1=pxy[i+1];
|
|
||||||
int x2=pxy[i+2];
|
|
||||||
int y2=pxy[i+3];
|
|
||||||
// skip if line is outside of scanline
|
|
||||||
if (y1 < y2) {
|
|
||||||
if (scanline < y1 || scanline > y2)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (scanline < y2 || scanline > y1)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// calculate x-coord of intersection
|
|
||||||
if (y1==y2) {
|
|
||||||
direct=0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
direct = y1>y2 ? 1 : -1;
|
|
||||||
// omit double intersections, if both lines lead in the same direction
|
|
||||||
intersection[num_of_intersects] =
|
|
||||||
x1+((scanline-y1)*(x2-x1))/(y2-y1);
|
|
||||||
if ( (direct!=old_direct)
|
|
||||||
|| (intersection[num_of_intersects] != intersection[num_of_intersects-1])
|
|
||||||
)
|
|
||||||
++num_of_intersects;
|
|
||||||
}
|
|
||||||
old_direct = direct;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort points of intersection
|
|
||||||
for (i=0; i<num_of_intersects-1; ++i) {
|
|
||||||
for (j=i+1; j<num_of_intersects; ++j) {
|
|
||||||
if (intersection[j]<intersection[i]) {
|
|
||||||
int temp=intersection[i];
|
|
||||||
intersection[i]=intersection[j];
|
|
||||||
intersection[j]=temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// draw
|
|
||||||
for (i=0; i<num_of_intersects; i+=2) {
|
|
||||||
rb->lcd_hline(intersection[i], intersection[i+1], scanline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* two extra elements at end of pxy needed */
|
|
||||||
static void v_fillarea(int count, int *pxy)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int y1, y2;
|
|
||||||
|
|
||||||
// find min and max y coords
|
|
||||||
y1=y2=pxy[1];
|
|
||||||
for (i=3; i<count*2; i+=2) {
|
|
||||||
if (pxy[i] < y1) y1 = pxy[i];
|
|
||||||
else if (pxy[i] > y2) y2 = pxy[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=y1; i<=y2; ++i) {
|
|
||||||
fill_poly_line(i, count, pxy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* I'm a horrible person: this was copy-pasta'd straight from
|
|
||||||
* xlcd_draw.c */
|
|
||||||
|
|
||||||
/* sort the given coordinates by increasing x value */
|
|
||||||
static void sort_points_by_increasing_x(int* x1, int* y1,
|
|
||||||
int* x2, int* y2,
|
|
||||||
int* x3, int* y3)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
if (*x1 > *x3)
|
|
||||||
{
|
|
||||||
if (*x2 < *x3) /* x2 < x3 < x1 */
|
|
||||||
{
|
|
||||||
x = *x1; *x1 = *x2; *x2 = *x3; *x3 = x;
|
|
||||||
y = *y1; *y1 = *y2; *y2 = *y3; *y3 = y;
|
|
||||||
}
|
|
||||||
else if (*x2 > *x1) /* x3 < x1 < x2 */
|
|
||||||
{
|
|
||||||
x = *x1; *x1 = *x3; *x3 = *x2; *x2 = x;
|
|
||||||
y = *y1; *y1 = *y3; *y3 = *y2; *y2 = y;
|
|
||||||
}
|
|
||||||
else /* x3 <= x2 <= x1 */
|
|
||||||
{
|
|
||||||
x = *x1; *x1 = *x3; *x3 = x;
|
|
||||||
y = *y1; *y1 = *y3; *y3 = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (*x2 < *x1) /* x2 < x1 <= x3 */
|
|
||||||
{
|
|
||||||
x = *x1; *x1 = *x2; *x2 = x;
|
|
||||||
y = *y1; *y1 = *y2; *y2 = y;
|
|
||||||
}
|
|
||||||
else if (*x2 > *x3) /* x1 <= x3 < x2 */
|
|
||||||
{
|
|
||||||
x = *x2; *x2 = *x3; *x3 = x;
|
|
||||||
y = *y2; *y2 = *y3; *y3 = y;
|
|
||||||
}
|
|
||||||
/* else already sorted */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define sort_points_by_increasing_y(x1, y1, x2, y2, x3, y3) \
|
|
||||||
sort_points_by_increasing_x(y1, x1, y2, x2, y3, x3)
|
|
||||||
|
|
||||||
/* draw a filled triangle, using horizontal lines for speed */
|
|
||||||
static void zoom_filltriangle(int x1, int y1,
|
|
||||||
int x2, int y2,
|
|
||||||
int x3, int y3)
|
|
||||||
{
|
|
||||||
long fp_x1, fp_x2, fp_dx1, fp_dx2;
|
|
||||||
int y;
|
|
||||||
sort_points_by_increasing_y(&x1, &y1, &x2, &y2, &x3, &y3);
|
|
||||||
|
|
||||||
if (y1 < y3) /* draw */
|
|
||||||
{
|
|
||||||
fp_dx1 = ((x3 - x1) << 16) / (y3 - y1);
|
|
||||||
fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1);
|
|
||||||
|
|
||||||
if (y1 < y2) /* first part */
|
|
||||||
{
|
|
||||||
fp_dx2 = ((x2 - x1) << 16) / (y2 - y1);
|
|
||||||
fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1);
|
|
||||||
for (y = y1; y < y2; y++)
|
|
||||||
{
|
|
||||||
zoom_hline(fp_x1 >> 16, fp_x2 >> 16, y);
|
|
||||||
fp_x1 += fp_dx1;
|
|
||||||
fp_x2 += fp_dx2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (y2 < y3) /* second part */
|
|
||||||
{
|
|
||||||
fp_dx2 = ((x3 - x2) << 16) / (y3 - y2);
|
|
||||||
fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1);
|
|
||||||
for (y = y2; y < y3; y++)
|
|
||||||
{
|
|
||||||
zoom_hline(fp_x1 >> 16, fp_x2 >> 16, y);
|
|
||||||
fp_x1 += fp_dx1;
|
|
||||||
fp_x2 += fp_dx2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Should probably refactor this */
|
|
||||||
static void rb_draw_poly(void *handle, const int *coords, int npoints,
|
|
||||||
int fillcolor, int outlinecolor)
|
|
||||||
{
|
|
||||||
if(!zoom_enabled)
|
|
||||||
{
|
|
||||||
LOGF("rb_draw_poly");
|
|
||||||
|
|
||||||
if(fillcolor >= 0)
|
|
||||||
{
|
|
||||||
rb_color(fillcolor);
|
|
||||||
#if 1
|
|
||||||
/* serious hack: draw a bunch of triangles between adjacent points */
|
|
||||||
/* this generally works, even with some concave polygons */
|
|
||||||
for(int i = 2; i < npoints; ++i)
|
|
||||||
{
|
|
||||||
int x1, y1, x2, y2, x3, y3;
|
|
||||||
x1 = coords[0];
|
|
||||||
y1 = coords[1];
|
|
||||||
x2 = coords[(i - 1) * 2];
|
|
||||||
y2 = coords[(i - 1) * 2 + 1];
|
|
||||||
x3 = coords[i * 2];
|
|
||||||
y3 = coords[i * 2 + 1];
|
|
||||||
offset_coords(&x1, &y1);
|
|
||||||
offset_coords(&x2, &y2);
|
|
||||||
offset_coords(&x3, &y3);
|
|
||||||
xlcd_filltriangle(x1, y1,
|
|
||||||
x2, y2,
|
|
||||||
x3, y3);
|
|
||||||
|
|
||||||
#ifdef DEBUG_MENU
|
|
||||||
if(debug_settings.polyanim)
|
|
||||||
{
|
|
||||||
rb->lcd_update();
|
|
||||||
rb->sleep(HZ/4);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
/* debug code */
|
|
||||||
rb->lcd_set_foreground(LCD_RGBPACK(255,0,0));
|
|
||||||
rb->lcd_drawpixel(x1, y1);
|
|
||||||
rb->lcd_drawpixel(x2, y2);
|
|
||||||
rb->lcd_drawpixel(x3, y3);
|
|
||||||
rb->lcd_update();
|
|
||||||
rb->sleep(HZ);
|
|
||||||
rb_color(fillcolor);
|
|
||||||
rb->lcd_drawpixel(x1, y1);
|
|
||||||
rb->lcd_drawpixel(x2, y2);
|
|
||||||
rb->lcd_drawpixel(x3, y3);
|
|
||||||
rb->lcd_update();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int *pxy = smalloc(sizeof(int) * 2 * npoints + 2);
|
|
||||||
/* copy points, offsetted */
|
|
||||||
for(int i = 0; i < npoints; ++i)
|
|
||||||
{
|
|
||||||
pxy[2 * i + 0] = coords[2 * i + 0];
|
|
||||||
pxy[2 * i + 1] = coords[2 * i + 1];
|
|
||||||
offset_coords(&pxy[2*i+0], &pxy[2*i+1]);
|
|
||||||
}
|
|
||||||
v_fillarea(npoints, pxy);
|
|
||||||
sfree(pxy);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* draw outlines last so they're not covered by the fill */
|
|
||||||
assert(outlinecolor >= 0);
|
|
||||||
rb_color(outlinecolor);
|
|
||||||
|
|
||||||
for(int i = 1; i < npoints; ++i)
|
|
||||||
{
|
|
||||||
int x1, y1, x2, y2;
|
|
||||||
x1 = coords[2 * (i - 1)];
|
|
||||||
y1 = coords[2 * (i - 1) + 1];
|
|
||||||
x2 = coords[2 * i];
|
|
||||||
y2 = coords[2 * i + 1];
|
|
||||||
if(debug_settings.no_aa)
|
|
||||||
{
|
|
||||||
offset_coords(&x1, &y1);
|
|
||||||
offset_coords(&x2, &y2);
|
|
||||||
rb->lcd_drawline(x1, y1,
|
|
||||||
x2, y2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
|
|
||||||
|
|
||||||
#ifdef DEBUG_MENU
|
|
||||||
if(debug_settings.polyanim)
|
|
||||||
{
|
|
||||||
rb->lcd_update();
|
|
||||||
rb->sleep(HZ/4);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int x1, y1, x2, y2;
|
|
||||||
x1 = coords[0];
|
|
||||||
y1 = coords[1];
|
|
||||||
x2 = coords[2 * (npoints - 1)];
|
|
||||||
y2 = coords[2 * (npoints - 1) + 1];
|
|
||||||
if(debug_settings.no_aa)
|
|
||||||
{
|
|
||||||
offset_coords(&x1, &y1);
|
|
||||||
offset_coords(&x2, &y2);
|
|
||||||
|
|
||||||
rb->lcd_drawline(x1, y1,
|
|
||||||
x2, y2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGF("rb_draw_poly");
|
|
||||||
|
|
||||||
if(fillcolor >= 0)
|
|
||||||
{
|
|
||||||
rb_color(fillcolor);
|
|
||||||
|
|
||||||
/* serious hack: draw a bunch of triangles between adjacent points */
|
|
||||||
/* this generally works, even with some concave polygons */
|
|
||||||
for(int i = 2; i < npoints; ++i)
|
|
||||||
{
|
|
||||||
int x1, y1, x2, y2, x3, y3;
|
|
||||||
x1 = coords[0];
|
|
||||||
y1 = coords[1];
|
|
||||||
x2 = coords[(i - 1) * 2];
|
|
||||||
y2 = coords[(i - 1) * 2 + 1];
|
|
||||||
x3 = coords[i * 2];
|
|
||||||
y3 = coords[i * 2 + 1];
|
|
||||||
zoom_filltriangle(x1, y1,
|
|
||||||
x2, y2,
|
|
||||||
x3, y3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* draw outlines last so they're not covered by the fill */
|
|
||||||
assert(outlinecolor >= 0);
|
|
||||||
rb_color(outlinecolor);
|
|
||||||
|
|
||||||
for(int i = 1; i < npoints; ++i)
|
|
||||||
{
|
|
||||||
int x1, y1, x2, y2;
|
|
||||||
x1 = coords[2 * (i - 1)];
|
|
||||||
y1 = coords[2 * (i - 1) + 1];
|
|
||||||
x2 = coords[2 * i];
|
|
||||||
y2 = coords[2 * i + 1];
|
|
||||||
draw_antialiased_line(zoom_fb, zoom_w, zoom_h, x1, y1, x2, y2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int x1, y1, x2, y2;
|
|
||||||
x1 = coords[0];
|
|
||||||
y1 = coords[1];
|
|
||||||
x2 = coords[2 * (npoints - 1)];
|
|
||||||
y2 = coords[2 * (npoints - 1) + 1];
|
|
||||||
draw_antialiased_line(zoom_fb, zoom_w, zoom_h, x1, y1, x2, y2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rb_draw_circle(void *handle, int cx, int cy, int radius,
|
|
||||||
int fillcolor, int outlinecolor)
|
int fillcolor, int outlinecolor)
|
||||||
{
|
{
|
||||||
if(!zoom_enabled)
|
if(!zoom_enabled)
|
||||||
|
@ -1449,7 +1107,7 @@ static void trim_rect(int *x, int *y, int *w, int *h)
|
||||||
*h = y1 - y0;
|
*h = y1 - y0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static blitter *rb_blitter_new(void *handle, int w, int h)
|
static blitter *rb_blitter_new(drawing *dr, int w, int h)
|
||||||
{
|
{
|
||||||
LOGF("rb_blitter_new");
|
LOGF("rb_blitter_new");
|
||||||
blitter *b = snew(blitter);
|
blitter *b = snew(blitter);
|
||||||
|
@ -1460,7 +1118,7 @@ static blitter *rb_blitter_new(void *handle, int w, int h)
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_blitter_free(void *handle, blitter *bl)
|
static void rb_blitter_free(drawing *dr, blitter *bl)
|
||||||
{
|
{
|
||||||
LOGF("rb_blitter_free");
|
LOGF("rb_blitter_free");
|
||||||
sfree(bl->bmp.data);
|
sfree(bl->bmp.data);
|
||||||
|
@ -1469,7 +1127,7 @@ static void rb_blitter_free(void *handle, blitter *bl)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy a section of the framebuffer */
|
/* copy a section of the framebuffer */
|
||||||
static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
|
static void rb_blitter_save(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
/* no viewport offset */
|
/* no viewport offset */
|
||||||
#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
|
#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
|
||||||
|
@ -1498,7 +1156,7 @@ static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_blitter_load(void *handle, blitter *bl, int x, int y)
|
static void rb_blitter_load(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
LOGF("rb_blitter_load");
|
LOGF("rb_blitter_load");
|
||||||
if(!bl->have_data)
|
if(!bl->have_data)
|
||||||
|
@ -1528,7 +1186,7 @@ static void rb_blitter_load(void *handle, blitter *bl, int x, int y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_draw_update(void *handle, int x, int y, int w, int h)
|
static void rb_draw_update(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
LOGF("rb_draw_update(%d, %d, %d, %d)", x, y, w, h);
|
LOGF("rb_draw_update(%d, %d, %d, %d)", x, y, w, h);
|
||||||
|
|
||||||
|
@ -1552,9 +1210,9 @@ static void rb_draw_update(void *handle, int x, int y, int w, int h)
|
||||||
need_draw_update = true;
|
need_draw_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_start_draw(void *handle)
|
static void rb_start_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
(void) handle;
|
(void) dr;
|
||||||
|
|
||||||
/* ... mumble mumble ... not ... reentrant ... mumble mumble ... */
|
/* ... mumble mumble ... not ... reentrant ... mumble mumble ... */
|
||||||
|
|
||||||
|
@ -1565,9 +1223,9 @@ static void rb_start_draw(void *handle)
|
||||||
ud_d = LCD_HEIGHT;
|
ud_d = LCD_HEIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_end_draw(void *handle)
|
static void rb_end_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
(void) handle;
|
(void) dr;
|
||||||
|
|
||||||
if(debug_settings.highlight_cursor)
|
if(debug_settings.highlight_cursor)
|
||||||
{
|
{
|
||||||
|
@ -1594,7 +1252,7 @@ static void rb_end_draw(void *handle)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_status_bar(void *handle, const char *text)
|
static void rb_status_bar(drawing *dr, const char *text)
|
||||||
{
|
{
|
||||||
if(titlebar)
|
if(titlebar)
|
||||||
sfree(titlebar);
|
sfree(titlebar);
|
||||||
|
@ -1692,7 +1350,7 @@ static void draw_mouse(void)
|
||||||
* glyph exists in a font) */
|
* glyph exists in a font) */
|
||||||
#if 0
|
#if 0
|
||||||
/* See: https://www.chiark.greenend.org.uk/~sgtatham/puzzles/devel/drawing.html#drawing-text-fallback */
|
/* See: https://www.chiark.greenend.org.uk/~sgtatham/puzzles/devel/drawing.html#drawing-text-fallback */
|
||||||
static char *rb_text_fallback(void *handle, const char *const *strings,
|
static char *rb_text_fallback(drawing *dr, const char *const *strings,
|
||||||
int nstrings)
|
int nstrings)
|
||||||
{
|
{
|
||||||
struct font *pf = rb->font_get(cur_font);
|
struct font *pf = rb->font_get(cur_font);
|
||||||
|
@ -1725,10 +1383,11 @@ static char *rb_text_fallback(void *handle, const char *const *strings,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const drawing_api rb_drawing = {
|
const drawing_api rb_drawing = {
|
||||||
|
1,
|
||||||
rb_draw_text,
|
rb_draw_text,
|
||||||
rb_draw_rect,
|
rb_draw_rect,
|
||||||
rb_draw_line,
|
rb_draw_line,
|
||||||
rb_draw_poly,
|
draw_polygon_fallback,
|
||||||
rb_draw_circle,
|
rb_draw_circle,
|
||||||
rb_draw_update,
|
rb_draw_update,
|
||||||
rb_clip,
|
rb_clip,
|
||||||
|
|
|
@ -6,13 +6,17 @@ project(puzzles
|
||||||
include(cmake/setup.cmake)
|
include(cmake/setup.cmake)
|
||||||
|
|
||||||
add_library(core_obj OBJECT
|
add_library(core_obj OBJECT
|
||||||
combi.c divvy.c drawing.c dsf.c findloop.c grid.c latin.c
|
combi.c divvy.c draw-poly.c drawing.c dsf.c findloop.c grid.c
|
||||||
laydomino.c loopgen.c malloc.c matching.c midend.c misc.c penrose.c
|
latin.c laydomino.c loopgen.c malloc.c matching.c midend.c misc.c
|
||||||
penrose-legacy.c ps.c random.c sort.c tdq.c tree234.c version.c
|
penrose.c penrose-legacy.c ps.c random.c sort.c tdq.c tree234.c
|
||||||
|
version.c
|
||||||
${platform_common_sources})
|
${platform_common_sources})
|
||||||
add_library(core $<TARGET_OBJECTS:core_obj>)
|
add_library(core $<TARGET_OBJECTS:core_obj>)
|
||||||
add_library(common $<TARGET_OBJECTS:core_obj> hat.c spectre.c)
|
add_library(common $<TARGET_OBJECTS:core_obj> hat.c spectre.c)
|
||||||
|
|
||||||
|
cliprogram(polygon-test draw-poly.c
|
||||||
|
SDL2_LIB COMPILE_DEFINITIONS STANDALONE_POLYGON)
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
puzzle(blackbox
|
puzzle(blackbox
|
||||||
|
|
302
apps/plugins/puzzles/src/draw-poly.c
Normal file
302
apps/plugins/puzzles/src/draw-poly.c
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
/*
|
||||||
|
* draw-poly.c: Fallback polygon drawing function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "puzzles.h"
|
||||||
|
|
||||||
|
struct edge {
|
||||||
|
int x1, y1;
|
||||||
|
int x2, y2;
|
||||||
|
bool active;
|
||||||
|
|
||||||
|
/* whether y1 is a closed endpoint (i.e. this edge should be
|
||||||
|
* active when y == y1) */
|
||||||
|
bool closed_y1;
|
||||||
|
|
||||||
|
/* (x2 - x1) / (y2 - y1) as 16.16 signed fixed point; precomputed
|
||||||
|
* for speed */
|
||||||
|
long inverse_slope;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FRACBITS 16
|
||||||
|
#define ONEHALF (1 << (FRACBITS-1))
|
||||||
|
|
||||||
|
void draw_polygon_fallback(drawing *dr, const int *coords, int npoints,
|
||||||
|
int fillcolour, int outlinecolour)
|
||||||
|
{
|
||||||
|
struct edge *edges;
|
||||||
|
int min_y = INT_MAX, max_y = INT_MIN, i, y;
|
||||||
|
int n_edges = 0;
|
||||||
|
int *intersections;
|
||||||
|
|
||||||
|
if(npoints < 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(fillcolour < 0)
|
||||||
|
goto draw_outline;
|
||||||
|
|
||||||
|
/* This uses a basic scanline rasterization algorithm for polygon
|
||||||
|
* filling. First, an "edge table" is constructed for each pair of
|
||||||
|
* neighboring points. Horizontal edges are excluded. Then, the
|
||||||
|
* algorithm iterates a horizontal "scan line" over the vertical
|
||||||
|
* (Y) extent of the polygon. At each Y level, it maintains a set
|
||||||
|
* of "active" edges, which are those which intersect the scan
|
||||||
|
* line at the current Y level. The X coordinates where the scan
|
||||||
|
* line intersects each active edge are then computed via
|
||||||
|
* fixed-point arithmetic and stored. Finally, horizontal lines
|
||||||
|
* are drawn between each successive pair of intersection points,
|
||||||
|
* in the order of ascending X coordinate. This has the effect of
|
||||||
|
* "even-odd" filling when the polygon is self-intersecting.
|
||||||
|
*
|
||||||
|
* I (vaguely) based this implementation off the slides below:
|
||||||
|
*
|
||||||
|
* https://www.khoury.northeastern.edu/home/fell/CS4300/Lectures/CS4300F2012-9-ScanLineFill.pdf
|
||||||
|
*
|
||||||
|
* I'm fairly confident that this current implementation is
|
||||||
|
* correct (i.e. draws the right polygon, free from artifacts),
|
||||||
|
* but it isn't quite as efficient as it could be. Namely, it
|
||||||
|
* currently maintains the active edge set by setting the `active`
|
||||||
|
* flag in the `edge` array, which is quite inefficient. Perhaps
|
||||||
|
* future optimization could see this replaced with a tree
|
||||||
|
* set. Additionally, one could perhaps replace the current linear
|
||||||
|
* search for edge endpoints (i.e. the inner loop over `edges`) by
|
||||||
|
* sorting the edge table by upper and lower Y coordinate.
|
||||||
|
*
|
||||||
|
* A final caveat comes from the use of fixed point arithmetic,
|
||||||
|
* which is motivated by performance considerations on FPU-less
|
||||||
|
* platforms (e.g. most Rockbox devices, and maybe others?). I'm
|
||||||
|
* currently using 16 fractional bits to compute the edge
|
||||||
|
* intersections, which (in the case of a 32-bit int) limits the
|
||||||
|
* acceptable range of coordinates to roughly (-2^14, +2^14). This
|
||||||
|
* ought to be acceptable for the forseeable future, but
|
||||||
|
* ultra-high DPI screens might one day exceed this. In that case,
|
||||||
|
* options include switching to int64_t (but that comes with its
|
||||||
|
* own portability headaches), reducing the number of fractional
|
||||||
|
* bits, or just giving up and using floating point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Build edge table from coords. Horizontal edges are filtered
|
||||||
|
* out, so n_edges <= n_points in general. */
|
||||||
|
edges = smalloc(npoints * sizeof(struct edge));
|
||||||
|
|
||||||
|
for(i = 0; i < npoints; i++) {
|
||||||
|
int x1, y1, x2, y2;
|
||||||
|
|
||||||
|
x1 = coords[(2*i+0)];
|
||||||
|
y1 = coords[(2*i+1)];
|
||||||
|
x2 = coords[(2*i+2) % (npoints * 2)];
|
||||||
|
y2 = coords[(2*i+3) % (npoints * 2)];
|
||||||
|
|
||||||
|
if(y1 < min_y)
|
||||||
|
min_y = y1;
|
||||||
|
if(y1 > max_y)
|
||||||
|
max_y = y1;
|
||||||
|
|
||||||
|
#define COORD_LIMIT (1<<(sizeof(int)*CHAR_BIT-2 - FRACBITS))
|
||||||
|
/* Prevent integer overflow when computing `inverse_slope',
|
||||||
|
* which shifts the coordinates left by FRACBITS, and for
|
||||||
|
* which we'd like to avoid relying on `long long'. */
|
||||||
|
/* If this ever causes issues, see the above comment about
|
||||||
|
possible solutions. */
|
||||||
|
assert(x1 < COORD_LIMIT && y1 < COORD_LIMIT);
|
||||||
|
|
||||||
|
/* Only create non-horizontal edges, and require y1 < y2. */
|
||||||
|
if(y1 != y2) {
|
||||||
|
bool swap = y1 > y2;
|
||||||
|
int lower_endpoint = swap ? (i + 1) : i;
|
||||||
|
|
||||||
|
/* Compute index of the point adjacent to lower end of
|
||||||
|
* this edge (which is not the upper end of this edge). */
|
||||||
|
int lower_neighbor = swap ? (lower_endpoint + 1) % npoints : (lower_endpoint + npoints - 1) % npoints;
|
||||||
|
|
||||||
|
struct edge *edge = edges + (n_edges++);
|
||||||
|
|
||||||
|
edge->active = false;
|
||||||
|
edge->x1 = swap ? x2 : x1;
|
||||||
|
edge->y1 = swap ? y2 : y1;
|
||||||
|
edge->x2 = swap ? x1 : x2;
|
||||||
|
edge->y2 = swap ? y1 : y2;
|
||||||
|
edge->inverse_slope = ((edge->x2 - edge->x1) << FRACBITS) / (edge->y2 - edge->y1);
|
||||||
|
edge->closed_y1 = edge->y1 < coords[2*lower_neighbor+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* a generous upper bound on number of intersections is n_edges */
|
||||||
|
intersections = smalloc(n_edges * sizeof(int));
|
||||||
|
|
||||||
|
for(y = min_y; y <= max_y; y++) {
|
||||||
|
int n_intersections = 0;
|
||||||
|
for(i = 0; i < n_edges; i++) {
|
||||||
|
struct edge *edge = edges + i;
|
||||||
|
/* Update active edge set. These conditions are mutually
|
||||||
|
* exclusive because of the invariant that y1 < y2. */
|
||||||
|
if(edge->y1 + (edge->closed_y1 ? 0 : 1) == y)
|
||||||
|
edge->active = true;
|
||||||
|
else if(edge->y2 + 1 == y)
|
||||||
|
edge->active = false;
|
||||||
|
|
||||||
|
if(edge->active) {
|
||||||
|
int x = edges[i].x1;
|
||||||
|
x += (edges[i].inverse_slope * (y - edges[i].y1) + ONEHALF) >> FRACBITS;
|
||||||
|
intersections[n_intersections++] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(intersections, n_intersections, sizeof(int), compare_integers);
|
||||||
|
|
||||||
|
assert(n_intersections % 2 == 0);
|
||||||
|
assert(n_intersections <= n_edges);
|
||||||
|
|
||||||
|
/* Draw horizontal lines between successive pairs of
|
||||||
|
* intersections of the scanline with active edges. */
|
||||||
|
for(i = 0; i + 1 < n_intersections; i += 2) {
|
||||||
|
draw_line(dr,
|
||||||
|
intersections[i], y,
|
||||||
|
intersections[i+1], y,
|
||||||
|
fillcolour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sfree(intersections);
|
||||||
|
sfree(edges);
|
||||||
|
|
||||||
|
draw_outline:
|
||||||
|
assert(outlinecolour >= 0);
|
||||||
|
for (i = 0; i < 2 * npoints; i += 2)
|
||||||
|
draw_line(dr,
|
||||||
|
coords[i], coords[i+1],
|
||||||
|
coords[(i+2)%(2*npoints)], coords[(i+3)%(2*npoints)],
|
||||||
|
outlinecolour);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef STANDALONE_POLYGON
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standalone program to test draw_polygon_fallback(). By default,
|
||||||
|
* creates a window and allows clicking points to build a
|
||||||
|
* polygon. Optionally, can draw a randomly growing polygon in
|
||||||
|
* "screensaver" mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
|
||||||
|
{
|
||||||
|
SDL_Renderer *renderer = GET_HANDLE_AS_TYPE(dr, SDL_Renderer);
|
||||||
|
SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WINDOW_WIDTH 800
|
||||||
|
#define WINDOW_HEIGHT 600
|
||||||
|
#define MAX_SCREENSAVER_POINTS 1000
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
SDL_Window* window = NULL;
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_Renderer *renderer = NULL;
|
||||||
|
int running = 1;
|
||||||
|
int i;
|
||||||
|
drawing dr;
|
||||||
|
bool screensaver = false;
|
||||||
|
|
||||||
|
if(argc >= 2) {
|
||||||
|
if(!strcmp(argv[1], "--screensaver"))
|
||||||
|
screensaver = true;
|
||||||
|
else
|
||||||
|
printf("usage: %s [--screensaver]\n", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int *poly = NULL;
|
||||||
|
int n_points = 0;
|
||||||
|
|
||||||
|
/* Initialize SDL */
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
|
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create window */
|
||||||
|
window = SDL_CreateWindow("Polygon Drawing Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
|
||||||
|
if (!window) {
|
||||||
|
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create renderer */
|
||||||
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
|
if (!renderer) {
|
||||||
|
printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dr.handle = renderer;
|
||||||
|
|
||||||
|
if(!screensaver)
|
||||||
|
printf("Click points in the window to create vertices. Pressing C resets.\n");
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
while (SDL_PollEvent(&event) != 0) {
|
||||||
|
if (event.type == SDL_QUIT) {
|
||||||
|
running = 0;
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||||
|
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||||
|
int mouseX = event.button.x;
|
||||||
|
int mouseY = event.button.y;
|
||||||
|
|
||||||
|
poly = realloc(poly, ++n_points * 2 * sizeof(int));
|
||||||
|
poly[2 * (n_points - 1)] = mouseX;
|
||||||
|
poly[2 * (n_points - 1) + 1] = mouseY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_KEYDOWN) {
|
||||||
|
if (event.key.keysym.sym == SDLK_c) {
|
||||||
|
free(poly);
|
||||||
|
poly = NULL;
|
||||||
|
n_points = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(screensaver) {
|
||||||
|
poly = realloc(poly, ++n_points * 2 * sizeof(int));
|
||||||
|
poly[2 * (n_points - 1)] = rand() % WINDOW_WIDTH;
|
||||||
|
poly[2 * (n_points - 1) + 1] = rand() % WINDOW_HEIGHT;
|
||||||
|
|
||||||
|
if(n_points >= MAX_SCREENSAVER_POINTS) {
|
||||||
|
free(poly);
|
||||||
|
poly = NULL;
|
||||||
|
n_points = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the screen with a black color */
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
/* Set draw color to white */
|
||||||
|
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||||
|
|
||||||
|
draw_polygon_fallback(&dr, poly, n_points, 1, 1);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
||||||
|
for(i = 0; i < 2*n_points; i+=2)
|
||||||
|
SDL_RenderDrawPoint(renderer, poly[i], poly[i+1]);
|
||||||
|
|
||||||
|
/* Present the back buffer */
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up and quit SDL */
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -42,9 +42,12 @@ struct print_colour {
|
||||||
float grey;
|
float grey;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drawing {
|
typedef struct drawing_internal {
|
||||||
const drawing_api *api;
|
/* we implement data hiding by casting `struct drawing*` pointers
|
||||||
void *handle;
|
* to `struct drawing_internal*` */
|
||||||
|
struct drawing pub;
|
||||||
|
|
||||||
|
/* private data */
|
||||||
struct print_colour *colours;
|
struct print_colour *colours;
|
||||||
int ncolours, coloursize;
|
int ncolours, coloursize;
|
||||||
float scale;
|
float scale;
|
||||||
|
@ -52,52 +55,69 @@ struct drawing {
|
||||||
* this may set it to NULL. */
|
* this may set it to NULL. */
|
||||||
midend *me;
|
midend *me;
|
||||||
char *laststatus;
|
char *laststatus;
|
||||||
};
|
} drawing_internal;
|
||||||
|
|
||||||
|
#define PRIVATE_CAST(dr) ((drawing_internal*)(dr))
|
||||||
|
#define PUBLIC_CAST(dri) ((drawing*)(dri))
|
||||||
|
|
||||||
|
/* See puzzles.h for a description of the version number. */
|
||||||
|
#define DRAWING_API_VERSION 1
|
||||||
|
|
||||||
drawing *drawing_new(const drawing_api *api, midend *me, void *handle)
|
drawing *drawing_new(const drawing_api *api, midend *me, void *handle)
|
||||||
{
|
{
|
||||||
drawing *dr = snew(drawing);
|
if(api->version != DRAWING_API_VERSION) {
|
||||||
dr->api = api;
|
fatal("Drawing API version mismatch: expected: %d, actual: %d\n", DRAWING_API_VERSION, api->version);
|
||||||
dr->handle = handle;
|
/* shouldn't get here */
|
||||||
dr->colours = NULL;
|
return NULL;
|
||||||
dr->ncolours = dr->coloursize = 0;
|
}
|
||||||
dr->scale = 1.0F;
|
|
||||||
dr->me = me;
|
drawing_internal *dri = snew(drawing_internal);
|
||||||
dr->laststatus = NULL;
|
dri->pub.api = api;
|
||||||
return dr;
|
dri->pub.handle = handle;
|
||||||
|
dri->colours = NULL;
|
||||||
|
dri->ncolours = dri->coloursize = 0;
|
||||||
|
dri->scale = 1.0F;
|
||||||
|
dri->me = me;
|
||||||
|
dri->laststatus = NULL;
|
||||||
|
return PUBLIC_CAST(dri);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawing_free(drawing *dr)
|
void drawing_free(drawing *dr)
|
||||||
{
|
{
|
||||||
sfree(dr->laststatus);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
sfree(dr->colours);
|
sfree(dri->laststatus);
|
||||||
sfree(dr);
|
sfree(dri->colours);
|
||||||
|
sfree(dri);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
|
void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
|
||||||
int align, int colour, const char *text)
|
int align, int colour, const char *text)
|
||||||
{
|
{
|
||||||
dr->api->draw_text(dr->handle, x, y, fonttype, fontsize, align,
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->draw_text(dr, x, y, fonttype, fontsize, align,
|
||||||
colour, text);
|
colour, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
void draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
||||||
{
|
{
|
||||||
dr->api->draw_rect(dr->handle, x, y, w, h, colour);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->draw_rect(dr, x, y, w, h, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
|
void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
|
||||||
{
|
{
|
||||||
dr->api->draw_line(dr->handle, x1, y1, x2, y2, colour);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->draw_line(dr, x1, y1, x2, y2, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_thick_line(drawing *dr, float thickness,
|
void draw_thick_line(drawing *dr, float thickness,
|
||||||
float x1, float y1, float x2, float y2, int colour)
|
float x1, float y1, float x2, float y2, int colour)
|
||||||
{
|
{
|
||||||
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
if (thickness < 1.0F)
|
if (thickness < 1.0F)
|
||||||
thickness = 1.0F;
|
thickness = 1.0F;
|
||||||
if (dr->api->draw_thick_line) {
|
if (dri->pub.api->draw_thick_line) {
|
||||||
dr->api->draw_thick_line(dr->handle, thickness,
|
dri->pub.api->draw_thick_line(dr, thickness,
|
||||||
x1, y1, x2, y2, colour);
|
x1, y1, x2, y2, colour);
|
||||||
} else {
|
} else {
|
||||||
/* We'll fake it up with a filled polygon. The tweak to the
|
/* We'll fake it up with a filled polygon. The tweak to the
|
||||||
|
@ -117,59 +137,67 @@ void draw_thick_line(drawing *dr, float thickness,
|
||||||
p[5] = y2 - tvhatx;
|
p[5] = y2 - tvhatx;
|
||||||
p[6] = x1 + tvhaty;
|
p[6] = x1 + tvhaty;
|
||||||
p[7] = y1 - tvhatx;
|
p[7] = y1 - tvhatx;
|
||||||
dr->api->draw_polygon(dr->handle, p, 4, colour, colour);
|
dri->pub.api->draw_polygon(dr, p, 4, colour, colour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_polygon(drawing *dr, const int *coords, int npoints,
|
void draw_polygon(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
dr->api->draw_polygon(dr->handle, coords, npoints, fillcolour,
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->draw_polygon(dr, coords, npoints, fillcolour,
|
||||||
outlinecolour);
|
outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_circle(drawing *dr, int cx, int cy, int radius,
|
void draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
dr->api->draw_circle(dr->handle, cx, cy, radius, fillcolour,
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->draw_circle(dr, cx, cy, radius, fillcolour,
|
||||||
outlinecolour);
|
outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_update(drawing *dr, int x, int y, int w, int h)
|
void draw_update(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
if (dr->api->draw_update)
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
dr->api->draw_update(dr->handle, x, y, w, h);
|
if (dri->pub.api->draw_update)
|
||||||
|
dri->pub.api->draw_update(dr, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clip(drawing *dr, int x, int y, int w, int h)
|
void clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
dr->api->clip(dr->handle, x, y, w, h);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->clip(dr, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unclip(drawing *dr)
|
void unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->unclip(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->unclip(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_draw(drawing *dr)
|
void start_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->start_draw(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->start_draw(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_draw(drawing *dr)
|
void end_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->end_draw(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->end_draw(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *text_fallback(drawing *dr, const char *const *strings, int nstrings)
|
char *text_fallback(drawing *dr, const char *const *strings, int nstrings)
|
||||||
{
|
{
|
||||||
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the drawing implementation provides one of these, use it.
|
* If the drawing implementation provides one of these, use it.
|
||||||
*/
|
*/
|
||||||
if (dr && dr->api->text_fallback)
|
if (dr && dri->pub.api->text_fallback)
|
||||||
return dr->api->text_fallback(dr->handle, strings, nstrings);
|
return dri->pub.api->text_fallback(dr, strings, nstrings);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise, do the simple thing and just pick the first string
|
* Otherwise, do the simple thing and just pick the first string
|
||||||
|
@ -196,18 +224,19 @@ char *text_fallback(drawing *dr, const char *const *strings, int nstrings)
|
||||||
|
|
||||||
void status_bar(drawing *dr, const char *text)
|
void status_bar(drawing *dr, const char *text)
|
||||||
{
|
{
|
||||||
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
char *rewritten;
|
char *rewritten;
|
||||||
|
|
||||||
if (!dr->api->status_bar)
|
if (!dri->pub.api->status_bar)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(dr->me);
|
assert(dri->me);
|
||||||
|
|
||||||
rewritten = midend_rewrite_statusbar(dr->me, text);
|
rewritten = midend_rewrite_statusbar(dri->me, text);
|
||||||
if (!dr->laststatus || strcmp(rewritten, dr->laststatus)) {
|
if (!dri->laststatus || strcmp(rewritten, dri->laststatus)) {
|
||||||
dr->api->status_bar(dr->handle, rewritten);
|
dri->pub.api->status_bar(dr, rewritten);
|
||||||
sfree(dr->laststatus);
|
sfree(dri->laststatus);
|
||||||
dr->laststatus = rewritten;
|
dri->laststatus = rewritten;
|
||||||
} else {
|
} else {
|
||||||
sfree(rewritten);
|
sfree(rewritten);
|
||||||
}
|
}
|
||||||
|
@ -215,74 +244,85 @@ void status_bar(drawing *dr, const char *text)
|
||||||
|
|
||||||
blitter *blitter_new(drawing *dr, int w, int h)
|
blitter *blitter_new(drawing *dr, int w, int h)
|
||||||
{
|
{
|
||||||
return dr->api->blitter_new(dr->handle, w, h);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
return dri->pub.api->blitter_new(dr, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blitter_free(drawing *dr, blitter *bl)
|
void blitter_free(drawing *dr, blitter *bl)
|
||||||
{
|
{
|
||||||
dr->api->blitter_free(dr->handle, bl);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->blitter_free(dr, bl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blitter_save(drawing *dr, blitter *bl, int x, int y)
|
void blitter_save(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
dr->api->blitter_save(dr->handle, bl, x, y);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->blitter_save(dr, bl, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blitter_load(drawing *dr, blitter *bl, int x, int y)
|
void blitter_load(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
dr->api->blitter_load(dr->handle, bl, x, y);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->blitter_load(dr, bl, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_begin_doc(drawing *dr, int pages)
|
void print_begin_doc(drawing *dr, int pages)
|
||||||
{
|
{
|
||||||
dr->api->begin_doc(dr->handle, pages);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->begin_doc(dr, pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_begin_page(drawing *dr, int number)
|
void print_begin_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
dr->api->begin_page(dr->handle, number);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->begin_page(dr, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_begin_puzzle(drawing *dr, float xm, float xc,
|
void print_begin_puzzle(drawing *dr, float xm, float xc,
|
||||||
float ym, float yc, int pw, int ph, float wmm,
|
float ym, float yc, int pw, int ph, float wmm,
|
||||||
float scale)
|
float scale)
|
||||||
{
|
{
|
||||||
dr->scale = scale;
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
dr->ncolours = 0;
|
dri->scale = scale;
|
||||||
dr->api->begin_puzzle(dr->handle, xm, xc, ym, yc, pw, ph, wmm);
|
dri->ncolours = 0;
|
||||||
|
dri->pub.api->begin_puzzle(dr, xm, xc, ym, yc, pw, ph, wmm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_end_puzzle(drawing *dr)
|
void print_end_puzzle(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->end_puzzle(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
dr->scale = 1.0F;
|
dri->pub.api->end_puzzle(dr);
|
||||||
|
dri->scale = 1.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_end_page(drawing *dr, int number)
|
void print_end_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
dr->api->end_page(dr->handle, number);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->end_page(dr, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_end_doc(drawing *dr)
|
void print_end_doc(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->end_doc(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->end_doc(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_get_colour(drawing *dr, int colour, bool printing_in_colour,
|
void print_get_colour(drawing *dr, int colour, bool printing_in_colour,
|
||||||
int *hatch, float *r, float *g, float *b)
|
int *hatch, float *r, float *g, float *b)
|
||||||
{
|
{
|
||||||
assert(colour >= 0 && colour < dr->ncolours);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
if (dr->colours[colour].hatch_when == 2 ||
|
assert(colour >= 0 && colour < dri->ncolours);
|
||||||
(dr->colours[colour].hatch_when == 1 && !printing_in_colour)) {
|
if (dri->colours[colour].hatch_when == 2 ||
|
||||||
*hatch = dr->colours[colour].hatch;
|
(dri->colours[colour].hatch_when == 1 && !printing_in_colour)) {
|
||||||
|
*hatch = dri->colours[colour].hatch;
|
||||||
} else {
|
} else {
|
||||||
*hatch = -1;
|
*hatch = -1;
|
||||||
if (printing_in_colour) {
|
if (printing_in_colour) {
|
||||||
*r = dr->colours[colour].r;
|
*r = dri->colours[colour].r;
|
||||||
*g = dr->colours[colour].g;
|
*g = dri->colours[colour].g;
|
||||||
*b = dr->colours[colour].b;
|
*b = dri->colours[colour].b;
|
||||||
} else {
|
} else {
|
||||||
*r = *g = *b = dr->colours[colour].grey;
|
*r = *g = *b = dri->colours[colour].grey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,18 +330,19 @@ void print_get_colour(drawing *dr, int colour, bool printing_in_colour,
|
||||||
static int print_generic_colour(drawing *dr, float r, float g, float b,
|
static int print_generic_colour(drawing *dr, float r, float g, float b,
|
||||||
float grey, int hatch, int hatch_when)
|
float grey, int hatch, int hatch_when)
|
||||||
{
|
{
|
||||||
if (dr->ncolours >= dr->coloursize) {
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
dr->coloursize = dr->ncolours + 16;
|
if (dri->ncolours >= dri->coloursize) {
|
||||||
dr->colours = sresize(dr->colours, dr->coloursize,
|
dri->coloursize = dri->ncolours + 16;
|
||||||
|
dri->colours = sresize(dri->colours, dri->coloursize,
|
||||||
struct print_colour);
|
struct print_colour);
|
||||||
}
|
}
|
||||||
dr->colours[dr->ncolours].hatch = hatch;
|
dri->colours[dri->ncolours].hatch = hatch;
|
||||||
dr->colours[dr->ncolours].hatch_when = hatch_when;
|
dri->colours[dri->ncolours].hatch_when = hatch_when;
|
||||||
dr->colours[dr->ncolours].r = r;
|
dri->colours[dri->ncolours].r = r;
|
||||||
dr->colours[dr->ncolours].g = g;
|
dri->colours[dri->ncolours].g = g;
|
||||||
dr->colours[dr->ncolours].b = b;
|
dri->colours[dri->ncolours].b = b;
|
||||||
dr->colours[dr->ncolours].grey = grey;
|
dri->colours[dri->ncolours].grey = grey;
|
||||||
return dr->ncolours++;
|
return dri->ncolours++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_mono_colour(drawing *dr, int grey)
|
int print_mono_colour(drawing *dr, int grey)
|
||||||
|
@ -336,6 +377,8 @@ int print_rgb_hatched_colour(drawing *dr, float r, float g, float b, int hatch)
|
||||||
|
|
||||||
void print_line_width(drawing *dr, int width)
|
void print_line_width(drawing *dr, int width)
|
||||||
{
|
{
|
||||||
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I don't think it's entirely sensible to have line widths be
|
* I don't think it's entirely sensible to have line widths be
|
||||||
* entirely relative to the puzzle size; there is a point
|
* entirely relative to the puzzle size; there is a point
|
||||||
|
@ -348,10 +391,11 @@ void print_line_width(drawing *dr, int width)
|
||||||
* _square root_ of the main puzzle scale. Double the puzzle
|
* _square root_ of the main puzzle scale. Double the puzzle
|
||||||
* size, and the line width multiplies by 1.4.
|
* size, and the line width multiplies by 1.4.
|
||||||
*/
|
*/
|
||||||
dr->api->line_width(dr->handle, (float)sqrt(dr->scale) * width);
|
dri->pub.api->line_width(dr, (float)sqrt(dri->scale) * width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_line_dotted(drawing *dr, bool dotted)
|
void print_line_dotted(drawing *dr, bool dotted)
|
||||||
{
|
{
|
||||||
dr->api->line_dotted(dr->handle, dotted);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->line_dotted(dr, dotted);
|
||||||
}
|
}
|
||||||
|
|
|
@ -722,18 +722,6 @@ static int move_goes_to(int w, int h, char *grid, int x, int y, int d)
|
||||||
return (y*w+x)*DP1+dr;
|
return (y*w+x)*DP1+dr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int compare_integers(const void *av, const void *bv)
|
|
||||||
{
|
|
||||||
const int *a = (const int *)av;
|
|
||||||
const int *b = (const int *)bv;
|
|
||||||
if (*a < *b)
|
|
||||||
return -1;
|
|
||||||
else if (*a > *b)
|
|
||||||
return +1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *solve_game(const game_state *state, const game_state *currstate,
|
static char *solve_game(const game_state *state, const game_state *currstate,
|
||||||
const char *aux, const char **error)
|
const char *aux, const char **error)
|
||||||
{
|
{
|
||||||
|
@ -1886,11 +1874,6 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y,
|
||||||
coords[d*4+2] = x + TILESIZE/2 + (int)((TILESIZE*3/7) * x2);
|
coords[d*4+2] = x + TILESIZE/2 + (int)((TILESIZE*3/7) * x2);
|
||||||
coords[d*4+3] = y + TILESIZE/2 + (int)((TILESIZE*3/7) * y2);
|
coords[d*4+3] = y + TILESIZE/2 + (int)((TILESIZE*3/7) * y2);
|
||||||
}
|
}
|
||||||
/* rockbox hack */
|
|
||||||
int tmp[2] = { coords[0], coords[1] };
|
|
||||||
memmove(coords, coords + 2, sizeof(int) * DIRECTIONS * 4 - 2);
|
|
||||||
memcpy(coords + DIRECTIONS * 4 - 2, tmp, 2 * sizeof(int));
|
|
||||||
|
|
||||||
draw_polygon(dr, coords, DIRECTIONS*2, COL_DEAD_PLAYER, COL_OUTLINE);
|
draw_polygon(dr, coords, DIRECTIONS*2, COL_DEAD_PLAYER, COL_OUTLINE);
|
||||||
} else {
|
} else {
|
||||||
draw_circle(dr, x + TILESIZE/2, y + TILESIZE/2,
|
draw_circle(dr, x + TILESIZE/2, y + TILESIZE/2,
|
||||||
|
@ -1906,6 +1889,8 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y,
|
||||||
int coords[14], *c;
|
int coords[14], *c;
|
||||||
|
|
||||||
c = coords;
|
c = coords;
|
||||||
|
*c++ = ox + px/9;
|
||||||
|
*c++ = oy + py/9;
|
||||||
*c++ = ox + px/9 + ax*2/3;
|
*c++ = ox + px/9 + ax*2/3;
|
||||||
*c++ = oy + py/9 + ay*2/3;
|
*c++ = oy + py/9 + ay*2/3;
|
||||||
*c++ = ox + px/3 + ax*2/3;
|
*c++ = ox + px/3 + ax*2/3;
|
||||||
|
@ -1918,8 +1903,6 @@ static void draw_player(drawing *dr, game_drawstate *ds, int x, int y,
|
||||||
*c++ = oy - py/9 + ay*2/3;
|
*c++ = oy - py/9 + ay*2/3;
|
||||||
*c++ = ox - px/9;
|
*c++ = ox - px/9;
|
||||||
*c++ = oy - py/9;
|
*c++ = oy - py/9;
|
||||||
*c++ = ox + px/9;
|
|
||||||
*c++ = oy + py/9;
|
|
||||||
draw_polygon(dr, coords, 7, COL_HINT, COL_OUTLINE);
|
draw_polygon(dr, coords, 7, COL_HINT, COL_OUTLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2867,12 +2867,12 @@ static void draw_tile(drawing *dr, game_drawstate *ds,
|
||||||
coords[(n)*2+0] = x + (int)(TILE_SIZE * (dx)); \
|
coords[(n)*2+0] = x + (int)(TILE_SIZE * (dx)); \
|
||||||
coords[(n)*2+1] = y + (int)(TILE_SIZE * (dy)); \
|
coords[(n)*2+1] = y + (int)(TILE_SIZE * (dy)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
SETCOORD(0, 0.6F, 0.7F);
|
SETCOORD(0, 0.6F, 0.35F);
|
||||||
SETCOORD(1, 0.8F, 0.8F);
|
SETCOORD(1, 0.6F, 0.7F);
|
||||||
SETCOORD(2, 0.25F, 0.8F);
|
SETCOORD(2, 0.8F, 0.8F);
|
||||||
SETCOORD(3, 0.55F, 0.7F);
|
SETCOORD(3, 0.25F, 0.8F);
|
||||||
SETCOORD(4, 0.55F, 0.35F);
|
SETCOORD(4, 0.55F, 0.7F);
|
||||||
SETCOORD(5, 0.6F, 0.35F);
|
SETCOORD(5, 0.55F, 0.35F);
|
||||||
draw_polygon(dr, coords, 6, COL_FLAGBASE, COL_FLAGBASE);
|
draw_polygon(dr, coords, 6, COL_FLAGBASE, COL_FLAGBASE);
|
||||||
|
|
||||||
SETCOORD(0, 0.6F, 0.2F);
|
SETCOORD(0, 0.6F, 0.2F);
|
||||||
|
|
|
@ -351,6 +351,17 @@ void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col)
|
||||||
draw_line(dr, cx + r, cy + r, cx + r/2, cy + r, col);
|
draw_line(dr, cx + r, cy + r, cx + r/2, cy + r, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int compare_integers(const void *av, const void *bv) {
|
||||||
|
const int *a = (const int *)av;
|
||||||
|
const int *b = (const int *)bv;
|
||||||
|
if (*a < *b)
|
||||||
|
return -1;
|
||||||
|
else if (*a > *b)
|
||||||
|
return +1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap,
|
char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap,
|
||||||
bool *visible)
|
bool *visible)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3442,7 +3442,7 @@ real challenge, set this value to 0 and then try to solve a grid in
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
\C{tracks} \i{Train Tracks}
|
\C{tracks} \i{Tracks}
|
||||||
|
|
||||||
\cfg{winhelp-topic}{games.tracks}
|
\cfg{winhelp-topic}{games.tracks}
|
||||||
|
|
||||||
|
@ -3454,9 +3454,9 @@ clues to the top and right of the grid.
|
||||||
There are only straight and 90 degree curved rails, and the track may not
|
There are only straight and 90 degree curved rails, and the track may not
|
||||||
cross itself.
|
cross itself.
|
||||||
|
|
||||||
Train Tracks was contributed to this collection by James Harvey.
|
Tracks was contributed to this collection by James Harvey.
|
||||||
|
|
||||||
\H{tracks-controls} \I{controls, for Tracks}Train Tracks controls
|
\H{tracks-controls} \I{controls, for Tracks}Tracks controls
|
||||||
|
|
||||||
Left-clicking on an edge between two squares adds a track segment between
|
Left-clicking on an edge between two squares adds a track segment between
|
||||||
the two squares. Right-clicking on an edge adds a cross on the edge,
|
the two squares. Right-clicking on an edge adds a cross on the edge,
|
||||||
|
@ -3473,7 +3473,7 @@ columns to match the clue.
|
||||||
|
|
||||||
(All the actions described in \k{common-actions} are also available.)
|
(All the actions described in \k{common-actions} are also available.)
|
||||||
|
|
||||||
\H{tracks-parameters} \I{parameters, for Tracks}Train Tracks parameters
|
\H{tracks-parameters} \I{parameters, for Tracks}Tracks parameters
|
||||||
|
|
||||||
These parameters are available from the \q{Custom...} option on the
|
These parameters are available from the \q{Custom...} option on the
|
||||||
\q{Type} menu.
|
\q{Type} menu.
|
||||||
|
@ -3490,12 +3490,12 @@ that would lead to impossible crossings later.
|
||||||
|
|
||||||
\dt \e{Disallow consecutive 1 clues}
|
\dt \e{Disallow consecutive 1 clues}
|
||||||
|
|
||||||
\dd Controls whether the Train Tracks game generation permits two
|
\dd Controls whether the Tracks game generation permits two adjacent
|
||||||
adjacent rows or columns to have a 1 clue, or permits the row or
|
rows or columns to have a 1 clue, or permits the row or column of the
|
||||||
column of the track's endpoint to have a 1 clue. By default this is
|
track's endpoint to have a 1 clue. By default this is not permitted,
|
||||||
not permitted, to avoid long straight boring segments of track and
|
to avoid long straight boring segments of track and make the games
|
||||||
make the games more twiddly and interesting. If you want to restore
|
more twiddly and interesting. If you want to restore the possibility,
|
||||||
the possibility, turn this option off.
|
turn this option off.
|
||||||
|
|
||||||
|
|
||||||
\C{palisade} \i{Palisade}
|
\C{palisade} \i{Palisade}
|
||||||
|
|
|
@ -266,6 +266,8 @@ void draw_rect(drawing *dr, int x, int y, int w, int h, int colour);
|
||||||
void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour);
|
void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour);
|
||||||
void draw_polygon(drawing *dr, const int *coords, int npoints,
|
void draw_polygon(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour);
|
int fillcolour, int outlinecolour);
|
||||||
|
void draw_polygon_fallback(drawing *dr, const int *coords, int npoints,
|
||||||
|
int fillcolour, int outlinecolour);
|
||||||
void draw_circle(drawing *dr, int cx, int cy, int radius,
|
void draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour);
|
int fillcolour, int outlinecolour);
|
||||||
void draw_thick_line(drawing *dr, float thickness,
|
void draw_thick_line(drawing *dr, float thickness,
|
||||||
|
@ -454,6 +456,9 @@ char *button2label(int button);
|
||||||
* standard per clause 7.26.11.1.) */
|
* standard per clause 7.26.11.1.) */
|
||||||
void swap_regions(void *av, void *bv, size_t size);
|
void swap_regions(void *av, void *bv, size_t size);
|
||||||
|
|
||||||
|
/* comparator for sorting ints with qsort() */
|
||||||
|
int compare_integers(const void *av, const void *bv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dsf.c
|
* dsf.c
|
||||||
*/
|
*/
|
||||||
|
@ -752,43 +757,76 @@ struct game {
|
||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GET_HANDLE_AS_TYPE(dr, type) ((type*)((dr)->handle))
|
||||||
|
|
||||||
|
struct drawing {
|
||||||
|
const drawing_api *api;
|
||||||
|
void *handle;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data structure containing the drawing API implemented by the
|
* Data structure containing the drawing API implemented by the
|
||||||
* front end and also by cross-platform printing modules such as
|
* front end and also by cross-platform printing modules such as
|
||||||
* PostScript.
|
* PostScript.
|
||||||
*/
|
*/
|
||||||
struct drawing_api {
|
struct drawing_api {
|
||||||
void (*draw_text)(void *handle, int x, int y, int fonttype, int fontsize,
|
/*
|
||||||
|
* API version. Increment this when there is a breaking change to
|
||||||
|
* this API which requires front ends to change.
|
||||||
|
*
|
||||||
|
* There is expliclty not a public LATEST_API_VERSION define, so
|
||||||
|
* that front end authors will need to manually intervene when the
|
||||||
|
* version number changes. Naturally, this should be done
|
||||||
|
* sparingly.
|
||||||
|
*
|
||||||
|
* If a function is ever added to this API, please move this field
|
||||||
|
* to the _end_ of the structure, so that changes thereafter will
|
||||||
|
* shift the position of the version and lead to a compilation
|
||||||
|
* error if old implementations are not updated. Then remove this
|
||||||
|
* comment.
|
||||||
|
*
|
||||||
|
* The latest version number is 1.
|
||||||
|
*
|
||||||
|
* Change log:
|
||||||
|
*
|
||||||
|
* Version 1 (2024-08-14): Introduction of version number, in
|
||||||
|
* conjunction with changing every API function to take `drawing
|
||||||
|
* *` instead of `void *`. See commit f379130 for the detailed
|
||||||
|
* rationale behind this change.
|
||||||
|
*/
|
||||||
|
int version;
|
||||||
|
|
||||||
|
void (*draw_text)(drawing *dr, int x, int y, int fonttype, int fontsize,
|
||||||
int align, int colour, const char *text);
|
int align, int colour, const char *text);
|
||||||
void (*draw_rect)(void *handle, int x, int y, int w, int h, int colour);
|
void (*draw_rect)(drawing *dr, int x, int y, int w, int h, int colour);
|
||||||
void (*draw_line)(void *handle, int x1, int y1, int x2, int y2,
|
void (*draw_line)(drawing *dr, int x1, int y1, int x2, int y2,
|
||||||
int colour);
|
int colour);
|
||||||
void (*draw_polygon)(void *handle, const int *coords, int npoints,
|
void (*draw_polygon)(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour);
|
int fillcolour, int outlinecolour);
|
||||||
void (*draw_circle)(void *handle, int cx, int cy, int radius,
|
void (*draw_circle)(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour);
|
int fillcolour, int outlinecolour);
|
||||||
void (*draw_update)(void *handle, int x, int y, int w, int h);
|
void (*draw_update)(drawing *dr, int x, int y, int w, int h);
|
||||||
void (*clip)(void *handle, int x, int y, int w, int h);
|
void (*clip)(drawing *dr, int x, int y, int w, int h);
|
||||||
void (*unclip)(void *handle);
|
void (*unclip)(drawing *dr);
|
||||||
void (*start_draw)(void *handle);
|
void (*start_draw)(drawing *dr);
|
||||||
void (*end_draw)(void *handle);
|
void (*end_draw)(drawing *dr);
|
||||||
void (*status_bar)(void *handle, const char *text);
|
void (*status_bar)(drawing *dr, const char *text);
|
||||||
blitter *(*blitter_new)(void *handle, int w, int h);
|
blitter *(*blitter_new)(drawing *dr, int w, int h);
|
||||||
void (*blitter_free)(void *handle, blitter *bl);
|
void (*blitter_free)(drawing *dr, blitter *bl);
|
||||||
void (*blitter_save)(void *handle, blitter *bl, int x, int y);
|
void (*blitter_save)(drawing *dr, blitter *bl, int x, int y);
|
||||||
void (*blitter_load)(void *handle, blitter *bl, int x, int y);
|
void (*blitter_load)(drawing *dr, blitter *bl, int x, int y);
|
||||||
void (*begin_doc)(void *handle, int pages);
|
void (*begin_doc)(drawing *dr, int pages);
|
||||||
void (*begin_page)(void *handle, int number);
|
void (*begin_page)(drawing *dr, int number);
|
||||||
void (*begin_puzzle)(void *handle, float xm, float xc,
|
void (*begin_puzzle)(drawing *dr, float xm, float xc,
|
||||||
float ym, float yc, int pw, int ph, float wmm);
|
float ym, float yc, int pw, int ph, float wmm);
|
||||||
void (*end_puzzle)(void *handle);
|
void (*end_puzzle)(drawing *dr);
|
||||||
void (*end_page)(void *handle, int number);
|
void (*end_page)(drawing *dr, int number);
|
||||||
void (*end_doc)(void *handle);
|
void (*end_doc)(drawing *dr);
|
||||||
void (*line_width)(void *handle, float width);
|
void (*line_width)(drawing *dr, float width);
|
||||||
void (*line_dotted)(void *handle, bool dotted);
|
void (*line_dotted)(drawing *dr, bool dotted);
|
||||||
char *(*text_fallback)(void *handle, const char *const *strings,
|
char *(*text_fallback)(drawing *dr, const char *const *strings,
|
||||||
int nstrings);
|
int nstrings);
|
||||||
void (*draw_thick_line)(void *handle, float thickness,
|
void (*draw_thick_line)(drawing *dr, float thickness,
|
||||||
float x1, float y1, float x2, float y2,
|
float x1, float y1, float x2, float y2,
|
||||||
int colour);
|
int colour);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1895,9 +1895,8 @@ static void draw_star(drawing *dr, int cx, int cy, int rad, int npoints,
|
||||||
coords = snewn(npoints * 2 * 2, int);
|
coords = snewn(npoints * 2 * 2, int);
|
||||||
|
|
||||||
for (n = 0; n < npoints * 2; n++) {
|
for (n = 0; n < npoints * 2; n++) {
|
||||||
/* hack to accomodate rockbox's concave polygon drawing */
|
a = 2.0 * PI * ((double)n / ((double)npoints * 2.0)) + angle_offset;
|
||||||
a = 2.0 * PI * ((double)n / ((double)npoints * 2.0)) + angle_offset - PI / npoints;
|
r = (n % 2) ? (double)rad/2.0 : (double)rad;
|
||||||
r = (n % 2 == 0) ? (double)rad/2.0 : (double)rad;
|
|
||||||
|
|
||||||
/* We're rotating the point at (0, -r) by a degrees */
|
/* We're rotating the point at (0, -r) by a degrees */
|
||||||
coords[2*n+0] = cx + (int)( r * sin(a));
|
coords[2*n+0] = cx + (int)( r * sin(a));
|
||||||
|
|
|
@ -532,18 +532,6 @@ static void free_game(game_state *state)
|
||||||
sfree(state);
|
sfree(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int compare_int(const void *av, const void *bv)
|
|
||||||
{
|
|
||||||
const int *a = (const int *)av;
|
|
||||||
const int *b = (const int *)bv;
|
|
||||||
if (*a < *b)
|
|
||||||
return -1;
|
|
||||||
else if (*a > *b)
|
|
||||||
return +1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *solve_game(const game_state *state, const game_state *currstate,
|
static char *solve_game(const game_state *state, const game_state *currstate,
|
||||||
const char *aux, const char **error)
|
const char *aux, const char **error)
|
||||||
{
|
{
|
||||||
|
@ -758,7 +746,7 @@ static game_state *execute_move(const game_state *from, const char *move)
|
||||||
* conveniently being able to get hold of a clean state from
|
* conveniently being able to get hold of a clean state from
|
||||||
* which to practise manoeuvres.
|
* which to practise manoeuvres.
|
||||||
*/
|
*/
|
||||||
qsort(ret->grid, ret->w*ret->h, sizeof(int), compare_int);
|
qsort(ret->grid, ret->w*ret->h, sizeof(int), compare_integers);
|
||||||
for (i = 0; i < ret->w*ret->h; i++)
|
for (i = 0; i < ret->w*ret->h; i++)
|
||||||
ret->grid[i] &= ~3;
|
ret->grid[i] &= ~3;
|
||||||
ret->used_solve = true;
|
ret->used_solve = true;
|
||||||
|
|
|
@ -1844,18 +1844,18 @@ static void draw_gt(drawing *dr, int ox, int oy,
|
||||||
{
|
{
|
||||||
int coords[12];
|
int coords[12];
|
||||||
int xdx = (dx1+dx2 ? 0 : 1), xdy = (dx1+dx2 ? 1 : 0);
|
int xdx = (dx1+dx2 ? 0 : 1), xdy = (dx1+dx2 ? 1 : 0);
|
||||||
coords[0] = ox + xdx + dx1;
|
coords[0] = ox + xdx;
|
||||||
coords[1] = oy + xdy + dy1;
|
coords[1] = oy + xdy;
|
||||||
coords[2] = ox + xdx + dx1 + dx2;
|
coords[2] = ox + xdx + dx1;
|
||||||
coords[3] = oy + xdy + dy1 + dy2;
|
coords[3] = oy + xdy + dy1;
|
||||||
coords[4] = ox - xdx + dx1 + dx2;
|
coords[4] = ox + xdx + dx1 + dx2;
|
||||||
coords[5] = oy - xdy + dy1 + dy2;
|
coords[5] = oy + xdy + dy1 + dy2;
|
||||||
coords[6] = ox - xdx + dx1;
|
coords[6] = ox - xdx + dx1 + dx2;
|
||||||
coords[7] = oy - xdy + dy1;
|
coords[7] = oy - xdy + dy1 + dy2;
|
||||||
coords[8] = ox - xdx;
|
coords[8] = ox - xdx + dx1;
|
||||||
coords[9] = oy - xdy;
|
coords[9] = oy - xdy + dy1;
|
||||||
coords[10] = ox + xdx;
|
coords[10] = ox - xdx;
|
||||||
coords[11] = oy + xdy;
|
coords[11] = oy - xdy;
|
||||||
draw_polygon(dr, coords, 6, col, col);
|
draw_polygon(dr, coords, 6, col, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue