Skip to content

Commit

Permalink
Add support for copying subregions from CGIWICBitmap.
Browse files Browse the repository at this point in the history
References microsoft#1379.
  • Loading branch information
DHowett committed Dec 16, 2016
1 parent 470fd9b commit 2138852
Showing 1 changed file with 39 additions and 8 deletions.
47 changes: 39 additions & 8 deletions Frameworks/include/CGIWICBitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class CGIWICBitmap : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::Runtime
}

// IWICBitmap interface
// TODO #1124: Today we do not support locking a region of the WIC bitmap for rendering. We only support locking the complete bitmap.
// TODO #1379: Today we do not support locking of a region smaller than the entire bitmap.
// This will suffice CoreText requirement but needs to be revisted for CoreGraphics usage in future.

HRESULT STDMETHODCALLTYPE Lock(_In_ const WICRect* region, _In_ DWORD flags, _COM_Outptr_ IWICBitmapLock** outLock) {
Expand Down Expand Up @@ -187,17 +187,48 @@ class CGIWICBitmap : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::Runtime
_Out_writes_all_(cbBufferSize) BYTE* buffer) {
RETURN_HR_IF_NULL(E_POINTER, buffer);

const WICRect fullRect = { 0, 0, m_width, m_height };

Microsoft::WRL::ComPtr<IWICBitmapLock> lock;
RETURN_IF_FAILED(Lock(copyRect, 0, &lock));
// TODO #1379: Support sub-regional locking.
RETURN_IF_FAILED(Lock(&fullRect, 0, &lock));

if (!copyRect) {
copyRect = &fullRect;
}

UINT sourceDataSize;
BYTE* sourceData;
RETURN_IF_FAILED(lock->GetDataPointer(&sourceDataSize, &sourceData));
RETURN_HR_IF(E_INVALIDARG, copyRect->Width == 0 || copyRect->Height == 0 || copyRect->X < 0 || copyRect->Y < 0);

RETURN_HR_IF(E_INVALIDARG, sourceDataSize > bufferSize);
unsigned int srcStride;
unsigned int srcSize;
uint8_t* srcData;
RETURN_IF_FAILED(lock->GetStride(&srcStride));
RETURN_IF_FAILED(lock->GetDataPointer(&srcSize, &srcData));

// TODO #1379 - should support regional copying.
RETURN_HR_IF(E_UNEXPECTED, memcpy_s(buffer, bufferSize, sourceData, sourceDataSize) != 0);
if (copyRect->X == 0 && copyRect->Y == 0 && copyRect->Width == m_width && copyRect->Height == m_height) {
RETURN_HR_IF(E_INVALIDARG, srcSize > bufferSize);
RETURN_HR_IF(E_UNEXPECTED, memcpy_s(buffer, bufferSize, srcData, srcSize) != 0);
} else {
// Once we support sub-regional locking we can fix this stride copier.

// Invalid state: Source stride is less than the width of the image.
// We can't copy regions from sub-8bpp images.
RETURN_HR_IF(E_NOTIMPL, srcStride < fullRect.Width);

size_t bytesPerPixel = srcStride / fullRect.Width;
ptrdiff_t srcOffset = (copyRect->X * bytesPerPixel) + (copyRect->Y * srcStride);
const uint8_t* end = buffer + (stride * copyRect->Height);
for (uint8_t *src = srcData + srcOffset, *dest = buffer;
dest < end;
src += srcStride, dest += stride) {
RETURN_HR_IF(E_UNEXPECTED,
memcpy_s(dest,
end - dest, // Total remaining bytes available in the destination buffer.
src,
stride)
);
}
}
return S_OK;
}

Expand Down

0 comments on commit 2138852

Please sign in to comment.