Example #1
0
/*****************************************************************************
 * GdipCombineRegionRectI [GDIPLUS.@]
 */
GpStatus WINGDIPAPI GdipCombineRegionRectI(GpRegion *region,
        GDIPCONST GpRect *rect, CombineMode mode)
{
    GpRectF rectf;

    TRACE("%p %p %d\n", region, rect, mode);

    if (!rect)
        return InvalidParameter;

    rectf.X = (REAL)rect->X;
    rectf.Y = (REAL)rect->Y;
    rectf.Height = (REAL)rect->Height;
    rectf.Width = (REAL)rect->Width;

    return GdipCombineRegionRect(region, &rectf, mode);
}
GpStatus
pango_MeasureCharacterRanges (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font,
	GDIPCONST GpRectF *layoutRect, GDIPCONST GpStringFormat *format, int regionCount, GpRegion **regions)
{
	PangoLayout *layout;
	GpStatus status = Ok;
	int i, j;
	GpRectF boundingBox;

	cairo_save (graphics->ct);

	layout = gdip_pango_setup_layout (graphics, stringUnicode, length, font, layoutRect, &boundingBox, format, NULL);
	if (!layout) {
		cairo_restore (graphics->ct);
		return OutOfMemory;
	}

	/* Create a region for every char range */
	for (i = 0; i < format->charRangeCount; i++) {
		int start, end;
		CharacterRange range = format->charRanges [i];

		GdipSetEmpty (regions [i]);

		if (range.Length > 0)
			start = range.First;
		else
			start = range.First + range.Length;

		end = start + range.Length;

		/* sanity check on charRange. negative lengths are allowed */
		if (range.First < 0) {
			status = InvalidParameter;
			goto cleanup;
		}

		if ((start < 0) || (end > length)) {
			status = InvalidParameter;
			goto cleanup;
		}

		/* calculate the initial UTF-8 index */
		int idxUtf8 = utf8_length_for_ucs2_string (stringUnicode, 0, start);

		/* calculate the regions */
		for (j = start; j < end; j++) {
			PangoRectangle box;
			GpRectF charRect;

			pango_layout_index_to_pos (layout, idxUtf8, &box);
			charRect.X = (float)box.x / PANGO_SCALE;
			charRect.Y = (float)box.y / PANGO_SCALE;
			charRect.Width = (float)box.width / PANGO_SCALE;
			charRect.Height = (float)box.height / PANGO_SCALE;
			/* Normalize values (width/height can be negative) */
			if (charRect.Width < 0) {
				charRect.Width = -charRect.Width;
				charRect.X -= charRect.Width;
			}
			if (charRect.Height < 0) {
				charRect.Height = -charRect.Height;
				charRect.Y -= charRect.Height;
			}
// g_warning ("[%d] [%d : %d-%d] %c [x %g y %g w %g h %g]", i, j, start, end, (char)stringUnicode[j], charRect.X, charRect.Y, charRect.Width, charRect.Height);
			status = GdipCombineRegionRect (regions [i], &charRect, CombineModeUnion);
			if (status != Ok)
				break;

			// update the UTF-8 index
			idxUtf8 += utf8_length_for_ucs2_string (stringUnicode, j, 1);
		}
		if (status != Ok)
			break;
	}

cleanup:
	cairo_restore (graphics->ct);
	return status;
}
Example #3
0
GpStatus
cairo_MeasureCharacterRanges (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, 
	GDIPCONST GpRectF *layout, GDIPCONST GpStringFormat *format, int regionCount, GpRegion **regions)
{
	int			i, j, start, end;
	int			lineHeight;
	CharacterRange		range;
	GpStringDetailStruct*	StringDetails;
	RectF			charRect;
	RectF 			rc_coords, *layoutRect = &rc_coords;
	BOOL			optimize_convert;
	WCHAR *CleanString;
	GpDrawTextData data; /* avoid recomputation of stuff done while measuring */
	int StringLen = length;

	GpStatus status = AllocStringData (&CleanString, &StringDetails, length);
	if (status != Ok)
		return status;

	/* avoid conversion if possible */
	optimize_convert = OPTIMIZE_CONVERSION (graphics);
	if (optimize_convert) {
		layoutRect->X = layout->X;
		layoutRect->Y = layout->Y;
		layoutRect->Width = layout->Width;
		layoutRect->Height = layout->Height;
	} else {
		layoutRect->X = gdip_unitx_convgr (graphics, layout->X);
		layoutRect->Y = gdip_unity_convgr (graphics, layout->Y);
		layoutRect->Width = gdip_unitx_convgr (graphics, layout->Width);
		layoutRect->Height = gdip_unity_convgr (graphics, layout->Height);
	}

	if (layoutRect->Width <= 0.0) {
		if (layoutRect->Height < 0.0) {
			/* special case only if BOTH values are negative */
			for (i = 0; i < format->charRangeCount; i++)
				GdipSetInfinite (regions [i]);
			return Ok;
		} else {
			layoutRect->Width = REGION_INFINITE_LENGTH;
		}
	}
	if (layoutRect->Height <= 0.0) {
		layoutRect->Height = REGION_INFINITE_LENGTH;
	}

	/* string measurements */
	status = MeasureString (graphics, stringUnicode, &StringLen, font, layoutRect, format, NULL, NULL, NULL, NULL,
		CleanString, StringDetails, &data);
	if (status != Ok)
		goto cleanup;

	lineHeight = data.line_height + data.descent;

	/* Create a region for every char range */
	for (i = 0; i < format->charRangeCount; i++) {
		range = format->charRanges [i];
		GdipSetEmpty (regions [i]); 

		if (range.Length > 0)
			start = range.First;
		else
			start = range.First + range.Length;

		end = start + range.Length;

		/* sanity check on charRange. negative lengths are allowed */
		if (range.First < 0) {
			status = InvalidParameter;
			goto cleanup;
		}

		if ((start < 0) || (end > length)) {
			status = InvalidParameter;
			goto cleanup;
		}

		/* calculate the regions */
		for (j = start; j < end; j++) {

			/* the prefix char (&) always count - even if we are not actually print it as a char */
			if ((StringDetails[j].Flags & STRING_DETAIL_HOTKEY) && (format->hotkeyPrefix != HotkeyPrefixNone)) {
				end--; /* '&' count as invisible char */
				continue;
			}

			/* workaround the fact that current implementation thinks LF is on the next line */
			if ((j == end - 1) && (StringDetails[j].Flags & STRING_DETAIL_LF))
				continue;

			if (format->formatFlags & StringFormatFlagsDirectionVertical) {
				charRect.X = layoutRect->X + StringDetails [j].PosY;
				charRect.Y = layoutRect->Y + StringDetails [j].PosX;
				charRect.Width = lineHeight;
				charRect.Height = StringDetails [j].Width;
			} else {
				charRect.X = layoutRect->X + StringDetails [j].PosX;
				charRect.Y = layoutRect->Y + StringDetails [j].PosY;
				charRect.Width = StringDetails [j].Width;
				charRect.Height = lineHeight;
			}

			if (optimize_convert) {
				charRect.X = gdip_convgr_unitx (graphics, charRect.X);
				charRect.Y = gdip_convgr_unity (graphics, charRect.Y);
				charRect.Width = gdip_convgr_unitx (graphics, charRect.Width);
				charRect.Height = gdip_convgr_unity (graphics, charRect.Height);
			}

			status = GdipCombineRegionRect (regions [i], &charRect, CombineModeUnion);
			if (status != Ok)
				break;
		}
		if (status != Ok)
			break;
	}

cleanup:
	/* Cleanup */
	GdipFree (CleanString);
	GdipFree (StringDetails);

	return status;
}
Example #4
0
static void test_combinereplace(void)
{
    GpStatus status;
    GpRegion *region, *region2;
    GpPath *path;
    GpRectF rectf;
    UINT needed;
    DWORD buf[50];

    rectf.X = rectf.Y = 0.0;
    rectf.Width = rectf.Height = 100.0;

    status = GdipCreateRegionRect(&rectf, &region);
    expect(Ok, status);

    /* replace with the same rectangle */
    status = GdipCombineRegionRect(region, &rectf,CombineModeReplace);
    expect(Ok, status);

    status = GdipGetRegionDataSize(region, &needed);
    expect(Ok, status);
    expect(36, needed);
    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
    expect(Ok, status);
    expect(36, needed);
    expect_dword(buf, 28);
    trace("buf[1] = %08x\n", buf[1]);
    expect_magic((DWORD*)(buf + 2));
    expect_dword(buf + 3, 0);
    expect_dword(buf + 4, RGNDATA_RECT);

    /* replace with path */
    status = GdipCreatePath(FillModeAlternate, &path);
    expect(Ok, status);
    status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 250.0);
    expect(Ok, status);
    status = GdipCombineRegionPath(region, path, CombineModeReplace);
    expect(Ok, status);

    status = GdipGetRegionDataSize(region, &needed);
    expect(Ok, status);
    expect(156, needed);
    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
    expect(Ok, status);
    expect(156, needed);
    expect_dword(buf, 148);
    trace("buf[1] = %08x\n", buf[1]);
    expect_magic((DWORD*)(buf + 2));
    expect_dword(buf + 3, 0);
    expect_dword(buf + 4, RGNDATA_PATH);
    GdipDeletePath(path);

    /* replace with infinite rect */
    status = GdipCreateRegion(&region2);
    expect(Ok, status);
    status = GdipCombineRegionRegion(region, region2, CombineModeReplace);
    expect(Ok, status);

    status = GdipGetRegionDataSize(region, &needed);
    expect(Ok, status);
    expect(20, needed);
    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
    expect(Ok, status);
    expect(20, needed);
    expect_dword(buf, 12);
    trace("buf[1] = %08x\n", buf[1]);
    expect_magic((DWORD*)(buf + 2));
    expect_dword(buf + 3, 0);
    expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
    GdipDeleteRegion(region2);

    /* more complex case : replace with a combined region */
    status = GdipCreateRegionRect(&rectf, &region2);
    expect(Ok, status);
    status = GdipCreatePath(FillModeAlternate, &path);
    expect(Ok, status);
    status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 250.0);
    expect(Ok, status);
    status = GdipCombineRegionPath(region2, path, CombineModeUnion);
    expect(Ok, status);
    GdipDeletePath(path);
    status = GdipCombineRegionRegion(region, region2, CombineModeReplace);
    expect(Ok, status);
    GdipDeleteRegion(region2);

    status = GdipGetRegionDataSize(region, &needed);
    expect(Ok, status);
    expect(180, needed);
    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
    expect(Ok, status);
    expect(180, needed);
    expect_dword(buf, 172);
    trace("buf[1] = %08x\n", buf[1]);
    expect_magic((DWORD*)(buf + 2));
    expect_dword(buf + 3, 2);
    expect_dword(buf + 4, CombineModeUnion);

    GdipDeleteRegion(region);
}