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; }
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 = ▭ 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; }