public void RotateAt (float angle, float centerX, float centerY) { angle = Conversions.DegreesToRadians (angle); var sina = (float)Math.Sin (angle); var cosa = (float)Math.Cos (angle); var matrix = new CGAffineTransform(cosa, sina, -sina, cosa, centerX - centerX * cosa + centerY * sina, centerY - centerX * sina - centerY * cosa); control = CGAffineTransform.Multiply (matrix, control); }
// // Operations // public static CGAffineTransform Multiply (CGAffineTransform a, CGAffineTransform b) { return new CGAffineTransform (a.xx * b.xx + a.yx * b.xy, a.xx * b.yx + a.yx * b.yy, a.xy * b.xx + a.yy * b.xy, a.xy * b.yx + a.yy * b.yy, a.x0 * b.xx + a.y0 * b.xy + b.x0, a.x0 * b.yx + a.y0 * b.yy + b.y0); }
public CGPattern (RectangleF bounds, CGAffineTransform matrix, float xStep, float yStep, CGPatternTiling tiling, bool isColored, DrawPattern drawPattern) { if (drawPattern == null) throw new ArgumentNullException ("drawPattern"); callbacks.draw = DrawCallback; callbacks.release = ReleaseCallback; callbacks.version = 0; this.draw_pattern = drawPattern; gch = GCHandle.Alloc (this); handle = CGPatternCreate (GCHandle.ToIntPtr (gch) , bounds, matrix, xStep, yStep, tiling, isColored, ref callbacks); }
public Matrix(Rectangle rect, Point[] plgpts) { if (plgpts == null) throw new ArgumentNullException ("plgpts"); if (plgpts.Length != 3) throw new ArgumentException ("plgpts"); Point p0 = plgpts [0]; Point p1 = plgpts [1]; Point p2 = plgpts [2]; float m11 = (p1.X - p0.X) / (float)rect.Width; float m12 = (p1.Y - p0.Y) / (float)rect.Width; float m21 = (p2.X - p0.X) / (float)rect.Height; float m22 = (p2.X - p0.X) / (float)rect.Height; transform = new CGAffineTransform (m11, m12, m21, m22, p0.X, p0.Y); transform.Translate (rect.Width, rect.Height); }
public void Apply(GraphicsHandler graphics) { graphics.SetFillColorSpace(); #if OSX if (graphics.DisplayView != null) { // adjust for position of the current view relative to the window var pos = graphics.DisplayView.ConvertPointToView(sd.PointF.Empty, null); graphics.Control.SetPatternPhase(new sd.SizeF(pos.X, pos.Y)); } #endif // make current transform apply to the pattern var currentTransform = graphics.CurrentTransform; if (pattern == null || viewTransform != currentTransform) { viewTransform = currentTransform; SetPattern(); } graphics.Control.SetFillPattern(pattern, alpha); }
public void AddCurveToPoint(CGAffineTransform transform, float cp1x, float cp1y, float cp2x, float cp2y, float x, float y) { CGPathAddCurveToPoint(handle, ref transform, cp1x, cp1y, cp2x, cp2y, x, y); }
public void AddRects(CGAffineTransform m, RectangleF [] rects) { CGPathAddRects(handle, ref m, rects, rects.Length); }
extern static bool CGPathContainsPoint(IntPtr path, ref CGAffineTransform m, PointF point, bool eoFill);
extern static void CGPathAddCurveToPoint(IntPtr path, ref CGAffineTransform m, float cp1x, float cp1y, float cp2x, float cp2y, float x, float y);
extern static void CGPathAddEllipseInRect(IntPtr path, ref CGAffineTransform m, RectangleF rect);
extern static void CGPathAddArcToPoint(IntPtr path, ref CGAffineTransform m, float x1, float y1, float x2, float y2, float radius);
public void AddArc(CGAffineTransform m, float x, float y, float radius, float startAngle, float endAngle, bool clockwise) { CGPathAddArc(handle, ref m, x, y, radius, startAngle, endAngle, clockwise); }
public void AddRects (CGAffineTransform m, RectangleF [] rects, int count) { if (count > rects.Length) throw new ArgumentException ("counts"); CGPathAddRects (handle, ref m, rects, count); }
public void AddElipseInRect(CGAffineTransform m, RectangleF rect) { CGPathAddEllipseInRect(handle, ref m, rect); }
extern static void CGPathAddArc(IntPtr path, ref CGAffineTransform m, float x, float y, float radius, float startAngle, float endAngle, bool clockwise);
public void AddLines(CGAffineTransform m, PointF [] points) { CGPathAddLines(handle, ref m, points, points.Length); }
extern static void CGPathAddLines(IntPtr path, ref CGAffineTransform m, PointF [] points, int size_t_count);
public void AddCurveToPoint (CGAffineTransform transform, float cp1x, float cp1y, float cp2x, float cp2y, float x, float y) { CGPathAddCurveToPoint (handle, ref transform, cp1x, cp1y, cp2x, cp2y, x, y); }
extern static void CGPathAddRects(IntPtr path, ref CGAffineTransform m, RectangleF [] rects, int size_t_count);
public void AddArcToPoint(CGAffineTransform m, float x1, float y1, float x2, float y2, float radius) { CGPathAddArcToPoint(handle, ref m, x1, y1, x2, y2, radius); }
public void AddLines (CGAffineTransform m, PointF [] points) { CGPathAddLines (handle, ref m, points, points.Length); }
extern static void CGPathAddRelativeArc(IntPtr path, ref CGAffineTransform m, float x, float y, float radius, float startAngle, float delta);
public void AddRelativeArc(CGAffineTransform m, float x, float y, float radius, float startAngle, float delta) { CGPathAddRelativeArc(handle, ref m, x, y, radius, startAngle, delta); }
extern static void CGPathAddPath(IntPtr path1, ref CGAffineTransform m, IntPtr path2);
public void AddRect(CGAffineTransform transform, RectangleF rect) { CGPathAddRect(handle, ref transform, rect); }
public void DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format = null) { if (font == null) throw new ArgumentNullException ("font"); if (brush == null) throw new ArgumentNullException ("brush"); if (s == null || s.Length == 0) return; if (format == null) { format = StringFormat.GenericDefault; } // TODO: Take into consideration units // Not sure we need the Save and Restore around this yet. context.SaveState(); // TextMatrix is not part of the Graphics State and Restore var saveMatrix = context.TextMatrix; bool layoutAvailable = true; // context.SelectFont ( font.nativeFont.PostScriptName, // font.SizeInPoints, // CGTextEncoding.MacRoman); // // context.SetCharacterSpacing(1); // context.SetTextDrawingMode(CGTextDrawingMode.Fill); // 5 // // // Setup both the stroke and the fill ? // brush.Setup(this, true); // brush.Setup(this, false); // // var textMatrix = font.nativeFont.Matrix; // // textMatrix.Scale(1,-1); // context.TextMatrix = textMatrix; // // context.ShowTextAtPoint(layoutRectangle.X, // layoutRectangle.Y + font.nativeFont.CapHeightMetric, s); // // // First we call the brush with a fill of false so the brush can setup the stroke color // that the text will be using. // For LinearGradientBrush this will setup a TransparentLayer so the gradient can // be filled at the end. See comments. brush.Setup(this, false); // Stroke // I think we only Fill the text with no Stroke surrounding context.SetTextDrawingMode(CGTextDrawingMode.Fill); var attributedString = buildAttributedString(s, font, format, lastBrushColor); // Work out the geometry RectangleF insetBounds = layoutRectangle; if (insetBounds.Size == SizeF.Empty) { insetBounds.Width = boundingBox.Width; insetBounds.Height = boundingBox.Height; layoutAvailable = false; } PointF textPosition = new PointF(insetBounds.X, insetBounds.Y); float boundsWidth = insetBounds.Width; // Calculate the lines int start = 0; int length = attributedString.Length; float baselineOffset = 0; var typesetter = new CTTypesetter(attributedString); // First we need to calculate the offset for Vertical Alignment if we // are using anything but Top if (layoutAvailable && format.LineAlignment != StringAlignment.Near) { while (start < length) { int count = typesetter.SuggestLineBreak (start, boundsWidth); var line = typesetter.GetLine (new NSRange(start, count)); // Create and initialize some values from the bounds. float ascent; float descent; float leading; line.GetTypographicBounds (out ascent, out descent, out leading); baselineOffset += (float)Math.Ceiling (ascent + descent + leading + 1); // +1 matches best to CTFramesetter's behavior line.Dispose (); start += count; } //textPosition.Y += baselineOffset; } // If we are drawing vertial direction then we need to rotate our context transform by 90 degrees if ((format.FormatFlags & StringFormatFlags.DirectionVertical) == StringFormatFlags.DirectionVertical) { //textMatrix.Rotate (ConversionHelpers.DegreesToRadians (90)); var verticalOffset = 0.0f; while (start < length) { int count = typesetter.SuggestLineBreak (start, boundsWidth); var line = typesetter.GetLine (new NSRange(start, count)); // Create and initialize some values from the bounds. float ascent; float descent; float leading; line.GetTypographicBounds (out ascent, out descent, out leading); verticalOffset += (float)Math.Ceiling (ascent + descent + leading + 1); // +1 matches best to CTFramesetter's behavior line.Dispose (); start += count; } context.TranslateCTM (layoutRectangle.X, layoutRectangle.Y); context.RotateCTM (ConversionHelpers.DegreesToRadians (90)); context.TranslateCTM (-layoutRectangle.X, -layoutRectangle.Y); context.TranslateCTM (0, -verticalOffset); start = 0; } start = 0; while (start < length && textPosition.Y < insetBounds.Bottom) { // Now we ask the typesetter to break off a line for us. // This also will take into account line feeds embedded in the text. // Example: "This is text \n with a line feed embedded inside it" int count = typesetter.SuggestLineBreak(start, boundsWidth); var line = typesetter.GetLine(new NSRange(start, count)); // Create and initialize some values from the bounds. float ascent; float descent; float leading; double lineWidth = line.GetTypographicBounds(out ascent, out descent, out leading); // Calculate the string format if need be var penFlushness = 0.0f; if (format != null) { if (layoutAvailable) { if (format.Alignment == StringAlignment.Far) penFlushness = (float)line.GetPenOffsetForFlush(1.0f, boundsWidth); else if (format.Alignment == StringAlignment.Center) penFlushness = (float)line.GetPenOffsetForFlush(0.5f, boundsWidth); } else { // We were only passed in a point so we need to format based // on the point. if (format.Alignment == StringAlignment.Far) penFlushness -= (float)lineWidth; else if (format.Alignment == StringAlignment.Center) penFlushness -= (float)lineWidth / 2.0f; } } // initialize our Text Matrix or we could get trash in here var textMatrix = new CGAffineTransform ( 1, 0, 0, -1, 0, ascent); if (format.LineAlignment == StringAlignment.Near) textMatrix.Translate (penFlushness + textPosition.X, textPosition.Y); if (format.LineAlignment == StringAlignment.Center) textMatrix.Translate (penFlushness + textPosition.X, textPosition.Y + ((insetBounds.Height / 2) - (baselineOffset / 2)) ); if (format.LineAlignment == StringAlignment.Far) textMatrix.Translate(penFlushness + textPosition.X, textPosition.Y + ((insetBounds.Height) - (baselineOffset))); context.TextMatrix = textMatrix; // and draw the line line.Draw(context); // Move the index beyond the line break. start += count; textPosition.Y += (float)Math.Ceiling(ascent + descent + leading + 1); // +1 matches best to CTFramesetter's behavior line.Dispose(); } // Now we call the brush with a fill of true so the brush can do the fill if need be // For LinearGradientBrush this will draw the Gradient and end the TransparentLayer. // See comments. brush.Setup(this, true); // Fill context.TextMatrix = saveMatrix; context.RestoreState(); }
//bool _highQuality = false; static CoreGraphicsGraphics() { //foreach (var f in UIFont.FamilyNames) { // Console.WriteLine (f); // var fs = UIFont.FontNamesForFamilyName (f); // foreach (var ff in fs) { // Console.WriteLine (" " + ff); // } //} _textMatrix = CGAffineTransform.MakeScale (1, -1); }
public void AddCurveToPoint(CGAffineTransform transform, PointF cp1, PointF cp2, PointF point) { CGPathAddCurveToPoint(handle, ref transform, cp1.X, cp1.Y, cp2.X, cp2.Y, point.X, point.Y); }
public void CGPathAddLineToPoint (CGAffineTransform transform, float x, float y) { CGPathAddLineToPoint (handle, ref transform, x, y); }
extern static void CGContextSetTextMatrix(IntPtr c, CGAffineTransform t);
extern static void CGPathAddLineToPoint(IntPtr path, ref CGAffineTransform m, float x, float y);
public bool ContainsPoint(CGAffineTransform m, PointF point, bool eoFill) { return(CGPathContainsPoint(handle, ref m, point, eoFill)); }
extern static IntPtr CGPathCreateCopyByDashingPath(IntPtr handle, ref CGAffineTransform transform, float [] phase, int count);
public void AddRect (CGAffineTransform transform, RectangleF rect) { CGPathAddRect (handle, ref transform, rect); }
public CGPath CopyByDashingPath(CGAffineTransform transform, float [] phase) { return(MakeMutable(CGPathCreateCopyByDashingPath(handle, ref transform, phase, phase == null ? 0 : phase.Length))); }
public void AddRects (CGAffineTransform m, RectangleF [] rects) { CGPathAddRects (handle, ref m, rects, rects.Length); }
extern static IntPtr CGPathCreateCopyByStrokingPath(IntPtr handle, ref CGAffineTransform transform, float lineWidth, CGLineCap lineCap, CGLineJoin lineJoin, float miterLimit);
public CGPath CopyByStrokingPath(CGAffineTransform transform, float lineWidth, CGLineCap lineCap, CGLineJoin lineJoin, float miterLimit) { return(MakeMutable(CGPathCreateCopyByStrokingPath(handle, ref transform, lineWidth, lineCap, lineJoin, miterLimit))); }
public void AddRects (CGAffineTransform m, PointF [] points, int count) { if (count > points.Length) throw new ArgumentException ("count"); CGPathAddLines (handle, ref m, points, count); }
extern static IntPtr CGPathCreateMutableCopyByTransformingPath(IntPtr handle, ref CGAffineTransform transform);
public void AddElipseInRect (CGAffineTransform m, RectangleF rect) { CGPathAddEllipseInRect (handle, ref m, rect); }
static public CGPath EllipseFromRect(RectangleF boundingRect, CGAffineTransform transform) { return(MakeMutable(CGPathCreateWithEllipse(boundingRect, ref transform))); }
public void AddArc (CGAffineTransform m, float x, float y, float radius, float startAngle, float endAngle, bool clockwise) { CGPathAddArc (handle, ref m, x, y, radius, startAngle, endAngle, clockwise); }
extern static IntPtr CGPathCreateWithRect(RectangleF boundingRect, ref CGAffineTransform transform);
public void AddArcToPoint (CGAffineTransform m, float x1, float y1, float x2, float y2, float radius) { CGPathAddArcToPoint (handle, ref m, x1, y1, x2, y2, radius); }
static public CGPath FromRect(RectangleF rectangle, CGAffineTransform transform) { return(MakeMutable(CGPathCreateWithRect(rectangle, ref transform))); }
public void AddPath (CGAffineTransform t, CGPath path2) { if (path2 == null) throw new ArgumentNullException ("path2"); CGPathAddPath (handle, ref t, path2.handle); }
static extern IntPtr CTFontCreateWithGraphicsFont(IntPtr graphicsFont, float size, ref CGAffineTransform matrix, IntPtr attributes);
public bool ContainsPoint (CGAffineTransform m, PointF point, bool eoFill) { return CGPathContainsPoint (handle, ref m, point, eoFill); }
public CTFont ToCTFont(float size, ref CGAffineTransform matrix) { return(new CTFont(CTFontCreateWithGraphicsFont(handle, size, ref matrix, IntPtr.Zero), true)); }
internal void NativeDrawString(string s, Font font, Color brush, RectangleF layoutRectangle, StringFormat stringFormat) { if (font == null) throw new ArgumentNullException ("font"); if (s == null || s.Length == 0) return; var attributedString = buildAttributedString(s, font, brush); // Work out the geometry RectangleF insetBounds = layoutRectangle; bool layoutAvailable = true; if (insetBounds.Size == SizeF.Empty) { insetBounds.Size = new SizeF (8388608, 8388608); layoutAvailable = false; } PointF textPosition = new PointF(insetBounds.X, insetBounds.Y); float boundsWidth = insetBounds.Width; // Calculate the lines int start = 0; int length = attributedString.Length; var typesetter = new CTTypesetter(attributedString); float baselineOffset = 0; // First we need to calculate the offset for Vertical Alignment if we // are using anything but Top if (layoutAvailable && stringFormat.LineAlignment != StringAlignment.Near) { while (start < length) { int count = typesetter.SuggestLineBreak (start, boundsWidth); var line = typesetter.GetLine (new NSRange(start, count)); // Create and initialize some values from the bounds. float ascent; float descent; float leading; line.GetTypographicBounds (out ascent, out descent, out leading); baselineOffset += (float)Math.Ceiling (ascent + descent + leading + 1); // +1 matches best to CTFramesetter's behavior line.Dispose (); start += count; } } start = 0; while (start < length && textPosition.Y < insetBounds.Bottom) { // Now we ask the typesetter to break off a line for us. // This also will take into account line feeds embedded in the text. // Example: "This is text \n with a line feed embedded inside it" int count = typesetter.SuggestLineBreak(start, boundsWidth); var line = typesetter.GetLine(new NSRange(start, count)); // Create and initialize some values from the bounds. float ascent; float descent; float leading; double lineWidth = line.GetTypographicBounds(out ascent, out descent, out leading); if (!layoutAvailable) { insetBounds.Width = (float)lineWidth; insetBounds.Height = ascent + descent + leading; } // Calculate the string format if need be var penFlushness = 0.0f; if (stringFormat.Alignment == StringAlignment.Far) penFlushness = (float)line.GetPenOffsetForFlush(1.0f, insetBounds.Width); else if (stringFormat.Alignment == StringAlignment.Center) penFlushness = (float)line.GetPenOffsetForFlush(0.5f, insetBounds.Width); // initialize our Text Matrix or we could get trash in here var textMatrix = new CGAffineTransform ( 1, 0, 0, -1, 0, ascent); if (stringFormat.LineAlignment == StringAlignment.Near) textMatrix.Translate (penFlushness + textPosition.X, textPosition.Y); //insetBounds.Height - textPosition.Y -(float)Math.Floor(ascent - 1)); if (stringFormat.LineAlignment == StringAlignment.Center) textMatrix.Translate (penFlushness + textPosition.X, textPosition.Y + ((insetBounds.Height / 2) - (baselineOffset / 2)) ); // -(float)Math.Floor(ascent) if (stringFormat.LineAlignment == StringAlignment.Far) textMatrix.Translate(penFlushness + textPosition.X, textPosition.Y + ((insetBounds.Height) - (baselineOffset))); var glyphRuns = line.GetGlyphRuns (); for (int glyphRunIndex = 0; glyphRunIndex < glyphRuns.Length; glyphRunIndex++) { var glyphRun = glyphRuns [glyphRunIndex]; var glyphs = glyphRun.GetGlyphs (); var glyphPositions = glyphRun.GetPositions (); //var textMatrix = glyphRun.TextMatrix; // Create and initialize some values from the bounds. float glyphAscent; float glyphDescent; float glyphLeading; var elementPoints = new PointF[3]; for (int glyphIndex = 0; glyphIndex < glyphs.Length; glyphIndex++) { if (glyphIndex > 0) { textMatrix.x0 += glyphPositions [glyphIndex].X - glyphPositions[glyphIndex - 1].X; textMatrix.y0 += glyphPositions [glyphIndex].Y - glyphPositions[glyphIndex - 1].Y; } var glyphPath = font.nativeFont.GetPathForGlyph (glyphs [glyphIndex]); // glyphPath = null if it is a white space character if (glyphPath != null) { glyphPath.Apply ( delegate (CGPathElement pathElement) { elementPoints[0] = textMatrix.TransformPoint(pathElement.Point1); elementPoints[1] = textMatrix.TransformPoint(pathElement.Point2); elementPoints[2] = textMatrix.TransformPoint(pathElement.Point3); //Console.WriteLine ("Applying {0} - {1}, {2}, {3}", pathElement.Type, elementPoints[0], elementPoints[1], elementPoints[2]); // now add position offsets switch(pathElement.Type) { case CGPathElementType.MoveToPoint: start_new_fig = true; Append(elementPoints[0].X, elementPoints[0].Y,PathPointType.Line,true); break; case CGPathElementType.AddLineToPoint: var lastPoint = points[points.Count - 1]; AppendPoint(lastPoint, PathPointType.Line, false); AppendPoint(elementPoints[0], PathPointType.Line, false); break; case CGPathElementType.AddCurveToPoint: case CGPathElementType.AddQuadCurveToPoint: // This is the only thing I can think of right now for the fonts that // I have tested. See the description of the quadraticToCubic method for // more information // Get the last point var pt1 = points[points.Count - 1]; var pt2 = PointF.Empty; var pt3 = PointF.Empty; var pt4 = elementPoints[1]; GeomUtilities.QuadraticToCubic(pt1, elementPoints[0], elementPoints[1], out pt2, out pt3); Append (pt1.X, pt1.Y, PathPointType.Line, true); AppendBezier (pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X, pt4.Y); break; case CGPathElementType.CloseSubpath: CloseFigure(); break; } } ); } } } // Move the index beyond the line break. start += count; textPosition.Y += (float)Math.Ceiling(ascent + descent + leading + 1); // +1 matches best to CTFramesetter's behavior line.Dispose(); } }
public void AddLineToPoint(CGAffineTransform transform, PointF point) { CGPathAddLineToPoint(handle, ref transform, point.X, point.Y); }