Ejemplo n.º 1
0
        internal CCTexture2D CreateTextSprite(string text, CCFontDefinition textDefinition)
        {
            if (string.IsNullOrEmpty(text))
            {
                return(new CCTexture2D());
            }

            int imageWidth;
            int imageHeight;
            var textDef = textDefinition;
            var contentScaleFactorWidth  = CCLabel.DefaultTexelToContentSizeRatios.Width;
            var contentScaleFactorHeight = CCLabel.DefaultTexelToContentSizeRatios.Height;

            textDef.FontSize          *= (int)contentScaleFactorWidth;
            textDef.Dimensions.Width  *= contentScaleFactorWidth;
            textDef.Dimensions.Height *= contentScaleFactorHeight;

            bool hasPremultipliedAlpha;

            // font
            NSFont font = null;

            var ext = System.IO.Path.GetExtension(textDef.FontName);

            if (!String.IsNullOrEmpty(ext) && ext.ToLower() == ".ttf")
            {
                try
                {
                    textDef.FontName = LoadFontFile(textDef.FontName);
                    font             = NSFont.FromFontName(textDef.FontName, textDef.FontSize);
                }
                catch (Exception exc)
                {
                    CCLog.Log(".ttf {0} file not found or can not be loaded.", textDef.FontName);
                }
            }
            else
            {
                // font
                font = NSFontManager.SharedFontManager.FontWithFamily(textDef.FontName, NSFontTraitMask.Unbold | NSFontTraitMask.Unitalic, 0, textDef.FontSize);
            }

            if (font == null)
            {
                font = NSFontManager.SharedFontManager.FontWithFamily("Arial", NSFontTraitMask.Unbold | NSFontTraitMask.Unitalic, 0, textDef.FontSize);
                CCLog.Log("{0} not found.  Defaulting to Arial.", textDef.FontName);
            }

            // color
            var fontColor       = textDef.FontFillColor;
            var fontAlpha       = textDef.FontAlpha;
            var foregroundColor = NSColor.FromDeviceRgba(fontColor.R / 255.0f,
                                                         fontColor.G / 255.0f,
                                                         fontColor.B / 255.0f,
                                                         fontAlpha / 255.0f);

            // alignment
            var horizontalAlignment = textDef.Alignment;
            var verticleAlignement  = textDef.LineAlignment;

            var textAlign = (CCTextAlignment.Right == horizontalAlignment) ? NSTextAlignment.Right
                : (CCTextAlignment.Center == horizontalAlignment) ? NSTextAlignment.Center
                : NSTextAlignment.Left;

            // LineBreak
            var lineBreak = (CCLabelLineBreak.Character == textDef.LineBreak) ? NSLineBreakMode.CharWrapping
                : (CCLabelLineBreak.Word == textDef.LineBreak) ? NSLineBreakMode.ByWordWrapping
                : NSLineBreakMode.Clipping;

            var nsparagraphStyle = new NSMutableParagraphStyle();

            nsparagraphStyle.SetParagraphStyle(NSMutableParagraphStyle.DefaultParagraphStyle);
            nsparagraphStyle.LineBreakMode = lineBreak;
            nsparagraphStyle.Alignment     = textAlign;

            // Create a new attributed string definition
            var nsAttributes = new NSStringAttributes();

            // Font attribute
            nsAttributes.Font            = font;
            nsAttributes.ForegroundColor = foregroundColor;
            nsAttributes.ParagraphStyle  = nsparagraphStyle;

            var stringWithAttributes = new NSAttributedString(text, nsAttributes);

            var realDimensions = stringWithAttributes.Size;

            // Mac crashes if the width or height is 0
            if (realDimensions == SizeF.Empty)
            {
                throw new ArgumentOutOfRangeException("Native string:", "Dimensions of native NSAttributedString can not be 0,0");
            }

            var dimensions = new SizeF(textDef.Dimensions.Width, textDef.Dimensions.Height);

            var layoutAvailable = true;

            //
            // * Note * This seems to only effect Mac because iOS works fine without this work around.
            // Right Alignment BoundingRectWithSize does not seem to be working correctly when the following conditions are set:
            //      1) Alignment Right
            //      2) No dimensions
            //      3) There are new line characters embedded in the string.
            //
            // So we set alignment to Left, calculate our bounds and then restore alignement afterwards before drawing.
            //
            if (dimensions.Width <= 0)
            {
                dimensions.Width = 8388608;
                layoutAvailable  = false;

                // Set our alignment variables to left - see notes above.
                nsparagraphStyle.Alignment = NSTextAlignment.Left;
            }

            if (dimensions.Height <= 0)
            {
                dimensions.Height = 8388608;
                layoutAvailable   = false;
            }

            // Calculate our bounding rectangle
            var boundingRect = stringWithAttributes.BoundingRectWithSize(new SizeF((int)dimensions.Width, (int)dimensions.Height),
                                                                         NSStringDrawingOptions.UsesLineFragmentOrigin);

            if (!layoutAvailable)
            {
                if (dimensions.Width == 8388608)
                {
                    dimensions.Width = boundingRect.Width;

                    // Restore our alignment before drawing - see notes above.
                    nsparagraphStyle.Alignment = textAlign;
                }
                if (dimensions.Height == 8388608)
                {
                    dimensions.Height = boundingRect.Height;
                }
            }

            imageWidth  = (int)dimensions.Width;
            imageHeight = (int)dimensions.Height;

            // Alignment
            var xOffset = 0.0f;

            switch (textAlign)
            {
            case NSTextAlignment.Left:
                xOffset = 0;
                break;

            case NSTextAlignment.Center:
                xOffset = (dimensions.Width - boundingRect.Width) / 2.0f;
                break;

            case NSTextAlignment.Right: xOffset = dimensions.Width - boundingRect.Width; break;

            default: break;
            }

            // Line alignment
            var yOffset = (CCVerticalTextAlignment.Top == verticleAlignement ||
                           boundingRect.Height >= dimensions.Height) ? (dimensions.Height - boundingRect.Height) // align to top
                : (CCVerticalTextAlignment.Bottom == verticleAlignement) ? 0                                     // align to bottom
                : (imageHeight - boundingRect.Height) / 2.0f;                                                    // align to center

            //Find the rect that the string will draw into inside the dimensions
            var drawRect = new RectangleF(xOffset
                                          , yOffset
                                          , boundingRect.Width
                                          , boundingRect.Height);

            //Disable antialias
            NSGraphicsContext.CurrentContext.ShouldAntialias = false;

            NSImage image = new NSImage(new SizeF(imageWidth, imageHeight));

            image.LockFocus();

            // set a default transform
            var transform = new NSAffineTransform();

            transform.Set();

            stringWithAttributes.DrawInRect(drawRect);

            image.UnlockFocus();

            // We will use Texture2D from stream here instead of CCTexture2D stream.
            var tex = Texture2D.FromStream(CCDrawManager.SharedDrawManager.XnaGraphicsDevice, image);

            // Debugging purposes
//            var path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
//            var fileName = Path.Combine(path, "Label3.png");
//            using (var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
//            {
//                tex.SaveAsPng(stream, imageWidth, imageHeight);
//            }

            // Create our texture of the label string.
            var texture = new CCTexture2D(tex);

            return(texture);
        }