https://git.reactos.org/?p=reactos.git;a=commitdiff;h=89f10a28f7927e6db2c62…
commit 89f10a28f7927e6db2c62bb89d1e40602b241b93
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Fri Jan 25 13:21:54 2019 +0100
Commit: Amine Khaldi <amine.khaldi(a)reactos.org>
CommitDate: Fri Jan 25 13:21:54 2019 +0100
[GDIPLUS] Sync with Wine Staging 4.0. CORE-15682
---
dll/win32/gdiplus/brush.c | 182 +++++++++++++++++++-----------------
dll/win32/gdiplus/font.c | 39 ++++++--
dll/win32/gdiplus/gdiplus_private.h | 2 -
dll/win32/gdiplus/graphics.c | 2 +-
dll/win32/gdiplus/image.c | 41 ++++++++
dll/win32/gdiplus/pen.c | 21 +----
media/doc/README.WINE | 2 +-
7 files changed, 173 insertions(+), 116 deletions(-)
diff --git a/dll/win32/gdiplus/brush.c b/dll/win32/gdiplus/brush.c
index f726023982..8d4043933f 100644
--- a/dll/win32/gdiplus/brush.c
+++ b/dll/win32/gdiplus/brush.c
@@ -294,12 +294,49 @@ GpStatus WINGDIPAPI GdipCreateHatchBrush(GpHatchStyle hatchstyle,
ARGB forecol,
return Ok;
}
-static void linegradient_init_transform(GpLineGradient *line)
+static GpStatus create_line_brush(const GpRectF *rect, ARGB startcolor, ARGB endcolor,
+ GpWrapMode wrap, GpLineGradient **line)
+{
+ *line = heap_alloc_zero(sizeof(GpLineGradient));
+ if(!*line) return OutOfMemory;
+
+ (*line)->brush.bt = BrushTypeLinearGradient;
+ (*line)->startcolor = startcolor;
+ (*line)->endcolor = endcolor;
+ (*line)->wrap = wrap;
+ (*line)->gamma = FALSE;
+ (*line)->rect = *rect;
+ (*line)->blendcount = 1;
+ (*line)->blendfac = heap_alloc_zero(sizeof(REAL));
+ (*line)->blendpos = heap_alloc_zero(sizeof(REAL));
+
+ if (!(*line)->blendfac || !(*line)->blendpos)
+ {
+ heap_free((*line)->blendfac);
+ heap_free((*line)->blendpos);
+ heap_free(*line);
+ *line = NULL;
+ return OutOfMemory;
+ }
+
+ (*line)->blendfac[0] = 1.0f;
+ (*line)->blendpos[0] = 1.0f;
+
+ (*line)->pblendcolor = NULL;
+ (*line)->pblendpos = NULL;
+ (*line)->pblendcount = 0;
+
+ GdipSetMatrixElements(&(*line)->transform, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f);
+
+ return Ok;
+}
+
+static void linegradient_init_transform(const GpPointF *startpoint, const GpPointF
*endpoint, GpLineGradient *line)
{
float trans_x = line->rect.X + (line->rect.Width / 2.f);
float trans_y = line->rect.Y + (line->rect.Height / 2.f);
- float dx = line->endpoint.X - line->startpoint.X;
- float dy = line->endpoint.Y - line->startpoint.Y;
+ float dx = endpoint->X - startpoint->X;
+ float dy = endpoint->Y - startpoint->Y;
float t_cos, t_sin, w_ratio, h_ratio;
float h;
GpMatrix rot;
@@ -336,6 +373,9 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF*
startpoint,
GDIPCONST GpPointF* endpoint, ARGB startcolor, ARGB endcolor,
GpWrapMode wrap, GpLineGradient **line)
{
+ GpStatus stat;
+ GpRectF rect;
+
TRACE("(%s, %s, %x, %x, %d, %p)\n", debugstr_pointf(startpoint),
debugstr_pointf(endpoint), startcolor, endcolor, wrap, line);
@@ -345,57 +385,27 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF*
startpoint,
if (startpoint->X == endpoint->X && startpoint->Y ==
endpoint->Y)
return OutOfMemory;
- *line = heap_alloc_zero(sizeof(GpLineGradient));
- if(!*line) return OutOfMemory;
+ rect.X = startpoint->X < endpoint->X ? startpoint->X : endpoint->X;
+ rect.Y = startpoint->Y < endpoint->Y ? startpoint->Y : endpoint->Y;
+ rect.Width = fabs(startpoint->X - endpoint->X);
+ rect.Height = fabs(startpoint->Y - endpoint->Y);
- (*line)->brush.bt = BrushTypeLinearGradient;
-
- (*line)->startpoint.X = startpoint->X;
- (*line)->startpoint.Y = startpoint->Y;
- (*line)->endpoint.X = endpoint->X;
- (*line)->endpoint.Y = endpoint->Y;
- (*line)->startcolor = startcolor;
- (*line)->endcolor = endcolor;
- (*line)->wrap = wrap;
- (*line)->gamma = FALSE;
-
- (*line)->rect.X = (startpoint->X < endpoint->X ? startpoint->X:
endpoint->X);
- (*line)->rect.Y = (startpoint->Y < endpoint->Y ? startpoint->Y:
endpoint->Y);
- (*line)->rect.Width = fabs(startpoint->X - endpoint->X);
- (*line)->rect.Height = fabs(startpoint->Y - endpoint->Y);
-
- if ((*line)->rect.Width == 0)
- {
- (*line)->rect.X -= (*line)->rect.Height / 2.0f;
- (*line)->rect.Width = (*line)->rect.Height;
- }
- else if ((*line)->rect.Height == 0)
+ if (rect.Width == 0.0f)
{
- (*line)->rect.Y -= (*line)->rect.Width / 2.0f;
- (*line)->rect.Height = (*line)->rect.Width;
+ rect.X -= rect.Height / 2.0f;
+ rect.Width = rect.Height;
}
-
- (*line)->blendcount = 1;
- (*line)->blendfac = heap_alloc_zero(sizeof(REAL));
- (*line)->blendpos = heap_alloc_zero(sizeof(REAL));
-
- if (!(*line)->blendfac || !(*line)->blendpos)
+ else if (rect.Height == 0.0f)
{
- heap_free((*line)->blendfac);
- heap_free((*line)->blendpos);
- heap_free(*line);
- *line = NULL;
- return OutOfMemory;
+ rect.Y -= rect.Width / 2.0f;
+ rect.Height = rect.Width;
}
- (*line)->blendfac[0] = 1.0f;
- (*line)->blendpos[0] = 1.0f;
-
- (*line)->pblendcolor = NULL;
- (*line)->pblendpos = NULL;
- (*line)->pblendcount = 0;
+ stat = create_line_brush(&rect, startcolor, endcolor, wrap, line);
+ if (stat != Ok)
+ return stat;
- linegradient_init_transform(*line);
+ linegradient_init_transform(startpoint, endpoint, *line);
TRACE("<-- %p\n", *line);
@@ -427,9 +437,7 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF*
rect,
ARGB startcolor, ARGB endcolor, LinearGradientMode mode, GpWrapMode wrap,
GpLineGradient **line)
{
- GpPointF start, end;
- float far_x, angle;
- GpStatus stat;
+ float angle;
TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
wrap, line);
@@ -439,6 +447,9 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF*
rect,
switch (mode)
{
+ case LinearGradientModeHorizontal:
+ angle = 0.0f;
+ break;
case LinearGradientModeVertical:
angle = 90.0f;
break;
@@ -448,17 +459,6 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF*
rect,
case LinearGradientModeBackwardDiagonal:
angle = 135.0f;
break;
- case LinearGradientModeHorizontal:
- far_x = rect->X + rect->Width;
-
- start.X = min(rect->X, far_x);
- start.Y = rect->Y;
- end.X = max(rect->X, far_x);
- end.Y = rect->Y;
- stat = GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap,
line);
- if (stat == Ok)
- (*line)->rect = *rect;
- return stat;
default:
return InvalidParameter;
}
@@ -535,7 +535,14 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST
GpRectF* rect
far_x = rect->X + rect->Width;
far_y = rect->Y + rect->Height;
- if (sin_cos_angle >= 0)
+ if (angle == 0.0f)
+ {
+ start.X = min(rect->X, far_x);
+ start.Y = rect->Y;
+ end.X = max(rect->X, far_x);
+ end.Y = rect->Y;
+ }
+ else if (sin_cos_angle >= 0)
{
start.X = min(rect->X, far_x);
start.Y = min(rect->Y, far_y);
@@ -550,37 +557,36 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST
GpRectF* rect
end.Y = max(rect->Y, far_y);
}
- stat = GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap, line);
+ stat = create_line_brush(rect, startcolor, endcolor, wrap, line);
+ if (stat != Ok || angle == 0.0f)
+ return stat;
- if (stat == Ok)
+ if (sin_cos_angle >= 0)
{
- if (sin_cos_angle >= 0)
- {
- exofs = rect->Height * sin_cos_angle + rect->Width * cos_angle *
cos_angle;
- eyofs = rect->Height * sin_angle * sin_angle + rect->Width *
sin_cos_angle;
- }
- else
- {
- exofs = rect->Width * sin_angle * sin_angle + rect->Height *
sin_cos_angle;
- eyofs = -rect->Width * sin_cos_angle + rect->Height * sin_angle *
sin_angle;
- }
-
- if (sin_angle >= 0)
- {
- (*line)->endpoint.X = rect->X + exofs;
- (*line)->endpoint.Y = rect->Y + eyofs;
- }
- else
- {
- (*line)->endpoint.X = (*line)->startpoint.X;
- (*line)->endpoint.Y = (*line)->startpoint.Y;
- (*line)->startpoint.X = rect->X + exofs;
- (*line)->startpoint.Y = rect->Y + eyofs;
- }
+ exofs = rect->Height * sin_cos_angle + rect->Width * cos_angle *
cos_angle;
+ eyofs = rect->Height * sin_angle * sin_angle + rect->Width *
sin_cos_angle;
+ }
+ else
+ {
+ exofs = rect->Width * sin_angle * sin_angle + rect->Height *
sin_cos_angle;
+ eyofs = -rect->Width * sin_cos_angle + rect->Height * sin_angle *
sin_angle;
+ }
- linegradient_init_transform(*line);
+ if (sin_angle >= 0)
+ {
+ end.X = rect->X + exofs;
+ end.Y = rect->Y + eyofs;
+ }
+ else
+ {
+ end.X = start.X;
+ end.Y = start.Y;
+ start.X = rect->X + exofs;
+ start.Y = rect->Y + eyofs;
}
+ linegradient_init_transform(&start, &end, *line);
+
return stat;
}
diff --git a/dll/win32/gdiplus/font.c b/dll/win32/gdiplus/font.c
index 64778bb226..5e6aa5430f 100644
--- a/dll/win32/gdiplus/font.c
+++ b/dll/win32/gdiplus/font.c
@@ -1125,6 +1125,7 @@ GpStatus WINGDIPAPI GdipDeletePrivateFontCollection(GpFontCollection
**fontColle
return InvalidParameter;
for (i = 0; i < (*fontCollection)->count; i++)
heap_free((*fontCollection)->FontFamilies[i]);
+ heap_free((*fontCollection)->FontFamilies);
heap_free(*fontCollection);
return Ok;
@@ -1493,6 +1494,13 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size,
DWORD id )
return NULL;
}
+struct add_font_param
+{
+ GpFontCollection *collection;
+ BOOL is_system;
+ GpStatus stat;
+};
+
static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, DWORD
type, LPARAM lParam);
/*****************************************************************************
@@ -1520,6 +1528,7 @@ GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection*
fontCollection,
ret = InvalidParameter;
else
{
+ struct add_font_param param;
HDC hdc;
LOGFONTW lfw;
@@ -1533,8 +1542,10 @@ GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection*
fontCollection,
lstrcpyW(lfw.lfFaceName, name);
lfw.lfPitchAndFamily = 0;
- if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)fontCollection,
0))
- ret = OutOfMemory;
+ param.collection = fontCollection;
+ param.is_system = FALSE;
+ if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)¶m, 0))
+ ret = param.stat;
DeleteDC(hdc);
}
@@ -1606,10 +1617,14 @@ void free_installed_fonts(void)
static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm,
DWORD type, LPARAM lParam)
{
- GpFontCollection* fonts = (GpFontCollection*)lParam;
+ struct add_font_param *param = (struct add_font_param *)lParam;
+ GpFontCollection *fonts = param->collection;
GpFontFamily* family;
+ GpStatus stat;
int i;
+ param->stat = Ok;
+
if (type == RASTER_FONTTYPE)
return 1;
@@ -1626,7 +1641,10 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const
TEXTMETRICW *ntm,
GpFontFamily** new_family_list = heap_alloc(new_alloc_count*sizeof(void*));
if (!new_family_list)
+ {
+ param->stat = OutOfMemory;
return 0;
+ }
memcpy(new_family_list, fonts->FontFamilies, fonts->count*sizeof(void*));
heap_free(fonts->FontFamilies);
@@ -1634,8 +1652,14 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const
TEXTMETRICW *ntm,
fonts->allocated = new_alloc_count;
}
- if (GdipCreateFontFamilyFromName(lfw->lfFaceName, NULL, &family) != Ok)
+ if ((stat = GdipCreateFontFamilyFromName(lfw->lfFaceName, NULL, &family)) !=
Ok)
+ {
+ WARN("Failed to create font family for %s, status %d.\n",
debugstr_w(lfw->lfFaceName), stat);
+ if (param->is_system)
+ return 1;
+ param->stat = stat;
return 0;
+ }
/* skip duplicates */
for (i=0; i<fonts->count; i++)
@@ -1662,6 +1686,7 @@ GpStatus WINGDIPAPI GdipNewInstalledFontCollection(
if (installedFontCollection.count == 0)
{
+ struct add_font_param param;
HDC hdc;
LOGFONTW lfw;
@@ -1671,11 +1696,13 @@ GpStatus WINGDIPAPI GdipNewInstalledFontCollection(
lfw.lfFaceName[0] = 0;
lfw.lfPitchAndFamily = 0;
- if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc,
(LPARAM)&installedFontCollection, 0))
+ param.collection = &installedFontCollection;
+ param.is_system = TRUE;
+ if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)¶m, 0))
{
free_installed_fonts();
DeleteDC(hdc);
- return OutOfMemory;
+ return param.stat;
}
DeleteDC(hdc);
diff --git a/dll/win32/gdiplus/gdiplus_private.h b/dll/win32/gdiplus/gdiplus_private.h
index b2e4f1e93f..8c4fcceded 100644
--- a/dll/win32/gdiplus/gdiplus_private.h
+++ b/dll/win32/gdiplus/gdiplus_private.h
@@ -291,8 +291,6 @@ struct GpPathGradient{
struct GpLineGradient{
GpBrush brush;
- GpPointF startpoint;
- GpPointF endpoint;
ARGB startcolor;
ARGB endcolor;
RectF rect;
diff --git a/dll/win32/gdiplus/graphics.c b/dll/win32/gdiplus/graphics.c
index 5666346afc..199b20442b 100644
--- a/dll/win32/gdiplus/graphics.c
+++ b/dll/win32/gdiplus/graphics.c
@@ -5434,7 +5434,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics*
graphics,
RectF scaled_rect;
REAL margin_x;
- TRACE("(%p %s %d %p %s %p %d %p)\n", graphics, debugstr_w(string),
+ TRACE("(%p %s %d %p %s %p %d %p)\n", graphics, debugstr_wn(string,
length),
length, font, debugstr_rectf(layoutRect), stringFormat, regionCount,
regions);
if (!(graphics && string && font && layoutRect &&
stringFormat && regions))
diff --git a/dll/win32/gdiplus/image.c b/dll/win32/gdiplus/image.c
index afa2afeac7..8425bcb54b 100644
--- a/dll/win32/gdiplus/image.c
+++ b/dll/win32/gdiplus/image.c
@@ -3955,6 +3955,39 @@ static GpStatus decode_image_jpeg(IStream* stream, GpImage
**image)
return decode_image_wic(stream, &GUID_ContainerFormatJpeg, NULL, image);
}
+static BOOL has_png_transparency_chunk(IStream *pIStream)
+{
+ LARGE_INTEGER seek;
+ BOOL has_tRNS = FALSE;
+ HRESULT hr;
+ BYTE header[8];
+
+ seek.QuadPart = 8;
+ do
+ {
+ ULARGE_INTEGER chunk_start;
+ ULONG bytesread, chunk_size;
+
+ hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start);
+ if (FAILED(hr)) break;
+
+ hr = IStream_Read(pIStream, header, 8, &bytesread);
+ if (FAILED(hr) || bytesread < 8) break;
+
+ chunk_size = (header[0] << 24) | (header[1] << 16) | (header[2]
<< 8) | header[3];
+ if (!memcmp(&header[4], "tRNS", 4))
+ {
+ has_tRNS = TRUE;
+ break;
+ }
+
+ seek.QuadPart = chunk_start.QuadPart + chunk_size + 12; /* skip data and CRC */
+ } while (memcmp(&header[4], "IDAT", 4) &&
memcmp(&header[4], "IEND", 4));
+
+ TRACE("has_tRNS = %d\n", has_tRNS);
+ return has_tRNS;
+}
+
static GpStatus decode_image_png(IStream* stream, GpImage **image)
{
IWICBitmapDecoder *decoder;
@@ -3976,6 +4009,14 @@ static GpStatus decode_image_png(IStream* stream, GpImage **image)
{
if (IsEqualGUID(&format, &GUID_WICPixelFormat8bppGray))
force_conversion = TRUE;
+ else if ((IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed) ||
+ IsEqualGUID(&format, &GUID_WICPixelFormat4bppIndexed) ||
+ IsEqualGUID(&format, &GUID_WICPixelFormat2bppIndexed) ||
+ IsEqualGUID(&format, &GUID_WICPixelFormat1bppIndexed) ||
+ IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR))
&&
+ has_png_transparency_chunk(stream))
+ force_conversion = TRUE;
+
status = decode_frame_wic(decoder, force_conversion, 0, png_metadata_reader,
image);
}
else
diff --git a/dll/win32/gdiplus/pen.c b/dll/win32/gdiplus/pen.c
index b86808b87e..8bcb91819a 100644
--- a/dll/win32/gdiplus/pen.c
+++ b/dll/win32/gdiplus/pen.c
@@ -470,48 +470,33 @@ GpStatus WINGDIPAPI GdipTranslatePenTransform(GpPen *pen, REAL dx,
REAL dy, GpMa
GpStatus WINGDIPAPI GdipScalePenTransform(GpPen *pen, REAL sx, REAL sy, GpMatrixOrder
order)
{
- static int calls;
-
TRACE("(%p,%0.2f,%0.2f,%u)\n", pen, sx, sy, order);
if(!pen)
return InvalidParameter;
- if(!(calls++))
- FIXME("(%p, %.2f, %.2f, %d) stub\n", pen, sx, sy, order);
-
- return NotImplemented;
+ return GdipScaleMatrix(&pen->transform, sx, sy, order);
}
GpStatus WINGDIPAPI GdipRotatePenTransform(GpPen *pen, REAL angle, GpMatrixOrder order)
{
- static int calls;
-
TRACE("(%p,%0.2f,%u)\n", pen, angle, order);
if(!pen)
return InvalidParameter;
- if(!(calls++))
- FIXME("not implemented\n");
-
- return NotImplemented;
+ return GdipRotateMatrix(&pen->transform, angle, order);
}
GpStatus WINGDIPAPI GdipMultiplyPenTransform(GpPen *pen, GDIPCONST GpMatrix *matrix,
GpMatrixOrder order)
{
- static int calls;
-
TRACE("(%p,%p,%u)\n", pen, matrix, order);
if(!pen)
return InvalidParameter;
- if(!(calls++))
- FIXME("not implemented\n");
-
- return NotImplemented;
+ return GdipMultiplyMatrix(&pen->transform, matrix, order);
}
GpStatus WINGDIPAPI GdipSetPenBrushFill(GpPen *pen, GpBrush *brush)
diff --git a/media/doc/README.WINE b/media/doc/README.WINE
index d2f702ab60..b7be7ac790 100644
--- a/media/doc/README.WINE
+++ b/media/doc/README.WINE
@@ -68,7 +68,7 @@ reactos/dll/win32/dciman32 # Synced to WineStaging-3.3
reactos/dll/win32/faultrep # Synced to WineStaging-2.9
reactos/dll/win32/fontsub # Synced to WineStaging-2.9
reactos/dll/win32/fusion # Synced to WineStaging-3.17
-reactos/dll/win32/gdiplus # Synced to WineStaging-3.17
+reactos/dll/win32/gdiplus # Synced to WineStaging-4.0
reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-3.17
reactos/dll/win32/hlink # Synced to WineStaging-3.3
reactos/dll/win32/hnetcfg # Synced to WineStaging-3.9