summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/rockbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/rockbox.c')
-rw-r--r--apps/plugins/puzzles/rockbox.c379
1 files changed, 19 insertions, 360 deletions
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c
index 60e6548826..27005a447d 100644
--- a/apps/plugins/puzzles/rockbox.c
+++ b/apps/plugins/puzzles/rockbox.c
@@ -753,7 +753,7 @@ static void rb_color(int n)
753 753
754/* clipping is implemented through viewports and offsetting 754/* clipping is implemented through viewports and offsetting
755 * coordinates */ 755 * coordinates */
756static void rb_clip(void *handle, int x, int y, int w, int h) 756static void rb_clip(drawing *dr, int x, int y, int w, int h)
757{ 757{
758 if(!zoom_enabled) 758 if(!zoom_enabled)
759 { 759 {
@@ -783,7 +783,7 @@ static void rb_clip(void *handle, int x, int y, int w, int h)
783 } 783 }
784} 784}
785 785
786static void rb_unclip(void *handle) 786static void rb_unclip(drawing *dr)
787{ 787{
788 if(!zoom_enabled) 788 if(!zoom_enabled)
789 { 789 {
@@ -800,7 +800,7 @@ static void rb_unclip(void *handle)
800 } 800 }
801} 801}
802 802
803static void rb_draw_text(void *handle, int x, int y, int fonttype, 803static void rb_draw_text(drawing *dr, int x, int y, int fonttype,
804 int fontsize, int align, int color, const char *text) 804 int fontsize, int align, int color, const char *text)
805{ 805{
806 (void) fontsize; 806 (void) fontsize;
@@ -865,7 +865,7 @@ static void rb_draw_text(void *handle, int x, int y, int fonttype,
865 } 865 }
866} 866}
867 867
868static void rb_draw_rect(void *handle, int x, int y, int w, int h, int color) 868static void rb_draw_rect(drawing *dr, int x, int y, int w, int h, int color)
869{ 869{
870 rb_color(color); 870 rb_color(color);
871 if(!zoom_enabled) 871 if(!zoom_enabled)
@@ -1007,7 +1007,7 @@ static void draw_antialiased_line(fb_data *fb, int w, int h, int x0, int y0, int
1007 } 1007 }
1008} 1008}
1009 1009
1010static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2, 1010static void rb_draw_line(drawing *dr, int x1, int y1, int x2, int y2,
1011 int color) 1011 int color)
1012{ 1012{
1013 rb_color(color); 1013 rb_color(color);
@@ -1035,349 +1035,7 @@ static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
1035 } 1035 }
1036} 1036}
1037 1037
1038#if 0 1038static void rb_draw_circle(drawing *dr, int cx, int cy, int radius,
1039/*
1040 * draw filled polygon
1041 * originally by Sebastian Leonhardt (ulmutul)
1042 * 'count' : number of coordinate pairs
1043 * 'pxy': array of coordinates. pxy[0]=x0,pxy[1]=y0,...
1044 * note: provide space for one extra coordinate, because the starting point
1045 * will automatically be inserted as end point.
1046 */
1047
1048/*
1049 * helper function:
1050 * find points of intersection between polygon and scanline
1051 */
1052
1053#define MAX_INTERSECTION 32
1054
1055static void fill_poly_line(int scanline, int count, int *pxy)
1056{
1057 int i;
1058 int j;
1059 int num_of_intersects;
1060 int direct, old_direct;
1061 //intersections of every line with scanline (y-coord)
1062 int intersection[MAX_INTERSECTION];
1063 /* add starting point as ending point */
1064 pxy[count*2] = pxy[0];
1065 pxy[count*2+1] = pxy[1];
1066
1067 old_direct=0;
1068 num_of_intersects=0;
1069 for (i=0; i<count*2; i+=2) {
1070 int x1=pxy[i];
1071 int y1=pxy[i+1];
1072 int x2=pxy[i+2];
1073 int y2=pxy[i+3];
1074 // skip if line is outside of scanline
1075 if (y1 < y2) {
1076 if (scanline < y1 || scanline > y2)
1077 continue;
1078 }
1079 else {
1080 if (scanline < y2 || scanline > y1)
1081 continue;
1082 }
1083 // calculate x-coord of intersection
1084 if (y1==y2) {
1085 direct=0;
1086 }
1087 else {
1088 direct = y1>y2 ? 1 : -1;
1089 // omit double intersections, if both lines lead in the same direction
1090 intersection[num_of_intersects] =
1091 x1+((scanline-y1)*(x2-x1))/(y2-y1);
1092 if ( (direct!=old_direct)
1093 || (intersection[num_of_intersects] != intersection[num_of_intersects-1])
1094 )
1095 ++num_of_intersects;
1096 }
1097 old_direct = direct;
1098 }
1099
1100 // sort points of intersection
1101 for (i=0; i<num_of_intersects-1; ++i) {
1102 for (j=i+1; j<num_of_intersects; ++j) {
1103 if (intersection[j]<intersection[i]) {
1104 int temp=intersection[i];
1105 intersection[i]=intersection[j];
1106 intersection[j]=temp;
1107 }
1108 }
1109 }
1110 // draw
1111 for (i=0; i<num_of_intersects; i+=2) {
1112 rb->lcd_hline(intersection[i], intersection[i+1], scanline);
1113 }
1114}
1115
1116/* two extra elements at end of pxy needed */
1117static void v_fillarea(int count, int *pxy)
1118{
1119 int i;
1120 int y1, y2;
1121
1122 // find min and max y coords
1123 y1=y2=pxy[1];
1124 for (i=3; i<count*2; i+=2) {
1125 if (pxy[i] < y1) y1 = pxy[i];
1126 else if (pxy[i] > y2) y2 = pxy[i];
1127 }
1128
1129 for (i=y1; i<=y2; ++i) {
1130 fill_poly_line(i, count, pxy);
1131 }
1132}
1133#endif
1134
1135/* I'm a horrible person: this was copy-pasta'd straight from
1136 * xlcd_draw.c */
1137
1138/* sort the given coordinates by increasing x value */
1139static void sort_points_by_increasing_x(int* x1, int* y1,
1140 int* x2, int* y2,
1141 int* x3, int* y3)
1142{
1143 int x, y;
1144 if (*x1 > *x3)
1145 {
1146 if (*x2 < *x3) /* x2 < x3 < x1 */
1147 {
1148 x = *x1; *x1 = *x2; *x2 = *x3; *x3 = x;
1149 y = *y1; *y1 = *y2; *y2 = *y3; *y3 = y;
1150 }
1151 else if (*x2 > *x1) /* x3 < x1 < x2 */
1152 {
1153 x = *x1; *x1 = *x3; *x3 = *x2; *x2 = x;
1154 y = *y1; *y1 = *y3; *y3 = *y2; *y2 = y;
1155 }
1156 else /* x3 <= x2 <= x1 */
1157 {
1158 x = *x1; *x1 = *x3; *x3 = x;
1159 y = *y1; *y1 = *y3; *y3 = y;
1160 }
1161 }
1162 else
1163 {
1164 if (*x2 < *x1) /* x2 < x1 <= x3 */
1165 {
1166 x = *x1; *x1 = *x2; *x2 = x;
1167 y = *y1; *y1 = *y2; *y2 = y;
1168 }
1169 else if (*x2 > *x3) /* x1 <= x3 < x2 */
1170 {
1171 x = *x2; *x2 = *x3; *x3 = x;
1172 y = *y2; *y2 = *y3; *y3 = y;
1173 }
1174 /* else already sorted */
1175 }
1176}
1177
1178#define sort_points_by_increasing_y(x1, y1, x2, y2, x3, y3) \
1179 sort_points_by_increasing_x(y1, x1, y2, x2, y3, x3)
1180
1181/* draw a filled triangle, using horizontal lines for speed */
1182static void zoom_filltriangle(int x1, int y1,
1183 int x2, int y2,
1184 int x3, int y3)
1185{
1186 long fp_x1, fp_x2, fp_dx1, fp_dx2;
1187 int y;
1188 sort_points_by_increasing_y(&x1, &y1, &x2, &y2, &x3, &y3);
1189
1190 if (y1 < y3) /* draw */
1191 {
1192 fp_dx1 = ((x3 - x1) << 16) / (y3 - y1);
1193 fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1);
1194
1195 if (y1 < y2) /* first part */
1196 {
1197 fp_dx2 = ((x2 - x1) << 16) / (y2 - y1);
1198 fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1);
1199 for (y = y1; y < y2; y++)
1200 {
1201 zoom_hline(fp_x1 >> 16, fp_x2 >> 16, y);
1202 fp_x1 += fp_dx1;
1203 fp_x2 += fp_dx2;
1204 }
1205 }
1206 if (y2 < y3) /* second part */
1207 {
1208 fp_dx2 = ((x3 - x2) << 16) / (y3 - y2);
1209 fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1);
1210 for (y = y2; y < y3; y++)
1211 {
1212 zoom_hline(fp_x1 >> 16, fp_x2 >> 16, y);
1213 fp_x1 += fp_dx1;
1214 fp_x2 += fp_dx2;
1215 }
1216 }
1217 }
1218}
1219
1220/* Should probably refactor this */
1221static void rb_draw_poly(void *handle, const int *coords, int npoints,
1222 int fillcolor, int outlinecolor)
1223{
1224 if(!zoom_enabled)
1225 {
1226 LOGF("rb_draw_poly");
1227
1228 if(fillcolor >= 0)
1229 {
1230 rb_color(fillcolor);
1231#if 1
1232 /* serious hack: draw a bunch of triangles between adjacent points */
1233 /* this generally works, even with some concave polygons */
1234 for(int i = 2; i < npoints; ++i)
1235 {
1236 int x1, y1, x2, y2, x3, y3;
1237 x1 = coords[0];
1238 y1 = coords[1];
1239 x2 = coords[(i - 1) * 2];
1240 y2 = coords[(i - 1) * 2 + 1];
1241 x3 = coords[i * 2];
1242 y3 = coords[i * 2 + 1];
1243 offset_coords(&x1, &y1);
1244 offset_coords(&x2, &y2);
1245 offset_coords(&x3, &y3);
1246 xlcd_filltriangle(x1, y1,
1247 x2, y2,
1248 x3, y3);
1249
1250#ifdef DEBUG_MENU
1251 if(debug_settings.polyanim)
1252 {
1253 rb->lcd_update();
1254 rb->sleep(HZ/4);
1255 }
1256#endif
1257#if 0
1258 /* debug code */
1259 rb->lcd_set_foreground(LCD_RGBPACK(255,0,0));
1260 rb->lcd_drawpixel(x1, y1);
1261 rb->lcd_drawpixel(x2, y2);
1262 rb->lcd_drawpixel(x3, y3);
1263 rb->lcd_update();
1264 rb->sleep(HZ);
1265 rb_color(fillcolor);
1266 rb->lcd_drawpixel(x1, y1);
1267 rb->lcd_drawpixel(x2, y2);
1268 rb->lcd_drawpixel(x3, y3);
1269 rb->lcd_update();
1270#endif
1271 }
1272#else
1273 int *pxy = smalloc(sizeof(int) * 2 * npoints + 2);
1274 /* copy points, offsetted */
1275 for(int i = 0; i < npoints; ++i)
1276 {
1277 pxy[2 * i + 0] = coords[2 * i + 0];
1278 pxy[2 * i + 1] = coords[2 * i + 1];
1279 offset_coords(&pxy[2*i+0], &pxy[2*i+1]);
1280 }
1281 v_fillarea(npoints, pxy);
1282 sfree(pxy);
1283#endif
1284 }
1285
1286 /* draw outlines last so they're not covered by the fill */
1287 assert(outlinecolor >= 0);
1288 rb_color(outlinecolor);
1289
1290 for(int i = 1; i < npoints; ++i)
1291 {
1292 int x1, y1, x2, y2;
1293 x1 = coords[2 * (i - 1)];
1294 y1 = coords[2 * (i - 1) + 1];
1295 x2 = coords[2 * i];
1296 y2 = coords[2 * i + 1];
1297 if(debug_settings.no_aa)
1298 {
1299 offset_coords(&x1, &y1);
1300 offset_coords(&x2, &y2);
1301 rb->lcd_drawline(x1, y1,
1302 x2, y2);
1303 }
1304 else
1305 draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
1306
1307#ifdef DEBUG_MENU
1308 if(debug_settings.polyanim)
1309 {
1310 rb->lcd_update();
1311 rb->sleep(HZ/4);
1312 }
1313#endif
1314 }
1315
1316 int x1, y1, x2, y2;
1317 x1 = coords[0];
1318 y1 = coords[1];
1319 x2 = coords[2 * (npoints - 1)];
1320 y2 = coords[2 * (npoints - 1) + 1];
1321 if(debug_settings.no_aa)
1322 {
1323 offset_coords(&x1, &y1);
1324 offset_coords(&x2, &y2);
1325
1326 rb->lcd_drawline(x1, y1,
1327 x2, y2);
1328 }
1329 else
1330 draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
1331 }
1332 else
1333 {
1334 LOGF("rb_draw_poly");
1335
1336 if(fillcolor >= 0)
1337 {
1338 rb_color(fillcolor);
1339
1340 /* serious hack: draw a bunch of triangles between adjacent points */
1341 /* this generally works, even with some concave polygons */
1342 for(int i = 2; i < npoints; ++i)
1343 {
1344 int x1, y1, x2, y2, x3, y3;
1345 x1 = coords[0];
1346 y1 = coords[1];
1347 x2 = coords[(i - 1) * 2];
1348 y2 = coords[(i - 1) * 2 + 1];
1349 x3 = coords[i * 2];
1350 y3 = coords[i * 2 + 1];
1351 zoom_filltriangle(x1, y1,
1352 x2, y2,
1353 x3, y3);
1354 }
1355 }
1356
1357 /* draw outlines last so they're not covered by the fill */
1358 assert(outlinecolor >= 0);
1359 rb_color(outlinecolor);
1360
1361 for(int i = 1; i < npoints; ++i)
1362 {
1363 int x1, y1, x2, y2;
1364 x1 = coords[2 * (i - 1)];
1365 y1 = coords[2 * (i - 1) + 1];
1366 x2 = coords[2 * i];
1367 y2 = coords[2 * i + 1];
1368 draw_antialiased_line(zoom_fb, zoom_w, zoom_h, x1, y1, x2, y2);
1369 }
1370
1371 int x1, y1, x2, y2;
1372 x1 = coords[0];
1373 y1 = coords[1];
1374 x2 = coords[2 * (npoints - 1)];
1375 y2 = coords[2 * (npoints - 1) + 1];
1376 draw_antialiased_line(zoom_fb, zoom_w, zoom_h, x1, y1, x2, y2);
1377 }
1378}
1379
1380static void rb_draw_circle(void *handle, int cx, int cy, int radius,
1381 int fillcolor, int outlinecolor) 1039 int fillcolor, int outlinecolor)
1382{ 1040{
1383 if(!zoom_enabled) 1041 if(!zoom_enabled)
@@ -1449,7 +1107,7 @@ static void trim_rect(int *x, int *y, int *w, int *h)
1449 *h = y1 - y0; 1107 *h = y1 - y0;
1450} 1108}
1451 1109
1452static blitter *rb_blitter_new(void *handle, int w, int h) 1110static blitter *rb_blitter_new(drawing *dr, int w, int h)
1453{ 1111{
1454 LOGF("rb_blitter_new"); 1112 LOGF("rb_blitter_new");
1455 blitter *b = snew(blitter); 1113 blitter *b = snew(blitter);
@@ -1460,7 +1118,7 @@ static blitter *rb_blitter_new(void *handle, int w, int h)
1460 return b; 1118 return b;
1461} 1119}
1462 1120
1463static void rb_blitter_free(void *handle, blitter *bl) 1121static void rb_blitter_free(drawing *dr, blitter *bl)
1464{ 1122{
1465 LOGF("rb_blitter_free"); 1123 LOGF("rb_blitter_free");
1466 sfree(bl->bmp.data); 1124 sfree(bl->bmp.data);
@@ -1469,7 +1127,7 @@ static void rb_blitter_free(void *handle, blitter *bl)
1469} 1127}
1470 1128
1471/* copy a section of the framebuffer */ 1129/* copy a section of the framebuffer */
1472static void rb_blitter_save(void *handle, blitter *bl, int x, int y) 1130static void rb_blitter_save(drawing *dr, blitter *bl, int x, int y)
1473{ 1131{
1474 /* no viewport offset */ 1132 /* no viewport offset */
1475#if LCD_STRIDEFORMAT == VERTICAL_STRIDE 1133#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
@@ -1498,7 +1156,7 @@ static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
1498#endif 1156#endif
1499} 1157}
1500 1158
1501static void rb_blitter_load(void *handle, blitter *bl, int x, int y) 1159static void rb_blitter_load(drawing *dr, blitter *bl, int x, int y)
1502{ 1160{
1503 LOGF("rb_blitter_load"); 1161 LOGF("rb_blitter_load");
1504 if(!bl->have_data) 1162 if(!bl->have_data)
@@ -1528,7 +1186,7 @@ static void rb_blitter_load(void *handle, blitter *bl, int x, int y)
1528 } 1186 }
1529} 1187}
1530 1188
1531static void rb_draw_update(void *handle, int x, int y, int w, int h) 1189static void rb_draw_update(drawing *dr, int x, int y, int w, int h)
1532{ 1190{
1533 LOGF("rb_draw_update(%d, %d, %d, %d)", x, y, w, h); 1191 LOGF("rb_draw_update(%d, %d, %d, %d)", x, y, w, h);
1534 1192
@@ -1552,9 +1210,9 @@ static void rb_draw_update(void *handle, int x, int y, int w, int h)
1552 need_draw_update = true; 1210 need_draw_update = true;
1553} 1211}
1554 1212
1555static void rb_start_draw(void *handle) 1213static void rb_start_draw(drawing *dr)
1556{ 1214{
1557 (void) handle; 1215 (void) dr;
1558 1216
1559 /* ... mumble mumble ... not ... reentrant ... mumble mumble ... */ 1217 /* ... mumble mumble ... not ... reentrant ... mumble mumble ... */
1560 1218
@@ -1565,9 +1223,9 @@ static void rb_start_draw(void *handle)
1565 ud_d = LCD_HEIGHT; 1223 ud_d = LCD_HEIGHT;
1566} 1224}
1567 1225
1568static void rb_end_draw(void *handle) 1226static void rb_end_draw(drawing *dr)
1569{ 1227{
1570 (void) handle; 1228 (void) dr;
1571 1229
1572 if(debug_settings.highlight_cursor) 1230 if(debug_settings.highlight_cursor)
1573 { 1231 {
@@ -1594,7 +1252,7 @@ static void rb_end_draw(void *handle)
1594#endif 1252#endif
1595} 1253}
1596 1254
1597static void rb_status_bar(void *handle, const char *text) 1255static void rb_status_bar(drawing *dr, const char *text)
1598{ 1256{
1599 if(titlebar) 1257 if(titlebar)
1600 sfree(titlebar); 1258 sfree(titlebar);
@@ -1692,7 +1350,7 @@ static void draw_mouse(void)
1692 * glyph exists in a font) */ 1350 * glyph exists in a font) */
1693#if 0 1351#if 0
1694/* See: https://www.chiark.greenend.org.uk/~sgtatham/puzzles/devel/drawing.html#drawing-text-fallback */ 1352/* See: https://www.chiark.greenend.org.uk/~sgtatham/puzzles/devel/drawing.html#drawing-text-fallback */
1695static char *rb_text_fallback(void *handle, const char *const *strings, 1353static char *rb_text_fallback(drawing *dr, const char *const *strings,
1696 int nstrings) 1354 int nstrings)
1697{ 1355{
1698 struct font *pf = rb->font_get(cur_font); 1356 struct font *pf = rb->font_get(cur_font);
@@ -1725,10 +1383,11 @@ static char *rb_text_fallback(void *handle, const char *const *strings,
1725#endif 1383#endif
1726 1384
1727const drawing_api rb_drawing = { 1385const drawing_api rb_drawing = {
1386 1,
1728 rb_draw_text, 1387 rb_draw_text,
1729 rb_draw_rect, 1388 rb_draw_rect,
1730 rb_draw_line, 1389 rb_draw_line,
1731 rb_draw_poly, 1390 draw_polygon_fallback,
1732 rb_draw_circle, 1391 rb_draw_circle,
1733 rb_draw_update, 1392 rb_draw_update,
1734 rb_clip, 1393 rb_clip,