From: Amine Khaldi Date: Fri, 25 Jan 2019 12:21:54 +0000 (+0100) Subject: [GDIPLUS] Sync with Wine Staging 4.0. CORE-15682 X-Git-Tag: 0.4.13-dev~618 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=89f10a28f7927e6db2c62bb89d1e40602b241b93 [GDIPLUS] Sync with Wine Staging 4.0. CORE-15682 --- diff --git a/dll/win32/gdiplus/brush.c b/dll/win32/gdiplus/brush.c index f7260239825..8d4043933ff 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 64778bb226e..5e6aa5430f0 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; icount; 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 b2e4f1e93f3..8c4fccededa 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 5666346afc1..199b20442b2 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 afa2afeac7c..8425bcb54b3 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 b86808b87e6..8bcb91819a2 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 d2f702ab60e..b7be7ac790f 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