Commit 3cee74c6 authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Rewrite GdipMeasureString using a helper function.

parent 0bc54fb4
...@@ -3550,61 +3550,37 @@ GpStatus WINGDIPAPI GdipIsVisibleRectI(GpGraphics *graphics, INT x, INT y, INT w ...@@ -3550,61 +3550,37 @@ GpStatus WINGDIPAPI GdipIsVisibleRectI(GpGraphics *graphics, INT x, INT y, INT w
return GdipIsVisibleRect(graphics, (REAL)x, (REAL)y, (REAL)width, (REAL)height, result); return GdipIsVisibleRect(graphics, (REAL)x, (REAL)y, (REAL)width, (REAL)height, result);
} }
GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics, typedef GpStatus (*gdip_format_string_callback)(GpGraphics *graphics,
GDIPCONST WCHAR* string, INT length, GDIPCONST GpFont* font, GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
GDIPCONST RectF* layoutRect, GDIPCONST GpStringFormat *stringFormat, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
INT regionCount, GpRegion** regions) INT lineno, const RectF *bounds, void *user_data);
{
FIXME("stub: %p %s %d %p %p %p %d %p\n", graphics, debugstr_w(string),
length, font, layoutRect, stringFormat, regionCount, regions);
if (!(graphics && string && font && layoutRect && stringFormat && regions)) static GpStatus gdip_format_string(GpGraphics *graphics,
return InvalidParameter;
return NotImplemented;
}
/* Find the smallest rectangle that bounds the text when it is printed in rect
* according to the format options listed in format. If rect has 0 width and
* height, then just find the smallest rectangle that bounds the text when it's
* printed at location (rect->X, rect-Y). */
GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, RectF *bounds, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
INT *codepointsfitted, INT *linesfilled) gdip_format_string_callback callback, void *user_data)
{ {
HFONT oldfont;
WCHAR* stringdup; WCHAR* stringdup;
INT sum = 0, height = 0, fit, fitcpy, max_width = 0, i, j, lret, nwidth, INT sum = 0, height = 0, fit, fitcpy, i, j, lret, nwidth,
nheight, lineend; nheight, lineend, lineno = 0;
RectF bounds;
StringAlignment halign;
GpStatus stat = Ok;
SIZE size; SIZE size;
TRACE("(%p, %s, %i, %p, %s, %p, %p, %p, %p)\n", graphics,
debugstr_wn(string, length), length, font, debugstr_rectf(rect), format,
bounds, codepointsfitted, linesfilled);
if(!graphics || !string || !font || !rect || !bounds)
return InvalidParameter;
if(linesfilled) *linesfilled = 0;
if(codepointsfitted) *codepointsfitted = 0;
if(format)
TRACE("may be ignoring some format flags: attr %x\n", format->attr);
if(length == -1) length = lstrlenW(string); if(length == -1) length = lstrlenW(string);
stringdup = GdipAlloc((length + 1) * sizeof(WCHAR)); stringdup = GdipAlloc((length + 1) * sizeof(WCHAR));
if(!stringdup) return OutOfMemory; if(!stringdup) return OutOfMemory;
oldfont = SelectObject(graphics->hdc, CreateFontIndirectW(&font->lfw));
nwidth = roundr(rect->Width); nwidth = roundr(rect->Width);
nheight = roundr(rect->Height); nheight = roundr(rect->Height);
if((nwidth == 0) && (nheight == 0)) if (nwidth == 0) nwidth = INT_MAX;
nwidth = nheight = INT_MAX; if (nheight == 0) nheight = INT_MAX;
for(i = 0, j = 0; i < length; i++){ for(i = 0, j = 0; i < length; i++){
/* FIXME: This makes the indexes passed to callback inaccurate. */
if(!isprintW(string[i]) && (string[i] != '\n')) if(!isprintW(string[i]) && (string[i] != '\n'))
continue; continue;
...@@ -3612,9 +3588,11 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, ...@@ -3612,9 +3588,11 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
j++; j++;
} }
stringdup[j] = 0;
length = j; length = j;
if (format) halign = format->align;
else halign = StringAlignmentNear;
while(sum < length){ while(sum < length){
GetTextExtentExPointW(graphics->hdc, stringdup + sum, length - sum, GetTextExtentExPointW(graphics->hdc, stringdup + sum, length - sum,
nwidth, &fit, NULL, &size); nwidth, &fit, NULL, &size);
...@@ -3657,12 +3635,38 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, ...@@ -3657,12 +3635,38 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
GetTextExtentExPointW(graphics->hdc, stringdup + sum, lineend, GetTextExtentExPointW(graphics->hdc, stringdup + sum, lineend,
nwidth, &j, NULL, &size); nwidth, &j, NULL, &size);
sum += fit + (lret < fitcpy ? 1 : 0); bounds.Width = size.cx;
if(codepointsfitted) *codepointsfitted = sum;
if(height + size.cy > nheight)
bounds.Height = nheight - (height + size.cy);
else
bounds.Height = size.cy;
bounds.Y = rect->Y + height;
switch (halign)
{
case StringAlignmentNear:
default:
bounds.X = rect->X;
break;
case StringAlignmentCenter:
bounds.X = rect->X + (rect->Width/2) - (bounds.Width/2);
break;
case StringAlignmentFar:
bounds.X = rect->X + rect->Width - bounds.Width;
break;
}
stat = callback(graphics, stringdup, sum, lineend,
font, rect, format, lineno, &bounds, user_data);
if (stat != Ok)
break;
sum += fit + (lret < fitcpy ? 1 : 0);
height += size.cy; height += size.cy;
if(linesfilled) *linesfilled += size.cy; lineno++;
max_width = max(max_width, size.cx);
if(height > nheight) if(height > nheight)
break; break;
...@@ -3672,12 +3676,92 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, ...@@ -3672,12 +3676,92 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
break; break;
} }
GdipFree(stringdup);
return stat;
}
GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
GDIPCONST WCHAR* string, INT length, GDIPCONST GpFont* font,
GDIPCONST RectF* layoutRect, GDIPCONST GpStringFormat *stringFormat,
INT regionCount, GpRegion** regions)
{
FIXME("stub: %p %s %d %p %p %p %d %p\n", graphics, debugstr_w(string),
length, font, layoutRect, stringFormat, regionCount, regions);
if (!(graphics && string && font && layoutRect && stringFormat && regions))
return InvalidParameter;
return NotImplemented;
}
struct measure_string_args {
RectF *bounds;
INT *codepointsfitted;
INT *linesfilled;
};
static GpStatus measure_string_callback(GpGraphics *graphics,
GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
INT lineno, const RectF *bounds, void *user_data)
{
struct measure_string_args *args = user_data;
if (bounds->Width > args->bounds->Width)
args->bounds->Width = bounds->Width;
if (bounds->Height + bounds->Y > args->bounds->Height + args->bounds->Y)
args->bounds->Height = bounds->Height + bounds->Y - args->bounds->Y;
if (args->codepointsfitted)
*args->codepointsfitted = index + length;
if (args->linesfilled)
*args->linesfilled += bounds->Height;
return Ok;
}
/* Find the smallest rectangle that bounds the text when it is printed in rect
* according to the format options listed in format. If rect has 0 width and
* height, then just find the smallest rectangle that bounds the text when it's
* printed at location (rect->X, rect-Y). */
GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, RectF *bounds,
INT *codepointsfitted, INT *linesfilled)
{
HFONT oldfont;
struct measure_string_args args;
TRACE("(%p, %s, %i, %p, %s, %p, %p, %p, %p)\n", graphics,
debugstr_wn(string, length), length, font, debugstr_rectf(rect), format,
bounds, codepointsfitted, linesfilled);
if(!graphics || !string || !font || !rect || !bounds)
return InvalidParameter;
if(linesfilled) *linesfilled = 0;
if(codepointsfitted) *codepointsfitted = 0;
if(format)
TRACE("may be ignoring some format flags: attr %x\n", format->attr);
oldfont = SelectObject(graphics->hdc, CreateFontIndirectW(&font->lfw));
bounds->X = rect->X; bounds->X = rect->X;
bounds->Y = rect->Y; bounds->Y = rect->Y;
bounds->Width = (REAL)max_width; bounds->Width = 0.0;
bounds->Height = (REAL) min(height, nheight); bounds->Height = 0.0;
args.bounds = bounds;
args.codepointsfitted = codepointsfitted;
args.linesfilled = linesfilled;
gdip_format_string(graphics, string, length, font, rect, format,
measure_string_callback, &args);
GdipFree(stringdup);
DeleteObject(SelectObject(graphics->hdc, oldfont)); DeleteObject(SelectObject(graphics->hdc, oldfont));
return Ok; return Ok;
......
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