Commit f40f379f authored by Ziqing Hui's avatar Ziqing Hui Committed by Alexandre Julliard

gdiplus: Correctly handle UnitDisplay for printer DC.

For printer DC, UnitDisplay specifies that a unit is 1/100 inch, which is different from display DC. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=17848Signed-off-by: 's avatarZiqing Hui <zhui@codeweavers.com> Signed-off-by: 's avatarEsme Povirk <esme@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 158a9e73
......@@ -168,7 +168,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL);
if (stat != Ok) return stat;
lfw.lfHeight = -units_to_pixels(emSize, unit, fontFamily->dpi);
lfw.lfHeight = -units_to_pixels(emSize, unit, fontFamily->dpi, FALSE);
lfw.lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR;
lfw.lfItalic = style & FontStyleItalic;
lfw.lfUnderline = style & FontStyleUnderline;
......@@ -468,16 +468,16 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW
if (font->unit == UnitPixel || font->unit == UnitWorld)
{
height = units_to_pixels(font->emSize, graphics->unit, graphics->yres);
height = units_to_pixels(font->emSize, graphics->unit, graphics->yres, graphics->printer_display);
if (graphics->unit != UnitDisplay)
GdipScaleMatrix(&matrix, graphics->scale, graphics->scale, MatrixOrderAppend);
}
else
{
if (graphics->unit == UnitDisplay || graphics->unit == UnitPixel)
height = units_to_pixels(font->emSize, font->unit, graphics->xres);
height = units_to_pixels(font->emSize, font->unit, graphics->xres, graphics->printer_display);
else
height = units_to_pixels(font->emSize, font->unit, graphics->yres);
height = units_to_pixels(font->emSize, font->unit, graphics->yres, graphics->printer_display);
}
pt[0].X = 0.0;
......@@ -570,7 +570,7 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
stat = GdipGetDpiY((GpGraphics *)graphics, &dpi);
if (stat != Ok) return stat;
*height = pixels_to_units(font_height, graphics->unit, dpi);
*height = pixels_to_units(font_height, graphics->unit, dpi, graphics->printer_display);
TRACE("%s,%d(unit %d) => %f\n",
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, graphics->unit, *height);
......@@ -604,7 +604,7 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
TRACE("%p (%s), %f, %p\n", font,
debugstr_w(font->family->FamilyName), dpi, height);
font_size = units_to_pixels(get_font_size(font), font->unit, dpi);
font_size = units_to_pixels(get_font_size(font), font->unit, dpi, FALSE);
style = get_font_style(font);
stat = GdipGetLineSpacing(font->family, style, &line_spacing);
if (stat != Ok) return stat;
......
......@@ -324,14 +324,18 @@ GpStatus hresult_to_status(HRESULT res)
}
/* converts a given unit to its value in pixels */
REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi, BOOL printer_display)
{
switch (unit)
{
case UnitPixel:
case UnitWorld:
case UnitDisplay:
return units;
case UnitDisplay:
if (printer_display)
return units * dpi / 100.0;
else
return units;
case UnitPoint:
return units * dpi / point_per_inch;
case UnitInch:
......@@ -347,14 +351,18 @@ REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
}
/* converts value in pixels to a given unit */
REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi)
REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi, BOOL printer_display)
{
switch (unit)
{
case UnitPixel:
case UnitWorld:
case UnitDisplay:
return pixels;
case UnitDisplay:
if (printer_display)
return pixels * 100.0 / dpi;
else
return pixels;
case UnitPoint:
return pixels * point_per_inch / dpi;
case UnitInch:
......@@ -369,10 +377,10 @@ REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi)
}
}
REAL units_scale(GpUnit from, GpUnit to, REAL dpi)
REAL units_scale(GpUnit from, GpUnit to, REAL dpi, BOOL printer_display)
{
REAL pixels = units_to_pixels(1.0, from, dpi);
return pixels_to_units(pixels, to, dpi);
REAL pixels = units_to_pixels(1.0, from, dpi, printer_display);
return pixels_to_units(pixels, to, dpi, printer_display);
}
/* Calculates Bezier points from cardinal spline points. */
......
......@@ -57,9 +57,9 @@ extern INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2,
REAL startAngle, REAL sweepAngle) DECLSPEC_HIDDEN;
extern REAL gdiplus_atan2(REAL dy, REAL dx) DECLSPEC_HIDDEN;
extern GpStatus hresult_to_status(HRESULT res) DECLSPEC_HIDDEN;
extern REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN;
extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN;
extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi) DECLSPEC_HIDDEN;
extern REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi, BOOL printer_display) DECLSPEC_HIDDEN;
extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi, BOOL printer_display) DECLSPEC_HIDDEN;
extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi, BOOL printer_display) DECLSPEC_HIDDEN;
#define WineCoordinateSpaceGdiDevice ((GpCoordinateSpace)4)
......@@ -231,6 +231,7 @@ struct GpGraphics{
HWND hwnd;
BOOL owndc;
BOOL alpha_hdc;
BOOL printer_display;
GpImage *image;
ImageType image_type;
SmoothingMode smoothing;
......@@ -413,6 +414,7 @@ struct GpMetafile{
GpPointF auto_frame_min, auto_frame_max;
DWORD next_object_id;
UINT limit_dpi;
BOOL printer_display;
/* playback */
GpGraphics *playback_graphics;
......
......@@ -273,7 +273,8 @@ static INT prepare_dc(GpGraphics *graphics, GpPen *pen)
width = sqrt((pt[1].X - pt[0].X) * (pt[1].X - pt[0].X) +
(pt[1].Y - pt[0].Y) * (pt[1].Y - pt[0].Y)) / sqrt(2.0);
width *= units_to_pixels(pen->width, pen->unit == UnitWorld ? graphics->unit : pen->unit, graphics->xres);
width *= units_to_pixels(pen->width, pen->unit == UnitWorld ? graphics->unit : pen->unit,
graphics->xres, graphics->printer_display);
width *= graphics->scale;
pt[0].X = 0.0;
......@@ -2268,14 +2269,14 @@ void get_log_fontW(const GpFont *font, GpGraphics *graphics, LOGFONTW *lf)
if (font->unit == UnitPixel)
{
height = units_to_pixels(font->emSize, graphics->unit, graphics->yres);
height = units_to_pixels(font->emSize, graphics->unit, graphics->yres, graphics->printer_display);
}
else
{
if (graphics->unit == UnitDisplay || graphics->unit == UnitPixel)
height = units_to_pixels(font->emSize, font->unit, graphics->xres);
height = units_to_pixels(font->emSize, font->unit, graphics->xres, graphics->printer_display);
else
height = units_to_pixels(font->emSize, font->unit, graphics->yres);
height = units_to_pixels(font->emSize, font->unit, graphics->yres, graphics->printer_display);
}
lf->lfHeight = -(height + 0.5);
......@@ -2312,7 +2313,7 @@ static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font,
REAL unit_scale, res;
res = (graphics->unit == UnitDisplay || graphics->unit == UnitPixel) ? graphics->xres : graphics->yres;
unit_scale = units_scale(font->unit, graphics->unit, res);
unit_scale = units_scale(font->unit, graphics->unit, res, graphics->printer_display);
font_height = font->emSize * unit_scale;
}
......@@ -2432,6 +2433,7 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra
(*graphics)->textcontrast = 4;
list_init(&(*graphics)->containers);
(*graphics)->contid = 0;
(*graphics)->printer_display = (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASPRINTER);
get_gdi_transform(*graphics, &(*graphics)->gdi_transform);
(*graphics)->gdi_clip = CreateRectRgn(0,0,0,0);
......@@ -2968,9 +2970,9 @@ GpStatus WINGDIPAPI GdipDrawImagePointRect(GpGraphics *graphics, GpImage *image,
if (!graphics || !image) return InvalidParameter;
scale_x = units_scale(srcUnit, graphics->unit, graphics->xres);
scale_x = units_scale(srcUnit, graphics->unit, graphics->xres, graphics->printer_display);
scale_x *= graphics->xres / image->xres;
scale_y = units_scale(srcUnit, graphics->unit, graphics->yres);
scale_y = units_scale(srcUnit, graphics->unit, graphics->yres, graphics->printer_display);
scale_y *= graphics->yres / image->yres;
width = srcwidth * scale_x;
height = srcheight * scale_y;
......@@ -3099,10 +3101,10 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
TRACE("%s %s %s %s\n", wine_dbgstr_point(&pti[0]), wine_dbgstr_point(&pti[1]),
wine_dbgstr_point(&pti[2]), wine_dbgstr_point(&pti[3]));
srcx = units_to_pixels(srcx, srcUnit, image->xres);
srcy = units_to_pixels(srcy, srcUnit, image->yres);
srcwidth = units_to_pixels(srcwidth, srcUnit, image->xres);
srcheight = units_to_pixels(srcheight, srcUnit, image->yres);
srcx = units_to_pixels(srcx, srcUnit, image->xres, graphics->printer_display);
srcy = units_to_pixels(srcy, srcUnit, image->yres, graphics->printer_display);
srcwidth = units_to_pixels(srcwidth, srcUnit, image->xres, graphics->printer_display);
srcheight = units_to_pixels(srcheight, srcUnit, image->yres, graphics->printer_display);
TRACE("src pixels: %f,%f %fx%f\n", srcx, srcy, srcwidth, srcheight);
if (image->type == ImageTypeBitmap)
......@@ -5443,7 +5445,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
(pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
margin_x = stringFormat->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, graphics->printer_display);
scaled_rect.X = (layoutRect->X + margin_x) * args.rel_width;
scaled_rect.Y = layoutRect->Y * args.rel_height;
......@@ -5572,7 +5574,7 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
(pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
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, graphics->printer_display);
scaled_rect.X = (rect->X + margin_x) * args.rel_width;
scaled_rect.Y = rect->Y * args.rel_height;
......@@ -5750,7 +5752,7 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
round_points(corners, rectcpy, 4);
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, graphics->printer_display);
scaled_rect.X = margin_x * rel_width;
scaled_rect.Y = 0.0;
......@@ -5923,8 +5925,8 @@ GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics, GDIPCONST GpRectF *
list_add_head(&graphics->containers, &container->entry);
*state = graphics->contid = container->contid;
scale_x = units_to_pixels(1.0, unit, graphics->xres);
scale_y = units_to_pixels(1.0, unit, graphics->yres);
scale_x = units_to_pixels(1.0, unit, graphics->xres, graphics->printer_display);
scale_y = units_to_pixels(1.0, unit, graphics->yres, graphics->printer_display);
scaled_srcrect.X = scale_x * srcrect->X;
scaled_srcrect.Y = scale_y * srcrect->Y;
......@@ -6863,8 +6865,8 @@ GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_spac
if (dst_space != src_space)
{
scale_x = units_to_pixels(1.0, graphics->unit, graphics->xres);
scale_y = units_to_pixels(1.0, graphics->unit, graphics->yres);
scale_x = units_to_pixels(1.0, graphics->unit, graphics->xres, graphics->printer_display);
scale_y = units_to_pixels(1.0, graphics->unit, graphics->yres, graphics->printer_display);
if(graphics->unit != UnitDisplay)
{
......
......@@ -2195,8 +2195,10 @@ GpStatus WINGDIPAPI GdipGetImageDimension(GpImage *image, REAL *width,
return InvalidParameter;
if(image->type == ImageTypeMetafile){
*height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit, image->yres);
*width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit, image->xres);
*height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit,
image->yres, ((GpMetafile*)image)->printer_display);
*width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit,
image->xres, ((GpMetafile*)image)->printer_display);
}
else if(image->type == ImageTypeBitmap){
*height = ((GpBitmap*)image)->height;
......@@ -2257,7 +2259,8 @@ GpStatus WINGDIPAPI GdipGetImageHeight(GpImage *image, UINT *height)
return InvalidParameter;
if(image->type == ImageTypeMetafile)
*height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit, image->yres);
*height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit,
image->yres, ((GpMetafile*)image)->printer_display);
else if(image->type == ImageTypeBitmap)
*height = ((GpBitmap*)image)->height;
else
......@@ -2366,7 +2369,8 @@ GpStatus WINGDIPAPI GdipGetImageWidth(GpImage *image, UINT *width)
return InvalidParameter;
if(image->type == ImageTypeMetafile)
*width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit, image->xres);
*width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit,
image->xres, ((GpMetafile*)image)->printer_display);
else if(image->type == ImageTypeBitmap)
*width = ((GpBitmap*)image)->width;
else
......
......@@ -837,6 +837,7 @@ GpStatus WINGDIPAPI GdipRecordMetafile(HDC hdc, EmfType type, GDIPCONST GpRectF
(*metafile)->comment_data_length = 0;
(*metafile)->limit_dpi = 96;
(*metafile)->hemf = NULL;
(*metafile)->printer_display = (GetDeviceCaps(record_dc, TECHNOLOGY) == DT_RASPRINTER);
list_init(&(*metafile)->containers);
if (!frameRect)
......@@ -965,6 +966,7 @@ GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result)
*result = metafile->record_graphics;
metafile->record_graphics->xres = 96.0;
metafile->record_graphics->yres = 96.0;
metafile->record_graphics->printer_display = metafile->printer_display;
}
return stat;
......@@ -1790,7 +1792,7 @@ static GpStatus METAFILE_PlaybackUpdateWorldTransform(GpMetafile *metafile)
if (stat == Ok)
{
REAL scale = units_to_pixels(1.0, metafile->page_unit, 96.0);
REAL scale = units_to_pixels(1.0, metafile->page_unit, 96.0, metafile->printer_display);
if (metafile->page_unit != UnitDisplay)
scale *= metafile->page_scale;
......@@ -2897,8 +2899,8 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
unit = record->Header.Flags & 0xff;
scale_x = units_to_pixels(1.0, unit, metafile->image.xres);
scale_y = units_to_pixels(1.0, unit, metafile->image.yres);
scale_x = units_to_pixels(1.0, unit, metafile->image.xres, metafile->printer_display);
scale_y = units_to_pixels(1.0, unit, metafile->image.yres, metafile->printer_display);
scaled_srcrect.X = scale_x * record->SrcRect.X;
scaled_srcrect.Y = scale_y * record->SrcRect.Y;
......@@ -3838,8 +3840,10 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileDestPoint(GpGraphics *graphics,
destf.X = dest->X;
destf.Y = dest->Y;
destf.Width = units_to_pixels(metafile->bounds.Width, metafile->unit, metafile->image.xres);
destf.Height = units_to_pixels(metafile->bounds.Height, metafile->unit, metafile->image.yres);
destf.Width = units_to_pixels(metafile->bounds.Width, metafile->unit,
metafile->image.xres, metafile->printer_display);
destf.Height = units_to_pixels(metafile->bounds.Height, metafile->unit,
metafile->image.yres, metafile->printer_display);
return GdipEnumerateMetafileDestRect(graphics, metafile, &destf, callback, cb_data, attrs);
}
......@@ -4064,6 +4068,9 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromEmf(HENHMETAFILE hemf, BOOL delete,
(*metafile)->metafile_type = header.Type;
(*metafile)->hemf = hemf;
(*metafile)->preserve_hemf = !delete;
/* If the 31th bit of EmfPlusFlags was set, metafile was recorded with a DC for a video display.
* If clear, metafile was recorded with a DC for a printer */
(*metafile)->printer_display = !(header.EmfPlusFlags & (1 << 31));
list_init(&(*metafile)->containers);
TRACE("<-- %p\n", *metafile);
......@@ -4512,10 +4519,10 @@ GpStatus METAFILE_DrawImagePointsRect(GpMetafile *metafile, GpImage *image,
draw_image_record->Header.Flags = image_id;
draw_image_record->ImageAttributesID = attributes_id;
draw_image_record->SrcUnit = UnitPixel;
draw_image_record->SrcRect.X = units_to_pixels(srcx, srcUnit, metafile->image.xres);
draw_image_record->SrcRect.Y = units_to_pixels(srcy, srcUnit, metafile->image.yres);
draw_image_record->SrcRect.Width = units_to_pixels(srcwidth, srcUnit, metafile->image.xres);
draw_image_record->SrcRect.Height = units_to_pixels(srcheight, srcUnit, metafile->image.yres);
draw_image_record->SrcRect.X = units_to_pixels(srcx, srcUnit, metafile->image.xres, metafile->printer_display);
draw_image_record->SrcRect.Y = units_to_pixels(srcy, srcUnit, metafile->image.yres, metafile->printer_display);
draw_image_record->SrcRect.Width = units_to_pixels(srcwidth, srcUnit, metafile->image.xres, metafile->printer_display);
draw_image_record->SrcRect.Height = units_to_pixels(srcheight, srcUnit, metafile->image.yres, metafile->printer_display);
draw_image_record->count = 3;
memcpy(draw_image_record->PointData.pointsF, points, 3 * sizeof(*points));
METAFILE_WriteRecords(metafile);
......
......@@ -7205,7 +7205,6 @@ static void test_printer_dc(void)
rect.Width = pixel_per_unit_x;
rect.Height = pixel_per_unit_y;
match = check_rect_pixels(pixel, &rect, width, 0, &pt);
todo_wine
ok(match, "Expected pixel (%u, %u) to be %08x, got %08x\n",
pt.X, pt.Y, 0, pixel[pt.X + pt.Y * width]);
......@@ -7215,7 +7214,6 @@ static void test_printer_dc(void)
rect.Width = pixel_per_unit_x;
rect.Height = pixel_per_unit_y;
match = check_rect_pixels(pixel, &rect, width, 0x00ffffff, &pt);
todo_wine
ok(match, "Expected pixel (%u, %u) to be %08x, got %08x\n",
pt.X, pt.Y, 0x00ffffff, pixel[pt.X + pt.Y * width]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment