Module: wine Branch: master Commit: 5373f8520d2fec729730aaa6a3278cefa46f9414 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5373f8520d2fec729730aaa6a3...
Author: Dmitry Timoshkov dmitry@baikal.ru Date: Wed Sep 12 15:09:09 2012 +0900
windowscodecs: Create Logical Screen Descriptor metadata for the GIF decoder.
---
dlls/windowscodecs/gifformat.c | 136 +++++++++++++++++++++++++++++++++++ dlls/windowscodecs/tests/metadata.c | 2 - 2 files changed, 136 insertions(+), 2 deletions(-)
diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index a224356..66c56a8 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -1,5 +1,6 @@ /* * Copyright 2009 Vincent Povirk for CodeWeavers + * Copyright 2012 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -322,8 +323,28 @@ HRESULT GCEReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) return MetadataReader_Create(&GCEReader_Vtbl, pUnkOuter, iid, ppv); }
+static IStream *create_stream(const void *data, int data_size) +{ + HRESULT hr; + IStream *stream; + HGLOBAL hdata; + void *locked_data; + + hdata = GlobalAlloc(GMEM_MOVEABLE, data_size); + if (!hdata) return NULL; + + locked_data = GlobalLock(hdata); + memcpy(locked_data, data, data_size); + GlobalUnlock(hdata); + + hr = CreateStreamOnHGlobal(hdata, TRUE, &stream); + return FAILED(hr) ? NULL : stream; +} + typedef struct { IWICBitmapDecoder IWICBitmapDecoder_iface; + IWICMetadataBlockReader IWICMetadataBlockReader_iface; + BYTE LSD_data[13]; /* Logical Screen Descriptor */ LONG ref; BOOL initialized; GifFileType *gif; @@ -342,6 +363,11 @@ static inline GifDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) return CONTAINING_RECORD(iface, GifDecoder, IWICBitmapDecoder_iface); }
+static inline GifDecoder *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface) +{ + return CONTAINING_RECORD(iface, GifDecoder, IWICMetadataBlockReader_iface); +} + static inline GifFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface) { return CONTAINING_RECORD(iface, GifFrameDecode, IWICBitmapFrameDecode_iface); @@ -591,6 +617,10 @@ static HRESULT WINAPI GifDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID { *ppv = &This->IWICBitmapDecoder_iface; } + else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid)) + { + *ppv = &This->IWICMetadataBlockReader_iface; + } else { *ppv = NULL; @@ -692,6 +722,10 @@ static HRESULT WINAPI GifDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p /* make sure we don't use the stream after this method returns */ This->gif->UserData = NULL;
+ seek.QuadPart = 0; + IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL); + IStream_Read(pIStream, &This->LSD_data, sizeof(This->LSD_data), NULL); + This->initialized = TRUE;
LeaveCriticalSection(&This->lock); @@ -817,6 +851,107 @@ static const IWICBitmapDecoderVtbl GifDecoder_Vtbl = { GifDecoder_GetFrame };
+static HRESULT WINAPI GifDecoder_Block_QueryInterface(IWICMetadataBlockReader *iface, + REFIID iid, void **ppv) +{ + GifDecoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv); +} + +static ULONG WINAPI GifDecoder_Block_AddRef(IWICMetadataBlockReader *iface) +{ + GifDecoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface); +} + +static ULONG WINAPI GifDecoder_Block_Release(IWICMetadataBlockReader *iface) +{ + GifDecoder *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); +} + +static HRESULT WINAPI GifDecoder_Block_GetContainerFormat(IWICMetadataBlockReader *iface, + GUID *guid) +{ + TRACE("(%p,%p)\n", iface, guid); + + if (!guid) return E_INVALIDARG; + + *guid = GUID_ContainerFormatGif; + return S_OK; +} + +static HRESULT WINAPI GifDecoder_Block_GetCount(IWICMetadataBlockReader *iface, + UINT *count) +{ + TRACE("%p,%p\n", iface, count); + + if (!count) return E_INVALIDARG; + + *count = 1; + return S_OK; +} + +static HRESULT create_LSD_metadata_reader(GifDecoder *This, IWICMetadataReader **reader) +{ + HRESULT hr; + IWICMetadataReader *metadata_reader; + IWICPersistStream *persist; + IStream *stream; + + /* FIXME: Use IWICComponentFactory_CreateMetadataReader once it's implemented */ + + hr = CoCreateInstance(&CLSID_WICLSDMetadataReader, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICMetadataReader, (void **)&metadata_reader); + if (FAILED(hr)) return hr; + + hr = IWICMetadataReader_QueryInterface(metadata_reader, &IID_IWICPersistStream, (void **)&persist); + if (FAILED(hr)) + { + IWICMetadataReader_Release(metadata_reader); + return hr; + } + + stream = create_stream(This->LSD_data, sizeof(This->LSD_data)); + IWICPersistStream_LoadEx(persist, stream, NULL, WICPersistOptionsDefault); + IStream_Release(stream); + + IWICPersistStream_Release(persist); + + *reader = metadata_reader; + return S_OK; +} + +static HRESULT WINAPI GifDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader *iface, + UINT index, IWICMetadataReader **reader) +{ + GifDecoder *This = impl_from_IWICMetadataBlockReader(iface); + + TRACE("(%p,%u,%p)\n", iface, index, reader); + + if (!reader || index != 0) return E_INVALIDARG; + + return create_LSD_metadata_reader(This, reader); +} + +static HRESULT WINAPI GifDecoder_Block_GetEnumerator(IWICMetadataBlockReader *iface, + IEnumUnknown **enumerator) +{ + FIXME("(%p,%p): stub\n", iface, enumerator); + return E_NOTIMPL; +} + +static const IWICMetadataBlockReaderVtbl GifDecoder_BlockVtbl = +{ + GifDecoder_Block_QueryInterface, + GifDecoder_Block_AddRef, + GifDecoder_Block_Release, + GifDecoder_Block_GetContainerFormat, + GifDecoder_Block_GetCount, + GifDecoder_Block_GetReaderByIndex, + GifDecoder_Block_GetEnumerator +}; + HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) { GifDecoder *This; @@ -832,6 +967,7 @@ HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) if (!This) return E_OUTOFMEMORY;
This->IWICBitmapDecoder_iface.lpVtbl = &GifDecoder_Vtbl; + This->IWICMetadataBlockReader_iface.lpVtbl = &GifDecoder_BlockVtbl; This->ref = 1; This->initialized = FALSE; This->gif = NULL; diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index e274106..6bdecee 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -1046,7 +1046,6 @@ static void test_metadata_gif(void)
/* global metadata block */ hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&blockreader); -todo_wine ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
if (SUCCEEDED(hr)) @@ -1149,7 +1148,6 @@ todo_wine
/* global metadata block */ hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&blockreader); -todo_wine ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
if (SUCCEEDED(hr))