diff --git a/dlls/windowscodecs/ddsformat.c b/dlls/windowscodecs/ddsformat.c index 54126c13d70..7a27c48dee0 100644 --- a/dlls/windowscodecs/ddsformat.c +++ b/dlls/windowscodecs/ddsformat.c @@ -475,9 +475,47 @@ static HRESULT WINAPI DdsFrameDecode_Dds_CopyBlocks(IWICDdsFrameDecode *iface, const WICRect *boundsInBlocks, UINT stride, UINT bufferSize, BYTE *buffer) { - FIXME("(%p,%p,%u,%u,%p): stub.\n", iface, boundsInBlocks, stride, bufferSize, buffer); + DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface); + int x, y, width, height; + UINT bytes_per_block, frame_stride, frame_size, i; + BYTE *data, *dst_buffer; - return E_NOTIMPL; + TRACE("(%p,%p,%u,%u,%p)\n", iface, boundsInBlocks, stride, bufferSize, buffer); + + if (!buffer) return E_INVALIDARG; + + bytes_per_block = This->info.bytes_per_block; + frame_stride = This->info.width_in_blocks * bytes_per_block; + frame_size = frame_stride * This->info.height_in_blocks; + if (!boundsInBlocks) { + if (stride < frame_stride) return E_INVALIDARG; + if (bufferSize < frame_size) return E_INVALIDARG; + memcpy(buffer, This->data, frame_size); + return S_OK; + } + + x = boundsInBlocks->X; + y = boundsInBlocks->Y; + width = boundsInBlocks->Width; + height = boundsInBlocks->Height; + if (x < 0 || y < 0 || width <= 0 || height <= 0 || + x + width > This->info.width_in_blocks || + y + height > This->info.height_in_blocks) { + return E_INVALIDARG; + } + if (stride < width * bytes_per_block) return E_INVALIDARG; + if (bufferSize < stride * height) return E_INVALIDARG; + + data = This->data + (x + y * This->info.width_in_blocks) * bytes_per_block; + dst_buffer = buffer; + for (i = 0; i < height; i++) + { + memcpy(dst_buffer, data, (size_t)width * bytes_per_block); + data += This->info.width_in_blocks * bytes_per_block; + dst_buffer += stride; + } + + return S_OK; } static const IWICDdsFrameDecodeVtbl DdsFrameDecode_Dds_Vtbl = { diff --git a/dlls/windowscodecs/tests/ddsformat.c b/dlls/windowscodecs/tests/ddsformat.c index d718a07f962..a69ff35dcb9 100644 --- a/dlls/windowscodecs/tests/ddsformat.c +++ b/dlls/windowscodecs/tests/ddsformat.c @@ -537,46 +537,46 @@ static void test_dds_decoder_frame_data(IWICDdsFrameDecode *dds_frame, UINT fram frame_size = frame_stride * height_in_blocks; hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, 0, 0, NULL); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect_test_a, stride, sizeof(buffer), buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect_test_b, stride, sizeof(buffer), buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect_test_c, stride, sizeof(buffer), buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect_test_d, stride, sizeof(buffer), buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride - 1, sizeof(buffer), buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride * 2, sizeof(buffer), buffer); - todo_wine ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride, sizeof(buffer), buffer); - todo_wine ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride, frame_stride * height_in_blocks - 1, buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride, frame_stride * height_in_blocks, buffer); - todo_wine ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, 0, sizeof(buffer), buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride - 1, sizeof(buffer), buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride * 2, sizeof(buffer), buffer); - todo_wine ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, 0, buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, 1, buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, stride * rect.Height - 1, buffer); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, stride * rect.Height, buffer); - todo_wine ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == S_OK, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, sizeof(buffer), NULL); - todo_wine ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); + ok (hr == E_INVALIDARG, "%d: [frame %d] Got unexpected hr %x\n", i, frame_index, hr); block_offset = 128; /* DDS magic and header */ if (has_extended_header(test_data[i].data)) block_offset += 20; /* DDS extended header */ @@ -600,19 +600,19 @@ static void test_dds_decoder_frame_data(IWICDdsFrameDecode *dds_frame, UINT fram } hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, &rect, stride, sizeof(buffer), buffer); - todo_wine ok (hr == S_OK, "%d: [frame %d] CopyBlocks failed, hr=%x\n", i, frame_index, hr); + ok (hr == S_OK, "%d: [frame %d] CopyBlocks failed, hr=%x\n", i, frame_index, hr); if (hr != S_OK) return; ok (!strncmp((const char *)test_data[i].data + block_offset, (const char *)buffer, format_info.BytesPerBlock), "%d: [frame %d] Block data mismatch\n", i, frame_index); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride, sizeof(buffer), buffer); - todo_wine ok (hr == S_OK, "%d: [frame %d] CopyBlocks failed, hr=%x\n", i, frame_index, hr); + ok (hr == S_OK, "%d: [frame %d] CopyBlocks failed, hr=%x\n", i, frame_index, hr); if (hr != S_OK) return; ok (!strncmp((const char *)test_data[i].data + block_offset, (const char *)buffer, frame_size), "%d: [frame %d] Block data mismatch\n", i, frame_index); hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, frame_stride * 2, sizeof(buffer), buffer); - todo_wine ok (hr == S_OK, "%d: [frame %d] CopyBlocks failed, hr=%x\n", i, frame_index, hr); + ok (hr == S_OK, "%d: [frame %d] CopyBlocks failed, hr=%x\n", i, frame_index, hr); if (hr != S_OK) return; ok (!strncmp((const char *)test_data[i].data + block_offset, (const char *)buffer, frame_size), "%d: [frame %d] Block data mismatch\n", i, frame_index);