private void DrawStringOnCurrPath(string value, IFontDefn font, PointF location, float fontBaselineHeight, float rotation) { var drawPath = _currPath; if (rotation != 0.0f) { drawPath = new GraphicsPath(); } font.AddStringToPath(this.Renderer, drawPath, value, new PointF(location.X, location.Y - fontBaselineHeight)); if (rotation != 0.0f && drawPath.PointCount > 0) { using (var matrix = new Matrix()) { matrix.Translate(-1 * location.X, -1 * location.Y, MatrixOrder.Append); matrix.Rotate(rotation, MatrixOrder.Append); matrix.Translate(location.X, location.Y, MatrixOrder.Append); drawPath.Transform(matrix); _currPath.AddPath(drawPath, false); } } }
/// <summary> /// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="SvgRenderer"/> /// </summary> /// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param> protected internal override void RenderStroke(SvgRenderer renderer) { if (this.Stroke != null) { float strokeWidth = this.StrokeWidth.ToDeviceValue(this); using (var pen = new Pen(this.Stroke.GetBrush(this, this.StrokeOpacity), strokeWidth)) { if (this.StrokeDashArray != null && this.StrokeDashArray.Count > 0) { /* divide by stroke width - GDI behaviour that I don't quite understand yet.*/ pen.DashPattern = this.StrokeDashArray.ConvertAll(u => u.Value / ((strokeWidth <= 0) ? 1 : strokeWidth)).ToArray(); } //hardcoded transformation matrix. I am not sure why this is not in proportion or rotated correctly (something to do with how the endcaps are determined in GDI) var transMatrix = new Matrix(); transMatrix.Rotate(-90f); transMatrix.Scale(.6f, .6f); if (this.MarkerStart != null) { var marker = this.OwnerDocument.GetElementById <SvgMarker>(this.MarkerStart.ToString()); var markerPath = marker.Path.Clone() as GraphicsPath; markerPath.Transform(transMatrix); pen.CustomStartCap = new CustomLineCap(markerPath, null); } if (this.MarkerEnd != null) { var marker = this.OwnerDocument.GetElementById <SvgMarker>(this.MarkerEnd.ToString()); var markerPath = marker.Path.Clone() as GraphicsPath; markerPath.Transform(transMatrix); pen.CustomEndCap = new CustomLineCap(markerPath, null); } renderer.DrawPath(pen, this.Path); } } }
/// <summary> /// Common code for rendering a marker once the orientation angle has been calculated /// </summary> /// <param name="fAngle"></param> /// <param name="pRenderer"></param> /// <param name="pOwner"></param> /// <param name="pMarkerPoint"></param> private void RenderPart2(float fAngle, ISvgRenderer pRenderer, SvgVisualElement pOwner, PointF pMarkerPoint) { using (var pRenderPen = CreatePen(pOwner, pRenderer)) { using (var markerPath = GetClone(pOwner, pRenderer)) { using (var transMatrix = new Matrix()) { transMatrix.Translate(pMarkerPoint.X, pMarkerPoint.Y); if (Orient.IsAuto) { transMatrix.Rotate(fAngle); } else { transMatrix.Rotate(Orient.Angle); } switch (MarkerUnits) { case SvgMarkerUnits.StrokeWidth: if (ViewBox.Width > 0 && ViewBox.Height > 0) { transMatrix.Scale(MarkerWidth, MarkerHeight); var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(pRenderer, UnitRenderingType.Other, this); transMatrix.Translate(AdjustForViewBoxWidth(-RefX.ToDeviceValue(pRenderer, UnitRenderingType.Horizontal, this) * strokeWidth), AdjustForViewBoxHeight(-RefY.ToDeviceValue(pRenderer, UnitRenderingType.Vertical, this) * strokeWidth)); } else { // SvgMarkerUnits.UserSpaceOnUse // TODO: We know this isn't correct. // But use this until the TODOs from AdjustForViewBoxWidth and AdjustForViewBoxHeight are done. // MORE see Unit Test "MakerEndTest.TestArrowCodeCreation()" transMatrix.Translate(-RefX.ToDeviceValue(pRenderer, UnitRenderingType.Horizontal, this), -RefY.ToDeviceValue(pRenderer, UnitRenderingType.Vertical, this)); } break; case SvgMarkerUnits.UserSpaceOnUse: transMatrix.Translate(-RefX.ToDeviceValue(pRenderer, UnitRenderingType.Horizontal, this), -RefY.ToDeviceValue(pRenderer, UnitRenderingType.Vertical, this)); break; } if (MarkerElement != null && MarkerElement.Transforms != null) { using (var matrix = MarkerElement.Transforms.GetMatrix()) transMatrix.Multiply(matrix); } markerPath.Transform(transMatrix); if (pRenderPen != null) { pRenderer.DrawPath(pRenderPen, markerPath); } SvgPaintServer pFill = this.Children.First().Fill; SvgFillRule pFillRule = FillRule; // TODO: What do we use the fill rule for? if (pFill != null) { using (var pBrush = pFill.GetBrush(this, pRenderer, FixOpacityValue(FillOpacity))) { pRenderer.FillPath(pBrush, markerPath); } } } } } }
public void RotateTransform(float fAngle, MatrixOrder order = MatrixOrder.Append) { _innerMatrix.Rotate(fAngle, order); }