[GDIPLUS] Sync with Wine Staging 2.9. CORE-13362

11fc5c0 gdiplus: Prefer using pre-multiplied ARGB data in the scaler.
17162a9 gdiplus: Remove ceilf/floorf calls from bilinear scaler. (v2)
6bade0c gdiplus: Change multiplications by additions in the x/y scaler loops.
db49130 gdiplus: Change the order of x/y loops in the scaler.
9247b54 gdiplus: Set correct color space flags for grayscale images.
81ccd6b gdiplus: Force conversion of 8 bpp grayscale PNG images to 32 bpp BGRA.
4fe61f3 gdiplus: Ignore an externally set DC clipping region.
a188922 gdiplus: Ignore an externally set DC origin.
b8a8e1b gdiplus: Check SHADEBLENDCAPS only for printer devices.
c2a4f19 gdiplus: Fix compilation on systems that don't support nameless unions.
29a55bc gdiplus: Use software mode to draw semi-transparent lines when necessary.
c89de1d gdiplus: Use better naming for line alignment format field.
69b41e7 gdiplus: Fix generic string formats behavior.
a3f0a59 gdiplus: Avoid infinite recursion in flatten_bezier().
36c9ac3 gdiplus: Check for null in GdipGetFontHeight.
7f25431 gdiplus: Fix GdipCreateStreamOnFile spec file entry.
43e36d6 gdiplus: Simplify and standardize the heap_xxx() declarations.

svn path=/trunk/; revision=74795
This commit is contained in:
Amine Khaldi 2017-06-03 19:01:50 +00:00
parent 903c7855c9
commit 718178aa88
9 changed files with 213 additions and 74 deletions

View file

@ -543,6 +543,8 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
TRACE("%p %p %p\n", font, graphics, height); TRACE("%p %p %p\n", font, graphics, height);
if (!font || !height) return InvalidParameter;
stat = GdipGetFontHeightGivenDPI(font, font->family->dpi, &font_height); stat = GdipGetFontHeightGivenDPI(font, font->family->dpi, &font_height);
if (stat != Ok) return stat; if (stat != Ok) return stat;

View file

@ -46,11 +46,13 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls( hinst ); DisableThreadLibraryCalls( hinst );
init_generic_string_formats();
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
if (reserved) break; if (reserved) break;
free_installed_fonts(); free_installed_fonts();
free_generic_string_formats();
break; break;
} }
return TRUE; return TRUE;

View file

@ -120,7 +120,7 @@
120 stdcall GdipCreateRegionRectI(ptr ptr) 120 stdcall GdipCreateRegionRectI(ptr ptr)
121 stdcall GdipCreateRegionRgnData(ptr long ptr) 121 stdcall GdipCreateRegionRgnData(ptr long ptr)
122 stdcall GdipCreateSolidFill(long ptr) 122 stdcall GdipCreateSolidFill(long ptr)
123 stdcall GdipCreateStreamOnFile(ptr long ptr) 123 stdcall GdipCreateStreamOnFile(wstr long ptr)
124 stdcall GdipCreateStringFormat(long long ptr) 124 stdcall GdipCreateStringFormat(long long ptr)
125 stdcall GdipCreateTexture2(ptr long float float float float ptr) 125 stdcall GdipCreateTexture2(ptr long float float float float ptr)
126 stdcall GdipCreateTexture2I(ptr long long long long long ptr) 126 stdcall GdipCreateTexture2I(ptr long long long long long ptr)

View file

@ -56,22 +56,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
#define GIF_DISPOSE_RESTORE_TO_BKGND 2 #define GIF_DISPOSE_RESTORE_TO_BKGND 2
#define GIF_DISPOSE_RESTORE_TO_PREV 3 #define GIF_DISPOSE_RESTORE_TO_PREV 3
static void *heap_alloc(size_t len) __WINE_ALLOC_SIZE(1); static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size)
static inline void *heap_alloc(size_t len)
{ {
return HeapAlloc(GetProcessHeap(), 0, len); return HeapAlloc(GetProcessHeap(), 0, size);
} }
static void *heap_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1); static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t size)
static inline void *heap_alloc_zero(size_t len)
{ {
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
} }
static void *heap_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2); static inline void* __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t size)
static inline void *heap_realloc(void *mem, size_t len)
{ {
return HeapReAlloc(GetProcessHeap(), 0, mem, len); return HeapReAlloc(GetProcessHeap(), 0, mem, size);
} }
static inline BOOL heap_free(void *mem) static inline BOOL heap_free(void *mem)
@ -452,6 +449,8 @@ struct GpFont{
Unit unit; Unit unit;
}; };
extern const struct GpStringFormat default_drawstring_format DECLSPEC_HIDDEN;
struct GpStringFormat{ struct GpStringFormat{
INT attr; INT attr;
LANGID lang; LANGID lang;
@ -459,7 +458,7 @@ struct GpStringFormat{
StringAlignment align; StringAlignment align;
StringTrimming trimming; StringTrimming trimming;
HotkeyPrefix hkprefix; HotkeyPrefix hkprefix;
StringAlignment vertalign; StringAlignment line_align;
StringDigitSubstitute digitsub; StringDigitSubstitute digitsub;
INT tabcount; INT tabcount;
REAL firsttab; REAL firsttab;
@ -469,6 +468,9 @@ struct GpStringFormat{
BOOL generic_typographic; BOOL generic_typographic;
}; };
extern void init_generic_string_formats(void) DECLSPEC_HIDDEN;
extern void free_generic_string_formats(void) DECLSPEC_HIDDEN;
struct GpFontCollection{ struct GpFontCollection{
GpFontFamily **FontFamilies; GpFontFamily **FontFamilies;
INT count; INT count;

View file

@ -519,12 +519,23 @@ 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 = gdip_round(position * 0xff); pos = (INT)(position * 255.0f + 0.5f);
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;
@ -926,6 +937,11 @@ 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)
@ -946,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;
leftxf = floorf(point->X); leftx = (INT)point->X;
leftx = (INT)leftxf; leftxf = (REAL)leftx;
rightx = (INT)ceilf(point->X); rightx = positive_ceilf(point->X);
topyf = floorf(point->Y); topy = (INT)point->Y;
topy = (INT)topyf; topyf = (REAL)topy;
bottomy = (INT)ceilf(point->Y); bottomy = positive_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,
@ -995,17 +1011,95 @@ 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;
} }
static BOOL brush_can_fill_path(GpBrush *brush) /* is_fill is TRUE if filling regions, FALSE for drawing primitives */
static BOOL brush_can_fill_path(GpBrush *brush, BOOL is_fill)
{ {
switch (brush->bt) switch (brush->bt)
{ {
case BrushTypeSolidColor: case BrushTypeSolidColor:
{
if (is_fill)
return TRUE; return TRUE;
else
{
/* cannot draw semi-transparent colors */
return (((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000;
}
}
case BrushTypeHatchFill: case BrushTypeHatchFill:
{ {
GpHatch *hatch = (GpHatch*)brush; GpHatch *hatch = (GpHatch*)brush;
@ -3003,8 +3097,10 @@ 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 else if (imageAttributes != &defaultImageAttributes)
lockeddata.PixelFormat = PixelFormat32bppARGB; lockeddata.PixelFormat = PixelFormat32bppARGB;
else
lockeddata.PixelFormat = PixelFormat32bppPARGB;
stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf, stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf,
lockeddata.PixelFormat, &lockeddata); lockeddata.PixelFormat, &lockeddata);
@ -3024,6 +3120,8 @@ 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)
@ -3041,24 +3139,42 @@ 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;
for (x=dst_area.left; x<dst_area.right; x++) delta_yy = dst_area.top * y_dy;
{ delta_yx = dst_area.top * y_dx;
for (y=dst_area.top; y<dst_area.bottom; y++) for (y=dst_area.top; y<dst_area.bottom; y++)
{
delta_xx = dst_area.left * x_dx;
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 + x * x_dx + y * y_dx; src_pointf.X = dst_to_src_points[0].X + delta_xx + delta_yx;
src_pointf.Y = dst_to_src_points[0].Y + x * x_dy + y * y_dy; src_pointf.Y = dst_to_src_points[0].Y + delta_xy + delta_yy;
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)
{
if (lockeddata.PixelFormat != PixelFormat32bppPARGB)
*dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf, *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
imageAttributes, interpolation, offset_mode); imageAttributes, interpolation, offset_mode);
else else
*dst_color = 0; *dst_color = resample_bitmap_pixel_premult(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
imageAttributes, interpolation, offset_mode);
} }
else
*dst_color = 0;
delta_xx += x_dx;
delta_yx += y_dx;
}
delta_xy += x_dy;
delta_yy += y_dy;
} }
} }
else else
@ -3784,7 +3900,7 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
if (path->pathdata.Count == 0) if (path->pathdata.Count == 0)
return Ok; return Ok;
if (!graphics->hdc) if (!graphics->hdc || !brush_can_fill_path(pen->brush, FALSE))
retval = SOFTWARE_GdipDrawPath(graphics, pen, path); retval = SOFTWARE_GdipDrawPath(graphics, pen, path);
else else
retval = GDI32_GdipDrawPath(graphics, pen, path); retval = GDI32_GdipDrawPath(graphics, pen, path);
@ -4034,7 +4150,7 @@ static GpStatus GDI32_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath
GpStatus retval; GpStatus retval;
HRGN hrgn=NULL; HRGN hrgn=NULL;
if(!graphics->hdc || !brush_can_fill_path(brush)) if(!graphics->hdc || !brush_can_fill_path(brush, TRUE))
return NotImplemented; return NotImplemented;
save_state = SaveDC(graphics->hdc); save_state = SaveDC(graphics->hdc);
@ -4327,7 +4443,7 @@ static GpStatus GDI32_GdipFillRegion(GpGraphics* graphics, GpBrush* brush,
HRGN hrgn; HRGN hrgn;
RECT rc; RECT rc;
if(!graphics->hdc || !brush_can_fill_path(brush)) if(!graphics->hdc || !brush_can_fill_path(brush, TRUE))
return NotImplemented; return NotImplemented;
status = GdipGetRegionHRgn(region, graphics, &hrgn); status = GdipGetRegionHRgn(region, graphics, &hrgn);
@ -4908,7 +5024,6 @@ GpStatus gdip_format_string(HDC hdc,
INT hotkeyprefix_count=0; INT hotkeyprefix_count=0;
INT hotkeyprefix_pos=0, hotkeyprefix_end_pos=0; INT hotkeyprefix_pos=0, hotkeyprefix_end_pos=0;
BOOL seen_prefix = FALSE; BOOL seen_prefix = FALSE;
GpStringFormat *dyn_format=NULL;
if(length == -1) length = lstrlenW(string); if(length == -1) length = lstrlenW(string);
@ -4916,15 +5031,7 @@ GpStatus gdip_format_string(HDC hdc,
if(!stringdup) return OutOfMemory; if(!stringdup) return OutOfMemory;
if (!format) if (!format)
{ format = &default_drawstring_format;
stat = GdipStringFormatGetGenericDefault(&dyn_format);
if (stat != Ok)
{
heap_free(stringdup);
return stat;
}
format = dyn_format;
}
nwidth = rect->Width; nwidth = rect->Width;
nheight = rect->Height; nheight = rect->Height;
@ -5074,7 +5181,6 @@ GpStatus gdip_format_string(HDC hdc,
heap_free(stringdup); heap_free(stringdup);
heap_free(hotkeyprefix_offsets); heap_free(hotkeyprefix_offsets);
GdipDeleteStringFormat(dyn_format);
return stat; return stat;
} }
@ -5426,19 +5532,19 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
/* Should be no need to explicitly test for StringAlignmentNear as /* Should be no need to explicitly test for StringAlignmentNear as
* that is default behavior if no alignment is passed. */ * that is default behavior if no alignment is passed. */
if(format->vertalign != StringAlignmentNear){ if(format->line_align != StringAlignmentNear){
RectF bounds, in_rect = *rect; RectF bounds, in_rect = *rect;
in_rect.Height = 0.0; /* avoid height clipping */ in_rect.Height = 0.0; /* avoid height clipping */
GdipMeasureString(graphics, string, length, font, &in_rect, format, &bounds, 0, 0); GdipMeasureString(graphics, string, length, font, &in_rect, format, &bounds, 0, 0);
TRACE("bounds %s\n", debugstr_rectf(&bounds)); TRACE("bounds %s\n", debugstr_rectf(&bounds));
if(format->vertalign == StringAlignmentCenter) if(format->line_align == StringAlignmentCenter)
offsety = (rect->Height - bounds.Height) / 2; offsety = (rect->Height - bounds.Height) / 2;
else if(format->vertalign == StringAlignmentFar) else if(format->line_align == StringAlignmentFar)
offsety = (rect->Height - bounds.Height); offsety = (rect->Height - bounds.Height);
} }
TRACE("vertical align %d, offsety %f\n", format->vertalign, offsety); TRACE("line align %d, offsety %f\n", format->line_align, offsety);
} }
save_state = SaveDC(hdc); save_state = SaveDC(hdc);

View file

@ -128,6 +128,10 @@ static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, R
mp[2].X = (mp[1].X + mp[3].X) / 2.0; mp[2].X = (mp[1].X + mp[3].X) / 2.0;
mp[2].Y = (mp[1].Y + mp[3].Y) / 2.0; mp[2].Y = (mp[1].Y + mp[3].Y) / 2.0;
if ((x2 == mp[0].X && y2 == mp[0].Y && x3 == mp[1].X && y3 == mp[1].Y) ||
(x2 == mp[3].X && y2 == mp[3].Y && x3 == mp[4].X && y3 == mp[4].Y))
return TRUE;
pt = end->pt; pt = end->pt;
pt_st = start->pt; pt_st = start->pt;
/* check flatness as a half of distance between middle point and a linearized path */ /* check flatness as a half of distance between middle point and a linearized path */
@ -1010,13 +1014,13 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
heap_free(backup); heap_free(backup);
return status; return status;
} }
if (format && format->vertalign == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height) if (format && format->line_align == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height)
{ {
float inc = layoutRect->Height + layoutRect->Y - args.maxY; float inc = layoutRect->Height + layoutRect->Y - args.maxY;
inc /= 2; inc /= 2;
for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i) for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i)
path->pathdata.Points[i].Y += inc; path->pathdata.Points[i].Y += inc;
} else if (format && format->vertalign == StringAlignmentFar) { } else if (format && format->line_align == StringAlignmentFar) {
float inc = layoutRect->Height + layoutRect->Y - args.maxY; float inc = layoutRect->Height + layoutRect->Y - args.maxY;
for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i) for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i)
path->pathdata.Points[i].Y += inc; path->pathdata.Points[i].Y += inc;

View file

@ -40,7 +40,6 @@ static const struct
{ &GUID_WICPixelFormat1bppIndexed, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW }, { &GUID_WICPixelFormat1bppIndexed, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW },
{ &GUID_WICPixelFormat4bppIndexed, PixelFormat4bppIndexed, WICBitmapPaletteTypeFixedHalftone8 }, { &GUID_WICPixelFormat4bppIndexed, PixelFormat4bppIndexed, WICBitmapPaletteTypeFixedHalftone8 },
{ &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 }, { &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 },
{ &GUID_WICPixelFormat32bppGrayFloat, PixelFormat32bppARGB, 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 },
@ -49,6 +48,7 @@ static const struct
{ &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat32bppCMYK, PixelFormat32bppCMYK, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppCMYK, PixelFormat32bppCMYK, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat32bppGrayFloat, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedGray256 },
{ &GUID_WICPixelFormat64bppCMYK, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat64bppCMYK, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
{ &GUID_WICPixelFormat64bppRGBA, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat64bppRGBA, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
{ NULL } { NULL }

View file

@ -19,6 +19,47 @@
#include "gdiplus_private.h" #include "gdiplus_private.h"
const GpStringFormat default_drawstring_format =
{
0,
LANG_NEUTRAL,
LANG_NEUTRAL,
StringAlignmentNear,
StringTrimmingCharacter,
HotkeyPrefixNone,
StringAlignmentNear,
StringDigitSubstituteUser,
0,
0.0,
NULL,
NULL,
0,
FALSE
};
static GpStringFormat generic_default_format;
static GpStringFormat generic_typographic_format;
void init_generic_string_formats(void)
{
memcpy(&generic_default_format, &default_drawstring_format, sizeof(generic_default_format));
memcpy(&generic_typographic_format, &default_drawstring_format, sizeof(generic_typographic_format));
generic_typographic_format.attr = StringFormatFlagsNoFitBlackBox | StringFormatFlagsLineLimit |
StringFormatFlagsNoClip;
generic_typographic_format.trimming = StringTrimmingNone;
generic_typographic_format.generic_typographic = TRUE;
}
void free_generic_string_formats(void)
{
heap_free(generic_default_format.character_ranges);
heap_free(generic_default_format.tabs);
heap_free(generic_typographic_format.character_ranges);
heap_free(generic_typographic_format.tabs);
}
GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang, GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang,
GpStringFormat **format) GpStringFormat **format)
{ {
@ -53,6 +94,9 @@ GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format)
if(!format) if(!format)
return InvalidParameter; return InvalidParameter;
if (format == &generic_default_format || format == &generic_typographic_format)
return Ok;
heap_free(format->character_ranges); heap_free(format->character_ranges);
heap_free(format->tabs); heap_free(format->tabs);
heap_free(format); heap_free(format);
@ -62,17 +106,10 @@ GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format)
GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format) GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format)
{ {
GpStatus stat;
if (!format) if (!format)
return InvalidParameter; return InvalidParameter;
stat = GdipCreateStringFormat(0, LANG_NEUTRAL, format); *format = &generic_default_format;
if(stat != Ok)
return stat;
(*format)->align = StringAlignmentNear;
(*format)->vertalign = StringAlignmentNear;
return Ok; return Ok;
} }
@ -128,7 +165,7 @@ GpStatus WINGDIPAPI GdipGetStringFormatLineAlign(GpStringFormat *format,
if(!format || !align) if(!format || !align)
return InvalidParameter; return InvalidParameter;
*align = format->vertalign; *align = format->line_align;
return Ok; return Ok;
} }
@ -232,7 +269,7 @@ GpStatus WINGDIPAPI GdipSetStringFormatLineAlign(GpStringFormat *format,
if(!format) if(!format)
return InvalidParameter; return InvalidParameter;
format->vertalign = align; format->line_align = align;
return Ok; return Ok;
} }
@ -357,24 +394,10 @@ GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpSt
GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format) GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format)
{ {
GpStatus stat;
if(!format) if(!format)
return InvalidParameter; return InvalidParameter;
stat = GdipCreateStringFormat(StringFormatFlagsNoFitBlackBox | *format = &generic_typographic_format;
StringFormatFlagsLineLimit |
StringFormatFlagsNoClip, LANG_NEUTRAL, format);
if(stat != Ok)
return stat;
(*format)->digitlang = LANG_NEUTRAL;
(*format)->digitsub = StringDigitSubstituteUser;
(*format)->trimming = StringTrimmingNone;
(*format)->hkprefix = HotkeyPrefixNone;
(*format)->align = StringAlignmentNear;
(*format)->vertalign = StringAlignmentNear;
(*format)->generic_typographic = TRUE;
TRACE("%p => %p\n", format, *format); TRACE("%p => %p\n", format, *format);

View file

@ -68,7 +68,7 @@ reactos/dll/win32/dciman32 # Synced to WineStaging-1.9.11
reactos/dll/win32/faultrep # Synced to WineStaging-1.9.11 reactos/dll/win32/faultrep # Synced to WineStaging-1.9.11
reactos/dll/win32/fontsub # Synced to WineStaging-1.9.13 reactos/dll/win32/fontsub # Synced to WineStaging-1.9.13
reactos/dll/win32/fusion # Synced to WineStaging-1.9.23 reactos/dll/win32/fusion # Synced to WineStaging-1.9.23
reactos/dll/win32/gdiplus # Synced to WineStaging-2.2 reactos/dll/win32/gdiplus # Synced to WineStaging-2.9
reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-2.2 reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-2.2
reactos/dll/win32/hlink # Synced to WineStaging-2.2 reactos/dll/win32/hlink # Synced to WineStaging-2.2
reactos/dll/win32/hnetcfg # Synced to WineStaging-1.9.16 reactos/dll/win32/hnetcfg # Synced to WineStaging-1.9.16