Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[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(FX_BYTE 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 = (FX_BYTE)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++] = (FX_BYTE)code;\r
53     code_first = (FX_BYTE)code;\r
54 }\r
55 void CGifLZWDecoder::AddCode(FX_WORD prefix_code, FX_BYTE 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 FX_INT32 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                             FX_BYTE 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(FX_BYTE, dst_buf, dst_len);\r
154         }\r
155         if (dst_buf == NULL) {\r
156             dst_len = size;\r
157             dst_buf = FX_Realloc(FX_BYTE, 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(FX_BYTE& val, FX_DWORD index, FX_BYTE index_bit, FX_BYTE index_bit_use, FX_BYTE 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 FX_BYTE _gif_cut_buf(FX_LPCBYTE buf, FX_DWORD& offset, FX_BYTE bit_cut, FX_BYTE& 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         FX_BYTE 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( FX_BYTE 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     FX_BYTE 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     FX_BYTE             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, FX_BYTE& 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(FX_BYTE, 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 = FX_NEW CFX_ArrayTemplate<GifImage*>;\r
346     if(gif_ptr->img_ptr_arr_ptr == NULL) {\r
347         FX_Free(gif_ptr);\r
348         return NULL;\r
349     }\r
350 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
351     gif_ptr->cmt_data_ptr = FX_NEW CFX_ByteString;\r
352     if(gif_ptr->cmt_data_ptr == NULL) {\r
353         delete gif_ptr->img_ptr_arr_ptr;\r
354         FX_Free(gif_ptr);\r
355         return NULL;\r
356     }\r
357 #endif\r
358 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
359     gif_ptr->pt_ptr_arr_ptr = FX_NEW CFX_ArrayTemplate<GifPlainText*>;\r
360     if(gif_ptr->pt_ptr_arr_ptr == NULL) {\r
361         delete(gif_ptr->cmt_data_ptr);\r
362         delete gif_ptr->img_ptr_arr_ptr;\r
363         FX_Free(gif_ptr);\r
364         return NULL;\r
365     }\r
366 #endif\r
367     return gif_ptr;\r
368 }\r
369 void _gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr)\r
370 {\r
371     if(gif_ptr_ptr == NULL || *gif_ptr_ptr == NULL) {\r
372         return;\r
373     }\r
374     gif_decompress_struct_p gif_ptr = *gif_ptr_ptr;\r
375     *gif_ptr_ptr = NULL;\r
376     if(gif_ptr->global_pal_ptr != NULL) {\r
377         FX_Free(gif_ptr->global_pal_ptr);\r
378     }\r
379     if(gif_ptr->img_decoder_ptr != NULL) {\r
380         delete gif_ptr->img_decoder_ptr;\r
381     }\r
382     if(gif_ptr->img_ptr_arr_ptr != NULL) {\r
383         FX_INT32 size_img_arr = gif_ptr->img_ptr_arr_ptr->GetSize();\r
384         for (FX_INT32 i = 0; i < size_img_arr; i++) {\r
385             GifImage* p = gif_ptr->img_ptr_arr_ptr->GetAt(i);\r
386             if(p->image_info_ptr != NULL) {\r
387                 FX_Free(p->image_info_ptr);\r
388             }\r
389             if(p->image_gce_ptr != NULL) {\r
390                 FX_Free(p->image_gce_ptr);\r
391             }\r
392             if(p->image_row_buf != NULL) {\r
393                 FX_Free(p->image_row_buf);\r
394             }\r
395             if(p->local_pal_ptr != NULL && p->local_pal_ptr != gif_ptr->global_pal_ptr) {\r
396                 FX_Free(p->local_pal_ptr);\r
397             }\r
398             FX_Free(p);\r
399         }\r
400         gif_ptr->img_ptr_arr_ptr->RemoveAll();\r
401         delete gif_ptr->img_ptr_arr_ptr;\r
402     }\r
403 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
404     if(gif_ptr->app_data != NULL) {\r
405         FX_Free(gif_ptr->app_data);\r
406     }\r
407 #endif\r
408 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
409     if(gif_ptr->cmt_data_ptr != NULL) {\r
410         delete gif_ptr->cmt_data_ptr;\r
411     }\r
412 #endif\r
413 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
414     if(gif_ptr->gce_ptr != NULL) {\r
415         FX_Free(gif_ptr->gce_ptr);\r
416     }\r
417 #endif\r
418 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
419     if(gif_ptr->pt_ptr_arr_ptr != NULL) {\r
420         FX_INT32 size_pt_arr = gif_ptr->pt_ptr_arr_ptr->GetSize();\r
421         for (FX_INT32 i = 0; i < size_pt_arr; i++) {\r
422             GifPlainText* p = gif_ptr->pt_ptr_arr_ptr->GetAt(i);\r
423             if(p->gce_ptr != NULL) {\r
424                 FX_Free(p->gce_ptr);\r
425             }\r
426             if(p->pte_ptr != NULL) {\r
427                 FX_Free(p->pte_ptr);\r
428             }\r
429             if(p->string_ptr != NULL) {\r
430                 delete p->string_ptr;\r
431             }\r
432         }\r
433         gif_ptr->pt_ptr_arr_ptr->RemoveAll();\r
434         delete gif_ptr->pt_ptr_arr_ptr;\r
435     }\r
436 #endif\r
437     FX_Free(gif_ptr);\r
438 }\r
439 gif_compress_struct_p _gif_create_compress()\r
440 {\r
441     gif_compress_struct_p gif_ptr = (gif_compress_struct*)FX_Alloc(FX_BYTE, sizeof(gif_compress_struct));\r
442     if (gif_ptr == NULL) {\r
443         return NULL;\r
444     }\r
445     FXSYS_memset32(gif_ptr, 0, sizeof(gif_compress_struct));\r
446     gif_ptr->img_encoder_ptr = FX_NEW CGifLZWEncoder;\r
447     if (gif_ptr->img_encoder_ptr == NULL) {\r
448         FX_Free(gif_ptr);\r
449         return NULL;\r
450     }\r
451     gif_ptr->header_ptr = (GifHeader*)FX_Alloc(FX_BYTE, sizeof(GifHeader));\r
452     if (gif_ptr->header_ptr == NULL) {\r
453         delete(gif_ptr->img_encoder_ptr);\r
454         FX_Free(gif_ptr);\r
455         return NULL;\r
456     }\r
457     FXSYS_memcpy32(gif_ptr->header_ptr->signature, GIF_SIGNATURE, 3);\r
458     FXSYS_memcpy32(gif_ptr->header_ptr->version, "89a", 3);\r
459     gif_ptr->lsd_ptr = (GifLSD*)FX_Alloc(FX_BYTE, sizeof(GifLSD));\r
460     if (gif_ptr->lsd_ptr == NULL) {\r
461         FX_Free(gif_ptr->header_ptr);\r
462         delete(gif_ptr->img_encoder_ptr);\r
463         FX_Free(gif_ptr);\r
464         return NULL;\r
465     }\r
466     FXSYS_memset32(gif_ptr->lsd_ptr, 0, sizeof(GifLSD));\r
467     gif_ptr->image_info_ptr = (GifImageInfo*)FX_Alloc(FX_BYTE, sizeof(GifImageInfo));\r
468     if (gif_ptr->image_info_ptr == NULL) {\r
469         FX_Free(gif_ptr->lsd_ptr);\r
470         FX_Free(gif_ptr->header_ptr);\r
471         delete(gif_ptr->img_encoder_ptr);\r
472         FX_Free(gif_ptr);\r
473         return NULL;\r
474     }\r
475     FXSYS_memset32(gif_ptr->image_info_ptr, 0, sizeof(GifImageInfo));\r
476 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
477     FXSYS_memcpy32(gif_ptr->app_identify, "netscape", 8);\r
478     FXSYS_memcpy32(gif_ptr->app_authentication, "2.0", 3);\r
479 #endif\r
480 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
481     gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(FX_BYTE, sizeof(GifGCE));\r
482     if (gif_ptr->gce_ptr == NULL) {\r
483         FX_Free(gif_ptr->image_info_ptr);\r
484         FX_Free(gif_ptr->lsd_ptr);\r
485         FX_Free(gif_ptr->header_ptr);\r
486         delete(gif_ptr->img_encoder_ptr);\r
487         FX_Free(gif_ptr);\r
488         return NULL;\r
489     }\r
490 #endif\r
491 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
492     gif_ptr->pte_ptr = (GifPTE*)FX_Alloc(FX_BYTE, sizeof(GifPTE));\r
493     if (gif_ptr->pte_ptr == NULL) {\r
494         FX_Free(gif_ptr->gce_ptr);\r
495         FX_Free(gif_ptr->image_info_ptr);\r
496         FX_Free(gif_ptr->lsd_ptr);\r
497         FX_Free(gif_ptr->header_ptr);\r
498         delete(gif_ptr->img_encoder_ptr);\r
499         FX_Free(gif_ptr);\r
500         return NULL;\r
501     }\r
502     FXSYS_memset32(gif_ptr->pte_ptr, 0, sizeof(GifPTE));\r
503     gif_ptr->pte_ptr->block_size = 12;\r
504 #endif\r
505     return gif_ptr;\r
506 }\r
507 void _gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr)\r
508 {\r
509     if(gif_ptr_ptr == NULL || *gif_ptr_ptr == NULL) {\r
510         return;\r
511     }\r
512     gif_compress_struct_p gif_ptr = *gif_ptr_ptr;\r
513     *gif_ptr_ptr = NULL;\r
514     if(gif_ptr->header_ptr != NULL)     {\r
515         FX_Free(gif_ptr->header_ptr);\r
516     }\r
517     if(gif_ptr->lsd_ptr != NULL)        {\r
518         FX_Free(gif_ptr->lsd_ptr);\r
519     }\r
520     if(gif_ptr->global_pal != NULL)     {\r
521         FX_Free(gif_ptr->global_pal);\r
522     }\r
523     if(gif_ptr->image_info_ptr != NULL) {\r
524         FX_Free(gif_ptr->image_info_ptr);\r
525     }\r
526     if(gif_ptr->local_pal != NULL)      {\r
527         FX_Free(gif_ptr->local_pal);\r
528     }\r
529     if(gif_ptr->img_encoder_ptr != NULL) {\r
530         delete gif_ptr->img_encoder_ptr;\r
531     }\r
532 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
533     if(gif_ptr->app_data != NULL) {\r
534         FX_Free(gif_ptr->app_data);\r
535     }\r
536 #endif\r
537 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
538     if(gif_ptr->gce_ptr != NULL) {\r
539         FX_Free(gif_ptr->gce_ptr);\r
540     }\r
541 #endif\r
542 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
543     if(gif_ptr->cmt_data_ptr != NULL) {\r
544         FX_Free(gif_ptr->cmt_data_ptr);\r
545     }\r
546 #endif\r
547 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
548     if(gif_ptr->pte_ptr != NULL) {\r
549         FX_Free(gif_ptr->pte_ptr);\r
550     }\r
551 #endif\r
552     FX_Free(gif_ptr);\r
553 }\r
554 void _gif_error(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg)\r
555 {\r
556     if(gif_ptr != NULL && gif_ptr->_gif_error_fn != NULL) {\r
557         gif_ptr->_gif_error_fn(gif_ptr, err_msg);\r
558     }\r
559 }\r
560 void _gif_warn(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg) {}\r
561 FX_INT32 _gif_read_header(gif_decompress_struct_p gif_ptr)\r
562 {\r
563     if(gif_ptr == NULL) {\r
564         return 0;\r
565     }\r
566     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
567     ASSERT(sizeof(GifHeader) == 6);\r
568     GifHeader* gif_header_ptr = NULL;\r
569     if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_header_ptr, 6) == NULL) {\r
570         return 2;\r
571     }\r
572     if(FXSYS_strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 ||\r
573             gif_header_ptr->version[0] != '8' ||\r
574             gif_header_ptr->version[2] != 'a') {\r
575         _gif_error(gif_ptr, "Not A Gif Image");\r
576         return 0;\r
577     }\r
578     ASSERT(sizeof(GifLSD) == 7);\r
579     GifLSD* gif_lsd_ptr = NULL;\r
580     if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_lsd_ptr, 7) == NULL) {\r
581         gif_ptr->skip_size = skip_size_org;\r
582         return 2;\r
583     }\r
584     if(((GifGF*)&gif_lsd_ptr->global_flag)->global_pal) {\r
585         gif_ptr->global_pal_num = 2 << ((GifGF*)&gif_lsd_ptr->global_flag)->pal_bits;\r
586         ASSERT(sizeof(GifPalette) == 3);\r
587         FX_INT32 global_pal_size = gif_ptr->global_pal_num * 3;\r
588         FX_LPBYTE global_pal_ptr = NULL;\r
589         if (_gif_read_data(gif_ptr, &global_pal_ptr, global_pal_size) == NULL) {\r
590             gif_ptr->skip_size = skip_size_org;\r
591             return 2;\r
592         }\r
593         gif_ptr->global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag;\r
594         gif_ptr->global_color_resolution = ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution;\r
595         if(gif_ptr->global_pal_ptr != NULL) {\r
596             FX_Free(gif_ptr->global_pal_ptr);\r
597         }\r
598         gif_ptr->global_pal_ptr = NULL;\r
599         gif_ptr->global_pal_ptr = (GifPalette*)FX_Alloc(FX_BYTE, global_pal_size);\r
600         GIF_PTR_NOT_NULL(gif_ptr->global_pal_ptr, gif_ptr);\r
601         FXSYS_memcpy32(gif_ptr->global_pal_ptr, global_pal_ptr, global_pal_size);\r
602     }\r
603     gif_ptr->width = (int)_GetWord_LSBFirst((FX_LPBYTE)&gif_lsd_ptr->width);\r
604     gif_ptr->height = (int)_GetWord_LSBFirst((FX_LPBYTE)&gif_lsd_ptr->height);\r
605     gif_ptr->bc_index = gif_lsd_ptr->bc_index;\r
606     gif_ptr->pixel_aspect = gif_lsd_ptr->pixel_aspect;\r
607     return 1;\r
608 }\r
609 FX_INT32 _gif_get_frame(gif_decompress_struct_p gif_ptr)\r
610 {\r
611     if(gif_ptr == NULL) {\r
612         return 0;\r
613     }\r
614     FX_INT32 ret = 1;\r
615     while (TRUE) {\r
616         switch(gif_ptr->decode_status) {\r
617             case GIF_D_STATUS_TAIL:\r
618                 return 1;\r
619             case GIF_D_STATUS_SIG: {\r
620                     FX_LPBYTE sig_ptr = NULL;\r
621                     if(_gif_read_data(gif_ptr, &sig_ptr, 1) == NULL) {\r
622                         return 2;\r
623                     }\r
624                     switch(*sig_ptr) {\r
625                         case GIF_SIG_EXTENSION:\r
626                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT);\r
627                             continue;\r
628                         case GIF_SIG_IMAGE:\r
629                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_INFO);\r
630                             continue;\r
631                         case GIF_SIG_TRAILER:\r
632                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
633                             return 1;\r
634                         default:\r
635                             if (gif_ptr->avail_in) {\r
636                                 _gif_warn(gif_ptr, "The Gif File has non_standard Tag!");\r
637                                 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);\r
638                                 continue;\r
639                             }\r
640                             _gif_warn(gif_ptr, "The Gif File Doesn't have Trailer Tag!");\r
641                             return 1;\r
642                     }\r
643                 }\r
644             case GIF_D_STATUS_EXT: {\r
645                     FX_LPBYTE ext_ptr = NULL;\r
646                     if(_gif_read_data(gif_ptr, &ext_ptr, 1) == NULL) {\r
647                         return 2;\r
648                     }\r
649                     switch(*ext_ptr) {\r
650 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
651                         case GIF_BLOCK_AE:\r
652                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_AE);\r
653                             continue;\r
654 #endif\r
655 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
656                         case GIF_BLOCK_CE:\r
657                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_CE);\r
658                             continue;\r
659 #endif\r
660 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
661                         case GIF_BLOCK_GCE:\r
662                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_GCE);\r
663                             continue;\r
664 #endif\r
665 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
666                         case GIF_BLOCK_PTE:\r
667                             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_PTE);\r
668                             continue;\r
669 #endif\r
670                         default: {\r
671                                 FX_INT32 status = GIF_D_STATUS_EXT_UNE;\r
672 #ifndef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
673                                 if(*ext_ptr == GIF_BLOCK_PTE) {\r
674                                     status = GIF_D_STATUS_EXT_PTE;\r
675                                 }\r
676 #endif\r
677                                 _gif_save_decoding_status(gif_ptr, status);\r
678                                 continue;\r
679                             }\r
680                     }\r
681                 }\r
682             case GIF_D_STATUS_IMG_INFO: {\r
683                     ret = _gif_decode_image_info(gif_ptr);\r
684                     if(ret != 1) {\r
685                         return ret;\r
686                     }\r
687                     continue;\r
688                 }\r
689             case GIF_D_STATUS_IMG_DATA: {\r
690                     FX_LPBYTE data_size_ptr = NULL;\r
691                     FX_LPBYTE data_ptr = NULL;\r
692                     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
693                     if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
694                         return 2;\r
695                     }\r
696                     while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
697                         if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {\r
698                             gif_ptr->skip_size = skip_size_org;\r
699                             return 2;\r
700                         }\r
701                         _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
702                         skip_size_org = gif_ptr->skip_size;\r
703                         if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
704                             return 2;\r
705                         }\r
706                     }\r
707                     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);\r
708                     continue;\r
709                 }\r
710             default: {\r
711                     ret = _gif_decode_extension(gif_ptr);\r
712                     if(ret != 1) {\r
713                         return ret;\r
714                     }\r
715                     continue;\r
716                 }\r
717         }\r
718     }\r
719     return 1;\r
720 }\r
721 void _gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr, GifGCE** gce_ptr_ptr)\r
722 {\r
723     *gce_ptr_ptr = NULL;\r
724 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
725     if(gif_ptr->gce_ptr != NULL && gce_ptr_ptr != NULL) {\r
726         *gce_ptr_ptr = gif_ptr->gce_ptr;\r
727         gif_ptr->gce_ptr = NULL;\r
728     }\r
729 #endif\r
730 }\r
731 FX_INT32 _gif_decode_extension(gif_decompress_struct_p gif_ptr)\r
732 {\r
733     FX_LPBYTE data_size_ptr = NULL;\r
734     FX_LPBYTE data_ptr = NULL;\r
735     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
736     switch(gif_ptr->decode_status) {\r
737 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
738         case GIF_D_STATUS_EXT_AE: {\r
739                 ASSERT(sizeof(GifAE) == 12);\r
740                 GifAE* gif_ae_ptr = NULL;\r
741                 if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_ae_ptr, 12) == NULL) {\r
742                     return 2;\r
743                 }\r
744                 CFX_ByteString gif_ae_data_str;\r
745                 if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
746                     gif_ptr->skip_size = skip_size_org;\r
747                     return 2;\r
748                 }\r
749                 while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
750                     FX_BYTE data_size = *data_size_ptr;\r
751                     if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||\r
752                             _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
753                         gif_ptr->skip_size = skip_size_org;\r
754                         return 2;\r
755                     }\r
756                     gif_ae_data_str += CFX_ByteString((FX_LPCBYTE)data_ptr, data_size);\r
757                 }\r
758                 FXSYS_memcpy32(gif_ptr->app_identify, gif_ae_ptr->app_identify, 8);\r
759                 FXSYS_memcpy32(gif_ptr->app_authentication, gif_ae_ptr->app_authentication, 3);\r
760                 gif_ptr->app_data_size = gif_ae_data_str.GetLength();\r
761                 if(gif_ptr->app_data != NULL) {\r
762                     FX_Free(gif_ptr->app_data);\r
763                     gif_ptr->app_data = NULL;\r
764                 }\r
765                 gif_ptr->app_data = FX_Alloc(FX_BYTE, gif_ptr->app_data_size);\r
766                 GIF_PTR_NOT_NULL(gif_ptr->app_data, gif_ptr);\r
767                 FXSYS_memcpy32(gif_ptr->app_data, FX_LPCBYTE(gif_ae_data_str), gif_ptr->app_data_size);\r
768             }\r
769             break;\r
770 #endif\r
771 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
772         case GIF_D_STATUS_EXT_CE: {\r
773                 if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
774                     gif_ptr->skip_size = skip_size_org;\r
775                     return 2;\r
776                 }\r
777                 gif_ptr->cmt_data_ptr->Empty();\r
778                 while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
779                     FX_BYTE data_size = *data_size_ptr;\r
780                     if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||\r
781                             _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
782                         gif_ptr->skip_size = skip_size_org;\r
783                         return 2;\r
784                     }\r
785                     *(gif_ptr->cmt_data_ptr) += CFX_ByteString((FX_LPCSTR)data_ptr, data_size);\r
786                 }\r
787             }\r
788             break;\r
789 #endif\r
790 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
791         case GIF_D_STATUS_EXT_PTE: {\r
792                 ASSERT(sizeof(GifPTE) == 13);\r
793                 GifPTE* gif_pte_ptr = NULL;\r
794                 if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_pte_ptr, 13) == NULL) {\r
795                     return 2;\r
796                 }\r
797                 GifPlainText* gif_pt_ptr = FX_Alloc(GifPlainText, 1);\r
798                 GIF_PTR_NOT_NULL(gif_pt_ptr, gif_ptr);\r
799                 FXSYS_memset32(gif_pt_ptr, 0, sizeof(GifPlainText));\r
800                 _gif_takeover_gce_ptr(gif_ptr, &gif_pt_ptr->gce_ptr);\r
801                 gif_pt_ptr->pte_ptr = (GifPTE*)FX_Alloc(FX_BYTE, sizeof(GifPTE));\r
802                 GIF_PTR_NOT_NULL(gif_pt_ptr->pte_ptr, gif_ptr);\r
803                 gif_pt_ptr->string_ptr = FX_NEW CFX_ByteString;\r
804                 GIF_PTR_NOT_NULL(gif_pt_ptr->string_ptr, gif_ptr);\r
805                 gif_pt_ptr->pte_ptr->block_size = gif_pte_ptr->block_size;\r
806                 gif_pt_ptr->pte_ptr->grid_left = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_left);\r
807                 gif_pt_ptr->pte_ptr->grid_top = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_top);\r
808                 gif_pt_ptr->pte_ptr->grid_width = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_width);\r
809                 gif_pt_ptr->pte_ptr->grid_height = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_height);\r
810                 gif_pt_ptr->pte_ptr->char_width = gif_pte_ptr->char_width;\r
811                 gif_pt_ptr->pte_ptr->char_height = gif_pte_ptr->char_height;\r
812                 gif_pt_ptr->pte_ptr->fc_index = gif_pte_ptr->fc_index;\r
813                 gif_pt_ptr->pte_ptr->bc_index = gif_pte_ptr->bc_index;\r
814                 if(_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                 while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
831                     FX_BYTE data_size = *data_size_ptr;\r
832                     if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||\r
833                             _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
834                         gif_ptr->skip_size = skip_size_org;\r
835                         if(gif_pt_ptr != NULL) {\r
836                             if(gif_pt_ptr->gce_ptr != NULL) {\r
837                                 FX_Free(gif_pt_ptr->gce_ptr);\r
838                             }\r
839                             if(gif_pt_ptr->pte_ptr != NULL) {\r
840                                 FX_Free(gif_pt_ptr->pte_ptr);\r
841                             }\r
842                             if(gif_pt_ptr->string_ptr != NULL) {\r
843                                 delete gif_pt_ptr->string_ptr;\r
844                             }\r
845                             FX_Free(gif_pt_ptr);\r
846                         }\r
847                         return 2;\r
848                     }\r
849                     *(gif_pt_ptr->string_ptr) += CFX_ByteString((FX_LPCSTR)data_ptr, data_size);\r
850                 }\r
851                 gif_ptr->pt_ptr_arr_ptr->Add(gif_pt_ptr);\r
852             }\r
853             break;\r
854 #endif\r
855 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
856         case GIF_D_STATUS_EXT_GCE: {\r
857                 ASSERT(sizeof(GifGCE) == 5);\r
858                 GifGCE* gif_gce_ptr = NULL;\r
859                 if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_gce_ptr, 6) == NULL) {\r
860                     return 2;\r
861                 }\r
862                 if(gif_ptr->gce_ptr == NULL) {\r
863                     gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(FX_BYTE, sizeof(GifGCE));\r
864                     GIF_PTR_NOT_NULL(gif_ptr->gce_ptr, gif_ptr);\r
865                 }\r
866                 gif_ptr->gce_ptr->block_size = gif_gce_ptr->block_size;\r
867                 gif_ptr->gce_ptr->gce_flag = gif_gce_ptr->gce_flag;\r
868                 gif_ptr->gce_ptr->delay_time = _GetWord_LSBFirst((FX_LPBYTE)&gif_gce_ptr->delay_time);\r
869                 gif_ptr->gce_ptr->trans_index = gif_gce_ptr->trans_index;\r
870             }\r
871             break;\r
872 #endif\r
873         default: {\r
874 #ifndef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
875                 if(gif_ptr->decode_status == GIF_D_STATUS_EXT_PTE) {\r
876 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
877                     if(gif_ptr->gce_ptr != NULL) {\r
878                         FX_Free(gif_ptr->gce_ptr);\r
879                         gif_ptr->gce_ptr = NULL;\r
880                     }\r
881 #endif\r
882                 }\r
883 #endif\r
884                 if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
885                     return 2;\r
886                 }\r
887                 while(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
888                     if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL ||\r
889                             _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL ) {\r
890                         gif_ptr->skip_size = skip_size_org;\r
891                         return 2;\r
892                     }\r
893                 }\r
894             }\r
895     }\r
896     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);\r
897     return 1;\r
898 }\r
899 FX_INT32 _gif_decode_image_info(gif_decompress_struct_p gif_ptr)\r
900 {\r
901     if(gif_ptr->width == 0 || gif_ptr->height == 0) {\r
902         _gif_error(gif_ptr, "No Image Header Info");\r
903         return 0;\r
904     }\r
905     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
906     ASSERT(sizeof(GifImageInfo) == 9);\r
907     GifImageInfo* gif_img_info_ptr = NULL;\r
908     if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_img_info_ptr, 9) == NULL) {\r
909         return 2;\r
910     }\r
911     GifImage* gif_image_ptr = (GifImage*)FX_Alloc(FX_BYTE, sizeof(GifImage));\r
912     GIF_PTR_NOT_NULL(gif_image_ptr, gif_ptr);\r
913     FXSYS_memset32(gif_image_ptr, 0, sizeof(GifImage));\r
914     gif_image_ptr->image_info_ptr = (GifImageInfo*)FX_Alloc(FX_BYTE, sizeof(GifImageInfo));\r
915     GIF_PTR_NOT_NULL(gif_image_ptr->image_info_ptr, gif_ptr);\r
916     gif_image_ptr->image_info_ptr->left = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->left);\r
917     gif_image_ptr->image_info_ptr->top = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->top);\r
918     gif_image_ptr->image_info_ptr->width = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->width);\r
919     gif_image_ptr->image_info_ptr->height = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->height);\r
920     gif_image_ptr->image_info_ptr->local_flag = gif_img_info_ptr->local_flag;\r
921     if(gif_image_ptr->image_info_ptr->left + gif_image_ptr->image_info_ptr->width > gif_ptr->width ||\r
922             gif_image_ptr->image_info_ptr->top + gif_image_ptr->image_info_ptr->height > gif_ptr->height) {\r
923         if(gif_image_ptr->image_info_ptr != NULL) {\r
924             FX_Free(gif_image_ptr->image_info_ptr);\r
925         }\r
926         if(gif_image_ptr->image_row_buf != NULL) {\r
927             FX_Free(gif_image_ptr->image_row_buf);\r
928         }\r
929         FX_Free(gif_image_ptr);\r
930         _gif_error(gif_ptr, "Image Data Out Of LSD, The File May Be Corrupt");\r
931         return 0;\r
932     }\r
933     GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;\r
934     if(gif_img_info_lf_ptr->local_pal) {\r
935         ASSERT(sizeof(GifPalette) == 3);\r
936         FX_INT32 loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3;\r
937         FX_LPBYTE loc_pal_ptr = NULL;\r
938         if(_gif_read_data(gif_ptr, &loc_pal_ptr, loc_pal_size) == NULL) {\r
939             gif_ptr->skip_size = skip_size_org;\r
940             if(gif_image_ptr->image_info_ptr != NULL) {\r
941                 FX_Free(gif_image_ptr->image_info_ptr);\r
942             }\r
943             if(gif_image_ptr->image_row_buf != NULL) {\r
944                 FX_Free(gif_image_ptr->image_row_buf);\r
945             }\r
946             FX_Free(gif_image_ptr);\r
947             return 2;\r
948         }\r
949         gif_image_ptr->local_pal_ptr = (GifPalette*)gif_ptr->_gif_ask_buf_for_pal_fn(gif_ptr, loc_pal_size);\r
950         if(gif_image_ptr->local_pal_ptr != NULL) {\r
951             FXSYS_memcpy32((FX_LPBYTE)gif_image_ptr->local_pal_ptr, loc_pal_ptr, loc_pal_size);\r
952         }\r
953     }\r
954     FX_LPBYTE code_size_ptr = NULL;\r
955     if(_gif_read_data(gif_ptr, &code_size_ptr, 1) == NULL) {\r
956         gif_ptr->skip_size = skip_size_org;\r
957         if(gif_image_ptr->image_info_ptr != NULL) {\r
958             FX_Free(gif_image_ptr->image_info_ptr);\r
959         }\r
960         if(gif_image_ptr->local_pal_ptr != NULL) {\r
961             FX_Free(gif_image_ptr->local_pal_ptr);\r
962         }\r
963         if(gif_image_ptr->image_row_buf != NULL) {\r
964             FX_Free(gif_image_ptr->image_row_buf);\r
965         }\r
966         FX_Free(gif_image_ptr);\r
967         return 2;\r
968     }\r
969     gif_image_ptr->image_code_size = *code_size_ptr;\r
970     gif_ptr->_gif_record_current_position_fn(gif_ptr, &gif_image_ptr->image_data_pos);\r
971     gif_image_ptr->image_data_pos += gif_ptr->skip_size;\r
972     _gif_takeover_gce_ptr(gif_ptr, &gif_image_ptr->image_gce_ptr);\r
973     gif_ptr->img_ptr_arr_ptr->Add(gif_image_ptr);\r
974     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
975     return 1;\r
976 }\r
977 FX_INT32 _gif_load_frame(gif_decompress_struct_p gif_ptr, FX_INT32 frame_num)\r
978 {\r
979     if(gif_ptr == NULL ||\r
980             frame_num < 0 ||\r
981             frame_num >= gif_ptr->img_ptr_arr_ptr->GetSize()\r
982       ) {\r
983         return 0;\r
984     }\r
985     FX_LPBYTE data_size_ptr = NULL;\r
986     FX_LPBYTE data_ptr = NULL;\r
987     FX_DWORD skip_size_org = gif_ptr->skip_size;\r
988     GifImage* gif_image_ptr = gif_ptr->img_ptr_arr_ptr->GetAt(frame_num);\r
989     FX_DWORD gif_img_row_bytes = gif_image_ptr->image_info_ptr->width;\r
990     if(gif_ptr->decode_status == GIF_D_STATUS_TAIL) {\r
991         if(gif_image_ptr->image_row_buf) {\r
992             FX_Free(gif_image_ptr->image_row_buf);\r
993             gif_image_ptr->image_row_buf = NULL;\r
994         }\r
995         gif_image_ptr->image_row_buf = FX_Alloc(FX_BYTE, gif_img_row_bytes);\r
996         GIF_PTR_NOT_NULL(gif_image_ptr->image_row_buf, gif_ptr);\r
997         GifGCE* gif_img_gce_ptr = gif_image_ptr->image_gce_ptr;\r
998         FX_INT32 loc_pal_num = ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->local_pal ?\r
999                                (2 << ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->pal_bits) : 0;\r
1000         gif_ptr->avail_in = 0;\r
1001         if(gif_img_gce_ptr == NULL) {\r
1002             FX_BOOL bRes = gif_ptr->_gif_get_record_position_fn(gif_ptr, gif_image_ptr->image_data_pos,\r
1003                            gif_image_ptr->image_info_ptr->left,\r
1004                            gif_image_ptr->image_info_ptr->top,\r
1005                            gif_image_ptr->image_info_ptr->width,\r
1006                            gif_image_ptr->image_info_ptr->height,\r
1007                            loc_pal_num, gif_image_ptr->local_pal_ptr,\r
1008                            0, 0, -1, 0,\r
1009                            (FX_BOOL)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace\r
1010                                                                );\r
1011             if(!bRes) {\r
1012                 FX_Free(gif_image_ptr->image_row_buf);\r
1013                 gif_image_ptr->image_row_buf = NULL;\r
1014                 _gif_error(gif_ptr, "Error Read Record Position Data");\r
1015                 return 0;\r
1016             }\r
1017         } else {\r
1018             FX_BOOL bRes = gif_ptr->_gif_get_record_position_fn(gif_ptr, gif_image_ptr->image_data_pos,\r
1019                            gif_image_ptr->image_info_ptr->left,\r
1020                            gif_image_ptr->image_info_ptr->top,\r
1021                            gif_image_ptr->image_info_ptr->width,\r
1022                            gif_image_ptr->image_info_ptr->height,\r
1023                            loc_pal_num, gif_image_ptr->local_pal_ptr,\r
1024                            (FX_INT32)gif_image_ptr->image_gce_ptr->delay_time,\r
1025                            (FX_BOOL)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->user_input,\r
1026                            ((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->transparency ?\r
1027                            (FX_INT32)gif_image_ptr->image_gce_ptr->trans_index : -1,\r
1028                            (FX_INT32)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->disposal_method,\r
1029                            (FX_BOOL)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace\r
1030                                                                );\r
1031             if(!bRes) {\r
1032                 FX_Free(gif_image_ptr->image_row_buf);\r
1033                 gif_image_ptr->image_row_buf = NULL;\r
1034                 _gif_error(gif_ptr, "Error Read Record Position Data");\r
1035                 return 0;\r
1036             }\r
1037         }\r
1038         if(gif_ptr->img_decoder_ptr == NULL) {\r
1039             gif_ptr->img_decoder_ptr = FX_NEW CGifLZWDecoder(gif_ptr->err_ptr);\r
1040             GIF_PTR_NOT_NULL(gif_ptr->img_decoder_ptr, gif_ptr);\r
1041         }\r
1042         gif_ptr->img_decoder_ptr->InitTable(gif_image_ptr->image_code_size);\r
1043         gif_ptr->img_row_offset = 0;\r
1044         gif_ptr->img_row_avail_size = 0;\r
1045         gif_ptr->img_pass_num = 0;\r
1046         gif_image_ptr->image_row_num = 0;\r
1047         _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
1048     }\r
1049     CGifLZWDecoder* img_decoder_ptr = gif_ptr->img_decoder_ptr;\r
1050     if(gif_ptr->decode_status == GIF_D_STATUS_IMG_DATA) {\r
1051         if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
1052             return 2;\r
1053         }\r
1054         if(*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
1055             if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {\r
1056                 gif_ptr->skip_size = skip_size_org;\r
1057                 return 2;\r
1058             }\r
1059             img_decoder_ptr->Input(data_ptr, *data_size_ptr);\r
1060             _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
1061             gif_ptr->img_row_offset += gif_ptr->img_row_avail_size;\r
1062             gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset;\r
1063             FX_INT32 ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size);\r
1064             if(ret == 0) {\r
1065                 FX_Free(gif_image_ptr->image_row_buf);\r
1066                 gif_image_ptr->image_row_buf = NULL;\r
1067                 _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
1068                 _gif_error(gif_ptr, "Decode Image Data Error");\r
1069                 return 0;\r
1070             }\r
1071             while (ret != 0) {\r
1072                 if(ret == 1) {\r
1073                     gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num, gif_image_ptr->image_row_buf);\r
1074                     FX_Free(gif_image_ptr->image_row_buf);\r
1075                     gif_image_ptr->image_row_buf = NULL;\r
1076                     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
1077                     return 1;\r
1078                 }\r
1079                 if(ret == 2) {\r
1080                     ASSERT(img_decoder_ptr->GetAvailInput() == 0);\r
1081                     skip_size_org = gif_ptr->skip_size;\r
1082                     if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) {\r
1083                         return 2;\r
1084                     }\r
1085                     if (*data_size_ptr != GIF_BLOCK_TERMINAL) {\r
1086                         if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) {\r
1087                             gif_ptr->skip_size = skip_size_org;\r
1088                             return 2;\r
1089                         }\r
1090                         img_decoder_ptr->Input(data_ptr, *data_size_ptr);\r
1091                         _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);\r
1092                         gif_ptr->img_row_offset += gif_ptr->img_row_avail_size;\r
1093                         gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset;\r
1094                         ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size);\r
1095                     }\r
1096                 }\r
1097                 if(ret == 3) {\r
1098                     if(((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace) {\r
1099                         gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num, gif_image_ptr->image_row_buf);\r
1100                         gif_image_ptr->image_row_num += s_gif_interlace_step[gif_ptr->img_pass_num];\r
1101                         if(gif_image_ptr->image_row_num >= (FX_INT32)gif_image_ptr->image_info_ptr->height) {\r
1102                             gif_ptr->img_pass_num++;\r
1103                             gif_image_ptr->image_row_num = s_gif_interlace_step[gif_ptr->img_pass_num] / 2;\r
1104                         }\r
1105                     } else {\r
1106                         gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num++, gif_image_ptr->image_row_buf);\r
1107                     }\r
1108                     gif_ptr->img_row_offset = 0;\r
1109                     gif_ptr->img_row_avail_size = gif_img_row_bytes;\r
1110                     ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size);\r
1111                 }\r
1112                 if(ret == 0) {\r
1113                     FX_Free(gif_image_ptr->image_row_buf);\r
1114                     gif_image_ptr->image_row_buf = NULL;\r
1115                     _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
1116                     _gif_error(gif_ptr, "Decode Image Data Error");\r
1117                     return 0;\r
1118                 }\r
1119             }\r
1120         }\r
1121         _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);\r
1122     }\r
1123     _gif_error(gif_ptr, "Decode Image Data Error");\r
1124     return 0;\r
1125 }\r
1126 void _gif_save_decoding_status(gif_decompress_struct_p gif_ptr, FX_INT32 status)\r
1127 {\r
1128     gif_ptr->decode_status = status;\r
1129     gif_ptr->next_in += gif_ptr->skip_size;\r
1130     gif_ptr->avail_in -= gif_ptr->skip_size;\r
1131     gif_ptr->skip_size = 0;\r
1132 }\r
1133 FX_LPBYTE _gif_read_data(gif_decompress_struct_p gif_ptr, FX_LPBYTE* des_buf_pp, FX_DWORD data_size)\r
1134 {\r
1135     if(gif_ptr == NULL ||\r
1136             gif_ptr->avail_in < gif_ptr->skip_size + data_size) {\r
1137         return NULL;\r
1138     }\r
1139     *des_buf_pp = gif_ptr->next_in + gif_ptr->skip_size;\r
1140     gif_ptr->skip_size += data_size;\r
1141     return *des_buf_pp;\r
1142 }\r
1143 void _gif_input_buffer(gif_decompress_struct_p gif_ptr, FX_LPBYTE src_buf, FX_DWORD src_size)\r
1144 {\r
1145     gif_ptr->next_in = src_buf;\r
1146     gif_ptr->avail_in = src_size;\r
1147     gif_ptr->skip_size = 0;\r
1148 }\r
1149 FX_DWORD _gif_get_avail_input(gif_decompress_struct_p gif_ptr, FX_LPBYTE* avial_buf_ptr)\r
1150 {\r
1151     if(avial_buf_ptr != NULL) {\r
1152         *avial_buf_ptr = NULL;\r
1153         if(gif_ptr->avail_in > 0) {\r
1154             *avial_buf_ptr = gif_ptr->next_in;\r
1155         }\r
1156     }\r
1157     return gif_ptr->avail_in;\r
1158 }\r
1159 FX_INT32 _gif_get_frame_num(gif_decompress_struct_p gif_ptr)\r
1160 {\r
1161     return gif_ptr->img_ptr_arr_ptr->GetSize();\r
1162 }\r
1163 static FX_BOOL _gif_write_header( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len )\r
1164 {\r
1165     if (gif_ptr->cur_offset) {\r
1166         return TRUE;\r
1167     }\r
1168     dst_len = sizeof(GifHeader) + sizeof(GifLSD) + sizeof(GifGF);\r
1169     dst_buf = FX_AllocNL(FX_BYTE, dst_len);\r
1170     if (dst_buf == NULL)        {\r
1171         return FALSE;\r
1172     }\r
1173     FXSYS_memset32(dst_buf, 0, dst_len);\r
1174     FXSYS_memcpy32(dst_buf, gif_ptr->header_ptr, sizeof(GifHeader));\r
1175     gif_ptr->cur_offset += sizeof(GifHeader);\r
1176     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->width);\r
1177     gif_ptr->cur_offset += 2;\r
1178     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->height);\r
1179     gif_ptr->cur_offset += 2;\r
1180     dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->global_flag;\r
1181     dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->bc_index;\r
1182     dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->pixel_aspect;\r
1183     if (gif_ptr->global_pal) {\r
1184         FX_WORD size = sizeof(GifPalette) * gif_ptr->gpal_num;\r
1185         if (!_gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + size)) {\r
1186             return FALSE;\r
1187         }\r
1188         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->global_pal, size);\r
1189         gif_ptr->cur_offset += size;\r
1190     }\r
1191     return TRUE;\r
1192 }\r
1193 void interlace_buf(FX_LPCBYTE buf, FX_DWORD pitch, FX_DWORD height)\r
1194 {\r
1195     CFX_ArrayTemplate<FX_LPBYTE> pass[4];\r
1196     int i, j;\r
1197     FX_DWORD row;\r
1198     row = 0;\r
1199     FX_LPBYTE temp;\r
1200     while (row < height) {\r
1201         if (row % 8 == 0) {\r
1202             j = 0;\r
1203         } else if (row % 4 == 0) {\r
1204             j = 1;\r
1205         } else if (row % 2 == 0) {\r
1206             j = 2;\r
1207         } else {\r
1208             j = 3;\r
1209         }\r
1210         temp = FX_Alloc(FX_BYTE, pitch);\r
1211         if (temp == NULL) {\r
1212             return;\r
1213         }\r
1214         FXSYS_memcpy32(temp, &buf[pitch * row], pitch);\r
1215         pass[j].Add(temp);\r
1216         row ++;\r
1217     }\r
1218     for (i = 0, row = 0; i < 4; i++) {\r
1219         for (j = 0; j < pass[i].GetSize(); j++, row++) {\r
1220             FXSYS_memcpy32((FX_LPBYTE)&buf[pitch * row], pass[i].GetAt(j), pitch);\r
1221             FX_Free(pass[i].GetAt(j));\r
1222         }\r
1223     }\r
1224 }\r
1225 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
1226 {\r
1227     FX_DWORD src_offset = 0;\r
1228     while (src_len > GIF_DATA_BLOCK) {\r
1229         dst_buf[dst_offset++] = GIF_DATA_BLOCK;\r
1230         FXSYS_memcpy32(&dst_buf[dst_offset], &src_buf[src_offset], GIF_DATA_BLOCK);\r
1231         dst_offset += GIF_DATA_BLOCK;\r
1232         src_offset += GIF_DATA_BLOCK;\r
1233         src_len -= GIF_DATA_BLOCK;\r
1234     }\r
1235     dst_buf[dst_offset++] = (FX_BYTE)src_len;\r
1236     FXSYS_memcpy32(&dst_buf[dst_offset], &src_buf[src_offset], src_len);\r
1237     dst_offset += src_len;\r
1238 }\r
1239 static FX_BOOL _gif_write_data( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len )\r
1240 {\r
1241     if (!_gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + GIF_DATA_BLOCK)) {\r
1242         return FALSE;\r
1243     }\r
1244 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION\r
1245     if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0) {\r
1246         dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;\r
1247         dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_GCE;\r
1248         gif_ptr->gce_ptr->block_size = 4;\r
1249         dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->block_size;\r
1250         gif_ptr->gce_ptr->gce_flag = 0;\r
1251         dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->gce_flag;\r
1252         gif_ptr->gce_ptr->delay_time = 10;\r
1253         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->gce_ptr->delay_time);\r
1254         gif_ptr->cur_offset += 2;\r
1255         gif_ptr->gce_ptr->trans_index = 0;\r
1256         dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->trans_index;\r
1257         dst_buf[gif_ptr->cur_offset++] = 0;\r
1258     }\r
1259 #endif\r
1260     dst_buf[gif_ptr->cur_offset++] = GIF_SIG_IMAGE;\r
1261     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->left);\r
1262     gif_ptr->cur_offset += 2;\r
1263     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->top);\r
1264     gif_ptr->cur_offset += 2;\r
1265     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->width);\r
1266     gif_ptr->cur_offset += 2;\r
1267     _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->height);\r
1268     gif_ptr->cur_offset += 2;\r
1269     GifLF& lf = (GifLF&)gif_ptr->image_info_ptr->local_flag;\r
1270     dst_buf[gif_ptr->cur_offset++] = gif_ptr->image_info_ptr->local_flag;\r
1271     if (gif_ptr->local_pal) {\r
1272         FX_DWORD pal_size = sizeof(GifPalette) * gif_ptr->lpal_num;\r
1273         if (!_gif_grow_buf(dst_buf, dst_len, pal_size + gif_ptr->cur_offset)) {\r
1274             return FALSE;\r
1275         }\r
1276         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->local_pal, pal_size);\r
1277         gif_ptr->cur_offset += pal_size;\r
1278     }\r
1279     if (lf.interlace) {\r
1280         interlace_buf(gif_ptr->src_buf, gif_ptr->src_pitch, gif_ptr->image_info_ptr->height);\r
1281     }\r
1282     FX_BYTE code_bit = lf.pal_bits;\r
1283     if (lf.local_pal == 0) {\r
1284         GifGF& gf = (GifGF&)gif_ptr->lsd_ptr->global_flag;\r
1285         code_bit = gf.pal_bits;\r
1286     }\r
1287     gif_ptr->img_encoder_ptr->Start(code_bit, gif_ptr->src_buf, dst_buf, gif_ptr->cur_offset);\r
1288     FX_DWORD i;\r
1289     for (i = 0; i < gif_ptr->src_row; i++) {\r
1290         if (!gif_ptr->img_encoder_ptr->Encode(&gif_ptr->src_buf[i * gif_ptr->src_pitch], gif_ptr->src_width * (code_bit + 1),\r
1291                                               dst_buf, dst_len, gif_ptr->cur_offset)) {\r
1292             return FALSE;\r
1293         }\r
1294     }\r
1295     gif_ptr->img_encoder_ptr->Finish(dst_buf, dst_len, gif_ptr->cur_offset);\r
1296     dst_buf[gif_ptr->cur_offset++] = 0;\r
1297 #ifdef GIF_SUPPORT_COMMENT_EXTENSION\r
1298     if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->cmt_data_ptr) {\r
1299         dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;\r
1300         dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_CE;\r
1301         _gif_write_block_data(gif_ptr->cmt_data_ptr, gif_ptr->cmt_data_len, dst_buf, dst_len, gif_ptr->cur_offset);\r
1302         dst_buf[gif_ptr->cur_offset++] = 0;\r
1303     }\r
1304 #endif\r
1305 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION\r
1306     if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->pte_data_ptr) {\r
1307         dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;\r
1308         dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_PTE;\r
1309         dst_buf[gif_ptr->cur_offset++] = gif_ptr->pte_ptr->block_size;\r
1310         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_left);\r
1311         gif_ptr->cur_offset += 2;\r
1312         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_top);\r
1313         gif_ptr->cur_offset += 2;\r
1314         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_width);\r
1315         gif_ptr->cur_offset += 2;\r
1316         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_height);\r
1317         gif_ptr->cur_offset += 2;\r
1318         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->char_width);\r
1319         gif_ptr->cur_offset += 2;\r
1320         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->char_height);\r
1321         gif_ptr->cur_offset += 2;\r
1322         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->fc_index);\r
1323         gif_ptr->cur_offset += 2;\r
1324         _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->bc_index);\r
1325         gif_ptr->cur_offset += 2;\r
1326         _gif_write_block_data(gif_ptr->pte_data_ptr, gif_ptr->pte_data_len, dst_buf, dst_len, gif_ptr->cur_offset);\r
1327         gif_ptr->cur_offset += gif_ptr->pte_data_len;\r
1328         dst_buf[gif_ptr->cur_offset++] = 0;\r
1329     }\r
1330 #endif\r
1331 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION\r
1332     if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->app_data) {\r
1333         dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION;\r
1334         dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_AE;\r
1335         dst_buf[gif_ptr->cur_offset++] = 11;\r
1336         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_identify, 8);\r
1337         gif_ptr->cur_offset += 8;\r
1338         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_authentication, 8);\r
1339         gif_ptr->cur_offset += 3;\r
1340         FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_data, gif_ptr->app_data_size);\r
1341         gif_ptr->cur_offset += gif_ptr->app_data_size;\r
1342         dst_buf[gif_ptr->cur_offset++] = 0;\r
1343     }\r
1344 #endif\r
1345     dst_buf[gif_ptr->cur_offset++] = GIF_SIG_TRAILER;\r
1346     return TRUE;\r
1347 }\r
1348 FX_BOOL _gif_encode( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len )\r
1349 {\r
1350     if (!_gif_write_header(gif_ptr, dst_buf, dst_len)) {\r
1351         return FALSE;\r
1352     }\r
1353     FX_DWORD cur_offset = gif_ptr->cur_offset;\r
1354     FX_BOOL res = TRUE;\r
1355     if (gif_ptr->frames) {\r
1356         gif_ptr->cur_offset--;\r
1357     }\r
1358     if (!_gif_write_data(gif_ptr, dst_buf, dst_len)) {\r
1359         gif_ptr->cur_offset = cur_offset;\r
1360         res = FALSE;\r
1361     }\r
1362     dst_len = gif_ptr->cur_offset;\r
1363     dst_buf[dst_len - 1] = GIF_SIG_TRAILER;\r
1364     if (res) {\r
1365         gif_ptr->frames++;\r
1366     }\r
1367     return res;\r
1368 }\r