windowscodecs: Create Logical Screen Descriptor metadata for the GIF decoder.
This commit is contained in:
parent
039f6d5114
commit
5373f8520d
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009 Vincent Povirk for CodeWeavers
|
* Copyright 2009 Vincent Povirk for CodeWeavers
|
||||||
|
* Copyright 2012 Dmitry Timoshkov
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* 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);
|
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 {
|
typedef struct {
|
||||||
IWICBitmapDecoder IWICBitmapDecoder_iface;
|
IWICBitmapDecoder IWICBitmapDecoder_iface;
|
||||||
|
IWICMetadataBlockReader IWICMetadataBlockReader_iface;
|
||||||
|
BYTE LSD_data[13]; /* Logical Screen Descriptor */
|
||||||
LONG ref;
|
LONG ref;
|
||||||
BOOL initialized;
|
BOOL initialized;
|
||||||
GifFileType *gif;
|
GifFileType *gif;
|
||||||
@ -342,6 +363,11 @@ static inline GifDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
|
|||||||
return CONTAINING_RECORD(iface, GifDecoder, 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)
|
static inline GifFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
|
||||||
{
|
{
|
||||||
return CONTAINING_RECORD(iface, GifFrameDecode, 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;
|
*ppv = &This->IWICBitmapDecoder_iface;
|
||||||
}
|
}
|
||||||
|
else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid))
|
||||||
|
{
|
||||||
|
*ppv = &This->IWICMetadataBlockReader_iface;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*ppv = NULL;
|
*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 */
|
/* make sure we don't use the stream after this method returns */
|
||||||
This->gif->UserData = NULL;
|
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;
|
This->initialized = TRUE;
|
||||||
|
|
||||||
LeaveCriticalSection(&This->lock);
|
LeaveCriticalSection(&This->lock);
|
||||||
@ -817,6 +851,107 @@ static const IWICBitmapDecoderVtbl GifDecoder_Vtbl = {
|
|||||||
GifDecoder_GetFrame
|
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)
|
HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
|
||||||
{
|
{
|
||||||
GifDecoder *This;
|
GifDecoder *This;
|
||||||
@ -832,6 +967,7 @@ HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
|
|||||||
if (!This) return E_OUTOFMEMORY;
|
if (!This) return E_OUTOFMEMORY;
|
||||||
|
|
||||||
This->IWICBitmapDecoder_iface.lpVtbl = &GifDecoder_Vtbl;
|
This->IWICBitmapDecoder_iface.lpVtbl = &GifDecoder_Vtbl;
|
||||||
|
This->IWICMetadataBlockReader_iface.lpVtbl = &GifDecoder_BlockVtbl;
|
||||||
This->ref = 1;
|
This->ref = 1;
|
||||||
This->initialized = FALSE;
|
This->initialized = FALSE;
|
||||||
This->gif = NULL;
|
This->gif = NULL;
|
||||||
|
@ -1046,7 +1046,6 @@ static void test_metadata_gif(void)
|
|||||||
|
|
||||||
/* global metadata block */
|
/* global metadata block */
|
||||||
hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&blockreader);
|
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);
|
ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
@ -1149,7 +1148,6 @@ todo_wine
|
|||||||
|
|
||||||
/* global metadata block */
|
/* global metadata block */
|
||||||
hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&blockreader);
|
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);
|
ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user