Merge branch 'upstream'
Michael Biebl
15 years ago
0 | The package is based on Adobe XMP SDK 4.1.1 | |
0 | The package is based on Adobe XMP SDK 4.1.1. | |
1 | ||
1 | 2 | |
2 | 3 | Other authors are: |
4 | ||
3 | 5 | Hubert Figuiere <hub@figuiere.net> |
4 | ||
6 | Ian Jacobi | |
7 | Jason Kivlighn |
0 | 2007-06-29 Hubert Figuiere <hub@figuiere.net> | |
0 | 2007-08-14 Hubert Figuiere <hub@figuiere.net> | |
1 | 1 | |
2 | * rpm/SLED10.spec: Added .spec for SLED10 packaging | |
3 | (only in git) | |
2 | * New API xmp_delete_localized_text(), by Ian Jacobi. | |
4 | 3 | |
5 | 2007-06-28 Hubert Figuiere <hub@figuiere.net> | |
4 | 2007-08-13 Hubert Figuiere <hub@figuiere.net> | |
6 | 5 | |
7 | * New API wrapped: xmp_serialize{,_and_format}() and the | |
8 | corresponding option bits | |
6 | * source/XMPCore/, public/include/: new call DeleteLocalizedText() | |
7 | by Ian Jacobi. | |
8 | ||
9 | * New API xmp_append_array_item(), xmp_delete_property(), | |
10 | xmp_has_property(), xmp_get_localized_text(), | |
11 | xmp_set_localized_text() by Ian Jacobi. | |
12 | * exempi.cpp (xmp_files_open_new): Handle exception properly | |
13 | by Ian Jacobi. | |
9 | 14 | |
10 | * New API wrapped: xmp_get_array_item() | |
15 | 2007-08-12 Hubert Figuiere <hub@figuiere.net> | |
11 | 16 | |
17 | * Added GIF smart handler support by Ian Jacobi. | |
18 | ||
19 | * source/XMPCore/XMPCore_Impl.hpp (kXMPCoreName): Add Exempi | |
20 | name to clearly identify when Exempi is generating. | |
21 |
0 | 1.99.4 | |
1 | ||
2 | - New: GIF Files smart handlers | |
3 | - New: API xmp_append_array_item(), xmp_delete_property(), | |
4 | xmp_has_property(), xmp_get_localized_text(), | |
5 | xmp_set_localized_text() | |
6 | - New: API xmp_delete_localized_text() | |
7 | - New: Exempi will be visible in the "generator" string of the XMP packet. | |
8 | - Bug: xmp_files_open_new() will handle exceptions properly | |
9 | ||
10 | 1.99.3 | |
11 | ||
12 | - New: API xmp_serialize{,_and_format}() and the | |
13 | corresponding option bits | |
14 | - New API xmp_get_array_item() | |
15 | ||
16 | 1.99.2 | |
17 | ||
18 | - New: API xmp_copy() | |
19 | - New: API xmp_set_property2(), xmp_set_array_item() | |
20 | and xmp_get_error() | |
21 | - New: API xmp_get_property_and_bits() | |
22 | - Bug: xmp_files_get_xmp() handle exceptions properly. | |
23 | ||
24 | 1.99.1 | |
25 | ||
26 | - Bug: store the TIFF tag as BYTE and not UNDEFINED | |
27 | to comply with the spec. | |
28 | - Bug: more exception catched. | |
29 | - New: added NS_CC namespace | |
30 | - New: API xmp_register_namespace() | |
31 | ||
32 | 1.99.0 | |
33 | ||
34 | Initial release of the 2.0 series. Based on Adobe XMP SDK 4.1.1 | |
35 |
2275 | 2275 | |
2276 | 2276 | # Define the identity of the package. |
2277 | 2277 | PACKAGE=exempi |
2278 | VERSION=1.99.3 | |
2278 | VERSION=1.99.4 | |
2279 | 2279 | |
2280 | 2280 | |
2281 | 2281 | cat >>confdefs.h <<_ACEOF |
2447 | 2447 | |
2448 | 2448 | EXEMPI_REVISION=0 |
2449 | 2449 | |
2450 | EXEMPI_AGE=3 | |
2451 | ||
2452 | EXEMPI_CURRENT=5 | |
2450 | EXEMPI_AGE=4 | |
2451 | ||
2452 | EXEMPI_CURRENT=6 | |
2453 | 2453 | |
2454 | 2454 | EXEMPI_CURRENT_MIN=`expr $EXEMPI_CURRENT - $EXEMPI_AGE` |
2455 | 2455 |
0 | 0 | AC_PREREQ(2.50) |
1 | 1 | AC_INIT(exempi/xmp.h) |
2 | AM_INIT_AUTOMAKE(exempi, 1.99.3) | |
2 | AM_INIT_AUTOMAKE(exempi, 1.99.4) | |
3 | 3 | AM_MAINTAINER_MODE |
4 | 4 | |
5 | 5 | |
29 | 29 | dnl 1.99.1 is the revision 3 1 0 |
30 | 30 | dnl 1.99.2 is the revision 4 2 0 |
31 | 31 | dnl 1.99.3 is the revision 5 3 0 |
32 | dnl 1.99.4 is the revision 6 4 0 | |
32 | 33 | AC_SUBST([EXEMPI_REVISION], [0]) |
33 | AC_SUBST([EXEMPI_AGE], [3]) | |
34 | AC_SUBST([EXEMPI_CURRENT], [5]) | |
34 | AC_SUBST([EXEMPI_AGE], [4]) | |
35 | AC_SUBST([EXEMPI_CURRENT], [6]) | |
35 | 36 | AC_SUBST([EXEMPI_CURRENT_MIN], |
36 | 37 | [`expr $EXEMPI_CURRENT - $EXEMPI_AGE`]) |
37 | 38 | AC_SUBST([EXEMPI_VERSION_INFO], |
126 | 126 | |
127 | 127 | XmpFilePtr xmp_files_open_new(const char *path, XmpOpenFileOptions options) |
128 | 128 | { |
129 | SXMPFiles *txf = new SXMPFiles(path, XMP_FT_UNKNOWN, options); | |
129 | SXMPFiles *txf = NULL; | |
130 | try { | |
131 | txf = new SXMPFiles(path, XMP_FT_UNKNOWN, options); | |
132 | } | |
133 | catch(const XMP_Error & e) { | |
134 | set_error(e); | |
135 | } | |
130 | 136 | |
131 | 137 | return (XmpFilePtr)txf; |
132 | 138 | } |
298 | 304 | SXMPMeta *txmp = (SXMPMeta *)xmp; |
299 | 305 | delete txmp; |
300 | 306 | } |
301 | ||
302 | 307 | |
303 | 308 | |
304 | 309 | bool xmp_get_property(XmpPtr xmp, const char *schema, |
400 | 405 | return ret; |
401 | 406 | } |
402 | 407 | |
408 | bool xmp_append_array_item(XmpPtr xmp, const char *schema, const char *name, | |
409 | uint32_t arrayOptions, const char *value, | |
410 | uint32_t optionBits) | |
411 | { | |
412 | bool ret = true; | |
413 | SXMPMeta *txmp = (SXMPMeta *)xmp; | |
414 | try { | |
415 | txmp->AppendArrayItem(schema, name, arrayOptions, value, | |
416 | optionBits); | |
417 | } | |
418 | catch(const XMP_Error & e) { | |
419 | set_error(-e.GetID()); | |
420 | ret = false; | |
421 | std::cerr << e.GetErrMsg() << std::endl; | |
422 | } | |
423 | catch(...) { | |
424 | ret = false; | |
425 | } | |
426 | return ret; | |
427 | } | |
428 | ||
429 | bool xmp_delete_property(XmpPtr xmp, const char *schema, const char *name) | |
430 | { | |
431 | bool ret = true; | |
432 | SXMPMeta *txmp = (SXMPMeta *)xmp; | |
433 | try { | |
434 | txmp->DeleteProperty(schema, name); | |
435 | } | |
436 | catch(const XMP_Error & e) { | |
437 | set_error(-e.GetID()); | |
438 | ret = false; | |
439 | std::cerr << e.GetErrMsg() << std::endl; | |
440 | } | |
441 | catch(...) { | |
442 | ret = false; | |
443 | } | |
444 | return ret; | |
445 | } | |
446 | ||
447 | bool xmp_has_property(XmpPtr xmp, const char *schema, const char *name) | |
448 | { | |
449 | bool ret = true; | |
450 | SXMPMeta *txmp = (SXMPMeta *)xmp; | |
451 | try { | |
452 | ret = txmp->DoesPropertyExist(schema, name); | |
453 | } | |
454 | catch(const XMP_Error & e) { | |
455 | set_error(-e.GetID()); | |
456 | ret = false; | |
457 | std::cerr << e.GetErrMsg() << std::endl; | |
458 | } | |
459 | catch(...) { | |
460 | ret = false; | |
461 | } | |
462 | return ret; | |
463 | } | |
464 | ||
465 | bool xmp_get_localized_text(XmpPtr xmp, const char *schema, const char *name, | |
466 | const char *genericLang, const char *specificLang, | |
467 | XmpStringPtr actualLang, XmpStringPtr itemValue, | |
468 | uint32_t *propsBits) | |
469 | { | |
470 | bool ret = false; | |
471 | try { | |
472 | SXMPMeta *txmp = (SXMPMeta *)xmp; | |
473 | XMP_OptionBits optionBits; | |
474 | ret = txmp->GetLocalizedText(schema, name, genericLang, | |
475 | specificLang, STRING(actualLang), | |
476 | STRING(itemValue), &optionBits); | |
477 | if(propsBits) { | |
478 | *propsBits = optionBits; | |
479 | } | |
480 | } | |
481 | catch(const XMP_Error & e) { | |
482 | set_error(e); | |
483 | ret = false; | |
484 | } | |
485 | return ret; | |
486 | } | |
487 | ||
488 | bool xmp_set_localized_text(XmpPtr xmp, const char *schema, const char *name, | |
489 | const char *genericLang, const char *specificLang, | |
490 | const char *value, uint32_t optionBits) | |
491 | { | |
492 | bool ret = true; | |
493 | SXMPMeta *txmp = (SXMPMeta *)xmp; | |
494 | try { | |
495 | txmp->SetLocalizedText(schema, name, genericLang, specificLang, | |
496 | value, optionBits); | |
497 | } | |
498 | catch(const XMP_Error & e) { | |
499 | set_error(-e.GetID()); | |
500 | ret = false; | |
501 | std::cerr << e.GetErrMsg() << std::endl; | |
502 | } | |
503 | catch(...) { | |
504 | ret = false; | |
505 | } | |
506 | return ret; | |
507 | } | |
508 | ||
509 | ||
510 | bool xmp_delete_localized_text(XmpPtr xmp, const char *schema, | |
511 | const char *name, const char *genericLang, | |
512 | const char *specificLang) | |
513 | { | |
514 | bool ret = true; | |
515 | SXMPMeta *txmp = (SXMPMeta *)xmp; | |
516 | try { | |
517 | txmp->DeleteLocalizedText(schema, name, genericLang, | |
518 | specificLang); | |
519 | } | |
520 | catch(const XMP_Error & e) { | |
521 | set_error(-e.GetID()); | |
522 | ret = false; | |
523 | std::cerr << e.GetErrMsg() << std::endl; | |
524 | } | |
525 | catch(...) { | |
526 | ret = false; | |
527 | } | |
528 | return ret; | |
529 | } | |
530 | ||
531 | ||
532 | ||
403 | 533 | XmpStringPtr xmp_string_new() |
404 | 534 | { |
405 | 535 | return (XmpStringPtr)new std::string; |
173 | 173 | |
174 | 174 | XmpStringPtr the_prop = xmp_string_new(); |
175 | 175 | |
176 | BOOST_CHECK(xmp_has_property(xmp, NS_TIFF, "Make")); | |
177 | BOOST_CHECK_EQUAL(xmp_has_property(xmp, NS_TIFF, "Foo"), false); | |
178 | ||
176 | 179 | BOOST_CHECK(xmp_get_property(xmp, NS_TIFF, "Make", the_prop)); |
177 | 180 | BOOST_CHECK_EQUAL(strcmp("Canon", xmp_string_cstr(the_prop)), 0); |
178 | 181 | |
195 | 198 | BOOST_CHECK_EQUAL(bits, 0x50); |
196 | 199 | BOOST_CHECK(XMP_HAS_PROP_QUALIFIERS(bits)); |
197 | 200 | |
198 | BOOST_CHECK(xmp_set_array_item(xmp, NS_DC, "rights", 2, | |
201 | XmpStringPtr the_lang = xmp_string_new(); | |
202 | BOOST_CHECK(xmp_get_localized_text(xmp, NS_DC, "rights", | |
203 | NULL, "x-default", | |
204 | the_lang, the_prop, &bits)); | |
205 | BOOST_CHECK_EQUAL(strcmp("x-default", xmp_string_cstr(the_lang)), 0); | |
206 | BOOST_CHECK(xmp_set_localized_text(xmp, NS_DC, "rights", | |
207 | "en", "en-CA", | |
208 | xmp_string_cstr(the_prop), 0)); | |
209 | BOOST_CHECK(xmp_get_localized_text(xmp, NS_DC, "rights", | |
210 | "en", "en-US", | |
211 | the_lang, the_prop, &bits)); | |
212 | BOOST_CHECK(strcmp("en-US", xmp_string_cstr(the_lang)) != 0); | |
213 | BOOST_CHECK_EQUAL(strcmp("en-CA", xmp_string_cstr(the_lang)), 0); | |
214 | ||
215 | BOOST_CHECK(xmp_delete_localized_text(xmp, NS_DC, "rights", | |
216 | "en", "en-CA")); | |
217 | BOOST_CHECK(xmp_has_property(xmp, NS_DC, "rights[1]")); | |
218 | BOOST_CHECK_EQUAL(xmp_has_property(xmp, NS_DC, "rights[2]"), false); | |
219 | ||
220 | ||
221 | xmp_string_free(the_lang); | |
222 | ||
223 | BOOST_CHECK(xmp_set_array_item(xmp, NS_DC, "creator", 2, | |
199 | 224 | "foo", 0)); |
200 | BOOST_CHECK(xmp_get_array_item(xmp, NS_DC, "rights", 2, | |
225 | BOOST_CHECK(xmp_get_array_item(xmp, NS_DC, "creator", 2, | |
201 | 226 | the_prop, &bits)); |
202 | 227 | BOOST_CHECK(XMP_IS_PROP_SIMPLE(bits)); |
203 | 228 | BOOST_CHECK_EQUAL(strcmp("foo", xmp_string_cstr(the_prop)), 0); |
229 | BOOST_CHECK(xmp_append_array_item(xmp, NS_DC, "creator", 0, "bar", 0)); | |
230 | ||
231 | BOOST_CHECK(xmp_get_array_item(xmp, NS_DC, "creator", 3, | |
232 | the_prop, &bits)); | |
233 | BOOST_CHECK(XMP_IS_PROP_SIMPLE(bits)); | |
234 | BOOST_CHECK_EQUAL(strcmp("bar", xmp_string_cstr(the_prop)), 0); | |
235 | ||
236 | BOOST_CHECK(xmp_delete_property(xmp, NS_DC, "creator[3]")); | |
237 | BOOST_CHECK_EQUAL(xmp_has_property(xmp, NS_DC, "creator[3]"), false); | |
204 | 238 | |
205 | 239 | xmp_string_free(the_prop); |
206 | 240 | xmp_free(xmp); |
8 | 8 | exit 255 |
9 | 9 | fi |
10 | 10 | |
11 | SAMPLES="BlueSquare.ai BlueSquare.eps BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif BlueSquare.avi BlueSquare.indd BlueSquare.pdf BlueSquare.psd BlueSquare.wav" | |
11 | SAMPLES="BlueSquare.ai BlueSquare.eps BlueSquare.gif BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif BlueSquare.avi BlueSquare.indd BlueSquare.pdf BlueSquare.psd BlueSquare.wav" | |
12 | 12 | SAMPLES_DIR=$srcdir/../../samples/BlueSquares |
13 | 13 | DUMPMAINXMP_PROG=../../samples/source/dumpmainxmp |
14 | 14 |
372 | 372 | * @param indent the initial indentation level |
373 | 373 | * @return TRUE if success. |
374 | 374 | */ |
375 | bool xmp_serialize_and_format(XmpPtr xmp, XmpStringPtr buffer, | |
375 | bool xmp_serialize_and_format(XmpPtr xmp, XmpStringPtr buffer, | |
376 | 376 | uint32_t options, |
377 | 377 | uint32_t padding, const char *newline, |
378 | 378 | const char *tab, int32_t indent); |
431 | 431 | const char *name, int32_t index, const char *value, |
432 | 432 | uint32_t optionBits); |
433 | 433 | |
434 | /** Append a value to the XMP Property array in the XMP Packet provided | |
435 | * @param xmp the XMP packet | |
436 | * @param schema the schema of the property | |
437 | * @param name the name of the property | |
438 | * @param arrayOptions option bits of the parent array | |
439 | * @param value null-terminated string | |
440 | * @param optionBits option bits of the value itself. | |
441 | */ | |
442 | bool xmp_append_array_item(XmpPtr xmp, const char *schema, const char *name, | |
443 | uint32_t arrayOptions, const char *value, | |
444 | uint32_t optionBits); | |
445 | ||
446 | /** Delete a property from the XMP Packet provided | |
447 | * @param xmp the XMP packet | |
448 | * @param schema the schema of the property | |
449 | * @param name the name of the property | |
450 | */ | |
451 | bool xmp_delete_property(XmpPtr xmp, const char *schema, const char *name); | |
452 | ||
453 | /** Determines if a property exists in the XMP Packet provided | |
454 | * @param xmp the XMP packet | |
455 | * @param schema the schema of the property. Can't be NULL or empty. | |
456 | * @param name the name of the property. Can't be NULL or empty. | |
457 | * @return true is the property exists | |
458 | */ | |
459 | bool xmp_has_property(XmpPtr xmp, const char *schema, const char *name); | |
460 | ||
461 | /** Get a localised text from a localisable property. | |
462 | * @param xmp the XMP packet | |
463 | * @param schema the schema | |
464 | * @param name the property name. | |
465 | * @param genericLang the generic language you may want as a fall back. | |
466 | * Can be NULL or empty. | |
467 | * @param specificLang the specific language you want. Can't be NULL or empty. | |
468 | * @param actualLang the actual language of the value. Can be NULL if | |
469 | * not wanted. | |
470 | * @param itemValue the localized value. Can be NULL if not wanted. | |
471 | * @param propBits the options flags describing the property. Can be NULL. | |
472 | * @return true if found, false otherwise. | |
473 | */ | |
474 | bool xmp_get_localized_text(XmpPtr xmp, const char *schema, const char *name, | |
475 | const char *genericLang, const char *specificLang, | |
476 | XmpStringPtr actualLang, XmpStringPtr itemValue, | |
477 | uint32_t *propBits); | |
478 | ||
479 | ||
480 | /** Set a localised text in a localisable property. | |
481 | * @param xmp the XMP packet | |
482 | * @param schema the schema | |
483 | * @param name the property name. | |
484 | * @param genericLang the generic language you may want to set too. | |
485 | * Can be NULL or empty. | |
486 | * @param specificLang the specific language you want. Can't be NULL or empty. | |
487 | * @param itemValue the localized value. Cannot be NULL. | |
488 | * @param propBits the options flags describing the property. | |
489 | * @return true if set, false otherwise. | |
490 | */ | |
491 | bool xmp_set_localized_text(XmpPtr xmp, const char *schema, const char *name, | |
492 | const char *genericLang, const char *specificLang, | |
493 | const char *value, uint32_t optionBits); | |
494 | ||
495 | ||
496 | ||
497 | bool xmp_delete_localized_text(XmpPtr xmp, const char *schema, | |
498 | const char *name, const char *genericLang, | |
499 | const char *specificLang); | |
500 | ||
434 | 501 | /** Instanciate a new string |
435 | 502 | * @return the new instance. Must be freed with |
436 | 503 | * xmp_string_free() |
1191 | 1191 | const tStringObj & itemValue, |
1192 | 1192 | XMP_OptionBits options = 0 ); |
1193 | 1193 | |
1194 | void | |
1195 | DeleteLocalizedText ( XMP_StringPtr schemaNS, | |
1196 | XMP_StringPtr altTextName, | |
1197 | XMP_StringPtr genericLang, | |
1198 | XMP_StringPtr specificLang ); | |
1199 | ||
1194 | 1200 | /// @} |
1195 | 1201 | |
1196 | 1202 | // ============================================================================================= |
678 | 678 | this->SetLocalizedText ( schemaNS, altTextName, genericLang, specificLang, itemValue.c_str(), options ); |
679 | 679 | } |
680 | 680 | |
681 | XMP_MethodIntro(TXMPMeta,void):: | |
682 | DeleteLocalizedText ( XMP_StringPtr schemaNS, | |
683 | XMP_StringPtr altTextName, | |
684 | XMP_StringPtr genericLang, | |
685 | XMP_StringPtr specificLang ) | |
686 | { | |
687 | WrapCheckVoid ( zXMPMeta_DeleteLocalizedText_1 ( schemaNS, altTextName, genericLang, specificLang ) ); | |
688 | } | |
689 | ||
681 | 690 | // ------------------------------------------------------------------------------------------------- |
682 | 691 | |
683 | 692 | XMP_MethodIntro(TXMPMeta,bool):: |
118 | 118 | |
119 | 119 | #define zXMPMeta_SetLocalizedText_1(schemaNS,altTextName,genericLang,specificLang,itemValue,options) \ |
120 | 120 | WXMPMeta_SetLocalizedText_1 ( this->xmpRef, schemaNS, altTextName, genericLang, specificLang, itemValue, options, &wResult ) |
121 | ||
122 | #define zXMPMeta_DeleteLocalizedText_1(schemaNS,altTextName,genericLang,specificLang) \ | |
123 | WXMPMeta_DeleteLocalizedText_1 ( this->xmpRef, schemaNS, altTextName, genericLang, specificLang, &wResult ) | |
121 | 124 | |
122 | 125 | #define zXMPMeta_GetProperty_Bool_1(schemaNS,propName,propValue,options) \ |
123 | 126 | WXMPMeta_GetProperty_Bool_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) |
459 | 462 | XMP_OptionBits options, |
460 | 463 | WXMP_Result * wResult ); |
461 | 464 | |
465 | extern void | |
466 | WXMPMeta_DeleteLocalizedText_1 ( XMPMetaRef xmpRef, | |
467 | XMP_StringPtr schemaNS, | |
468 | XMP_StringPtr altTextName, | |
469 | XMP_StringPtr genericLang, | |
470 | XMP_StringPtr specificLang, | |
471 | WXMP_Result * wResult ); | |
472 | ||
462 | 473 | // ------------------------------------------------------------------------------------------------- |
463 | 474 | |
464 | 475 | extern void |
Binary diff not shown
34 | 34 | # |
35 | 35 | |
36 | 36 | |
37 | EXTRA_DIST=BlueSquare.ai BlueSquare.eps BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif\ | |
37 | EXTRA_DIST=BlueSquare.ai BlueSquare.eps BlueSquare.gif BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif\ | |
38 | 38 | BlueSquare.avi BlueSquare.indd BlueSquare.mov BlueSquare.pdf BlueSquare.psd BlueSquare.wav |
196 | 196 | target_alias = @target_alias@ |
197 | 197 | top_builddir = @top_builddir@ |
198 | 198 | top_srcdir = @top_srcdir@ |
199 | EXTRA_DIST = BlueSquare.ai BlueSquare.eps BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif\ | |
199 | EXTRA_DIST = BlueSquare.ai BlueSquare.eps BlueSquare.gif BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif\ | |
200 | 200 | BlueSquare.avi BlueSquare.indd BlueSquare.mov BlueSquare.pdf BlueSquare.psd BlueSquare.wav |
201 | 201 | |
202 | 202 | all: all-am |
867 | 867 | // ------------------------------------------------------------------------------------------------- |
868 | 868 | |
869 | 869 | void |
870 | WXMPMeta_DeleteLocalizedText_1 ( XMPMetaRef xmpRef, | |
871 | XMP_StringPtr schemaNS, | |
872 | XMP_StringPtr arrayName, | |
873 | XMP_StringPtr genericLang, | |
874 | XMP_StringPtr specificLang, | |
875 | WXMP_Result * wResult ) | |
876 | { | |
877 | XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteLocalizedText_1" ) | |
878 | ||
879 | if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); | |
880 | if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); | |
881 | if ( genericLang == 0 ) genericLang = ""; | |
882 | if ( (specificLang == 0) ||(*specificLang == 0) ) XMP_Throw ( "Empty specific language", kXMPErr_BadParam ); | |
883 | ||
884 | XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); | |
885 | meta->DeleteLocalizedText ( schemaNS, arrayName, genericLang, specificLang ); | |
886 | ||
887 | XMP_EXIT_WRAPPER | |
888 | } | |
889 | ||
890 | // ------------------------------------------------------------------------------------------------- | |
891 | ||
892 | void | |
870 | 893 | WXMPMeta_GetProperty_Bool_1 ( XMPMetaRef xmpRef, |
871 | 894 | XMP_StringPtr schemaNS, |
872 | 895 | XMP_StringPtr propName, |
121 | 121 | (XMP_API_VERSION_MINOR << 16) | \ |
122 | 122 | (XMP_API_VERSION_MICRO << 8) ) |
123 | 123 | |
124 | #define kXMPCoreName "XMP Core" | |
124 | #define kXMPCoreName "Exempi + XMP Core" | |
125 | 125 | #define kXMPCore_VersionMessage kXMPCoreName " " XMP_API_VERSION_STRING |
126 | 126 | // ================================================================================================= |
127 | 127 | // Support for asserts |
972 | 972 | |
973 | 973 | |
974 | 974 | // ------------------------------------------------------------------------------------------------- |
975 | // DeleteLocalizedText | |
976 | // ---------------- | |
977 | ||
978 | void | |
979 | XMPMeta::DeleteLocalizedText ( XMP_StringPtr schemaNS, | |
980 | XMP_StringPtr arrayName, | |
981 | XMP_StringPtr _genericLang, | |
982 | XMP_StringPtr _specificLang ) | |
983 | { | |
984 | XMP_Assert ( (schemaNS != 0) && (arrayName != 0) && (_genericLang != 0) && (_specificLang != 0) ); // Enforced by wrapper. | |
985 | ||
986 | XMP_StringPtr itemPath; | |
987 | XMP_StringLen pathLen; | |
988 | ||
989 | XMP_VarString zGenericLang ( _genericLang ); | |
990 | XMP_VarString zSpecificLang ( _specificLang ); | |
991 | NormalizeLangValue ( &zGenericLang ); | |
992 | NormalizeLangValue ( &zSpecificLang ); | |
993 | ||
994 | XMP_StringPtr genericLang = zGenericLang.c_str(); | |
995 | XMP_StringPtr specificLang = zSpecificLang.c_str(); | |
996 | ||
997 | XMP_ExpandedXPath arrayPath; | |
998 | ExpandXPath ( schemaNS, arrayName, &arrayPath ); | |
999 | ||
1000 | const XMP_Node * arrayNode = FindConstNode ( &tree, arrayPath ); // *** This expand/find idiom is used in 3 Getters. | |
1001 | if ( arrayNode == 0 ) return; // *** Should extract it into a local utility. | |
1002 | ||
1003 | XMP_CLTMatch match; | |
1004 | const XMP_Node * itemNode; | |
1005 | ||
1006 | match = ChooseLocalizedText ( arrayNode, genericLang, specificLang, &itemNode ); | |
1007 | // FIXED: Only remove SpecificMatch | |
1008 | if ( match != kXMP_CLT_SpecificMatch ) return; | |
1009 | ||
1010 | XMPUtils::ComposeLangSelector ( schemaNS, arrayName, itemNode->qualifiers[0]->value.c_str(), &itemPath, &pathLen ); | |
1011 | DeleteProperty ( schemaNS, itemPath ); | |
1012 | ||
1013 | } // DeleteLocalizedText | |
1014 | ||
1015 | ||
1016 | // ------------------------------------------------------------------------------------------------- | |
975 | 1017 | // GetProperty_Bool |
976 | 1018 | // ---------------- |
977 | 1019 |
255 | 255 | XMP_StringPtr itemValue, |
256 | 256 | XMP_OptionBits options ); |
257 | 257 | |
258 | void | |
259 | DeleteLocalizedText ( XMP_StringPtr schemaNS, | |
260 | XMP_StringPtr altTextName, | |
261 | XMP_StringPtr genericLang, | |
262 | XMP_StringPtr specificLang); | |
263 | ||
258 | 264 | // --------------------------------------------------------------------------------------------- |
259 | 265 | |
260 | 266 | bool |
0 | // ================================================================================================= | |
1 | // ADOBE SYSTEMS INCORPORATED | |
2 | // Copyright 2002-2007 Adobe Systems Incorporated | |
3 | // All Rights Reserved | |
4 | // | |
5 | // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms | |
6 | // of the Adobe license agreement accompanying it. | |
7 | // | |
8 | // Derived from PNG_Handler.cpp by Ian Jacobi | |
9 | // ================================================================================================= | |
10 | ||
11 | #include "GIF_Handler.hpp" | |
12 | ||
13 | #include "GIF_Support.hpp" | |
14 | ||
15 | using namespace std; | |
16 | ||
17 | // ================================================================================================= | |
18 | /// \file GIF_Handler.hpp | |
19 | /// \brief File format handler for GIF. | |
20 | /// | |
21 | /// This handler ... | |
22 | /// | |
23 | // ================================================================================================= | |
24 | ||
25 | // ================================================================================================= | |
26 | // GIF_MetaHandlerCTor | |
27 | // ==================== | |
28 | ||
29 | XMPFileHandler * GIF_MetaHandlerCTor ( XMPFiles * parent ) | |
30 | { | |
31 | return new GIF_MetaHandler ( parent ); | |
32 | ||
33 | } // GIF_MetaHandlerCTor | |
34 | ||
35 | // ================================================================================================= | |
36 | // GIF_CheckFormat | |
37 | // =============== | |
38 | ||
39 | bool GIF_CheckFormat ( XMP_FileFormat format, | |
40 | XMP_StringPtr filePath, | |
41 | LFA_FileRef fileRef, | |
42 | XMPFiles * parent ) | |
43 | { | |
44 | IgnoreParam(format); IgnoreParam(fileRef); IgnoreParam(parent); | |
45 | XMP_Assert ( format == kXMP_GIFFile ); | |
46 | ||
47 | IOBuffer ioBuf; | |
48 | ||
49 | LFA_Seek ( fileRef, 0, SEEK_SET ); | |
50 | if ( ! CheckFileSpace ( fileRef, &ioBuf, GIF_SIGNATURE_LEN ) ) return false; // We need at least 3, so the buffer is not filled. | |
51 | ||
52 | if ( ! CheckBytes ( ioBuf.ptr, GIF_SIGNATURE_DATA, GIF_SIGNATURE_LEN ) ) return false; | |
53 | ||
54 | return true; | |
55 | ||
56 | } // GIF_CheckFormat | |
57 | ||
58 | // ================================================================================================= | |
59 | // GIF_MetaHandler::GIF_MetaHandler | |
60 | // ================================== | |
61 | ||
62 | GIF_MetaHandler::GIF_MetaHandler ( XMPFiles * _parent ) | |
63 | { | |
64 | this->parent = _parent; | |
65 | this->handlerFlags = kGIF_HandlerFlags; | |
66 | // It MUST be UTF-8. | |
67 | this->stdCharForm = kXMP_Char8Bit; | |
68 | ||
69 | } | |
70 | ||
71 | // ================================================================================================= | |
72 | // GIF_MetaHandler::~GIF_MetaHandler | |
73 | // =================================== | |
74 | ||
75 | GIF_MetaHandler::~GIF_MetaHandler() | |
76 | { | |
77 | } | |
78 | ||
79 | // ================================================================================================= | |
80 | // GIF_MetaHandler::CacheFileData | |
81 | // =============================== | |
82 | ||
83 | void GIF_MetaHandler::CacheFileData() | |
84 | { | |
85 | ||
86 | this->containsXMP = false; | |
87 | ||
88 | LFA_FileRef fileRef ( this->parent->fileRef ); | |
89 | if ( fileRef == 0) return; | |
90 | ||
91 | // We try to navigate through the blocks to find the XMP block. | |
92 | GIF_Support::BlockState blockState; | |
93 | long numBlocks = GIF_Support::OpenGIF ( fileRef, blockState ); | |
94 | if ( numBlocks == 0 ) return; | |
95 | ||
96 | if (blockState.xmpLen != 0) | |
97 | { | |
98 | // XMP present | |
99 | ||
100 | this->xmpPacket.reserve(blockState.xmpLen); | |
101 | this->xmpPacket.assign(blockState.xmpLen, ' '); | |
102 | ||
103 | if (GIF_Support::ReadBuffer ( fileRef, blockState.xmpPos, blockState.xmpLen, const_cast<char *>(this->xmpPacket.data()) )) | |
104 | { | |
105 | this->packetInfo.offset = blockState.xmpPos; | |
106 | this->packetInfo.length = blockState.xmpLen; | |
107 | this->containsXMP = true; | |
108 | } | |
109 | } | |
110 | else | |
111 | { | |
112 | // no XMP | |
113 | } | |
114 | ||
115 | } // GIF_MetaHandler::CacheFileData | |
116 | ||
117 | // ================================================================================================= | |
118 | // GIF_MetaHandler::ProcessTNail | |
119 | // ============================== | |
120 | ||
121 | void GIF_MetaHandler::ProcessTNail() | |
122 | { | |
123 | ||
124 | XMP_Throw ( "GIF_MetaHandler::ProcessTNail isn't implemented yet", kXMPErr_Unimplemented ); | |
125 | ||
126 | } // GIF_MetaHandler::ProcessTNail | |
127 | ||
128 | // ================================================================================================= | |
129 | // GIF_MetaHandler::ProcessXMP | |
130 | // ============================ | |
131 | // | |
132 | // Process the raw XMP and legacy metadata that was previously cached. | |
133 | ||
134 | void GIF_MetaHandler::ProcessXMP() | |
135 | { | |
136 | this->processedXMP = true; // Make sure we only come through here once. | |
137 | ||
138 | // Process the XMP packet. | |
139 | ||
140 | if ( ! this->xmpPacket.empty() ) { | |
141 | ||
142 | XMP_Assert ( this->containsXMP ); | |
143 | XMP_StringPtr packetStr = this->xmpPacket.c_str(); | |
144 | XMP_StringLen packetLen = this->xmpPacket.size(); | |
145 | ||
146 | this->xmpObj.ParseFromBuffer ( packetStr, packetLen ); | |
147 | ||
148 | this->containsXMP = true; | |
149 | ||
150 | } | |
151 | ||
152 | } // GIF_MetaHandler::ProcessXMP | |
153 | ||
154 | // ================================================================================================= | |
155 | // GIF_MetaHandler::UpdateFile | |
156 | // ============================ | |
157 | ||
158 | void GIF_MetaHandler::UpdateFile ( bool doSafeUpdate ) | |
159 | { | |
160 | bool updated = false; | |
161 | ||
162 | if ( ! this->needsUpdate ) return; | |
163 | if ( doSafeUpdate ) XMP_Throw ( "GIF_MetaHandler::UpdateFile: Safe update not supported", kXMPErr_Unavailable ); | |
164 | ||
165 | XMP_StringPtr packetStr = xmpPacket.c_str(); | |
166 | XMP_StringLen packetLen = xmpPacket.size(); | |
167 | if ( packetLen == 0 ) return; | |
168 | ||
169 | LFA_FileRef fileRef(this->parent->fileRef); | |
170 | if ( fileRef == 0 ) return; | |
171 | ||
172 | GIF_Support::BlockState blockState; | |
173 | long numBlocks = GIF_Support::OpenGIF ( fileRef, blockState ); | |
174 | if ( numBlocks == 0 ) return; | |
175 | ||
176 | // write/update block(s) | |
177 | if (blockState.xmpLen == 0) | |
178 | { | |
179 | // no current chunk -> inject | |
180 | updated = SafeWriteFile(); | |
181 | } | |
182 | else if (blockState.xmpLen >= packetLen ) | |
183 | { | |
184 | // current chunk size is sufficient -> write and update CRC (in place update) | |
185 | updated = GIF_Support::WriteBuffer(fileRef, blockState.xmpPos, packetLen, packetStr ); | |
186 | // GIF doesn't have a CRC like PNG. | |
187 | } | |
188 | else if (blockState.xmpLen < packetLen) | |
189 | { | |
190 | // XMP is too large for current chunk -> expand | |
191 | updated = SafeWriteFile(); | |
192 | } | |
193 | ||
194 | if ( ! updated )return; // If there's an error writing the chunk, bail. | |
195 | ||
196 | this->needsUpdate = false; | |
197 | ||
198 | } // GIF_MetaHandler::UpdateFile | |
199 | ||
200 | // ================================================================================================= | |
201 | // GIF_MetaHandler::WriteFile | |
202 | // =========================== | |
203 | ||
204 | void GIF_MetaHandler::WriteFile ( LFA_FileRef sourceRef, const std::string & sourcePath ) | |
205 | { | |
206 | LFA_FileRef destRef = this->parent->fileRef; | |
207 | ||
208 | GIF_Support::BlockState blockState; | |
209 | long numBlocks = GIF_Support::OpenGIF ( sourceRef, blockState ); | |
210 | if ( numBlocks == 0 ) return; | |
211 | ||
212 | LFA_Truncate(destRef, 0); | |
213 | // LFA_Write(destRef, GIF_SIGNATURE_DATA, GIF_SIGNATURE_LEN); | |
214 | ||
215 | GIF_Support::BlockIterator curPos = blockState.blocks.begin(); | |
216 | GIF_Support::BlockIterator endPos = blockState.blocks.end(); | |
217 | ||
218 | long blockCount; | |
219 | ||
220 | for (blockCount = 0; (curPos != endPos); ++curPos, ++blockCount) | |
221 | { | |
222 | GIF_Support::BlockData block = *curPos; | |
223 | ||
224 | // discard existing XMP block | |
225 | if (block.xmp) | |
226 | continue; | |
227 | ||
228 | // copy any other block | |
229 | GIF_Support::CopyBlock(sourceRef, destRef, block); | |
230 | ||
231 | // place XMP block immediately before trailer | |
232 | if (blockCount == numBlocks - 2) | |
233 | { | |
234 | XMP_StringPtr packetStr = xmpPacket.c_str(); | |
235 | XMP_StringLen packetLen = xmpPacket.size(); | |
236 | ||
237 | GIF_Support::WriteXMPBlock(destRef, packetLen, packetStr ); | |
238 | } | |
239 | } | |
240 | ||
241 | } // GIF_MetaHandler::WriteFile | |
242 | ||
243 | // ================================================================================================= | |
244 | // GIF_MetaHandler::SafeWriteFile | |
245 | // =========================== | |
246 | ||
247 | bool GIF_MetaHandler::SafeWriteFile () | |
248 | { | |
249 | bool ret = false; | |
250 | ||
251 | std::string origPath = this->parent->filePath; | |
252 | LFA_FileRef origRef = this->parent->fileRef; | |
253 | ||
254 | std::string updatePath; | |
255 | LFA_FileRef updateRef = 0; | |
256 | ||
257 | CreateTempFile ( origPath, &updatePath, kCopyMacRsrc ); | |
258 | updateRef = LFA_Open ( updatePath.c_str(), 'w' ); | |
259 | ||
260 | this->parent->filePath = updatePath; | |
261 | this->parent->fileRef = updateRef; | |
262 | ||
263 | try { | |
264 | this->WriteFile ( origRef, origPath ); | |
265 | ret = true; | |
266 | } catch ( ... ) { | |
267 | LFA_Close ( updateRef ); | |
268 | this->parent->filePath = origPath; | |
269 | this->parent->fileRef = origRef; | |
270 | throw; | |
271 | } | |
272 | ||
273 | LFA_Close ( origRef ); | |
274 | LFA_Delete ( origPath.c_str() ); | |
275 | ||
276 | LFA_Close ( updateRef ); | |
277 | LFA_Rename ( updatePath.c_str(), origPath.c_str() ); | |
278 | this->parent->filePath = origPath; | |
279 | ||
280 | this->parent->fileRef = 0; | |
281 | ||
282 | return ret; | |
283 | ||
284 | } // GIF_MetaHandler::SafeWriteFile | |
285 | ||
286 | // ================================================================================================= |
0 | #ifndef __GIF_Handler_hpp__ | |
1 | #define __GIF_Handler_hpp__ 1 | |
2 | ||
3 | // ================================================================================================= | |
4 | // ADOBE SYSTEMS INCORPORATED | |
5 | // Copyright 2002-2007 Adobe Systems Incorporated | |
6 | // All Rights Reserved | |
7 | // | |
8 | // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms | |
9 | // of the Adobe license agreement accompanying it. | |
10 | // | |
11 | // Derived from PNG_Handler.hpp by Ian Jacobi | |
12 | // ================================================================================================= | |
13 | ||
14 | #include "GIF_Support.hpp" | |
15 | ||
16 | // ================================================================================================= | |
17 | /// \file GIF_Handler.hpp | |
18 | /// \brief File format handler for GIF. | |
19 | /// | |
20 | /// This header ... | |
21 | /// | |
22 | // ================================================================================================= | |
23 | ||
24 | // *** Could derive from Basic_Handler - buffer file tail in a temp file. | |
25 | ||
26 | extern XMPFileHandler* GIF_MetaHandlerCTor ( XMPFiles* parent ); | |
27 | ||
28 | extern bool GIF_CheckFormat ( XMP_FileFormat format, | |
29 | XMP_StringPtr filePath, | |
30 | LFA_FileRef fileRef, | |
31 | XMPFiles* parent ); | |
32 | ||
33 | static const XMP_OptionBits kGIF_HandlerFlags = ( kXMPFiles_CanInjectXMP | | |
34 | kXMPFiles_CanExpand | | |
35 | kXMPFiles_PrefersInPlace | | |
36 | kXMPFiles_AllowsOnlyXMP | | |
37 | kXMPFiles_ReturnsRawPacket | | |
38 | kXMPFiles_NeedsReadOnlyPacket | |
39 | ); | |
40 | ||
41 | class GIF_MetaHandler : public XMPFileHandler | |
42 | { | |
43 | public: | |
44 | ||
45 | void CacheFileData(); | |
46 | void ProcessTNail(); | |
47 | void ProcessXMP(); | |
48 | ||
49 | void UpdateFile ( bool doSafeUpdate ); | |
50 | void WriteFile ( LFA_FileRef sourceRef, const std::string& sourcePath ); | |
51 | ||
52 | bool SafeWriteFile (); | |
53 | ||
54 | GIF_MetaHandler ( XMPFiles* parent ); | |
55 | virtual ~GIF_MetaHandler(); | |
56 | ||
57 | }; // GIF_MetaHandler | |
58 | ||
59 | // ================================================================================================= | |
60 | ||
61 | #endif /* __GIF_Handler_hpp__ */ |
41 | 41 | Scanner_Handler.hpp Trivial_Handler.hpp\ |
42 | 42 | Basic_Handler.hpp JPEG_Handler.hpp \ |
43 | 43 | MP3_Handler.hpp PNG_Handler.hpp PSD_Handler.hpp \ |
44 | TIFF_Handler.hpp WAV_Handler.hpp | |
44 | TIFF_Handler.hpp WAV_Handler.hpp GIF_Handler.hpp | |
45 | 45 | |
46 | 46 | |
47 | 47 | INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../FormatSupport \ |
58 | 58 | Trivial_Handler.cpp \ |
59 | 59 | Basic_Handler.cpp JPEG_Handler.cpp MP3_Handler.cpp \ |
60 | 60 | PNG_Handler.cpp PSD_Handler.cpp TIFF_Handler.cpp \ |
61 | WAV_Handler.cpp | |
61 | WAV_Handler.cpp GIF_Handler.cpp |
85 | 85 | MPEG_Handler.lo PostScript_Handler.lo Scanner_Handler.lo \ |
86 | 86 | Trivial_Handler.lo Basic_Handler.lo JPEG_Handler.lo \ |
87 | 87 | MP3_Handler.lo PNG_Handler.lo PSD_Handler.lo TIFF_Handler.lo \ |
88 | WAV_Handler.lo | |
88 | WAV_Handler.lo GIF_Handler.lo | |
89 | 89 | libxmpfilehandlers_la_OBJECTS = $(am_libxmpfilehandlers_la_OBJECTS) |
90 | 90 | DEFAULT_INCLUDES = -I.@am__isrc@ |
91 | 91 | depcomp = $(SHELL) $(top_srcdir)/depcomp |
228 | 228 | Scanner_Handler.hpp Trivial_Handler.hpp\ |
229 | 229 | Basic_Handler.hpp JPEG_Handler.hpp \ |
230 | 230 | MP3_Handler.hpp PNG_Handler.hpp PSD_Handler.hpp \ |
231 | TIFF_Handler.hpp WAV_Handler.hpp | |
231 | TIFF_Handler.hpp WAV_Handler.hpp GIF_Handler.hpp | |
232 | 232 | |
233 | 233 | INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../FormatSupport \ |
234 | 234 | -I$(top_srcdir)/public/include/ -I$(top_srcdir)/build/ \ |
243 | 243 | Trivial_Handler.cpp \ |
244 | 244 | Basic_Handler.cpp JPEG_Handler.cpp MP3_Handler.cpp \ |
245 | 245 | PNG_Handler.cpp PSD_Handler.cpp TIFF_Handler.cpp \ |
246 | WAV_Handler.cpp | |
246 | WAV_Handler.cpp GIF_Handler.cpp | |
247 | 247 | |
248 | 248 | all: all-am |
249 | 249 | |
298 | 298 | |
299 | 299 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AVI_Handler.Plo@am__quote@ |
300 | 300 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Basic_Handler.Plo@am__quote@ |
301 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GIF_Handler.Plo@am__quote@ | |
301 | 302 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InDesign_Handler.Plo@am__quote@ |
302 | 303 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/JPEG_Handler.Plo@am__quote@ |
303 | 304 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MP3_Handler.Plo@am__quote@ |
0 | // ================================================================================================= | |
1 | // ADOBE SYSTEMS INCORPORATED | |
2 | // Copyright 2002-2007 Adobe Systems Incorporated | |
3 | // All Rights Reserved | |
4 | // | |
5 | // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms | |
6 | // of the Adobe license agreement accompanying it. | |
7 | // | |
8 | // Derived from PNG_Support.cpp by Ian Jacobi | |
9 | // ================================================================================================= | |
10 | ||
11 | #include "GIF_Support.hpp" | |
12 | ||
13 | typedef std::basic_string<unsigned char> filebuffer; | |
14 | ||
15 | // Don't need CRC. | |
16 | ||
17 | namespace GIF_Support | |
18 | { | |
19 | // This only really counts for extension blocks. | |
20 | enum blockType { | |
21 | bGraphicControl = 0xF9, | |
22 | bComment = 0xFE, | |
23 | bPlainText = 0x01, | |
24 | bApplication = 0xFF, | |
25 | // Hacky. Don't like the following, but there's no easy way. | |
26 | bImage = 0x2C, | |
27 | bExtension = 0x21, | |
28 | bTerminator = 0x3B, | |
29 | bHeader = 0x47 | |
30 | }; | |
31 | ||
32 | // ============================================================================================= | |
33 | ||
34 | long OpenGIF ( LFA_FileRef fileRef, BlockState & inOutBlockState ) | |
35 | { | |
36 | XMP_Uns64 pos = 0; | |
37 | unsigned char name; | |
38 | XMP_Uns32 len; | |
39 | BlockData newBlock; | |
40 | ||
41 | pos = LFA_Seek ( fileRef, 0, SEEK_SET ); | |
42 | // header needs to be a block, mostly for our safe write. | |
43 | pos = ReadHeader ( fileRef ); | |
44 | if (pos < 13) return 0; | |
45 | ||
46 | newBlock.pos = 0; | |
47 | newBlock.len = pos; | |
48 | newBlock.type = bHeader; | |
49 | inOutBlockState.blocks.push_back(newBlock); | |
50 | ||
51 | // read first and following blocks | |
52 | while ( ReadBlock ( fileRef, inOutBlockState, &name, &len, pos) ) {} | |
53 | ||
54 | return inOutBlockState.blocks.size(); | |
55 | ||
56 | } | |
57 | ||
58 | // ============================================================================================= | |
59 | ||
60 | long ReadHeader ( LFA_FileRef fileRef ) | |
61 | { | |
62 | long bytesRead; | |
63 | long headerSize; | |
64 | long tableSize = 0; | |
65 | long bytesPerColor = 0; | |
66 | unsigned char buffer[256]; | |
67 | ||
68 | headerSize = 0; | |
69 | bytesRead = LFA_Read ( fileRef, buffer, GIF_SIGNATURE_LEN ); | |
70 | if ( bytesRead != GIF_SIGNATURE_LEN ) return 0; | |
71 | if ( memcmp ( buffer, GIF_SIGNATURE_DATA, GIF_SIGNATURE_LEN) != 0 ) return 0; | |
72 | headerSize += bytesRead; | |
73 | bytesRead = LFA_Read ( fileRef, buffer, 3 ); | |
74 | if ( bytesRead != 3 ) return 0; | |
75 | if ( memcmp ( buffer, "87a", 3 ) != 0 && memcmp ( buffer, "89a", 3 ) != 0 ) return 0; | |
76 | headerSize += bytesRead; | |
77 | bytesRead = LFA_Read ( fileRef, buffer, 4 ); | |
78 | if ( bytesRead != 4 ) return 0; | |
79 | headerSize += bytesRead; | |
80 | bytesRead = LFA_Read ( fileRef, buffer, 3 ); | |
81 | if ( bytesRead != 3 ) return 0; | |
82 | headerSize += bytesRead; | |
83 | if ( buffer[0] & 0x80 ) tableSize = (1 << ((buffer[0] & 0x07) + 1)) * 3; | |
84 | bytesRead = LFA_Read ( fileRef, buffer, tableSize ); | |
85 | if ( bytesRead != tableSize ) return 0; | |
86 | headerSize += bytesRead; | |
87 | ||
88 | return headerSize; | |
89 | } | |
90 | ||
91 | // ============================================================================================= | |
92 | ||
93 | bool ReadBlock ( LFA_FileRef fileRef, BlockState & inOutBlockState, unsigned char * blockType, XMP_Uns32 * blockLength, XMP_Uns64 & inOutPosition ) | |
94 | { | |
95 | try | |
96 | { | |
97 | XMP_Uns64 startPosition = inOutPosition; | |
98 | long bytesRead; | |
99 | long blockSize; | |
100 | unsigned char buffer[256]; | |
101 | ||
102 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
103 | if ( bytesRead != 1 ) return false; | |
104 | inOutPosition += 1; | |
105 | if ( buffer[0] == bImage ) | |
106 | { | |
107 | // Image is a special case. | |
108 | long tableSize = 0; | |
109 | bytesRead = LFA_Read ( fileRef, buffer, 4 ); | |
110 | if ( bytesRead != 4 ) return false; | |
111 | inOutPosition += 4; | |
112 | bytesRead = LFA_Read ( fileRef, buffer, 4 ); | |
113 | if ( bytesRead != 4 ) return false; | |
114 | inOutPosition += 4; | |
115 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
116 | if ( bytesRead != 1 ) return false; | |
117 | inOutPosition += 1; | |
118 | if ( buffer[0] & 0x80 ) tableSize = (1 << ((buffer[0] & 0x07) + 1)) * 3; | |
119 | bytesRead = LFA_Read ( fileRef, buffer, tableSize ); | |
120 | if ( bytesRead != tableSize ) return 0; | |
121 | inOutPosition += tableSize; | |
122 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
123 | if ( bytesRead != 1 ) return false; | |
124 | inOutPosition += 1; | |
125 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
126 | if ( bytesRead != 1 ) return false; | |
127 | inOutPosition += 1; | |
128 | tableSize = buffer[0]; | |
129 | while ( tableSize != 0x00 ) | |
130 | { | |
131 | bytesRead = LFA_Read ( fileRef, buffer, tableSize ); | |
132 | if ( bytesRead != tableSize ) return false; | |
133 | inOutPosition += tableSize; | |
134 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
135 | if ( bytesRead != 1 ) return false; | |
136 | inOutPosition += 1; | |
137 | tableSize = buffer[0]; | |
138 | } | |
139 | ||
140 | BlockData newBlock; | |
141 | ||
142 | newBlock.pos = startPosition; | |
143 | newBlock.len = inOutPosition - startPosition; | |
144 | newBlock.type = bImage; | |
145 | ||
146 | inOutBlockState.blocks.push_back ( newBlock ); | |
147 | } | |
148 | else if ( buffer[0] == bExtension ) | |
149 | { | |
150 | unsigned char type; | |
151 | long tableSize = 0; | |
152 | ||
153 | BlockData newBlock; | |
154 | ||
155 | newBlock.pos = startPosition; | |
156 | ||
157 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
158 | if ( bytesRead != 1 ) return false; | |
159 | inOutPosition += 1; | |
160 | type = buffer[0]; | |
161 | newBlock.type = type; | |
162 | ||
163 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
164 | if ( bytesRead != 1 ) return false; | |
165 | inOutPosition += 1; | |
166 | tableSize = buffer[0]; | |
167 | while ( tableSize != 0x00 ) | |
168 | { | |
169 | bytesRead = LFA_Read ( fileRef, buffer, tableSize ); | |
170 | if ( bytesRead != tableSize ) return false; | |
171 | inOutPosition += tableSize; | |
172 | if ( inOutPosition - startPosition == 14 && type == bApplication ) | |
173 | { | |
174 | // Check for XMP identifier... | |
175 | CheckApplicationBlockHeader ( fileRef, inOutBlockState, newBlock, inOutPosition ); | |
176 | ||
177 | if ( newBlock.xmp == true ) | |
178 | { | |
179 | newBlock.len = inOutPosition - startPosition; | |
180 | ||
181 | inOutBlockState.blocks.push_back ( newBlock ); | |
182 | ||
183 | return true; | |
184 | } | |
185 | } | |
186 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
187 | if ( bytesRead != 1 ) return false; | |
188 | inOutPosition += 1; | |
189 | tableSize = buffer[0]; | |
190 | } | |
191 | ||
192 | newBlock.len = inOutPosition - startPosition; | |
193 | ||
194 | inOutBlockState.blocks.push_back ( newBlock ); | |
195 | } | |
196 | else if ( buffer[0] == bTerminator ) | |
197 | { | |
198 | BlockData newBlock; | |
199 | ||
200 | newBlock.pos = startPosition; | |
201 | newBlock.len = 1; | |
202 | newBlock.type = buffer[0]; | |
203 | ||
204 | inOutBlockState.blocks.push_back ( newBlock ); | |
205 | } | |
206 | ||
207 | } catch ( ... ) { | |
208 | ||
209 | return false; | |
210 | ||
211 | } | |
212 | ||
213 | return true; | |
214 | ||
215 | } | |
216 | ||
217 | // ============================================================================================= | |
218 | ||
219 | bool WriteXMPBlock ( LFA_FileRef fileRef, XMP_Uns32 len, const char* inBuffer ) | |
220 | { | |
221 | bool ret = false; | |
222 | unsigned long datalen = (APPLICATION_HEADER_LEN + len + MAGIC_TRAILER_LEN); | |
223 | unsigned char* buffer = new unsigned char[datalen]; | |
224 | ||
225 | try | |
226 | { | |
227 | size_t pos = 0; | |
228 | memcpy(&buffer[pos], APPLICATION_HEADER_DATA, APPLICATION_HEADER_LEN); | |
229 | pos += APPLICATION_HEADER_LEN; | |
230 | memcpy(&buffer[pos], inBuffer, len); | |
231 | pos += len; | |
232 | memcpy(&buffer[pos], MAGIC_TRAILER_DATA, MAGIC_TRAILER_LEN); | |
233 | ||
234 | LFA_Write(fileRef, buffer, datalen); | |
235 | ||
236 | ret = true; | |
237 | } | |
238 | catch ( ... ) {} | |
239 | ||
240 | delete [] buffer; | |
241 | ||
242 | return ret; | |
243 | } | |
244 | ||
245 | // ============================================================================================= | |
246 | ||
247 | bool CopyBlock ( LFA_FileRef sourceRef, LFA_FileRef destRef, BlockData& block ) | |
248 | { | |
249 | try | |
250 | { | |
251 | LFA_Seek (sourceRef, block.pos, SEEK_SET ); | |
252 | LFA_Copy (sourceRef, destRef, (block.len)); | |
253 | ||
254 | } catch ( ... ) { | |
255 | ||
256 | return false; | |
257 | ||
258 | } | |
259 | ||
260 | return true; | |
261 | } | |
262 | ||
263 | // ============================================================================================= | |
264 | ||
265 | // Don't need CRC. | |
266 | ||
267 | // ============================================================================================= | |
268 | ||
269 | unsigned long CheckApplicationBlockHeader ( LFA_FileRef fileRef, BlockState& inOutBlockState, BlockData& inOutBlockData, XMP_Uns64& inOutPosition ) | |
270 | { | |
271 | try | |
272 | { | |
273 | LFA_Seek(fileRef, (inOutBlockData.pos), SEEK_SET); | |
274 | ||
275 | unsigned char buffer[256]; | |
276 | long bytesRead = LFA_Read ( fileRef, buffer, APPLICATION_HEADER_LEN ); | |
277 | ||
278 | if (bytesRead == APPLICATION_HEADER_LEN) | |
279 | { | |
280 | if (memcmp(buffer, APPLICATION_HEADER_DATA, APPLICATION_HEADER_LEN) == 0) | |
281 | { | |
282 | // We still have to go through all of the data... | |
283 | long tableSize = 0; | |
284 | long xmpSize; | |
285 | ||
286 | inOutPosition = inOutBlockData.pos + APPLICATION_HEADER_LEN; | |
287 | inOutBlockState.xmpPos = inOutPosition; | |
288 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
289 | if ( bytesRead != 1 ) return 0; | |
290 | inOutPosition += 1; | |
291 | tableSize = buffer[0]; | |
292 | while ( tableSize != 0x00 ) | |
293 | { | |
294 | bytesRead = LFA_Read ( fileRef, buffer, tableSize ); | |
295 | if ( bytesRead != tableSize ) return false; | |
296 | inOutPosition += tableSize; | |
297 | bytesRead = LFA_Read ( fileRef, buffer, 1 ); | |
298 | if ( bytesRead != 1 ) return false; | |
299 | inOutPosition += 1; | |
300 | tableSize = buffer[0]; | |
301 | } | |
302 | inOutBlockState.xmpLen = inOutPosition - inOutBlockData.pos - APPLICATION_HEADER_LEN - MAGIC_TRAILER_LEN; | |
303 | inOutBlockState.xmpBlock = inOutBlockData; | |
304 | inOutBlockData.xmp = true; | |
305 | } | |
306 | } | |
307 | } | |
308 | catch ( ... ) {} | |
309 | ||
310 | return 0; | |
311 | } | |
312 | ||
313 | bool ReadBuffer ( LFA_FileRef fileRef, XMP_Uns64 & pos, XMP_Uns32 len, char * outBuffer ) | |
314 | { | |
315 | try | |
316 | { | |
317 | if ( (fileRef == 0) || (outBuffer == 0) ) return false; | |
318 | ||
319 | LFA_Seek (fileRef, pos, SEEK_SET ); | |
320 | long bytesRead = LFA_Read ( fileRef, outBuffer, len ); | |
321 | if ( XMP_Uns32(bytesRead) != len ) return false; | |
322 | ||
323 | return true; | |
324 | } | |
325 | catch ( ... ) {} | |
326 | ||
327 | return false; | |
328 | } | |
329 | ||
330 | bool WriteBuffer ( LFA_FileRef fileRef, XMP_Uns64 & pos, XMP_Uns32 len, const char * inBuffer ) | |
331 | { | |
332 | try | |
333 | { | |
334 | if ( (fileRef == 0) || (inBuffer == 0) ) return false; | |
335 | ||
336 | LFA_Seek (fileRef, pos, SEEK_SET ); | |
337 | LFA_Write( fileRef, inBuffer, len ); | |
338 | ||
339 | return true; | |
340 | } | |
341 | catch ( ... ) {} | |
342 | ||
343 | return false; | |
344 | } | |
345 | ||
346 | } // namespace GIF_Support |
0 | #ifndef __GIF_Support_hpp__ | |
1 | #define __GIF_Support_hpp__ 1 | |
2 | ||
3 | // ================================================================================================= | |
4 | // ADOBE SYSTEMS INCORPORATED | |
5 | // Copyright 2002-2007 Adobe Systems Incorporated | |
6 | // All Rights Reserved | |
7 | // | |
8 | // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms | |
9 | // of the Adobe license agreement accompanying it | |
10 | // | |
11 | // Derived from PNG_Support.hpp by Ian Jacobi | |
12 | // ================================================================================================= | |
13 | ||
14 | #include "XMP_Environment.h" // ! This must be the first include. | |
15 | ||
16 | #include "XMPFiles_Impl.hpp" | |
17 | ||
18 | #define GIF_SIGNATURE_LEN 3 | |
19 | #define GIF_SIGNATURE_DATA "\x47\x49\x46" | |
20 | ||
21 | #define APPLICATION_HEADER_LEN 14 | |
22 | #define APPLICATION_HEADER_DATA "\x21\xFF\x0B\x58\x4D\x50\x20\x44\x61\x74\x61\x58\x4D\x50" | |
23 | ||
24 | #define MAGIC_TRAILER_LEN 258 | |
25 | #define MAGIC_TRAILER_DATA "\x01\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8\xF7\xF6\xF5\xF4\xF3\xF2\xF1\xF0\xEF\xEE\xED\xEC\xEB\xEA\xE9\xE8\xE7\xE6\xE5\xE4\xE3\xE2\xE1\xE0\xDF\xDE\xDD\xDC\xDB\xDA\xD9\xD8\xD7\xD6\xD5\xD4\xD3\xD2\xD1\xD0\xCF\xCE\xCD\xCC\xCB\xCA\xC9\xC8\xC7\xC6\xC5\xC4\xC3\xC2\xC1\xC0\xBF\xBE\xBD\xBC\xBB\xBA\xB9\xB8\xB7\xB6\xB5\xB4\xB3\xB2\xB1\xB0\xAF\xAE\xAD\xAC\xAB\xAA\xA9\xA8\xA7\xA6\xA5\xA4\xA3\xA2\xA1\xA0\x9F\x9E\x9D\x9C\x9B\x9A\x99\x98\x97\x96\x95\x94\x93\x92\x91\x90\x8F\x8E\x8D\x8C\x8B\x8A\x89\x88\x87\x86\x85\x84\x83\x82\x81\x80\x7F\x7E\x7D\x7C\x7B\x7A\x79\x78\x77\x76\x75\x74\x73\x72\x71\x70\x6F\x6E\x6D\x6C\x6B\x6A\x69\x68\x67\x66\x65\x64\x63\x62\x61\x60\x5F\x5E\x5D\x5C\x5B\x5A\x59\x58\x57\x56\x55\x54\x53\x52\x51\x50\x4F\x4E\x4D\x4C\x4B\x4A\x49\x48\x47\x46\x45\x44\x43\x42\x41\x40\x3F\x3E\x3D\x3C\x3B\x3A\x39\x38\x37\x36\x35\x34\x33\x32\x31\x30\x2F\x2E\x2D\x2C\x2B\x2A\x29\x28\x27\x26\x25\x24\x23\x22\x21\x20\x1F\x1E\x1D\x1C\x1B\x1A\x19\x18\x17\x16\x15\x14\x13\x12\x11\x10\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00\x00" | |
26 | ||
27 | namespace GIF_Support | |
28 | { | |
29 | class BlockData | |
30 | { | |
31 | public: | |
32 | BlockData() : pos(0), len(0), type(0), xmp(false) {} | |
33 | virtual ~BlockData() {} | |
34 | ||
35 | XMP_Uns64 pos; // file offset of block | |
36 | XMP_Uns32 len; // length of block data, including extension introducer and label | |
37 | char type; // name/type of block | |
38 | bool xmp; // application extension block with XMP ? | |
39 | }; | |
40 | ||
41 | typedef std::vector<BlockData> BlockVector; | |
42 | typedef BlockVector::iterator BlockIterator; | |
43 | ||
44 | class BlockState | |
45 | { | |
46 | public: | |
47 | BlockState() : xmpPos(0), xmpLen(0) {} | |
48 | virtual ~BlockState() {} | |
49 | ||
50 | XMP_Uns64 xmpPos; | |
51 | XMP_Uns32 xmpLen; | |
52 | BlockData xmpBlock; | |
53 | BlockVector blocks; /* vector of blocks */ | |
54 | }; | |
55 | ||
56 | long OpenGIF ( LFA_FileRef fileRef, BlockState& inOutBlockState ); | |
57 | ||
58 | long ReadHeader ( LFA_FileRef fileRef ); | |
59 | bool ReadBlock ( LFA_FileRef fileRef, BlockState& inOutBlockState, unsigned char* blockType, XMP_Uns32* blockLength, XMP_Uns64& inOutPosition ); | |
60 | bool WriteXMPBlock ( LFA_FileRef fileRef, XMP_Uns32 len, const char* inBuffer ); | |
61 | bool CopyBlock ( LFA_FileRef sourceRef, LFA_FileRef destRef, BlockData& block ); | |
62 | ||
63 | unsigned long CheckApplicationBlockHeader ( LFA_FileRef fileRef, BlockState& inOutBlockState, BlockData& inOutBlockData, XMP_Uns64& inOutPosition ); | |
64 | ||
65 | bool ReadBuffer ( LFA_FileRef fileRef, XMP_Uns64& pos, XMP_Uns32 len, char* outBuffer ); | |
66 | bool WriteBuffer ( LFA_FileRef fileRef, XMP_Uns64& pos, XMP_Uns32 len, const char* inBuffer ); | |
67 | ||
68 | } // namespace GIF_Support | |
69 | ||
70 | #endif // __GIF_Support_hpp__ |
37 | 37 | noinst_HEADERS = EndianUtils.hpp IPTC_Support.hpp PSIR_Support.hpp\ |
38 | 38 | Reconcile_Impl.hpp RIFF_Support.hpp XMPScanner.hpp\ |
39 | 39 | ID3_Support.hpp PNG_Support.hpp QuickTime_Support.hpp\ |
40 | ReconcileLegacy.hpp TIFF_Support.hpp | |
40 | ReconcileLegacy.hpp TIFF_Support.hpp GIF_Support.hpp | |
41 | 41 | |
42 | 42 | |
43 | 43 | INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../common \ |
56 | 56 | IPTC_Support.cpp PSIR_MemoryReader.cpp ReconcileIPTC.cpp \ |
57 | 57 | RIFF_Support.cpp TIFF_Support.cpp \ |
58 | 58 | PNG_Support.cpp ReconcileLegacy.cpp \ |
59 | TIFF_FileWriter.cpp XMPScanner.cpp⏎ | |
59 | TIFF_FileWriter.cpp XMPScanner.cpp GIF_Support.cpp⏎ |
85 | 85 | Reconcile_Impl.lo ReconcileTIFF.lo TIFF_MemoryReader.lo \ |
86 | 86 | IPTC_Support.lo PSIR_MemoryReader.lo ReconcileIPTC.lo \ |
87 | 87 | RIFF_Support.lo TIFF_Support.lo PNG_Support.lo \ |
88 | ReconcileLegacy.lo TIFF_FileWriter.lo XMPScanner.lo | |
88 | ReconcileLegacy.lo TIFF_FileWriter.lo XMPScanner.lo \ | |
89 | GIF_Support.lo | |
89 | 90 | libformatsupport_la_OBJECTS = $(am_libformatsupport_la_OBJECTS) |
90 | 91 | DEFAULT_INCLUDES = -I.@am__isrc@ |
91 | 92 | depcomp = $(SHELL) $(top_srcdir)/depcomp |
226 | 227 | noinst_HEADERS = EndianUtils.hpp IPTC_Support.hpp PSIR_Support.hpp\ |
227 | 228 | Reconcile_Impl.hpp RIFF_Support.hpp XMPScanner.hpp\ |
228 | 229 | ID3_Support.hpp PNG_Support.hpp QuickTime_Support.hpp\ |
229 | ReconcileLegacy.hpp TIFF_Support.hpp | |
230 | ReconcileLegacy.hpp TIFF_Support.hpp GIF_Support.hpp | |
230 | 231 | |
231 | 232 | INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../common \ |
232 | 233 | -I$(top_srcdir)/public/include/ -I$(top_srcdir)/build/ \ |
241 | 242 | IPTC_Support.cpp PSIR_MemoryReader.cpp ReconcileIPTC.cpp \ |
242 | 243 | RIFF_Support.cpp TIFF_Support.cpp \ |
243 | 244 | PNG_Support.cpp ReconcileLegacy.cpp \ |
244 | TIFF_FileWriter.cpp XMPScanner.cpp | |
245 | TIFF_FileWriter.cpp XMPScanner.cpp GIF_Support.cpp | |
245 | 246 | |
246 | 247 | all: all-am |
247 | 248 | |
294 | 295 | distclean-compile: |
295 | 296 | -rm -f *.tab.c |
296 | 297 | |
298 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GIF_Support.Plo@am__quote@ | |
297 | 299 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ID3_Support.Plo@am__quote@ |
298 | 300 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IPTC_Support.Plo@am__quote@ |
299 | 301 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PNG_Support.Plo@am__quote@ |
30 | 30 | #include "FileHandlers/PNG_Handler.hpp" |
31 | 31 | #include "FileHandlers/AVI_Handler.hpp" |
32 | 32 | #include "FileHandlers/WAV_Handler.hpp" |
33 | #include "FileHandlers/GIF_Handler.hpp" | |
33 | 34 | |
34 | 35 | // ================================================================================================= |
35 | 36 | /// \file XMPFiles.cpp |
223 | 224 | |
224 | 225 | XMP_Assert ( ! (kMP3_HandlerFlags & kXMPFiles_HandlerOwnsFile) ); |
225 | 226 | RegisterXMPFileHandler ( kXMP_MP3File, kMP3_HandlerFlags, MP3_CheckFormat, MP3_MetaHandlerCTor ); |
227 | ||
228 | XMP_Assert ( ! (kGIF_HandlerFlags & kXMPFiles_HandlerOwnsFile) ); | |
229 | RegisterXMPFileHandler ( kXMP_GIFFile, kGIF_HandlerFlags, GIF_CheckFormat, GIF_MetaHandlerCTor ); | |
226 | 230 | |
227 | 231 | #if XMP_WinBuild |
228 | 232 |
126 | 126 | { "", 0 } }; // ! Must be last as a sentinel. |
127 | 127 | |
128 | 128 | const char * kKnownScannedFiles[] = // Files known to contain XMP but have no smart handling, here or elsewhere. |
129 | { "gif", // GIF, public format but no smart handler. | |
130 | "ai", // Illustrator, actually a PDF file. | |
129 | { "ai", // Illustrator, actually a PDF file. | |
131 | 130 | "ait", // Illustrator template, actually a PDF file. |
132 | 131 | "svg", // SVG, an XML file. |
133 | 132 | "aet", // After Effects template project file. |