void CreateNativeFont(FontFamily familyName, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont)
        {
            sizeInPoints = ConversionHelpers.GraphicsUnitConversion(unit, GraphicsUnit.Point, 96f, emSize);
            bold         = FontStyle.Bold == (style & FontStyle.Bold);
            italic       = FontStyle.Italic == (style & FontStyle.Italic);
            underLine    = FontStyle.Underline == (style & FontStyle.Underline);
            this.size    = emSize;
            this.unit    = unit;

            var size = sizeInPoints * 96f / 72f;
            UIFontDescriptorSymbolicTraits traits = 0;

            if (bold)
            {
                traits |= UIFontDescriptorSymbolicTraits.Bold;
            }
            if (italic)
            {
                traits |= UIFontDescriptorSymbolicTraits.Italic;
            }

            UIFont font = null;

            if (NSThread.Current.IsMainThread)
            {
                font = MakeFont(familyName.Name, size, traits);
            }
            else
            {
                NSThread.MainThread.InvokeOnMainThread(() => { font = MakeFont(familyName.Name, size, traits); });
            }

            nativeFont = font.ToCTFont();
        }
        void CreateNativeFont(FontFamily familyName, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont)
        {
            this.sizeInPoints = ConversionHelpers.GraphicsUnitConversion(unit, GraphicsUnit.Point, 96f, emSize);
            this.bold         = FontStyle.Bold == (style & FontStyle.Bold);
            this.italic       = FontStyle.Italic == (style & FontStyle.Italic);
            this.underLine    = FontStyle.Underline == (style & FontStyle.Underline);
            this.size         = emSize;
            this.unit         = unit;

            var size   = sizeInPoints * 96f / 72f;
            var traits = (NSFontTraitMask)0;

            if (bold)
            {
                traits |= NSFontTraitMask.Bold;
            }
            if (italic)
            {
                traits |= NSFontTraitMask.Italic;
            }

            var f = NSFontWithFamily(familyName.Name, traits, RegularWeight, size) ?? NSSystemFont(RegularWeight, size);

            this.nativeFont = f.ToCTFont();
        }
        /// <summary>
        /// Draws the specified image, using its original physical size, at the location specified by a coordinate pair.
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="x">The x coordinate.</param>
        /// <param name="y">The y coordinate.</param>
        public void DrawImage(Image image, float x, float y)
        {
            var width  = image.physicalSize.Width;
            var height = image.physicalSize.Height;

            if (graphicsUnit != GraphicsUnit.Pixel)
            {
                width  = ConversionHelpers.GraphicsUnitConversion(GraphicsUnit.Pixel, graphicsUnit, image.HorizontalResolution, width);
                height = ConversionHelpers.GraphicsUnitConversion(GraphicsUnit.Pixel, graphicsUnit, image.VerticalResolution, height);
            }
            DrawImage(image, new RectangleF(x, y, width, height));
        }
Beispiel #4
0
        /// <summary>
        /// Draws the specified portion of the specified Image at the specified location and with the specified size.
        ///
        /// The srcRect parameter specifies a rectangular portion of the image object to draw. This portion is scaled
        /// up or down (in the case where source rectangle overruns the bounds of the image) to fit inside the rectangle
        /// specified by the destRect parameter.
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="destRect">Destination rect.</param>
        /// <param name="srcRect">Source rect.</param>
        /// <param name="srcUnit">Source unit.</param>
        public void DrawImage(Image image, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit)
        {
            if (image == null)
            {
                throw new ArgumentNullException("image");
            }

            var srcRect1 = srcRect;

            // If the source units are not the same we need to convert them
            // The reason we check for Pixel here is that our graphics already has the Pixel's baked into the model view transform
            if (srcUnit != graphicsUnit && srcUnit != GraphicsUnit.Pixel)
            {
                ConversionHelpers.GraphicsUnitConversion(srcUnit, graphicsUnit, image.HorizontalResolution, image.VerticalResolution, ref srcRect1);
            }

            if (srcRect1.Location == Point.Empty && srcRect1.Size == image.Size)
            {
                DrawImage(image, destRect);
                return;
            }

            if (image.NativeCGImage == null)
            {
                throw new NotImplementedException();
            }

            // Obtain the subImage
            var subImage = image.NativeCGImage.WithImageInRect(new CGRect(srcRect1.X, srcRect1.Y, srcRect1.Width, srcRect1.Height));

            // If we do not have anything to draw then we exit here
            if (subImage == null || subImage.Width == 0 || subImage.Height == 0)
            {
                return;
            }

            var transform = image.imageTransform;

            // Reset our height on the transform to account for subImage
            transform.y0 = subImage.Height;

            // Make sure we scale the image in case the source rectangle
            // overruns our subimage bouncs width and/or height
            float scaleX = subImage.Width / srcRect1.Width;
            float scaleY = subImage.Height / srcRect1.Height;

            transform.Scale(scaleX, scaleY);

            // Now draw our image
            DrawImage(destRect, subImage, transform);
        }
Beispiel #5
0
        void CreateNativeFont(FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont)
        {
            this.sizeInPoints = ConversionHelpers.GraphicsUnitConversion(unit, GraphicsUnit.Point, 96f, emSize);
            this.size         = emSize;
            this.unit         = unit;

            var size = sizeInPoints * 96f / 72f;

            var traits = CTFontSymbolicTraits.None;

            traits |= Bold ? CTFontSymbolicTraits.Bold : 0;
            traits |= Italic ? CTFontSymbolicTraits.Italic : 0;

            this.nativeFont = CTFontWithFamily(family, traits, size);
        }
Beispiel #6
0
        /// <summary>
        /// Draws the specified image, using its original physical size, at the location specified by a coordinate pair.
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="x">The x coordinate.</param>
        /// <param name="y">The y coordinate.</param>
        public void DrawImage(Image image, float x, float y)
        {
            var size   = image.physicalSize;
            var width  = size.Width;
            var height = size.Height;

            if (graphicsUnit != GraphicsUnit.Pixel)
            {
                width  = ConversionHelpers.GraphicsUnitConversion(GraphicsUnit.Pixel, graphicsUnit, image.HorizontalResolution, width);
                height = ConversionHelpers.GraphicsUnitConversion(GraphicsUnit.Pixel, graphicsUnit, image.VerticalResolution, height);
            }
            var uss = context.ConvertSizeToUserSpace(new CGSize(width, height));

            DrawImage(image, new RectangleF(x, y, (float)uss.Width, (float)uss.Height));
        }
        public Font(string familyName, float emSize, FontStyle style,
                    GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont)
        {
            if (emSize <= 0)
            {
                throw new ArgumentException("emSize is less than or equal to 0, evaluates to infinity, or is not a valid number.", "emSize");
            }


            // convert to 96 Dpi to be consistent with Windows
            var dpiSize = emSize * dpiScale;

            try {
                nativeFont = new CTFont(familyName, dpiSize);
            }
            catch
            {
                //nativeFont = new CTFont("Lucida Grande",emSize);
                nativeFont = new CTFont("Helvetica", dpiSize);
            }

            CTFontSymbolicTraits tMask = CTFontSymbolicTraits.None;

            if ((style & FontStyle.Bold) == FontStyle.Bold)
            {
                tMask |= CTFontSymbolicTraits.Bold;
            }
            if ((style & FontStyle.Italic) == FontStyle.Italic)
            {
                tMask |= CTFontSymbolicTraits.Italic;
            }
            strikeThrough = (style & FontStyle.Strikeout) == FontStyle.Strikeout;
            underLine     = (style & FontStyle.Underline) == FontStyle.Underline;

            var nativeFont2 = nativeFont.WithSymbolicTraits(dpiSize, tMask, tMask);

            if (nativeFont2 != null)
            {
                nativeFont = nativeFont2;
            }

            sizeInPoints = emSize;
            this.unit    = unit;

            // FIXME
            // I do not like the hard coded 72 but am just trying to boot strap the Font class right now
            size = ConversionHelpers.GraphicsUnitConversion(GraphicsUnit.Point, unit, 72.0f, sizeInPoints);
        }
Beispiel #8
0
        public void UnlockBits(BitmapData data)
        {
            if ((ImageLockMode)data.Reserved == ImageLockMode.ReadOnly)
            {
                return;
            }

            if (NativeCGImage.BitsPerPixel == 32)
            {
                if (!ConversionHelpers.sTablesInitialized)
                {
                    ConversionHelpers.CalculateTables();
                }
                Convert_BGRA_8888_To_P_RGBA_8888(bitmapBlock, data.Stride * data.Height);
            }
        }
        /// <summary>
        /// Draws a portion of an image at a specified location.
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="x">The x coordinate.</param>
        /// <param name="y">The y coordinate.</param>
        /// <param name="srcRect">Source rect.</param>
        /// <param name="srcUnit">Source unit.</param>
        public void DrawImage(Image image, float x, float y, RectangleF srcRect, GraphicsUnit srcUnit)
        {
            if (image == null)
            {
                throw new ArgumentNullException("image");
            }

            var srcRect1 = srcRect;

            // If the source units are not the same we need to convert them
            // The reason we check for Pixel here is that our graphics already has the Pixel's baked into the model view transform
            if (srcUnit != graphicsUnit && srcUnit != GraphicsUnit.Pixel)
            {
                ConversionHelpers.GraphicsUnitConversion(srcUnit, graphicsUnit, image.VerticalResolution, image.HorizontalResolution, ref srcRect1);
            }

            DrawImage(image, new RectangleF(x, y, srcRect1.Width, srcRect1.Height), srcRect1, graphicsUnit);
        }
        /// <summary>
        /// Draws a portion of an image at a specified location.
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="x">The x coordinate.</param>
        /// <param name="y">The y coordinate.</param>
        /// <param name="srcRect">Source rect.</param>
        /// <param name="srcUnit">Source unit.</param>
        public void DrawImage(Image image, int x, int y, Rectangle srcRect, GraphicsUnit srcUnit)
        {
            if (image == null)
            {
                throw new ArgumentNullException("image");
            }

            var width  = image.physicalSize.Width;
            var height = image.physicalSize.Height;

            if (graphicsUnit != GraphicsUnit.Pixel)
            {
                width  = ConversionHelpers.GraphicsUnitConversion(GraphicsUnit.Pixel, graphicsUnit, image.HorizontalResolution, width);
                height = ConversionHelpers.GraphicsUnitConversion(GraphicsUnit.Pixel, graphicsUnit, image.VerticalResolution, height);
            }

            DrawImage(image, new RectangleF(x, y, width, height), srcRect, srcUnit);
        }
Beispiel #11
0
        void CreateNativeFont(FontFamily family, float emSize, FontStyle style, GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont)
        {
            this.sizeInPoints  = ConversionHelpers.GraphicsUnitConversion(unit, GraphicsUnit.Point, 96f, emSize);
            this.underLine     = 0 != (style & FontStyle.Underline);
            this.strikeThrough = 0 != (style & FontStyle.Strikeout);

            this.size = emSize;
            this.unit = unit;

            var size = sizeInPoints * 96f / 72f;

            var traits = CTFontSymbolicTraits.None;

            traits |= style.IsBold() ? CTFontSymbolicTraits.Bold : 0;
            traits |= style.IsItalic() ? CTFontSymbolicTraits.Italic : 0;

            this.nativeFont = CTFontWithFamily(family, traits, size);
        }
Beispiel #12
0
        private void CreateNativeFont(FontFamily familyName, float emSize, FontStyle style,
                                      GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont)
        {
            // convert to 96 Dpi to be consistent with Windows
            var dpiSize = emSize * dpiScale;

            try
            {
                nativeFont = new CTFont(familyName.NativeDescriptor, dpiSize);
            }
            catch
            {
                nativeFont = new CTFont("Helvetica", dpiSize);
            }

            CTFontSymbolicTraits tMask = CTFontSymbolicTraits.None;

            if ((style & FontStyle.Bold) == FontStyle.Bold)
            {
                tMask |= CTFontSymbolicTraits.Bold;
            }
            if ((style & FontStyle.Italic) == FontStyle.Italic)
            {
                tMask |= CTFontSymbolicTraits.Italic;
            }
            strikeThrough = (style & FontStyle.Strikeout) == FontStyle.Strikeout;
            underLine     = (style & FontStyle.Underline) == FontStyle.Underline;

            var nativeFont2 = nativeFont.WithSymbolicTraits(dpiSize, tMask, tMask);

            if (nativeFont2 != null)
            {
                nativeFont = nativeFont2;
            }

            bold         = (nativeFont.SymbolicTraits & CTFontSymbolicTraits.Bold) == CTFontSymbolicTraits.Bold;
            italic       = (nativeFont.SymbolicTraits & CTFontSymbolicTraits.Italic) == CTFontSymbolicTraits.Italic;
            sizeInPoints = emSize;
            this.unit    = unit;

            // FIXME
            // I do not like the hard coded 72 but am just trying to boot strap the Font class right now
            size = ConversionHelpers.GraphicsUnitConversion(GraphicsUnit.Point, unit, 72.0f, sizeInPoints);
        }
Beispiel #13
0
        public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat pixelFormat)
        {
            // We don't support conversion
            if (PixelFormat != pixelFormat)
            {
                throw new ArgumentException("", "pixelFormat");
            }
            if (rect != new RectangleF(new PointF(0, 0), physicalDimension))
            {
                throw new NotImplementedException("Sub rectangles of bitmaps not supported yet.");
            }

            // Bitmap created from external data, convert it
            if (bitmapBlock == IntPtr.Zero)
            {
                GetRenderableContext();
            }

            BitmapData bitmapData = new BitmapData();

            //bitmapData.Scan0 = (IntPtr)((long)pinnedScanArray.AddrOfPinnedObject() + ((rect.Left * NativeCGImage.BitsPerPixel + 7) / 8) + (rect.Top * NativeCGImage.BytesPerRow));
            bitmapData.Scan0       = bitmapBlock;
            bitmapData.Height      = (int)rect.Height;
            bitmapData.Width       = (int)rect.Width;
            bitmapData.PixelFormat = pixelFormat;
            bitmapData.Stride      = (int)NativeCGImage.BytesPerRow;
            bitmapData.Reserved    = (int)flags;

            if (flags != ImageLockMode.WriteOnly)
            {
                if (NativeCGImage.BitsPerPixel == 32)
                {
                    if (!ConversionHelpers.sTablesInitialized)
                    {
                        ConversionHelpers.CalculateTables();
                    }
                    Convert_P_RGBA_8888_To_BGRA_8888(bitmapBlock, bitmapData.Stride * bitmapData.Height);
                }
            }

            return(bitmapData);
        }
Beispiel #14
0
        // Our internal format is pre-multiplied alpha
        static unsafe void Convert_BGRA_8888_To_P_RGBA_8888(IntPtr bitmapBlock, int size)
        {
            byte  temp   = 0;
            byte  alpha  = 0;
            byte *buffer = (byte *)bitmapBlock;

            for (int sd = 0; sd < size; sd += 4)
            {
                alpha = buffer [sd + 3];
                temp  = buffer [sd];                 // save off blue
                if (alpha < 255)
                {
                    buffer [sd]     = ConversionHelpers.PremultiplyValue(alpha, buffer [sd + 2]);                   // move red back
                    buffer [sd + 1] = ConversionHelpers.PremultiplyValue(alpha, buffer [sd + 1]);
                    buffer [sd + 2] = ConversionHelpers.PremultiplyValue(alpha, temp);
                }
                else
                {
                    buffer [sd]     = buffer [sd + 2];                  // move red back
                    buffer [sd + 2] = temp;
                }
            }
        }
Beispiel #15
0
        // Our internal format is pre-multiplied alpha
        static unsafe void Convert_P_RGBA_8888_To_BGRA_8888(IntPtr bitmapBlock, int size)
        {
            byte  temp   = 0;
            byte  alpha  = 0;
            byte *buffer = (byte *)bitmapBlock;

            for (int x = 0; x < size; x += 4)
            {
                alpha = buffer [x + 3];             // Save off alpha
                temp  = buffer [x];                 // save off red

                if (alpha < 255)
                {
                    buffer [x]     = ConversionHelpers.UnpremultiplyValue(alpha, buffer [x + 2]);               // move blue to red
                    buffer [x + 1] = ConversionHelpers.UnpremultiplyValue(alpha, buffer [x + 1]);
                    buffer [x + 2] = ConversionHelpers.UnpremultiplyValue(alpha, temp);                         // move the red to green
                }
                else
                {
                    buffer [x]     = buffer [x + 2];            // move blue to red
                    buffer [x + 2] = temp;                      // move the red to green
                }
            }
        }
        public void DrawImage(Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs)
        {
            if (image == null)
            {
                throw new ArgumentNullException("image");
            }

            var srcRect1 = new RectangleF(srcX, srcY, srcWidth, srcHeight);

            // If the source units are not the same we need to convert them
            // The reason we check for Pixel here is that our graphics already has the Pixel's baked into the model view transform
            if (srcUnit != graphicsUnit && srcUnit != GraphicsUnit.Pixel)
            {
                ConversionHelpers.GraphicsUnitConversion(srcUnit, graphicsUnit, image.HorizontalResolution, image.VerticalResolution, ref srcRect1);
            }
            if (image.NativeCGImage == null)
            {
                DrawImage(image, destRect);
                return;
            }

            // Obtain the subImage
            var subImage = image.NativeCGImage.WithImageInRect(srcRect1.ToCGRect());

            // If we do not have anything to draw then we exit here
            if (subImage.Width == 0 || subImage.Height == 0)
            {
                return;
            }

//			var transform = image.imageTransform;
////			// Reset our height on the transform to account for subImage
//			transform.y0 = subImage.Height;
////
////			// Make sure we scale the image in case the source rectangle
////			// overruns our subimage bouncs width and/or height
//			float scaleX = subImage.Width/srcRect1.Width;
//			float scaleY = subImage.Height/srcRect1.Height;
//			transform.Scale (scaleX, scaleY);
            bool attributesSet = imageAttrs != null && (imageAttrs.isColorMatrixSet || imageAttrs.isGammaSet);

            if (attributesSet)
            {
                InitializeImagingContext();
                CIImage result = subImage;

                if (imageAttrs.isColorMatrixSet)
                {
                    var ciFilter = CIFilter.FromName("CIColorMatrix");
                    ciFilter.SetDefaults();

                    ciFilter.SetValueForKey(result, new NSString("inputImage"));

                    var inputRVector    = new CIVector(imageAttrs.colorMatrix.Matrix00, imageAttrs.colorMatrix.Matrix01, imageAttrs.colorMatrix.Matrix02, imageAttrs.colorMatrix.Matrix03);
                    var inputGVector    = new CIVector(imageAttrs.colorMatrix.Matrix10, imageAttrs.colorMatrix.Matrix11, imageAttrs.colorMatrix.Matrix12, imageAttrs.colorMatrix.Matrix13);
                    var inputBVector    = new CIVector(imageAttrs.colorMatrix.Matrix20, imageAttrs.colorMatrix.Matrix21, imageAttrs.colorMatrix.Matrix22, imageAttrs.colorMatrix.Matrix23);
                    var inputAVector    = new CIVector(imageAttrs.colorMatrix.Matrix30, imageAttrs.colorMatrix.Matrix31, imageAttrs.colorMatrix.Matrix32, imageAttrs.colorMatrix.Matrix33);
                    var inputBiasVector = new CIVector(imageAttrs.colorMatrix.Matrix40, imageAttrs.colorMatrix.Matrix41, imageAttrs.colorMatrix.Matrix42, imageAttrs.colorMatrix.Matrix43);

                    ciFilter.SetValueForKey(inputRVector, new NSString("inputRVector"));
                    ciFilter.SetValueForKey(inputGVector, new NSString("inputGVector"));
                    ciFilter.SetValueForKey(inputBVector, new NSString("inputBVector"));
                    ciFilter.SetValueForKey(inputAVector, new NSString("inputAVector"));
                    ciFilter.SetValueForKey(inputBiasVector, new NSString("inputBiasVector"));
                    result = (CIImage)ciFilter.ValueForKey(new NSString("outputImage"));
                }

                if (imageAttrs.isGammaSet)
                {
                    var ciFilter = CIFilter.FromName("CIGammaAdjust");
                    ciFilter.SetDefaults();

                    ciFilter.SetValueForKey(result, new NSString("inputImage"));

                    var inputPower = NSNumber.FromFloat(imageAttrs.gamma);

                    ciFilter.SetValueForKey(inputPower, new NSString("inputPower"));
                    result = (CIImage)ciFilter.ValueForKey(new NSString("outputImage"));
                }


                subImage = ciContext.CreateCGImage(result, result.Extent);
            }

            transform    = image.imageTransform;
            transform.y0 = subImage.Height;
            float scaleX1 = subImage.Width / srcRect1.Width;
            float scaleY1 = subImage.Height / srcRect1.Height;

            transform.Scale(scaleX1, scaleY1);
            // Now draw our image
            DrawImage(destRect, subImage, transform);
        }
        /// <summary>
        /// Draws the specified portion of the specified Image at the specified location and with the specified size.
        ///
        /// The destPoints specifies a parallelogram with the first point specifying the upper left corner,
        /// second point specifying the upper right corner and the third point specifying the lower left corner.
        ///
        /// The srcRect parameter specifies a rectangular portion of the image object to draw. This portion is scaled
        /// up or down (in the case where source rectangle overruns the bounds of the image) to fit inside the rectangle
        /// specified by the destRect parameter.
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="destPoints">Destination points.</param>
        /// <param name="srcRect">Source rect.</param>
        /// <param name="srcUnit">Source unit.</param>
        public void DrawImage(Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit)
        {
            if (image == null)
            {
                throw new ArgumentNullException("image");
            }
            if (destPoints == null)
            {
                throw new ArgumentNullException("destPoints");
            }

            if (destPoints.Length < 3)
            {
                throw new ArgumentException("Destination points must be an array with a length of 3 or 4. " +
                                            "A length of 3 defines a parallelogram with the upper-left, upper-right, " +
                                            "and lower-left corners. A length of 4 defines a quadrilateral with the " +
                                            "fourth element of the array specifying the lower-right coordinate.");
            }

            // Windows throws a Not Implemented error if the points are more than 3
            if (destPoints.Length > 3)
            {
                throw new NotImplementedException();
            }

            var srcRect1 = srcRect;

            // If the source units are not the same we need to convert them
            // The reason we check for Pixel here is that our graphics already has the Pixel's baked into the model view transform
            if (srcUnit != graphicsUnit && srcUnit != GraphicsUnit.Pixel)
            {
                ConversionHelpers.GraphicsUnitConversion(srcUnit, graphicsUnit, image.HorizontalResolution, image.VerticalResolution, ref srcRect1);
            }

            if (srcRect1.Location == Point.Empty && srcRect1.Size == image.Size)
            {
                DrawImage(image, destPoints);
                return;
            }
            if (image.NativeCGImage == null)
            {
                throw new NotImplementedException();
            }

            // Obtain the subImage
            var subImage = image.NativeCGImage.WithImageInRect(srcRect1.ToCGRect());

            // If we do not have anything to draw then we exit here
            if (subImage.Width == 0 || subImage.Height == 0)
            {
                return;
            }

            // create our rectangle.  Offset is 0 because the CreateGeometricTransform bakes our x,y offset in there.
            var rect = new RectangleF(0, 0, destPoints [1].X - destPoints [0].X, destPoints [2].Y - destPoints [0].Y);

            // We need to flip our Y axis so the image appears right side up
            var geoTransform = new CGAffineTransform(1, 0, 0, -1, 0, rect.Height);

            // Make sure we scale the image in case the source rectangle
            // overruns our subimage bounds (width and/or height)
            float scaleX = subImage.Width / srcRect1.Width;
            float scaleY = subImage.Height / srcRect1.Height;

            geoTransform.Scale(scaleX, scaleY);

            //var geott = GeomUtilities.CreateGeometricTransform (rect, destPoints);
            geoTransform.Multiply(GeomUtilities.CreateGeometricTransform(rect, destPoints));

            // Apply our transform to the context
            context.ConcatCTM(geoTransform);

            // now we draw our image.
            context.DrawImage(rect.ToCGRect(), subImage);

            // Now we revert our image transform from the context
            var revert = CGAffineTransform.CGAffineTransformInvert(geoTransform);

            context.ConcatCTM(revert);

            subImage.Dispose();
        }
Beispiel #18
0
        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;

                if (format.LineAlignment != StringAlignment.Near)
                {
                    insetBounds.Size = MeasureString(s, font);
                }
            }

            PointF textPosition = new PointF(insetBounds.X,
                                             insetBounds.Y);

            float boundsWidth = insetBounds.Width;

            // Calculate the lines
            int   start          = 0;
            int   length         = (int)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 = (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;
            }

            // 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 = (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);
                    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 = (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);

                // 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)
                {
                    if (layoutAvailable)
                    {
                        textMatrix.Translate(penFlushness + textPosition.X, textPosition.Y + ((insetBounds.Height / 2) - (baselineOffset / 2)));
                    }
                    else
                    {
                        textMatrix.Translate(penFlushness + textPosition.X, textPosition.Y - ((insetBounds.Height / 2) - (baselineOffset / 2)));
                    }
                }

                if (format.LineAlignment == StringAlignment.Far)
                {
                    if (layoutAvailable)
                    {
                        textMatrix.Translate(penFlushness + textPosition.X, textPosition.Y + ((insetBounds.Height) - (baselineOffset)));
                    }
                    else
                    {
                        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();
        }