예제 #1
0
        private void InitWithCGImage(CGImage image, All filter)
        {
            int	width, height, i;
            CGContext context = null;
            IntPtr data;
            CGColorSpace colorSpace;
            IntPtr tempData;
            bool hasAlpha;
            CGImageAlphaInfo info;
            CGAffineTransform transform;
            Size imageSize;
            SurfaceFormat pixelFormat;
            //bool sizeToFit = false;

            if (image == null) {
                throw new ArgumentException (" NSImage is invalid! " );
            }

            info = image.AlphaInfo;
            hasAlpha = ((info == CGImageAlphaInfo.PremultipliedLast) || (info == CGImageAlphaInfo.PremultipliedFirst) || (info == CGImageAlphaInfo.Last) || (info == CGImageAlphaInfo.First) ? true : false);

            if (image.ColorSpace != null) {
                if (hasAlpha) {
                    pixelFormat = SurfaceFormat.Color;
                } else {
                    pixelFormat = SurfaceFormat.Color;
                }
            } else {
                pixelFormat = SurfaceFormat.Alpha8;
            }

            imageSize = new Size (image.Width,image.Height);
            transform = CGAffineTransform.MakeIdentity ();
            width = imageSize.Width;

            // Take out the width and height adjustments for power of 2
            //  If not then GetData and SetData is messed up.

            // The Mac opengl version supports non power of 2 textures
            // so we do not have to make them so
            //			if ((width != 1) && ((width & (width - 1)) != 0)) {
            //				i = 1;
            //				while ((sizeToFit ? 2 * i : i) < width)
            //					i *= 2;
            //				width = i;
            //			}

            height = imageSize.Height;

            // The Mac opengl version supports non power of 2 textures
            // so we do not have to make them so
            //			if ((height != 1) && ((height & (height - 1)) != 0)) {
            //				i = 1;
            //				while ((sizeToFit ? 2 * i : i) < height)
            //					i *= 2;
            //				height = i;
            //			}
            // TODO: kMaxTextureSize = 1024
            //			while ((width > 1024) || (height > 1024)) {
            //				width /= 2;
            //				height /= 2;
            //				transform = CGAffineTransform.MakeScale (0.5f, 0.5f);
            //				imageSize.Width /= 2;
            //				imageSize.Height /= 2;
            //			}

            float size = Math.Max(width,height);
            if(size > 1024)
            {
                float ratio = 1024 / size;
                width = (int)(width * ratio);
                height = (int)(height * ratio);
                transform = CGAffineTransform.MakeScale(ratio, ratio);
                imageSize.Width = (int)(imageSize.Width * ratio);
                imageSize.Height = (int)(imageSize.Height * ratio);;
            }

            switch (pixelFormat) {
            case SurfaceFormat.Color:
                colorSpace = CGColorSpace.CreateDeviceRGB ();
                data = Marshal.AllocHGlobal (height * width * 4);
                context = new CGBitmapContext (data, width, height, 8, 4 * width, colorSpace,CGImageAlphaInfo.PremultipliedLast);
                colorSpace.Dispose ();
                break;
            case SurfaceFormat.Alpha8:
                data = Marshal.AllocHGlobal (height * width);
                context = new CGBitmapContext (data, width, height, 8, width, null, CGImageAlphaInfo.Only);
                break;
            default:
                throw new NotSupportedException ("Invalid pixel format");
            }

            context.ClearRect (new RectangleF (0,0,width,height));
            context.TranslateCTM (0, height - imageSize.Height);

            if (!transform.IsIdentity) {
                context.ConcatCTM (transform);
            }

            context.DrawImage (new RectangleF (0, 0, image.Width, image.Height), image);

            //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
            /*
            if(pixelFormat == SurfaceFormat.Rgb32) {
                tempData = Marshal.AllocHGlobal(height * width * 2);

                int d32;
                short d16;
                int inPixel32Count=0,outPixel16Count=0;
                for(i = 0; i < width * height; ++i, inPixel32Count+=sizeof(int))
                {
                    d32 = Marshal.ReadInt32(data,inPixel32Count);
                    short R = (short)((((d32 >> 0) & 0xFF) >> 3) << 11);
                    short G = (short)((((d32 >> 8) & 0xFF) >> 2) << 5);
                    short B = (short)((((d32 >> 16) & 0xFF) >> 3) << 0);
                    d16 = (short)  (R | G | B);
                    Marshal.WriteInt16(tempData,outPixel16Count,d16);
                    outPixel16Count += sizeof(short);
                }
                Marshal.FreeHGlobal(data);
                data = tempData;
            }
            */

            InitWithData (data, pixelFormat, width, height, imageSize, filter);

            context.Dispose ();
            Marshal.FreeHGlobal (data);
        }
예제 #2
0
		private void InitWithCGImage (CGImage image, All filter)
		{
			int	width, height, i;
			CGContext context = null;
			IntPtr data;
			CGColorSpace colorSpace;
			IntPtr tempData;
			bool hasAlpha;
			CGImageAlphaInfo info;
			CGAffineTransform transform;
			Size imageSize;
			SurfaceFormat pixelFormat;
			bool sizeToFit = false;

			if (image == null) {
				throw new ArgumentException (" NSImage is invalid! " );
			}

			info = image.AlphaInfo;
			hasAlpha = ((info == CGImageAlphaInfo.PremultipliedLast) || (info == CGImageAlphaInfo.PremultipliedFirst) || (info == CGImageAlphaInfo.Last) || (info == CGImageAlphaInfo.First) ? true : false);

			if (image.ColorSpace != null) {
				if (hasAlpha) {
					pixelFormat = SurfaceFormat.Rgba32;
				} else {
					pixelFormat = SurfaceFormat.Rgb32;
				}
			} else {	
				pixelFormat = SurfaceFormat.Alpha8;
			}

			imageSize = new Size (image.Width,image.Height);
			transform = CGAffineTransform.MakeIdentity ();
			width = imageSize.Width;

			if ((width != 1) && ((width & (width - 1)) != 0)) {
				i = 1;
				while ((sizeToFit ? 2 * i : i) < width)
					i *= 2;
				width = i;
			}
			height = imageSize.Height;
			if ((height != 1) && ((height & (height - 1)) != 0)) {
				i = 1;
				while ((sizeToFit ? 2 * i : i) < height)
					i *= 2;
				height = i;
			}
			// TODO: kMaxTextureSize = 1024
			while ((width > 1024) || (height > 1024)) {
				width /= 2;
				height /= 2;
				transform = CGAffineTransform.MakeScale (0.5f, 0.5f);
				imageSize.Width /= 2;
				imageSize.Height /= 2;
			}

			switch (pixelFormat) {		
			case SurfaceFormat.Rgba32:
				colorSpace = CGColorSpace.CreateDeviceRGB ();
				data = Marshal.AllocHGlobal (height * width * 4);
				context = new CGBitmapContext (data, width, height, 8, 4 * width, colorSpace,CGImageAlphaInfo.PremultipliedLast);
				colorSpace.Dispose ();
				break;
			case SurfaceFormat.Rgb32:
				colorSpace = CGColorSpace.CreateDeviceRGB ();
				data = Marshal.AllocHGlobal (height * width * 4);
				context = new CGBitmapContext (data, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.NoneSkipLast);
				colorSpace.Dispose ();
				break;					
			case SurfaceFormat.Alpha8:
				data = Marshal.AllocHGlobal (height * width);
				context = new CGBitmapContext (data, width, height, 8, width, null, CGImageAlphaInfo.Only);
				break;				
			default:
				throw new NotSupportedException ("Invalid pixel format"); 
			}

			context.ClearRect (new RectangleF (0,0,width,height));
			context.TranslateCTM (0, height - imageSize.Height);

			if (!transform.IsIdentity) {
				context.ConcatCTM (transform);
			}

			context.DrawImage (new RectangleF (0, 0, image.Width, image.Height), image);

			//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
			if (pixelFormat == SurfaceFormat.Rgb32) {
				tempData = Marshal.AllocHGlobal (height * width * 2);

				int d32;
				short d16;
				int inPixel32Count = 0, outPixel16Count=0;
				for (i = 0; i < width * height; ++i, inPixel32Count+=sizeof(int)) {
					d32 = Marshal.ReadInt32 (data, inPixel32Count);
					short R = (short)((((d32 >> 0) & 0xFF) >> 3) << 11);
					short G = (short)((((d32 >> 8) & 0xFF) >> 2) << 5);
					short B = (short)((((d32 >> 16) & 0xFF) >> 3) << 0);
					d16 = (short)(R | G | B);
					Marshal.WriteInt16 (tempData, outPixel16Count, d16);
					outPixel16Count += sizeof(short);
				}
				Marshal.FreeHGlobal (data);
				data = tempData;			
			}

			InitWithData (data, pixelFormat, width, height, imageSize, filter);

			context.Dispose ();
			Marshal.FreeHGlobal (data);	
		}
		internal static void NativeDrawString (CGBitmapContext bitmapContext, string s, CTFont font, CCColor4B brush, CGRect layoutRectangle)
		{
			if (font == null)
				throw new ArgumentNullException ("font");

			if (s == null || s.Length == 0)
				return;

			bitmapContext.ConcatCTM (bitmapContext.GetCTM().Invert());

            // This is not needed here since the color is set in the attributed string.
			//bitmapContext.SetFillColor(brush.R/255f, brush.G/255f, brush.B/255f, brush.A/255f);

            // I think we only Fill the text with no Stroke surrounding
			//bitmapContext.SetTextDrawingMode(CGTextDrawingMode.Fill);

			var attributedString = buildAttributedString(s, font, brush);

			// Work out the geometry
			CGRect insetBounds = layoutRectangle;

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

            float boundsWidth = (float)insetBounds.Width;

			// Calculate the lines
			nint start = 0;
            nint 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 (vertical != CCVerticalTextAlignment.Top) {
				while (start < length) {

                    nint count = typesetter.SuggestLineBreak((int)start, (double)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 ((float)(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"
                nint count = typesetter.SuggestLineBreak((int)start, (double)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);

				// Calculate the string format if need be
				var penFlushness = 0.0f;

				if (horizontal == CCTextAlignment.Right)
					penFlushness = (float)line.GetPenOffsetForFlush(1.0f, boundsWidth);
				else if (horizontal == CCTextAlignment.Center)
					penFlushness = (float)line.GetPenOffsetForFlush(0.5f, boundsWidth);

				// initialize our Text Matrix or we could get trash in here
				var textMatrix = CGAffineTransform.MakeIdentity();

				if (vertical == CCVerticalTextAlignment.Top)
					textMatrix.Translate(penFlushness, insetBounds.Height - textPosition.Y -(float)Math.Floor(ascent - 1));
				if (vertical == CCVerticalTextAlignment.Center)
					textMatrix.Translate(penFlushness, ((insetBounds.Height / 2) + (baselineOffset / 2)) - textPosition.Y -(float)Math.Floor(ascent - 1));
				if (vertical == CCVerticalTextAlignment.Bottom)
					textMatrix.Translate(penFlushness, baselineOffset - textPosition.Y -(float)Math.Floor(ascent - 1));

				// Set our matrix
				bitmapContext.TextMatrix = textMatrix;

				// and draw the line
				line.Draw(bitmapContext);

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

			}

		}	
예제 #4
0
        private void InitWithCGImage(CGImage image)
        {
            int	width, height;
            CGBitmapContext bitmap = null;
            bool hasAlpha;
            CGImageAlphaInfo alphaInfo;
            CGColorSpace colorSpace;
            int bitsPerComponent, bytesPerRow;
            CGBitmapFlags bitmapInfo;
            bool premultiplied = false;
            int bitsPerPixel = 0;

            if (image == null) {
                throw new ArgumentException (" image is invalid! " );
            }

            alphaInfo = image.AlphaInfo;
            hasAlpha = ((alphaInfo == CGImageAlphaInfo.PremultipliedLast) || (alphaInfo == CGImageAlphaInfo.PremultipliedFirst) || (alphaInfo == CGImageAlphaInfo.Last) || (alphaInfo == CGImageAlphaInfo.First) ? true : false);

            imageSize.Width = image.Width;
            imageSize.Height = image.Height;

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

            // Not sure yet if we need to keep the original image information
            // before we change it internally.  TODO look at what windows does
            // and follow that.
            bitmapInfo = image.BitmapInfo;
            bitsPerComponent = image.BitsPerComponent;
            bitsPerPixel = image.BitsPerPixel;
            bytesPerRow = width * bitsPerPixel/bitsPerComponent;
            int size = bytesPerRow * height;

            colorSpace = image.ColorSpace;

            // Right now internally we represent the images all the same
            // I left the call here just in case we find that this is not
            // possible.  Read the comments for non alpha images.
            if(colorSpace != null) {
                if( hasAlpha ) {
                    premultiplied = true;
                    colorSpace = CGColorSpace.CreateDeviceRGB ();
                    bitsPerComponent = 8;
                    bitsPerPixel = 32;
                    bitmapInfo = CGBitmapFlags.PremultipliedLast;
                }
                else
                {
                    // even for images without alpha we will internally
                    // represent them as RGB with alpha.  There were problems
                    // if we do not do it this way and creating a bitmap context.
                    // The images were not drawing correctly and tearing.  Also
                    // creating a Graphics to draw on was a nightmare.  This
                    // should probably be looked into or maybe it is ok and we
                    // can continue representing internally with this representation
                    premultiplied = true;
                    colorSpace = CGColorSpace.CreateDeviceRGB ();
                    bitsPerComponent = 8;
                    bitsPerPixel = 32;
                    bitmapInfo = CGBitmapFlags.NoneSkipLast;
                }
            } else {
                premultiplied = true;
                colorSpace = CGColorSpace.CreateDeviceRGB ();
                bitsPerComponent = 8;
                bitsPerPixel = 32;
                bitmapInfo = CGBitmapFlags.NoneSkipLast;
            }

            bytesPerRow = width * bitsPerPixel/bitsPerComponent;
            size = bytesPerRow * height;

            bitmapBlock = Marshal.AllocHGlobal (size);
            bitmap = new CGBitmapContext (bitmapBlock,
                                          width, height,
                                          bitsPerComponent,
                                          bytesPerRow,
                                          colorSpace,
                                          bitmapInfo);

            bitmap.ClearRect (new RectangleF (0,0,width,height));

            // We need to flip the Y axis to go from right handed to lefted handed coordinate system
            var transform = new CGAffineTransform(1, 0, 0, -1, 0, image.Height);
            bitmap.ConcatCTM(transform);

            bitmap.DrawImage(new RectangleF (0, 0, image.Width, image.Height), image);

            var provider = new CGDataProvider (bitmapBlock, size, true);
            NativeCGImage = new CGImage (width, height, bitsPerComponent,
                                         bitsPerPixel, bytesPerRow,
                                         colorSpace,
                                         bitmapInfo,
                                         provider, null, true, image.RenderingIntent);

            colorSpace.Dispose();
            bitmap.Dispose();
        }