[GDIPLUS] Sync with Wine Staging 4.0. CORE-15682
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 25 Jan 2019 12:21:54 +0000 (13:21 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 25 Jan 2019 12:21:54 +0000 (13:21 +0100)
dll/win32/gdiplus/brush.c
dll/win32/gdiplus/font.c
dll/win32/gdiplus/gdiplus_private.h
dll/win32/gdiplus/graphics.c
dll/win32/gdiplus/image.c
dll/win32/gdiplus/pen.c
media/doc/README.WINE

index f726023..8d40439 100644 (file)
@@ -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;
 }
 
index 64778bb..5e6aa54 100644 (file)
@@ -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)&param, 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)&param, 0))
         {
             free_installed_fonts();
             DeleteDC(hdc);
-            return OutOfMemory;
+            return param.stat;
         }
 
         DeleteDC(hdc);
index b2e4f1e..8c4fcce 100644 (file)
@@ -291,8 +291,6 @@ struct GpPathGradient{
 
 struct GpLineGradient{
     GpBrush brush;
-    GpPointF startpoint;
-    GpPointF endpoint;
     ARGB startcolor;
     ARGB endcolor;
     RectF rect;
index 5666346..199b204 100644 (file)
@@ -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))
index afa2afe..8425bcb 100644 (file)
@@ -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
index b86808b..8bcb918 100644 (file)
@@ -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)
index d2f702a..b7be7ac 100644 (file)
@@ -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