Dmitry Timoshkov : windowscodecs: Create Logical Screen Descriptor metadata for the GIF decoder.

Alexandre Julliard julliard at winehq.org
Wed Sep 12 13:39:16 CDT 2012


Module: wine
Branch: master
Commit: 5373f8520d2fec729730aaa6a3278cefa46f9414
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5373f8520d2fec729730aaa6a3278cefa46f9414

Author: Dmitry Timoshkov <dmitry at 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))




More information about the wine-cvs mailing list