Module: wine Branch: master Commit: 1a032a94df301286a6c13ee3b2654e7ba1cbc893 URL: http://source.winehq.org/git/wine.git/?a=commit;h=1a032a94df301286a6c13ee3b2...
Author: Vincent Povirk vincent@codeweavers.com Date: Mon Sep 10 17:01:15 2012 -0500
windowscodecs: Implement PNG tEXt metadata reader.
---
dlls/windowscodecs/clsfactory.c | 1 + dlls/windowscodecs/metadatahandler.c | 7 ++- dlls/windowscodecs/pngformat.c | 112 +++++++++++++++++++++++++ dlls/windowscodecs/regsvr.c | 25 ++++++ dlls/windowscodecs/tests/metadata.c | 2 +- dlls/windowscodecs/wincodecs_private.h | 4 + dlls/windowscodecs/windowscodecs_wincodec.idl | 7 ++ 7 files changed, 156 insertions(+), 2 deletions(-)
diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c index 40d1547..91c75b7 100644 --- a/dlls/windowscodecs/clsfactory.c +++ b/dlls/windowscodecs/clsfactory.c @@ -61,6 +61,7 @@ static const classinfo wic_classes[] = { {&CLSID_WineTgaDecoder, TgaDecoder_CreateInstance}, {&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance}, {&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance}, + {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance}, {0}};
typedef struct { diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 084facf..5e50cb9 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -255,6 +255,11 @@ static int propvar_cmp(const PROPVARIANT *v1, const PROPVARIANT *v2) { LONGLONG value1, value2;
+ if (v1->vt == VT_LPSTR && v2->vt == VT_LPSTR) + { + return lstrcmpA(v1->u.pszVal, v2->u.pszVal); + } + if (!get_int_value(v1, &value1)) return -1; if (!get_int_value(v2, &value2)) return -1;
@@ -446,7 +451,7 @@ static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl = { MetadataHandler_SaveEx };
-static HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkOuter, REFIID iid, void** ppv) +HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkOuter, REFIID iid, void** ppv) { MetadataHandler *This; HRESULT hr; diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 683da2d..3eae4b7 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -40,6 +40,118 @@
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+static HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size) +{ + BYTE header[8]; + HRESULT hr; + ULONG bytesread; + + hr = IStream_Read(stream, header, 8, &bytesread); + if (FAILED(hr) || bytesread < 8) + { + if (SUCCEEDED(hr)) + hr = E_FAIL; + return hr; + } + + *data_size = header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3]; + + memcpy(type, &header[4], 4); + + if (data) + { + *data = HeapAlloc(GetProcessHeap(), 0, *data_size); + if (!*data) + return E_OUTOFMEMORY; + + hr = IStream_Read(stream, *data, *data_size, &bytesread); + + if (FAILED(hr) || bytesread < *data_size) + { + if (SUCCEEDED(hr)) + hr = E_FAIL; + HeapFree(GetProcessHeap(), 0, *data); + *data = NULL; + return hr; + } + + /* FIXME: Verify the CRC? */ + } + + return S_OK; +} + +static HRESULT LoadTextMetadata(IStream *stream, const GUID *preferred_vendor, + DWORD persist_options, MetadataItem **items, DWORD *item_count) +{ + HRESULT hr; + BYTE type[4]; + BYTE *data; + ULONG data_size; + ULONG name_len, value_len; + BYTE *name_end_ptr; + LPSTR name, value; + MetadataItem *result; + + hr = read_png_chunk(stream, type, &data, &data_size); + if (FAILED(hr)) return hr; + + name_end_ptr = memchr(data, 0, data_size); + + name_len = name_end_ptr - data; + + if (!name_end_ptr || name_len > 79) + { + HeapFree(GetProcessHeap(), 0, data); + return E_FAIL; + } + + value_len = data_size - name_len - 1; + + result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem)); + name = HeapAlloc(GetProcessHeap(), 0, name_len + 1); + value = HeapAlloc(GetProcessHeap(), 0, value_len + 1); + if (!result || !name || !value) + { + HeapFree(GetProcessHeap(), 0, data); + HeapFree(GetProcessHeap(), 0, result); + HeapFree(GetProcessHeap(), 0, name); + HeapFree(GetProcessHeap(), 0, value); + return E_OUTOFMEMORY; + } + + PropVariantInit(&result[0].schema); + PropVariantInit(&result[0].id); + PropVariantInit(&result[0].value); + + memcpy(name, data, name_len + 1); + memcpy(value, name_end_ptr + 1, value_len); + value[value_len] = 0; + + result[0].id.vt = VT_LPSTR; + result[0].id.pszVal = name; + result[0].value.vt = VT_LPSTR; + result[0].value.pszVal = value; + + *items = result; + *item_count = 1; + + HeapFree(GetProcessHeap(), 0, data); + + return S_OK; +} + +static const MetadataHandlerVtbl TextReader_Vtbl = { + 0, + &CLSID_WICPngTextMetadataReader, + LoadTextMetadata +}; + +HRESULT PngTextReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) +{ + return MetadataReader_Create(&TextReader_Vtbl, pUnkOuter, iid, ppv); +} + #ifdef SONAME_LIBPNG
static void *libpng_handle; diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index a422747..cb11430 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1503,6 +1503,21 @@ static const struct reader_containers ifd_containers[] = { { NULL } /* list terminator */ };
+static const BYTE tEXt[] = "tEXt"; + +static const struct metadata_pattern pngtext_metadata_pattern[] = { + { 4, 4, tEXt, mask_all, 4 }, + { 0 } +}; + +static const struct reader_containers pngtext_containers[] = { + { + &GUID_ContainerFormatPng, + pngtext_metadata_pattern + }, + { NULL } /* list terminator */ +}; + static struct regsvr_metadatareader const metadatareader_list[] = { { &CLSID_WICUnknownMetadataReader, "The Wine Project", @@ -1525,6 +1540,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = { 1, 1, 0, ifd_containers }, + { &CLSID_WICPngTextMetadataReader, + "The Wine Project", + "Unknown Metadata Reader", + "1.0.0.0", + "1.0.0.0", + &GUID_VendorMicrosoft, + &GUID_MetadataFormatChunktEXt, + 0, 0, 0, + pngtext_containers + }, { NULL } /* list terminator */ };
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 4bb33ae..229753c 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -303,7 +303,7 @@ static void test_metadata_tEXt(void)
hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER, &IID_IWICMetadataReader, (void**)&reader); - todo_wine ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); + ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); if (FAILED(hr)) return;
hr = IWICMetadataReader_GetCount(reader, NULL); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 0bee818..37f9c90 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -90,7 +90,11 @@ typedef struct _MetadataHandlerVtbl ULARGE_INTEGER *size); } MetadataHandlerVtbl;
+extern HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkOuter, REFIID iid, void** ppv) DECLSPEC_HIDDEN; + extern HRESULT UnknownMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) DECLSPEC_HIDDEN; extern HRESULT IfdMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) DECLSPEC_HIDDEN;
+extern HRESULT PngTextReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) DECLSPEC_HIDDEN; + #endif /* WINCODECS_PRIVATE_H */ diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl index bc4c994..6d5bd2d 100644 --- a/dlls/windowscodecs/windowscodecs_wincodec.idl +++ b/dlls/windowscodecs/windowscodecs_wincodec.idl @@ -135,3 +135,10 @@ coclass WICUnknownMetadataReader { interface IWICMetadataReader; } uuid(8f914656-9d0a-4eb2-9019-0bf96d8a9ee6) ] coclass WICIfdMetadataReader { interface IWICIfdMetadataReader; } + +[ + helpstring("WIC Png tEXt Metadata Reader"), + threading(both), + uuid(4b59afcc-b8c3-408a-b670-89e5fab6fda7) +] +coclass WICPngTextMetadataReader { interface IWICMetadataReader; }