From 824c465a675cfb66dfc8f31c7ace09b74836afc4 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Fri, 1 Jan 2010 16:11:46 -0600 Subject: [PATCH] gdiplus: Implement GdipMeasureCharacterRanges. --- dlls/gdiplus/graphics.c | 126 +++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 121 insertions(+), 5 deletions(-) diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 563e43a..b083990 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -3449,16 +3449,132 @@ GpStatus WINGDIPAPI GdipIsVisibleRectI(GpGraphics *graphics, INT x, INT y, INT w GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics, GDIPCONST WCHAR* string, INT length, GDIPCONST GpFont* font, - GDIPCONST RectF* layoutRect, GDIPCONST GpStringFormat *stringFormat, + GDIPCONST RectF* rect, GDIPCONST GpStringFormat *format, INT regionCount, GpRegion** regions) { - if (!(graphics && string && font && layoutRect && stringFormat && regions)) + HFONT oldfont; + WCHAR* stringdup; + INT sum = 0, height = 0, fit, fitcpy, i, j, lret, nwidth, + nheight, lineend, range; + SIZE size; + + TRACE("%p %s %d %p %p %p %d %p\n", graphics, debugstr_wn(string, length), + length, font, rect, format, regionCount, regions); + + if (!graphics || !string || !font || !rect || !format || !regions) return InvalidParameter; - FIXME("stub: %p %s %d %p %p %p %d %p\n", graphics, debugstr_w(string), - length, font, layoutRect, stringFormat, regionCount, regions); + if (regionCount != format->range_count) + return InvalidParameter; - return NotImplemented; + if (format->attr) + TRACE("may be ignoring some format flags: attr %x\n", format->attr); + + if(length == -1) length = lstrlenW(string); + + stringdup = GdipAlloc((length + 1) * sizeof(WCHAR)); + if(!stringdup) return OutOfMemory; + + oldfont = SelectObject(graphics->hdc, CreateFontIndirectW(&font->lfw)); + nwidth = roundr(rect->Width); + nheight = roundr(rect->Height); + + if((nwidth == 0) && (nheight == 0)) + nwidth = nheight = INT_MAX; + + for(i = 0, j = 0; i < length; i++){ + if(!isprintW(string[i]) && (string[i] != '\n')) + continue; + + stringdup[j] = string[i]; + j++; + } + + stringdup[j] = 0; + length = j; + + while(sum < length){ + GetTextExtentExPointW(graphics->hdc, stringdup + sum, length - sum, + nwidth, &fit, NULL, &size); + fitcpy = fit; + + if(fit == 0) + break; + + for(lret = 0; lret < fit; lret++) + if(*(stringdup + sum + lret) == '\n') + break; + + /* Line break code (may look strange, but it imitates windows). */ + if(lret < fit) + lineend = fit = lret; /* this is not an off-by-one error */ + else if(fit < (length - sum)){ + if(*(stringdup + sum + fit) == ' ') + while(*(stringdup + sum + fit) == ' ') + fit++; + else + while(*(stringdup + sum + fit - 1) != ' '){ + fit--; + + if(*(stringdup + sum + fit) == '\t') + break; + + if(fit == 0){ + fit = fitcpy; + break; + } + } + lineend = fit; + while(*(stringdup + sum + lineend - 1) == ' ' || + *(stringdup + sum + lineend - 1) == '\t') + lineend--; + } + else + lineend = fit; + + GetTextExtentExPointW(graphics->hdc, stringdup + sum, lineend, + nwidth, &j, NULL, &size); + + for (range=0; rangecharacter_ranges[range].First); + INT range_end = min(sum+lineend, format->character_ranges[range].First+format->character_ranges[range].Length); + if (range_start < range_end) + { + GpRectF range_rect; + SIZE range_size; + + range_rect.Y = height; + range_rect.Height = size.cy; + + GetTextExtentExPointW(graphics->hdc, stringdup + sum, range_start - sum, + nwidth, NULL, NULL, &range_size); + range_rect.X = range_size.cx; + + GetTextExtentExPointW(graphics->hdc, stringdup + range_start, range_end - range_start, + nwidth, NULL, NULL, &range_size); + range_rect.Width = range_size.cx; + + GdipCombineRegionRect(regions[range], &range_rect, CombineModeIntersect); + } + } + + sum += fit + (lret < fitcpy ? 1 : 0); + + height += size.cy; + + if(height > nheight) + break; + + /* Stop if this was a linewrap (but not if it was a linebreak). */ + if((lret == fitcpy) && format && (format->attr & StringFormatFlagsNoWrap)) + break; + } + + GdipFree(stringdup); + DeleteObject(SelectObject(graphics->hdc, oldfont)); + + return Ok; } /* Find the smallest rectangle that bounds the text when it is printed in rect -- 1.6.3.3