Exemple #1
0
 public PointF TransformPoint(Point p)
 {
                 #if __UNIFIED__
     return(control.TransformPoint(p.ToNS()).ToEto());
                 #else
     return(control.TransformPoint(p.ToSDPointF()).ToEto());
                 #endif
 }
        //
        // Helper function to generate shadow
        //
        private void GenerateShapeShadow(CGContext context, UIBezierPath shapeObject, nfloat xOffset, nfloat yOffset, nfloat blurValue, CGBlendMode blendingMode, UIColor shadowColor, nfloat borderWidth, int borderPosition, nfloat iWidth, nfloat iHeight)
        {
            CGPoint basePoint;
            CGPoint offsetPoint;
            CGSize  calculatedShadowOffset;
            nfloat  calculatedShadowBlur;
            CGPoint constPointZero;

            constPointZero = new CGPoint(0, 0);

            basePoint              = baseTransform.TransformPoint(context.PointToDeviceSpace(constPointZero));
            offsetPoint            = baseTransform.TransformPoint(context.PointToDeviceSpace(new CGPoint(xOffset, yOffset)));
            calculatedShadowOffset = new CGSize(offsetPoint.X - basePoint.X, offsetPoint.Y - basePoint.Y);
            if (blurValue == 0)
            {
                calculatedShadowBlur = 0;
            }
            else
            {
                calculatedShadowBlur = Hypot(calculatedShadowOffset.Width, calculatedShadowOffset.Height) / blurValue;
            }
            context.SetShadow(calculatedShadowOffset, calculatedShadowBlur, shadowColor.CGColor);
            context.SetBlendMode(blendingMode);

            context.BeginTransparencyLayer(null);

            UIColor.Black.SetFill();
            shapeObject.Fill();

            if (borderWidth > 0)
            {
                if (borderPosition == 0)
                {
                    context.SaveState();
                    shapeObject.LineWidth = borderWidth;
                    UIColor.Black.SetStroke();
                    shapeObject.Stroke();
                    context.RestoreState();
                }

                if (borderPosition == 1)
                {
                    context.BeginPath();
                    context.AddPath(shapeObject.CGPath);
                    context.EOClip();
                }

                if (borderPosition == 2)
                {
                    context.BeginPath();
                    context.AddPath(shapeObject.CGPath);
                    context.AddRect(RectangleFExtensions.Inset(shapeObject.Bounds, iWidth, iHeight));
                    context.EOClip();
                }
            }

            context.EndTransparencyLayer();
        }
Exemple #3
0
        public void TransformPoints(PointF[] pts)
        {
            if (pts == null)
            {
                throw new ArgumentNullException("pts");
            }

            for (int i = 0; i < pts.Length; i++)
            {
                pts [i] = transform.TransformPoint(pts [i].ToCGPoint()).ToPointF();
            }
        }
        public void TransformPoints(PointF[] pts)
        {
            if (pts == null)
            {
                throw new ArgumentNullException("pts");
            }

            for (int i = 0; i < pts.Length; i++)
            {
                var point = transform.TransformPoint(new CGPoint(pts [i].X, pts [i].Y));
                pts [i] = new PointF((float)point.X, (float)point.Y);
            }
        }
        public void TransformPoint()
        {
            var transform = new CGAffineTransform(1, 2, 3, 4, 5, 6);
            var point     = transform.TransformPoint(new CGPoint(4, 5));

            Assert.AreEqual((nfloat)24, point.X, "X");
            Assert.AreEqual((nfloat)34, point.Y, "Y");
        }
Exemple #6
0
        private static PointF RotateCGPointAroundCenter(PointF point, PointF center, float angle)
        {
            CGAffineTransform translation = CGAffineTransform.MakeTranslation(center.X, center.Y);
            CGAffineTransform rotation    = CGAffineTransform.MakeRotation(angle);

            var inverted = CGAffineTransform.CGAffineTransformInvert(translation);

            CGAffineTransform transformGroup = inverted * rotation * translation;

            return(transformGroup.TransformPoint(point));
        }
Exemple #7
0
        public void TransformPoint(object backend, ref double x, ref double y)
        {
            GetContext(backend);
            CGContext         gp = NSGraphicsContext.CurrentContext.GraphicsPort;
            CGAffineTransform t  = gp.GetCTM();

            PointF p = t.TransformPoint(new PointF((float)x, (float)y));

            x = p.X;
            y = p.Y;
        }
Exemple #8
0
        public void TransformPoints(object backend, Point[] points)
        {
            GetContext(backend);
            CGContext         gp = NSGraphicsContext.CurrentContext.GraphicsPort;
            CGAffineTransform t  = gp.GetCTM();

            PointF p;

            for (int i = 0; i < points.Length; ++i)
            {
                p           = t.TransformPoint(new PointF((float)points[i].X, (float)points[i].Y));
                points[i].X = p.X;
                points[i].Y = p.Y;
            }
        }
Exemple #9
0
        public void TransformDistance(object backend, ref double dx, ref double dy)
        {
            GetContext(backend);
            CGContext         gp = NSGraphicsContext.CurrentContext.GraphicsPort;
            CGAffineTransform t  = gp.GetCTM();

            // remove translational elements from CTM
            t.x0 = 0;
            t.y0 = 0;

            PointF p = t.TransformPoint(new PointF((float)dx, (float)dy));

            dx = p.X;
            dy = p.Y;
        }
Exemple #10
0
        public void TransformDistances(object backend, Distance[] vectors)
        {
            GetContext(backend);
            CGContext         gp = NSGraphicsContext.CurrentContext.GraphicsPort;
            CGAffineTransform t  = gp.GetCTM();

            t.x0 = 0;
            t.y0 = 0;
            PointF p;

            for (int i = 0; i < vectors.Length; ++i)
            {
                p             = t.TransformPoint(new PointF((float)vectors[i].Dx, (float)vectors[i].Dy));
                vectors[i].Dx = p.X;
                vectors[i].Dy = p.Y;
            }
        }
Exemple #11
0
 public PointF TransformPoint(Point p)
 {
     return(Platform.Conversions.ToEto(control.TransformPoint(p.ToSDPointF())));
 }
		public static CGPoint Apply (this CGPoint point, CGAffineTransform transform)
		{
			return transform.TransformPoint (point);
		}
Exemple #13
0
        public static PathData ToCGPath(this Geometry geometry)
        {
            PathData pathData = new PathData
            {
                Data = new CGPath()
            };

            CGAffineTransform transform = CGAffineTransform.MakeIdentity();

            if (geometry is LineGeometry)
            {
                LineGeometry lineGeometry = geometry as LineGeometry;
                pathData.Data.MoveToPoint(transform, lineGeometry.StartPoint.ToPointF());
                pathData.Data.AddLineToPoint(transform, lineGeometry.EndPoint.ToPointF());
            }
            else if (geometry is RectangleGeometry)
            {
                Rect rect = (geometry as RectangleGeometry).Rect;
                pathData.Data.AddRect(transform, new CGRect(rect.X, rect.Y, rect.Width, rect.Height));
            }
            else if (geometry is EllipseGeometry)
            {
                EllipseGeometry ellipseGeometry = geometry as EllipseGeometry;

                CGRect rect = new CGRect(
                    ellipseGeometry.Center.X - ellipseGeometry.RadiusX,
                    ellipseGeometry.Center.Y - ellipseGeometry.RadiusY,
                    ellipseGeometry.RadiusX * 2,
                    ellipseGeometry.RadiusY * 2);

                pathData.Data.AddEllipseInRect(transform, rect);
            }
            else if (geometry is GeometryGroup)
            {
                GeometryGroup geometryGroup = geometry as GeometryGroup;

                pathData.IsNonzeroFillRule = geometryGroup.FillRule == FillRule.Nonzero;

                foreach (Geometry child in geometryGroup.Children)
                {
                    PathData pathChild = child.ToCGPath();
                    pathData.Data.AddPath(pathChild.Data);
                }
            }
            else if (geometry is PathGeometry)
            {
                PathGeometry pathGeometry = geometry as PathGeometry;

                pathData.IsNonzeroFillRule = pathGeometry.FillRule == FillRule.Nonzero;

                foreach (PathFigure pathFigure in pathGeometry.Figures)
                {
                    pathData.Data.MoveToPoint(transform, pathFigure.StartPoint.ToPointF());
                    Point lastPoint = pathFigure.StartPoint;

                    foreach (PathSegment pathSegment in pathFigure.Segments)
                    {
                        // LineSegment
                        if (pathSegment is LineSegment)
                        {
                            LineSegment lineSegment = pathSegment as LineSegment;

                            pathData.Data.AddLineToPoint(transform, lineSegment.Point.ToPointF());
                            lastPoint = lineSegment.Point;
                        }
                        // PolyLineSegment
                        else if (pathSegment is PolyLineSegment)
                        {
                            PolyLineSegment polylineSegment = pathSegment as PolyLineSegment;
                            PointCollection points          = polylineSegment.Points;

                            for (int i = 0; i < points.Count; i++)
                            {
                                pathData.Data.AddLineToPoint(transform, points[i].ToPointF());
                            }

                            lastPoint = points[points.Count - 1];
                        }

                        // BezierSegment
                        if (pathSegment is BezierSegment)
                        {
                            BezierSegment bezierSegment = pathSegment as BezierSegment;

                            pathData.Data.AddCurveToPoint(
                                transform,
                                bezierSegment.Point1.ToPointF(),
                                bezierSegment.Point2.ToPointF(),
                                bezierSegment.Point3.ToPointF());

                            lastPoint = bezierSegment.Point3;
                        }
                        // PolyBezierSegment
                        else if (pathSegment is PolyBezierSegment)
                        {
                            PolyBezierSegment polyBezierSegment = pathSegment as PolyBezierSegment;
                            PointCollection   points            = polyBezierSegment.Points;

                            for (int i = 0; i < points.Count; i += 3)
                            {
                                pathData.Data.AddCurveToPoint(
                                    transform,
                                    points[i].ToPointF(),
                                    points[i + 1].ToPointF(),
                                    points[i + 2].ToPointF());
                            }
                            lastPoint = points[points.Count - 1];
                        }

                        // QuadraticBezierSegment
                        if (pathSegment is QuadraticBezierSegment)
                        {
                            QuadraticBezierSegment bezierSegment = pathSegment as QuadraticBezierSegment;

                            pathData.Data.AddQuadCurveToPoint(
                                transform,
                                new nfloat(bezierSegment.Point1.X),
                                new nfloat(bezierSegment.Point1.Y),
                                new nfloat(bezierSegment.Point2.X),
                                new nfloat(bezierSegment.Point2.Y));

                            lastPoint = bezierSegment.Point2;
                        }
                        // PolyQuadraticBezierSegment
                        else if (pathSegment is PolyQuadraticBezierSegment)
                        {
                            PolyQuadraticBezierSegment polyBezierSegment = pathSegment as PolyQuadraticBezierSegment;
                            PointCollection            points            = polyBezierSegment.Points;

                            for (int i = 0; i < points.Count; i += 2)
                            {
                                pathData.Data.AddQuadCurveToPoint(
                                    transform,
                                    new nfloat(points[i + 0].X),
                                    new nfloat(points[i + 0].Y),
                                    new nfloat(points[i + 1].X),
                                    new nfloat(points[i + 1].Y));
                            }

                            lastPoint = points[points.Count - 1];
                        }
                        // ArcSegment
                        else if (pathSegment is ArcSegment)
                        {
                            ArcSegment arcSegment = pathSegment as ArcSegment;

                            List <Point> points = new List <Point>();

                            GeometryHelper.FlattenArc(points,
                                                      lastPoint,
                                                      arcSegment.Point,
                                                      arcSegment.Size.Width,
                                                      arcSegment.Size.Height,
                                                      arcSegment.RotationAngle,
                                                      arcSegment.IsLargeArc,
                                                      arcSegment.SweepDirection == SweepDirection.CounterClockwise,
                                                      1);

                            CGPoint[] cgpoints = new CGPoint[points.Count];

                            for (int i = 0; i < points.Count; i++)
                            {
                                cgpoints[i] = transform.TransformPoint(points[i].ToPointF());
                            }

                            pathData.Data.AddLines(cgpoints);

                            lastPoint = points[points.Count - 1];
                        }
                    }

                    if (pathFigure.IsClosed)
                    {
                        pathData.Data.CloseSubpath();
                    }
                }
            }

            return(pathData);
        }
 public static CGPoint Apply(this CGPoint point, CGAffineTransform transform)
 {
     return(transform.TransformPoint(point));
 }
        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 = (int)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 = (int)typesetter.SuggestLineBreak(start, boundsWidth);
                    var line  = typesetter.GetLine(new NSRange(start, count));

                    // Create and initialize some values from the bounds.
                    nfloat ascent;
                    nfloat descent;
                    nfloat 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 = (int)typesetter.SuggestLineBreak(start, boundsWidth);
                var line  = typesetter.GetLine(new NSRange(start, count));

                // Create and initialize some values from the bounds.
                nfloat ascent;
                nfloat descent;
                nfloat leading;
                double lineWidth = line.GetTypographicBounds(out ascent, out descent, out leading);

                if (!layoutAvailable)
                {
                    insetBounds.Width  = (float)lineWidth;
                    insetBounds.Height = (float)(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).ToPointF();
                                elementPoints[1] = textMatrix.TransformPoint(pathElement.Point2).ToPointF();
                                elementPoints[2] = textMatrix.TransformPoint(pathElement.Point3).ToPointF();
                                //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();
            }
        }
        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 = (int)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 = (int)typesetter.SuggestLineBreak (start, boundsWidth);
                    var line = typesetter.GetLine (new NSRange(start, count));

                    // Create and initialize some values from the bounds.
                    nfloat ascent;
                    nfloat descent;
                    nfloat 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 = (int)typesetter.SuggestLineBreak(start, boundsWidth);
                var line = typesetter.GetLine(new NSRange(start, count));

                // Create and initialize some values from the bounds.
                nfloat ascent;
                nfloat descent;
                nfloat leading;
                double lineWidth = line.GetTypographicBounds(out ascent, out descent, out leading);

                if (!layoutAvailable)
                {
                    insetBounds.Width = (float)lineWidth;
                    insetBounds.Height = (float)(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).ToPointF ();
                                    elementPoints[1] = textMatrix.TransformPoint(pathElement.Point2).ToPointF ();
                                        elementPoints[2] = textMatrix.TransformPoint(pathElement.Point3).ToPointF ();
                                //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();

            }
        }
Exemple #17
0
        public object ConvertToNative(Geometry geometry)
        {
            // Create the CGPathPlus
            CGPathPlus cgPath = new CGPathPlus();   // TODO: Has a Dispose. What are the implications?

            // Obtain the native transform to apply to the geometry
            CGAffineTransform transform = new CGAffineTransform();

            if (geometry.Transform == null)
            {
                transform = CGAffineTransform.MakeIdentity();
            }
            else
            {
                transform = (CGAffineTransform)geometry.Transform.GetNativeObject();
            }


            // Determine what type of Geometry we're dealing with
            if (geometry is LineGeometry)
            {
                LineGeometry lineGeometry = geometry as LineGeometry;
                cgPath.MoveToPoint(transform, ConvertPoint(lineGeometry.StartPoint));
                cgPath.AddLineToPoint(transform, ConvertPoint(lineGeometry.EndPoint));
            }

            else if (geometry is RectangleGeometry)
            {
                Rect rect = (geometry as RectangleGeometry).Rect;
                cgPath.AddRect(transform, new CGRect(rect.X, rect.Y, rect.Width, rect.Height));
            }

            else if (geometry is EllipseGeometry)
            {
                EllipseGeometry ellipseGeometry = geometry as EllipseGeometry;

                CGRect rect = new CGRect(ellipseGeometry.Center.X - ellipseGeometry.RadiusX,
                                         ellipseGeometry.Center.Y - ellipseGeometry.RadiusY,
                                         ellipseGeometry.RadiusX * 2,
                                         ellipseGeometry.RadiusY * 2);

                cgPath.AddEllipseInRect(transform, rect);
            }

            else if (geometry is GeometryGroup)
            {
                GeometryGroup geometryGroup = geometry as GeometryGroup;

                cgPath.IsNonzeroFill = geometryGroup.FillRule == FillRule.Nonzero;      // make a little method?

                foreach (Geometry child in geometryGroup.Children)
                {
                    CGPath pathChild = ConvertToNative(child) as CGPath;
                    cgPath.AddPath(pathChild);          // Should there be a transform here as the first argument????
                }
            }

            else if (geometry is PathGeometry)
            {
                PathGeometry pathGeometry = geometry as PathGeometry;

                cgPath.IsNonzeroFill = pathGeometry.FillRule == FillRule.Nonzero;

                foreach (PathFigure pathFigure in pathGeometry.Figures)
                {
                    cgPath.MoveToPoint(transform, ConvertPoint(pathFigure.StartPoint));
                    Point lastPoint = pathFigure.StartPoint;

                    foreach (PathSegment pathSegment in pathFigure.Segments)
                    {
                        // LineSegment
                        if (pathSegment is LineSegment)
                        {
                            LineSegment lineSegment = pathSegment as LineSegment;

                            cgPath.AddLineToPoint(transform, ConvertPoint(lineSegment.Point));
                            lastPoint = lineSegment.Point;
                        }

                        // PolyLineSegment
                        else if (pathSegment is PolyLineSegment)
                        {
                            PolyLineSegment polylineSegment = pathSegment as PolyLineSegment;
                            PointCollection points          = polylineSegment.Points;

                            // TODO: Or AddLines

                            for (int i = 0; i < points.Count; i++)
                            {
                                cgPath.AddLineToPoint(transform, ConvertPoint(points[i]));
                            }
                            lastPoint = points[points.Count - 1];
                        }

                        // BezierSegment
                        if (pathSegment is BezierSegment)
                        {
                            BezierSegment bezierSegment = pathSegment as BezierSegment;

                            cgPath.AddCurveToPoint(transform,
                                                   ConvertPoint(bezierSegment.Point1),
                                                   ConvertPoint(bezierSegment.Point2),
                                                   ConvertPoint(bezierSegment.Point3));

                            lastPoint = bezierSegment.Point3;
                        }

                        // PolyBezierSegment
                        else if (pathSegment is PolyBezierSegment)
                        {
                            PolyBezierSegment polyBezierSegment = pathSegment as PolyBezierSegment;
                            PointCollection   points            = polyBezierSegment.Points;

                            for (int i = 0; i < points.Count; i += 3)
                            {
                                cgPath.AddCurveToPoint(transform,
                                                       ConvertPoint(points[i]),
                                                       ConvertPoint(points[i + 1]),
                                                       ConvertPoint(points[i + 2]));
                            }
                            lastPoint = points[points.Count - 1];
                        }

                        // QuadraticBezierSegment
                        if (pathSegment is QuadraticBezierSegment)
                        {
                            QuadraticBezierSegment bezierSegment = pathSegment as QuadraticBezierSegment;

                            cgPath.AddQuadCurveToPoint(transform,
                                                       new nfloat(bezierSegment.Point1.X),
                                                       new nfloat(bezierSegment.Point1.Y),
                                                       new nfloat(bezierSegment.Point2.X),
                                                       new nfloat(bezierSegment.Point2.Y));

                            lastPoint = bezierSegment.Point2;
                        }

                        // PolyQuadraticBezierSegment
                        else if (pathSegment is PolyQuadraticBezierSegment)
                        {
                            PolyQuadraticBezierSegment polyBezierSegment = pathSegment as PolyQuadraticBezierSegment;
                            PointCollection            points            = polyBezierSegment.Points;

                            for (int i = 0; i < points.Count; i += 2)
                            {
                                cgPath.AddQuadCurveToPoint(transform,
                                                           new nfloat(points[i + 0].X),
                                                           new nfloat(points[i + 0].Y),
                                                           new nfloat(points[i + 1].X),
                                                           new nfloat(points[i + 1].Y));
                            }
                            lastPoint = points[points.Count - 1];
                        }

                        // ArcSegment
                        else if (pathSegment is ArcSegment)
                        {
                            ArcSegment arcSegment = pathSegment as ArcSegment;

                            List <Point> points = new List <Point>();
                            Xamarin.Forms.Shapes.Shapes.FlattenArc(points,
                                                                   lastPoint,
                                                                   arcSegment.Point,
                                                                   arcSegment.Size.Width,
                                                                   arcSegment.Size.Height,
                                                                   arcSegment.RotationAngle,
                                                                   arcSegment.IsLargeArc,
                                                                   arcSegment.SweepDirection == SweepDirection.Counterclockwise,
                                                                   1);

                            CGPoint[] cgpoints = new CGPoint[points.Count];

                            for (int i = 0; i < points.Count; i++)
                            {
                                cgpoints[i] = transform.TransformPoint(ConvertPoint(points[i]));
                            }
                            cgPath.AddLines(cgpoints);

                            lastPoint = points[points.Count - 1];
                        }
                    }

                    if (pathFigure.IsClosed)
                    {
                        cgPath.CloseSubpath();
                    }
                }
            }

            return(cgPath);
        }
Exemple #18
0
 public PointF TransformPoint(Point p)
 {
     return(control.TransformPoint(p.ToNS()).ToEto());
 }