LiteRGSS 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/ext/LiteRGSS/Bitmap.cpp +316 -0
  3. data/ext/LiteRGSS/Bitmap.h +24 -0
  4. data/ext/LiteRGSS/BlendMode.cpp +202 -0
  5. data/ext/LiteRGSS/BlendMode.h +20 -0
  6. data/ext/LiteRGSS/CBitmap_Element.cpp +50 -0
  7. data/ext/LiteRGSS/CBitmap_Element.h +17 -0
  8. data/ext/LiteRGSS/CDrawable_Element.cpp +38 -0
  9. data/ext/LiteRGSS/CDrawable_Element.h +30 -0
  10. data/ext/LiteRGSS/CRect_Element.h +15 -0
  11. data/ext/LiteRGSS/CShaderSprite_Element.cpp +17 -0
  12. data/ext/LiteRGSS/CShaderSprite_Element.h +17 -0
  13. data/ext/LiteRGSS/CSprite_Element.cpp +15 -0
  14. data/ext/LiteRGSS/CSprite_Element.h +36 -0
  15. data/ext/LiteRGSS/CText_Element.cpp +12 -0
  16. data/ext/LiteRGSS/CText_Element.h +29 -0
  17. data/ext/LiteRGSS/CTone_Element.h +17 -0
  18. data/ext/LiteRGSS/CViewport_Element.cpp +224 -0
  19. data/ext/LiteRGSS/CViewport_Element.h +57 -0
  20. data/ext/LiteRGSS/Color.cpp +200 -0
  21. data/ext/LiteRGSS/Color.h +22 -0
  22. data/ext/LiteRGSS/Fonts.cpp +126 -0
  23. data/ext/LiteRGSS/Fonts.h +20 -0
  24. data/ext/LiteRGSS/Graphics.cpp +314 -0
  25. data/ext/LiteRGSS/Graphics.h +31 -0
  26. data/ext/LiteRGSS/Graphics.local.cpp +365 -0
  27. data/ext/LiteRGSS/Graphics.local.h +37 -0
  28. data/ext/LiteRGSS/Image.cpp +460 -0
  29. data/ext/LiteRGSS/Image.h +32 -0
  30. data/ext/LiteRGSS/Input.cpp +664 -0
  31. data/ext/LiteRGSS/Input.h +38 -0
  32. data/ext/LiteRGSS/LiteRGSS.cpp +34 -0
  33. data/ext/LiteRGSS/LiteRGSS.h +113 -0
  34. data/ext/LiteRGSS/Rect.cpp +324 -0
  35. data/ext/LiteRGSS/Rect.h +24 -0
  36. data/ext/LiteRGSS/Shader.cpp +279 -0
  37. data/ext/LiteRGSS/Shader.h +13 -0
  38. data/ext/LiteRGSS/ShaderSprite.cpp +78 -0
  39. data/ext/LiteRGSS/ShaderSprite.h +8 -0
  40. data/ext/LiteRGSS/Sprite.cpp +495 -0
  41. data/ext/LiteRGSS/Sprite.h +43 -0
  42. data/ext/LiteRGSS/Table.cpp +228 -0
  43. data/ext/LiteRGSS/Table.h +29 -0
  44. data/ext/LiteRGSS/Table32.cpp +228 -0
  45. data/ext/LiteRGSS/Table32.h +29 -0
  46. data/ext/LiteRGSS/Text.cpp +574 -0
  47. data/ext/LiteRGSS/Text.h +52 -0
  48. data/ext/LiteRGSS/Texture.hpp +735 -0
  49. data/ext/LiteRGSS/Tone.cpp +228 -0
  50. data/ext/LiteRGSS/Tone.h +22 -0
  51. data/ext/LiteRGSS/Viewport.cpp +491 -0
  52. data/ext/LiteRGSS/Viewport.h +33 -0
  53. data/ext/LiteRGSS/Yuki.cpp +29 -0
  54. data/ext/LiteRGSS/Yuki.h +8 -0
  55. data/ext/LiteRGSS/Yuki_Gif.cpp +218 -0
  56. data/ext/LiteRGSS/Yuki_Gif.h +25 -0
  57. data/ext/LiteRGSS/extconf.rb +8 -0
  58. data/ext/LiteRGSS/libnsgif.c +1169 -0
  59. data/ext/LiteRGSS/libnsgif.h +183 -0
  60. data/ext/LiteRGSS/libnsgif.hpp +184 -0
  61. data/ext/LiteRGSS/lodepng.cpp +6245 -0
  62. data/ext/LiteRGSS/lodepng.h +1769 -0
  63. data/ext/LiteRGSS/lzw.c +377 -0
  64. data/ext/LiteRGSS/lzw.h +105 -0
  65. data/ext/LiteRGSS/sf_Text2.cpp +690 -0
  66. data/ext/LiteRGSS/sf_Text2.hpp +549 -0
  67. data/ext/LiteRGSS/utils/log.h +21 -0
  68. metadata +112 -0
@@ -0,0 +1,377 @@
1
+ /*
2
+ * This file is part of NetSurf's LibNSGIF, http://www.netsurf-browser.org/
3
+ * Licensed under the MIT License,
4
+ * http://www.opensource.org/licenses/mit-license.php
5
+ *
6
+ * Copyright 2017 Michael Drake <michael.drake@codethink.co.uk>
7
+ */
8
+
9
+ #include <assert.h>
10
+ #include <stdint.h>
11
+ #include <stdlib.h>
12
+ #include <stdbool.h>
13
+
14
+ #include "lzw.h"
15
+
16
+ /**
17
+ * \file
18
+ * \brief LZW decompression (implementation)
19
+ *
20
+ * Decoder for GIF LZW data.
21
+ */
22
+
23
+
24
+ /**
25
+ * Context for reading LZW data.
26
+ *
27
+ * LZW data is split over multiple sub-blocks. Each sub-block has a
28
+ * byte at the start, which says the sub-block size, and then the data.
29
+ * Zero-size sub-blocks have no data, and the biggest sub-block size is
30
+ * 255, which means there are 255 bytes of data following the sub-block
31
+ * size entry.
32
+ *
33
+ * Note that an individual LZW code can be split over up to three sub-blocks.
34
+ */
35
+ struct lzw_read_ctx {
36
+ const uint8_t *data; /**< Pointer to start of input data */
37
+ uint32_t data_len; /**< Input data length */
38
+ uint32_t data_sb_next; /**< Offset to sub-block size */
39
+
40
+ const uint8_t *sb_data; /**< Pointer to current sub-block in data */
41
+ uint32_t sb_bit; /**< Current bit offset in sub-block */
42
+ uint32_t sb_bit_count; /**< Bit count in sub-block */
43
+ };
44
+
45
+ /**
46
+ * LZW dictionary entry.
47
+ *
48
+ * Records in the dictionary are composed of 1 or more entries.
49
+ * Entries point to previous entries which can be followed to compose
50
+ * the complete record. To compose the record in reverse order, take
51
+ * the `last_value` from each entry, and move to the previous entry.
52
+ * If the previous_entry's index is < the current clear_code, then it
53
+ * is the last entry in the record.
54
+ */
55
+ struct lzw_dictionary_entry {
56
+ uint8_t last_value; /**< Last value for record ending at entry. */
57
+ uint8_t first_value; /**< First value for entry's record. */
58
+ uint16_t previous_entry; /**< Offset in dictionary to previous entry. */
59
+ };
60
+
61
+ /**
62
+ * LZW decompression context.
63
+ */
64
+ struct lzw_ctx {
65
+ /** Input reading context */
66
+ struct lzw_read_ctx input;
67
+
68
+ uint32_t previous_code; /**< Code read from input previously. */
69
+ uint32_t previous_code_first; /**< First value of previous code. */
70
+
71
+ uint32_t initial_code_size; /**< Starting LZW code size. */
72
+ uint32_t current_code_size; /**< Current LZW code size. */
73
+ uint32_t current_code_size_max; /**< Max code value for current size. */
74
+
75
+ uint32_t clear_code; /**< Special Clear code value */
76
+ uint32_t eoi_code; /**< Special End of Information code value */
77
+
78
+ uint32_t current_entry; /**< Next position in table to fill. */
79
+
80
+ /** Output value stack. */
81
+ uint8_t stack_base[1 << LZW_CODE_MAX];
82
+
83
+ /** LZW decode dictionary. Generated during decode. */
84
+ struct lzw_dictionary_entry table[1 << LZW_CODE_MAX];
85
+ };
86
+
87
+
88
+ /* Exported function, documented in lzw.h */
89
+ lzw_result lzw_context_create(struct lzw_ctx **ctx)
90
+ {
91
+ struct lzw_ctx *c = malloc(sizeof(*c));
92
+ if (c == NULL) {
93
+ return LZW_NO_MEM;
94
+ }
95
+
96
+ *ctx = c;
97
+ return LZW_OK;
98
+ }
99
+
100
+
101
+ /* Exported function, documented in lzw.h */
102
+ void lzw_context_destroy(struct lzw_ctx *ctx)
103
+ {
104
+ free(ctx);
105
+ }
106
+
107
+
108
+ /**
109
+ * Advance the context to the next sub-block in the input data.
110
+ *
111
+ * \param[in] ctx LZW reading context, updated on success.
112
+ * \return LZW_OK or LZW_OK_EOD on success, appropriate error otherwise.
113
+ */
114
+ static lzw_result lzw__block_advance(struct lzw_read_ctx *ctx)
115
+ {
116
+ uint32_t block_size;
117
+ uint32_t next_block_pos = ctx->data_sb_next;
118
+ const uint8_t *data_next = ctx->data + next_block_pos;
119
+
120
+ if (next_block_pos >= ctx->data_len) {
121
+ return LZW_NO_DATA;
122
+ }
123
+
124
+ block_size = *data_next;
125
+
126
+ if ((next_block_pos + block_size) >= ctx->data_len) {
127
+ return LZW_NO_DATA;
128
+ }
129
+
130
+ ctx->sb_bit = 0;
131
+ ctx->sb_bit_count = block_size * 8;
132
+
133
+ if (block_size == 0) {
134
+ ctx->data_sb_next += 1;
135
+ return LZW_OK_EOD;
136
+ }
137
+
138
+ ctx->sb_data = data_next + 1;
139
+ ctx->data_sb_next += block_size + 1;
140
+
141
+ return LZW_OK;
142
+ }
143
+
144
+
145
+ /**
146
+ * Get the next LZW code of given size from the raw input data.
147
+ *
148
+ * Reads codes from the input data stream coping with GIF data sub-blocks.
149
+ *
150
+ * \param[in] ctx LZW reading context, updated.
151
+ * \param[in] code_size Size of LZW code to get from data.
152
+ * \param[out] code_out Returns an LZW code on success.
153
+ * \return LZW_OK or LZW_OK_EOD on success, appropriate error otherwise.
154
+ */
155
+ static inline lzw_result lzw__next_code(
156
+ struct lzw_read_ctx *ctx,
157
+ uint8_t code_size,
158
+ uint32_t *code_out)
159
+ {
160
+ uint32_t code = 0;
161
+ uint8_t current_bit = ctx->sb_bit & 0x7;
162
+ uint8_t byte_advance = (current_bit + code_size) >> 3;
163
+
164
+ assert(byte_advance <= 2);
165
+
166
+ if (ctx->sb_bit + code_size < ctx->sb_bit_count) {
167
+ /* Fast path: code fully inside this sub-block */
168
+ const uint8_t *data = ctx->sb_data + (ctx->sb_bit >> 3);
169
+ switch (byte_advance) {
170
+ case 2: code |= data[2] << 16; /* Fall through */
171
+ case 1: code |= data[1] << 8; /* Fall through */
172
+ case 0: code |= data[0] << 0;
173
+ }
174
+ ctx->sb_bit += code_size;
175
+ } else {
176
+ /* Slow path: code spans sub-blocks */
177
+ uint8_t byte = 0;
178
+ uint8_t bits_remaining_0 = (code_size < (8 - current_bit)) ?
179
+ code_size : (8 - current_bit);
180
+ uint8_t bits_remaining_1 = code_size - bits_remaining_0;
181
+ uint8_t bits_used[3] = {
182
+ [0] = bits_remaining_0,
183
+ [1] = bits_remaining_1 < 8 ? bits_remaining_1 : 8,
184
+ [2] = bits_remaining_1 - 8,
185
+ };
186
+
187
+ while (true) {
188
+ const uint8_t *data = ctx->sb_data;
189
+ lzw_result res;
190
+
191
+ /* Get any data from end of this sub-block */
192
+ while (byte <= byte_advance &&
193
+ ctx->sb_bit < ctx->sb_bit_count) {
194
+ code |= data[ctx->sb_bit >> 3] << (byte << 3);
195
+ ctx->sb_bit += bits_used[byte];
196
+ byte++;
197
+ }
198
+
199
+ /* Check if we have all we need */
200
+ if (byte > byte_advance) {
201
+ break;
202
+ }
203
+
204
+ /* Move to next sub-block */
205
+ res = lzw__block_advance(ctx);
206
+ if (res != LZW_OK) {
207
+ return res;
208
+ }
209
+ }
210
+ }
211
+
212
+ *code_out = (code >> current_bit) & ((1 << code_size) - 1);
213
+ return LZW_OK;
214
+ }
215
+
216
+
217
+ /**
218
+ * Clear LZW code dictionary.
219
+ *
220
+ * \param[in] ctx LZW reading context, updated.
221
+ * \param[out] stack_pos_out Returns current stack position.
222
+ * \return LZW_OK or error code.
223
+ */
224
+ static lzw_result lzw__clear_codes(
225
+ struct lzw_ctx *ctx,
226
+ const uint8_t ** const stack_pos_out)
227
+ {
228
+ uint32_t code;
229
+ uint8_t *stack_pos;
230
+
231
+ /* Reset dictionary building context */
232
+ ctx->current_code_size = ctx->initial_code_size + 1;
233
+ ctx->current_code_size_max = (1 << ctx->current_code_size) - 1;;
234
+ ctx->current_entry = (1 << ctx->initial_code_size) + 2;
235
+
236
+ /* There might be a sequence of clear codes, so process them all */
237
+ do {
238
+ lzw_result res = lzw__next_code(&ctx->input,
239
+ ctx->current_code_size, &code);
240
+ if (res != LZW_OK) {
241
+ return res;
242
+ }
243
+ } while (code == ctx->clear_code);
244
+
245
+ /* The initial code must be from the initial dictionary. */
246
+ if (code > ctx->clear_code) {
247
+ return LZW_BAD_ICODE;
248
+ }
249
+
250
+ /* Record this initial code as "previous" code, needed during decode. */
251
+ ctx->previous_code = code;
252
+ ctx->previous_code_first = code;
253
+
254
+ /* Reset the stack, and add first non-clear code added as first item. */
255
+ stack_pos = ctx->stack_base;
256
+ *stack_pos++ = code;
257
+
258
+ *stack_pos_out = stack_pos;
259
+ return LZW_OK;
260
+ }
261
+
262
+
263
+ /* Exported function, documented in lzw.h */
264
+ lzw_result lzw_decode_init(
265
+ struct lzw_ctx *ctx,
266
+ const uint8_t *compressed_data,
267
+ uint32_t compressed_data_len,
268
+ uint32_t compressed_data_pos,
269
+ uint8_t code_size,
270
+ const uint8_t ** const stack_base_out,
271
+ const uint8_t ** const stack_pos_out)
272
+ {
273
+ struct lzw_dictionary_entry *table = ctx->table;
274
+
275
+ /* Initialise the input reading context */
276
+ ctx->input.data = compressed_data;
277
+ ctx->input.data_len = compressed_data_len;
278
+ ctx->input.data_sb_next = compressed_data_pos;
279
+
280
+ ctx->input.sb_bit = 0;
281
+ ctx->input.sb_bit_count = 0;
282
+
283
+ /* Initialise the dictionary building context */
284
+ ctx->initial_code_size = code_size;
285
+
286
+ ctx->clear_code = (1 << code_size) + 0;
287
+ ctx->eoi_code = (1 << code_size) + 1;
288
+
289
+ /* Initialise the standard dictionary entries */
290
+ for (uint32_t i = 0; i < ctx->clear_code; ++i) {
291
+ table[i].first_value = i;
292
+ table[i].last_value = i;
293
+ }
294
+
295
+ *stack_base_out = ctx->stack_base;
296
+ return lzw__clear_codes(ctx, stack_pos_out);
297
+ }
298
+
299
+
300
+ /* Exported function, documented in lzw.h */
301
+ lzw_result lzw_decode(struct lzw_ctx *ctx,
302
+ const uint8_t ** const stack_pos_out)
303
+ {
304
+ lzw_result res;
305
+ uint32_t code_new;
306
+ uint32_t code_out;
307
+ uint8_t last_value;
308
+ uint8_t *stack_pos = ctx->stack_base;
309
+ uint32_t clear_code = ctx->clear_code;
310
+ uint32_t current_entry = ctx->current_entry;
311
+ struct lzw_dictionary_entry * const table = ctx->table;
312
+
313
+ /* Get a new code from the input */
314
+ res = lzw__next_code(&ctx->input, ctx->current_code_size, &code_new);
315
+ if (res != LZW_OK) {
316
+ return res;
317
+ }
318
+
319
+ /* Handle the new code */
320
+ if (code_new == clear_code) {
321
+ /* Got Clear code */
322
+ return lzw__clear_codes(ctx, stack_pos_out);
323
+
324
+ } else if (code_new == ctx->eoi_code) {
325
+ /* Got End of Information code */
326
+ return LZW_EOI_CODE;
327
+
328
+ } else if (code_new > current_entry) {
329
+ /* Code is invalid */
330
+ return LZW_BAD_CODE;
331
+
332
+ } else if (code_new < current_entry) {
333
+ /* Code is in table */
334
+ code_out = code_new;
335
+ last_value = table[code_new].first_value;
336
+ } else {
337
+ /* Code not in table */
338
+ *stack_pos++ = ctx->previous_code_first;
339
+ code_out = ctx->previous_code;
340
+ last_value = ctx->previous_code_first;
341
+ }
342
+
343
+ /* Add to the dictionary, only if there's space */
344
+ if (current_entry < (1 << LZW_CODE_MAX)) {
345
+ struct lzw_dictionary_entry *entry = table + current_entry;
346
+ entry->last_value = last_value;
347
+ entry->first_value = ctx->previous_code_first;
348
+ entry->previous_entry = ctx->previous_code;
349
+ ctx->current_entry++;
350
+ }
351
+
352
+ /* Ensure code size is increased, if needed. */
353
+ if (current_entry == ctx->current_code_size_max) {
354
+ if (ctx->current_code_size < LZW_CODE_MAX) {
355
+ ctx->current_code_size++;
356
+ ctx->current_code_size_max =
357
+ (1 << ctx->current_code_size) - 1;
358
+ }
359
+ }
360
+
361
+ /* Store details of this code as "previous code" to the context. */
362
+ ctx->previous_code_first = table[code_new].first_value;
363
+ ctx->previous_code = code_new;
364
+
365
+ /* Put rest of data for this code on output stack.
366
+ * Note, in the case of "code not in table", the last entry of the
367
+ * current code has already been placed on the stack above. */
368
+ while (code_out > clear_code) {
369
+ struct lzw_dictionary_entry *entry = table + code_out;
370
+ *stack_pos++ = entry->last_value;
371
+ code_out = entry->previous_entry;
372
+ }
373
+ *stack_pos++ = table[code_out].last_value;
374
+
375
+ *stack_pos_out = stack_pos;
376
+ return LZW_OK;
377
+ }
@@ -0,0 +1,105 @@
1
+ /*
2
+ * This file is part of NetSurf's LibNSGIF, http://www.netsurf-browser.org/
3
+ * Licensed under the MIT License,
4
+ * http://www.opensource.org/licenses/mit-license.php
5
+ *
6
+ * Copyright 2017 Michael Drake <michael.drake@codethink.co.uk>
7
+ */
8
+
9
+ #ifndef LZW_H_
10
+ #define LZW_H_
11
+
12
+ /**
13
+ * \file
14
+ * \brief LZW decompression (interface)
15
+ *
16
+ * Decoder for GIF LZW data.
17
+ */
18
+
19
+
20
+ /** Maximum LZW code size in bits */
21
+ #define LZW_CODE_MAX 12
22
+
23
+
24
+ /* Declare lzw internal context structure */
25
+ struct lzw_ctx;
26
+
27
+
28
+ /** LZW decoding response codes */
29
+ typedef enum lzw_result {
30
+ LZW_OK, /**< Success */
31
+ LZW_OK_EOD, /**< Success; reached zero-length sub-block */
32
+ LZW_NO_MEM, /**< Error: Out of memory */
33
+ LZW_NO_DATA, /**< Error: Out of data */
34
+ LZW_EOI_CODE, /**< Error: End of Information code */
35
+ LZW_BAD_ICODE, /**< Error: Bad initial LZW code */
36
+ LZW_BAD_CODE, /**< Error: Bad LZW code */
37
+ } lzw_result;
38
+
39
+
40
+ /**
41
+ * Create an LZW decompression context.
42
+ *
43
+ * \param[out] ctx Returns an LZW decompression context. Caller owned,
44
+ * free with lzw_context_destroy().
45
+ * \return LZW_OK on success, or appropriate error code otherwise.
46
+ */
47
+ lzw_result lzw_context_create(
48
+ struct lzw_ctx **ctx);
49
+
50
+ /**
51
+ * Destroy an LZW decompression context.
52
+ *
53
+ * \param[in] ctx The LZW decompression context to destroy.
54
+ */
55
+ void lzw_context_destroy(
56
+ struct lzw_ctx *ctx);
57
+
58
+ /**
59
+ * Initialise an LZW decompression context for decoding.
60
+ *
61
+ * Caller owns neither `stack_base_out` or `stack_pos_out`.
62
+ *
63
+ * \param[in] ctx The LZW decompression context to initialise.
64
+ * \param[in] compressed_data The compressed data.
65
+ * \param[in] compressed_data_len Byte length of compressed data.
66
+ * \param[in] compressed_data_pos Start position in data. Must be position
67
+ * of a size byte at sub-block start.
68
+ * \param[in] code_size The initial LZW code size to use.
69
+ * \param[out] stack_base_out Returns base of decompressed data stack.
70
+ * \param[out] stack_pos_out Returns current stack position.
71
+ * There are `stack_pos_out - stack_base_out`
72
+ * current stack entries.
73
+ * \return LZW_OK on success, or appropriate error code otherwise.
74
+ */
75
+ lzw_result lzw_decode_init(
76
+ struct lzw_ctx *ctx,
77
+ const uint8_t *compressed_data,
78
+ uint32_t compressed_data_len,
79
+ uint32_t compressed_data_pos,
80
+ uint8_t code_size,
81
+ const uint8_t ** const stack_base_out,
82
+ const uint8_t ** const stack_pos_out);
83
+
84
+ /**
85
+ * Fill the LZW stack with decompressed data
86
+ *
87
+ * Ensure anything on the stack is used before calling this, as anything
88
+ * on the stack before this call will be trampled.
89
+ *
90
+ * Caller does not own `stack_pos_out`.
91
+ *
92
+ * \param[in] ctx LZW reading context, updated.
93
+ * \param[out] stack_pos_out Returns current stack position.
94
+ * Use with `stack_base_out` value from previous
95
+ * lzw_decode_init() call.
96
+ * There are `stack_pos_out - stack_base_out`
97
+ * current stack entries.
98
+ * \return LZW_OK on success, or appropriate error code otherwise.
99
+ */
100
+ lzw_result lzw_decode(
101
+ struct lzw_ctx *ctx,
102
+ const uint8_t ** const stack_pos_out);
103
+
104
+
105
+ #endif