Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2021
- 82 participants
- 607 discussions
[PATCH 1/3] qcap/tests: Add some tests for filter state on the video capture filter.
by Zebediah Figura 15 Jun '21
by Zebediah Figura 15 Jun '21
15 Jun '21
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/qcap/tests/videocapture.c | 57 ++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c
index fafd18009f4..7733dfdc8ed 100644
--- a/dlls/qcap/tests/videocapture.c
+++ b/dlls/qcap/tests/videocapture.c
@@ -360,12 +360,65 @@ static void testfilter_init(struct testfilter *filter)
strmbase_sink_init(&filter->sink, &filter->filter, L"sink", &testsink_ops, NULL);
}
+static void test_filter_state(IMediaControl *control)
+{
+ OAFilterState state;
+ HRESULT hr;
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == State_Stopped, "Got state %u.\n", state);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == VFW_S_CANT_CUE, "Got hr %#x.\n", hr);
+ ok(state == State_Paused, "Got state %u.\n", state);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == State_Running, "Got state %u.\n", state);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == VFW_S_CANT_CUE, "Got hr %#x.\n", hr);
+ ok(state == State_Paused, "Got state %u.\n", state);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == State_Stopped, "Got state %u.\n", state);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == State_Running, "Got state %u.\n", state);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == State_Stopped, "Got state %u.\n", state);
+}
+
static void test_connect_pin(IBaseFilter *filter, IPin *source)
{
AM_MEDIA_TYPE req_mt, default_mt, mt, *mts[2];
IAMStreamConfig *stream_config;
struct testfilter testsink;
IEnumMediaTypes *enummt;
+ IMediaControl *control;
IFilterGraph2 *graph;
ULONG count, ref;
HRESULT hr;
@@ -373,6 +426,7 @@ static void test_connect_pin(IBaseFilter *filter, IPin *source)
CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
&IID_IFilterGraph2, (void **)&graph);
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
testfilter_init(&testsink);
IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink");
IFilterGraph2_AddFilter(graph, filter, L"source");
@@ -406,6 +460,8 @@ static void test_connect_pin(IBaseFilter *filter, IPin *source)
hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
ok(hr == S_OK, "Got hr %#x.\n", hr);
+ test_filter_state(control);
+
hr = IPin_ConnectedTo(source, &peer);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(peer == &testsink.sink.pin.IPin_iface, "Got peer %p.\n", peer);
@@ -445,6 +501,7 @@ static void test_connect_pin(IBaseFilter *filter, IPin *source)
FreeMediaType(&req_mt);
FreeMediaType(&default_mt);
IAMStreamConfig_Release(stream_config);
+ IMediaControl_Release(control);
ref = IFilterGraph2_Release(graph);
ok(!ref, "Got outstanding refcount %d.\n", ref);
ref = IBaseFilter_Release(&testsink.filter.IBaseFilter_iface);
--
2.30.2
1
2
14 Jun '21
COLORONCOLOR(STRETCH_DELETESCANS) was used in place of HALFTONE. COLORONCOLOR mode may delete rows
of pixels without trying to preserve information so it will cause Wine to render poorly when the
destination rectangle is small.
According to tests, HALFTONE mode uses box filter when doing integer downscaling and nearest
neighbor interpolation when doing upscaling in both horizontally and vertically. In other cases,
HALFTONE mode uses a lanczos3 like algorithm to interpolate pixels. There are also other heuristics
involved. For example, shrinking a 2x2 image to 1x1 may not use box filter depending on image data.
Since this algorithm is undocumented, it's difficult to reverse engineer the original algorithm and
produce identical results. Instead, this patch uses a naive implementation of bilinear interpolation
to implement HALFTONE mode and it produces good quality images.
For 8-bit and lower color depth images, nulldrv_StretchBlt should resize the images first and then
converts color depth.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46375
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/gdi32/dibdrv/bitblt.c | 7 +
dlls/gdi32/dibdrv/dibdrv.h | 2 +
dlls/gdi32/dibdrv/primitives.c | 629 ++++++++++++++++++++++++++++++++-
3 files changed, 629 insertions(+), 9 deletions(-)
diff --git a/dlls/gdi32/dibdrv/bitblt.c b/dlls/gdi32/dibdrv/bitblt.c
index d2f59965b02..9b46ad2916f 100644
--- a/dlls/gdi32/dibdrv/bitblt.c
+++ b/dlls/gdi32/dibdrv/bitblt.c
@@ -1216,6 +1216,12 @@ DWORD stretch_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bit
init_dib_info_from_bitmapinfo( &src_dib, src_info, src_bits );
init_dib_info_from_bitmapinfo( &dst_dib, dst_info, dst_bits );
+ if (mode == HALFTONE)
+ {
+ dst_dib.funcs->halftone( &dst_dib, dst, &src_dib, src );
+ goto done;
+ }
+
/* v */
ret = calc_1d_stretch_params( dst->y, dst->height, dst->visrect.top, dst->visrect.bottom,
src->y, src->height, src->visrect.top, src->visrect.bottom,
@@ -1300,6 +1306,7 @@ DWORD stretch_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bit
}
}
+done:
/* update coordinates, the destination rectangle is always stored at 0,0 */
*src = *dst;
src->x -= src->visrect.left;
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index d3a35b96c75..0492c0bd51e 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -211,6 +211,8 @@ typedef struct primitive_funcs
void (* shrink_row)(const dib_info *dst_dib, const POINT *dst_start,
const dib_info *src_dib, const POINT *src_start,
const struct stretch_params *params, int mode, BOOL keep_dst);
+ void (* halftone)(const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src);
} primitive_funcs;
extern const primitive_funcs funcs_8888 DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c
index e4b18a6656d..5eca124b918 100644
--- a/dlls/gdi32/dibdrv/primitives.c
+++ b/dlls/gdi32/dibdrv/primitives.c
@@ -7430,6 +7430,608 @@ static void shrink_row_null(const dib_info *dst_dib, const POINT *dst_start,
return;
}
+static float clampf( float value, float min, float max )
+{
+ return max( min, min( value, max ) );
+}
+
+static int clamp( int value, int min, int max )
+{
+ return max( min, min( value, max ) );
+}
+
+static BYTE linear_interpolate( BYTE start, BYTE end, float delta )
+{
+ return start + (end - start) * delta + 0.5f;
+}
+
+static BYTE bilinear_interpolate( BYTE c00, BYTE c01, BYTE c10, BYTE c11, float dx, float dy )
+{
+ return linear_interpolate( linear_interpolate( c00, c01, dx ),
+ linear_interpolate( c10, c11, dx ), dy );
+}
+
+static void calc_halftone_params( const struct bitblt_coords *dst, const struct bitblt_coords *src,
+ RECT *dst_rect, RECT *src_rect, int *src_start_x,
+ int *src_start_y, float *src_inc_x, float *src_inc_y )
+{
+ int src_width, src_height, dst_width, dst_height;
+ BOOL mirrored_x, mirrored_y;
+
+ get_bounding_rect( src_rect, src->x, src->y, src->width, src->height );
+ get_bounding_rect( dst_rect, dst->x, dst->y, dst->width, dst->height );
+ intersect_rect( src_rect, &src->visrect, src_rect );
+ intersect_rect( dst_rect, &dst->visrect, dst_rect );
+ offset_rect( dst_rect, -dst_rect->left, -dst_rect->top );
+
+ src_width = src_rect->right - src_rect->left;
+ src_height = src_rect->bottom - src_rect->top;
+ dst_width = dst_rect->right - dst_rect->left;
+ dst_height = dst_rect->bottom - dst_rect->top;
+
+ mirrored_x = (dst->width < 0) != (src->width < 0);
+ mirrored_y = (dst->height < 0) != (src->height < 0);
+ *src_start_x = mirrored_x ? src_rect->right - 1 : src_rect->left;
+ *src_start_y = mirrored_y ? src_rect->bottom - 1 : src_rect->top;
+ *src_inc_x = mirrored_x ? -(float)src_width / dst_width : (float)src_width / dst_width;
+ *src_inc_y = mirrored_y ? -(float)src_height / dst_height : (float)src_height / dst_height;
+}
+
+static void halftone_888( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{
+ int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
+ DWORD *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
+ float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
+ BYTE c00_r, c01_r, c10_r, c11_r;
+ BYTE c00_g, c01_g, c10_g, c11_g;
+ BYTE c00_b, c01_b, c10_b, c11_b;
+ RECT dst_rect, src_rect;
+ BYTE r, g, b;
+
+ calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
+ &src_inc_y );
+
+ float_y = src_start_y;
+ dst_ptr = get_pixel_ptr_32( dst_dib, dst_rect.left, dst_rect.top );
+ for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
+ {
+ float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
+ y0 = float_y;
+ y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
+ dy = float_y - y0;
+
+ float_x = src_start_x;
+ src_ptr = get_pixel_ptr_32( src_dib, 0, y0 );
+ src_ptr_dy = (y1 - y0) * src_dib->stride / 4;
+ for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
+ {
+ float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
+ x0 = float_x;
+ x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
+ dx = float_x - x0;
+
+ c00_ptr = src_ptr + x0;
+ c01_ptr = src_ptr + x1;
+ c10_ptr = c00_ptr + src_ptr_dy;
+ c11_ptr = c01_ptr + src_ptr_dy;
+ c00_r = (*c00_ptr >> 16) & 0xff;
+ c01_r = (*c01_ptr >> 16) & 0xff;
+ c10_r = (*c10_ptr >> 16) & 0xff;
+ c11_r = (*c11_ptr >> 16) & 0xff;
+ c00_g = (*c00_ptr >> 8) & 0xff;
+ c01_g = (*c01_ptr >> 8) & 0xff;
+ c10_g = (*c10_ptr >> 8) & 0xff;
+ c11_g = (*c11_ptr >> 8) & 0xff;
+ c00_b = *c00_ptr & 0xff;
+ c01_b = *c01_ptr & 0xff;
+ c10_b = *c10_ptr & 0xff;
+ c11_b = *c11_ptr & 0xff;
+ r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
+ g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
+ b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
+ dst_ptr[dst_x] = ((r << 16) & 0xff0000) | ((g << 8) & 0x00ff00) | (b & 0x0000ff);
+
+ float_x += src_inc_x;
+ }
+
+ dst_ptr += dst_dib->stride / 4;
+ float_y += src_inc_y;
+ }
+}
+
+static void halftone_32( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{
+ int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
+ DWORD *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
+ float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
+ BYTE c00_r, c01_r, c10_r, c11_r;
+ BYTE c00_g, c01_g, c10_g, c11_g;
+ BYTE c00_b, c01_b, c10_b, c11_b;
+ RECT dst_rect, src_rect;
+ BYTE r, g, b;
+
+ calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
+ &src_inc_y );
+
+ float_y = src_start_y;
+ dst_ptr = get_pixel_ptr_32( dst_dib, dst_rect.left, dst_rect.top );
+ for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
+ {
+ float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
+ y0 = float_y;
+ y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
+ dy = float_y - y0;
+
+ float_x = src_start_x;
+ src_ptr = get_pixel_ptr_32( src_dib, 0, y0 );
+ src_ptr_dy = (y1 - y0) * src_dib->stride / 4;
+ for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
+ {
+ float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
+ x0 = float_x;
+ x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
+ dx = float_x - x0;
+
+ c00_ptr = src_ptr + x0;
+ c01_ptr = src_ptr + x1;
+ c10_ptr = c00_ptr + src_ptr_dy;
+ c11_ptr = c01_ptr + src_ptr_dy;
+ c00_r = get_field( *c00_ptr, src_dib->red_shift, src_dib->red_len );
+ c01_r = get_field( *c01_ptr, src_dib->red_shift, src_dib->red_len );
+ c10_r = get_field( *c10_ptr, src_dib->red_shift, src_dib->red_len );
+ c11_r = get_field( *c11_ptr, src_dib->red_shift, src_dib->red_len );
+ c00_g = get_field( *c00_ptr, src_dib->green_shift, src_dib->green_len );
+ c01_g = get_field( *c01_ptr, src_dib->green_shift, src_dib->green_len );
+ c10_g = get_field( *c10_ptr, src_dib->green_shift, src_dib->green_len );
+ c11_g = get_field( *c11_ptr, src_dib->green_shift, src_dib->green_len );
+ c00_b = get_field( *c00_ptr, src_dib->blue_shift, src_dib->blue_len );
+ c01_b = get_field( *c01_ptr, src_dib->blue_shift, src_dib->blue_len );
+ c10_b = get_field( *c10_ptr, src_dib->blue_shift, src_dib->blue_len );
+ c11_b = get_field( *c11_ptr, src_dib->blue_shift, src_dib->blue_len );
+ r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
+ g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
+ b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
+ dst_ptr[dst_x] = rgb_to_pixel_masks( dst_dib, r, g, b );
+
+ float_x += src_inc_x;
+ }
+
+ dst_ptr += dst_dib->stride / 4;
+ float_y += src_inc_y;
+ }
+}
+
+static void halftone_24( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{
+ int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
+ BYTE *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
+ float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
+ BYTE c00_r, c01_r, c10_r, c11_r;
+ BYTE c00_g, c01_g, c10_g, c11_g;
+ BYTE c00_b, c01_b, c10_b, c11_b;
+ RECT dst_rect, src_rect;
+ BYTE r, g, b;
+
+ calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
+ &src_inc_y );
+
+ float_y = src_start_y;
+ dst_ptr = get_pixel_ptr_24( dst_dib, dst_rect.left, dst_rect.top );
+ for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
+ {
+ float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
+ y0 = float_y;
+ y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
+ dy = float_y - y0;
+
+ float_x = src_start_x;
+ src_ptr = get_pixel_ptr_24( src_dib, 0, y0 );
+ src_ptr_dy = (y1 - y0) * src_dib->stride;
+ for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
+ {
+ float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
+ x0 = float_x;
+ x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
+ dx = float_x - x0;
+
+ c00_ptr = src_ptr + x0 * 3;
+ c01_ptr = src_ptr + x1 * 3;
+ c10_ptr = c00_ptr + src_ptr_dy;
+ c11_ptr = c01_ptr + src_ptr_dy;
+ c00_b = c00_ptr[0];
+ c01_b = c01_ptr[0];
+ c10_b = c10_ptr[0];
+ c11_b = c11_ptr[0];
+ c00_g = c00_ptr[1];
+ c01_g = c01_ptr[1];
+ c10_g = c10_ptr[1];
+ c11_g = c11_ptr[1];
+ c00_r = c00_ptr[2];
+ c01_r = c01_ptr[2];
+ c10_r = c10_ptr[2];
+ c11_r = c11_ptr[2];
+ r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
+ g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
+ b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
+ dst_ptr[dst_x * 3] = b;
+ dst_ptr[dst_x * 3 + 1] = g;
+ dst_ptr[dst_x * 3 + 2] = r;
+
+ float_x += src_inc_x;
+ }
+
+ dst_ptr += dst_dib->stride;
+ float_y += src_inc_y;
+ }
+}
+
+static void halftone_555( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{
+ int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
+ WORD *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
+ float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
+ BYTE c00_r, c01_r, c10_r, c11_r;
+ BYTE c00_g, c01_g, c10_g, c11_g;
+ BYTE c00_b, c01_b, c10_b, c11_b;
+ RECT dst_rect, src_rect;
+ BYTE r, g, b;
+
+ calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
+ &src_inc_y );
+
+ float_y = src_start_y;
+ dst_ptr = get_pixel_ptr_16( dst_dib, dst_rect.left, dst_rect.top );
+ for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
+ {
+ float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
+ y0 = float_y;
+ y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
+ dy = float_y - y0;
+
+ float_x = src_start_x;
+ src_ptr = get_pixel_ptr_16( src_dib, 0, y0 );
+ src_ptr_dy = (y1 - y0) * src_dib->stride / 2;
+ for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
+ {
+ float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
+ x0 = float_x;
+ x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
+ dx = float_x - x0;
+
+ c00_ptr = src_ptr + x0;
+ c01_ptr = src_ptr + x1;
+ c10_ptr = c00_ptr + src_ptr_dy;
+ c11_ptr = c01_ptr + src_ptr_dy;
+ c00_r = ((*c00_ptr >> 7) & 0xf8) | ((*c00_ptr >> 12) & 0x07);
+ c01_r = ((*c01_ptr >> 7) & 0xf8) | ((*c01_ptr >> 12) & 0x07);
+ c10_r = ((*c10_ptr >> 7) & 0xf8) | ((*c10_ptr >> 12) & 0x07);
+ c11_r = ((*c11_ptr >> 7) & 0xf8) | ((*c11_ptr >> 12) & 0x07);
+ c00_g = ((*c00_ptr >> 2) & 0xf8) | ((*c00_ptr >> 7) & 0x07);
+ c01_g = ((*c01_ptr >> 2) & 0xf8) | ((*c01_ptr >> 7) & 0x07);
+ c10_g = ((*c10_ptr >> 2) & 0xf8) | ((*c10_ptr >> 7) & 0x07);
+ c11_g = ((*c11_ptr >> 2) & 0xf8) | ((*c11_ptr >> 7) & 0x07);
+ c00_b = ((*c00_ptr << 3) & 0xf8) | ((*c00_ptr >> 2) & 0x07);
+ c01_b = ((*c01_ptr << 3) & 0xf8) | ((*c01_ptr >> 2) & 0x07);
+ c10_b = ((*c10_ptr << 3) & 0xf8) | ((*c10_ptr >> 2) & 0x07);
+ c11_b = ((*c11_ptr << 3) & 0xf8) | ((*c11_ptr >> 2) & 0x07);
+ r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
+ g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
+ b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
+ dst_ptr[dst_x] = ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001f);
+
+ float_x += src_inc_x;
+ }
+
+ dst_ptr += dst_dib->stride / 2;
+ float_y += src_inc_y;
+ }
+}
+
+static void halftone_16( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{
+ int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
+ WORD *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
+ float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
+ BYTE c00_r, c01_r, c10_r, c11_r;
+ BYTE c00_g, c01_g, c10_g, c11_g;
+ BYTE c00_b, c01_b, c10_b, c11_b;
+ RECT dst_rect, src_rect;
+ BYTE r, g, b;
+
+ calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
+ &src_inc_y );
+
+ float_y = src_start_y;
+ dst_ptr = get_pixel_ptr_16( dst_dib, dst_rect.left, dst_rect.top );
+ for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
+ {
+ float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
+ y0 = float_y;
+ y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
+ dy = float_y - y0;
+
+ float_x = src_start_x;
+ src_ptr = get_pixel_ptr_16( src_dib, 0, y0 );
+ src_ptr_dy = (y1 - y0) * src_dib->stride / 2;
+ for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
+ {
+ float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
+ x0 = float_x;
+ x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
+ dx = float_x - x0;
+
+ c00_ptr = src_ptr + x0;
+ c01_ptr = src_ptr + x1;
+ c10_ptr = c00_ptr + src_ptr_dy;
+ c11_ptr = c01_ptr + src_ptr_dy;
+ c00_r = get_field( *c00_ptr, src_dib->red_shift, src_dib->red_len );
+ c01_r = get_field( *c01_ptr, src_dib->red_shift, src_dib->red_len );
+ c10_r = get_field( *c10_ptr, src_dib->red_shift, src_dib->red_len );
+ c11_r = get_field( *c11_ptr, src_dib->red_shift, src_dib->red_len );
+ c00_g = get_field( *c00_ptr, src_dib->green_shift, src_dib->green_len );
+ c01_g = get_field( *c01_ptr, src_dib->green_shift, src_dib->green_len );
+ c10_g = get_field( *c10_ptr, src_dib->green_shift, src_dib->green_len );
+ c11_g = get_field( *c11_ptr, src_dib->green_shift, src_dib->green_len );
+ c00_b = get_field( *c00_ptr, src_dib->blue_shift, src_dib->blue_len );
+ c01_b = get_field( *c01_ptr, src_dib->blue_shift, src_dib->blue_len );
+ c10_b = get_field( *c10_ptr, src_dib->blue_shift, src_dib->blue_len );
+ c11_b = get_field( *c11_ptr, src_dib->blue_shift, src_dib->blue_len );
+ r = bilinear_interpolate( c00_r, c01_r, c10_r, c11_r, dx, dy );
+ g = bilinear_interpolate( c00_g, c01_g, c10_g, c11_g, dx, dy );
+ b = bilinear_interpolate( c00_b, c01_b, c10_b, c11_b, dx, dy );
+ dst_ptr[dst_x] = rgb_to_pixel_masks( dst_dib, r, g, b );
+
+ float_x += src_inc_x;
+ }
+
+ dst_ptr += dst_dib->stride / 2;
+ float_y += src_inc_y;
+ }
+}
+
+static void halftone_8( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{
+ int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
+ BYTE *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
+ RGBQUAD c00_rgb, c01_rgb, c10_rgb, c11_rgb, zero_rgb = {0};
+ float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
+ const RGBQUAD *src_clr_table;
+ RECT dst_rect, src_rect;
+ BYTE r, g, b;
+
+ calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
+ &src_inc_y );
+
+ float_y = src_start_y;
+ src_clr_table = get_dib_color_table( src_dib );
+ dst_ptr = get_pixel_ptr_8( dst_dib, dst_rect.left, dst_rect.top );
+ for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
+ {
+ float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
+ y0 = float_y;
+ y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
+ dy = float_y - y0;
+
+ float_x = src_start_x;
+ src_ptr = get_pixel_ptr_8( src_dib, 0, y0 );
+ src_ptr_dy = (y1 - y0) * src_dib->stride;
+ for (dst_x = 0; dst_x < dst_rect.right - dst_rect.left; ++dst_x)
+ {
+ float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
+ x0 = float_x;
+ x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
+ dx = float_x - x0;
+
+ c00_ptr = src_ptr + x0;
+ c01_ptr = src_ptr + x1;
+ c10_ptr = c00_ptr + src_ptr_dy;
+ c11_ptr = c01_ptr + src_ptr_dy;
+ if (src_clr_table)
+ {
+ c00_rgb = *c00_ptr < src_dib->color_table_size ? src_clr_table[*c00_ptr] : zero_rgb;
+ c01_rgb = *c01_ptr < src_dib->color_table_size ? src_clr_table[*c01_ptr] : zero_rgb;
+ c10_rgb = *c10_ptr < src_dib->color_table_size ? src_clr_table[*c10_ptr] : zero_rgb;
+ c11_rgb = *c11_ptr < src_dib->color_table_size ? src_clr_table[*c11_ptr] : zero_rgb;
+ r = bilinear_interpolate( c00_rgb.rgbRed, c01_rgb.rgbRed, c10_rgb.rgbRed, c11_rgb.rgbRed, dx, dy );
+ g = bilinear_interpolate( c00_rgb.rgbGreen, c01_rgb.rgbGreen, c10_rgb.rgbGreen, c11_rgb.rgbGreen, dx, dy );
+ b = bilinear_interpolate( c00_rgb.rgbBlue, c01_rgb.rgbBlue, c10_rgb.rgbBlue, c11_rgb.rgbBlue, dx, dy );
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0;
+ }
+ dst_ptr[dst_x] = rgb_to_pixel_colortable( dst_dib, r, g, b );
+
+ float_x += src_inc_x;
+ }
+
+ dst_ptr += dst_dib->stride;
+ float_y += src_inc_y;
+ }
+}
+
+static void halftone_4( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{
+ BYTE *dst_col_ptr, *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
+ int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1;
+ RGBQUAD c00_rgb, c01_rgb, c10_rgb, c11_rgb, zero_rgb = {0};
+ float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
+ BYTE r, g, b, val, c00, c01, c10, c11;
+ const RGBQUAD *src_clr_table;
+ RECT dst_rect, src_rect;
+
+ calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
+ &src_inc_y );
+
+ float_y = src_start_y;
+ src_clr_table = get_dib_color_table( src_dib );
+ dst_col_ptr = (BYTE *)dst_dib->bits.ptr + (dst_dib->rect.top + dst_rect.top) * dst_dib->stride;
+ for (dst_y = 0; dst_y < dst_rect.bottom - dst_rect.top; ++dst_y)
+ {
+ float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
+ y0 = float_y;
+ y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
+ dy = float_y - y0;
+
+ float_x = src_start_x;
+ src_ptr = (BYTE *)src_dib->bits.ptr + (src_dib->rect.top + y0) * src_dib->stride;
+ src_ptr_dy = (y1 - y0) * src_dib->stride;
+ for (dst_x = dst_rect.left; dst_x < dst_rect.right; ++dst_x)
+ {
+ float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
+ x0 = float_x;
+ x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
+ dx = float_x - x0;
+
+ c00_ptr = src_ptr + (src_dib->rect.left + x0) / 2;
+ c01_ptr = src_ptr + (src_dib->rect.left + x1) / 2;
+ c10_ptr = c00_ptr + src_ptr_dy;
+ c11_ptr = c01_ptr + src_ptr_dy;
+ if ((src_dib->rect.left + x0) & 1)
+ {
+ c00 = *c00_ptr & 0x0f;
+ c10 = *c10_ptr & 0x0f;
+ }
+ else
+ {
+ c00 = (*c00_ptr >> 4) & 0x0f;
+ c10 = (*c10_ptr >> 4) & 0x0f;
+ }
+ if ((src_dib->rect.left + x1) & 1)
+ {
+ c01 = *c01_ptr & 0x0f;
+ c11 = *c11_ptr & 0x0f;
+ }
+ else
+ {
+ c01 = (*c01_ptr >> 4) & 0x0f;
+ c11 = (*c11_ptr >> 4) & 0x0f;
+ }
+
+ if (src_clr_table)
+ {
+ c00_rgb = c00 < src_dib->color_table_size ? src_clr_table[c00] : zero_rgb;
+ c01_rgb = c01 < src_dib->color_table_size ? src_clr_table[c01] : zero_rgb;
+ c10_rgb = c10 < src_dib->color_table_size ? src_clr_table[c10] : zero_rgb;
+ c11_rgb = c11 < src_dib->color_table_size ? src_clr_table[c11] : zero_rgb;
+ r = bilinear_interpolate( c00_rgb.rgbRed, c01_rgb.rgbRed, c10_rgb.rgbRed, c11_rgb.rgbRed, dx, dy );
+ g = bilinear_interpolate( c00_rgb.rgbGreen, c01_rgb.rgbGreen, c10_rgb.rgbGreen, c11_rgb.rgbGreen, dx, dy );
+ b = bilinear_interpolate( c00_rgb.rgbBlue, c01_rgb.rgbBlue, c10_rgb.rgbBlue, c11_rgb.rgbBlue, dx, dy );
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0;
+ }
+
+ dst_ptr = dst_col_ptr + (dst_dib->rect.left + dst_x) / 2;
+ val = rgb_to_pixel_colortable( dst_dib, r, g, b );
+ if ((dst_x + dst_dib->rect.left) & 1)
+ *dst_ptr = (val & 0x0f) | (*dst_ptr & 0xf0);
+ else
+ *dst_ptr = (val << 4) & 0xf0;
+
+ float_x += src_inc_x;
+ }
+
+ dst_col_ptr += dst_dib->stride;
+ float_y += src_inc_y;
+ }
+}
+
+static void halftone_1( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{
+ int src_start_x, src_start_y, src_ptr_dy, dst_x, dst_y, x0, x1, y0, y1, bit_pos;
+ BYTE *dst_col_ptr, *dst_ptr, *src_ptr, *c00_ptr, *c01_ptr, *c10_ptr, *c11_ptr;
+ RGBQUAD c00_rgb, c01_rgb, c10_rgb, c11_rgb, zero_rgb = {0};
+ float src_inc_x, src_inc_y, float_x, float_y, dx, dy;
+ BYTE r, g, b, val, c00, c01, c10, c11;
+ const RGBQUAD *src_clr_table;
+ RECT dst_rect, src_rect;
+ RGBQUAD bg_entry;
+ DWORD bg_pixel;
+
+ calc_halftone_params( dst, src, &dst_rect, &src_rect, &src_start_x, &src_start_y, &src_inc_x,
+ &src_inc_y );
+
+ float_y = src_start_y;
+ bg_entry = *get_dib_color_table( dst_dib );
+ src_clr_table = get_dib_color_table( src_dib );
+ dst_col_ptr = (BYTE *)dst_dib->bits.ptr + (dst_dib->rect.top + dst_rect.top) * dst_dib->stride;
+ for (dst_y = dst_rect.top; dst_y < dst_rect.bottom; ++dst_y)
+ {
+ float_y = clampf( float_y, src_rect.top, src_rect.bottom - 1 );
+ y0 = float_y;
+ y1 = clamp( y0 + 1, src_rect.top, src_rect.bottom - 1 );
+ dy = float_y - y0;
+
+ float_x = src_start_x;
+ src_ptr = (BYTE *)src_dib->bits.ptr + (src_dib->rect.top + y0) * src_dib->stride;
+ src_ptr_dy = (y1 - y0) * src_dib->stride;
+ for (dst_x = dst_rect.left; dst_x < dst_rect.right; ++dst_x)
+ {
+ float_x = clampf( float_x, src_rect.left, src_rect.right - 1 );
+ x0 = float_x;
+ x1 = clamp( x0 + 1, src_rect.left, src_rect.right - 1 );
+ dx = float_x - x0;
+
+ c00_ptr = src_ptr + (src_dib->rect.left + x0) / 8;
+ c01_ptr = src_ptr + (src_dib->rect.left + x1) / 8;
+ c10_ptr = c00_ptr + src_ptr_dy;
+ c11_ptr = c01_ptr + src_ptr_dy;
+ c00 = (*c00_ptr & pixel_masks_1[(src_dib->rect.left + x0) & 7]) ? 1 : 0;
+ c01 = (*c01_ptr & pixel_masks_1[(src_dib->rect.left + x1) & 7]) ? 1 : 0;
+ c10 = (*c10_ptr & pixel_masks_1[(src_dib->rect.left + x0) & 7]) ? 1 : 0;
+ c11 = (*c11_ptr & pixel_masks_1[(src_dib->rect.left + x1) & 7]) ? 1 : 0;
+
+ if (src_clr_table)
+ {
+ c00_rgb = c00 < src_dib->color_table_size ? src_clr_table[c00] : zero_rgb;
+ c01_rgb = c01 < src_dib->color_table_size ? src_clr_table[c01] : zero_rgb;
+ c10_rgb = c10 < src_dib->color_table_size ? src_clr_table[c10] : zero_rgb;
+ c11_rgb = c11 < src_dib->color_table_size ? src_clr_table[c11] : zero_rgb;
+ r = bilinear_interpolate( c00_rgb.rgbRed, c01_rgb.rgbRed, c10_rgb.rgbRed, c11_rgb.rgbRed, dx, dy );
+ g = bilinear_interpolate( c00_rgb.rgbGreen, c01_rgb.rgbGreen, c10_rgb.rgbGreen, c11_rgb.rgbGreen, dx, dy );
+ b = bilinear_interpolate( c00_rgb.rgbBlue, c01_rgb.rgbBlue, c10_rgb.rgbBlue, c11_rgb.rgbBlue, dx, dy );
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0;
+ }
+
+ dst_ptr = dst_col_ptr + (dst_dib->rect.left + dst_x) / 8;
+ bit_pos = (dst_x + dst_dib->rect.left) & 7;
+ bg_pixel = FILTER_DIBINDEX(bg_entry, RGB(bg_entry.rgbRed, bg_entry.rgbGreen, bg_entry.rgbBlue));
+ val = rgb_to_pixel_mono( dst_dib, FALSE, dst_x, dst_y, RGB(r, g, b), bg_pixel, r, g, b );
+ if (bit_pos == 0)
+ *dst_ptr = 0;
+ *dst_ptr = (*dst_ptr & ~pixel_masks_1[bit_pos]) | (val & pixel_masks_1[bit_pos]);
+
+ float_x += src_inc_x;
+ }
+
+ dst_col_ptr += dst_dib->stride;
+ float_y += src_inc_y;
+ }
+}
+
+static void halftone_null( const dib_info *dst_dib, const struct bitblt_coords *dst,
+ const dib_info *src_dib, const struct bitblt_coords *src )
+{}
+
const primitive_funcs funcs_8888 =
{
solid_rects_32,
@@ -7448,7 +8050,8 @@ const primitive_funcs funcs_8888 =
create_rop_masks_32,
create_dither_masks_null,
stretch_row_32,
- shrink_row_32
+ shrink_row_32,
+ halftone_888
};
const primitive_funcs funcs_32 =
@@ -7469,7 +8072,8 @@ const primitive_funcs funcs_32 =
create_rop_masks_32,
create_dither_masks_null,
stretch_row_32,
- shrink_row_32
+ shrink_row_32,
+ halftone_32
};
const primitive_funcs funcs_24 =
@@ -7490,7 +8094,8 @@ const primitive_funcs funcs_24 =
create_rop_masks_24,
create_dither_masks_null,
stretch_row_24,
- shrink_row_24
+ shrink_row_24,
+ halftone_24
};
const primitive_funcs funcs_555 =
@@ -7511,7 +8116,8 @@ const primitive_funcs funcs_555 =
create_rop_masks_16,
create_dither_masks_null,
stretch_row_16,
- shrink_row_16
+ shrink_row_16,
+ halftone_555
};
const primitive_funcs funcs_16 =
@@ -7532,7 +8138,8 @@ const primitive_funcs funcs_16 =
create_rop_masks_16,
create_dither_masks_null,
stretch_row_16,
- shrink_row_16
+ shrink_row_16,
+ halftone_16
};
const primitive_funcs funcs_8 =
@@ -7553,7 +8160,8 @@ const primitive_funcs funcs_8 =
create_rop_masks_8,
create_dither_masks_8,
stretch_row_8,
- shrink_row_8
+ shrink_row_8,
+ halftone_8
};
const primitive_funcs funcs_4 =
@@ -7574,7 +8182,8 @@ const primitive_funcs funcs_4 =
create_rop_masks_4,
create_dither_masks_4,
stretch_row_4,
- shrink_row_4
+ shrink_row_4,
+ halftone_4
};
const primitive_funcs funcs_1 =
@@ -7595,7 +8204,8 @@ const primitive_funcs funcs_1 =
create_rop_masks_1,
create_dither_masks_1,
stretch_row_1,
- shrink_row_1
+ shrink_row_1,
+ halftone_1
};
const primitive_funcs funcs_null =
@@ -7616,5 +8226,6 @@ const primitive_funcs funcs_null =
create_rop_masks_null,
create_dither_masks_null,
stretch_row_null,
- shrink_row_null
+ shrink_row_null,
+ halftone_null
};
--
2.30.2
3
2
[PATCH] wined3d: Don't pass a 3D texture view's depth range as layer range to Vulkan.
by Jan Sikorski 14 Jun '21
by Jan Sikorski 14 Jun '21
14 Jun '21
Layer index and count fields in struct wined3d_view_desc double as the depth range of a 3D texture view.
Signed-off-by: Jan Sikorski <jsikorski(a)codeweavers.com>
---
dlls/wined3d/view.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index 91d26c05fae..7900df3c246 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -773,8 +773,19 @@ static VkImageView wined3d_view_vk_create_vk_image_view(struct wined3d_context_v
}
create_info.subresourceRange.baseMipLevel = desc->u.texture.level_idx;
create_info.subresourceRange.levelCount = desc->u.texture.level_count;
- create_info.subresourceRange.baseArrayLayer = desc->u.texture.layer_idx;
- create_info.subresourceRange.layerCount = desc->u.texture.layer_count;
+ if (create_info.viewType == VK_IMAGE_VIEW_TYPE_3D)
+ {
+ if (desc->u.texture.layer_idx || (desc->u.texture.layer_count != texture_vk->t.resource.depth
+ && desc->u.texture.layer_count != ~0u))
+ WARN("Partial 3D texture views are not supported.\n");
+ create_info.subresourceRange.baseArrayLayer = 0;
+ create_info.subresourceRange.layerCount = 1;
+ }
+ else
+ {
+ create_info.subresourceRange.baseArrayLayer = desc->u.texture.layer_idx;
+ create_info.subresourceRange.layerCount = desc->u.texture.layer_count;
+ }
if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &create_info, NULL, &vk_image_view))) < 0)
{
ERR("Failed to create Vulkan image view, vr %s.\n", wined3d_debug_vkresult(vr));
--
2.30.2
2
1
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
---
dlls/crtdll/Makefile.in | 1 -
dlls/msvcr100/Makefile.in | 1 -
dlls/msvcr110/Makefile.in | 1 -
dlls/msvcr120/Makefile.in | 1 -
dlls/msvcr70/Makefile.in | 1 -
dlls/msvcr71/Makefile.in | 1 -
dlls/msvcr80/Makefile.in | 1 -
dlls/msvcr90/Makefile.in | 1 -
dlls/msvcrt/Makefile.in | 1 -
dlls/msvcrt/math.c | 423 +++++++++++++++++++++++++++++++++++++-
dlls/msvcrt/unixlib.c | 64 ------
dlls/msvcrt/unixlib.h | 29 ---
dlls/msvcrtd/Makefile.in | 1 -
dlls/ucrtbase/Makefile.in | 1 -
14 files changed, 412 insertions(+), 115 deletions(-)
delete mode 100644 dlls/msvcrt/unixlib.c
delete mode 100644 dlls/msvcrt/unixlib.h
1
0
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
---
dlls/msvcrt/math.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
1
0
14 Jun '21
It's only going to be used for internal HID preparsed data, to save a
custom struct.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
v3: Should really be no-op, add a BitCount in the Reserved2 fields for
now, but we'll drop it later.
Supersedes: 207499-207501
dlls/hid/hidp.c | 20 ++++++++++----------
dlls/hidclass.sys/descriptor.c | 17 ++++++++---------
include/ddk/hidpi.h | 5 +++++
include/wine/hid.h | 1 -
4 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c
index 2933c2ff7ef..4532f656008 100644
--- a/dlls/hid/hidp.c
+++ b/dlls/hid/hidp.c
@@ -277,7 +277,7 @@ static NTSTATUS find_usage(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT
if (value->IsRange && value->Range.UsageMin <= Usage && Usage <= value->Range.UsageMax)
{
*element = elems[report->elementIdx + i];
- element->valueStartBit += value->BitSize * (Usage - value->Range.UsageMin);
+ element->caps.StartBit += value->BitSize * (Usage - value->Range.UsageMin);
element->bitCount = elems[report->elementIdx + i].caps.BitSize;
return HIDP_STATUS_SUCCESS;
}
@@ -332,7 +332,7 @@ NTSTATUS WINAPI HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType, USAGE Usag
{
ULONG rawValue;
rc = get_report_data((BYTE*)Report, ReportLength,
- element.valueStartBit, element.bitCount, &rawValue);
+ element.caps.StartBit, element.bitCount, &rawValue);
if (rc != HIDP_STATUS_SUCCESS)
return rc;
*UsageValue = logical_to_physical(sign_extend(rawValue, &element), &element);
@@ -357,7 +357,7 @@ NTSTATUS WINAPI HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage,
if (rc == HIDP_STATUS_SUCCESS)
{
return get_report_data((BYTE*)Report, ReportLength,
- element.valueStartBit, element.bitCount, UsageValue);
+ element.caps.StartBit, element.bitCount, UsageValue);
}
return rc;
@@ -381,7 +381,7 @@ NTSTATUS WINAPI HidP_GetUsageValueArray(HIDP_REPORT_TYPE ReportType, USAGE Usage
if (element.caps.IsRange || element.caps.ReportCount <= 1 || !element.bitCount)
return HIDP_STATUS_NOT_VALUE_ARRAY;
- return get_report_data_array((BYTE*)Report, ReportLength, element.valueStartBit, element.bitCount,
+ return get_report_data_array((BYTE*)Report, ReportLength, element.caps.StartBit, element.bitCount,
element.caps.ReportCount, UsageValue, UsageValueByteLength);
}
@@ -444,7 +444,7 @@ NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USH
{
UINT v = 0;
NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength,
- element->valueStartBit + k, 1, &v);
+ element->caps.StartBit + k, 1, &v);
if (rc != HIDP_STATUS_SUCCESS)
return rc;
found = TRUE;
@@ -636,7 +636,7 @@ NTSTATUS WINAPI HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage,
if (rc == HIDP_STATUS_SUCCESS)
{
return set_report_data((BYTE*)Report, ReportLength,
- element.valueStartBit, element.bitCount, UsageValue);
+ element.caps.StartBit, element.bitCount, UsageValue);
}
return rc;
@@ -661,7 +661,7 @@ NTSTATUS WINAPI HidP_SetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USH
if (rc == HIDP_STATUS_SUCCESS)
{
rc = set_report_data((BYTE*)Report, ReportLength,
- element.valueStartBit, element.bitCount, -1);
+ element.caps.StartBit, element.bitCount, -1);
}
if (rc != HIDP_STATUS_SUCCESS)
@@ -869,7 +869,7 @@ NTSTATUS WINAPI HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, USHORT LinkCollect
{
UINT v = 0;
NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength,
- element->valueStartBit + k, 1, &v);
+ element->caps.StartBit + k, 1, &v);
if (rc != HIDP_STATUS_SUCCESS)
return rc;
if (v)
@@ -952,7 +952,7 @@ NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, U
{
UINT v = 0;
NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength,
- element->valueStartBit + k, 1, &v);
+ element->caps.StartBit + k, 1, &v);
if (rc != HIDP_STATUS_SUCCESS)
return rc;
if (v)
@@ -972,7 +972,7 @@ NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, U
{
UINT v;
NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength,
- element->valueStartBit, element->bitCount, &v);
+ element->caps.StartBit, element->bitCount, &v);
if (rc != HIDP_STATUS_SUCCESS)
return rc;
DataList[uCount].DataIndex = element->caps.NotRange.DataIndex;
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c
index 65c2f9aadae..9cf6f311fca 100644
--- a/dlls/hidclass.sys/descriptor.c
+++ b/dlls/hidclass.sys/descriptor.c
@@ -137,12 +137,12 @@ static inline const char *debugstr_hidp_value_caps( HIDP_VALUE_CAPS *caps )
{
if (!caps) return "(null)";
return wine_dbg_sprintf( "RId %d, Usg %02x:%02x-%02x Dat %02x-%02x (%d), Str %d-%d (%d), Des %d-%d (%d), "
- "Bits %02x, Als %d, Abs %d, Nul %d, LCol %d LUsg %02x:%02x, BitSz %d, RCnt %d, "
+ "Bits %02x, Als %d, Abs %d, Nul %d, LCol %d LUsg %02x:%02x, BitStrt %d, BitSz %d, RCnt %d, "
"Unit %x E%+d, Log %+d-%+d, Phy %+d-%+d",
caps->ReportID, caps->UsagePage, caps->Range.UsageMin, caps->Range.UsageMax, caps->Range.DataIndexMin, caps->Range.DataIndexMax, caps->IsRange,
caps->Range.StringMin, caps->Range.StringMax, caps->IsStringRange, caps->Range.DesignatorMin, caps->Range.DesignatorMax, caps->IsDesignatorRange,
- caps->BitField, caps->IsAlias, caps->IsAbsolute, caps->HasNull, caps->LinkCollection, caps->LinkUsagePage, caps->LinkUsage, caps->BitSize, caps->ReportCount,
- caps->Units, caps->UnitsExp, caps->LogicalMin, caps->LogicalMax, caps->PhysicalMin, caps->PhysicalMax );
+ caps->BitField, caps->IsAlias, caps->IsAbsolute, caps->HasNull, caps->LinkCollection, caps->LinkUsagePage, caps->LinkUsage, caps->StartBit,
+ caps->BitSize, caps->ReportCount, caps->Units, caps->UnitsExp, caps->LogicalMin, caps->LogicalMax, caps->PhysicalMin, caps->PhysicalMax );
}
static void debug_feature(struct feature *feature)
@@ -196,7 +196,7 @@ static void debug_print_report(const char* type, WINE_HIDP_PREPARSED_DATA *data,
for (i = 0; i < report->elementCount; i++)
{
WINE_HID_ELEMENT *elem = elems + report->elementIdx + i;
- TRACE("%s: %s, StartBit %d, BitCount %d\n", type, debugstr_hidp_value_caps(&elem->caps), elem->valueStartBit, elem->bitCount);
+ TRACE("%s: %s, BitCount %d\n", type, debugstr_hidp_value_caps(&elem->caps), elem->bitCount);
}
TRACE(">>> END Report %i\n",report->reportID);
}
@@ -589,11 +589,6 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems
return;
}
- wine_element->valueStartBit = wine_report->bitSize;
-
- wine_element->bitCount = (feature->caps.BitSize * feature->caps.ReportCount);
- wine_report->bitSize += wine_element->bitCount;
-
wine_element->caps = feature->caps;
wine_element->caps.BitField = feature->BitField;
wine_element->caps.LinkCollection = feature->collection->index;
@@ -601,6 +596,10 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems
wine_element->caps.LinkUsagePage = feature->collection->caps.UsagePage;
wine_element->caps.IsAbsolute = feature->IsAbsolute;
wine_element->caps.HasNull = feature->HasNull;
+ wine_element->caps.StartBit = wine_report->bitSize;
+
+ wine_element->bitCount = (wine_element->caps.BitSize * wine_element->caps.ReportCount);
+ wine_report->bitSize += wine_element->bitCount;
if (wine_element->caps.IsRange)
{
diff --git a/include/ddk/hidpi.h b/include/ddk/hidpi.h
index fb497f3282f..9da84f38531 100644
--- a/include/ddk/hidpi.h
+++ b/include/ddk/hidpi.h
@@ -83,7 +83,12 @@ typedef struct _HIDP_VALUE_CAPS
UCHAR Reserved;
USHORT BitSize;
USHORT ReportCount;
+#ifdef __WINESRC__
+ USHORT Reserved2[3];
+ ULONG StartBit;
+#else
USHORT Reserved2[5];
+#endif
ULONG UnitsExp;
ULONG Units;
LONG LogicalMin;
diff --git a/include/wine/hid.h b/include/wine/hid.h
index cfb4f389eb9..0c0d3fdca99 100644
--- a/include/wine/hid.h
+++ b/include/wine/hid.h
@@ -33,7 +33,6 @@
typedef struct __WINE_ELEMENT
{
- UINT valueStartBit;
UINT bitCount;
HIDP_VALUE_CAPS caps;
} WINE_HID_ELEMENT;
--
2.31.0
1
3
14 Jun '21
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
I'm not sure the tests should be in tests/dib.c. The framework in dib.c hashes results and compares them.
I don't think that's going to help us figuring out the exact HALFTONE algorithm details with the results
being hashes. Also, the tests that succeed have all input pixels has the same value. So if I only add the
tests that succeed, it provides little value. The tests here are mostly for helping figuring out the
algorithm in the future. Since the actual Wine implementation in the previous patch uses a different approach.
It doesn't reproduce identical results. So if you feel that such tests are not necessary, you can drop this.
dlls/gdi32/tests/bitmap.c | 1136 +++++++++++++++++++++++++++++++++++++
1 file changed, 1136 insertions(+)
diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c
index fe3482671b2..c28dde8159b 100644
--- a/dlls/gdi32/tests/bitmap.c
+++ b/dlls/gdi32/tests/bitmap.c
@@ -57,6 +57,29 @@ static inline int get_dib_image_size( const BITMAPINFO *info )
* abs( info->bmiHeader.biHeight );
}
+static void dump_bits(int bpp, int width, const BYTE *expected, const BYTE *result, int size,
+ const char *comment)
+{
+ int i, stride;
+
+ stride = get_dib_stride(width, bpp);
+ printf("%s expected:\n", comment);
+ for (i = 0; i < size; i++)
+ {
+ printf("%02x ", expected[i]);
+ if ((i + 1) % stride == 0)
+ printf("\n");
+ }
+ printf("\n%s got:\n", comment);
+ for (i = 0; i < size; i++)
+ {
+ printf("%02x ", result[i]);
+ if ((i + 1) % stride == 0)
+ printf("\n");
+ }
+ printf("\n");
+}
+
static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHEADER *bmih)
{
BITMAP bm;
@@ -3426,6 +3449,1118 @@ static void test_StretchBlt(void)
DeleteDC(hdcScreen);
}
+static void test_StretchBlt_HALFTONE(void)
+{
+#define PAD_ZERO 0x00,
+
+ /* Same dimension */
+ /* 1x1 -> 1x1 */
+ static const unsigned char test_bits_0[] =
+ {
+ 0xff, 0x7f, 0x00,
+ };
+ static const unsigned char expected_bits_0[] =
+ {
+ 0xff, 0x7f, 0x00,
+ };
+
+ /* Shrink horizontally */
+ /* 2x1 -> 1x1 */
+ /* 0xff / 2 = 0x7f.8, (0xff + 1) / 2 = 0x80 */
+ static const unsigned char test_bits_1[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x01, 0x00,
+ };
+ static const unsigned char expected_bits_1[] =
+ {
+ 0x7f, 0x80, 0x7f,
+ };
+ static const unsigned char test_bits_2[] =
+ {
+ 0x00, 0x01, 0x00, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_2[] =
+ {
+ 0x7f, 0x80, 0x7f,
+ };
+
+ /* 3x1 -> 1x1 */
+ /* 0xff / 3 = 0x55 */
+ static const unsigned char test_bits_3[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_3[] =
+ {
+ 0x54, 0x54, 0x54,
+ };
+ static const unsigned char test_bits_4[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_4[] =
+ {
+ 0x55, 0x55, 0x55,
+ };
+ static const unsigned char test_bits_5[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_5[] =
+ {
+ 0x55, 0x55, 0x55,
+ };
+ /* 0xff * 2 / 3 = 0xaa */
+ static const unsigned char test_bits_6[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_6[] =
+ {
+ 0xa9, 0xa9, 0xa9,
+ };
+ static const unsigned char test_bits_7[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_7[] =
+ {
+ 0xa9, 0xa9, 0xa9,
+ };
+ static const unsigned char test_bits_8[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_8[] =
+ {
+ 0xaa, 0xaa, 0xaa,
+ };
+ static const unsigned char test_bits_9[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_9[] =
+ {
+ 0xff, 0xff, 0xff,
+ };
+
+ /* 4x1 -> 1x1 */
+ /* 0xff * 3 / 4 = 0xbf.4 */
+ static const unsigned char test_bits_10[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_10[] =
+ {
+ 0xbf, 0xbf, 0xbf,
+ };
+
+ /* 5x1 -> 1x1 */
+ /* 0xff * 4 / 5 = 0xcc */
+ static const unsigned char test_bits_11[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_11[] =
+ {
+ 0xcc, 0xcc, 0xcc,
+ };
+
+ /* Shrink horizontally with non-integer ratio */
+ /* 3x1 -> 2x1 */
+ static const unsigned char test_bits_12[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_12[] =
+ {
+ 0xd4, 0xd4, 0xd4, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char test_bits_13[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_13[] =
+ {
+ 0x55, 0x55, 0x55, 0x54, 0x54, 0x54,
+ };
+ static const unsigned char test_bits_14[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_14[] =
+ {
+ 0x00, 0x00, 0x00, 0xd4, 0xd4, 0xd4,
+ };
+ static const unsigned char test_bits_15[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_15[] =
+ {
+ 0xff, 0xff, 0xff, 0x2a, 0x2a, 0x2a,
+ };
+ static const unsigned char test_bits_16[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_16[] =
+ {
+ 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa,
+ };
+ static const unsigned char test_bits_17[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_17[] =
+ {
+ 0x2a, 0x2a, 0x2a, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char test_bits_18[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_18[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+
+ /* 4x1 -> 3x1 */
+ static const unsigned char test_bits_19[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_19[] =
+ {
+ 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char test_bits_20[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_20[] =
+ {
+ 0xcf, 0xcf, 0xcf, 0x7f, 0x7f, 0x7f, 0x2f, 0x2f, 0x2f,
+ };
+ static const unsigned char test_bits_21[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_21[] =
+ {
+ 0x2f, 0x2f, 0x2f, 0x7f, 0x7f, 0x7f, 0xcf, 0xcf, 0xcf,
+ };
+ static const unsigned char test_bits_22[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff
+ };
+ static const unsigned char expected_bits_22[] =
+ {
+ 0xef, 0xef, 0xef, 0x00, 0x00, 0x00, 0xef, 0xef, 0xef,
+ };
+ static const unsigned char test_bits_23[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_23[] =
+ {
+ 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x0f,
+ };
+
+ /* 5x1 -> 3x1 */
+ static const unsigned char test_bits_24[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_24[] =
+ {
+ 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char test_bits_25[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char expected_bits_25[] =
+ {
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x65, 0x65, 0x65,
+ };
+ static const unsigned char test_bits_26[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_26[] =
+ {
+ 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99,
+ };
+
+ /* Shrink vertically */
+ /* 1x2 -> 1x1 */
+ /* 0xff / 2 = 0x7f.8, (0xff + 1) / 2 = 0x80 */
+ static const unsigned char test_bits_27[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x01, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_27[] =
+ {
+ 0x7f, 0x80, 0x7f
+ };
+ static const unsigned char test_bits_28[] =
+ {
+ 0x00, 0x01, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_28[] =
+ {
+ 0x7f, 0x80, 0x7f
+ };
+
+ /* 1x3 -> 1x1 */
+ /* 0xff / 3 = 0x55 */
+ static const unsigned char test_bits_29[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_29[] =
+ {
+ 0x55, 0x55, 0x55,
+ };
+ static const unsigned char test_bits_30[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_30[] =
+ {
+ 0x55, 0x55, 0x55,
+ };
+ static const unsigned char test_bits_31[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_31[] =
+ {
+ 0x54, 0x54, 0x54,
+ };
+ /* 0xff * 2 / 3 = 0xaa */
+ static const unsigned char test_bits_32[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_32[] =
+ {
+ 0xaa, 0xaa, 0xaa,
+ };
+ static const unsigned char test_bits_33[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_33[] =
+ {
+ 0xa9, 0xa9, 0xa9,
+ };
+ static const unsigned char test_bits_34[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_34[] =
+ {
+ 0xa9, 0xa9, 0xa9,
+ };
+ static const unsigned char test_bits_35[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_35[] =
+ {
+ 0xff, 0xff, 0xff,
+ };
+
+ /* 1x4 -> 1x1 */
+ /* 0xff * 3 / 4 = 0xbf.4 */
+ static const unsigned char test_bits_36[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_36[] =
+ {
+ 0xbf, 0xbf, 0xbf,
+ };
+
+ /* 1x5 -> 1x1 */
+ /* 0xff * 4 / 5 = 0xcc */
+ static const unsigned char test_bits_37[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_37[] =
+ {
+ 0xcb, 0xcb, 0xcb,
+ };
+
+ /* Shrink vertically with a non-integer ratio */
+ /* 3x1 -> 2x1 */
+ static const unsigned char test_bits_38[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_38[] =
+ {
+ 0xd4, 0xd4, 0xd4, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char test_bits_39[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_39[] =
+ {
+ 0x54, 0x54, 0x54, PAD_ZERO
+ 0x55, 0x55, 0x55, PAD_ZERO
+ };
+ static const unsigned char test_bits_40[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_40[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xd4, 0xd4, 0xd4, PAD_ZERO
+ };
+ static const unsigned char test_bits_41[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_41[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x2a, 0x2a, 0x2a, PAD_ZERO
+ };
+ static const unsigned char test_bits_42[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_42[] =
+ {
+ 0xaa, 0xaa, 0xaa, PAD_ZERO
+ 0xa9, 0xa9, 0xa9, PAD_ZERO
+ };
+ static const unsigned char test_bits_43[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_43[] =
+ {
+ 0x2a, 0x2a, 0x2a, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char test_bits_44[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_44[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+
+ /* 4x1 -> 3x1 */
+ static const unsigned char test_bits_45[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_45[] =
+ {
+ 0x0f, 0x0f, 0x0f, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char test_bits_46[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_46[] =
+ {
+ 0xcf, 0xcf, 0xcf, PAD_ZERO
+ 0x7f, 0x7f, 0x7f, PAD_ZERO
+ 0x2f, 0x2f, 0x2f, PAD_ZERO
+ };
+ static const unsigned char test_bits_47[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_47[] =
+ {
+ 0x2f, 0x2f, 0x2f, PAD_ZERO
+ 0x7f, 0x7f, 0x7f, PAD_ZERO
+ 0xcf, 0xcf, 0xcf, PAD_ZERO
+ };
+ static const unsigned char test_bits_48[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_48[] =
+ {
+ 0xef, 0xef, 0xef, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xef, 0xef, 0xef, PAD_ZERO
+ };
+ static const unsigned char test_bits_49[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_49[] =
+ {
+ 0x0f, 0x0f, 0x0f, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x0f, 0x0f, 0x0f, PAD_ZERO
+ };
+
+ /* 5x1 -> 3x1 */
+ static const unsigned char test_bits_50[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_50[] =
+ {
+ 0x3f, 0x3f, 0x3f, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char test_bits_51[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char expected_bits_51[] =
+ {
+ 0x65, 0x65, 0x65, PAD_ZERO
+ 0x66, 0x66, 0x66, PAD_ZERO
+ 0x66, 0x66, 0x66, PAD_ZERO
+ };
+ static const unsigned char test_bits_52[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_52[] =
+ {
+ 0x99, 0x99, 0x99, PAD_ZERO
+ 0x98, 0x98, 0x98, PAD_ZERO
+ 0x98, 0x98, 0x98, PAD_ZERO
+ };
+
+ /* Stretch horizontally */
+ /* 1x1 -> 2x1 */
+ static const unsigned char test_bits_53[] =
+ {
+ 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_53[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ /* 2x1 -> 3x1 */
+ static const unsigned char test_bits_54[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_54[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ };
+ /* 3x1 -> 4x1 */
+ static const unsigned char test_bits_55[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_55[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ /* 4x1 -> 5x1 */
+ static const unsigned char test_bits_56[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_56[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+
+ /* Stretch vertically */
+ /* 1x1 -> 1x2 */
+ static const unsigned char test_bits_57[] =
+ {
+ 0xff, 0xff, 0xff,
+ };
+ static const unsigned char expected_bits_57[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ /* 1x2 -> 1x3 */
+ static const unsigned char test_bits_58[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_58[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ /* 1x3 -> 1x4 */
+ static const unsigned char test_bits_59[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_59[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ /* 1x4 -> 1x5 */
+ static const unsigned char test_bits_60[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char expected_bits_60[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+
+ /* Shrink both horizontally and vertically*/
+ /* 2x2 -> 1x1 */
+ /* 0xff / 4 = 0x3f.c */
+ static const unsigned char test_bits_61[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_61[] =
+ {
+ 0x40, 0x40, 0x40,
+ };
+ static const unsigned char test_bits_62[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_62[] =
+ {
+ 0x40, 0x40, 0x40,
+ };
+ static const unsigned char test_bits_63[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_63[] =
+ {
+ 0x40, 0x40, 0x40,
+ };
+ static const unsigned char test_bits_64[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_64[] =
+ {
+ 0x40, 0x40, 0x40,
+ };
+ /* 0xff * 2 / 4 = 0x7f.8 */
+ static const unsigned char test_bits_65[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_65[] =
+ {
+ 0x80, 0x80, 0x80,
+ };
+ static const unsigned char test_bits_66[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_66[] =
+ {
+ 0x80, 0x80, 0x80,
+ };
+ static const unsigned char test_bits_67[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_67[] =
+ {
+ 0xff, 0xff, 0xff,
+ };
+
+ /* Stretch horizontally and shrink vertically */
+ /* 2x2 -> 1x4 */
+ static const unsigned char test_bits_68[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_68[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char test_bits_69[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_69[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ static const unsigned char test_bits_70[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_70[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ static const unsigned char test_bits_71[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_71[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ static const unsigned char test_bits_72[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_72[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const unsigned char test_bits_73[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_73[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ /* 0xff * 2 / 4 = 0x7f.8 */
+ static const unsigned char test_bits_74[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_74[] =
+ {
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
+ };
+ static const unsigned char test_bits_75[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_75[] =
+ {
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
+ };
+ static const unsigned char test_bits_76[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_76[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ /* 0xfe * 2 / 4 = 0x7f */
+ static const unsigned char test_bits_77[] =
+ {
+ 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, PAD_ZERO PAD_ZERO
+ 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_77[] =
+ {
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
+ };
+
+ /* Stretch vertically and shrink horizontally */
+ /* 2x2 -> 4x1 */
+ static const unsigned char test_bits_78[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_78[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char test_bits_79[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_79[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char test_bits_80[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_80[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char test_bits_81[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_81[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ static const unsigned char test_bits_82[] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_82[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ static const unsigned char test_bits_83[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_83[] =
+ {
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ };
+ /* 0xff * 2 / 4 = 0x7f.8 */
+ static const unsigned char test_bits_84[] =
+ {
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_84[] =
+ {
+ 0x80, 0x80, 0x80, PAD_ZERO
+ 0x80, 0x80, 0x80, PAD_ZERO
+ 0x80, 0x80, 0x80, PAD_ZERO
+ 0x80, 0x80, 0x80, PAD_ZERO
+ };
+ static const unsigned char test_bits_85[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_85[] =
+ {
+ 0x80, 0x80, 0x80, PAD_ZERO
+ 0x80, 0x80, 0x80, PAD_ZERO
+ 0x80, 0x80, 0x80, PAD_ZERO
+ 0x80, 0x80, 0x80, PAD_ZERO
+ };
+ static const unsigned char test_bits_86[] =
+ {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, PAD_ZERO PAD_ZERO
+ 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_86[] =
+ {
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0xff, 0xff, 0xff, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ 0x00, 0x00, 0x00, PAD_ZERO
+ };
+ /* 0xfe * 2 / 4 = 0x7f */
+ static const unsigned char test_bits_87[] =
+ {
+ 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, PAD_ZERO PAD_ZERO
+ 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, PAD_ZERO PAD_ZERO
+ };
+ static const unsigned char expected_bits_87[] =
+ {
+ 0x7f, 0x7f, 0x7f, PAD_ZERO
+ 0x7f, 0x7f, 0x7f, PAD_ZERO
+ 0x7f, 0x7f, 0x7f, PAD_ZERO
+ 0x7f, 0x7f, 0x7f, PAD_ZERO
+ };
+
+#undef PAD_ZERO
+
+ static const struct
+ {
+ const unsigned char *src_bits;
+ size_t src_bits_size;
+ const unsigned char *dst_bits;
+ size_t dst_bits_size;
+ int bpp;
+ int src_width;
+ int src_height;
+ int dst_width;
+ int dst_height;
+ BOOL todo;
+ }
+ tests[] =
+ {
+#define BITS(x) test_bits_##x, sizeof(test_bits_##x), expected_bits_##x, sizeof(expected_bits_##x)
+
+ {BITS(0), 24, 1, 1, 1, 1},
+ {BITS(1), 24, 2, 1, 1, 1, TRUE},
+ {BITS(2), 24, 2, 1, 1, 1, TRUE},
+ {BITS(3), 24, 3, 1, 1, 1, TRUE},
+ {BITS(4), 24, 3, 1, 1, 1, TRUE},
+ {BITS(5), 24, 3, 1, 1, 1, TRUE},
+ {BITS(6), 24, 3, 1, 1, 1, TRUE},
+ {BITS(7), 24, 3, 1, 1, 1, TRUE},
+ {BITS(8), 24, 3, 1, 1, 1, TRUE},
+ {BITS(9), 24, 3, 1, 1, 1},
+ {BITS(10), 24, 4, 1, 1, 1, TRUE},
+ {BITS(11), 24, 5, 1, 1, 1, TRUE},
+ {BITS(12), 24, 3, 1, 2, 1, TRUE},
+ {BITS(13), 24, 3, 1, 2, 1, TRUE},
+ {BITS(14), 24, 3, 1, 2, 1, TRUE},
+ {BITS(15), 24, 3, 1, 2, 1, TRUE},
+ {BITS(16), 24, 3, 1, 2, 1, TRUE},
+ {BITS(17), 24, 3, 1, 2, 1, TRUE},
+ {BITS(18), 24, 3, 1, 2, 1},
+ {BITS(19), 24, 4, 1, 3, 1, TRUE},
+ {BITS(20), 24, 4, 1, 3, 1, TRUE},
+ {BITS(21), 24, 4, 1, 3, 1, TRUE},
+ {BITS(22), 24, 4, 1, 3, 1, TRUE},
+ {BITS(23), 24, 4, 1, 3, 1, TRUE},
+ {BITS(24), 24, 5, 1, 3, 1, TRUE},
+ {BITS(25), 24, 5, 1, 3, 1, TRUE},
+ {BITS(26), 24, 5, 1, 3, 1, TRUE},
+ {BITS(27), 24, 1, 2, 1, 1, TRUE},
+ {BITS(28), 24, 1, 2, 1, 1, TRUE},
+ {BITS(29), 24, 1, 3, 1, 1, TRUE},
+ {BITS(30), 24, 1, 3, 1, 1, TRUE},
+ {BITS(31), 24, 1, 3, 1, 1, TRUE},
+ {BITS(32), 24, 1, 3, 1, 1, TRUE},
+ {BITS(33), 24, 1, 3, 1, 1, TRUE},
+ {BITS(34), 24, 1, 3, 1, 1, TRUE},
+ {BITS(35), 24, 1, 3, 1, 1},
+ {BITS(36), 24, 1, 4, 1, 1, TRUE},
+ {BITS(37), 24, 1, 5, 1, 1, TRUE},
+ {BITS(38), 24, 1, 3, 1, 2, TRUE},
+ {BITS(39), 24, 1, 3, 1, 2, TRUE},
+ {BITS(40), 24, 1, 3, 1, 2, TRUE},
+ {BITS(41), 24, 1, 3, 1, 2, TRUE},
+ {BITS(42), 24, 1, 3, 1, 2, TRUE},
+ {BITS(43), 24, 1, 3, 1, 2, TRUE},
+ {BITS(44), 24, 1, 3, 1, 2},
+ {BITS(45), 24, 1, 4, 1, 3, TRUE},
+ {BITS(46), 24, 1, 4, 1, 3, TRUE},
+ {BITS(47), 24, 1, 4, 1, 3, TRUE},
+ {BITS(48), 24, 1, 4, 1, 3, TRUE},
+ {BITS(49), 24, 1, 4, 1, 3, TRUE},
+ {BITS(50), 24, 1, 5, 1, 3, TRUE},
+ {BITS(51), 24, 1, 5, 1, 3, TRUE},
+ {BITS(52), 24, 1, 5, 1, 3, TRUE},
+ {BITS(53), 24, 1, 1, 2, 1},
+ {BITS(54), 24, 2, 1, 3, 1, TRUE},
+ {BITS(55), 24, 3, 1, 4, 1, TRUE},
+ {BITS(56), 24, 4, 1, 5, 1, TRUE},
+ {BITS(57), 24, 1, 1, 1, 2},
+ {BITS(58), 24, 1, 2, 1, 3, TRUE},
+ {BITS(59), 24, 1, 3, 1, 4, TRUE},
+ {BITS(60), 24, 1, 4, 1, 5, TRUE},
+ {BITS(61), 24, 2, 2, 1, 1, TRUE},
+ {BITS(62), 24, 2, 2, 1, 1, TRUE},
+ {BITS(63), 24, 2, 2, 1, 1, TRUE},
+ {BITS(64), 24, 2, 2, 1, 1, TRUE},
+ {BITS(65), 24, 2, 2, 1, 1, TRUE},
+ {BITS(66), 24, 2, 2, 1, 1, TRUE},
+ {BITS(67), 24, 2, 2, 1, 1},
+ {BITS(68), 24, 2, 2, 4, 1, TRUE},
+ {BITS(69), 24, 2, 2, 4, 1, TRUE},
+ {BITS(70), 24, 2, 2, 4, 1, TRUE},
+ {BITS(71), 24, 2, 2, 4, 1, TRUE},
+ {BITS(72), 24, 2, 2, 4, 1, TRUE},
+ {BITS(73), 24, 2, 2, 4, 1, TRUE},
+ {BITS(74), 24, 2, 2, 4, 1, TRUE},
+ {BITS(75), 24, 2, 2, 4, 1, TRUE},
+ {BITS(76), 24, 2, 2, 4, 1, TRUE},
+ {BITS(77), 24, 2, 2, 4, 1, TRUE},
+ {BITS(78), 24, 2, 2, 1, 4, TRUE},
+ {BITS(79), 24, 2, 2, 1, 4, TRUE},
+ {BITS(80), 24, 2, 2, 1, 4, TRUE},
+ {BITS(81), 24, 2, 2, 1, 4, TRUE},
+ {BITS(82), 24, 2, 2, 1, 4, TRUE},
+ {BITS(83), 24, 2, 2, 1, 4, TRUE},
+ {BITS(84), 24, 2, 2, 1, 4, TRUE},
+ {BITS(85), 24, 2, 2, 1, 4, TRUE},
+ {BITS(86), 24, 2, 2, 1, 4, TRUE},
+ {BITS(87), 24, 2, 2, 1, 4, TRUE},
+
+#undef BITS
+ };
+
+ unsigned char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
+ HBITMAP src_bmp, dst_bmp, old_src_bmp, old_dst_bmp;
+ BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
+ unsigned char *src_bits, *dst_bits;
+ HDC dc, src_dc, dst_dc;
+ int i, ret;
+
+ dc = GetDC(0);
+
+ memset(&bmi_buffer, 0, sizeof(bmi_buffer));
+ bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi->bmiHeader.biPlanes = 1;
+ bmi->bmiHeader.biCompression = BI_RGB;
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ winetest_push_context("Test %d", i);
+
+ bmi->bmiHeader.biBitCount = tests[i].bpp;
+ bmi->bmiHeader.biWidth = tests[i].src_width;
+ bmi->bmiHeader.biHeight = tests[i].src_height;
+ src_dc = CreateCompatibleDC(dc);
+ src_bmp = CreateDIBSection(src_dc, bmi, DIB_RGB_COLORS, (void **)&src_bits, NULL, 0);
+ ok(src_bmp && src_bits, "CreateDIBSection failed, error %u.\n", GetLastError());
+ memcpy(src_bits, tests[i].src_bits, tests[i].src_bits_size);
+ old_src_bmp = SelectObject(src_dc, src_bmp);
+
+ bmi->bmiHeader.biWidth = tests[i].dst_width;
+ bmi->bmiHeader.biHeight = tests[i].dst_height;
+ dst_dc = CreateCompatibleDC(dc);
+ dst_bmp = CreateDIBSection(dst_dc, bmi, DIB_RGB_COLORS, (void **)&dst_bits, NULL, 0);
+ ok(dst_bmp && dst_bits, "CreateDIBSection failed, error %u.\n", GetLastError());
+ old_dst_bmp = SelectObject(dst_dc, dst_bmp);
+
+ SetStretchBltMode(dst_dc, HALFTONE);
+ ret = GetStretchBltMode(dst_dc);
+ ok(ret == HALFTONE, "Expected mode %#x, got %#x\n", HALFTONE, ret);
+ ret = StretchBlt(dst_dc, 0, 0, tests[i].dst_width, tests[i].dst_height, src_dc, 0, 0,
+ tests[i].src_width, tests[i].src_height, SRCCOPY);
+ ok(ret, "StretchBlt failed, error %u.\n", GetLastError());
+
+ ret = memcmp(dst_bits, tests[i].dst_bits, tests[i].dst_bits_size);
+ todo_wine_if(tests[i].todo)
+ ok(!ret, "Bits mismatch.\n");
+ if (ret)
+ dump_bits(tests[i].bpp, tests[i].dst_width, tests[i].dst_bits, dst_bits,
+ tests[i].dst_bits_size, "StretchBlt_HALFTONE");
+
+ SelectObject(dst_dc, old_dst_bmp);
+ SelectObject(src_dc, old_src_bmp);
+ DeleteObject(dst_bmp);
+ DeleteObject(src_bmp);
+ DeleteDC(dst_dc);
+ DeleteDC(src_dc);
+
+ winetest_pop_context();
+ }
+
+ ReleaseDC(0, dc);
+}
+
static void check_StretchDIBits_pixel(HDC hdcDst, UINT32 *dstBuffer, UINT32 *srcBuffer,
DWORD dwRop, UINT32 expected, int line)
{
@@ -5963,6 +7098,7 @@ START_TEST(bitmap)
test_CreateBitmap();
test_BitBlt();
test_StretchBlt();
+ test_StretchBlt_HALFTONE();
test_StretchDIBits();
test_GdiAlphaBlend();
test_GdiGradientFill();
--
2.30.2
2
1
14 Jun '21
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
Superseded patch 206830.
v4:
- Discard nCursor parameter in ME_InsertOLEFromCursor().
- Rename ME_InsertOLEFromCursor() to editor_insert_oleobj().
---
dlls/riched20/caret.c | 16 ++++++++++++----
dlls/riched20/editor.c | 2 +-
dlls/riched20/editor.h | 2 +-
dlls/riched20/richole.c | 2 +-
dlls/riched20/tests/richole.c | 18 +++++++++---------
5 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 1f4c3903a38..beac8af50a1 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -455,15 +455,23 @@ static struct re_object* create_re_object(const REOBJECT *reo)
return reobj;
}
-void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor)
+void editor_insert_oleobj(ME_TextEditor *editor, const REOBJECT *reo)
{
ME_Run *run, *prev;
const WCHAR space = ' ';
struct re_object *reobj_prev = NULL;
- ME_Cursor *cursor = editor->pCursors + nCursor;
- ME_Style *style = style_get_insert_style( editor, cursor );
+ ME_Cursor *cursor, cursor_from_ofs;
+ ME_Style *style;
+
+ if (reo->cp == REO_CP_SELECTION)
+ cursor = editor->pCursors;
+ else
+ {
+ cursor_from_char_ofs( editor, reo->cp, &cursor_from_ofs );
+ cursor = &cursor_from_ofs;
+ }
+ style = style_get_insert_style( editor, cursor );
- /* FIXME no no no */
if (ME_IsSelection(editor))
ME_DeleteSelection(editor);
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index d4aadc325f9..cc02604767e 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1172,7 +1172,7 @@ static HRESULT insert_static_object(ME_TextEditor *editor, HENHMETAFILE hemf, HB
reobject.dwFlags = 0; /* FIXME */
reobject.dwUser = 0;
- ME_InsertOLEFromCursor(editor, &reobject, 0);
+ editor_insert_oleobj(editor, &reobject);
hr = S_OK;
}
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 141e9034a6a..fdf3e068fe9 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -188,7 +188,7 @@ int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to) DEC
BOOL ME_IsSelection(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_DeleteSelection(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_SendSelChange(ME_TextEditor *editor) DECLSPEC_HIDDEN;
-void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor) DECLSPEC_HIDDEN;
+void editor_insert_oleobj( ME_TextEditor *editor, const REOBJECT *reo ) DECLSPEC_HIDDEN;
BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars, BOOL bForce) DECLSPEC_HIDDEN;
int ME_GetTextLength(ME_TextEditor *editor) DECLSPEC_HIDDEN;
int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index 72840a4cafa..03572511ff7 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -1367,7 +1367,7 @@ IRichEditOle_fnInsertObject(IRichEditOle *iface, REOBJECT *reo)
if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER;
- ME_InsertOLEFromCursor(services->editor, reo, 0);
+ editor_insert_oleobj(services->editor, reo);
ME_CommitUndo(services->editor);
ME_UpdateRepaint(services->editor, FALSE);
return S_OK;
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index a76f9fdaf2e..a8c48994613 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -3377,15 +3377,15 @@ static void test_InsertObject(void)
SendMessageW(hwnd, EM_SETSEL, 3, 4);
result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0);
- todo_wine ok(result == SEL_OBJECT, "Got selection type: %x.\n", result);
- todo_wine CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo1.polesite, 1);
+ ok(result == SEL_OBJECT, "Got selection type: %x.\n", result);
+ CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo1.polesite, 1);
SendMessageW(hwnd, EM_SETSEL, 2, 4);
result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0);
- todo_wine ok(result == (SEL_TEXT | SEL_OBJECT), "Got selection type: %x.\n", result);
+ ok(result == (SEL_TEXT | SEL_OBJECT), "Got selection type: %x.\n", result);
SendMessageW(hwnd, EM_SETSEL, 5, 6);
- todo_wine CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo2.polesite, 2);
+ CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo2.polesite, 2);
expected_string = L"abc\xfffc""d\xfffc""efg";
gettextex.cb = sizeof(buffer);
@@ -3408,7 +3408,7 @@ static void test_InsertObject(void)
SendMessageA(hwnd, EM_SETSEL, 0, -1);
result = SendMessageA(hwnd, EM_GETSELTEXT, (WPARAM)sizeof(bufferA), (LPARAM)bufferA);
ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result);
- todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
+ ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
memset(bufferA, 0, sizeof(bufferA));
textrange.lpstrText = bufferA;
@@ -3416,7 +3416,7 @@ static void test_InsertObject(void)
textrange.chrg.cpMax = 11;
result = SendMessageA(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&textrange);
ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result);
- todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
+ ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
expected_string = L"abc\xfffc""d\xfffc""efg\r";
hr = ITextDocument_Range(doc, 0, 11, &range);
@@ -3467,7 +3467,7 @@ static void test_InsertObject(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
string = GlobalLock(stgmedium.hGlobal);
ok(lstrlenW(string) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(string));
- todo_wine ok(!lstrcmpW(string, expected_string), "Got wrong content: %s.\n", debugstr_w(string));
+ ok(!lstrcmpW(string, expected_string), "Got wrong content: %s.\n", debugstr_w(string));
GlobalUnlock(stgmedium.hGlobal);
expected_string = L"abc\xfffc""d\xfffc""efg";
@@ -3491,7 +3491,7 @@ static void test_InsertObject(void)
SendMessageA(hwnd, EM_SETSEL, 0, -1);
result = SendMessageA(hwnd, EM_GETSELTEXT, (WPARAM)sizeof(bufferA), (LPARAM)bufferA);
ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result);
- todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
+ ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
memset(bufferA, 0, sizeof(bufferA));
textrange.lpstrText = bufferA;
@@ -3499,7 +3499,7 @@ static void test_InsertObject(void)
textrange.chrg.cpMax = 11;
result = SendMessageA(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&textrange);
ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result);
- todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
+ ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA);
expected_string = L"abc\xfffc""d\xfffc""efg";
hr = ITextDocument_Range(doc, 0, 11, &range);
--
2.30.2
2
3
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/painting.c | 2 +-
dlls/gdi32/tests/dc.c | 10 ++++++++++
2 files changed, 11 insertions(+), 1 deletion(-)
2
1
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
include/wine/afd.h | 19 ++++++
server/sock.c | 166 +++++++++++++++++++++++++++++----------------
2 files changed, 128 insertions(+), 57 deletions(-)
diff --git a/include/wine/afd.h b/include/wine/afd.h
index 595fc572a1c..c4a15d6688c 100644
--- a/include/wine/afd.h
+++ b/include/wine/afd.h
@@ -36,6 +36,25 @@
#define IOCTL_AFD_RECV CTL_CODE(FILE_DEVICE_BEEP, 0x805, METHOD_NEITHER, FILE_ANY_ACCESS)
#define IOCTL_AFD_POLL CTL_CODE(FILE_DEVICE_BEEP, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS)
+enum afd_poll_bit
+{
+ AFD_POLL_BIT_READ = 0,
+ AFD_POLL_BIT_OOB = 1,
+ AFD_POLL_BIT_WRITE = 2,
+ AFD_POLL_BIT_HUP = 3,
+ AFD_POLL_BIT_RESET = 4,
+ AFD_POLL_BIT_CLOSE = 5,
+ AFD_POLL_BIT_CONNECT = 6,
+ AFD_POLL_BIT_ACCEPT = 7,
+ AFD_POLL_BIT_CONNECT_ERR = 8,
+ /* IOCTL_AFD_GET_EVENTS has space for 13 events. */
+ AFD_POLL_BIT_UNK1 = 9,
+ AFD_POLL_BIT_UNK2 = 10,
+ AFD_POLL_BIT_UNK3 = 11,
+ AFD_POLL_BIT_UNK4 = 12,
+ AFD_POLL_BIT_COUNT = 13,
+};
+
#define AFD_POLL_READ 0x0001
#define AFD_POLL_OOB 0x0002
#define AFD_POLL_WRITE 0x0004
diff --git a/server/sock.c b/server/sock.c
index 66440a540dc..2a22bb2340b 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -146,14 +146,14 @@ struct sock
struct fd *fd; /* socket file descriptor */
enum connection_state state; /* connection state */
unsigned int mask; /* event mask */
- /* pending FD_* events which have not yet been reported to the application */
+ /* pending AFD_POLL_* events which have not yet been reported to the application */
unsigned int pending_events;
- /* FD_* events which have already been reported and should not be selected
- * for again until reset by a relevant call.
+ /* AFD_POLL_* events which have already been reported and should not be
+ * selected for again until reset by a relevant call.
*
- * For example, if FD_READ is set here and not in pending_events, it has
- * already been reported and consumed, and we should not report it again,
- * even if POLLIN is signaled, until it is reset by e.g recv().
+ * For example, if AFD_POLL_READ is set here and not in pending_events, it
+ * has already been reported and consumed, and we should not report it
+ * again, even if POLLIN is signaled, until it is reset by e.g recv().
*
* If an event has been signaled and not consumed yet, it will be set in
* both pending_events and reported_events (as we should only ever report
@@ -167,7 +167,7 @@ struct sock
user_handle_t window; /* window to send the message to */
unsigned int message; /* message to send */
obj_handle_t wparam; /* message wparam (socket handle) */
- unsigned int errors[FD_MAX_EVENTS]; /* event errors */
+ unsigned int errors[AFD_POLL_BIT_COUNT]; /* event errors */
timeout_t connect_time;/* time the socket was connected */
struct sock *deferred; /* socket that waits for a deferred accept */
struct async_queue read_q; /* queue for asynchronous reads */
@@ -338,27 +338,21 @@ static int sockaddr_from_unix( const union unix_sockaddr *uaddr, struct WS_socka
}
}
-/* Permutation of 0..FD_MAX_EVENTS - 1 representing the order in which
- * we post messages if there are multiple events. Used to send
- * messages. The problem is if there is both a FD_CONNECT event and,
- * say, an FD_READ event available on the same socket, we want to
- * notify the app of the connect event first. Otherwise it may
- * discard the read event because it thinks it hasn't connected yet.
- */
-static const int event_bitorder[FD_MAX_EVENTS] =
+/* some events are generated at the same time but must be sent in a particular
+ * order (e.g. CONNECT must be sent before READ) */
+static const enum afd_poll_bit event_bitorder[] =
{
- FD_CONNECT_BIT,
- FD_ACCEPT_BIT,
- FD_OOB_BIT,
- FD_WRITE_BIT,
- FD_READ_BIT,
- FD_CLOSE_BIT,
- 6, 7, 8, 9 /* leftovers */
+ AFD_POLL_BIT_CONNECT,
+ AFD_POLL_BIT_CONNECT_ERR,
+ AFD_POLL_BIT_ACCEPT,
+ AFD_POLL_BIT_OOB,
+ AFD_POLL_BIT_WRITE,
+ AFD_POLL_BIT_READ,
+ AFD_POLL_BIT_RESET,
+ AFD_POLL_BIT_HUP,
+ AFD_POLL_BIT_CLOSE,
};
-/* Flags that make sense only for SOCK_STREAM sockets */
-#define STREAM_FLAG_MASK ((unsigned int) (FD_CONNECT | FD_ACCEPT | FD_WINE_LISTENING | FD_WINE_CONNECTED))
-
typedef enum {
SOCK_SHUTDOWN_ERROR = -1,
SOCK_SHUTDOWN_EOF = 0,
@@ -425,6 +419,53 @@ static int sock_reselect( struct sock *sock )
return ev;
}
+static unsigned int afd_poll_flag_to_win32( unsigned int flags )
+{
+ static const unsigned int map[] =
+ {
+ FD_READ, /* READ */
+ FD_OOB, /* OOB */
+ FD_WRITE, /* WRITE */
+ FD_CLOSE, /* HUP */
+ FD_CLOSE, /* RESET */
+ 0, /* CLOSE */
+ FD_CONNECT, /* CONNECT */
+ FD_ACCEPT, /* ACCEPT */
+ FD_CONNECT, /* CONNECT_ERR */
+ };
+
+ unsigned int i, ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(map); ++i)
+ {
+ if (flags & (1 << i)) ret |= map[i];
+ }
+
+ return ret;
+}
+
+static unsigned int afd_poll_flag_from_win32( unsigned int flags )
+{
+ static const unsigned int map[] =
+ {
+ AFD_POLL_READ,
+ AFD_POLL_WRITE,
+ AFD_POLL_OOB,
+ AFD_POLL_ACCEPT,
+ AFD_POLL_CONNECT | AFD_POLL_CONNECT_ERR,
+ AFD_POLL_RESET | AFD_POLL_HUP,
+ };
+
+ unsigned int i, ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(map); ++i)
+ {
+ if (flags & (1 << i)) ret |= map[i];
+ }
+
+ return ret;
+}
+
/* wake anybody waiting on the socket event or send the associated message */
static void sock_wake_up( struct sock *sock )
{
@@ -440,12 +481,12 @@ static void sock_wake_up( struct sock *sock )
if (sock->window)
{
if (debug_level) fprintf(stderr, "signalling events %x win %08x\n", events, sock->window );
- for (i = 0; i < FD_MAX_EVENTS; i++)
+ for (i = 0; i < ARRAY_SIZE(event_bitorder); i++)
{
- int event = event_bitorder[i];
+ enum afd_poll_bit event = event_bitorder[i];
if (events & (1 << event))
{
- lparam_t lparam = (1 << event) | (sock->errors[event] << 16);
+ lparam_t lparam = afd_poll_flag_to_win32(1 << event) | (sock->errors[event] << 16);
post_message( sock->window, sock->message, sock->wparam, lparam );
}
}
@@ -810,7 +851,7 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
return event;
}
-static void post_socket_event( struct sock *sock, unsigned int event_bit, unsigned int error )
+static void post_socket_event( struct sock *sock, enum afd_poll_bit event_bit, unsigned int error )
{
unsigned int event = (1 << event_bit);
@@ -830,28 +871,30 @@ static void sock_dispatch_events( struct sock *sock, enum connection_state prevs
break;
case SOCK_CONNECTING:
- if (event & (POLLOUT | POLLERR | POLLHUP))
- post_socket_event( sock, FD_CONNECT_BIT, sock_get_error( error ) );
+ if (event & POLLOUT)
+ post_socket_event( sock, AFD_POLL_BIT_CONNECT, 0 );
+ if (event & (POLLERR | POLLHUP))
+ post_socket_event( sock, AFD_POLL_BIT_CONNECT_ERR, sock_get_error( error ) );
break;
case SOCK_LISTENING:
if (event & (POLLIN | POLLERR | POLLHUP))
- post_socket_event( sock, FD_ACCEPT_BIT, sock_get_error( error ) );
+ post_socket_event( sock, AFD_POLL_BIT_ACCEPT, sock_get_error( error ) );
break;
case SOCK_CONNECTED:
case SOCK_CONNECTIONLESS:
if (event & POLLIN)
- post_socket_event( sock, FD_READ_BIT, 0 );
+ post_socket_event( sock, AFD_POLL_BIT_READ, 0 );
if (event & POLLOUT)
- post_socket_event( sock, FD_WRITE_BIT, 0 );
+ post_socket_event( sock, AFD_POLL_BIT_WRITE, 0 );
if (event & POLLPRI)
- post_socket_event( sock, FD_OOB_BIT, 0 );
+ post_socket_event( sock, AFD_POLL_BIT_OOB, 0 );
if (event & (POLLERR | POLLHUP))
- post_socket_event( sock, FD_CLOSE_BIT, sock_get_error( error ) );
+ post_socket_event( sock, AFD_POLL_BIT_HUP, sock_get_error( error ) );
break;
}
@@ -1006,7 +1049,7 @@ static int sock_get_poll_events( struct fd *fd )
return POLLOUT;
case SOCK_LISTENING:
- if (!list_empty( &sock->accept_list ) || (mask & FD_ACCEPT))
+ if (!list_empty( &sock->accept_list ) || (mask & AFD_POLL_ACCEPT))
ev |= POLLIN;
break;
@@ -1020,17 +1063,17 @@ static int sock_get_poll_events( struct fd *fd )
{
if (async_waiting( &sock->read_q )) ev |= POLLIN | POLLPRI;
}
- else if (!sock->rd_shutdown && (mask & FD_READ))
+ else if (!sock->rd_shutdown && (mask & AFD_POLL_READ))
ev |= POLLIN | POLLPRI;
- /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
- else if (sock->state == SOCK_CONNECTED && (mask & FD_CLOSE) && !(sock->reported_events & FD_READ))
+ /* We use POLLIN with 0 bytes recv() as hangup indication for stream sockets. */
+ else if (sock->state == SOCK_CONNECTED && (mask & AFD_POLL_HUP) && !(sock->reported_events & AFD_POLL_READ))
ev |= POLLIN;
if (async_queued( &sock->write_q ))
{
if (async_waiting( &sock->write_q )) ev |= POLLOUT;
}
- else if (!sock->wr_shutdown && (mask & FD_WRITE))
+ else if (!sock->wr_shutdown && (mask & AFD_POLL_WRITE))
{
ev |= POLLOUT;
}
@@ -1465,8 +1508,8 @@ static struct sock *accept_socket( struct sock *sock )
}
}
clear_error();
- sock->pending_events &= ~FD_ACCEPT;
- sock->reported_events &= ~FD_ACCEPT;
+ sock->pending_events &= ~AFD_POLL_ACCEPT;
+ sock->reported_events &= ~AFD_POLL_ACCEPT;
sock_reselect( sock );
return acceptsock;
}
@@ -1514,8 +1557,8 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
acceptsock->fd = newfd;
clear_error();
- sock->pending_events &= ~FD_ACCEPT;
- sock->reported_events &= ~FD_ACCEPT;
+ sock->pending_events &= ~AFD_POLL_ACCEPT;
+ sock->reported_events &= ~AFD_POLL_ACCEPT;
sock_reselect( sock );
return TRUE;
@@ -1791,7 +1834,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
/* a listening socket can no longer be accepted into */
allow_fd_caching( sock->fd );
- /* we may already be selecting for FD_ACCEPT */
+ /* we may already be selecting for AFD_POLL_ACCEPT */
sock_reselect( sock );
return 0;
}
@@ -2374,11 +2417,11 @@ DECL_HANDLER(set_socket_event)
FILE_WRITE_ATTRIBUTES, &sock_ops))) return;
if (get_unix_fd( sock->fd ) == -1) return;
old_event = sock->event;
- sock->mask = req->mask;
+ sock->mask = afd_poll_flag_from_win32( req->mask );
if (req->window)
{
- sock->pending_events &= ~req->mask;
- sock->reported_events &= ~req->mask;
+ sock->pending_events &= ~sock->mask;
+ sock->reported_events &= ~sock->mask;
}
sock->event = NULL;
sock->window = req->window;
@@ -2393,7 +2436,7 @@ DECL_HANDLER(set_socket_event)
sock->nonblocking = 1;
/* if a network event is pending, signal the event object
- it is possible that FD_CONNECT or FD_ACCEPT network events has happened
+ it is possible that CONNECT or ACCEPT network events has happened
before a WSAEventSelect() was done on it.
(when dealing with Asynchronous socket) */
sock_wake_up( sock );
@@ -2405,14 +2448,23 @@ DECL_HANDLER(set_socket_event)
/* get socket event parameters */
DECL_HANDLER(get_socket_event)
{
+ unsigned int errors[FD_MAX_EVENTS] = {0};
struct sock *sock;
if (!(sock = (struct sock *)get_handle_obj( current->process, req->handle,
FILE_READ_ATTRIBUTES, &sock_ops ))) return;
if (get_unix_fd( sock->fd ) == -1) return;
- reply->mask = sock->mask;
- reply->pmask = sock->pending_events;
- set_reply_data( sock->errors, min( get_reply_max_size(), sizeof(sock->errors) ));
+ reply->mask = afd_poll_flag_to_win32( sock->mask );
+ reply->pmask = afd_poll_flag_to_win32( sock->pending_events );
+
+ errors[FD_READ_BIT] = sock->errors[AFD_POLL_BIT_READ];
+ errors[FD_WRITE_BIT] = sock->errors[AFD_POLL_BIT_WRITE];
+ errors[FD_OOB_BIT] = sock->errors[AFD_POLL_BIT_OOB];
+ errors[FD_ACCEPT_BIT] = sock->errors[AFD_POLL_BIT_ACCEPT];
+ errors[FD_CONNECT_BIT] = sock->errors[AFD_POLL_BIT_CONNECT_ERR];
+ if (!(errors[FD_CLOSE_BIT] = sock->errors[AFD_POLL_BIT_HUP]))
+ errors[FD_CLOSE_BIT] = sock->errors[AFD_POLL_BIT_RESET];
+ set_reply_data( errors, min( get_reply_max_size(), sizeof(errors) ));
if (req->service)
{
@@ -2499,8 +2551,8 @@ DECL_HANDLER(recv_socket)
if (status == STATUS_PENDING && sock->rd_shutdown) status = STATUS_PIPE_DISCONNECTED;
- sock->pending_events &= ~(req->oob ? FD_OOB : FD_READ);
- sock->reported_events &= ~(req->oob ? FD_OOB : FD_READ);
+ sock->pending_events &= ~(req->oob ? AFD_POLL_OOB : AFD_POLL_READ);
+ sock->reported_events &= ~(req->oob ? AFD_POLL_OOB : AFD_POLL_READ);
if ((async = create_request_async( fd, get_fd_comp_flags( fd ), &req->async )))
{
@@ -2570,8 +2622,8 @@ DECL_HANDLER(send_socket)
if (status != STATUS_SUCCESS)
{
/* send() calls only clear and reselect events if unsuccessful. */
- sock->pending_events &= ~FD_WRITE;
- sock->reported_events &= ~FD_WRITE;
+ sock->pending_events &= ~AFD_POLL_WRITE;
+ sock->reported_events &= ~AFD_POLL_WRITE;
}
/* If we had a short write and the socket is nonblocking (and the client is
--
2.30.2
1
4