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
|
||||
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
|
||||
================
|
||||
|
||||
|
@ -44,16 +39,8 @@ to Untangle and Palisade). These divergent changes complicated
|
|||
maintenance of this port, as merge conflicts often arose when upstream
|
||||
changes to these games conflicted with our changes. To remedy this, I
|
||||
sent most of these patches back upstream in summer 2024, and since
|
||||
then, Simon has merged the majority of them into his 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.
|
||||
then, Simon has merged them into his repo. We are now able to run with
|
||||
a fully unmodified puzzles source tree.
|
||||
|
||||
Maintenance
|
||||
===========
|
||||
|
@ -62,7 +49,7 @@ Simon's upstream tree sees continued development. The port is
|
|||
structured so that integrating new upstream versions is
|
||||
straightforward: all the upstream sources live in the src/
|
||||
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
|
||||
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
|
||||
========
|
||||
|
||||
- Proper polygon filling algorithm. The current algorithm is a hack
|
||||
that uses overdrawn triangles. This will enable us to eliminate the
|
||||
last of the Rockbox-specific modifications.
|
||||
- Nothing!
|
||||
|
||||
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
|
||||
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 */
|
||||
src/combi.c
|
||||
src/divvy.c
|
||||
src/draw-poly.c
|
||||
src/drawing.c
|
||||
src/dsf.c
|
||||
src/findloop.c
|
||||
|
|
|
@ -6,148 +6,148 @@
|
|||
|
||||
struct style_text help_text_style[] = {
|
||||
{ 0, TEXT_CENTER | C_RED },
|
||||
{ 88, TEXT_CENTER | C_RED },
|
||||
{ 209, TEXT_CENTER | C_RED },
|
||||
{ 87, TEXT_CENTER | C_RED },
|
||||
{ 208, TEXT_CENTER | C_RED },
|
||||
{ 225, TEXT_UNDERLINE },
|
||||
{ 226, TEXT_UNDERLINE },
|
||||
{ 227, TEXT_UNDERLINE },
|
||||
{ 238, TEXT_UNDERLINE },
|
||||
{ 270, TEXT_UNDERLINE },
|
||||
{ 237, TEXT_UNDERLINE },
|
||||
{ 269, TEXT_UNDERLINE },
|
||||
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[] = {
|
||||
0xf0, 0x02, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20,
|
||||
0x34, 0x30, 0x3a, 0x20, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x06,
|
||||
0x00, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x00, 0x2d, 0x01, 0x00,
|
||||
0x04, 0xf0, 0x19, 0x00, 0x00, 0x00, 0x59, 0x6f, 0x75, 0x00,
|
||||
0x61, 0x72, 0x65, 0x00, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x00,
|
||||
0x61, 0x00, 0x67, 0x72, 0x69, 0x64, 0x00, 0x6f, 0x66, 0x00,
|
||||
0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x2c, 0x00, 0x73,
|
||||
0x6f, 0x6d, 0x65, 0x11, 0x00, 0x51, 0x77, 0x68, 0x69, 0x63,
|
||||
0x68, 0x2b, 0x00, 0xd0, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64,
|
||||
0x00, 0x77, 0x69, 0x74, 0x68, 0x00, 0x74, 0x68, 0x00, 0x21,
|
||||
0x00, 0x74, 0x68, 0x00, 0x11, 0x2e, 0x4d, 0x00, 0xf2, 0x05,
|
||||
0x6e, 0x65, 0x65, 0x64, 0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f,
|
||||
0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x00, 0x74, 0x68, 0x65,
|
||||
0x21, 0x00, 0x70, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x00, 0x41,
|
||||
0x1d, 0x00, 0x91, 0x42, 0x00, 0x73, 0x6f, 0x00, 0x74, 0x68,
|
||||
0x61, 0x74, 0x1e, 0x00, 0xf1, 0x06, 0x72, 0x6f, 0x77, 0x73,
|
||||
0x00, 0x61, 0x6e, 0x64, 0x00, 0x63, 0x6f, 0x6c, 0x75, 0x6d,
|
||||
0x6e, 0x73, 0x00, 0x63, 0x6f, 0x6e, 0x74, 0x58, 0x00, 0xe0,
|
||||
0x68, 0x65, 0x00, 0x73, 0x61, 0x6d, 0x65, 0x00, 0x6e, 0x75,
|
||||
0x6d, 0x62, 0x65, 0x72, 0x87, 0x00, 0x02, 0x4a, 0x00, 0xb1,
|
||||
0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x61,
|
||||
0x73, 0x93, 0x00, 0xa3, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x64, 0x00, 0x36, 0x00, 0x50, 0x63, 0x6c, 0x75,
|
||||
0x65, 0x73, 0x6a, 0x00, 0x01, 0x7e, 0x00, 0x21, 0x6f, 0x70,
|
||||
0x5f, 0x00, 0x51, 0x72, 0x69, 0x67, 0x68, 0x74, 0x45, 0x00,
|
||||
0x21, 0x68, 0x65, 0xe9, 0x00, 0x91, 0x2e, 0x00, 0x00, 0x00,
|
||||
0x54, 0x68, 0x65, 0x72, 0x65, 0x45, 0x00, 0x60, 0x6f, 0x6e,
|
||||
0x6c, 0x79, 0x00, 0x73, 0xd2, 0x00, 0x00, 0x27, 0x00, 0x00,
|
||||
0x31, 0x00, 0xf1, 0x08, 0x39, 0x30, 0x00, 0x64, 0x65, 0x67,
|
||||
0x72, 0x65, 0x65, 0x00, 0x63, 0x75, 0x72, 0x76, 0x65, 0x64,
|
||||
0x00, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x2c, 0x1c, 0x00, 0x06,
|
||||
0xd7, 0x00, 0xf1, 0x05, 0x6d, 0x61, 0x79, 0x00, 0x6e, 0x6f,
|
||||
0x74, 0x00, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x00, 0x69, 0x74,
|
||||
0x73, 0x65, 0x6c, 0x66, 0x5a, 0x00, 0x01, 0x1c, 0x01, 0x02,
|
||||
0x84, 0x01, 0x32, 0x00, 0x77, 0x61, 0xd7, 0x00, 0x40, 0x72,
|
||||
0x69, 0x62, 0x75, 0xa8, 0x00, 0x01, 0x9b, 0x00, 0x20, 0x69,
|
||||
0x73, 0xf3, 0x00, 0xf0, 0x08, 0x6c, 0x65, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a, 0x61, 0x6d, 0x65,
|
||||
0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65, 0x79, 0x43, 0x00,
|
||||
0x4a, 0x34, 0x30, 0x2e, 0x31, 0xcc, 0x01, 0x01, 0x44, 0x00,
|
||||
0xf4, 0x1c, 0x6f, 0x6c, 0x73, 0x20, 0x00, 0x00, 0x00, 0x4c,
|
||||
0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x69,
|
||||
0x6e, 0x67, 0x00, 0x6f, 0x6e, 0x00, 0x61, 0x6e, 0x00, 0x65,
|
||||
0x64, 0x67, 0x65, 0x00, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65,
|
||||
0x6e, 0x00, 0x74, 0x77, 0x6f, 0xc9, 0x01, 0x7a, 0x00, 0x61,
|
||||
0x64, 0x64, 0x73, 0x00, 0x61, 0x40, 0x01, 0x06, 0x29, 0x00,
|
||||
0x28, 0x68, 0x65, 0x2d, 0x00, 0x30, 0x2e, 0x00, 0x52, 0x04,
|
||||
0x01, 0x0f, 0x5c, 0x00, 0x02, 0x03, 0x48, 0x00, 0x02, 0xed,
|
||||
0x00, 0x12, 0x6f, 0x3b, 0x00, 0x00, 0x19, 0x00, 0x14, 0x2c,
|
||||
0x85, 0x01, 0x00, 0x30, 0x00, 0x23, 0x6e, 0x6f, 0x69, 0x00,
|
||||
0xa1, 0x69, 0x73, 0x00, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62,
|
||||
0x6c, 0x09, 0x02, 0x3d, 0x72, 0x65, 0x2e, 0xb8, 0x00, 0x10,
|
||||
0x69, 0x77, 0x02, 0x02, 0x79, 0x00, 0x05, 0x5d, 0x00, 0x54,
|
||||
0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x51, 0x00, 0x70, 0x6f, 0x72,
|
||||
0x00, 0x73, 0x68, 0x6f, 0x77, 0x2c, 0x00, 0x01, 0x33, 0x02,
|
||||
0x82, 0x79, 0x6f, 0x75, 0x00, 0x6b, 0x6e, 0x6f, 0x77, 0x1f,
|
||||
0x02, 0x02, 0x39, 0x00, 0x45, 0x6d, 0x75, 0x73, 0x74, 0x37,
|
||||
0x02, 0x03, 0xe6, 0x00, 0x30, 0x2c, 0x00, 0x65, 0xd4, 0x02,
|
||||
0x21, 0x69, 0x66, 0x32, 0x00, 0x52, 0x64, 0x6f, 0x6e, 0x27,
|
||||
0x74, 0x38, 0x00, 0x02, 0xcb, 0x02, 0x00, 0xb5, 0x00, 0x00,
|
||||
0xaf, 0x01, 0x02, 0xcb, 0x00, 0x6d, 0x65, 0x73, 0x00, 0x79,
|
||||
0x65, 0x74, 0xf9, 0x00, 0x0e, 0x9d, 0x00, 0x04, 0xe7, 0x01,
|
||||
0x06, 0xed, 0x00, 0x15, 0x69, 0x7a, 0x00, 0x16, 0x73, 0xf9,
|
||||
0x00, 0x03, 0x62, 0x01, 0x05, 0xef, 0x00, 0x32, 0x00, 0x6f,
|
||||
0x72, 0x80, 0x02, 0x60, 0x2d, 0x64, 0x72, 0x61, 0x67, 0x67,
|
||||
0x38, 0x00, 0x04, 0x7d, 0x01, 0x05, 0xa2, 0x01, 0x20, 0x6c,
|
||||
0x6c, 0x09, 0x03, 0x00, 0xad, 0x00, 0x86, 0x74, 0x6f, 0x00,
|
||||
0x6c, 0x61, 0x79, 0x00, 0x61, 0x8f, 0x02, 0x31, 0x6c, 0x69,
|
||||
0x6e, 0x87, 0x03, 0x32, 0x69, 0x73, 0x2d, 0x61, 0x00, 0x20,
|
||||
0x6f, 0x72, 0x0c, 0x00, 0x33, 0x6e, 0x6f, 0x74, 0x10, 0x00,
|
||||
0x05, 0x2d, 0x01, 0xd1, 0x73, 0x2c, 0x00, 0x75, 0x73, 0x65,
|
||||
0x66, 0x75, 0x6c, 0x00, 0x66, 0x6f, 0x72, 0xad, 0x03, 0x03,
|
||||
0xc9, 0x00, 0x01, 0x67, 0x03, 0x25, 0x6f, 0x72, 0x66, 0x03,
|
||||
0x85, 0x74, 0x6f, 0x00, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x31,
|
||||
0x03, 0x00, 0xad, 0x00, 0x41, 0x28, 0x41, 0x6c, 0x6c, 0x11,
|
||||
0x00, 0x11, 0x61, 0x95, 0x02, 0x92, 0x73, 0x00, 0x64, 0x65,
|
||||
0x73, 0x63, 0x72, 0x69, 0x62, 0x5b, 0x03, 0x13, 0x73, 0xab,
|
||||
0x02, 0x41, 0x32, 0x2e, 0x31, 0x00, 0x13, 0x01, 0xf2, 0x00,
|
||||
0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,
|
||||
0x62, 0x6c, 0x65, 0x2e, 0x29, 0xb3, 0x02, 0x1a, 0x32, 0xb3,
|
||||
0x02, 0xb2, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
|
||||
0x72, 0x73, 0x20, 0x70, 0x03, 0x36, 0x73, 0x65, 0x00, 0x14,
|
||||
0x00, 0x02, 0x48, 0x00, 0x04, 0x43, 0x00, 0x02, 0x24, 0x04,
|
||||
0x00, 0x80, 0x00, 0xe1, 0x60, 0x43, 0x75, 0x73, 0x74, 0x6f,
|
||||
0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f, 0x70, 0x76, 0x00,
|
||||
0x03, 0x6e, 0x02, 0xb0, 0x60, 0x54, 0x79, 0x70, 0x65, 0x27,
|
||||
0x00, 0x6d, 0x65, 0x6e, 0x75, 0xb2, 0x00, 0x91, 0x57, 0x69,
|
||||
0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65, 0x28, 0x01, 0x68,
|
||||
0x00, 0x00, 0x53, 0x69, 0x7a, 0x65, 0xe5, 0x03, 0x00, 0x99,
|
||||
0x02, 0x06, 0xd9, 0x02, 0xf3, 0x01, 0x00, 0x00, 0x44, 0x69,
|
||||
0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x00, 0x00,
|
||||
0x00, 0x43, 0x4f, 0x03, 0x01, 0x2e, 0x00, 0x16, 0x64, 0x1a,
|
||||
0x00, 0x04, 0x40, 0x00, 0x41, 0x65, 0x6e, 0x65, 0x72, 0x58,
|
||||
0x04, 0xf3, 0x0b, 0x70, 0x75, 0x7a, 0x7a, 0x6c, 0x65, 0x3a,
|
||||
0x00, 0x61, 0x74, 0x00, 0x54, 0x72, 0x69, 0x63, 0x6b, 0x79,
|
||||
0x00, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x2c, 0x00, 0x79, 0x41,
|
||||
0x05, 0x82, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
|
||||
0x57, 0x01, 0xc3, 0x6b, 0x65, 0x00, 0x6d, 0x6f, 0x72, 0x65,
|
||||
0x00, 0x64, 0x65, 0x64, 0x75, 0x49, 0x01, 0x60, 0x72, 0x65,
|
||||
0x67, 0x61, 0x72, 0x64, 0x8c, 0x01, 0x36, 0x64, 0x69, 0x73,
|
||||
0x0d, 0x00, 0x52, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0xd9, 0x02,
|
||||
0x91, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x6c, 0x65, 0x61,
|
||||
0x45, 0x00, 0x25, 0x69, 0x6d, 0x3a, 0x03, 0x01, 0x73, 0x02,
|
||||
0xa2, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x6c, 0x61, 0x74, 0x65,
|
||||
0x72, 0xc6, 0x00, 0x11, 0x73, 0x30, 0x02, 0x00, 0x11, 0x04,
|
||||
0xb2, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x20,
|
||||
0x31, 0x20, 0xf8, 0x04, 0x07, 0xd8, 0x00, 0x30, 0x77, 0x68,
|
||||
0x65, 0x78, 0x03, 0x01, 0xce, 0x00, 0x09, 0x91, 0x04, 0x35,
|
||||
0x67, 0x61, 0x6d, 0xe0, 0x00, 0x00, 0x5d, 0x01, 0x71, 0x70,
|
||||
0x65, 0x72, 0x6d, 0x69, 0x74, 0x73, 0x07, 0x04, 0x50, 0x61,
|
||||
0x64, 0x6a, 0x61, 0x63, 0x20, 0x04, 0x0f, 0x33, 0x02, 0x00,
|
||||
0x81, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61, 0x00, 0x31, 0x32,
|
||||
0x02, 0x10, 0x2c, 0x1d, 0x00, 0x05, 0x3a, 0x00, 0x02, 0xcb,
|
||||
0x05, 0x06, 0x30, 0x00, 0x04, 0x46, 0x01, 0x01, 0xa1, 0x02,
|
||||
0xbd, 0x27, 0x73, 0x00, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x47, 0x00, 0xc2, 0x2e, 0x00, 0x42, 0x79, 0x00,
|
||||
0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x17, 0x05, 0x21,
|
||||
0x69, 0x73, 0x53, 0x05, 0x02, 0x5b, 0x00, 0x60, 0x74, 0x65,
|
||||
0x64, 0x2c, 0x00, 0x74, 0x69, 0x02, 0x86, 0x6f, 0x69, 0x64,
|
||||
0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x18, 0x03, 0x30, 0x62, 0x6f,
|
||||
0x72, 0x46, 0x01, 0x05, 0x11, 0x06, 0x05, 0x23, 0x06, 0x00,
|
||||
0xa4, 0x05, 0x01, 0x88, 0x01, 0x01, 0xc8, 0x01, 0x01, 0x58,
|
||||
0x05, 0x01, 0x92, 0x01, 0x71, 0x74, 0x77, 0x69, 0x64, 0x64,
|
||||
0x6c, 0x79, 0x20, 0x00, 0x70, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x65, 0x73, 0xc6, 0x03, 0x32, 0x2e, 0x00, 0x49, 0x28, 0x04,
|
||||
0x22, 0x77, 0x61, 0xa1, 0x00, 0x00, 0x18, 0x00, 0x22, 0x6f,
|
||||
0x72, 0x3f, 0x00, 0x02, 0x89, 0x01, 0xb2, 0x69, 0x6c, 0x69,
|
||||
0x74, 0x79, 0x2c, 0x00, 0x74, 0x75, 0x72, 0x6e, 0xa5, 0x00,
|
||||
0x03, 0x97, 0x02, 0x50, 0x6f, 0x66, 0x66, 0x2e, 0x00,
|
||||
0xfd, 0x06, 0x43, 0x68, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20,
|
||||
0x34, 0x30, 0x3a, 0x20, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x73,
|
||||
0x20, 0x00, 0x2d, 0x01, 0x00, 0xf0, 0x19, 0x00, 0x00, 0x00,
|
||||
0x59, 0x6f, 0x75, 0x00, 0x61, 0x72, 0x65, 0x00, 0x67, 0x69,
|
||||
0x76, 0x65, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x72, 0x69, 0x64,
|
||||
0x00, 0x6f, 0x66, 0x00, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65,
|
||||
0x73, 0x2c, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x11, 0x00, 0x51,
|
||||
0x77, 0x68, 0x69, 0x63, 0x68, 0x2b, 0x00, 0xf1, 0x04, 0x66,
|
||||
0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x77, 0x69, 0x74, 0x68,
|
||||
0x00, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x00, 0x74, 0x62, 0x00,
|
||||
0x11, 0x2e, 0x4d, 0x00, 0xf2, 0x05, 0x6e, 0x65, 0x65, 0x64,
|
||||
0x00, 0x74, 0x6f, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x00, 0x74, 0x68, 0x65, 0x21, 0x00, 0x70, 0x00,
|
||||
0x66, 0x72, 0x6f, 0x6d, 0x00, 0x41, 0x1d, 0x00, 0x91, 0x42,
|
||||
0x00, 0x73, 0x6f, 0x00, 0x74, 0x68, 0x61, 0x74, 0x1e, 0x00,
|
||||
0xf1, 0x06, 0x72, 0x6f, 0x77, 0x73, 0x00, 0x61, 0x6e, 0x64,
|
||||
0x00, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x00, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x58, 0x00, 0xe0, 0x68, 0x65, 0x00, 0x73,
|
||||
0x61, 0x6d, 0x65, 0x00, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
|
||||
0x87, 0x00, 0x02, 0x4a, 0x00, 0xb1, 0x73, 0x65, 0x67, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x73, 0x00, 0x61, 0x73, 0x93, 0x00, 0xa3,
|
||||
0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x00,
|
||||
0x36, 0x00, 0x50, 0x63, 0x6c, 0x75, 0x65, 0x73, 0x6a, 0x00,
|
||||
0x01, 0x7e, 0x00, 0x21, 0x6f, 0x70, 0x5f, 0x00, 0x51, 0x72,
|
||||
0x69, 0x67, 0x68, 0x74, 0x45, 0x00, 0x21, 0x68, 0x65, 0xe9,
|
||||
0x00, 0x91, 0x2e, 0x00, 0x00, 0x00, 0x54, 0x68, 0x65, 0x72,
|
||||
0x65, 0x45, 0x00, 0x60, 0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x73,
|
||||
0xd2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x31, 0x00, 0xf1, 0x08,
|
||||
0x39, 0x30, 0x00, 0x64, 0x65, 0x67, 0x72, 0x65, 0x65, 0x00,
|
||||
0x63, 0x75, 0x72, 0x76, 0x65, 0x64, 0x00, 0x72, 0x61, 0x69,
|
||||
0x6c, 0x73, 0x2c, 0x1c, 0x00, 0x06, 0xd7, 0x00, 0xf1, 0x05,
|
||||
0x6d, 0x61, 0x79, 0x00, 0x6e, 0x6f, 0x74, 0x00, 0x63, 0x72,
|
||||
0x6f, 0x73, 0x73, 0x00, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66,
|
||||
0x5a, 0x00, 0x01, 0x16, 0x01, 0x32, 0x00, 0x77, 0x61, 0xd1,
|
||||
0x00, 0x40, 0x72, 0x69, 0x62, 0x75, 0xa2, 0x00, 0x01, 0x95,
|
||||
0x00, 0x20, 0x69, 0x73, 0xed, 0x00, 0xf0, 0x08, 0x6c, 0x65,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x62, 0x79, 0x00, 0x4a,
|
||||
0x61, 0x6d, 0x65, 0x73, 0x00, 0x48, 0x61, 0x72, 0x76, 0x65,
|
||||
0x79, 0x3d, 0x00, 0x44, 0x34, 0x30, 0x2e, 0x31, 0xba, 0x01,
|
||||
0x01, 0x3e, 0x00, 0xf4, 0x1c, 0x6f, 0x6c, 0x73, 0x20, 0x00,
|
||||
0x00, 0x00, 0x4c, 0x65, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69,
|
||||
0x63, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x6f, 0x6e, 0x00, 0x61,
|
||||
0x6e, 0x00, 0x65, 0x64, 0x67, 0x65, 0x00, 0x62, 0x65, 0x74,
|
||||
0x77, 0x65, 0x65, 0x6e, 0x00, 0x74, 0x77, 0x6f, 0xbd, 0x01,
|
||||
0x7a, 0x00, 0x61, 0x64, 0x64, 0x73, 0x00, 0x61, 0x34, 0x01,
|
||||
0x06, 0x29, 0x00, 0x28, 0x68, 0x65, 0x2d, 0x00, 0x30, 0x2e,
|
||||
0x00, 0x52, 0xf8, 0x00, 0x0f, 0x5c, 0x00, 0x02, 0x03, 0x48,
|
||||
0x00, 0x02, 0xe1, 0x00, 0x12, 0x6f, 0x3b, 0x00, 0x00, 0x19,
|
||||
0x00, 0x14, 0x2c, 0x79, 0x01, 0x00, 0x30, 0x00, 0x23, 0x6e,
|
||||
0x6f, 0x69, 0x00, 0xa1, 0x69, 0x73, 0x00, 0x70, 0x6f, 0x73,
|
||||
0x73, 0x69, 0x62, 0x6c, 0xfd, 0x01, 0x3d, 0x72, 0x65, 0x2e,
|
||||
0xb8, 0x00, 0x10, 0x69, 0x6b, 0x02, 0x02, 0x79, 0x00, 0x05,
|
||||
0x5d, 0x00, 0x54, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x51, 0x00,
|
||||
0x70, 0x6f, 0x72, 0x00, 0x73, 0x68, 0x6f, 0x77, 0x2c, 0x00,
|
||||
0x01, 0x27, 0x02, 0x82, 0x79, 0x6f, 0x75, 0x00, 0x6b, 0x6e,
|
||||
0x6f, 0x77, 0x13, 0x02, 0x02, 0x39, 0x00, 0x45, 0x6d, 0x75,
|
||||
0x73, 0x74, 0x2b, 0x02, 0x03, 0xe6, 0x00, 0x30, 0x2c, 0x00,
|
||||
0x65, 0xc8, 0x02, 0x21, 0x69, 0x66, 0x32, 0x00, 0x52, 0x64,
|
||||
0x6f, 0x6e, 0x27, 0x74, 0x38, 0x00, 0x02, 0xbf, 0x02, 0x00,
|
||||
0xb5, 0x00, 0x00, 0xa3, 0x01, 0x02, 0xcb, 0x00, 0x6d, 0x65,
|
||||
0x73, 0x00, 0x79, 0x65, 0x74, 0xf9, 0x00, 0x0e, 0x9d, 0x00,
|
||||
0x04, 0xdb, 0x01, 0x06, 0xed, 0x00, 0x15, 0x69, 0x7a, 0x00,
|
||||
0x16, 0x73, 0xf9, 0x00, 0x03, 0x62, 0x01, 0x05, 0xef, 0x00,
|
||||
0x32, 0x00, 0x6f, 0x72, 0x74, 0x02, 0x60, 0x2d, 0x64, 0x72,
|
||||
0x61, 0x67, 0x67, 0x38, 0x00, 0x04, 0x7d, 0x01, 0x05, 0xa2,
|
||||
0x01, 0x20, 0x6c, 0x6c, 0xfd, 0x02, 0x00, 0xad, 0x00, 0x86,
|
||||
0x74, 0x6f, 0x00, 0x6c, 0x61, 0x79, 0x00, 0x61, 0x83, 0x02,
|
||||
0x31, 0x6c, 0x69, 0x6e, 0x7b, 0x03, 0x32, 0x69, 0x73, 0x2d,
|
||||
0x61, 0x00, 0x20, 0x6f, 0x72, 0x0c, 0x00, 0x33, 0x6e, 0x6f,
|
||||
0x74, 0x10, 0x00, 0x05, 0x2d, 0x01, 0xd1, 0x73, 0x2c, 0x00,
|
||||
0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x00, 0x66, 0x6f, 0x72,
|
||||
0xa1, 0x03, 0x03, 0xc9, 0x00, 0x01, 0x5b, 0x03, 0x25, 0x6f,
|
||||
0x72, 0x5a, 0x03, 0x85, 0x74, 0x6f, 0x00, 0x6d, 0x61, 0x74,
|
||||
0x63, 0x68, 0x25, 0x03, 0x00, 0xad, 0x00, 0x41, 0x28, 0x41,
|
||||
0x6c, 0x6c, 0x11, 0x00, 0x11, 0x61, 0x8f, 0x02, 0x92, 0x73,
|
||||
0x00, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x4f, 0x03,
|
||||
0x13, 0x73, 0xa5, 0x02, 0x41, 0x32, 0x2e, 0x31, 0x00, 0x13,
|
||||
0x01, 0xf2, 0x00, 0x6c, 0x73, 0x6f, 0x00, 0x61, 0x76, 0x61,
|
||||
0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x29, 0xad, 0x02,
|
||||
0x14, 0x32, 0xad, 0x02, 0xb2, 0x70, 0x61, 0x72, 0x61, 0x6d,
|
||||
0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x5e, 0x03, 0x36, 0x73,
|
||||
0x65, 0x00, 0x14, 0x00, 0x02, 0x42, 0x00, 0x04, 0x3d, 0x00,
|
||||
0x02, 0x12, 0x04, 0x00, 0x7a, 0x00, 0xe1, 0x60, 0x43, 0x75,
|
||||
0x73, 0x74, 0x6f, 0x6d, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x6f,
|
||||
0x70, 0x70, 0x00, 0x03, 0x68, 0x02, 0xb0, 0x60, 0x54, 0x79,
|
||||
0x70, 0x65, 0x27, 0x00, 0x6d, 0x65, 0x6e, 0x75, 0xac, 0x00,
|
||||
0x91, 0x57, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x00, 0x48, 0x65,
|
||||
0x22, 0x01, 0x68, 0x00, 0x00, 0x53, 0x69, 0x7a, 0x65, 0xd3,
|
||||
0x03, 0x00, 0x93, 0x02, 0x06, 0xd3, 0x02, 0xf3, 0x01, 0x00,
|
||||
0x00, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74,
|
||||
0x79, 0x00, 0x00, 0x00, 0x43, 0x49, 0x03, 0x01, 0x2e, 0x00,
|
||||
0x16, 0x64, 0x1a, 0x00, 0x04, 0x40, 0x00, 0x41, 0x65, 0x6e,
|
||||
0x65, 0x72, 0x46, 0x04, 0xf3, 0x0b, 0x70, 0x75, 0x7a, 0x7a,
|
||||
0x6c, 0x65, 0x3a, 0x00, 0x61, 0x74, 0x00, 0x54, 0x72, 0x69,
|
||||
0x63, 0x6b, 0x79, 0x00, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x2c,
|
||||
0x00, 0x79, 0x2f, 0x05, 0x82, 0x72, 0x65, 0x71, 0x75, 0x69,
|
||||
0x72, 0x65, 0x64, 0x51, 0x01, 0xc3, 0x6b, 0x65, 0x00, 0x6d,
|
||||
0x6f, 0x72, 0x65, 0x00, 0x64, 0x65, 0x64, 0x75, 0x43, 0x01,
|
||||
0x60, 0x72, 0x65, 0x67, 0x61, 0x72, 0x64, 0x86, 0x01, 0x36,
|
||||
0x64, 0x69, 0x73, 0x0d, 0x00, 0x52, 0x6d, 0x6f, 0x76, 0x65,
|
||||
0x73, 0xd3, 0x02, 0x91, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x00,
|
||||
0x6c, 0x65, 0x61, 0x45, 0x00, 0x25, 0x69, 0x6d, 0x34, 0x03,
|
||||
0x01, 0x6d, 0x02, 0xa2, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x6c,
|
||||
0x61, 0x74, 0x65, 0x72, 0xc6, 0x00, 0x11, 0x73, 0x2a, 0x02,
|
||||
0x00, 0x0b, 0x04, 0xb2, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69,
|
||||
0x76, 0x65, 0x20, 0x31, 0x20, 0xe6, 0x04, 0x07, 0xd8, 0x00,
|
||||
0x30, 0x77, 0x68, 0x65, 0x72, 0x03, 0x01, 0xce, 0x00, 0x03,
|
||||
0x7f, 0x04, 0x35, 0x67, 0x61, 0x6d, 0xda, 0x00, 0x00, 0x57,
|
||||
0x01, 0x71, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x73, 0xfb,
|
||||
0x03, 0x50, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x14, 0x04, 0x0f,
|
||||
0x27, 0x02, 0x00, 0x81, 0x68, 0x61, 0x76, 0x65, 0x00, 0x61,
|
||||
0x00, 0x31, 0x26, 0x02, 0x10, 0x2c, 0x1d, 0x00, 0x05, 0x3a,
|
||||
0x00, 0x02, 0xb3, 0x05, 0x06, 0x30, 0x00, 0x04, 0x40, 0x01,
|
||||
0x01, 0x95, 0x02, 0xbd, 0x27, 0x73, 0x00, 0x65, 0x6e, 0x64,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x00, 0xc2, 0x2e, 0x00,
|
||||
0x42, 0x79, 0x00, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
|
||||
0x05, 0x05, 0x21, 0x69, 0x73, 0x3b, 0x05, 0x02, 0x5b, 0x00,
|
||||
0x60, 0x74, 0x65, 0x64, 0x2c, 0x00, 0x74, 0x5d, 0x02, 0x86,
|
||||
0x6f, 0x69, 0x64, 0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x0c, 0x03,
|
||||
0x30, 0x62, 0x6f, 0x72, 0x40, 0x01, 0x05, 0xf9, 0x05, 0x05,
|
||||
0x0b, 0x06, 0x00, 0x8c, 0x05, 0x01, 0x82, 0x01, 0x01, 0xc2,
|
||||
0x01, 0x01, 0x46, 0x05, 0x01, 0x8c, 0x01, 0x71, 0x74, 0x77,
|
||||
0x69, 0x64, 0x64, 0x6c, 0x79, 0x20, 0x00, 0x70, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x65, 0x73, 0xba, 0x03, 0x32, 0x2e, 0x00,
|
||||
0x49, 0x1c, 0x04, 0x22, 0x77, 0x61, 0xa1, 0x00, 0x00, 0x18,
|
||||
0x00, 0x22, 0x6f, 0x72, 0x3f, 0x00, 0x02, 0x83, 0x01, 0xb2,
|
||||
0x69, 0x6c, 0x69, 0x74, 0x79, 0x2c, 0x00, 0x74, 0x75, 0x72,
|
||||
0x6e, 0xa5, 0x00, 0x03, 0x91, 0x02, 0x50, 0x6f, 0x66, 0x66,
|
||||
0x2e, 0x00,
|
||||
};
|
||||
|
||||
const unsigned short help_text_len = 1917;
|
||||
const unsigned short help_text_words = 339;
|
||||
const unsigned short help_text_len = 1881;
|
||||
const unsigned short help_text_words = 337;
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
(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);
|
||||
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)
|
||||
{
|
||||
rb_color(color);
|
||||
|
@ -1035,349 +1035,7 @@ static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* 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,
|
||||
static void rb_draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||
int fillcolor, int outlinecolor)
|
||||
{
|
||||
if(!zoom_enabled)
|
||||
|
@ -1449,7 +1107,7 @@ static void trim_rect(int *x, int *y, int *w, int *h)
|
|||
*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");
|
||||
blitter *b = snew(blitter);
|
||||
|
@ -1460,7 +1118,7 @@ static blitter *rb_blitter_new(void *handle, int w, int h)
|
|||
return b;
|
||||
}
|
||||
|
||||
static void rb_blitter_free(void *handle, blitter *bl)
|
||||
static void rb_blitter_free(drawing *dr, blitter *bl)
|
||||
{
|
||||
LOGF("rb_blitter_free");
|
||||
sfree(bl->bmp.data);
|
||||
|
@ -1469,7 +1127,7 @@ static void rb_blitter_free(void *handle, blitter *bl)
|
|||
}
|
||||
|
||||
/* 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 */
|
||||
#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
|
||||
|
@ -1498,7 +1156,7 @@ static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
|
|||
#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");
|
||||
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);
|
||||
|
||||
|
@ -1552,9 +1210,9 @@ static void rb_draw_update(void *handle, int x, int y, int w, int h)
|
|||
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 ... */
|
||||
|
||||
|
@ -1565,9 +1223,9 @@ static void rb_start_draw(void *handle)
|
|||
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)
|
||||
{
|
||||
|
@ -1594,7 +1252,7 @@ static void rb_end_draw(void *handle)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void rb_status_bar(void *handle, const char *text)
|
||||
static void rb_status_bar(drawing *dr, const char *text)
|
||||
{
|
||||
if(titlebar)
|
||||
sfree(titlebar);
|
||||
|
@ -1692,7 +1350,7 @@ static void draw_mouse(void)
|
|||
* glyph exists in a font) */
|
||||
#if 0
|
||||
/* 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)
|
||||
{
|
||||
struct font *pf = rb->font_get(cur_font);
|
||||
|
@ -1725,10 +1383,11 @@ static char *rb_text_fallback(void *handle, const char *const *strings,
|
|||
#endif
|
||||
|
||||
const drawing_api rb_drawing = {
|
||||
1,
|
||||
rb_draw_text,
|
||||
rb_draw_rect,
|
||||
rb_draw_line,
|
||||
rb_draw_poly,
|
||||
draw_polygon_fallback,
|
||||
rb_draw_circle,
|
||||
rb_draw_update,
|
||||
rb_clip,
|
||||
|
|
|
@ -6,13 +6,17 @@ project(puzzles
|
|||
include(cmake/setup.cmake)
|
||||
|
||||
add_library(core_obj OBJECT
|
||||
combi.c divvy.c drawing.c dsf.c findloop.c grid.c latin.c
|
||||
laydomino.c loopgen.c malloc.c matching.c midend.c misc.c penrose.c
|
||||
penrose-legacy.c ps.c random.c sort.c tdq.c tree234.c version.c
|
||||
combi.c divvy.c draw-poly.c drawing.c dsf.c findloop.c grid.c
|
||||
latin.c laydomino.c loopgen.c malloc.c matching.c midend.c misc.c
|
||||
penrose.c penrose-legacy.c ps.c random.c sort.c tdq.c tree234.c
|
||||
version.c
|
||||
${platform_common_sources})
|
||||
add_library(core $<TARGET_OBJECTS:core_obj>)
|
||||
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})
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct drawing {
|
||||
const drawing_api *api;
|
||||
void *handle;
|
||||
typedef struct drawing_internal {
|
||||
/* we implement data hiding by casting `struct drawing*` pointers
|
||||
* to `struct drawing_internal*` */
|
||||
struct drawing pub;
|
||||
|
||||
/* private data */
|
||||
struct print_colour *colours;
|
||||
int ncolours, coloursize;
|
||||
float scale;
|
||||
|
@ -52,53 +55,70 @@ struct drawing {
|
|||
* this may set it to NULL. */
|
||||
midend *me;
|
||||
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 *dr = snew(drawing);
|
||||
dr->api = api;
|
||||
dr->handle = handle;
|
||||
dr->colours = NULL;
|
||||
dr->ncolours = dr->coloursize = 0;
|
||||
dr->scale = 1.0F;
|
||||
dr->me = me;
|
||||
dr->laststatus = NULL;
|
||||
return dr;
|
||||
if(api->version != DRAWING_API_VERSION) {
|
||||
fatal("Drawing API version mismatch: expected: %d, actual: %d\n", DRAWING_API_VERSION, api->version);
|
||||
/* shouldn't get here */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
drawing_internal *dri = snew(drawing_internal);
|
||||
dri->pub.api = api;
|
||||
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)
|
||||
{
|
||||
sfree(dr->laststatus);
|
||||
sfree(dr->colours);
|
||||
sfree(dr);
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
sfree(dri->laststatus);
|
||||
sfree(dri->colours);
|
||||
sfree(dri);
|
||||
}
|
||||
|
||||
void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
|
||||
int align, int colour, const char *text)
|
||||
{
|
||||
dr->api->draw_text(dr->handle, x, y, fonttype, fontsize, align,
|
||||
colour, text);
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
dri->pub.api->draw_text(dr, x, y, fonttype, fontsize, align,
|
||||
colour, text);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
float x1, float y1, float x2, float y2, int colour)
|
||||
{
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
if (thickness < 1.0F)
|
||||
thickness = 1.0F;
|
||||
if (dr->api->draw_thick_line) {
|
||||
dr->api->draw_thick_line(dr->handle, thickness,
|
||||
x1, y1, x2, y2, colour);
|
||||
if (dri->pub.api->draw_thick_line) {
|
||||
dri->pub.api->draw_thick_line(dr, thickness,
|
||||
x1, y1, x2, y2, colour);
|
||||
} else {
|
||||
/* We'll fake it up with a filled polygon. The tweak to the
|
||||
* thickness empirically compensates for rounding errors, because
|
||||
|
@ -117,59 +137,67 @@ void draw_thick_line(drawing *dr, float thickness,
|
|||
p[5] = y2 - tvhatx;
|
||||
p[6] = x1 + tvhaty;
|
||||
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,
|
||||
int fillcolour, int outlinecolour)
|
||||
{
|
||||
dr->api->draw_polygon(dr->handle, coords, npoints, fillcolour,
|
||||
outlinecolour);
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
dri->pub.api->draw_polygon(dr, coords, npoints, fillcolour,
|
||||
outlinecolour);
|
||||
}
|
||||
|
||||
void draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||
int fillcolour, int outlinecolour)
|
||||
{
|
||||
dr->api->draw_circle(dr->handle, cx, cy, radius, fillcolour,
|
||||
outlinecolour);
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
dri->pub.api->draw_circle(dr, cx, cy, radius, fillcolour,
|
||||
outlinecolour);
|
||||
}
|
||||
|
||||
void draw_update(drawing *dr, int x, int y, int w, int h)
|
||||
{
|
||||
if (dr->api->draw_update)
|
||||
dr->api->draw_update(dr->handle, x, y, w, h);
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
dr->api->unclip(dr->handle);
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
dri->pub.api->unclip(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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
int i;
|
||||
|
||||
/*
|
||||
* If the drawing implementation provides one of these, use it.
|
||||
*/
|
||||
if (dr && dr->api->text_fallback)
|
||||
return dr->api->text_fallback(dr->handle, strings, nstrings);
|
||||
if (dr && dri->pub.api->text_fallback)
|
||||
return dri->pub.api->text_fallback(dr, strings, nstrings);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
char *rewritten;
|
||||
|
||||
if (!dr->api->status_bar)
|
||||
if (!dri->pub.api->status_bar)
|
||||
return;
|
||||
|
||||
assert(dr->me);
|
||||
assert(dri->me);
|
||||
|
||||
rewritten = midend_rewrite_statusbar(dr->me, text);
|
||||
if (!dr->laststatus || strcmp(rewritten, dr->laststatus)) {
|
||||
dr->api->status_bar(dr->handle, rewritten);
|
||||
sfree(dr->laststatus);
|
||||
dr->laststatus = rewritten;
|
||||
rewritten = midend_rewrite_statusbar(dri->me, text);
|
||||
if (!dri->laststatus || strcmp(rewritten, dri->laststatus)) {
|
||||
dri->pub.api->status_bar(dr, rewritten);
|
||||
sfree(dri->laststatus);
|
||||
dri->laststatus = rewritten;
|
||||
} else {
|
||||
sfree(rewritten);
|
||||
}
|
||||
|
@ -215,74 +244,85 @@ void status_bar(drawing *dr, const char *text)
|
|||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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,
|
||||
float ym, float yc, int pw, int ph, float wmm,
|
||||
float scale)
|
||||
{
|
||||
dr->scale = scale;
|
||||
dr->ncolours = 0;
|
||||
dr->api->begin_puzzle(dr->handle, xm, xc, ym, yc, pw, ph, wmm);
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
dri->scale = scale;
|
||||
dri->ncolours = 0;
|
||||
dri->pub.api->begin_puzzle(dr, xm, xc, ym, yc, pw, ph, wmm);
|
||||
}
|
||||
|
||||
void print_end_puzzle(drawing *dr)
|
||||
{
|
||||
dr->api->end_puzzle(dr->handle);
|
||||
dr->scale = 1.0F;
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
dri->pub.api->end_puzzle(dr);
|
||||
dri->scale = 1.0F;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
int *hatch, float *r, float *g, float *b)
|
||||
{
|
||||
assert(colour >= 0 && colour < dr->ncolours);
|
||||
if (dr->colours[colour].hatch_when == 2 ||
|
||||
(dr->colours[colour].hatch_when == 1 && !printing_in_colour)) {
|
||||
*hatch = dr->colours[colour].hatch;
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
assert(colour >= 0 && colour < dri->ncolours);
|
||||
if (dri->colours[colour].hatch_when == 2 ||
|
||||
(dri->colours[colour].hatch_when == 1 && !printing_in_colour)) {
|
||||
*hatch = dri->colours[colour].hatch;
|
||||
} else {
|
||||
*hatch = -1;
|
||||
if (printing_in_colour) {
|
||||
*r = dr->colours[colour].r;
|
||||
*g = dr->colours[colour].g;
|
||||
*b = dr->colours[colour].b;
|
||||
*r = dri->colours[colour].r;
|
||||
*g = dri->colours[colour].g;
|
||||
*b = dri->colours[colour].b;
|
||||
} 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,
|
||||
float grey, int hatch, int hatch_when)
|
||||
{
|
||||
if (dr->ncolours >= dr->coloursize) {
|
||||
dr->coloursize = dr->ncolours + 16;
|
||||
dr->colours = sresize(dr->colours, dr->coloursize,
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
if (dri->ncolours >= dri->coloursize) {
|
||||
dri->coloursize = dri->ncolours + 16;
|
||||
dri->colours = sresize(dri->colours, dri->coloursize,
|
||||
struct print_colour);
|
||||
}
|
||||
dr->colours[dr->ncolours].hatch = hatch;
|
||||
dr->colours[dr->ncolours].hatch_when = hatch_when;
|
||||
dr->colours[dr->ncolours].r = r;
|
||||
dr->colours[dr->ncolours].g = g;
|
||||
dr->colours[dr->ncolours].b = b;
|
||||
dr->colours[dr->ncolours].grey = grey;
|
||||
return dr->ncolours++;
|
||||
dri->colours[dri->ncolours].hatch = hatch;
|
||||
dri->colours[dri->ncolours].hatch_when = hatch_when;
|
||||
dri->colours[dri->ncolours].r = r;
|
||||
dri->colours[dri->ncolours].g = g;
|
||||
dri->colours[dri->ncolours].b = b;
|
||||
dri->colours[dri->ncolours].grey = grey;
|
||||
return dri->ncolours++;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||
|
||||
/*
|
||||
* I don't think it's entirely sensible to have line widths be
|
||||
* 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
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
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+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);
|
||||
} else {
|
||||
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;
|
||||
|
||||
c = coords;
|
||||
*c++ = ox + px/9;
|
||||
*c++ = oy + py/9;
|
||||
*c++ = ox + px/9 + ax*2/3;
|
||||
*c++ = oy + py/9 + ay*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++ = ox - px/9;
|
||||
*c++ = oy - py/9;
|
||||
*c++ = ox + px/9;
|
||||
*c++ = oy + py/9;
|
||||
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+1] = y + (int)(TILE_SIZE * (dy)); \
|
||||
} while (0)
|
||||
SETCOORD(0, 0.6F, 0.7F);
|
||||
SETCOORD(1, 0.8F, 0.8F);
|
||||
SETCOORD(2, 0.25F, 0.8F);
|
||||
SETCOORD(3, 0.55F, 0.7F);
|
||||
SETCOORD(4, 0.55F, 0.35F);
|
||||
SETCOORD(5, 0.6F, 0.35F);
|
||||
SETCOORD(0, 0.6F, 0.35F);
|
||||
SETCOORD(1, 0.6F, 0.7F);
|
||||
SETCOORD(2, 0.8F, 0.8F);
|
||||
SETCOORD(3, 0.25F, 0.8F);
|
||||
SETCOORD(4, 0.55F, 0.7F);
|
||||
SETCOORD(5, 0.55F, 0.35F);
|
||||
draw_polygon(dr, coords, 6, COL_FLAGBASE, COL_FLAGBASE);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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}
|
||||
|
||||
|
@ -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
|
||||
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
|
||||
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.)
|
||||
|
||||
\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
|
||||
\q{Type} menu.
|
||||
|
@ -3490,12 +3490,12 @@ that would lead to impossible crossings later.
|
|||
|
||||
\dt \e{Disallow consecutive 1 clues}
|
||||
|
||||
\dd Controls whether the Train Tracks game generation permits two
|
||||
adjacent rows or columns to have a 1 clue, or permits the row or
|
||||
column of the track's endpoint to have a 1 clue. By default this is
|
||||
not permitted, to avoid long straight boring segments of track and
|
||||
make the games more twiddly and interesting. If you want to restore
|
||||
the possibility, turn this option off.
|
||||
\dd Controls whether the Tracks game generation permits two adjacent
|
||||
rows or columns to have a 1 clue, or permits the row or column of the
|
||||
track's endpoint to have a 1 clue. By default this is not permitted,
|
||||
to avoid long straight boring segments of track and make the games
|
||||
more twiddly and interesting. If you want to restore the possibility,
|
||||
turn this option off.
|
||||
|
||||
|
||||
\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_polygon(drawing *dr, const int *coords, int npoints,
|
||||
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,
|
||||
int fillcolour, int outlinecolour);
|
||||
void draw_thick_line(drawing *dr, float thickness,
|
||||
|
@ -454,6 +456,9 @@ char *button2label(int button);
|
|||
* standard per clause 7.26.11.1.) */
|
||||
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
|
||||
*/
|
||||
|
@ -752,43 +757,76 @@ struct game {
|
|||
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
|
||||
* front end and also by cross-platform printing modules such as
|
||||
* PostScript.
|
||||
*/
|
||||
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);
|
||||
void (*draw_rect)(void *handle, 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_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_polygon)(void *handle, const int *coords, int npoints,
|
||||
void (*draw_polygon)(drawing *dr, const int *coords, int npoints,
|
||||
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);
|
||||
void (*draw_update)(void *handle, int x, int y, int w, int h);
|
||||
void (*clip)(void *handle, int x, int y, int w, int h);
|
||||
void (*unclip)(void *handle);
|
||||
void (*start_draw)(void *handle);
|
||||
void (*end_draw)(void *handle);
|
||||
void (*status_bar)(void *handle, const char *text);
|
||||
blitter *(*blitter_new)(void *handle, int w, int h);
|
||||
void (*blitter_free)(void *handle, blitter *bl);
|
||||
void (*blitter_save)(void *handle, blitter *bl, int x, int y);
|
||||
void (*blitter_load)(void *handle, blitter *bl, int x, int y);
|
||||
void (*begin_doc)(void *handle, int pages);
|
||||
void (*begin_page)(void *handle, int number);
|
||||
void (*begin_puzzle)(void *handle, float xm, float xc,
|
||||
void (*draw_update)(drawing *dr, int x, int y, int w, int h);
|
||||
void (*clip)(drawing *dr, int x, int y, int w, int h);
|
||||
void (*unclip)(drawing *dr);
|
||||
void (*start_draw)(drawing *dr);
|
||||
void (*end_draw)(drawing *dr);
|
||||
void (*status_bar)(drawing *dr, const char *text);
|
||||
blitter *(*blitter_new)(drawing *dr, int w, int h);
|
||||
void (*blitter_free)(drawing *dr, blitter *bl);
|
||||
void (*blitter_save)(drawing *dr, blitter *bl, int x, int y);
|
||||
void (*blitter_load)(drawing *dr, blitter *bl, int x, int y);
|
||||
void (*begin_doc)(drawing *dr, int pages);
|
||||
void (*begin_page)(drawing *dr, int number);
|
||||
void (*begin_puzzle)(drawing *dr, float xm, float xc,
|
||||
float ym, float yc, int pw, int ph, float wmm);
|
||||
void (*end_puzzle)(void *handle);
|
||||
void (*end_page)(void *handle, int number);
|
||||
void (*end_doc)(void *handle);
|
||||
void (*line_width)(void *handle, float width);
|
||||
void (*line_dotted)(void *handle, bool dotted);
|
||||
char *(*text_fallback)(void *handle, const char *const *strings,
|
||||
void (*end_puzzle)(drawing *dr);
|
||||
void (*end_page)(drawing *dr, int number);
|
||||
void (*end_doc)(drawing *dr);
|
||||
void (*line_width)(drawing *dr, float width);
|
||||
void (*line_dotted)(drawing *dr, bool dotted);
|
||||
char *(*text_fallback)(drawing *dr, const char *const *strings,
|
||||
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,
|
||||
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);
|
||||
|
||||
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 - PI / npoints;
|
||||
r = (n % 2 == 0) ? (double)rad/2.0 : (double)rad;
|
||||
a = 2.0 * PI * ((double)n / ((double)npoints * 2.0)) + angle_offset;
|
||||
r = (n % 2) ? (double)rad/2.0 : (double)rad;
|
||||
|
||||
/* We're rotating the point at (0, -r) by a degrees */
|
||||
coords[2*n+0] = cx + (int)( r * sin(a));
|
||||
|
|
|
@ -532,18 +532,6 @@ static void free_game(game_state *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,
|
||||
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
|
||||
* 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++)
|
||||
ret->grid[i] &= ~3;
|
||||
ret->used_solve = true;
|
||||
|
|
|
@ -1844,18 +1844,18 @@ static void draw_gt(drawing *dr, int ox, int oy,
|
|||
{
|
||||
int coords[12];
|
||||
int xdx = (dx1+dx2 ? 0 : 1), xdy = (dx1+dx2 ? 1 : 0);
|
||||
coords[0] = ox + xdx + dx1;
|
||||
coords[1] = oy + xdy + dy1;
|
||||
coords[2] = ox + xdx + dx1 + dx2;
|
||||
coords[3] = oy + xdy + dy1 + dy2;
|
||||
coords[4] = ox - xdx + dx1 + dx2;
|
||||
coords[5] = oy - xdy + dy1 + dy2;
|
||||
coords[6] = ox - xdx + dx1;
|
||||
coords[7] = oy - xdy + dy1;
|
||||
coords[8] = ox - xdx;
|
||||
coords[9] = oy - xdy;
|
||||
coords[10] = ox + xdx;
|
||||
coords[11] = oy + xdy;
|
||||
coords[0] = ox + xdx;
|
||||
coords[1] = oy + xdy;
|
||||
coords[2] = ox + xdx + dx1;
|
||||
coords[3] = oy + xdy + dy1;
|
||||
coords[4] = ox + xdx + dx1 + dx2;
|
||||
coords[5] = oy + xdy + dy1 + dy2;
|
||||
coords[6] = ox - xdx + dx1 + dx2;
|
||||
coords[7] = oy - xdy + dy1 + dy2;
|
||||
coords[8] = ox - xdx + dx1;
|
||||
coords[9] = oy - xdy + dy1;
|
||||
coords[10] = ox - xdx;
|
||||
coords[11] = oy - xdy;
|
||||
draw_polygon(dr, coords, 6, col, col);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue