LiteRGSS 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/LiteRGSS/Bitmap.cpp +316 -0
- data/ext/LiteRGSS/Bitmap.h +24 -0
- data/ext/LiteRGSS/BlendMode.cpp +202 -0
- data/ext/LiteRGSS/BlendMode.h +20 -0
- data/ext/LiteRGSS/CBitmap_Element.cpp +50 -0
- data/ext/LiteRGSS/CBitmap_Element.h +17 -0
- data/ext/LiteRGSS/CDrawable_Element.cpp +38 -0
- data/ext/LiteRGSS/CDrawable_Element.h +30 -0
- data/ext/LiteRGSS/CRect_Element.h +15 -0
- data/ext/LiteRGSS/CShaderSprite_Element.cpp +17 -0
- data/ext/LiteRGSS/CShaderSprite_Element.h +17 -0
- data/ext/LiteRGSS/CSprite_Element.cpp +15 -0
- data/ext/LiteRGSS/CSprite_Element.h +36 -0
- data/ext/LiteRGSS/CText_Element.cpp +12 -0
- data/ext/LiteRGSS/CText_Element.h +29 -0
- data/ext/LiteRGSS/CTone_Element.h +17 -0
- data/ext/LiteRGSS/CViewport_Element.cpp +224 -0
- data/ext/LiteRGSS/CViewport_Element.h +57 -0
- data/ext/LiteRGSS/Color.cpp +200 -0
- data/ext/LiteRGSS/Color.h +22 -0
- data/ext/LiteRGSS/Fonts.cpp +126 -0
- data/ext/LiteRGSS/Fonts.h +20 -0
- data/ext/LiteRGSS/Graphics.cpp +314 -0
- data/ext/LiteRGSS/Graphics.h +31 -0
- data/ext/LiteRGSS/Graphics.local.cpp +365 -0
- data/ext/LiteRGSS/Graphics.local.h +37 -0
- data/ext/LiteRGSS/Image.cpp +460 -0
- data/ext/LiteRGSS/Image.h +32 -0
- data/ext/LiteRGSS/Input.cpp +664 -0
- data/ext/LiteRGSS/Input.h +38 -0
- data/ext/LiteRGSS/LiteRGSS.cpp +34 -0
- data/ext/LiteRGSS/LiteRGSS.h +113 -0
- data/ext/LiteRGSS/Rect.cpp +324 -0
- data/ext/LiteRGSS/Rect.h +24 -0
- data/ext/LiteRGSS/Shader.cpp +279 -0
- data/ext/LiteRGSS/Shader.h +13 -0
- data/ext/LiteRGSS/ShaderSprite.cpp +78 -0
- data/ext/LiteRGSS/ShaderSprite.h +8 -0
- data/ext/LiteRGSS/Sprite.cpp +495 -0
- data/ext/LiteRGSS/Sprite.h +43 -0
- data/ext/LiteRGSS/Table.cpp +228 -0
- data/ext/LiteRGSS/Table.h +29 -0
- data/ext/LiteRGSS/Table32.cpp +228 -0
- data/ext/LiteRGSS/Table32.h +29 -0
- data/ext/LiteRGSS/Text.cpp +574 -0
- data/ext/LiteRGSS/Text.h +52 -0
- data/ext/LiteRGSS/Texture.hpp +735 -0
- data/ext/LiteRGSS/Tone.cpp +228 -0
- data/ext/LiteRGSS/Tone.h +22 -0
- data/ext/LiteRGSS/Viewport.cpp +491 -0
- data/ext/LiteRGSS/Viewport.h +33 -0
- data/ext/LiteRGSS/Yuki.cpp +29 -0
- data/ext/LiteRGSS/Yuki.h +8 -0
- data/ext/LiteRGSS/Yuki_Gif.cpp +218 -0
- data/ext/LiteRGSS/Yuki_Gif.h +25 -0
- data/ext/LiteRGSS/extconf.rb +8 -0
- data/ext/LiteRGSS/libnsgif.c +1169 -0
- data/ext/LiteRGSS/libnsgif.h +183 -0
- data/ext/LiteRGSS/libnsgif.hpp +184 -0
- data/ext/LiteRGSS/lodepng.cpp +6245 -0
- data/ext/LiteRGSS/lodepng.h +1769 -0
- data/ext/LiteRGSS/lzw.c +377 -0
- data/ext/LiteRGSS/lzw.h +105 -0
- data/ext/LiteRGSS/sf_Text2.cpp +690 -0
- data/ext/LiteRGSS/sf_Text2.hpp +549 -0
- data/ext/LiteRGSS/utils/log.h +21 -0
- metadata +112 -0
data/ext/LiteRGSS/lzw.c
ADDED
@@ -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
|
+
}
|
data/ext/LiteRGSS/lzw.h
ADDED
@@ -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
|