[GDIPLUS] Sync with Wine 3.0. CORE-14225

This commit is contained in:
Amine Khaldi 2018-01-19 00:17:41 +01:00
parent 7a00f240c6
commit 007122e774
10 changed files with 1824 additions and 491 deletions

View File

@ -243,7 +243,7 @@ static const char HatchBrushes[][8] = {
{ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff }, /* HatchStyleDarkHorizontal */ { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff }, /* HatchStyleDarkHorizontal */
}; };
GpStatus get_hatch_data(HatchStyle hatchstyle, const char **result) GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result)
{ {
if (hatchstyle < sizeof(HatchBrushes) / sizeof(HatchBrushes[0])) if (hatchstyle < sizeof(HatchBrushes) / sizeof(HatchBrushes[0]))
{ {
@ -257,12 +257,15 @@ GpStatus get_hatch_data(HatchStyle hatchstyle, const char **result)
/****************************************************************************** /******************************************************************************
* GdipCreateHatchBrush [GDIPLUS.@] * GdipCreateHatchBrush [GDIPLUS.@]
*/ */
GpStatus WINGDIPAPI GdipCreateHatchBrush(HatchStyle hatchstyle, ARGB forecol, ARGB backcol, GpHatch **brush) GpStatus WINGDIPAPI GdipCreateHatchBrush(GpHatchStyle hatchstyle, ARGB forecol, ARGB backcol, GpHatch **brush)
{ {
TRACE("(%d, %d, %d, %p)\n", hatchstyle, forecol, backcol, brush); TRACE("(%d, %d, %d, %p)\n", hatchstyle, forecol, backcol, brush);
if(!brush) return InvalidParameter; if(!brush) return InvalidParameter;
if(hatchstyle < HatchStyleMin || hatchstyle > HatchStyleMax)
return InvalidParameter;
*brush = heap_alloc_zero(sizeof(GpHatch)); *brush = heap_alloc_zero(sizeof(GpHatch));
if (!*brush) return OutOfMemory; if (!*brush) return OutOfMemory;
@ -491,9 +494,12 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF* rect
TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable, TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
wrap, line); wrap, line);
if (!rect || !rect->Width || !rect->Height) if (!rect || !line || wrap == WrapModeClamp)
return InvalidParameter; return InvalidParameter;
if (!rect->Width || !rect->Height)
return OutOfMemory;
angle = fmodf(angle, 360); angle = fmodf(angle, 360);
if (angle < 0) if (angle < 0)
angle += 360; angle += 360;
@ -951,7 +957,7 @@ GpStatus WINGDIPAPI GdipGetHatchForegroundColor(GpHatch *brush, ARGB *forecol)
return Ok; return Ok;
} }
GpStatus WINGDIPAPI GdipGetHatchStyle(GpHatch *brush, HatchStyle *hatchstyle) GpStatus WINGDIPAPI GdipGetHatchStyle(GpHatch *brush, GpHatchStyle *hatchstyle)
{ {
TRACE("(%p, %p)\n", brush, hatchstyle); TRACE("(%p, %p)\n", brush, hatchstyle);

View File

@ -1378,33 +1378,36 @@ static int match_name_table_language( const tt_name_record *name, LANGID lang )
return 0; return 0;
} }
static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *data, WCHAR *ret, DWORD len ) static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *data )
{ {
WORD name_len = GET_BE_WORD(name->length); WORD name_len = GET_BE_WORD(name->length);
WORD codepage; WORD codepage;
WCHAR *ret;
int len;
switch (GET_BE_WORD(name->platform_id)) switch (GET_BE_WORD(name->platform_id))
{ {
case TT_PLATFORM_APPLE_UNICODE: case TT_PLATFORM_APPLE_UNICODE:
case TT_PLATFORM_MICROSOFT: case TT_PLATFORM_MICROSOFT:
if (name_len >= len*sizeof(WCHAR)) ret = heap_alloc((name_len / 2 + 1) * sizeof(WCHAR));
return NULL;
for (len = 0; len < name_len / 2; len++) for (len = 0; len < name_len / 2; len++)
ret[len] = (data[len * 2] << 8) | data[len * 2 + 1]; ret[len] = (data[len * 2] << 8) | data[len * 2 + 1];
ret[len] = 0; ret[len] = 0;
return ret; return ret;
case TT_PLATFORM_MACINTOSH: case TT_PLATFORM_MACINTOSH:
codepage = get_mac_code_page( name ); codepage = get_mac_code_page( name );
len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, ret, len-1 ); len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, NULL, 0 ) + 1;
if (!len) if (!len)
return NULL; return NULL;
ret = heap_alloc(len * sizeof(WCHAR));
len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, ret, len - 1 );
ret[len] = 0; ret[len] = 0;
return ret; return ret;
} }
return NULL; return NULL;
} }
static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR *ret, DWORD len ) static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id )
{ {
LANGID lang = GetSystemDefaultLangID(); LANGID lang = GetSystemDefaultLangID();
const tt_header *header; const tt_header *header;
@ -1465,8 +1468,9 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR
if (best_lang) if (best_lang)
{ {
WCHAR *ret;
name_record = (const tt_name_record*)(name_table + 1) + best_index; name_record = (const tt_name_record*)(name_table + 1) + best_index;
ret = copy_name_table_string( name_record, mem+ofs+GET_BE_WORD(name_record->offset), ret, len ); ret = copy_name_table_string( name_record, mem+ofs+GET_BE_WORD(name_record->offset) );
TRACE( "name %u found platform %u lang %04x %s\n", GET_BE_WORD(name_record->name_id), TRACE( "name %u found platform %u lang %04x %s\n", GET_BE_WORD(name_record->name_id),
GET_BE_WORD(name_record->platform_id), GET_BE_WORD(name_record->language_id), debugstr_w( ret )); GET_BE_WORD(name_record->platform_id), GET_BE_WORD(name_record->language_id), debugstr_w( ret ));
return ret; return ret;
@ -1482,43 +1486,45 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, D
GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection, GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
GDIPCONST void* memory, INT length) GDIPCONST void* memory, INT length)
{ {
WCHAR buf[32], *name; WCHAR *name;
DWORD count = 0; DWORD count = 0;
HANDLE font; HANDLE font;
GpStatus ret = Ok;
TRACE("%p, %p, %d\n", fontCollection, memory, length); TRACE("%p, %p, %d\n", fontCollection, memory, length);
if (!fontCollection || !memory || !length) if (!fontCollection || !memory || !length)
return InvalidParameter; return InvalidParameter;
name = load_ttf_name_id(memory, length, NAME_ID_FULL_FONT_NAME, buf, sizeof(buf)/sizeof(*buf)); name = load_ttf_name_id(memory, length, NAME_ID_FULL_FONT_NAME);
if (!name) if (!name)
return OutOfMemory; return OutOfMemory;
font = AddFontMemResourceEx((void*)memory, length, NULL, &count); font = AddFontMemResourceEx((void*)memory, length, NULL, &count);
TRACE("%s: %p/%u\n", debugstr_w(name), font, count); TRACE("%s: %p/%u\n", debugstr_w(name), font, count);
if (!font || !count) if (!font || !count)
return InvalidParameter; ret = InvalidParameter;
else
if (count)
{ {
HDC hdc; HDC hdc;
LOGFONTW lfw; LOGFONTW lfw;
hdc = CreateCompatibleDC(0); hdc = CreateCompatibleDC(0);
/* Truncate name if necessary, GDI32 can't deal with long names */
if(lstrlenW(name) > LF_FACESIZE - 1)
name[LF_FACESIZE - 1] = 0;
lfw.lfCharSet = DEFAULT_CHARSET; lfw.lfCharSet = DEFAULT_CHARSET;
lstrcpyW(lfw.lfFaceName, name); lstrcpyW(lfw.lfFaceName, name);
lfw.lfPitchAndFamily = 0; lfw.lfPitchAndFamily = 0;
if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)fontCollection, 0)) if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)fontCollection, 0))
{ ret = OutOfMemory;
DeleteDC(hdc);
return OutOfMemory;
}
DeleteDC(hdc); DeleteDC(hdc);
} }
return Ok; heap_free(name);
return ret;
} }
/***************************************************************************** /*****************************************************************************

View File

@ -615,7 +615,7 @@
615 stub GdipGetEffectParameterSize 615 stub GdipGetEffectParameterSize
616 stub GdipGetEffectParameters 616 stub GdipGetEffectParameters
617 stdcall GdipSetEffectParameters(ptr ptr long) 617 stdcall GdipSetEffectParameters(ptr ptr long)
618 stdcall GdipInitializePalette(ptr long long long ptr) 618 stdcall -stub GdipInitializePalette(ptr long long long ptr)
619 stdcall GdipBitmapCreateApplyEffect(ptr long ptr ptr ptr ptr long ptr ptr) 619 stdcall GdipBitmapCreateApplyEffect(ptr long ptr ptr ptr ptr long ptr ptr)
620 stdcall GdipBitmapApplyEffect(ptr ptr ptr long ptr ptr) 620 stdcall GdipBitmapApplyEffect(ptr ptr ptr long ptr ptr)
621 stdcall GdipBitmapGetHistogram(ptr long long ptr ptr ptr ptr) 621 stdcall GdipBitmapGetHistogram(ptr long long ptr ptr ptr ptr)

View File

@ -129,6 +129,7 @@ extern GpStatus METAFILE_DrawImagePointsRect(GpMetafile* metafile, GpImage *imag
extern GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val) DECLSPEC_HIDDEN; extern GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) DECLSPEC_HIDDEN; extern GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) DECLSPEC_HIDDEN; extern GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) DECLSPEC_HIDDEN;
extern void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1, extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN; REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN;
@ -147,7 +148,7 @@ extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN;
typedef struct region_element region_element; typedef struct region_element region_element;
extern void delete_element(region_element *element) DECLSPEC_HIDDEN; extern void delete_element(region_element *element) DECLSPEC_HIDDEN;
extern GpStatus get_hatch_data(HatchStyle hatchstyle, const char **result) DECLSPEC_HIDDEN; extern GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result) DECLSPEC_HIDDEN;
static inline INT gdip_round(REAL x) static inline INT gdip_round(REAL x)
{ {
@ -270,6 +271,7 @@ struct GpGraphics{
INT origin_x, origin_y; INT origin_x, origin_y;
INT gdi_transform_acquire_count, gdi_transform_save; INT gdi_transform_acquire_count, gdi_transform_save;
GpMatrix gdi_transform; GpMatrix gdi_transform;
HRGN gdi_clip;
/* For giving the caller an HDC when we technically can't: */ /* For giving the caller an HDC when we technically can't: */
HBITMAP temp_hbitmap; HBITMAP temp_hbitmap;
int temp_hbitmap_width; int temp_hbitmap_width;
@ -284,7 +286,7 @@ struct GpBrush{
struct GpHatch{ struct GpHatch{
GpBrush brush; GpBrush brush;
HatchStyle hatchstyle; GpHatchStyle hatchstyle;
ARGB forecol; ARGB forecol;
ARGB backcol; ARGB backcol;
}; };
@ -378,6 +380,38 @@ struct GpImage{
LONG busy; LONG busy;
}; };
#define EmfPlusObjectTableSize 64
typedef enum EmfPlusObjectType
{
ObjectTypeInvalid,
ObjectTypeBrush,
ObjectTypePen,
ObjectTypePath,
ObjectTypeRegion,
ObjectTypeImage,
ObjectTypeFont,
ObjectTypeStringFormat,
ObjectTypeImageAttributes,
ObjectTypeCustomLineCap,
ObjectTypeMax = ObjectTypeCustomLineCap,
} EmfPlusObjectType;
/* Deserialized EmfPlusObject record. */
struct emfplus_object {
EmfPlusObjectType type;
union {
GpBrush *brush;
GpPen *pen;
GpPath *path;
GpRegion *region;
GpImage *image;
GpFont *font;
GpImageAttributes *image_attributes;
void *object;
} u;
};
struct GpMetafile{ struct GpMetafile{
GpImage image; GpImage image;
GpRectF bounds; GpRectF bounds;
@ -411,6 +445,7 @@ struct GpMetafile{
GpRegion *base_clip; /* clip region in device space for all metafile output */ GpRegion *base_clip; /* clip region in device space for all metafile output */
GpRegion *clip; /* clip region within the metafile */ GpRegion *clip; /* clip region within the metafile */
struct list containers; struct list containers;
struct emfplus_object objtable[EmfPlusObjectTableSize];
}; };
struct GpBitmap{ struct GpBitmap{
@ -454,6 +489,12 @@ struct color_remap_table{
ColorMap *colormap; ColorMap *colormap;
}; };
enum imageattr_noop{
IMAGEATTR_NOOP_UNDEFINED,
IMAGEATTR_NOOP_SET,
IMAGEATTR_NOOP_CLEAR,
};
struct GpImageAttributes{ struct GpImageAttributes{
WrapMode wrap; WrapMode wrap;
ARGB outside_color; ARGB outside_color;
@ -463,6 +504,7 @@ struct GpImageAttributes{
struct color_remap_table colorremaptables[ColorAdjustTypeCount]; struct color_remap_table colorremaptables[ColorAdjustTypeCount];
BOOL gamma_enabled[ColorAdjustTypeCount]; BOOL gamma_enabled[ColorAdjustTypeCount];
REAL gamma[ColorAdjustTypeCount]; REAL gamma[ColorAdjustTypeCount];
enum imageattr_noop noop[ColorAdjustTypeCount];
}; };
struct GpFont{ struct GpFont{
@ -535,6 +577,30 @@ struct GpRegion{
region_element node; region_element node;
}; };
struct memory_buffer
{
const BYTE *buffer;
INT size, pos;
};
static inline void init_memory_buffer(struct memory_buffer *mbuf, const BYTE *buffer, INT size)
{
mbuf->buffer = buffer;
mbuf->size = size;
mbuf->pos = 0;
}
static inline const void *buffer_read(struct memory_buffer *mbuf, INT size)
{
if (mbuf->size - mbuf->pos >= size)
{
const void *data = mbuf->buffer + mbuf->pos;
mbuf->pos += size;
return data;
}
return NULL;
}
typedef GpStatus (*gdip_format_string_callback)(HDC hdc, typedef GpStatus (*gdip_format_string_callback)(HDC hdc,
GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font, GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,

View File

@ -302,13 +302,6 @@ static void round_points(POINT *pti, GpPointF *ptf, INT count)
} }
} }
static void transform_and_round_points(GpGraphics *graphics, POINT *pti,
GpPointF *ptf, INT count)
{
gdip_transform_points(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, ptf, count);
round_points(pti, ptf, count);
}
static void gdi_alpha_blend(GpGraphics *graphics, INT dst_x, INT dst_y, INT dst_width, INT dst_height, static void gdi_alpha_blend(GpGraphics *graphics, INT dst_x, INT dst_y, INT dst_width, INT dst_height,
HDC hdc, INT src_x, INT src_y, INT src_width, INT src_height) HDC hdc, INT src_x, INT src_y, INT src_width, INT src_height)
{ {
@ -355,6 +348,17 @@ static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn)
GdipDeleteRegion(rgn); GdipDeleteRegion(rgn);
} }
if (stat == Ok && graphics->gdi_clip)
{
if (*hrgn)
CombineRgn(*hrgn, *hrgn, graphics->gdi_clip, RGN_AND);
else
{
*hrgn = CreateRectRgn(0,0,0,0);
CombineRgn(*hrgn, graphics->gdi_clip, graphics->gdi_clip, RGN_COPY);
}
}
return stat; return stat;
} }
@ -505,8 +509,6 @@ static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst
save = SaveDC(graphics->hdc); save = SaveDC(graphics->hdc);
SetViewportOrgEx(graphics->hdc, 0, 0, NULL);
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY); ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
if (hregion) if (hregion)
@ -529,23 +531,12 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL, fmt); return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL, fmt);
} }
/* NOTE: start and end pixels must be in pre-multiplied ARGB format */
static inline ARGB blend_colors_premult(ARGB start, ARGB end, REAL position)
{
UINT pos = position * 255.0f + 0.5f;
return
(((((start >> 24) ) << 8) + (((end >> 24) ) - ((start >> 24) )) * pos) >> 8) << 24 |
(((((start >> 16) & 0xff) << 8) + (((end >> 16) & 0xff) - ((start >> 16) & 0xff)) * pos) >> 8) << 16 |
(((((start >> 8) & 0xff) << 8) + (((end >> 8) & 0xff) - ((start >> 8) & 0xff)) * pos) >> 8) << 8 |
(((((start ) & 0xff) << 8) + (((end ) & 0xff) - ((start ) & 0xff)) * pos) >> 8);
}
static ARGB blend_colors(ARGB start, ARGB end, REAL position) static ARGB blend_colors(ARGB start, ARGB end, REAL position)
{ {
INT start_a, end_a, final_a; INT start_a, end_a, final_a;
INT pos; INT pos;
pos = (INT)(position * 255.0f + 0.5f); pos = gdip_round(position * 0xff);
start_a = ((start >> 24) & 0xff) * (pos ^ 0xff); start_a = ((start >> 24) & 0xff) * (pos ^ 0xff);
end_a = ((end >> 24) & 0xff) * pos; end_a = ((end >> 24) & 0xff) * pos;
@ -685,6 +676,11 @@ PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE d
UINT x, y; UINT x, y;
INT i; INT i;
if ((attributes->noop[type] == IMAGEATTR_NOOP_UNDEFINED &&
attributes->noop[ColorAdjustTypeDefault] == IMAGEATTR_NOOP_SET) ||
(attributes->noop[type] == IMAGEATTR_NOOP_SET))
return fmt;
if (attributes->colorkeys[type].enabled || if (attributes->colorkeys[type].enabled ||
attributes->colorkeys[ColorAdjustTypeDefault].enabled) attributes->colorkeys[ColorAdjustTypeDefault].enabled)
{ {
@ -946,11 +942,6 @@ static ARGB sample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT wi
return ((DWORD*)(bits))[(x - src_rect->X) + (y - src_rect->Y) * src_rect->Width]; return ((DWORD*)(bits))[(x - src_rect->X) + (y - src_rect->Y) * src_rect->Width];
} }
static inline int positive_ceilf(float f)
{
return f - (int)f > 0.0f ? f + 1.0f : f;
}
static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width, static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width,
UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes, UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes,
InterpolationMode interpolation, PixelOffsetMode offset_mode) InterpolationMode interpolation, PixelOffsetMode offset_mode)
@ -971,12 +962,12 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT
ARGB top, bottom; ARGB top, bottom;
float x_offset; float x_offset;
leftx = (INT)point->X; leftxf = floorf(point->X);
leftxf = (REAL)leftx; leftx = (INT)leftxf;
rightx = positive_ceilf(point->X); rightx = (INT)ceilf(point->X);
topy = (INT)point->Y; topyf = floorf(point->Y);
topyf = (REAL)topy; topy = (INT)topyf;
bottomy = positive_ceilf(point->Y); bottomy = (INT)ceilf(point->Y);
if (leftx == rightx && topy == bottomy) if (leftx == rightx && topy == bottomy)
return sample_bitmap_pixel(src_rect, bits, width, height, return sample_bitmap_pixel(src_rect, bits, width, height,
@ -1020,75 +1011,6 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT
} }
} }
static ARGB resample_bitmap_pixel_premult(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width,
UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes,
InterpolationMode interpolation, PixelOffsetMode offset_mode)
{
static int fixme;
switch (interpolation)
{
default:
if (!fixme++)
FIXME("Unimplemented interpolation %i\n", interpolation);
/* fall-through */
case InterpolationModeBilinear:
{
REAL leftxf, topyf;
INT leftx, rightx, topy, bottomy;
ARGB topleft, topright, bottomleft, bottomright;
ARGB top, bottom;
float x_offset;
leftx = (INT)point->X;
leftxf = (REAL)leftx;
rightx = positive_ceilf(point->X);
topy = (INT)point->Y;
topyf = (REAL)topy;
bottomy = positive_ceilf(point->Y);
if (leftx == rightx && topy == bottomy)
return sample_bitmap_pixel(src_rect, bits, width, height,
leftx, topy, attributes);
topleft = sample_bitmap_pixel(src_rect, bits, width, height,
leftx, topy, attributes);
topright = sample_bitmap_pixel(src_rect, bits, width, height,
rightx, topy, attributes);
bottomleft = sample_bitmap_pixel(src_rect, bits, width, height,
leftx, bottomy, attributes);
bottomright = sample_bitmap_pixel(src_rect, bits, width, height,
rightx, bottomy, attributes);
x_offset = point->X - leftxf;
top = blend_colors_premult(topleft, topright, x_offset);
bottom = blend_colors_premult(bottomleft, bottomright, x_offset);
return blend_colors_premult(top, bottom, point->Y - topyf);
}
case InterpolationModeNearestNeighbor:
{
FLOAT pixel_offset;
switch (offset_mode)
{
default:
case PixelOffsetModeNone:
case PixelOffsetModeHighSpeed:
pixel_offset = 0.5;
break;
case PixelOffsetModeHalf:
case PixelOffsetModeHighQuality:
pixel_offset = 0.0;
break;
}
return sample_bitmap_pixel(src_rect, bits, width, height,
floorf(point->X + pixel_offset), point->Y + pixel_offset, attributes);
}
}
}
static REAL intersect_line_scanline(const GpPointF *p1, const GpPointF *p2, REAL y) static REAL intersect_line_scanline(const GpPointF *p1, const GpPointF *p2, REAL y)
{ {
return (p1->X - p2->X) * (p2->Y - y) / (p2->Y - p1->Y) + p2->X; return (p1->X - p2->X) * (p2->Y - y) / (p2->Y - p1->Y) + p2->X;
@ -2312,7 +2234,7 @@ static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font,
GdipTransformMatrixPoints(&xform, pt, 3); GdipTransformMatrixPoints(&xform, pt, 3);
} }
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 3); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, pt, 3);
angle = -gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X)); angle = -gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X));
rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+ rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
(pt[1].X-pt[0].X)*(pt[1].X-pt[0].X)); (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
@ -2342,6 +2264,20 @@ GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
return GdipCreateFromHDC2(hdc, NULL, graphics); return GdipCreateFromHDC2(hdc, NULL, graphics);
} }
static void get_gdi_transform(GpGraphics *graphics, GpMatrix *matrix)
{
XFORM xform;
if (graphics->hdc == NULL)
{
GdipSetMatrixElements(matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
return;
}
GetTransform(graphics->hdc, 0x204, &xform);
GdipSetMatrixElements(matrix, xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
}
GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **graphics) GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **graphics)
{ {
GpStatus retval; GpStatus retval;
@ -2391,7 +2327,19 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra
(*graphics)->busy = FALSE; (*graphics)->busy = FALSE;
(*graphics)->textcontrast = 4; (*graphics)->textcontrast = 4;
list_init(&(*graphics)->containers); list_init(&(*graphics)->containers);
#ifdef __REACTOS__
(*graphics)->contid = GDIP_GET_NEW_CONTID_FOR(*graphics); (*graphics)->contid = GDIP_GET_NEW_CONTID_FOR(*graphics);
#else
(*graphics)->contid = 0;
#endif
get_gdi_transform(*graphics, &(*graphics)->gdi_transform);
(*graphics)->gdi_clip = CreateRectRgn(0,0,0,0);
if (!GetClipRgn(hdc, (*graphics)->gdi_clip))
{
DeleteObject((*graphics)->gdi_clip);
(*graphics)->gdi_clip = NULL;
}
TRACE("<-- %p\n", *graphics); TRACE("<-- %p\n", *graphics);
@ -2406,6 +2354,7 @@ GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics)
if(!*graphics) return OutOfMemory; if(!*graphics) return OutOfMemory;
GdipSetMatrixElements(&(*graphics)->worldtrans, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); GdipSetMatrixElements(&(*graphics)->worldtrans, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
GdipSetMatrixElements(&(*graphics)->gdi_transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
if((retval = GdipCreateRegion(&(*graphics)->clip)) != Ok){ if((retval = GdipCreateRegion(&(*graphics)->clip)) != Ok){
heap_free(*graphics); heap_free(*graphics);
@ -2431,7 +2380,11 @@ GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics)
(*graphics)->busy = FALSE; (*graphics)->busy = FALSE;
(*graphics)->textcontrast = 4; (*graphics)->textcontrast = 4;
list_init(&(*graphics)->containers); list_init(&(*graphics)->containers);
#ifdef __REACTOS__
(*graphics)->contid = GDIP_GET_NEW_CONTID_FOR(*graphics); (*graphics)->contid = GDIP_GET_NEW_CONTID_FOR(*graphics);
#else
(*graphics)->contid = 0;
#endif
TRACE("<-- %p\n", *graphics); TRACE("<-- %p\n", *graphics);
@ -2516,6 +2469,8 @@ GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
GdipDeleteRegion(graphics->clip); GdipDeleteRegion(graphics->clip);
DeleteObject(graphics->gdi_clip);
/* Native returns ObjectBusy on the second free, instead of crashing as we'd /* Native returns ObjectBusy on the second free, instead of crashing as we'd
* do otherwise, but we can't have that in the test suite because it means * do otherwise, but we can't have that in the test suite because it means
* accessing freed memory. */ * accessing freed memory. */
@ -3151,10 +3106,8 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
lockeddata.Scan0 = src_data; lockeddata.Scan0 = src_data;
if (!do_resampling && bitmap->format == PixelFormat32bppPARGB) if (!do_resampling && bitmap->format == PixelFormat32bppPARGB)
lockeddata.PixelFormat = apply_image_attributes(imageAttributes, NULL, 0, 0, 0, ColorAdjustTypeBitmap, bitmap->format); lockeddata.PixelFormat = apply_image_attributes(imageAttributes, NULL, 0, 0, 0, ColorAdjustTypeBitmap, bitmap->format);
else if (imageAttributes != &defaultImageAttributes)
lockeddata.PixelFormat = PixelFormat32bppARGB;
else else
lockeddata.PixelFormat = PixelFormat32bppPARGB; lockeddata.PixelFormat = PixelFormat32bppARGB;
stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf, stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf,
lockeddata.PixelFormat, &lockeddata); lockeddata.PixelFormat, &lockeddata);
@ -3174,8 +3127,6 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
if (do_resampling) if (do_resampling)
{ {
REAL delta_xx, delta_xy, delta_yx, delta_yy;
/* Transform the bits as needed to the destination. */ /* Transform the bits as needed to the destination. */
dst_data = dst_dyn_data = heap_alloc_zero(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top)); dst_data = dst_dyn_data = heap_alloc_zero(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top));
if (!dst_data) if (!dst_data)
@ -3193,42 +3144,24 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X; y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X;
y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y; y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y;
delta_yy = dst_area.top * y_dy; for (x=dst_area.left; x<dst_area.right; x++)
delta_yx = dst_area.top * y_dx;
for (y=dst_area.top; y<dst_area.bottom; y++)
{ {
delta_xx = dst_area.left * x_dx; for (y=dst_area.top; y<dst_area.bottom; y++)
delta_xy = dst_area.left * x_dy;
for (x=dst_area.left; x<dst_area.right; x++)
{ {
GpPointF src_pointf; GpPointF src_pointf;
ARGB *dst_color; ARGB *dst_color;
src_pointf.X = dst_to_src_points[0].X + delta_xx + delta_yx; src_pointf.X = dst_to_src_points[0].X + x * x_dx + y * y_dx;
src_pointf.Y = dst_to_src_points[0].Y + delta_xy + delta_yy; src_pointf.Y = dst_to_src_points[0].Y + x * x_dy + y * y_dy;
dst_color = (ARGB*)(dst_data + dst_stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left)); dst_color = (ARGB*)(dst_data + dst_stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left));
if (src_pointf.X >= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight) if (src_pointf.X >= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight)
{ *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
if (lockeddata.PixelFormat != PixelFormat32bppPARGB) imageAttributes, interpolation, offset_mode);
*dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
imageAttributes, interpolation, offset_mode);
else
*dst_color = resample_bitmap_pixel_premult(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
imageAttributes, interpolation, offset_mode);
}
else else
*dst_color = 0; *dst_color = 0;
delta_xx += x_dx;
delta_yx += y_dx;
} }
delta_xy += x_dy;
delta_yy += y_dy;
} }
} }
else else
@ -3322,9 +3255,9 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
stat = get_clip_hrgn(graphics, &hrgn); stat = get_clip_hrgn(graphics, &hrgn);
if (stat == Ok && hrgn) if (stat == Ok)
{ {
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
DeleteObject(hrgn); DeleteObject(hrgn);
} }
@ -3565,8 +3498,7 @@ static GpStatus GDI32_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *pat
if (retval != Ok) if (retval != Ok)
goto end; goto end;
if (hrgn) ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
gdi_transform_acquire(graphics); gdi_transform_acquire(graphics);
@ -3907,7 +3839,7 @@ static GpStatus SOFTWARE_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *
points[1].X = pen->width; points[1].X = pen->width;
points[2].Y = pen->width; points[2].Y = pen->width;
stat = GdipTransformPoints(graphics, CoordinateSpaceDevice, stat = gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice,
CoordinateSpaceWorld, points, 3); CoordinateSpaceWorld, points, 3);
if (stat != Ok) if (stat != Ok)
@ -3931,7 +3863,7 @@ static GpStatus SOFTWARE_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *
stat = GdipCreateMatrix(&transform); stat = GdipCreateMatrix(&transform);
if (stat == Ok) if (stat == Ok)
stat = get_graphics_transform(graphics, CoordinateSpaceDevice, stat = get_graphics_transform(graphics, WineCoordinateSpaceGdiDevice,
CoordinateSpaceWorld, transform); CoordinateSpaceWorld, transform);
} }
else else
@ -3939,7 +3871,7 @@ static GpStatus SOFTWARE_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *
/* Set flatness based on the final coordinate space */ /* Set flatness based on the final coordinate space */
GpMatrix t; GpMatrix t;
stat = get_graphics_transform(graphics, CoordinateSpaceDevice, stat = get_graphics_transform(graphics, WineCoordinateSpaceGdiDevice,
CoordinateSpaceWorld, &t); CoordinateSpaceWorld, &t);
if (stat != Ok) if (stat != Ok)
@ -4254,8 +4186,7 @@ static GpStatus GDI32_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath
if (retval != Ok) if (retval != Ok)
goto end; goto end;
if (hrgn) ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
gdi_transform_acquire(graphics); gdi_transform_acquire(graphics);
@ -4542,32 +4473,30 @@ static GpStatus GDI32_GdipFillRegion(GpGraphics* graphics, GpBrush* brush,
if(!graphics->hdc || !brush_can_fill_path(brush, TRUE)) if(!graphics->hdc || !brush_can_fill_path(brush, TRUE))
return NotImplemented; return NotImplemented;
status = GdipGetRegionHRgn(region, graphics, &hrgn);
if(status != Ok)
return status;
save_state = SaveDC(graphics->hdc); save_state = SaveDC(graphics->hdc);
EndPath(graphics->hdc); EndPath(graphics->hdc);
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
DeleteObject(hrgn);
hrgn = NULL; hrgn = NULL;
status = get_clip_hrgn(graphics, &hrgn); status = get_clip_hrgn(graphics, &hrgn);
if (status != Ok) if (status != Ok)
{ {
RestoreDC(graphics->hdc, save_state); RestoreDC(graphics->hdc, save_state);
return status; return status;
} }
if (hrgn) ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
DeleteObject(hrgn);
status = GdipGetRegionHRgn(region, graphics, &hrgn);
if (status != Ok)
{ {
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); RestoreDC(graphics->hdc, save_state);
DeleteObject(hrgn); return status;
} }
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
DeleteObject(hrgn);
if (GetClipBox(graphics->hdc, &rc) != NULLREGION) if (GetClipBox(graphics->hdc, &rc) != NULLREGION)
{ {
BeginPath(graphics->hdc); BeginPath(graphics->hdc);
@ -5371,7 +5300,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
pt[1].Y = 0.0; pt[1].Y = 0.0;
pt[2].X = 0.0; pt[2].X = 0.0;
pt[2].Y = 1.0; pt[2].Y = 1.0;
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 3); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, pt, 3);
args.rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+ args.rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
(pt[1].X-pt[0].X)*(pt[1].X-pt[0].X)); (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+ args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
@ -5400,9 +5329,13 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
args.regions = regions; args.regions = regions;
gdi_transform_acquire(graphics);
stat = gdip_format_string(hdc, string, length, font, &scaled_rect, stringFormat, stat = gdip_format_string(hdc, string, length, font, &scaled_rect, stringFormat,
(stringFormat->attr & StringFormatFlagsNoClip) != 0, measure_ranges_callback, &args); (stringFormat->attr & StringFormatFlagsNoClip) != 0, measure_ranges_callback, &args);
gdi_transform_release(graphics);
SelectObject(hdc, oldfont); SelectObject(hdc, oldfont);
DeleteObject(gdifont); DeleteObject(gdifont);
@ -5490,7 +5423,7 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
pt[1].Y = 0.0; pt[1].Y = 0.0;
pt[2].X = 0.0; pt[2].X = 0.0;
pt[2].Y = 1.0; pt[2].Y = 1.0;
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 3); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, pt, 3);
args.rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+ args.rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
(pt[1].X-pt[0].X)*(pt[1].X-pt[0].X)); (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+ args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
@ -5525,9 +5458,13 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
args.linesfilled = &lines; args.linesfilled = &lines;
lines = glyphs = 0; lines = glyphs = 0;
gdi_transform_acquire(graphics);
gdip_format_string(hdc, string, length, font, &scaled_rect, format, TRUE, gdip_format_string(hdc, string, length, font, &scaled_rect, format, TRUE,
measure_string_callback, &args); measure_string_callback, &args);
gdi_transform_release(graphics);
if (linesfilled) *linesfilled = lines; if (linesfilled) *linesfilled = lines;
if (codepointsfitted) *codepointsfitted = glyphs; if (codepointsfitted) *codepointsfitted = glyphs;
@ -5657,7 +5594,7 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
pt[1].Y = 0.0; pt[1].Y = 0.0;
pt[2].X = 0.0; pt[2].X = 0.0;
pt[2].Y = 1.0; pt[2].Y = 1.0;
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 3); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, pt, 3);
rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+ rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
(pt[1].X-pt[0].X)*(pt[1].X-pt[0].X)); (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+ rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
@ -5667,7 +5604,8 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
rectcpy[1].Y = rectcpy[0].Y = rect->Y; rectcpy[1].Y = rectcpy[0].Y = rect->Y;
rectcpy[2].X = rectcpy[1].X = rect->X + rect->Width; rectcpy[2].X = rectcpy[1].X = rect->X + rect->Width;
rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height; rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height;
transform_and_round_points(graphics, corners, rectcpy, 4); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, rectcpy, 4);
round_points(corners, rectcpy, 4);
margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0; margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
margin_x *= units_scale(font->unit, graphics->unit, graphics->xres); margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
@ -5706,12 +5644,16 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
args.rel_width = rel_width; args.rel_width = rel_width;
args.rel_height = rel_height; args.rel_height = rel_height;
gdi_transform_acquire(graphics);
GetTextMetricsW(hdc, &textmetric); GetTextMetricsW(hdc, &textmetric);
args.ascent = textmetric.tmAscent / rel_height; args.ascent = textmetric.tmAscent / rel_height;
gdip_format_string(hdc, string, length, font, &scaled_rect, format, TRUE, gdip_format_string(hdc, string, length, font, &scaled_rect, format, TRUE,
draw_string_callback, &args); draw_string_callback, &args);
gdi_transform_release(graphics);
DeleteObject(rgn); DeleteObject(rgn);
DeleteObject(gdifont); DeleteObject(gdifont);
@ -6311,6 +6253,7 @@ GpStatus WINGDIPAPI GdipSetClipHrgn(GpGraphics *graphics, HRGN hrgn, CombineMode
{ {
GpRegion *region; GpRegion *region;
GpStatus status; GpStatus status;
GpMatrix transform;
TRACE("(%p, %p, %d)\n", graphics, hrgn, mode); TRACE("(%p, %p, %d)\n", graphics, hrgn, mode);
@ -6320,14 +6263,21 @@ GpStatus WINGDIPAPI GdipSetClipHrgn(GpGraphics *graphics, HRGN hrgn, CombineMode
if(graphics->busy) if(graphics->busy)
return ObjectBusy; return ObjectBusy;
/* hrgn is already in device units */ /* hrgn is in gdi32 device units */
status = GdipCreateRegionHrgn(hrgn, &region); status = GdipCreateRegionHrgn(hrgn, &region);
if(status != Ok)
return status;
status = GdipCombineRegionRegion(graphics->clip, region, mode); if (status == Ok)
{
status = get_graphics_transform(graphics, CoordinateSpaceDevice, WineCoordinateSpaceGdiDevice, &transform);
GdipDeleteRegion(region); if (status == Ok)
status = GdipTransformRegion(region, &transform);
if (status == Ok)
status = GdipCombineRegionRegion(graphics->clip, region, mode);
GdipDeleteRegion(region);
}
return status; return status;
} }
@ -6723,31 +6673,10 @@ GpStatus WINGDIPAPI GdipGetClip(GpGraphics *graphics, GpRegion *region)
return Ok; return Ok;
} }
static void get_gdi_transform(GpGraphics *graphics, GpMatrix *matrix)
{
XFORM xform;
if (graphics->hdc == NULL)
{
GdipSetMatrixElements(matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
return;
}
if (graphics->gdi_transform_acquire_count)
{
*matrix = graphics->gdi_transform;
return;
}
GetTransform(graphics->hdc, 0x204, &xform);
GdipSetMatrixElements(matrix, xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
}
GpStatus gdi_transform_acquire(GpGraphics *graphics) GpStatus gdi_transform_acquire(GpGraphics *graphics)
{ {
if (graphics->gdi_transform_acquire_count == 0 && graphics->hdc) if (graphics->gdi_transform_acquire_count == 0 && graphics->hdc)
{ {
get_gdi_transform(graphics, &graphics->gdi_transform);
graphics->gdi_transform_save = SaveDC(graphics->hdc); graphics->gdi_transform_save = SaveDC(graphics->hdc);
SetGraphicsMode(graphics->hdc, GM_COMPATIBLE); SetGraphicsMode(graphics->hdc, GM_COMPATIBLE);
SetMapMode(graphics->hdc, MM_TEXT); SetMapMode(graphics->hdc, MM_TEXT);
@ -6762,7 +6691,7 @@ GpStatus gdi_transform_release(GpGraphics *graphics)
{ {
if (graphics->gdi_transform_acquire_count <= 0) if (graphics->gdi_transform_acquire_count <= 0)
{ {
ERR("called without matching gdi_transform_acquire"); ERR("called without matching gdi_transform_acquire\n");
return GenericError; return GenericError;
} }
if (graphics->gdi_transform_acquire_count == 1 && graphics->hdc) if (graphics->gdi_transform_acquire_count == 1 && graphics->hdc)
@ -6800,7 +6729,7 @@ GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_spac
case WineCoordinateSpaceGdiDevice: case WineCoordinateSpaceGdiDevice:
{ {
GpMatrix gdixform; GpMatrix gdixform;
get_gdi_transform(graphics, &gdixform); gdixform = graphics->gdi_transform;
stat = GdipInvertMatrix(&gdixform); stat = GdipInvertMatrix(&gdixform);
if (stat != Ok) if (stat != Ok)
break; break;
@ -6841,9 +6770,7 @@ GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_spac
/* else fall-through */ /* else fall-through */
case CoordinateSpaceDevice: case CoordinateSpaceDevice:
{ {
GpMatrix gdixform; GdipMultiplyMatrix(matrix, &graphics->gdi_transform, MatrixOrderAppend);
get_gdi_transform(graphics, &gdixform);
GdipMultiplyMatrix(matrix, &gdixform, MatrixOrderAppend);
break; break;
} }
} }
@ -7015,7 +6942,7 @@ GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT
GpMatrix xform = *matrix; GpMatrix xform = *matrix;
GdipTransformMatrixPoints(&xform, pt, 3); GdipTransformMatrixPoints(&xform, pt, 3);
} }
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 3); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, pt, 3);
rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+ rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
(pt[1].X-pt[0].X)*(pt[1].X-pt[0].X)); (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+ rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
@ -7102,22 +7029,26 @@ static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT1
status = get_clip_hrgn(graphics, &hrgn); status = get_clip_hrgn(graphics, &hrgn);
if (status == Ok && hrgn) if (status == Ok)
{ {
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
DeleteObject(hrgn); DeleteObject(hrgn);
} }
pt = positions[0]; pt = positions[0];
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &pt, 1); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, &pt, 1);
get_font_hfont(graphics, font, format, &hfont, matrix); get_font_hfont(graphics, font, format, &hfont, matrix);
SelectObject(graphics->hdc, hfont); SelectObject(graphics->hdc, hfont);
SetTextAlign(graphics->hdc, TA_BASELINE|TA_LEFT); SetTextAlign(graphics->hdc, TA_BASELINE|TA_LEFT);
gdi_transform_acquire(graphics);
ExtTextOutW(graphics->hdc, gdip_round(pt.X), gdip_round(pt.Y), eto_flags, NULL, text, length, NULL); ExtTextOutW(graphics->hdc, gdip_round(pt.X), gdip_round(pt.Y), eto_flags, NULL, text, length, NULL);
gdi_transform_release(graphics);
RestoreDC(graphics->hdc, save_state); RestoreDC(graphics->hdc, save_state);
DeleteObject(hfont); DeleteObject(hfont);
@ -7165,7 +7096,8 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
{ {
real_position = positions[0]; real_position = positions[0];
transform_and_round_points(graphics, pti, &real_position, 1); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, &real_position, 1);
round_points(pti, &real_position, 1);
} }
else else
{ {
@ -7178,7 +7110,8 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
memcpy(real_positions, positions, sizeof(PointF) * length); memcpy(real_positions, positions, sizeof(PointF) * length);
transform_and_round_points(graphics, pti, real_positions, length); gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, real_positions, length);
round_points(pti, real_positions, length);
heap_free(real_positions); heap_free(real_positions);
} }
@ -7318,10 +7251,14 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
heap_free(text_mask); heap_free(text_mask);
gdi_transform_acquire(graphics);
/* draw the result */ /* draw the result */
stat = alpha_blend_pixels(graphics, min_x, min_y, pixel_data, pixel_area.Width, stat = alpha_blend_pixels(graphics, min_x, min_y, pixel_data, pixel_area.Width,
pixel_area.Height, pixel_data_stride, PixelFormat32bppARGB); pixel_area.Height, pixel_data_stride, PixelFormat32bppARGB);
gdi_transform_release(graphics);
heap_free(pixel_data); heap_free(pixel_data);
return stat; return stat;

View File

@ -38,19 +38,13 @@ static const struct
{ {
{ &GUID_WICPixelFormatBlackWhite, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW }, { &GUID_WICPixelFormatBlackWhite, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW },
{ &GUID_WICPixelFormat1bppIndexed, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW }, { &GUID_WICPixelFormat1bppIndexed, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW },
{ &GUID_WICPixelFormat4bppIndexed, PixelFormat4bppIndexed, WICBitmapPaletteTypeFixedHalftone8 },
{ &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 }, { &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 },
{ &GUID_WICPixelFormat8bppIndexed, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat8bppIndexed, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat16bppBGR555, PixelFormat16bppRGB555, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat16bppBGR555, PixelFormat16bppRGB555, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat24bppBGR, PixelFormat24bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat24bppBGR, PixelFormat24bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat32bppBGR, PixelFormat32bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppBGR, PixelFormat32bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat48bppRGB, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat32bppCMYK, PixelFormat32bppCMYK, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat32bppGrayFloat, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedGray256 },
{ &GUID_WICPixelFormat64bppCMYK, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat64bppRGBA, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
{ NULL } { NULL }
}; };
@ -2074,24 +2068,7 @@ static GpStatus free_image_data(GpImage *image)
heap_free(((GpBitmap*)image)->prop_item); heap_free(((GpBitmap*)image)->prop_item);
} }
else if (image->type == ImageTypeMetafile) else if (image->type == ImageTypeMetafile)
{ METAFILE_Free((GpMetafile *)image);
GpMetafile *metafile = (GpMetafile*)image;
heap_free(metafile->comment_data);
DeleteEnhMetaFile(CloseEnhMetaFile(metafile->record_dc));
if (!metafile->preserve_hemf)
DeleteEnhMetaFile(metafile->hemf);
if (metafile->record_graphics)
{
WARN("metafile closed while recording\n");
/* not sure what to do here; for now just prevent the graphics from functioning or using this object */
metafile->record_graphics->image = NULL;
metafile->record_graphics->busy = TRUE;
}
if (metafile->record_stream)
{
IStream_Release(metafile->record_stream);
}
}
else else
{ {
WARN("invalid image: %p\n", image); WARN("invalid image: %p\n", image);
@ -4568,7 +4545,7 @@ static GpStatus encode_image_jpeg(GpImage *image, IStream* stream,
static GpStatus encode_image_gif(GpImage *image, IStream* stream, static GpStatus encode_image_gif(GpImage *image, IStream* stream,
GDIPCONST EncoderParameters* params) GDIPCONST EncoderParameters* params)
{ {
return encode_image_wic(image, stream, &GUID_ContainerFormatGif, params); return encode_image_wic(image, stream, &CLSID_WICGifEncoder, params);
} }
/***************************************************************************** /*****************************************************************************
@ -4581,7 +4558,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
encode_image_func encode_image; encode_image_func encode_image;
int i; int i;
TRACE("%p %p %s %p\n", image, stream, wine_dbgstr_guid(clsid), params); TRACE("%p %p %p %p\n", image, stream, clsid, params);
if(!image || !stream) if(!image || !stream)
return InvalidParameter; return InvalidParameter;
@ -5595,111 +5572,3 @@ GpStatus WINGDIPAPI GdipBitmapGetHistogramSize(HistogramFormat format, UINT *num
*num_of_entries = 256; *num_of_entries = 256;
return Ok; return Ok;
} }
static GpStatus create_optimal_palette(ColorPalette *palette, INT desired,
BOOL transparent, GpBitmap *bitmap)
{
GpStatus status;
BitmapData data;
HRESULT hr;
IWICImagingFactory *factory;
IWICPalette *wic_palette;
if (!bitmap) return InvalidParameter;
if (palette->Count < desired) return GenericError;
status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
if (status != Ok) return status;
hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
if (hr != S_OK)
{
GdipBitmapUnlockBits(bitmap, &data);
return hresult_to_status(hr);
}
hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
if (hr == S_OK)
{
IWICBitmap *bitmap;
/* PixelFormat24bppRGB actually stores the bitmap bits as BGR. */
hr = IWICImagingFactory_CreateBitmapFromMemory(factory, data.Width, data.Height,
&GUID_WICPixelFormat24bppBGR, data.Stride, data.Stride * data.Width, data.Scan0, &bitmap);
if (hr == S_OK)
{
hr = IWICPalette_InitializeFromBitmap(wic_palette, (IWICBitmapSource *)bitmap, desired, transparent);
if (hr == S_OK)
{
palette->Flags = 0;
IWICPalette_GetColorCount(wic_palette, &palette->Count);
IWICPalette_GetColors(wic_palette, palette->Count, palette->Entries, &palette->Count);
}
IWICBitmap_Release(bitmap);
}
IWICPalette_Release(wic_palette);
}
IWICImagingFactory_Release(factory);
GdipBitmapUnlockBits(bitmap, &data);
return hresult_to_status(hr);
}
/*****************************************************************************
* GdipInitializePalette [GDIPLUS.@]
*/
GpStatus WINGDIPAPI GdipInitializePalette(ColorPalette *palette,
PaletteType type, INT desired, BOOL transparent, GpBitmap *bitmap)
{
TRACE("(%p,%d,%d,%d,%p)\n", palette, type, desired, transparent, bitmap);
if (!palette) return InvalidParameter;
switch (type)
{
case PaletteTypeCustom:
return Ok;
case PaletteTypeOptimal:
return create_optimal_palette(palette, desired, transparent, bitmap);
/* WIC palette type enumeration matches these gdiplus enums */
case PaletteTypeFixedBW:
case PaletteTypeFixedHalftone8:
case PaletteTypeFixedHalftone27:
case PaletteTypeFixedHalftone64:
case PaletteTypeFixedHalftone125:
case PaletteTypeFixedHalftone216:
case PaletteTypeFixedHalftone252:
case PaletteTypeFixedHalftone256:
{
ColorPalette *wic_palette;
GpStatus status = Ok;
wic_palette = get_palette(NULL, type);
if (!wic_palette) return OutOfMemory;
if (palette->Count >= wic_palette->Count)
{
palette->Flags = wic_palette->Flags;
palette->Count = wic_palette->Count;
memcpy(palette->Entries, wic_palette->Entries, wic_palette->Count * sizeof(wic_palette->Entries[0]));
}
else
status = GenericError;
heap_free(wic_palette);
return status;
}
default:
FIXME("unknown palette type %d\n", type);
break;
}
return InvalidParameter;
}

View File

@ -209,14 +209,14 @@ GpStatus WINGDIPAPI GdipSetImageAttributesGamma(GpImageAttributes *imageAttr,
GpStatus WINGDIPAPI GdipSetImageAttributesNoOp(GpImageAttributes *imageAttr, GpStatus WINGDIPAPI GdipSetImageAttributesNoOp(GpImageAttributes *imageAttr,
ColorAdjustType type, BOOL enableFlag) ColorAdjustType type, BOOL enableFlag)
{ {
static int calls;
TRACE("(%p,%u,%i)\n", imageAttr, type, enableFlag); TRACE("(%p,%u,%i)\n", imageAttr, type, enableFlag);
if(!(calls++)) if (type >= ColorAdjustTypeCount)
FIXME("not implemented\n"); return InvalidParameter;
return NotImplemented; imageAttr->noop[type] = enableFlag ? IMAGEATTR_NOOP_SET : IMAGEATTR_NOOP_CLEAR;
return Ok;
} }
GpStatus WINGDIPAPI GdipSetImageAttributesOutputChannel(GpImageAttributes *imageAttr, GpStatus WINGDIPAPI GdipSetImageAttributesOutputChannel(GpImageAttributes *imageAttr,
@ -323,6 +323,7 @@ GpStatus WINGDIPAPI GdipResetImageAttributes(GpImageAttributes *imageAttr,
GdipSetImageAttributesColorKeys(imageAttr, type, FALSE, 0, 0); GdipSetImageAttributesColorKeys(imageAttr, type, FALSE, 0, 0);
GdipSetImageAttributesRemapTable(imageAttr, type, FALSE, 0, NULL); GdipSetImageAttributesRemapTable(imageAttr, type, FALSE, 0, NULL);
GdipSetImageAttributesGamma(imageAttr, type, FALSE, 0.0); GdipSetImageAttributesGamma(imageAttr, type, FALSE, 0.0);
imageAttr->noop[type] = IMAGEATTR_NOOP_UNDEFINED;
return Ok; return Ok;
} }

File diff suppressed because it is too large Load Diff

View File

@ -64,12 +64,6 @@
#define FLAGS_INTPATH 0x4000 #define FLAGS_INTPATH 0x4000
struct memory_buffer
{
const BYTE *buffer;
INT size, pos;
};
struct region_header struct region_header
{ {
DWORD magic; DWORD magic;
@ -766,24 +760,6 @@ GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
return Ok; return Ok;
} }
static inline void init_memory_buffer(struct memory_buffer *mbuf, const BYTE *buffer, INT size)
{
mbuf->buffer = buffer;
mbuf->size = size;
mbuf->pos = 0;
}
static inline const void *buffer_read(struct memory_buffer *mbuf, INT size)
{
if (mbuf->size - mbuf->pos >= size)
{
const void *data = mbuf->buffer + mbuf->pos;
mbuf->pos += size;
return data;
}
return NULL;
}
static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, region_element *node, INT *count) static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, region_element *node, INT *count)
{ {
GpStatus status; GpStatus status;

View File

@ -68,7 +68,7 @@ reactos/dll/win32/dciman32 # Synced to WineStaging-2.9
reactos/dll/win32/faultrep # Synced to WineStaging-2.9 reactos/dll/win32/faultrep # Synced to WineStaging-2.9
reactos/dll/win32/fontsub # Synced to WineStaging-2.9 reactos/dll/win32/fontsub # Synced to WineStaging-2.9
reactos/dll/win32/fusion # Synced to Wine-3.0 reactos/dll/win32/fusion # Synced to Wine-3.0
reactos/dll/win32/gdiplus # Synced to WineStaging-2.16 reactos/dll/win32/gdiplus # Synced to Wine-3.0
reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-2.9 reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-2.9
reactos/dll/win32/hlink # Synced to WineStaging-2.9 reactos/dll/win32/hlink # Synced to WineStaging-2.9
reactos/dll/win32/hnetcfg # Synced to WineStaging-2.9 reactos/dll/win32/hnetcfg # Synced to WineStaging-2.9