1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

gdiplus: Switch to a struct for gdip_format_string callback args.

This commit is contained in:
Esme Povirk 2024-02-23 19:48:59 +00:00 committed by Alexandre Julliard
parent 8a8d1dedcf
commit f2c92c68a2
3 changed files with 82 additions and 78 deletions

View file

@ -619,12 +619,22 @@ struct gdip_font_link_info {
struct list sections; struct list sections;
}; };
struct gdip_format_string_info {
GpGraphics *graphics;
GDIPCONST WCHAR *string;
INT index;
INT length;
struct gdip_font_link_info font_link_info;
GDIPCONST RectF *rect;
GDIPCONST GpStringFormat *format;
INT lineno;
const RectF *bounds;
INT *underlined_indexes;
INT underlined_index_count;
void *user_data;
};
typedef GpStatus (*gdip_format_string_callback)(GpGraphics *graphics, typedef GpStatus (*gdip_format_string_callback)(struct gdip_format_string_info *info);
GDIPCONST WCHAR *string, INT index, INT length, struct gdip_font_link_info *sections,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
INT lineno, const RectF *bounds, INT *underlined_indexes,
INT underlined_index_count, void *user_data);
GpStatus gdip_format_string(GpGraphics *graphics, GpStatus gdip_format_string(GpGraphics *graphics,
GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font,

View file

@ -5318,17 +5318,26 @@ GpStatus gdip_format_string(GpGraphics *graphics,
INT *hotkeyprefix_offsets=NULL; INT *hotkeyprefix_offsets=NULL;
INT hotkeyprefix_count=0; INT hotkeyprefix_count=0;
INT hotkeyprefix_pos=0, hotkeyprefix_end_pos=0; INT hotkeyprefix_pos=0, hotkeyprefix_end_pos=0;
struct gdip_font_link_info font_link_info = { 0 };
BOOL seen_prefix = FALSE, unixstyle_newline = TRUE; BOOL seen_prefix = FALSE, unixstyle_newline = TRUE;
struct gdip_format_string_info info;
info.graphics = graphics;
info.rect = rect;
info.bounds = &bounds;
info.user_data = user_data;
if(length == -1) length = lstrlenW(string); if(length == -1) length = lstrlenW(string);
stringdup = calloc(length + 1, sizeof(WCHAR)); stringdup = calloc(length + 1, sizeof(WCHAR));
if(!stringdup) return OutOfMemory; if(!stringdup) return OutOfMemory;
info.string = stringdup;
if (!format) if (!format)
format = &default_drawstring_format; format = &default_drawstring_format;
info.format = format;
nwidth = (int)(rect->Width + 0.005f); nwidth = (int)(rect->Width + 0.005f);
nheight = (int)(rect->Height + 0.005f); nheight = (int)(rect->Height + 0.005f);
if (ignore_empty_clip) if (ignore_empty_clip)
@ -5384,10 +5393,10 @@ GpStatus gdip_format_string(GpGraphics *graphics,
halign = format->align; halign = format->align;
generate_font_link_info(graphics, stringdup, length, font, &font_link_info); generate_font_link_info(graphics, stringdup, length, font, &info.font_link_info);
while(sum < length){ while(sum < length){
font_link_get_text_extent_point(&font_link_info, graphics, stringdup, sum, length - sum, nwidth, &fit, &size); font_link_get_text_extent_point(&info.font_link_info, graphics, stringdup, sum, length - sum, nwidth, &fit, &size);
fitcpy = fit; fitcpy = fit;
if(fit == 0) if(fit == 0)
@ -5435,7 +5444,7 @@ GpStatus gdip_format_string(GpGraphics *graphics,
else else
lineend = fit; lineend = fit;
font_link_get_text_extent_point(&font_link_info, graphics, stringdup, sum, lineend, nwidth, &j, &size); font_link_get_text_extent_point(&info.font_link_info, graphics, stringdup, sum, lineend, nwidth, &j, &size);
bounds.Width = size.cx; bounds.Width = size.cx;
@ -5468,10 +5477,13 @@ GpStatus gdip_format_string(GpGraphics *graphics,
if (hotkeyprefix_offsets[hotkeyprefix_end_pos] >= sum + lineend) if (hotkeyprefix_offsets[hotkeyprefix_end_pos] >= sum + lineend)
break; break;
stat = callback(graphics, stringdup, sum, lineend, info.index = sum;
&font_link_info, rect, format, lineno, &bounds, info.length = lineend;
&hotkeyprefix_offsets[hotkeyprefix_pos], info.lineno = lineno;
hotkeyprefix_end_pos-hotkeyprefix_pos, user_data); info.underlined_indexes = &hotkeyprefix_offsets[hotkeyprefix_pos];
info.underlined_index_count = hotkeyprefix_end_pos-hotkeyprefix_pos;
stat = callback(&info);
if (stat != Ok) if (stat != Ok)
break; break;
@ -5500,7 +5512,7 @@ GpStatus gdip_format_string(GpGraphics *graphics,
break; break;
} }
release_font_link_info(&font_link_info); release_font_link_info(&info.font_link_info);
free(stringdup); free(stringdup);
free(hotkeyprefix_offsets); free(hotkeyprefix_offsets);
@ -5535,34 +5547,30 @@ struct measure_ranges_args {
REAL rel_width, rel_height; REAL rel_width, rel_height;
}; };
static GpStatus measure_ranges_callback(GpGraphics *graphics, static GpStatus measure_ranges_callback(struct gdip_format_string_info *info)
GDIPCONST WCHAR *string, INT index, INT length,
struct gdip_font_link_info *font_link_info,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
INT lineno, const RectF *bounds, INT *underlined_indexes,
INT underlined_index_count, void *user_data)
{ {
int i; int i;
GpStatus stat = Ok; GpStatus stat = Ok;
struct measure_ranges_args *args = user_data; struct measure_ranges_args *args = info->user_data;
CharacterRange *ranges = info->format->character_ranges;
for (i=0; i<format->range_count; i++) for (i=0; i < info->format->range_count; i++)
{ {
INT range_start = max(index, format->character_ranges[i].First); INT range_start = max(info->index, ranges[i].First);
INT range_end = min(index+length, format->character_ranges[i].First+format->character_ranges[i].Length); INT range_end = min(info->index + info->length, ranges[i].First + ranges[i].Length);
if (range_start < range_end) if (range_start < range_end)
{ {
GpRectF range_rect; GpRectF range_rect;
SIZE range_size; SIZE range_size;
range_rect.Y = bounds->Y / args->rel_height; range_rect.Y = info->bounds->Y / args->rel_height;
range_rect.Height = bounds->Height / args->rel_height; range_rect.Height = info->bounds->Height / args->rel_height;
font_link_get_text_extent_point(font_link_info, graphics, string, index, range_start - index, INT_MAX, NULL, &range_size); font_link_get_text_extent_point(&info->font_link_info, info->graphics, info->string, info->index, range_start - info->index, INT_MAX, NULL, &range_size);
range_rect.X = (bounds->X + range_size.cx) / args->rel_width; range_rect.X = (info->bounds->X + range_size.cx) / args->rel_width;
font_link_get_text_extent_point(font_link_info, graphics, string, index, range_end - index, INT_MAX, NULL, &range_size); font_link_get_text_extent_point(&info->font_link_info, info->graphics, info->string, info->index, range_end - info->index, INT_MAX, NULL, &range_size);
range_rect.Width = (bounds->X + range_size.cx) / args->rel_width - range_rect.X; range_rect.Width = (info->bounds->X + range_size.cx) / args->rel_width - range_rect.X;
stat = GdipCombineRegionRect(args->regions[i], &range_rect, CombineModeUnion); stat = GdipCombineRegionRect(args->regions[i], &range_rect, CombineModeUnion);
if (stat != Ok) if (stat != Ok)
@ -5659,18 +5667,13 @@ struct measure_string_args {
REAL rel_width, rel_height; REAL rel_width, rel_height;
}; };
static GpStatus measure_string_callback(GpGraphics *graphics, static GpStatus measure_string_callback(struct gdip_format_string_info *info)
GDIPCONST WCHAR *string, INT index, INT length,
struct gdip_font_link_info *font_link_info,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
INT lineno, const RectF *bounds, INT *underlined_indexes,
INT underlined_index_count, void *user_data)
{ {
struct measure_string_args *args = user_data; struct measure_string_args *args = info->user_data;
REAL new_width, new_height; REAL new_width, new_height;
new_width = bounds->Width / args->rel_width; new_width = info->bounds->Width / args->rel_width;
new_height = (bounds->Height + bounds->Y) / args->rel_height - args->bounds->Y; new_height = (info->bounds->Height + info->bounds->Y) / args->rel_height - args->bounds->Y;
if (new_width > args->bounds->Width) if (new_width > args->bounds->Width)
args->bounds->Width = new_width; args->bounds->Width = new_width;
@ -5679,7 +5682,7 @@ static GpStatus measure_string_callback(GpGraphics *graphics,
args->bounds->Height = new_height; args->bounds->Height = new_height;
if (args->codepointsfitted) if (args->codepointsfitted)
*args->codepointsfitted = index + length; *args->codepointsfitted = info->index + info->length;
if (args->linesfilled) if (args->linesfilled)
(*args->linesfilled)++; (*args->linesfilled)++;
@ -5778,63 +5781,58 @@ struct draw_string_args {
REAL x, y, rel_width, rel_height, ascent; REAL x, y, rel_width, rel_height, ascent;
}; };
static GpStatus draw_string_callback(GpGraphics *graphics, static GpStatus draw_string_callback(struct gdip_format_string_info *info)
GDIPCONST WCHAR *string, INT index, INT length,
struct gdip_font_link_info *font_link_info,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
INT lineno, const RectF *bounds, INT *underlined_indexes,
INT underlined_index_count, void *user_data)
{ {
struct draw_string_args *args = user_data; struct draw_string_args *args = info->user_data;
int i = index; int i = info->index;
PointF position; PointF position;
SIZE size; SIZE size;
DWORD to_draw_length; DWORD to_draw_length;
struct gdip_font_link_section *section; struct gdip_font_link_section *section;
GpStatus stat = Ok; GpStatus stat = Ok;
position.X = args->x + bounds->X / args->rel_width; position.X = args->x + info->bounds->X / args->rel_width;
position.Y = args->y + bounds->Y / args->rel_height + args->ascent; position.Y = args->y + info->bounds->Y / args->rel_height + args->ascent;
LIST_FOR_EACH_ENTRY(section, &font_link_info->sections, struct gdip_font_link_section, entry) LIST_FOR_EACH_ENTRY(section, &info->font_link_info.sections, struct gdip_font_link_section, entry)
{ {
if (i >= section->end) continue; if (i >= section->end) continue;
to_draw_length = min(length - (i - index), section->end - i); to_draw_length = min(info->length - (i - info->index), section->end - i);
TRACE("index %d, todraw %ld, used %s\n", i, to_draw_length, section->font == font_link_info->base_font ? "base font" : "map"); TRACE("index %d, todraw %ld, used %s\n", i, to_draw_length, section->font == info->font_link_info.base_font ? "base font" : "map");
font_link_get_text_extent_point(font_link_info, graphics, string, i, to_draw_length, 0, NULL, &size); font_link_get_text_extent_point(&info->font_link_info, info->graphics, info->string, i, to_draw_length, 0, NULL, &size);
stat = draw_driver_string(graphics, &string[i], to_draw_length, stat = draw_driver_string(info->graphics, &info->string[i], to_draw_length,
section->font, format, args->brush, &position, section->font, info->format, args->brush, &position,
DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance, NULL); DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance, NULL);
position.X += size.cx / args->rel_width; position.X += size.cx / args->rel_width;
i += to_draw_length; i += to_draw_length;
if (stat != Ok || (i - index) >= length) break; if (stat != Ok || (i - info->index) >= info->length) break;
} }
if (stat == Ok && underlined_index_count) if (stat == Ok && info->underlined_index_count)
{ {
OUTLINETEXTMETRICW otm; OUTLINETEXTMETRICW otm;
REAL underline_y, underline_height; REAL underline_y, underline_height;
int i; int i;
GetOutlineTextMetricsW(graphics->hdc, sizeof(otm), &otm); GetOutlineTextMetricsW(info->graphics->hdc, sizeof(otm), &otm);
underline_height = otm.otmsUnderscoreSize / args->rel_height; underline_height = otm.otmsUnderscoreSize / args->rel_height;
underline_y = position.Y - otm.otmsUnderscorePosition / args->rel_height - underline_height / 2; underline_y = position.Y - otm.otmsUnderscorePosition / args->rel_height - underline_height / 2;
for (i=0; i<underlined_index_count; i++) for (i=0; i<info->underlined_index_count; i++)
{ {
REAL start_x, end_x; REAL start_x, end_x;
SIZE text_size; SIZE text_size;
INT ofs = underlined_indexes[i] - index; INT ofs = info->underlined_indexes[i] - info->index;
font_link_get_text_extent_point(font_link_info, graphics, string, index, ofs, INT_MAX, NULL, &text_size); font_link_get_text_extent_point(&info->font_link_info, info->graphics, info->string, info->index, ofs, INT_MAX, NULL, &text_size);
start_x = text_size.cx / args->rel_width; start_x = text_size.cx / args->rel_width;
font_link_get_text_extent_point(font_link_info, graphics, string, index, ofs+1, INT_MAX, NULL, &text_size); font_link_get_text_extent_point(&info->font_link_info, info->graphics, info->string, info->index, ofs+1, INT_MAX, NULL, &text_size);
end_x = text_size.cx / args->rel_width; end_x = text_size.cx / args->rel_width;
GdipFillRectangle(graphics, (GpBrush*)args->brush, position.X+start_x, underline_y, end_x-start_x, underline_height); GdipFillRectangle(info->graphics, (GpBrush*)args->brush, position.X+start_x, underline_y, end_x-start_x, underline_height);
} }
} }

View file

@ -997,33 +997,29 @@ struct format_string_args
float ascent; float ascent;
}; };
static GpStatus format_string_callback(GpGraphics *graphics, static GpStatus format_string_callback(struct gdip_format_string_info* info)
GDIPCONST WCHAR *string, INT index, INT length, struct gdip_font_link_info *font_link_info,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
INT lineno, const RectF *bounds, INT *underlined_indexes,
INT underlined_index_count, void *priv)
{ {
static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} }; static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
struct format_string_args *args = priv; struct format_string_args *args = info->user_data;
GpPath *path = args->path; GpPath *path = args->path;
GpStatus status = Ok; GpStatus status = Ok;
float x = rect->X + (bounds->X - rect->X) * args->scale; float x = info->rect->X + (info->bounds->X - info->rect->X) * args->scale;
float y = rect->Y + (bounds->Y - rect->Y) * args->scale; float y = info->rect->Y + (info->bounds->Y - info->rect->Y) * args->scale;
int i; int i;
if (underlined_index_count) if (info->underlined_index_count)
FIXME("hotkey underlines not drawn yet\n"); FIXME("hotkey underlines not drawn yet\n");
if (y + bounds->Height * args->scale > args->maxY) if (y + info->bounds->Height * args->scale > args->maxY)
args->maxY = y + bounds->Height * args->scale; args->maxY = y + info->bounds->Height * args->scale;
for (i = index; i < length + index; ++i) for (i = info->index; i < info->length + info->index; ++i)
{ {
GLYPHMETRICS gm; GLYPHMETRICS gm;
TTPOLYGONHEADER *ph = NULL, *origph; TTPOLYGONHEADER *ph = NULL, *origph;
char *start; char *start;
DWORD len, ofs = 0; DWORD len, ofs = 0;
len = GetGlyphOutlineW(graphics->hdc, string[i], GGO_BEZIER, &gm, 0, NULL, &identity); len = GetGlyphOutlineW(info->graphics->hdc, info->string[i], GGO_BEZIER, &gm, 0, NULL, &identity);
if (len == GDI_ERROR) if (len == GDI_ERROR)
{ {
status = GenericError; status = GenericError;
@ -1037,7 +1033,7 @@ static GpStatus format_string_callback(GpGraphics *graphics,
status = OutOfMemory; status = OutOfMemory;
break; break;
} }
GetGlyphOutlineW(graphics->hdc, string[i], GGO_BEZIER, &gm, len, start, &identity); GetGlyphOutlineW(info->graphics->hdc, info->string[i], GGO_BEZIER, &gm, len, start, &identity);
ofs = 0; ofs = 0;
while (ofs < len) while (ofs < len)