Skip to content

Commit da9d224

Browse files
committed
UI: experimental keypad to replace android keypad
1 parent 8c6752f commit da9d224

File tree

9 files changed

+1011
-233
lines changed

9 files changed

+1011
-233
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ set(SOURCES
185185
${UI_DIR}/textedit.cpp
186186
${UI_DIR}/keypad.cpp
187187
${UI_DIR}/image.cpp
188-
${UI_DIR}/lodepng_codec.cpp
188+
${UI_DIR}/image_codec.cpp
189189
${UI_DIR}/strlib.cpp
190190
${UI_DIR}/audio.cpp
191191
${SDL_DIR}/main.cpp

images/keypad/build.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ declare -a IMAGE_FILES=(\
99
"proicons-book-info-2.png"\
1010
"proicons-backspace.png"\
1111
"proicons-arrow-enter.png"\
12+
"proicons-search.png"\
1213
)
1314

14-
echo "#pragma once" > keypad-icons.h
15-
echo "// https://procode-software.github.io/proicons/icons" >> keypad-icons.h
15+
echo "#pragma once" > keypad_icons.h
16+
echo "// https://procode-software.github.io/proicons/icons" >> keypad_icons.h
1617
for imageFile in "${IMAGE_FILES[@]}"
1718
do
1819
name=`ls -1 ${imageFile} | sed -e 's/proicons-/img-/' | sed -e 's/\.png//'`
19-
xxd -n ${name} -i ${imageFile} >> keypad-icons.h
20+
xxd -n ${name} -i ${imageFile} >> keypad_icons.h
2021
done
22+
23+
cp keypad_icons.h ../../src/ui
24+

src/ui/image_codec.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// This file is part of SmallBASIC
2+
//
3+
// Image handling
4+
//
5+
// This program is distributed under the terms of the GPL v2.0 or later
6+
// Download the GNU Public License (GPL) from www.gnu.org
7+
//
8+
// Copyright(C) 2002-2025 Chris Warren-Smith.
9+
10+
#include "image_codec.h"
11+
#include "lib/lodepng/lodepng.h"
12+
#include <cstdlib>
13+
#include <cstring>
14+
15+
static char g_last_error[256] = {0};
16+
17+
static float lerp(float a, float b, float t) {
18+
return a + t * (b - a);
19+
}
20+
21+
ImageCodec::ImageCodec(const uint8_t *data, size_t size) :
22+
_width(0),
23+
_height(0),
24+
_pixels(nullptr) {
25+
auto error = lodepng_decode32(&_pixels, &_width, &_height, data, size);
26+
if (error) {
27+
snprintf(g_last_error, sizeof(g_last_error), "%s", lodepng_error_text(error));
28+
}
29+
}
30+
31+
ImageCodec::~ImageCodec() {
32+
free(_pixels);
33+
_pixels = nullptr;
34+
}
35+
36+
const char *ImageCodec::getLastError(void) {
37+
return g_last_error;
38+
}
39+
40+
bool ImageCodec::encode(uint8_t **data, size_t *size) const {
41+
bool result;
42+
if (!data || !size) {
43+
sprintf(g_last_error, "Invalid args");
44+
result = false;
45+
} else {
46+
uint8_t *img = nullptr;
47+
size_t img_size = 0;
48+
auto error = lodepng_encode32(&img, &img_size, _pixels, _width, _height);
49+
if (error) {
50+
snprintf(g_last_error, sizeof(g_last_error), "%s", lodepng_error_text(error));
51+
} else {
52+
*data = img;
53+
*size = img_size;
54+
}
55+
result = !error;
56+
}
57+
return result;
58+
}
59+
60+
void ImageCodec::resize(unsigned width, unsigned height) {
61+
uint8_t *pixels = new uint8_t[width * height * 4];
62+
63+
for (int y = 0; y < height; y++) {
64+
float gy = ((float)y + 0.5f) * _height / height - 0.5f;
65+
int y0 = (int)gy, y1 = y0 + 1;
66+
float fy = gy - y0;
67+
y0 = y0 < 0 ? 0 : (y0 >= _height ? _height - 1 : y0);
68+
y1 = y1 < 0 ? 0 : (y1 >= _height ? _height - 1 : y1);
69+
70+
for (int x = 0; x < width; x++) {
71+
float gx = ((float)x + 0.5f) * _width / width - 0.5f;
72+
int x0 = (int)gx, x1 = x0 + 1;
73+
float fx = gx - x0;
74+
x0 = x0 < 0 ? 0 : (x0 >= _width ? _width - 1 : x0);
75+
x1 = x1 < 0 ? 0 : (x1 >= _width ? _width - 1 : x1);
76+
77+
int offset = 4 * (y * width + x);
78+
for (int c = 0; c < 4; c++) {
79+
// A, R, G, B
80+
float tl = _pixels[4 * (y0 * _width + x0) + c];
81+
float tr = _pixels[4 * (y0 * _width + x1) + c];
82+
float bl = _pixels[4 * (y1 * _width + x0) + c];
83+
float br = _pixels[4 * (y1 * _width + x1) + c];
84+
85+
float top = lerp(tl, tr, fx);
86+
float bottom = lerp(bl, br, fx);
87+
float value = lerp(top, bottom, fy);
88+
89+
pixels[offset + c] = (uint8_t)(value + 0.5f);
90+
}
91+
}
92+
}
93+
94+
free(_pixels);
95+
_pixels = pixels;
96+
_width = width;
97+
_height = height;
98+
}
99+

src/ui/image_codec.h

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,47 +6,53 @@
66
// Download the GNU Public License (GPL) from www.gnu.org
77
//
88

9-
#ifndef IMG_CODEC_H
10-
#define IMG_CODEC_H
9+
#pragma once
1110

1211
#include "config.h"
1312
#include <cstddef>
1413
#include <cstdint>
1514

16-
#ifdef __cplusplus
17-
extern "C" {
18-
#endif
19-
20-
struct ImageData {
21-
ImageData();
22-
~ImageData();
23-
15+
class ImageCodec {
16+
public:
17+
//
18+
// Decode IMG to raw RGBA image
19+
//
20+
ImageCodec(const uint8_t *data, size_t size);
21+
virtual ~ImageCodec();
22+
23+
// Prevent copy and move
24+
ImageCodec(const ImageCodec &) = delete;
25+
ImageCodec& operator=(const ImageCodec &) = delete;
26+
27+
//
28+
// Encode the raw image RGBA data to png
29+
// The function allocates *data which must be freed.
30+
//
31+
bool encode(uint8_t **data, size_t *size) const;
32+
33+
//
34+
// resize the image to the given dimensions
35+
//
36+
void resize(unsigned width, unsigned height);
37+
38+
//
39+
// Returns the last error
40+
//
41+
static const char *getLastError(void);
42+
43+
//
44+
// Returns the image width
45+
//
46+
int getWidth() const { return _width; }
47+
48+
//
49+
// Returns the image height
50+
//
51+
int getHeight() const { return _height; }
52+
53+
protected:
2454
unsigned _width;
2555
unsigned _height;
2656
uint8_t *_pixels;
2757
};
2858

29-
//
30-
// Decode IMG to raw RGBA image
31-
// Caller allocates and passes in imgData and its size.
32-
// The function allocates ImageData.pixels (must be freed with img_free).
33-
//
34-
int img_decode(const uint8_t *imgData, size_t imgSize, ImageData *outImage);
35-
36-
//
37-
// Encode raw RGBA image to IMG
38-
// Caller allocates and passes in image.
39-
// The function allocates *outImgData which must be freed.
40-
//
41-
int img_encode(const ImageData *image, uint8_t **outImgData, size_t *outImgSize);
42-
43-
//
44-
// Get last error string
45-
//
46-
const char *img_get_last_error(void);
47-
48-
#ifdef __cplusplus
49-
}
50-
#endif
51-
52-
#endif // IMG_CODEC_H

src/ui/keycode.h

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// This file is part of SmallBASIC
2+
//
3+
// Copyright(C) 2001-2025 Chris Warren-Smith.
4+
//
5+
// This program is distributed under the terms of the GPL v2.0 or later
6+
// Download the GNU Public License (GPL) from www.gnu.org
7+
//
8+
9+
#pragma once
10+
11+
enum KeyCode : char {
12+
K_UP = -1,
13+
K_DOWN = -2,
14+
K_LEFT = -3,
15+
K_RIGHT = -4,
16+
K_HOME = -5,
17+
K_END = -6,
18+
K_PAGE_UP = -7,
19+
K_PAGE_DOWN = -8,
20+
K_INSERT = -9,
21+
K_DELETE = -10,
22+
K_CUT = -11,
23+
K_COPY = -12,
24+
K_PASTE = -13,
25+
K_SAVE = -14,
26+
K_HELP = -15,
27+
K_SEARCH = -16,
28+
K_RUN = -17,
29+
K_TOGGLE = -18,
30+
K_SHIFT = -19,
31+
K_FIND = -20,
32+
K_NULL = 0,
33+
K_BACKSPACE = 8,
34+
K_TAB = 9,
35+
K_NEWLINE = 10,
36+
K_ENTER = 13,
37+
K_ESCAPE = 27,
38+
K_SPACE = 32,
39+
K_EXCLAIM = 33, // !
40+
K_QUOTE = 34, // "
41+
K_HASH = 35, // #
42+
K_DOLLAR = 36, // $
43+
K_PERCENT = 37, // %
44+
K_AMPERSAND = 38, // &
45+
K_APOSTROPHE = 39, // '
46+
K_LPAREN = 40, // (
47+
K_RPAREN = 41, // )
48+
K_ASTERISK = 42, // *
49+
K_PLUS = 43, // +
50+
K_COMMA = 44, // ,
51+
K_MINUS = 45, // -
52+
K_PERIOD = 46, // .
53+
K_SLASH = 47, // /
54+
K_0 = 48, K_1 = 49, K_2 = 50, K_3 = 51, K_4 = 52,
55+
K_5 = 53, K_6 = 54, K_7 = 55, K_8 = 56, K_9 = 57,
56+
K_COLON = 58, // :
57+
K_SEMICOLON = 59, // ;
58+
K_LESS = 60, // <
59+
K_EQUALS = 61, // =
60+
K_GREATER = 62, // >
61+
K_QUESTION = 63, // ?
62+
K_AT = 64, // @
63+
K_A = 65, K_B = 66, K_C = 67, K_D = 68, K_E = 69,
64+
K_F = 70, K_G = 71, K_H = 72, K_I = 73, K_J = 74,
65+
K_K = 75, K_L = 76, K_M = 77, K_N = 78, K_O = 79,
66+
K_P = 80, K_Q = 81, K_R = 82, K_S = 83, K_T = 84,
67+
K_U = 85, K_V = 86, K_W = 87, K_X = 88, K_Y = 89,
68+
K_Z = 90,
69+
K_LBRACKET = 91, // [
70+
K_BACKSLASH = 92, //
71+
K_RBRACKET = 93, // ]
72+
K_CARET = 94, // ^
73+
K_UNDERSCORE = 95, // _
74+
K_BACKTICK = 96, // `
75+
K_a = 97, K_b = 98, K_c = 99, K_d = 100, K_e = 101,
76+
K_f = 102, K_g = 103, K_h = 104, K_i = 105, K_j = 106,
77+
K_k = 107, K_l = 108, K_m = 109, K_n = 110, K_o = 111,
78+
K_p = 112, K_q = 113, K_r = 114, K_s = 115, K_t = 116,
79+
K_u = 117, K_v = 118, K_w = 119, K_x = 120, K_y = 121,
80+
K_z = 122,
81+
K_LBRACE = 123, // {
82+
K_PIPE = 124, // |
83+
K_RBRACE = 125, // }
84+
K_TILDE = 126, // ~
85+
K_DEL = 127 // DEL
86+
};
87+
88+
inline bool isPrintable(KeyCode key) {
89+
return key >= K_SPACE && key <= K_TILDE;
90+
}
91+
92+
inline bool isNumber(KeyCode key) {
93+
return key >= K_0 && key <= K_9;
94+
}
95+

0 commit comments

Comments
 (0)