From 500ab2b5c7d17d8ba42cc90ecb9fc2455e603af8 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Tue, 11 Sep 2012 16:48:37 +0900 Subject: [PATCH] windowscodecs: Implement Logical Screen Descriptor metadata reader. --- dlls/windowscodecs/clsfactory.c | 1 + dlls/windowscodecs/gifformat.c | 111 ++++++++++++++++++ dlls/windowscodecs/regsvr.c | 27 ++++- dlls/windowscodecs/tests/metadata.c | 1 - dlls/windowscodecs/wincodecs_private.h | 2 +- dlls/windowscodecs/windowscodecs_wincodec.idl | 7 ++ 6 files changed, 145 insertions(+), 4 deletions(-) diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c index 91c75b77b83..3f1328ccae4 100644 --- a/dlls/windowscodecs/clsfactory.c +++ b/dlls/windowscodecs/clsfactory.c @@ -62,6 +62,7 @@ static const classinfo wic_classes[] = { {&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance}, {&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance}, {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance}, + {&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance}, {0}}; typedef struct { diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index 17de9aa26bb..c4ee5668f0e 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -21,11 +21,13 @@ #include #define COBJMACROS +#define NONAMELESSUNION #include "windef.h" #include "winbase.h" #include "objbase.h" #include "wincodec.h" +#include "wincodecsdk.h" #include "ungif.h" @@ -35,6 +37,115 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); +static LPWSTR strdupAtoW(const char *src) +{ + int len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); + LPWSTR dst = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (dst) MultiByteToWideChar(CP_ACP, 0, src, -1, dst, len); + return dst; +} + +static HRESULT load_LSD_metadata(IStream *stream, const GUID *vendor, DWORD options, + MetadataItem **items, DWORD *count) +{ + struct logical_screen_descriptor + { + char signature[6]; + USHORT width; + USHORT height; + BYTE packed; + /* global_color_table_flag : 1; + * color_resolution : 3; + * sort_flag : 1; + * global_color_table_size : 3; + */ + BYTE background_color_index; + BYTE pixel_aspect_ratio; + } lsd_data; + HRESULT hr; + ULONG bytesread, i; + MetadataItem *result; + + *items = NULL; + *count = 0; + + hr = IStream_Read(stream, &lsd_data, sizeof(lsd_data), &bytesread); + if (FAILED(hr) || bytesread != sizeof(lsd_data)) return S_OK; + + result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem) * 9); + if (!result) return E_OUTOFMEMORY; + + for (i = 0; i < 9; i++) + { + PropVariantInit(&result[i].schema); + PropVariantInit(&result[i].id); + PropVariantInit(&result[i].value); + } + + result[0].id.vt = VT_LPWSTR; + result[0].id.u.pwszVal = strdupAtoW("Signature"); + result[0].value.vt = VT_UI1|VT_VECTOR; + result[0].value.u.caub.cElems = 6; + result[0].value.u.caub.pElems = HeapAlloc(GetProcessHeap(), 0, sizeof(lsd_data.signature)); + memcpy(result[0].value.u.caub.pElems, lsd_data.signature, sizeof(lsd_data.signature)); + + result[1].id.vt = VT_LPWSTR; + result[1].id.u.pwszVal = strdupAtoW("Width"); + result[1].value.vt = VT_UI2; + result[1].value.u.uiVal = lsd_data.width; + + result[2].id.vt = VT_LPWSTR; + result[2].id.u.pwszVal = strdupAtoW("Height"); + result[2].value.vt = VT_UI2; + result[2].value.u.uiVal = lsd_data.height; + + result[3].id.vt = VT_LPWSTR; + result[3].id.u.pwszVal = strdupAtoW("GlobalColorTableFlag"); + result[3].value.vt = VT_BOOL; + result[3].value.u.boolVal = (lsd_data.packed >> 7) & 1; + + result[4].id.vt = VT_LPWSTR; + result[4].id.u.pwszVal = strdupAtoW("ColorResolution"); + result[4].value.vt = VT_UI1; + result[4].value.u.bVal = (lsd_data.packed >> 6) & 7; + + result[5].id.vt = VT_LPWSTR; + result[5].id.u.pwszVal = strdupAtoW("SortFlag"); + result[5].value.vt = VT_BOOL; + result[5].value.u.boolVal = (lsd_data.packed >> 3) & 1; + + result[6].id.vt = VT_LPWSTR; + result[6].id.u.pwszVal = strdupAtoW("GlobalColorTableSize"); + result[6].value.vt = VT_UI1; + result[6].value.u.bVal = lsd_data.packed & 7; + + result[7].id.vt = VT_LPWSTR; + result[7].id.u.pwszVal = strdupAtoW("BackgroundColorIndex"); + result[7].value.vt = VT_UI1; + result[7].value.u.bVal = lsd_data.background_color_index; + + result[8].id.vt = VT_LPWSTR; + result[8].id.u.pwszVal = strdupAtoW("PixelAspectRatio"); + result[8].value.vt = VT_UI1; + result[8].value.u.bVal = lsd_data.pixel_aspect_ratio; + + *items = result; + *count = 9; + + return S_OK; +} + +static const MetadataHandlerVtbl LSDReader_Vtbl = { + 0, + &CLSID_WICLSDMetadataReader, + load_LSD_metadata +}; + +HRESULT LSDReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) +{ + return MetadataReader_Create(&LSDReader_Vtbl, pUnkOuter, iid, ppv); +} + typedef struct { IWICBitmapDecoder IWICBitmapDecoder_iface; LONG ref; diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 3fa2df3404d..cb48d639a14 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1518,6 +1518,20 @@ static const struct reader_containers pngtext_containers[] = { { NULL } /* list terminator */ }; +static const struct metadata_pattern lsd_metadata_patterns[] = { + { 0, 6, gif87a_magic, mask_all, 0 }, + { 0, 6, gif89a_magic, mask_all, 0 }, + { 0 } +}; + +static const struct reader_containers lsd_containers[] = { + { + &GUID_ContainerFormatGif, + lsd_metadata_patterns + }, + { NULL } /* list terminator */ +}; + static struct regsvr_metadatareader const metadatareader_list[] = { { &CLSID_WICUnknownMetadataReader, "The Wine Project", @@ -1529,8 +1543,7 @@ static struct regsvr_metadatareader const metadatareader_list[] = { 0, 0, 0, NULL }, - { - &CLSID_WICIfdMetadataReader, + { &CLSID_WICIfdMetadataReader, "The Wine Project", "Ifd Reader", "1.0.0.0", @@ -1550,6 +1563,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = { 0, 0, 0, pngtext_containers }, + { &CLSID_WICLSDMetadataReader, + "The Wine Project", + "Logical Screen Descriptor Reader", + "1.0.0.0", + "1.0.0.0", + &GUID_VendorMicrosoft, + &GUID_MetadataFormatLSD, + 0, 0, 0, + lsd_containers + }, { NULL } /* list terminator */ }; diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 229753cf99f..fd81e6f088d 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -1287,7 +1287,6 @@ static void test_metadata_LSD(void) hr = CoCreateInstance(&CLSID_WICLSDMetadataReader, NULL, CLSCTX_INPROC_SERVER, &IID_IWICMetadataReader, (void **)&reader); -todo_wine ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */, "CoCreateInstance error %#x\n", hr); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 37f9c906e67..908b2e60fc3 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -94,7 +94,7 @@ extern HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown 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; +extern HRESULT LSDReader_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 6d5bd2d1a93..d360ae50bab 100644 --- a/dlls/windowscodecs/windowscodecs_wincodec.idl +++ b/dlls/windowscodecs/windowscodecs_wincodec.idl @@ -142,3 +142,10 @@ coclass WICIfdMetadataReader { interface IWICIfdMetadataReader; } uuid(4b59afcc-b8c3-408a-b670-89e5fab6fda7) ] coclass WICPngTextMetadataReader { interface IWICMetadataReader; } + +[ + helpstring("WIC LSD Metadata Reader"), + threading(both), + uuid(41070793-59e4-479a-a1f7-954adc2ef5fc) +] +coclass WICLSDMetadataReader { interface IWICMetadataReader; }