/// <summary> /// Initializes a new instance of the XRect class. /// </summary> public XRect(XPoint location, XSize size) { if (size.IsEmpty) { this = s_empty; } else { _x = location.X; _y = location.Y; _width = size.Width; _height = size.Height; } }
public void AddArc(XPoint point1, XPoint point2, XSize size, double rotationAngle, bool isLargeArg, XSweepDirection sweepDirection) { List <XPoint> points = GeometryHelper.BezierCurveFromArc(point1, point2, size, rotationAngle, isLargeArg, sweepDirection == XSweepDirection.Clockwise, PathStart.MoveTo1st); int count = points.Count; Debug.Assert((count + 2) % 3 == 0); MoveOrLineTo(points[0].X, points[0].Y); for (int idx = 1; idx < count; idx += 3) { BezierTo(points[idx].X, points[idx].Y, points[idx + 1].X, points[idx + 1].Y, points[idx + 2].X, points[idx + 2].Y, false); } }
/// <summary> /// Measure string directly from font data. /// </summary> public static XSize MeasureString(string text, XFont font, XStringFormat stringFormat) { XSize size = new XSize(); OpenTypeDescriptor descriptor = FontDescriptorCache.GetOrCreateDescriptorFor(font) as OpenTypeDescriptor; if (descriptor != null) { // Height is the sum of ascender and descender. size.Height = (descriptor.Ascender + descriptor.Descender) * font.Size / font.UnitsPerEm; Debug.Assert(descriptor.Ascender > 0); bool symbol = descriptor.FontFace.cmap.symbol; int length = text.Length; int width = 0; for (int idx = 0; idx < length; idx++) { char ch = text[idx]; // HACK: Unclear what to do here. if (ch < 32) { continue; } if (symbol) { // Remap ch for symbol fonts. ch = (char)(ch | (descriptor.FontFace.os2.usFirstCharIndex & 0xFF00)); // @@@ refactor // Used | instead of + because of: http://PdfSharpCore.codeplex.com/workitem/15954 } int glyphIndex = descriptor.CharCodeToGlyphIndex(ch); width += descriptor.GlyphIndexToWidth(glyphIndex); } // What? size.Width = width * font.Size * (font.Italic ? 1 : 1) / descriptor.UnitsPerEm; size.Width = width * font.Size / descriptor.UnitsPerEm; // Adjust bold simulation. if ((font.GlyphTypeface.StyleSimulations & XStyleSimulations.BoldSimulation) == XStyleSimulations.BoldSimulation) { // Add 2% of the em-size for each character. // Unsure how to deal with white space. Currently count as regular character. size.Width += length * font.Size * Const.BoldEmphasis; } } Debug.Assert(descriptor != null, "No OpenTypeDescriptor."); return(size); }
/// <summary> /// Initializes a new instance of the <see cref="XForm"/> class that represents a page of a PDF document. /// </summary> /// <param name="document">The PDF document.</param> /// <param name="size">The size of the page.</param> public XForm(PdfDocument document, XSize size) : this(document, new XRect(0, 0, size.Width, size.Height)) { ////if (size.width < 1 || size.height < 1) //// throw new ArgumentNullException("size", "The size of the XPdfForm is to small."); ////// I must tie the XPdfForm to a document immediately, because otherwise I would have no place where ////// to store the resources. ////if (document == null) //// throw new ArgumentNullException("document", "An XPdfForm template must be associated with a document."); ////_formState = FormState.Created; ////_document = document; ////pdfForm = new PdfFormXObject(document, this); ////templateSize = size; ////PdfRectangle rect = new PdfRectangle(new XPoint(), size); ////pdfForm.Elements.SetRectangle(PdfFormXObject.Keys.BBox, rect); }
/// <summary> /// Parses the size from a string. /// </summary> public static XSize Parse(string source) { XSize empty; CultureInfo cultureInfo = CultureInfo.InvariantCulture; TokenizerHelper helper = new TokenizerHelper(source, cultureInfo); string str = helper.NextTokenRequired(); if (str == "Empty") { empty = Empty; } else { empty = new XSize(Convert.ToDouble(str, cultureInfo), Convert.ToDouble(helper.NextTokenRequired(), cultureInfo)); } helper.LastTokenRequired(); return(empty); }
static XSize() { s_empty = CreateEmptySize(); }
/// <summary> /// Indicates whether this instance and a specified size are equal. /// </summary> public bool Equals(XSize value) { return(Equals(this, value)); }
/// <summary> /// Returns the rectangle that results from expanding the specified rectangle by the specified Size, in all directions. /// </summary> public static XRect Inflate(XRect rect, XSize size) { rect.Inflate(size.Width, size.Height); return(rect); }
/// <summary> /// Expands the rectangle by using the specified Size, in all directions. /// </summary> public void Inflate(XSize size) { Inflate(size.Width, size.Height); }
/// <summary> /// Adds an elliptical arc to the current figure. The arc is specified WPF like. /// </summary> public void AddArc(XPoint point1, XPoint point2, XSize size, double rotationAngle, bool isLargeArg, XSweepDirection sweepDirection) { _corePath.AddArc(point1, point2, size, rotationAngle, isLargeArg, sweepDirection); }
/// <summary> /// Creates between 1 and 5 Béziers curves from parameters specified like in WPF. /// </summary> public static List <XPoint> BezierCurveFromArc(XPoint point1, XPoint point2, XSize size, double rotationAngle, bool isLargeArc, bool clockwise, PathStart pathStart) { // See also http://www.charlespetzold.com/blog/blog.xml from January 2, 2008: // http://www.charlespetzold.com/blog/2008/01/Mathematics-of-ArcSegment.html double δx = size.Width; double δy = size.Height; Debug.Assert(δx * δy > 0); double factor = δy / δx; bool isCounterclockwise = !clockwise; // Adjust for different radii and rotation angle. XMatrix matrix = new XMatrix(); matrix.RotateAppend(-rotationAngle); matrix.ScaleAppend(δy / δx, 1); XPoint pt1 = matrix.Transform(point1); XPoint pt2 = matrix.Transform(point2); // Get info about chord that connects both points. XPoint midPoint = new XPoint((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2); XVector vect = pt2 - pt1; double halfChord = vect.Length / 2; // Get vector from chord to center. XVector vectRotated; // (comparing two Booleans here!) if (isLargeArc == isCounterclockwise) { vectRotated = new XVector(-vect.Y, vect.X); } else { vectRotated = new XVector(vect.Y, -vect.X); } vectRotated.Normalize(); // Distance from chord to center. double centerDistance = Math.Sqrt(δy * δy - halfChord * halfChord); if (double.IsNaN(centerDistance)) { centerDistance = 0; } // Calculate center point. XPoint center = midPoint + centerDistance * vectRotated; // Get angles from center to the two points. double α = Math.Atan2(pt1.Y - center.Y, pt1.X - center.X); double β = Math.Atan2(pt2.Y - center.Y, pt2.X - center.X); // (another comparison of two Booleans!) if (isLargeArc == (Math.Abs(β - α) < Math.PI)) { if (α < β) { α += 2 * Math.PI; } else { β += 2 * Math.PI; } } // Invert matrix for final point calculation. matrix.Invert(); double sweepAngle = β - α; // Let the algorithm of GDI+ DrawArc to Bézier curves do the rest of the job return(BezierCurveFromArc(center.X - δx * factor, center.Y - δy, 2 * δx * factor, 2 * δy, α / Calc.Deg2Rad, sweepAngle / Calc.Deg2Rad, pathStart, ref matrix)); }