GpStatus
pango_DrawString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, GDIPCONST RectF *rc,
	GDIPCONST GpStringFormat *format, GpBrush *brush)
{
	PangoLayout *layout;
	RectF box;

	/* Setup cairo */
	if (brush) {
		gdip_brush_setup (graphics, brush);
	} else {
		cairo_set_source_rgb (graphics->ct, 0., 0., 0.);
	}

	cairo_save (graphics->ct);

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

	gdip_cairo_move_to (graphics, rc->X, rc->Y, FALSE, TRUE);
	pango_cairo_show_layout (graphics->ct, layout);

	g_object_unref (layout);
	cairo_restore (graphics->ct);
	return Ok;
}
Example #2
0
GpStatus
gdip_adjust_arrowcap_draw (GpGraphics *graphics, GpPen *pen, GpCustomLineCap *customCap, float x, float y, float otherend_x, float otherend_y)
{
	double angle;
	GpAdjustableArrowCap *arrowcap;
	float w;
	float h;
	float penwidth;

	if (!graphics || !customCap)
		return InvalidParameter;

	penwidth = pen->width;
	if (penwidth < 2.0) {
		/* Seems to be a minimum */
		penwidth = 2.0;
	}

	arrowcap = (GpAdjustableArrowCap *)customCap;
	w = arrowcap->width / 2;
	h = arrowcap->height;

	angle = gdip_custom_linecap_angle (x, y, otherend_x, otherend_y);

	cairo_save (graphics->ct);

	/* FIXME: handle base_inset (including set/get!) */
	cairo_translate (graphics->ct, x, y);
	cairo_rotate (graphics->ct, angle);

	gdip_cairo_move_to (graphics, 0, 0, TRUE, TRUE);
	gdip_cairo_line_to (graphics, -w * penwidth, -h * penwidth, TRUE, TRUE);
	gdip_cairo_line_to (graphics, w * penwidth, -h * penwidth, TRUE, TRUE);
	gdip_cairo_line_to (graphics, 0, 0, TRUE, TRUE);

	if (arrowcap->fill_state) {
		/* FIXME: handle middle_inset */
		cairo_fill_preserve (graphics->ct);
	}

	cairo_stroke (graphics->ct);

	cairo_restore (graphics->ct);

	return Ok;
}
Example #3
0
static GpStatus
DrawString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, 
	GDIPCONST RectF *rc_org, GDIPCONST GpStringFormat *fmt, GpBrush *brush, 
	WCHAR *CleanString, GpStringDetailStruct* StringDetails, GpDrawTextData *data)
{
	float CursorX = 0.0;		/* Current X position of drawing cursor */
	float CursorY = 0.0;		/* Current Y position of drawing cursor */
	int StringLen = length;
	BOOL SetClipping = FALSE;
	unsigned long	i, j;
	int AlignHorz = data->align_horz;
	int AlignVert = data->align_vert;
	int LineHeight = data->line_height;
	int MaxY = data->max_y;
	cairo_font_extents_t FontExtent;
	RectF rect, *rc = &rect;

	cairo_font_extents (graphics->ct, &FontExtent);

	if (OPTIMIZE_CONVERSION (graphics)) {
		rc->X = rc_org->X;
		rc->Y = rc_org->Y;
		rc->Width = rc_org->Width;
		rc->Height = rc_org->Height;
	} else {
		rc->X = gdip_unitx_convgr (graphics, rc_org->X);
		rc->Y = gdip_unity_convgr (graphics, rc_org->Y);
		rc->Width = gdip_unitx_convgr (graphics, rc_org->Width);
		rc->Height = gdip_unity_convgr (graphics, rc_org->Height);
	}

	/* Set our clipping rectangle */
	if ((rc->Width!=0) && (rc->Height!=0) && ((fmt->formatFlags & StringFormatFlagsNoClip)==0)) {
#ifdef DRAWSTRING_DEBUG
		printf("Setting clipping rectangle (%f, %f %fx%f)\n", rc->X, rc->Y, rc->Width, rc->Height);
#endif		
		/* We do not call cairo_reset_clip because we want to take previous clipping into account */
		gdip_cairo_rectangle (graphics, rc->X, rc->Y, rc->Width, rc->Height, TRUE);
		cairo_clip (graphics->ct);
		SetClipping = TRUE;
	}

	/* Setup cairo */

	if (brush) {
		gdip_brush_setup (graphics, (GpBrush *)brush);
	} else {
		cairo_set_source_rgb (graphics->ct, 0., 0., 0.);
	}

	for (i=0; i<StringLen; i++) {
		if (StringDetails[i].Flags & STRING_DETAIL_LINESTART) {
			BYTE *String;
			int length = StringDetails[i].LineLen;
			int current_line_length = min (length + i, StringLen);

			/* To support the LineLimit flag */
			if ((StringDetails[i].Flags & STRING_DETAIL_HIDDEN)!=0){
#ifdef DRAWSTRING_DEBUG
				printf("Hidding partially visible line\n");
#endif
				i=StringLen;
				continue;
			}

			if (length > StringLen - i)
				length = StringLen - i;
			String = (BYTE*) ucs2_to_utf8 ((const gunichar2 *)(CleanString+i), length);
#ifdef DRAWSTRING_DEBUG
			printf("Displaying line >%s< (%d chars)\n", String, length);
#endif

			if ((fmt->formatFlags & StringFormatFlagsDirectionVertical)==0) {
				CursorX = rc->X + StringDetails[i].PosX;
				CursorY = rc->Y + StringDetails[i].PosY + LineHeight;

				gdip_cairo_move_to (graphics, CursorX, CursorY, FALSE, TRUE);
				cairo_show_text (graphics->ct, (const char *) String);
			} else {
				CursorY = rc->Y + StringDetails[i].PosX;
				CursorX = rc->X + StringDetails[i].PosY;

				/* Rotate text for vertical drawing */
				cairo_save (graphics->ct);
				gdip_cairo_move_to (graphics, CursorX, CursorY, FALSE, TRUE);
				cairo_rotate (graphics->ct, PI/2);
				cairo_show_text (graphics->ct, (const char *) String);
				cairo_restore (graphics->ct);
			}

#ifdef DRAWSTRING_DEBUG
			printf("Drawing %d chars at %d x %d (width=%f pixels)\n", StringDetails[i].LineLen, (int)CursorX, (int)CursorY, StringDetails[i+StringDetails[i].LineLen-1].PosX);
#endif
			GdipFree (String);

			if (font->style & (FontStyleUnderline | FontStyleStrikeout)) {
				double line_width = cairo_get_line_width (graphics->ct);

				/* Calculate the width of the line */
				cairo_set_line_width (graphics->ct, 1.0);
				j=StringDetails[i+StringDetails[i].LineLen-1].PosX+StringDetails[i+StringDetails[i].LineLen-1].Width;

				if (font->style & FontStyleStrikeout) {
					if ((fmt->formatFlags & StringFormatFlagsDirectionVertical)==0) {
						gdip_cairo_move_to (graphics, (int)(CursorX), (int)(CursorY-FontExtent.descent), FALSE, TRUE);
						gdip_cairo_line_to (graphics, (int)(CursorX+j), (int)(CursorY-FontExtent.descent), FALSE, TRUE);
					} else {
						gdip_cairo_move_to (graphics, (int)(CursorX+FontExtent.descent), (int)(CursorY), FALSE, TRUE);
						gdip_cairo_line_to (graphics, (int)(CursorX+FontExtent.descent), (int)(CursorY+j), FALSE, TRUE);
					}
				}

				if (font->style & FontStyleUnderline) {
					if ((fmt->formatFlags & StringFormatFlagsDirectionVertical)==0) {
						gdip_cairo_move_to (graphics, (int)(CursorX), (int)(CursorY+FontExtent.descent-2), FALSE, TRUE);
						gdip_cairo_line_to (graphics, (int)(CursorX+j), (int)(CursorY+FontExtent.descent-2), FALSE, TRUE);
					} else {
						gdip_cairo_move_to (graphics, (int)(CursorX+FontExtent.descent-2), (int)(CursorY), FALSE, TRUE);
						gdip_cairo_line_to (graphics, (int)(CursorX+FontExtent.descent-2), (int)(CursorY+j), FALSE, TRUE);
					}
				}

				cairo_stroke (graphics->ct);
				cairo_set_line_width (graphics->ct, line_width);
			}

			i+=StringDetails[i].LineLen-1;
		}
	}

	/* Handle Hotkey prefix */
	if (fmt->hotkeyPrefix==HotkeyPrefixShow && data->has_hotkeys) {
		GpStringDetailStruct *CurrentDetail = StringDetails;
		for (i=0; i<StringLen; i++) {
			if (CurrentDetail->Flags & STRING_DETAIL_HOTKEY) {
				if ((fmt->formatFlags & StringFormatFlagsDirectionVertical)==0) {
					CursorX = rc->X + StringDetails[i].PosX;
					CursorY = rc->Y + StringDetails[i].PosY + LineHeight;
				} else {
					CursorY = rc->Y + StringDetails[i].PosX;
					CursorX = rc->X + StringDetails[i].PosY;
				}

				if ((fmt->formatFlags & StringFormatFlagsDirectionVertical)==0) {
					cairo_set_line_width(graphics->ct, 1);
					gdip_cairo_move_to (graphics, (int)(CursorX), (int)(CursorY+FontExtent.descent), FALSE, TRUE);
					gdip_cairo_line_to (graphics, (int)(CursorX+CurrentDetail->Width), (int)(CursorY+FontExtent.descent), FALSE, TRUE);
					cairo_stroke (graphics->ct);
				} else {
					gdip_cairo_move_to (graphics, (int)(CursorX-FontExtent.descent), (int)(CursorY), FALSE, TRUE);
					gdip_cairo_line_to (graphics, (int)(CursorX-FontExtent.descent), (int)(CursorY+CurrentDetail->Width), FALSE, TRUE);
				}
			}
			CurrentDetail++;
		}
	}

	/* Restore the graphics clipping region */
	if (SetClipping)
		cairo_SetGraphicsClip (graphics);

	return Ok;
}