gdiplus: Add support for generic typographic string format.

This commit is contained in:
Dmitry Timoshkov 2012-09-03 17:57:17 +09:00 committed by Alexandre Julliard
parent bfa35f37a7
commit b8f4252290
3 changed files with 58 additions and 40 deletions

View File

@ -368,6 +368,7 @@ struct GpStringFormat{
REAL *tabs; REAL *tabs;
CharacterRange *character_ranges; CharacterRange *character_ranges;
INT range_count; INT range_count;
BOOL generic_typographic;
}; };
struct GpFontCollection{ struct GpFontCollection{

View File

@ -46,6 +46,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
#define ANCHOR_WIDTH (2.0) #define ANCHOR_WIDTH (2.0)
#define MAX_ITERS (50) #define MAX_ITERS (50)
static GpStatus draw_driver_string(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format,
GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
INT flags, GDIPCONST GpMatrix *matrix);
/* Converts angle (in degrees) to x/y coordinates */ /* Converts angle (in degrees) to x/y coordinates */
static void deg2xy(REAL angle, REAL x_0, REAL y_0, REAL *x, REAL *y) static void deg2xy(REAL angle, REAL x_0, REAL y_0, REAL *x, REAL *y)
{ {
@ -2110,7 +2115,8 @@ end:
return stat; return stat;
} }
static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font, HFONT *hfont) static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font,
GDIPCONST GpStringFormat *format, HFONT *hfont)
{ {
HDC hdc = CreateCompatibleDC(0); HDC hdc = CreateCompatibleDC(0);
GpPointF pt[3]; GpPointF pt[3];
@ -2119,7 +2125,7 @@ static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font, HFONT *
HFONT unscaled_font; HFONT unscaled_font;
TEXTMETRICW textmet; TEXTMETRICW textmet;
font_to_pixel_scale = units_scale(UnitPoint, UnitPixel, font->family->dpi); font_to_pixel_scale = (format && format->generic_typographic) ? 1.0 : units_scale(UnitPoint, UnitPixel, font->family->dpi);
if (font->unit == UnitPixel) if (font->unit == UnitPixel)
font_height = font->emSize * font_to_pixel_scale; font_height = font->emSize * font_to_pixel_scale;
@ -4972,8 +4978,8 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+ args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
(pt[2].X-pt[0].X)*(pt[2].X-pt[0].X)); (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
/* FIXME: GenericTypographic format prevents extra margins */ margin_x = stringFormat->generic_typographic ? 0.0 : font->emSize / 6.0;
margin_x = units_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0; margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
scaled_rect.X = (layoutRect->X + margin_x) * args.rel_width; scaled_rect.X = (layoutRect->X + margin_x) * args.rel_width;
scaled_rect.Y = layoutRect->Y * args.rel_height; scaled_rect.Y = layoutRect->Y * args.rel_height;
@ -4993,7 +4999,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */ if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
} }
get_font_hfont(graphics, font, &gdifont); get_font_hfont(graphics, font, stringFormat, &gdifont);
oldfont = SelectObject(hdc, gdifont); oldfont = SelectObject(hdc, gdifont);
for (i=0; i<stringFormat->range_count; i++) for (i=0; i<stringFormat->range_count; i++)
@ -5101,8 +5107,8 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+ args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
(pt[2].X-pt[0].X)*(pt[2].X-pt[0].X)); (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
/* FIXME: GenericTypographic format prevents extra margins */ margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
margin_x = units_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0; margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
scaled_rect.X = (rect->X + margin_x) * args.rel_width; scaled_rect.X = (rect->X + margin_x) * args.rel_width;
scaled_rect.Y = rect->Y * args.rel_height; scaled_rect.Y = rect->Y * args.rel_height;
@ -5123,7 +5129,7 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
if (scaled_rect.Width >= INT_MAX || scaled_rect.Width < 0.5) scaled_rect.Width = (REAL)(1 << 23); if (scaled_rect.Width >= INT_MAX || scaled_rect.Width < 0.5) scaled_rect.Width = (REAL)(1 << 23);
if (scaled_rect.Height >= INT_MAX || scaled_rect.Height < 0.5) scaled_rect.Height = (REAL)(1 << 23); if (scaled_rect.Height >= INT_MAX || scaled_rect.Height < 0.5) scaled_rect.Height = (REAL)(1 << 23);
get_font_hfont(graphics, font, &gdifont); get_font_hfont(graphics, font, format, &gdifont);
oldfont = SelectObject(hdc, gdifont); oldfont = SelectObject(hdc, gdifont);
bounds->X = rect->X; bounds->X = rect->X;
@ -5173,7 +5179,7 @@ static GpStatus draw_string_callback(HDC hdc,
position.X = args->x + bounds->X / args->rel_width; position.X = args->x + bounds->X / args->rel_width;
position.Y = args->y + bounds->Y / args->rel_height + args->ascent; position.Y = args->y + bounds->Y / args->rel_height + args->ascent;
stat = GdipDrawDriverString(args->graphics, &string[index], length, font, stat = draw_driver_string(args->graphics, &string[index], length, font, format,
args->brush, &position, args->brush, &position,
DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance, NULL); DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance, NULL);
@ -5280,8 +5286,8 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height; rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height;
transform_and_round_points(graphics, corners, rectcpy, 4); transform_and_round_points(graphics, corners, rectcpy, 4);
/* FIXME: GenericTypographic format prevents extra margins */ margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
margin_x = units_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0; margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
scaled_rect.X = margin_x * rel_width; scaled_rect.X = margin_x * rel_width;
scaled_rect.Y = 0.0; scaled_rect.Y = 0.0;
@ -5310,7 +5316,7 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
SelectClipRgn(hdc, rgn); SelectClipRgn(hdc, rgn);
} }
get_font_hfont(graphics, font, &gdifont); get_font_hfont(graphics, font, format, &gdifont);
SelectObject(hdc, gdifont); SelectObject(hdc, gdifont);
args.graphics = graphics; args.graphics = graphics;
@ -6269,7 +6275,7 @@ GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT
if (matrix) if (matrix)
FIXME("Ignoring matrix\n"); FIXME("Ignoring matrix\n");
get_font_hfont(graphics, font, &hfont); get_font_hfont(graphics, font, NULL, &hfont);
hdc = CreateCompatibleDC(0); hdc = CreateCompatibleDC(0);
SelectObject(hdc, hfont); SelectObject(hdc, hfont);
@ -6345,9 +6351,9 @@ GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT
} }
static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
GDIPCONST GpFont *font, GDIPCONST GpBrush *brush, GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format,
GDIPCONST PointF *positions, INT flags, GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
GDIPCONST GpMatrix *matrix ) INT flags, GDIPCONST GpMatrix *matrix)
{ {
static const INT unsupported_flags = ~(DriverStringOptionsRealizedAdvance|DriverStringOptionsCmapLookup); static const INT unsupported_flags = ~(DriverStringOptionsRealizedAdvance|DriverStringOptionsCmapLookup);
INT save_state; INT save_state;
@ -6371,7 +6377,7 @@ static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT1
pt = positions[0]; pt = positions[0];
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &pt, 1); GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &pt, 1);
get_font_hfont(graphics, font, &hfont); get_font_hfont(graphics, font, format, &hfont);
SelectObject(graphics->hdc, hfont); SelectObject(graphics->hdc, hfont);
SetTextAlign(graphics->hdc, TA_BASELINE|TA_LEFT); SetTextAlign(graphics->hdc, TA_BASELINE|TA_LEFT);
@ -6386,9 +6392,9 @@ static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT1
} }
static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
GDIPCONST GpFont *font, GDIPCONST GpBrush *brush, GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format,
GDIPCONST PointF *positions, INT flags, GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
GDIPCONST GpMatrix *matrix ) INT flags, GDIPCONST GpMatrix *matrix)
{ {
static const INT unsupported_flags = ~(DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance); static const INT unsupported_flags = ~(DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance);
GpStatus stat; GpStatus stat;
@ -6446,7 +6452,7 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
GdipFree(real_positions); GdipFree(real_positions);
} }
get_font_hfont(graphics, font, &hfont); get_font_hfont(graphics, font, format, &hfont);
hdc = CreateCompatibleDC(0); hdc = CreateCompatibleDC(0);
SelectObject(hdc, hfont); SelectObject(hdc, hfont);
@ -6579,20 +6585,12 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
return stat; return stat;
} }
/***************************************************************************** static GpStatus draw_driver_string(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
* GdipDrawDriverString [GDIPLUS.@] GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format,
*/ GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
GpStatus WINGDIPAPI GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, INT flags, GDIPCONST GpMatrix *matrix)
GDIPCONST GpFont *font, GDIPCONST GpBrush *brush,
GDIPCONST PointF *positions, INT flags,
GDIPCONST GpMatrix *matrix )
{ {
GpStatus stat=NotImplemented; GpStatus stat = NotImplemented;
TRACE("(%p %s %p %p %p %d %p)\n", graphics, debugstr_wn(text, length), font, brush, positions, flags, matrix);
if (!graphics || !text || !font || !brush || !positions)
return InvalidParameter;
if (length == -1) if (length == -1)
length = strlenW(text); length = strlenW(text);
@ -6601,16 +6599,31 @@ GpStatus WINGDIPAPI GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16
((flags & DriverStringOptionsRealizedAdvance) || length <= 1) && ((flags & DriverStringOptionsRealizedAdvance) || length <= 1) &&
brush->bt == BrushTypeSolidColor && brush->bt == BrushTypeSolidColor &&
(((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000) (((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000)
stat = GDI32_GdipDrawDriverString(graphics, text, length, font, brush, stat = GDI32_GdipDrawDriverString(graphics, text, length, font, format,
positions, flags, matrix); brush, positions, flags, matrix);
if (stat == NotImplemented) if (stat == NotImplemented)
stat = SOFTWARE_GdipDrawDriverString(graphics, text, length, font, brush, stat = SOFTWARE_GdipDrawDriverString(graphics, text, length, font, format,
positions, flags, matrix); brush, positions, flags, matrix);
return stat; return stat;
} }
/*****************************************************************************
* GdipDrawDriverString [GDIPLUS.@]
*/
GpStatus WINGDIPAPI GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
GDIPCONST GpFont *font, GDIPCONST GpBrush *brush,
GDIPCONST PointF *positions, INT flags,
GDIPCONST GpMatrix *matrix )
{
TRACE("(%p %s %p %p %p %d %p)\n", graphics, debugstr_wn(text, length), font, brush, positions, flags, matrix);
if (!graphics || !text || !font || !brush || !positions)
return InvalidParameter;
return draw_driver_string(graphics, text, length, font, NULL,
brush, positions, flags, matrix);
}
GpStatus WINGDIPAPI GdipRecordMetafileStream(IStream *stream, HDC hdc, EmfType type, GDIPCONST GpRect *frameRect, GpStatus WINGDIPAPI GdipRecordMetafileStream(IStream *stream, HDC hdc, EmfType type, GDIPCONST GpRect *frameRect,
MetafileFrameUnit frameUnit, GDIPCONST WCHAR *desc, GpMetafile **metafile) MetafileFrameUnit frameUnit, GDIPCONST WCHAR *desc, GpMetafile **metafile)
{ {

View File

@ -50,6 +50,7 @@ GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang,
(*format)->digitsub = StringDigitSubstituteUser; (*format)->digitsub = StringDigitSubstituteUser;
(*format)->character_ranges = NULL; (*format)->character_ranges = NULL;
(*format)->range_count = 0; (*format)->range_count = 0;
(*format)->generic_typographic = FALSE;
/* tabstops */ /* tabstops */
(*format)->tabcount = 0; (*format)->tabcount = 0;
(*format)->firsttab = 0.0; (*format)->firsttab = 0.0;
@ -386,6 +387,9 @@ GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **forma
(*format)->hkprefix = HotkeyPrefixNone; (*format)->hkprefix = HotkeyPrefixNone;
(*format)->align = StringAlignmentNear; (*format)->align = StringAlignmentNear;
(*format)->vertalign = StringAlignmentNear; (*format)->vertalign = StringAlignmentNear;
(*format)->generic_typographic = TRUE;
TRACE("%p => %p\n", format, *format);
return Ok; return Ok;
} }