Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / core / src / fxcodec / lgif / fx_gif.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "fx_gif.h"\r
8 void CGifLZWDecoder::Input(FX_LPBYTE src_buf, FX_DWORD src_size)\r
9 {\r
10     next_in = src_buf;\r
11     avail_in = src_size;\r
12 }\r
13 FX_DWORD CGifLZWDecoder::GetAvailInput()\r
14 {\r
15     return avail_in;\r
16 }\r
17 void CGifLZWDecoder::InitTable(uint8_t code_len)\r
18 {\r
19     code_size = code_len;\r
20     code_clear = 1 << code_size;\r
21     code_end = code_clear + 1;\r
22     bits_left = 0;\r
23     code_store = 0;\r
24     next_in = NULL;\r
25     avail_in = 0;\r
26     stack_size = 0;\r
27     code_first = 0;\r
28     ClearTable();\r
29 }\r
30 void CGifLZWDecoder::ClearTable()\r
31 {\r
32     code_size_cur = code_size + 1;\r
33     code_next = code_end + 1;\r
34     code_old = (FX_WORD) - 1;\r
35     FXSYS_memset32(code_table, 0, sizeof(tag_Table)*GIF_MAX_LZW_CODE);\r
36     FXSYS_memset32(stack, 0, GIF_MAX_LZW_CODE);\r
37     for (FX_WORD i = 0; i < code_clear; i++) {\r
38         code_table[i].suffix = (uint8_t)i;\r
39     }\r
40 }\r
41 void CGifLZWDecoder::DecodeString(FX_WORD code)\r
42 {\r
43     stack_size = 0;\r
44     while (TRUE) {\r
45         ASSERT(code <= code_next);\r
46         if(code < code_clear || code > code_next) {\r
47             break;\r
48         }\r
49         stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = code_table[code].suffix;\r
50         code = code_table[code].prefix;\r
51     }\r
52     stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = (uint8_t)code;\r
53     code_first = (uint8_t)code;\r
54 }\r
55 void CGifLZWDecoder::AddCode(FX_WORD prefix_code, uint8_t append_char)\r
56 {\r
57     if(code_next == GIF_MAX_LZW_CODE) {\r
58         return;\r
59     }\r
60     code_table[code_next].prefix = prefix_code;\r
61     code_table[code_next].suffix = append_char;\r
62     if(++code_next < GIF_MAX_LZW_CODE) {\r
63         if(code_next >> code_size_cur) {\r
64             code_size_cur++;\r
65         }\r
66     }\r
67 }\r
68 int32_t CGifLZWDecoder::Decode(FX_LPBYTE des_buf, FX_DWORD& des_size)\r
69 {\r
70     if(des_size == 0) {\r
71         return 3;\r
72     }\r
73     FX_DWORD i = 0;\r
74     if(stack_size != 0) {\r
75         if(des_size < stack_size) {\r
76             FXSYS_memcpy32(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], des_size);\r
77             stack_size -= (FX_WORD)des_size;\r
78             return 3;\r
79         }\r
80         FXSYS_memcpy32(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size);\r
81         des_buf += stack_size;\r
82         i += stack_size;\r
83         stack_size = 0;\r
84     }\r
85     FX_WORD code = 0;\r
86     while(i <= des_size && (avail_in > 0 || bits_left >= code_size_cur)) {\r
87         if(code_size_cur > 12) {\r
88             if(err_msg_ptr)     {\r
89                 FXSYS_strncpy(err_msg_ptr, "Code Length Out Of Range", GIF_MAX_ERROR_SIZE - 1);\r
90             }\r
91             return 0;\r
92         }\r
93         if (avail_in > 0) {\r
94             code_store |= (*next_in++) << bits_left;\r
95             avail_in--;\r
96             bits_left += 8;\r
97         }\r
98         while (bits_left >= code_size_cur) {\r
99             code = (FX_WORD)code_store & ((1 << code_size_cur) - 1);\r
100             code_store >>= code_size_cur;\r
101             bits_left -= code_size_cur;\r
102             if(code == code_clear) {\r
103                 ClearTable();\r
104                 continue;\r
105             } else if (code == code_end) {\r
106                 des_size = i;\r
107                 return 1;\r
108             } else {\r
109                 if(code_old != (FX_WORD) - 1) {\r
110                     if(code_next < GIF_MAX_LZW_CODE) {\r
111                         if(code == code_next) {\r
112                             AddCode(code_old, code_first);\r
113                             DecodeString(code);\r
114                         } else if(code > code_next) {\r
115                             if(err_msg_ptr)     {\r
116                                 FXSYS_strncpy(err_msg_ptr, "Decode Error, Out Of Range", GIF_MAX_ERROR_SIZE - 1);\r
117                             }\r
118                             return 0;\r
119                         } else {\r
120                             DecodeString(code);\r
121                             uint8_t append_char = stack[GIF_MAX_LZW_CODE - stack_size];\r
122                             AddCode(code_old, append_char);\r
123                         }\r
124                     }\r
125                 } else {\r
126                     DecodeString(code);\r
127                 }\r
128                 code_old = code;\r
129                 if(i + stack_size > des_size) {\r
130                     FXSYS_memcpy32(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], des_size - i);\r
131                     stack_size -= (FX_WORD)(des_size - i);\r
132                     return 3;\r
133                 }\r
134                 FXSYS_memcpy32(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size);\r
135                 des_buf += stack_size;\r
136                 i += stack_size;\r
137                 stack_size = 0;\r
138             }\r
139         }\r
140     }\r
141     if(avail_in == 0) {\r
142         des_size = i;\r
143         return 2;\r
144     }\r
145     return 0;\r
146 }\r
147 static FX_BOOL _gif_grow_buf(FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD size)\r
148 {\r
149     if (dst_len < size) {\r
150         FX_DWORD len_org = dst_len;\r
151         while (dst_buf && dst_len < size) {\r
152             dst_len <<= 1;\r
153             dst_buf = FX_Realloc(uint8_t, dst_buf, dst_len);\r
154         }\r
155         if (dst_buf == NULL) {\r
156             dst_len = size;\r
157             dst_buf = FX_Realloc(uint8_t, dst_buf, dst_len);\r
158             if (dst_buf == NULL) {\r
159                 return FALSE;\r
160             }\r
161         }\r
162         FXSYS_memset32(dst_buf + len_org, 0, dst_len - len_org);\r
163         return dst_buf != NULL;\r
164     }\r
165     return TRUE;\r
166 }\r
167 static inline void _gif_cut_index(uint8_t& val, FX_DWORD index, uint8_t index_bit, uint8_t index_bit_use, uint8_t bit_use)\r
168 {\r
169     FX_DWORD cut = ((1 << (index_bit - index_bit_use)) - 1) << index_bit_use;\r
170     val |= ((index & cut) >> index_bit_use) << bit_use;\r
171 }\r
172 static inline uint8_t _gif_cut_buf(FX_LPCBYTE buf, FX_DWORD& offset, uint8_t bit_cut, uint8_t& bit_offset, FX_DWORD& bit_num)\r
173 {\r
174     if (bit_cut != 8) {\r
175         FX_WORD index = 0;\r
176         index |= ((1 << bit_cut) - 1) << (7 - bit_offset);\r
177         uint8_t ret = ((index & buf[offset]) >> (7 - bit_offset));\r
178         bit_offset += bit_cut;\r
179         if (bit_offset >= 8) {\r
180             if (bit_offset > 8) {\r
181                 ret |= ((index & (buf[offset + 1] << 8)) >> 8);\r
182             }\r
183             bit_offset -= 8;\r
184             offset ++;\r
185         }\r
186         bit_num += bit_cut;\r
187         return ret;\r
188     }\r
189     bit_num += bit_cut;\r
190     return buf[offset++];\r
191 }\r
192 CGifLZWEncoder::CGifLZWEncoder()\r
193 {\r
194     FXSYS_memset32(this, 0, sizeof(CGifLZWEncoder));\r
195 }\r
196 CGifLZWEncoder::~CGifLZWEncoder()\r
197 {\r
198 }\r
199 void CGifLZWEncoder::ClearTable()\r
200 {\r
201     index_bit_cur = code_size + 1;\r
202     index_num = code_end + 1;\r
203     table_cur = code_end + 1;\r
204     for (FX_WORD i = 0; i < GIF_MAX_LZW_CODE; i++) {\r
205         code_table[i].prefix = 0;\r
206         code_table[i].suffix = 0;\r
207     }\r
208 }\r
209 void CGifLZWEncoder::Start( uint8_t code_len, FX_LPCBYTE src_buf, FX_LPBYTE& dst_buf, FX_DWORD& offset)\r
210 {\r
211     code_size = code_len + 1;\r
212     src_bit_cut = code_size;\r
213     if (code_len == 0) {\r
214         src_bit_cut = 1;\r
215         code_size = 2;\r
216     }\r
217     code_clear = 1 << code_size;\r
218     code_end = code_clear + 1;\r
219     dst_buf[offset++] = code_size;\r
220     bit_offset = 0;\r
221     ClearTable();\r
222     src_offset = 0;\r
223     src_bit_offset = 0;\r
224     src_bit_num = 0;\r
225     code_table[index_num].prefix = _gif_cut_buf(src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num);\r
226     code_table[index_num].suffix = _gif_cut_buf(src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num);\r
227 }\r
228 void CGifLZWEncoder::WriteBlock(FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset)\r
229 {\r
230     if (!_gif_grow_buf(dst_buf, dst_len, offset + GIF_DATA_BLOCK + 1)) {\r
231         longjmp(jmp, 1);\r
232     }\r
233     dst_buf[offset++] = index_buf_len;\r
234     FXSYS_memcpy32(&dst_buf[offset], index_buf, index_buf_len);\r
235     offset += index_buf_len;\r
236     FXSYS_memset32(index_buf, 0, GIF_DATA_BLOCK);\r
237     index_buf_len = 0;\r
238 }\r
239 void CGifLZWEncoder::EncodeString( FX_DWORD index, FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset )\r
240 {\r
241     uint8_t index_bit_use;\r
242     index_bit_use = 0;\r
243     if (index_buf_len == GIF_DATA_BLOCK) {\r
244         WriteBlock(dst_buf, dst_len, offset);\r
245     }\r
246     _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, bit_offset);\r
247     if (index_bit_cur <= (8 - bit_offset)) {\r
248         bit_offset += index_bit_cur;\r
249     } else if (index_bit_cur <= (16 - bit_offset)) {\r
250         index_bit_use += (8 - bit_offset);\r
251         bit_offset = 0;\r
252         index_buf_len++;\r
253         if (index_buf_len == GIF_DATA_BLOCK) {\r
254             WriteBlock(dst_buf, dst_len, offset);\r
255         }\r
256         _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, bit_offset);\r
257         bit_offset = index_bit_cur - index_bit_use;\r
258     } else {\r
259         index_bit_use += (8 - bit_offset);\r
260         bit_offset = 0;\r
261         index_buf_len++;\r
262         if (index_buf_len == GIF_DATA_BLOCK) {\r
263             WriteBlock(dst_buf, dst_len, offset);\r
264         }\r
265         _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, bit_offset);\r
266         index_bit_use += 8;\r
267         bit_offset = 0;\r
268         index_buf_len++;\r
269         if (index_buf_len == GIF_DATA_BLOCK) {\r
270             WriteBlock(dst_buf, dst_len, offset);\r
271         }\r
272         _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, bit_offset);\r
273         bit_offset = index_bit_cur - index_bit_use;\r
274     }\r
275     if (bit_offset == 8) {\r
276         bit_offset = 0;\r
277         index_buf_len++;\r
278         if (index_buf_len == GIF_DATA_BLOCK) {\r
279             WriteBlock(dst_buf, dst_len, offset);\r
280         }\r
281     }\r
282     if (index == code_end)      {\r
283         index_buf_len++;\r
284         WriteBlock(dst_buf, dst_len, offset);\r
285     }\r
286     if (index_num++ >> index_bit_cur) {\r
287         index_bit_cur++;\r
288     }\r
289 }\r
290 FX_BOOL CGifLZWEncoder::Encode( FX_LPCBYTE src_buf, FX_DWORD src_len, FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset )\r
291 {\r
292     uint8_t             suffix;\r
293     if (setjmp(jmp)) {\r
294         return FALSE;\r
295     }\r
296     while(src_bit_num < src_len) {\r
297         if (!LookUpInTable(src_buf, src_offset, src_bit_offset)) {\r
298             EncodeString(code_table[index_num].prefix, dst_buf, dst_len, offset);\r
299             if (index_num == GIF_MAX_LZW_CODE) {\r
300                 suffix = code_table[index_num - 1].suffix;\r
301                 EncodeString(code_clear, dst_buf, dst_len, offset);\r
302                 ClearTable();\r
303                 code_table[index_num].prefix = suffix;\r
304                 code_table[index_num].suffix = _gif_cut_buf(src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num);\r
305             } else {\r
306                 code_table[index_num].prefix = code_table[index_num - 1].suffix;\r
307                 code_table[index_num].suffix = _gif_cut_buf(src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num);\r
308             }\r
309         }\r
310     }\r
311     src_offset = 0;\r
312     src_bit_offset = 0;\r
313     src_bit_num = 0;\r
314     return TRUE;\r
315 }\r
316 FX_BOOL CGifLZWEncoder::LookUpInTable( FX_LPCBYTE buf, FX_DWORD& offset, uint8_t& bit_offset )\r
317 {\r
318     for (FX_WORD i = table_cur; i < index_num; i++) {\r
319         if (code_table[i].prefix == code_table[index_num].prefix &&\r
320                 code_table[i].suffix == code_table[index_num].suffix) {\r
321             code_table[index_num].prefix = i;\r
322             code_table[index_num].suffix = _gif_cut_buf(buf, offset, src_bit_cut, bit_offset, src_bit_num);\r
323             table_cur = i;\r
324             return TRUE;\r
325         }\r
326     }\r
327     table_cur = code_end + 1;\r
328     return FALSE;\r
329 }\r
330 void CGifLZWEncoder::Finish(FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset)\r
331 {\r
332     EncodeString(code_table[index_num].prefix, dst_buf, dst_len, offset);\r
333     EncodeString(code_end, dst_buf, dst_len, offset);\r
334     bit_offset = 0;\r
335     ClearTable();\r
336 }\r
337 gif_decompress_struct_p _gif_create_decompress()\r
338 {\r
339     gif_decompress_struct_p gif_ptr = (gif_decompress_struct*)FX_Alloc(uint8_t, sizeof(gif_decompress_struct));\r
340     if(gif_ptr == NULL) {\r
341         return NULL;\r
342     }\r
343     FXSYS_memset32(gif_ptr, 0, sizeof(gif_decompress_struct));\r
344     gif_ptr->decode_status = GIF_D_STATUS_SIG;\r
345     gif_ptr->img_ptr_arr_ptr = new CFX_ArrayTemplate<GifImage*>;\r
346 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
347     gif_ptr->cmt_data_ptr = new CFX_ByteString;\r
348 #endif\r
349 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
350     gif_ptr->pt_ptr_arr_ptr = new CFX_ArrayTemplate<GifPlainText*>;\r
351 #endif\r
352     return gif_ptr;\r
353 }\r
354 void _gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr)\r
355 {\r
356     if(gif_ptr_ptr == NULL || *gif_ptr_ptr == NULL) {\r
357         return;\r
358     }\r
359     gif_decompress_struct_p gif_ptr = *gif_ptr_ptr;\r
360     *gif_ptr_ptr = NULL;\r
361     if(gif_ptr->global_pal_ptr != NULL) {\r
362         FX_Free(gif_ptr->global_pal_ptr);\r
363     }\r
364     if(gif_ptr->img_decoder_ptr != NULL) {\r
365         delete gif_ptr->img_decoder_ptr;\r
366     }\r
367     if(gif_ptr->img_ptr_arr_ptr != NULL) {\r
368         int32_t size_img_arr = gif_ptr->img_ptr_arr_ptr->GetSize();\r
369         for (int32_t i = 0; i < size_img_arr; i++) {\r
370             GifImage* p = gif_ptr->img_ptr_arr_ptr->GetAt(i);\r
371             if(p->image_info_ptr != NULL) {\r
372                 FX_Free(p->image_info_ptr);\r
373             }\r
374             if(p->image_gce_ptr != NULL) {\r
375                 FX_Free(p->image_gce_ptr);\r
376             }\r
377             if(p->image_row_buf != NULL) {\r
378                 FX_Free(p->image_row_buf);\r
379             }\r
380             if(p->local_pal_ptr != NULL && p->local_pal_ptr != gif_ptr->global_pal_ptr) {\r
381                 FX_Free(p->local_pal_ptr);\r
382             }\r
383             FX_Free(p);\r
384         }\r
385         gif_ptr->img_ptr_arr_ptr->RemoveAll();\r
386         delete gif_ptr->img_ptr_arr_ptr;\r
387     }\r
388 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
389     if(gif_ptr->app_data != NULL) {\r
390         FX_Free(gif_ptr->app_data);\r
391     }\r
392 #endif\r
393 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
394     if(gif_ptr->cmt_data_ptr != NULL) {\r
395         delete gif_ptr->cmt_data_ptr;\r
396     }\r
397 #endif\r
398 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
399     if(gif_ptr->gce_ptr != NULL) {\r
400         FX_Free(gif_ptr->gce_ptr);\r
401     }\r
402 #endif\r
403 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
404     if(gif_ptr->pt_ptr_arr_ptr != NULL) {\r
405         int32_t size_pt_arr = gif_ptr->pt_ptr_arr_ptr->GetSize();\r
406         for (int32_t i = 0; i < size_pt_arr; i++) {\r
407             GifPlainText* p = gif_ptr->pt_ptr_arr_ptr->GetAt(i);\r
408             if(p->gce_ptr != NULL) {\r
409                 FX_Free(p->gce_ptr);\r
410             }\r
411             if(p->pte_ptr != NULL) {\r
412                 FX_Free(p->pte_ptr);\r
413             }\r
414             if(p->string_ptr != NULL) {\r
415                 delete p->string_ptr;\r
416             }\r
417         }\r
418         gif_ptr->pt_ptr_arr_ptr->RemoveAll();\r
419         delete gif_ptr->pt_ptr_arr_ptr;\r
420     }\r
421 #endif\r
422     FX_Free(gif_ptr);\r
423 }\r
424 gif_compress_struct_p _gif_create_compress()\r
425 {\r
426     gif_compress_struct_p gif_ptr = (gif_compress_struct*)FX_Alloc(uint8_t, sizeof(gif_compress_struct));\r
427     if (gif_ptr == NULL) {\r
428         return NULL;\r
429     }\r
430     FXSYS_memset32(gif_ptr, 0, sizeof(gif_compress_struct));\r
431     gif_ptr->img_encoder_ptr = new CGifLZWEncoder;\r
432     gif_ptr->header_ptr = (GifHeader*)FX_Alloc(uint8_t, sizeof(GifHeader));\r
433     if (gif_ptr->header_ptr == NULL) {\r
434         delete(gif_ptr->img_encoder_ptr);\r
435         FX_Free(gif_ptr);\r
436         return NULL;\r
437     }\r
438     FXSYS_memcpy32(gif_ptr->header_ptr->signature, GIF_SIGNATURE, 3);\r
439     FXSYS_memcpy32(gif_ptr->header_ptr->version, "89a", 3);\r
440     gif_ptr->lsd_ptr = (GifLSD*)FX_Alloc(uint8_t, sizeof(GifLSD));\r
441     if (gif_ptr->lsd_ptr == NULL) {\r
442         FX_Free(gif_ptr->header_ptr);\r
443         delete(gif_ptr->img_encoder_ptr);\r
444         FX_Free(gif_ptr);\r
445         return NULL;\r
446     }\r
447     FXSYS_memset32(gif_ptr->lsd_ptr, 0, sizeof(GifLSD));\r
448     gif_ptr->image_info_ptr = (GifImageInfo*)FX_Alloc(uint8_t, sizeof(GifImageInfo));\r
449     if (gif_ptr->image_info_ptr == NULL) {\r
450         FX_Free(gif_ptr->lsd_ptr);\r
451         FX_Free(gif_ptr->header_ptr);\r
452         delete(gif_ptr->img_encoder_ptr);\r
453         FX_Free(gif_ptr);\r
454         return NULL;\r
455     }\r
456     FXSYS_memset32(gif_ptr->image_info_ptr, 0, sizeof(GifImageInfo));\r
457 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
458     FXSYS_memcpy32(gif_ptr->app_identify, "netscape", 8);\r
459     FXSYS_memcpy32(gif_ptr->app_authentication, "2.0", 3);\r
460 #endif\r
461 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
462     gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(uint8_t, sizeof(GifGCE));\r
463     if (gif_ptr->gce_ptr == NULL) {\r
464         FX_Free(gif_ptr->image_info_ptr);\r
465         FX_Free(gif_ptr->lsd_ptr);\r
466         FX_Free(gif_ptr->header_ptr);\r
467         delete(gif_ptr->img_encoder_ptr);\r
468         FX_Free(gif_ptr);\r
469         return NULL;\r
470     }\r
471 #endif\r
472 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
473     gif_ptr->pte_ptr = (GifPTE*)FX_Alloc(uint8_t, sizeof(GifPTE));\r
474     if (gif_ptr->pte_ptr == NULL) {\r
475         FX_Free(gif_ptr->gce_ptr);\r
476         FX_Free(gif_ptr->image_info_ptr);\r
477         FX_Free(gif_ptr->lsd_ptr);\r
478         FX_Free(gif_ptr->header_ptr);\r
479         delete(gif_ptr->img_encoder_ptr);\r
480         FX_Free(gif_ptr);\r
481         return NULL;\r
482     }\r
483     FXSYS_memset32(gif_ptr->pte_ptr, 0, sizeof(GifPTE));\r
484     gif_ptr->pte_ptr->block_size = 12;\r
485 #endif\r
486     return gif_ptr;\r
487 }\r
488 void _gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr)\r
489 {\r
490     if(gif_ptr_ptr == NULL || *gif_ptr_ptr == NULL) {\r
491         return;\r
492     }\r
493     gif_compress_struct_p gif_ptr = *gif_ptr_ptr;\r
494     *gif_ptr_ptr = NULL;\r
495     if(gif_ptr->header_ptr != NULL)     {\r
496         FX_Free(gif_ptr->header_ptr);\r
497     }\r
498     if(gif_ptr->lsd_ptr != NULL)        {\r
499         FX_Free(gif_ptr->lsd_ptr);\r
500     }\r
501     if(gif_ptr->global_pal != NULL)     {\r
502         FX_Free(gif_ptr->global_pal);\r
503     }\r
504     if(gif_ptr->image_info_ptr != NULL) {\r
505         FX_Free(gif_ptr->image_info_ptr);\r
506     }\r
507     if(gif_ptr->local_pal != NULL)      {\r
508         FX_Free(gif_ptr->local_pal);\r
509     }\r
510     if(gif_ptr->img_encoder_ptr != NULL) {\r
511         delete gif_ptr->img_encoder_ptr;\r
512     }\r
513 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
514     if(gif_ptr->app_data != NULL) {\r
515         FX_Free(gif_ptr->app_data);\r
516     }\r
517 #endif\r
518 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
519     if(gif_ptr->gce_ptr != NULL) {\r
520         FX_Free(gif_ptr->gce_ptr);\r
521     }\r
522 #endif\r
523 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
524     if(gif_ptr->cmt_data_ptr != NULL) {\r
525         FX_Free(gif_ptr->cmt_data_ptr);\r
526     }\r
527 #endif\r
528 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
529     if(gif_ptr->pte_ptr != NULL) {\r
530         FX_Free(gif_ptr->pte_ptr);\r
531     }\r
532 #endif\r
533     FX_Free(gif_ptr);\r
534 }\r
535 void _gif_error(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg)\r
536 {\r
537     if(gif_ptr != NULL && gif_ptr->_gif_error_fn != NULL) {\r
538         gif_ptr->_gif_error_fn(gif_ptr, err_msg);\r
539     }\r
540 }\r
541 void _gif_warn(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg) {}\r
542 int32_t _gif_read_header(gif_decompress_struct_p gif_ptr)\r
543 {\r
544     if(gif_ptr == NULL) {\r
545         return 0;\r
546     }\r
547     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
548     ASSERT(sizeof(GifHeader) == 6);\r
549     GifHeader* gif_header_ptr = NULL;\r
550     if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_header_ptr, 6) == NULL) {\r
551         return 2;\r
552     }\r
553     if(FXSYS_strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 ||\r
554             gif_header_ptr->version[0] != '8' ||\r
555             gif_header_ptr->version[2] != 'a') {\r
556         _gif_error(gif_ptr, "Not A Gif Image");\r
557         return 0;\r
558     }\r
559     ASSERT(sizeof(GifLSD) == 7);\r
560     GifLSD* gif_lsd_ptr = NULL;\r
561     if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_lsd_ptr, 7) == NULL) {\r
562         gif_ptr->skip_size = skip_size_org;\r
563         return 2;\r
564     }\r
565     if(((GifGF*)&gif_lsd_ptr->global_flag)->global_pal) {\r
566         gif_ptr->global_pal_num = 2 << ((GifGF*)&gif_lsd_ptr->global_flag)->pal_bits;\r
567         ASSERT(sizeof(GifPalette) == 3);\r
568         int32_t global_pal_size = gif_ptr->global_pal_num * 3;\r
569         FX_LPBYTE global_pal_ptr = NULL;\r
570         if (_gif_read_data(gif_ptr, &global_pal_ptr, global_pal_size) == NULL) {\r
571             gif_ptr->skip_size = skip_size_org;\r
572             return 2;\r
573         }\r
574         gif_ptr->global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag;\r
575         gif_ptr->global_color_resolution = ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution;\r
576         if(gif_ptr->global_pal_ptr != NULL) {\r
577             FX_Free(gif_ptr->global_pal_ptr);\r
578         }\r
579         gif_ptr->global_pal_ptr = NULL;\r
580         gif_ptr->global_pal_ptr = (GifPalette*)FX_Alloc(uint8_t, global_pal_size);\r
581         GIF_PTR_NOT_NULL(gif_ptr->global_pal_ptr, gif_ptr);\r
582         FXSYS_memcpy32(gif_ptr->global_pal_ptr, global_pal_ptr, global_pal_size);\r
583     }\r
584     gif_ptr->width = (int)_GetWord_LSBFirst((FX_LPBYTE)&gif_lsd_ptr->width);\r
585     gif_ptr->height = (int)_GetWord_LSBFirst((FX_LPBYTE)&gif_lsd_ptr->height);\r
586     gif_ptr->bc_index = gif_lsd_ptr->bc_index;\r
587     gif_ptr->pixel_aspect = gif_lsd_ptr->pixel_aspect;\r
588     return 1;\r
589 }\r
590 int32_t _gif_get_frame(gif_decompress_struct_p gif_ptr)\r
591 {\r
592     if(gif_ptr == NULL) {\r
593         return 0;\r
594     }\r
595     int32_t ret = 1;\r
596     while (TRUE) {\r
597         switch(gif_ptr->decode_status) {\r
598             case GIF_D_STATUS_TAIL:\r
599                 return 1;\r
600             case GIF_D_STATUS_SIG: {\r
601                     FX_LPBYTE sig_ptr = NULL;\r
602                     if(_gif_read_data(gif_ptr, &sig_ptr, 1) == NULL) {\r
603                         return 2;\r
604                     }\r
605                     switch(*sig_ptr) {\r
606                         case GIF_SIG_EXTENSION:\r
607                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT);\r
608                             continue;\r
609                         case GIF_SIG_IMAGE:\r
610                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_INFO);\r
611                             continue;\r
612                         case GIF_SIG_TRAILER:\r
613                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
614                             return 1;\r
615                         default:\r
616                             if (gif_ptr->avail_in) {\r
617                                 _gif_warn(gif_ptr, "The Gif File has non_standard Tag!");\r
618                                 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);\r
619                                 continue;\r
620                             }\r
621                             _gif_warn(gif_ptr, "The Gif File Doesn't have Trailer Tag!");\r
622                             return 1;\r
623                     }\r
624                 }\r
625             case GIF_D_STATUS_EXT: {\r
626                     FX_LPBYTE ext_ptr = NULL;\r
627                     if(_gif_read_data(gif_ptr, &ext_ptr, 1) == NULL) {\r
628                         return 2;\r
629                     }\r
630                     switch(*ext_ptr) {\r
631 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
632                         case GIF_BLOCK_AE:\r
633                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_AE);\r
634                             continue;\r
635 #endif\r
636 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
637                         case GIF_BLOCK_CE:\r
638                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_CE);\r
639                             continue;\r
640 #endif\r
641 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
642                         case GIF_BLOCK_GCE:\r
643                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_GCE);\r
644                             continue;\r
645 #endif\r
646 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
647                         case GIF_BLOCK_PTE:\r
648                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_PTE);\r
649                             continue;\r
650 #endif\r
651                         default: {\r
652                                 int32_t status = GIF_D_STATUS_EXT_UNE;\r
653 #ifndef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
654                                 if(*ext_ptr == GIF_BLOCK_PTE) {\r
655                                     status = GIF_D_STATUS_EXT_PTE;\r
656                                 }\r
657 #endif\r
658                                 _gif_save_decoding_status(gif_ptr, status);\r
659                                 continue;\r
660                             }\r
661                     }\r
662                 }\r
663             case GIF_D_STATUS_IMG_INFO: {\r
664                     ret = _gif_decode_image_info(gif_ptr);\r
665                     if(ret != 1) {\r
666                         return ret;\r
667                     }\r
668                     continue;\r
669                 }\r
670             case GIF_D_STATUS_IMG_DATA: {\r
671                     FX_LPBYTE data_size_ptr = NULL;\r
672                     FX_LPBYTE data_ptr = NULL;\r
673                     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
674                     if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
675                         return 2;\r
676                     }\r
677                     while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
678                         if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {\r
679                             gif_ptr->skip_size = skip_size_org;\r
680                             return 2;\r
681                         }\r
682                         _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
683                         skip_size_org = gif_ptr->skip_size;\r
684                         if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
685                             return 2;\r
686                         }\r
687                     }\r
688                     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);\r
689                     continue;\r
690                 }\r
691             default: {\r
692                     ret = _gif_decode_extension(gif_ptr);\r
693                     if(ret != 1) {\r
694                         return ret;\r
695                     }\r
696                     continue;\r
697                 }\r
698         }\r
699     }\r
700     return 1;\r
701 }\r
702 void _gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr, GifGCE** gce_ptr_ptr)\r
703 {\r
704     *gce_ptr_ptr = NULL;\r
705 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
706     if(gif_ptr->gce_ptr != NULL && gce_ptr_ptr != NULL) {\r
707         *gce_ptr_ptr = gif_ptr->gce_ptr;\r
708         gif_ptr->gce_ptr = NULL;\r
709     }\r
710 #endif\r
711 }\r
712 int32_t _gif_decode_extension(gif_decompress_struct_p gif_ptr)\r
713 {\r
714     FX_LPBYTE data_size_ptr = NULL;\r
715     FX_LPBYTE data_ptr = NULL;\r
716     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
717     switch(gif_ptr->decode_status) {\r
718 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
719         case GIF_D_STATUS_EXT_AE: {\r
720                 ASSERT(sizeof(GifAE) == 12);\r
721                 GifAE* gif_ae_ptr = NULL;\r
722                 if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_ae_ptr, 12) == NULL) {\r
723                     return 2;\r
724                 }\r
725                 CFX_ByteString gif_ae_data_str;\r
726                 if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
727                     gif_ptr->skip_size = skip_size_org;\r
728                     return 2;\r
729                 }\r
730                 while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
731                     uint8_t data_size = *data_size_ptr;\r
732                     if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||\r
733                             _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
734                         gif_ptr->skip_size = skip_size_org;\r
735                         return 2;\r
736                     }\r
737                     gif_ae_data_str += CFX_ByteString((FX_LPCBYTE)data_ptr, data_size);\r
738                 }\r
739                 FXSYS_memcpy32(gif_ptr->app_identify, gif_ae_ptr->app_identify, 8);\r
740                 FXSYS_memcpy32(gif_ptr->app_authentication, gif_ae_ptr->app_authentication, 3);\r
741                 gif_ptr->app_data_size = gif_ae_data_str.GetLength();\r
742                 if(gif_ptr->app_data != NULL) {\r
743                     FX_Free(gif_ptr->app_data);\r
744                     gif_ptr->app_data = NULL;\r
745                 }\r
746                 gif_ptr->app_data = FX_Alloc(uint8_t, gif_ptr->app_data_size);\r
747                 GIF_PTR_NOT_NULL(gif_ptr->app_data, gif_ptr);\r
748                 FXSYS_memcpy32(gif_ptr->app_data, FX_LPCBYTE(gif_ae_data_str), gif_ptr->app_data_size);\r
749             }\r
750             break;\r
751 #endif\r
752 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
753         case GIF_D_STATUS_EXT_CE: {\r
754                 if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
755                     gif_ptr->skip_size = skip_size_org;\r
756                     return 2;\r
757                 }\r
758                 gif_ptr->cmt_data_ptr->Empty();\r
759                 while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
760                     uint8_t data_size = *data_size_ptr;\r
761                     if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||\r
762                             _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
763                         gif_ptr->skip_size = skip_size_org;\r
764                         return 2;\r
765                     }\r
766                     *(gif_ptr->cmt_data_ptr) += CFX_ByteString((FX_LPCSTR)data_ptr, data_size);\r
767                 }\r
768             }\r
769             break;\r
770 #endif\r
771 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
772         case GIF_D_STATUS_EXT_PTE: {\r
773                 ASSERT(sizeof(GifPTE) == 13);\r
774                 GifPTE* gif_pte_ptr = NULL;\r
775                 if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_pte_ptr, 13) == NULL) {\r
776                     return 2;\r
777                 }\r
778                 GifPlainText* gif_pt_ptr = FX_Alloc(GifPlainText, 1);\r
779                 GIF_PTR_NOT_NULL(gif_pt_ptr, gif_ptr);\r
780                 FXSYS_memset32(gif_pt_ptr, 0, sizeof(GifPlainText));\r
781                 _gif_takeover_gce_ptr(gif_ptr, &gif_pt_ptr->gce_ptr);\r
782                 gif_pt_ptr->pte_ptr = (GifPTE*)FX_Alloc(uint8_t, sizeof(GifPTE));\r
783                 GIF_PTR_NOT_NULL(gif_pt_ptr->pte_ptr, gif_ptr);\r
784                 gif_pt_ptr->string_ptr = new CFX_ByteString;\r
785                 GIF_PTR_NOT_NULL(gif_pt_ptr->string_ptr, gif_ptr);\r
786                 gif_pt_ptr->pte_ptr->block_size = gif_pte_ptr->block_size;\r
787                 gif_pt_ptr->pte_ptr->grid_left = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_left);\r
788                 gif_pt_ptr->pte_ptr->grid_top = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_top);\r
789                 gif_pt_ptr->pte_ptr->grid_width = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_width);\r
790                 gif_pt_ptr->pte_ptr->grid_height = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_height);\r
791                 gif_pt_ptr->pte_ptr->char_width = gif_pte_ptr->char_width;\r
792                 gif_pt_ptr->pte_ptr->char_height = gif_pte_ptr->char_height;\r
793                 gif_pt_ptr->pte_ptr->fc_index = gif_pte_ptr->fc_index;\r
794                 gif_pt_ptr->pte_ptr->bc_index = gif_pte_ptr->bc_index;\r
795                 if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
796                     gif_ptr->skip_size = skip_size_org;\r
797                     if(gif_pt_ptr != NULL) {\r
798                         if(gif_pt_ptr->gce_ptr != NULL) {\r
799                             FX_Free(gif_pt_ptr->gce_ptr);\r
800                         }\r
801                         if(gif_pt_ptr->pte_ptr != NULL) {\r
802                             FX_Free(gif_pt_ptr->pte_ptr);\r
803                         }\r
804                         if(gif_pt_ptr->string_ptr != NULL) {\r
805                             delete gif_pt_ptr->string_ptr;\r
806                         }\r
807                         FX_Free(gif_pt_ptr);\r
808                     }\r
809                     return 2;\r
810                 }\r
811                 while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
812                     uint8_t data_size = *data_size_ptr;\r
813                     if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||\r
814                             _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
815                         gif_ptr->skip_size = skip_size_org;\r
816                         if(gif_pt_ptr != NULL) {\r
817                             if(gif_pt_ptr->gce_ptr != NULL) {\r
818                                 FX_Free(gif_pt_ptr->gce_ptr);\r
819                             }\r
820                             if(gif_pt_ptr->pte_ptr != NULL) {\r
821                                 FX_Free(gif_pt_ptr->pte_ptr);\r
822                             }\r
823                             if(gif_pt_ptr->string_ptr != NULL) {\r
824                                 delete gif_pt_ptr->string_ptr;\r
825                             }\r
826                             FX_Free(gif_pt_ptr);\r
827                         }\r
828                         return 2;\r
829                     }\r
830                     *(gif_pt_ptr->string_ptr) += CFX_ByteString((FX_LPCSTR)data_ptr, data_size);\r
831                 }\r
832                 gif_ptr->pt_ptr_arr_ptr->Add(gif_pt_ptr);\r
833             }\r
834             break;\r
835 #endif\r
836 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
837         case GIF_D_STATUS_EXT_GCE: {\r
838                 ASSERT(sizeof(GifGCE) == 5);\r
839                 GifGCE* gif_gce_ptr = NULL;\r
840                 if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_gce_ptr, 6) == NULL) {\r
841                     return 2;\r
842                 }\r
843                 if(gif_ptr->gce_ptr == NULL) {\r
844                     gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(uint8_t, sizeof(GifGCE));\r
845                     GIF_PTR_NOT_NULL(gif_ptr->gce_ptr, gif_ptr);\r
846                 }\r
847                 gif_ptr->gce_ptr->block_size = gif_gce_ptr->block_size;\r
848                 gif_ptr->gce_ptr->gce_flag = gif_gce_ptr->gce_flag;\r
849                 gif_ptr->gce_ptr->delay_time = _GetWord_LSBFirst((FX_LPBYTE)&gif_gce_ptr->delay_time);\r
850                 gif_ptr->gce_ptr->trans_index = gif_gce_ptr->trans_index;\r
851             }\r
852             break;\r
853 #endif\r
854         default: {\r
855 #ifndef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
856                 if(gif_ptr->decode_status == GIF_D_STATUS_EXT_PTE) {\r
857 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
858                     if(gif_ptr->gce_ptr != NULL) {\r
859                         FX_Free(gif_ptr->gce_ptr);\r
860                         gif_ptr->gce_ptr = NULL;\r
861                     }\r
862 #endif\r
863                 }\r
864 #endif\r
865                 if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
866                     return 2;\r
867                 }\r
868                 while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
869                     if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||\r
870                             _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL ) {\r
871                         gif_ptr->skip_size = skip_size_org;\r
872                         return 2;\r
873                     }\r
874                 }\r
875             }\r
876     }\r
877     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);\r
878     return 1;\r
879 }\r
880 int32_t _gif_decode_image_info(gif_decompress_struct_p gif_ptr)\r
881 {\r
882     if(gif_ptr->width == 0 || gif_ptr->height == 0) {\r
883         _gif_error(gif_ptr, "No Image Header Info");\r
884         return 0;\r
885     }\r
886     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
887     ASSERT(sizeof(GifImageInfo) == 9);\r
888     GifImageInfo* gif_img_info_ptr = NULL;\r
889     if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_img_info_ptr, 9) == NULL) {\r
890         return 2;\r
891     }\r
892     GifImage* gif_image_ptr = (GifImage*)FX_Alloc(uint8_t, sizeof(GifImage));\r
893     GIF_PTR_NOT_NULL(gif_image_ptr, gif_ptr);\r
894     FXSYS_memset32(gif_image_ptr, 0, sizeof(GifImage));\r
895     gif_image_ptr->image_info_ptr = (GifImageInfo*)FX_Alloc(uint8_t, sizeof(GifImageInfo));\r
896     GIF_PTR_NOT_NULL(gif_image_ptr->image_info_ptr, gif_ptr);\r
897     gif_image_ptr->image_info_ptr->left = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->left);\r
898     gif_image_ptr->image_info_ptr->top = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->top);\r
899     gif_image_ptr->image_info_ptr->width = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->width);\r
900     gif_image_ptr->image_info_ptr->height = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->height);\r
901     gif_image_ptr->image_info_ptr->local_flag = gif_img_info_ptr->local_flag;\r
902     if(gif_image_ptr->image_info_ptr->left + gif_image_ptr->image_info_ptr->width > gif_ptr->width ||\r
903             gif_image_ptr->image_info_ptr->top + gif_image_ptr->image_info_ptr->height > gif_ptr->height) {\r
904         if(gif_image_ptr->image_info_ptr != NULL) {\r
905             FX_Free(gif_image_ptr->image_info_ptr);\r
906         }\r
907         if(gif_image_ptr->image_row_buf != NULL) {\r
908             FX_Free(gif_image_ptr->image_row_buf);\r
909         }\r
910         FX_Free(gif_image_ptr);\r
911         _gif_error(gif_ptr, "Image Data Out Of LSD, The File May Be Corrupt");\r
912         return 0;\r
913     }\r
914     GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;\r
915     if(gif_img_info_lf_ptr->local_pal) {\r
916         ASSERT(sizeof(GifPalette) == 3);\r
917         int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3;\r
918         FX_LPBYTE loc_pal_ptr = NULL;\r
919         if(_gif_read_data(gif_ptr, &loc_pal_ptr, loc_pal_size) == NULL) {\r
920             gif_ptr->skip_size = skip_size_org;\r
921             if(gif_image_ptr->image_info_ptr != NULL) {\r
922                 FX_Free(gif_image_ptr->image_info_ptr);\r
923             }\r
924             if(gif_image_ptr->image_row_buf != NULL) {\r
925                 FX_Free(gif_image_ptr->image_row_buf);\r
926             }\r
927             FX_Free(gif_image_ptr);\r
928             return 2;\r
929         }\r
930         gif_image_ptr->local_pal_ptr = (GifPalette*)gif_ptr->_gif_ask_buf_for_pal_fn(gif_ptr, loc_pal_size);\r
931         if(gif_image_ptr->local_pal_ptr != NULL) {\r
932             FXSYS_memcpy32((FX_LPBYTE)gif_image_ptr->local_pal_ptr, loc_pal_ptr, loc_pal_size);\r
933         }\r
934     }\r
935     FX_LPBYTE code_size_ptr = NULL;\r
936     if(_gif_read_data(gif_ptr, &code_size_ptr, 1) == NULL) {\r
937         gif_ptr->skip_size = skip_size_org;\r
938         if(gif_image_ptr->image_info_ptr != NULL) {\r
939             FX_Free(gif_image_ptr->image_info_ptr);\r
940         }\r
941         if(gif_image_ptr->local_pal_ptr != NULL) {\r
942             FX_Free(gif_image_ptr->local_pal_ptr);\r
943         }\r
944         if(gif_image_ptr->image_row_buf != NULL) {\r
945             FX_Free(gif_image_ptr->image_row_buf);\r
946         }\r
947         FX_Free(gif_image_ptr);\r
948         return 2;\r
949     }\r
950     gif_image_ptr->image_code_size = *code_size_ptr;\r
951     gif_ptr->_gif_record_current_position_fn(gif_ptr, &gif_image_ptr->image_data_pos);\r
952     gif_image_ptr->image_data_pos += gif_ptr->skip_size;\r
953     _gif_takeover_gce_ptr(gif_ptr, &gif_image_ptr->image_gce_ptr);\r
954     gif_ptr->img_ptr_arr_ptr->Add(gif_image_ptr);\r
955     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
956     return 1;\r
957 }\r
958 int32_t _gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num)\r
959 {\r
960     if(gif_ptr == NULL ||\r
961             frame_num < 0 ||\r
962             frame_num >= gif_ptr->img_ptr_arr_ptr->GetSize()\r
963       ) {\r
964         return 0;\r
965     }\r
966     FX_LPBYTE data_size_ptr = NULL;\r
967     FX_LPBYTE data_ptr = NULL;\r
968     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
969     GifImage* gif_image_ptr = gif_ptr->img_ptr_arr_ptr->GetAt(frame_num);\r
970     FX_DWORD gif_img_row_bytes = gif_image_ptr->image_info_ptr->width;\r
971     if(gif_ptr->decode_status == GIF_D_STATUS_TAIL) {\r
972         if(gif_image_ptr->image_row_buf) {\r
973             FX_Free(gif_image_ptr->image_row_buf);\r
974             gif_image_ptr->image_row_buf = NULL;\r
975         }\r
976         gif_image_ptr->image_row_buf = FX_Alloc(uint8_t, gif_img_row_bytes);\r
977         GIF_PTR_NOT_NULL(gif_image_ptr->image_row_buf, gif_ptr);\r
978         GifGCE* gif_img_gce_ptr = gif_image_ptr->image_gce_ptr;\r
979         int32_t loc_pal_num = ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->local_pal ?\r
980                                (2 << ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->pal_bits) : 0;\r
981         gif_ptr->avail_in = 0;\r
982         if(gif_img_gce_ptr == NULL) {\r
983             FX_BOOL bRes = gif_ptr->_gif_get_record_position_fn(gif_ptr, gif_image_ptr->image_data_pos,\r
984                            gif_image_ptr->image_info_ptr->left,\r
985                            gif_image_ptr->image_info_ptr->top,\r
986                            gif_image_ptr->image_info_ptr->width,\r
987                            gif_image_ptr->image_info_ptr->height,\r
988                            loc_pal_num, gif_image_ptr->local_pal_ptr,\r
989                            0, 0, -1, 0,\r
990                            (FX_BOOL)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace\r
991                                                                );\r
992             if(!bRes) {\r
993                 FX_Free(gif_image_ptr->image_row_buf);\r
994                 gif_image_ptr->image_row_buf = NULL;\r
995                 _gif_error(gif_ptr, "Error Read Record Position Data");\r
996                 return 0;\r
997             }\r
998         } else {\r
999             FX_BOOL bRes = gif_ptr->_gif_get_record_position_fn(gif_ptr, gif_image_ptr->image_data_pos,\r
1000                            gif_image_ptr->image_info_ptr->left,\r
1001                            gif_image_ptr->image_info_ptr->top,\r
1002                            gif_image_ptr->image_info_ptr->width,\r
1003                            gif_image_ptr->image_info_ptr->height,\r
1004                            loc_pal_num, gif_image_ptr->local_pal_ptr,\r
1005                            (int32_t)gif_image_ptr->image_gce_ptr->delay_time,\r
1006                            (FX_BOOL)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->user_input,\r
1007                            ((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->transparency ?\r
1008                            (int32_t)gif_image_ptr->image_gce_ptr->trans_index : -1,\r
1009                            (int32_t)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->disposal_method,\r
1010                            (FX_BOOL)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace\r
1011                                                                );\r
1012             if(!bRes) {\r
1013                 FX_Free(gif_image_ptr->image_row_buf);\r
1014                 gif_image_ptr->image_row_buf = NULL;\r
1015                 _gif_error(gif_ptr, "Error Read Record Position Data");\r
1016                 return 0;\r
1017             }\r
1018         }\r
1019         if(gif_ptr->img_decoder_ptr == NULL) {\r
1020             gif_ptr->img_decoder_ptr = new CGifLZWDecoder(gif_ptr->err_ptr);\r
1021             GIF_PTR_NOT_NULL(gif_ptr->img_decoder_ptr, gif_ptr);\r
1022         }\r
1023         gif_ptr->img_decoder_ptr->InitTable(gif_image_ptr->image_code_size);\r
1024         gif_ptr->img_row_offset = 0;\r
1025         gif_ptr->img_row_avail_size = 0;\r
1026         gif_ptr->img_pass_num = 0;\r
1027         gif_image_ptr->image_row_num = 0;\r
1028         _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
1029     }\r
1030     CGifLZWDecoder* img_decoder_ptr = gif_ptr->img_decoder_ptr;\r
1031     if(gif_ptr->decode_status == GIF_D_STATUS_IMG_DATA) {\r
1032         if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
1033             return 2;\r
1034         }\r
1035         if(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
1036             if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {\r
1037                 gif_ptr->skip_size = skip_size_org;\r
1038                 return 2;\r
1039             }\r
1040             img_decoder_ptr->Input(data_ptr, *data_size_ptr);\r
1041             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
1042             gif_ptr->img_row_offset += gif_ptr->img_row_avail_size;\r
1043             gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset;\r
1044             int32_t ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size);\r
1045             if(ret == 0) {\r
1046                 FX_Free(gif_image_ptr->image_row_buf);\r
1047                 gif_image_ptr->image_row_buf = NULL;\r
1048                 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
1049                 _gif_error(gif_ptr, "Decode Image Data Error");\r
1050                 return 0;\r
1051             }\r
1052             while (ret != 0) {\r
1053                 if(ret == 1) {\r
1054                     gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num, gif_image_ptr->image_row_buf);\r
1055                     FX_Free(gif_image_ptr->image_row_buf);\r
1056                     gif_image_ptr->image_row_buf = NULL;\r
1057                     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
1058                     return 1;\r
1059                 }\r
1060                 if(ret == 2) {\r
1061                     ASSERT(img_decoder_ptr->GetAvailInput() == 0);\r
1062                     skip_size_org = gif_ptr->skip_size;\r
1063                     if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
1064                         return 2;\r
1065                     }\r
1066                     if (*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
1067                         if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {\r
1068                             gif_ptr->skip_size = skip_size_org;\r
1069                             return 2;\r
1070                         }\r
1071                         img_decoder_ptr->Input(data_ptr, *data_size_ptr);\r
1072                         _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
1073                         gif_ptr->img_row_offset += gif_ptr->img_row_avail_size;\r
1074                         gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset;\r
1075                         ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size);\r
1076                     }\r
1077                 }\r
1078                 if(ret == 3) {\r
1079                     if(((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace) {\r
1080                         gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num, gif_image_ptr->image_row_buf);\r
1081                         gif_image_ptr->image_row_num += s_gif_interlace_step[gif_ptr->img_pass_num];\r
1082                         if(gif_image_ptr->image_row_num >= (int32_t)gif_image_ptr->image_info_ptr->height) {\r
1083                             gif_ptr->img_pass_num++;\r
1084                             gif_image_ptr->image_row_num = s_gif_interlace_step[gif_ptr->img_pass_num] / 2;\r
1085                         }\r
1086                     } else {\r
1087                         gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num++, gif_image_ptr->image_row_buf);\r
1088                     }\r
1089                     gif_ptr->img_row_offset = 0;\r
1090                     gif_ptr->img_row_avail_size = gif_img_row_bytes;\r
1091                     ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size);\r
1092                 }\r
1093                 if(ret == 0) {\r
1094                     FX_Free(gif_image_ptr->image_row_buf);\r
1095                     gif_image_ptr->image_row_buf = NULL;\r
1096                     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
1097                     _gif_error(gif_ptr, "Decode Image Data Error");\r
1098                     return 0;\r
1099                 }\r
1100             }\r
1101         }\r
1102         _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
1103     }\r
1104     _gif_error(gif_ptr, "Decode Image Data Error");\r
1105     return 0;\r
1106 }\r
1107 void _gif_save_decoding_status(gif_decompress_struct_p gif_ptr, int32_t status)\r
1108 {\r
1109     gif_ptr->decode_status = status;\r
1110     gif_ptr->next_in += gif_ptr->skip_size;\r
1111     gif_ptr->avail_in -= gif_ptr->skip_size;\r
1112     gif_ptr->skip_size = 0;\r
1113 }\r
1114 FX_LPBYTE _gif_read_data(gif_decompress_struct_p gif_ptr, FX_LPBYTE* des_buf_pp, FX_DWORD data_size)\r
1115 {\r
1116     if(gif_ptr == NULL ||\r
1117             gif_ptr->avail_in < gif_ptr->skip_size + data_size) {\r
1118         return NULL;\r
1119     }\r
1120     *des_buf_pp = gif_ptr->next_in + gif_ptr->skip_size;\r
1121     gif_ptr->skip_size += data_size;\r
1122     return *des_buf_pp;\r
1123 }\r
1124 void _gif_input_buffer(gif_decompress_struct_p gif_ptr, FX_LPBYTE src_buf, FX_DWORD src_size)\r
1125 {\r
1126     gif_ptr->next_in = src_buf;\r
1127     gif_ptr->avail_in = src_size;\r
1128     gif_ptr->skip_size = 0;\r
1129 }\r
1130 FX_DWORD _gif_get_avail_input(gif_decompress_struct_p gif_ptr, FX_LPBYTE* avial_buf_ptr)\r
1131 {\r
1132     if(avial_buf_ptr != NULL) {\r
1133         *avial_buf_ptr = NULL;\r
1134         if(gif_ptr->avail_in > 0) {\r
1135             *avial_buf_ptr = gif_ptr->next_in;\r
1136         }\r
1137     }\r
1138     return gif_ptr->avail_in;\r
1139 }\r
1140 int32_t _gif_get_frame_num(gif_decompress_struct_p gif_ptr)\r
1141 {\r
1142     return gif_ptr->img_ptr_arr_ptr->GetSize();\r
1143 }\r
1144 static FX_BOOL _gif_write_header( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len )\r
1145 {\r
1146     if (gif_ptr->cur_offset) {\r
1147         return TRUE;\r
1148     }\r
1149     dst_len = sizeof(GifHeader) + sizeof(GifLSD) + sizeof(GifGF);\r
1150     dst_buf = FX_TryAlloc(uint8_t, dst_len);\r
1151     if (dst_buf == NULL)        {\r
1152         return FALSE;\r
1153     }\r
1154     FXSYS_memset32(dst_buf, 0, dst_len);\r
1155     FXSYS_memcpy32(dst_buf, gif_ptr->header_ptr, sizeof(GifHeader));\r
1156     gif_ptr->cur_offset += sizeof(GifHeader);\r
1157     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->width);\r
1158     gif_ptr->cur_offset += 2;\r
1159     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->height);\r
1160     gif_ptr->cur_offset += 2;\r
1161     dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->global_flag;\r
1162     dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->bc_index;\r
1163     dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->pixel_aspect;\r
1164     if (gif_ptr->global_pal) {\r
1165         FX_WORD size = sizeof(GifPalette) * gif_ptr->gpal_num;\r
1166         if (!_gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + size)) {\r
1167             return FALSE;\r
1168         }\r
1169         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->global_pal, size);\r
1170         gif_ptr->cur_offset += size;\r
1171     }\r
1172     return TRUE;\r
1173 }\r
1174 void interlace_buf(FX_LPCBYTE buf, FX_DWORD pitch, FX_DWORD height)\r
1175 {\r
1176     CFX_ArrayTemplate<FX_LPBYTE> pass[4];\r
1177     int i, j;\r
1178     FX_DWORD row;\r
1179     row = 0;\r
1180     FX_LPBYTE temp;\r
1181     while (row < height) {\r
1182         if (row % 8 == 0) {\r
1183             j = 0;\r
1184         } else if (row % 4 == 0) {\r
1185             j = 1;\r
1186         } else if (row % 2 == 0) {\r
1187             j = 2;\r
1188         } else {\r
1189             j = 3;\r
1190         }\r
1191         temp = FX_Alloc(uint8_t, pitch);\r
1192         if (temp == NULL) {\r
1193             return;\r
1194         }\r
1195         FXSYS_memcpy32(temp, &buf[pitch * row], pitch);\r
1196         pass[j].Add(temp);\r
1197         row ++;\r
1198     }\r
1199     for (i = 0, row = 0; i < 4; i++) {\r
1200         for (j = 0; j < pass[i].GetSize(); j++, row++) {\r
1201             FXSYS_memcpy32((FX_LPBYTE)&buf[pitch * row], pass[i].GetAt(j), pitch);\r
1202             FX_Free(pass[i].GetAt(j));\r
1203         }\r
1204     }\r
1205 }\r
1206 static void _gif_write_block_data(FX_LPCBYTE src_buf, FX_DWORD src_len, FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& dst_offset)\r
1207 {\r
1208     FX_DWORD src_offset = 0;\r
1209     while (src_len > GIF_DATA_BLOCK) {\r
1210         dst_buf[dst_offset++] = GIF_DATA_BLOCK;\r
1211         FXSYS_memcpy32(&dst_buf[dst_offset], &src_buf[src_offset], GIF_DATA_BLOCK);\r
1212         dst_offset += GIF_DATA_BLOCK;\r
1213         src_offset += GIF_DATA_BLOCK;\r
1214         src_len -= GIF_DATA_BLOCK;\r
1215     }\r
1216     dst_buf[dst_offset++] = (uint8_t)src_len;\r
1217     FXSYS_memcpy32(&dst_buf[dst_offset], &src_buf[src_offset], src_len);\r
1218     dst_offset += src_len;\r
1219 }\r
1220 static FX_BOOL _gif_write_data( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len )\r
1221 {\r
1222     if (!_gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + GIF_DATA_BLOCK)) {\r
1223         return FALSE;\r
1224     }\r
1225 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
1226     if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0) {\r
1227         dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;\r
1228         dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_GCE;\r
1229         gif_ptr->gce_ptr->block_size = 4;\r
1230         dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->block_size;\r
1231         gif_ptr->gce_ptr->gce_flag = 0;\r
1232         dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->gce_flag;\r
1233         gif_ptr->gce_ptr->delay_time = 10;\r
1234         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->gce_ptr->delay_time);\r
1235         gif_ptr->cur_offset += 2;\r
1236         gif_ptr->gce_ptr->trans_index = 0;\r
1237         dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->trans_index;\r
1238         dst_buf[gif_ptr->cur_offset++] = 0;\r
1239     }\r
1240 #endif\r
1241     dst_buf[gif_ptr->cur_offset++] = GIF_SIG_IMAGE;\r
1242     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->left);\r
1243     gif_ptr->cur_offset += 2;\r
1244     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->top);\r
1245     gif_ptr->cur_offset += 2;\r
1246     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->width);\r
1247     gif_ptr->cur_offset += 2;\r
1248     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->height);\r
1249     gif_ptr->cur_offset += 2;\r
1250     GifLF& lf = (GifLF&)gif_ptr->image_info_ptr->local_flag;\r
1251     dst_buf[gif_ptr->cur_offset++] = gif_ptr->image_info_ptr->local_flag;\r
1252     if (gif_ptr->local_pal) {\r
1253         FX_DWORD pal_size = sizeof(GifPalette) * gif_ptr->lpal_num;\r
1254         if (!_gif_grow_buf(dst_buf, dst_len, pal_size + gif_ptr->cur_offset)) {\r
1255             return FALSE;\r
1256         }\r
1257         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->local_pal, pal_size);\r
1258         gif_ptr->cur_offset += pal_size;\r
1259     }\r
1260     if (lf.interlace) {\r
1261         interlace_buf(gif_ptr->src_buf, gif_ptr->src_pitch, gif_ptr->image_info_ptr->height);\r
1262     }\r
1263     uint8_t code_bit = lf.pal_bits;\r
1264     if (lf.local_pal == 0) {\r
1265         GifGF& gf = (GifGF&)gif_ptr->lsd_ptr->global_flag;\r
1266         code_bit = gf.pal_bits;\r
1267     }\r
1268     gif_ptr->img_encoder_ptr->Start(code_bit, gif_ptr->src_buf, dst_buf, gif_ptr->cur_offset);\r
1269     FX_DWORD i;\r
1270     for (i = 0; i < gif_ptr->src_row; i++) {\r
1271         if (!gif_ptr->img_encoder_ptr->Encode(&gif_ptr->src_buf[i * gif_ptr->src_pitch], gif_ptr->src_width * (code_bit + 1),\r
1272                                               dst_buf, dst_len, gif_ptr->cur_offset)) {\r
1273             return FALSE;\r
1274         }\r
1275     }\r
1276     gif_ptr->img_encoder_ptr->Finish(dst_buf, dst_len, gif_ptr->cur_offset);\r
1277     dst_buf[gif_ptr->cur_offset++] = 0;\r
1278 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
1279     if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->cmt_data_ptr) {\r
1280         dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;\r
1281         dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_CE;\r
1282         _gif_write_block_data(gif_ptr->cmt_data_ptr, gif_ptr->cmt_data_len, dst_buf, dst_len, gif_ptr->cur_offset);\r
1283         dst_buf[gif_ptr->cur_offset++] = 0;\r
1284     }\r
1285 #endif\r
1286 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
1287     if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->pte_data_ptr) {\r
1288         dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;\r
1289         dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_PTE;\r
1290         dst_buf[gif_ptr->cur_offset++] = gif_ptr->pte_ptr->block_size;\r
1291         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_left);\r
1292         gif_ptr->cur_offset += 2;\r
1293         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_top);\r
1294         gif_ptr->cur_offset += 2;\r
1295         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_width);\r
1296         gif_ptr->cur_offset += 2;\r
1297         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_height);\r
1298         gif_ptr->cur_offset += 2;\r
1299         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->char_width);\r
1300         gif_ptr->cur_offset += 2;\r
1301         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->char_height);\r
1302         gif_ptr->cur_offset += 2;\r
1303         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->fc_index);\r
1304         gif_ptr->cur_offset += 2;\r
1305         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->bc_index);\r
1306         gif_ptr->cur_offset += 2;\r
1307         _gif_write_block_data(gif_ptr->pte_data_ptr, gif_ptr->pte_data_len, dst_buf, dst_len, gif_ptr->cur_offset);\r
1308         gif_ptr->cur_offset += gif_ptr->pte_data_len;\r
1309         dst_buf[gif_ptr->cur_offset++] = 0;\r
1310     }\r
1311 #endif\r
1312 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
1313     if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->app_data) {\r
1314         dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;\r
1315         dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_AE;\r
1316         dst_buf[gif_ptr->cur_offset++] = 11;\r
1317         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_identify, 8);\r
1318         gif_ptr->cur_offset += 8;\r
1319         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_authentication, 8);\r
1320         gif_ptr->cur_offset += 3;\r
1321         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_data, gif_ptr->app_data_size);\r
1322         gif_ptr->cur_offset += gif_ptr->app_data_size;\r
1323         dst_buf[gif_ptr->cur_offset++] = 0;\r
1324     }\r
1325 #endif\r
1326     dst_buf[gif_ptr->cur_offset++] = GIF_SIG_TRAILER;\r
1327     return TRUE;\r
1328 }\r
1329 FX_BOOL _gif_encode( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len )\r
1330 {\r
1331     if (!_gif_write_header(gif_ptr, dst_buf, dst_len)) {\r
1332         return FALSE;\r
1333     }\r
1334     FX_DWORD cur_offset = gif_ptr->cur_offset;\r
1335     FX_BOOL res = TRUE;\r
1336     if (gif_ptr->frames) {\r
1337         gif_ptr->cur_offset--;\r
1338     }\r
1339     if (!_gif_write_data(gif_ptr, dst_buf, dst_len)) {\r
1340         gif_ptr->cur_offset = cur_offset;\r
1341         res = FALSE;\r
1342     }\r
1343     dst_len = gif_ptr->cur_offset;\r
1344     dst_buf[dst_len - 1] = GIF_SIG_TRAILER;\r
1345     if (res) {\r
1346         gif_ptr->frames++;\r
1347     }\r
1348     return res;\r
1349 }\r