public override Size MeasureText(Font font, string text) { CTFont sysFont = font.RendererData as CTFont; if (sysFont == null || Math.Abs(font.RealSize - font.Size * Scale) > 2) { FreeFont(font); LoadFont(font); sysFont = font.RendererData as CTFont; } var key = new Tuple <String, Font>(text, font); if (m_StringCache.ContainsKey(key)) { var tex = m_StringCache[key].Texture; return(new Size(tex.Width, tex.Height)); } text = text.Replace("\t", " "); var attributedString = new NSAttributedString(text, new CTStringAttributes() { Font = sysFont, UnderlineStyle = font.Underline ? CTUnderlineStyle.Single : CTUnderlineStyle.None }); CTLine ctLine = new CTLine(attributedString); CGRect cgRect = ctLine.GetBounds(CTLineBoundsOptions.IncludeLanguageExtents | CTLineBoundsOptions.UseHangingPunctuation); ctLine.Dispose(); attributedString.Dispose(); return(new Size(Util.Ceil((float)cgRect.Width), Util.Ceil((float)cgRect.Height))); }
public void OnDetached() { _nativeTextView.LayoutManager.Delegate = null; _nativeTextView.AttributedText = _orgString; _nativeTextView.Text = _formsEditor.Text; _orgString?.Dispose(); _orgString = null; _nativeTextView = null; _formsEditor = null; }
public override void RenderText(Font font, Point position, string text) { Flush(); CTFont sysFont = font.RendererData as CTFont; if (sysFont == null || Math.Abs(font.RealSize - font.Size * Scale) > 2) { FreeFont(font); LoadFont(font); sysFont = font.RendererData as CTFont; } var key = new Tuple <String, Font>(text, font); if (!m_StringCache.ContainsKey(key)) { // not cached - create text renderer text = text.Replace("\t", " "); var attributedString = new NSAttributedString(text, new CTStringAttributes() { ForegroundColorFromContext = true, Font = sysFont, UnderlineStyle = font.Underline ? CTUnderlineStyle.Single : CTUnderlineStyle.None }); CTLine ctLine = new CTLine(attributedString); CGRect cgRect = ctLine.GetBounds(CTLineBoundsOptions.IncludeLanguageExtents | CTLineBoundsOptions.UseHangingPunctuation); TextRenderer tr = new TextRenderer(Util.Ceil((float)cgRect.Width), Util.Ceil((float)cgRect.Height), this); tr.DrawString(ctLine, new Point(0, (int)sysFont.DescentMetric)); // renders string on the texture ctLine.Dispose(); attributedString.Dispose(); DrawTexturedRect(tr.Texture, new Rectangle(position.X, position.Y, tr.Texture.Width, tr.Texture.Height)); m_StringCache[key] = tr; } else { TextRenderer tr = m_StringCache[key]; DrawTexturedRect(tr.Texture, new Rectangle(position.X, position.Y, tr.Texture.Width, tr.Texture.Height)); } }
public void DrawText(string text, float x, float y, float width, float height, Xamarin.Forms.TextAlignment hAlignment, Xamarin.Forms.TextAlignment vAlignment) { if (font == null || font.NativeFont == null) { return; } var attributedString = new NSAttributedString(text, new CTStringAttributes() { Font = font.NativeFont, ForegroundColorFromContext = true }); CTLine ctLine = new CTLine(attributedString); CGSize size = new CGSize((float)ctLine.GetTypographicBounds(), font.NativeFont.CapHeightMetric + font.NativeFont.DescentMetric); if ((hAlignment & Xamarin.Forms.TextAlignment.Center) != 0) { x += (width - (float)size.Width) / 2; } else if ((hAlignment & Xamarin.Forms.TextAlignment.End) != 0) { x += width - (float)size.Width; } if ((vAlignment & Xamarin.Forms.TextAlignment.Center) != 0) { y += (height - (float)size.Height) / 2; } else if ((vAlignment & Xamarin.Forms.TextAlignment.End) != 0) { y += height - (float)size.Height; } context.SaveState(); context.ScaleCTM(1f, -1f); context.TextPosition = new CGPoint(x, -y - font.NativeFont.CapHeightMetric); ctLine.Draw(context); context.RestoreState(); ctLine.Dispose(); attributedString.Dispose(); }
public Xamarin.Forms.Size MeasureText(string text) { if (font == null || font.NativeFont == null) { return(Xamarin.Forms.Size.Zero); } var attributedString = new NSAttributedString(text, new CTStringAttributes() { Font = font.NativeFont, ForegroundColorFromContext = true }); CTLine ctLine = new CTLine(attributedString); Xamarin.Forms.Size size = new Xamarin.Forms.Size((float)ctLine.GetTypographicBounds(), font.NativeFont.CapHeightMetric + font.NativeFont.DescentMetric); ctLine.Dispose(); attributedString.Dispose(); return(size); }
public void DrawText(string text, float x, float y) { if (font == null || font.NativeFont == null) { return; } var attributedString = new NSAttributedString(text, new CTStringAttributes() { Font = font.NativeFont, ForegroundColorFromContext = true }); CTLine ctLine = new CTLine(attributedString); context.SaveState(); context.ScaleCTM(1f, -1f); context.TextPosition = new CGPoint(x, -y - font.NativeFont.CapHeightMetric); ctLine.Draw(context); context.RestoreState(); ctLine.Dispose(); attributedString.Dispose(); }
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 *= contentScaleFactorWidth; textDef.Dimensions.Width *= contentScaleFactorWidth; textDef.Dimensions.Height *= contentScaleFactorHeight; bool hasPremultipliedAlpha; // font UIFont font = null; var ext = System.IO.Path.GetExtension(textDef.FontName); if (!String.IsNullOrEmpty(ext) && ext.ToLower() == ".ttf") { try { textDef.FontName = LoadFontFile(textDef.FontName); font = UIFont.FromName(textDef.FontName, textDef.FontSize); } catch (Exception exc) { CCLog.Log(".ttf {0} file not found or can not be loaded.", textDef.FontName); } } else { // font font = UIFont.FromName(textDef.FontName, textDef.FontSize); //NSFontManager.SharedFontManager.FontWithFamily(textDef.FontName, NSFontTraitMask.Unbold | NSFontTraitMask.Unitalic, 0, textDef.FontSize); } if (font == null) { font = UIFont.FromName("Arial", textDef.FontSize); CCLog.Log("{0} not found. Defaulting to Arial.", textDef.FontName); } // color var foregroundColor = UIColor.White; // alignment var horizontalAlignment = textDef.Alignment; var verticleAlignement = textDef.LineAlignment; var textAlign = (CCTextAlignment.Right == horizontalAlignment) ? UITextAlignment.Right : (CCTextAlignment.Center == horizontalAlignment) ? UITextAlignment.Center : UITextAlignment.Left; // LineBreak var lineBreak = (CCLabelLineBreak.Character == textDef.LineBreak) ? UILineBreakMode.CharacterWrap : (CCLabelLineBreak.Word == textDef.LineBreak) ? UILineBreakMode.WordWrap : UILineBreakMode.Clip; var nsparagraphStyle = (NSMutableParagraphStyle)NSParagraphStyle.Default.MutableCopy(); nsparagraphStyle.LineBreakMode = lineBreak; nsparagraphStyle.Alignment = textAlign; // Create a new attributed string definition var nsAttributes = new UIStringAttributes(); // 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 CGSize(textDef.Dimensions.Width, textDef.Dimensions.Height); var layoutAvailable = true; if (dimensions.Width <= 0) { dimensions.Width = 8388608; layoutAvailable = false; } if (dimensions.Height <= 0) { dimensions.Height = 8388608; layoutAvailable = false; } var boundingRect = stringWithAttributes.GetBoundingRect(new CGSize((int)dimensions.Width, (int)dimensions.Height), NSStringDrawingOptions.UsesLineFragmentOrigin, null); if (!layoutAvailable) { if (dimensions.Width == 8388608) { dimensions.Width = boundingRect.Width; } if (dimensions.Height == 8388608) { dimensions.Height = boundingRect.Height; } } imageWidth = (int)dimensions.Width; imageHeight = (int)dimensions.Height; // Alignment var xOffset = (nfloat)0.0f; switch (textAlign) { case UITextAlignment.Left: xOffset = 0; break; case UITextAlignment.Center: xOffset = (dimensions.Width - boundingRect.Width) / 2.0f; break; case UITextAlignment.Right: xOffset = dimensions.Width - boundingRect.Width; break; default: break; } // Line alignment var yOffset = (CCVerticalTextAlignment.Bottom == verticleAlignement || boundingRect.Height >= dimensions.Height) ? (dimensions.Height - boundingRect.Height) // align to bottom : (CCVerticalTextAlignment.Top == verticleAlignement) ? 0 // align to top : (imageHeight - boundingRect.Height) / 2.0f; // align to center //Find the rect that the string will draw into inside the dimensions var drawRect = new CGRect(xOffset , yOffset , boundingRect.Width , boundingRect.Height); UIImage image = null; CGContext context = null; try { UIGraphics.BeginImageContext(new CGSize(imageWidth, imageHeight)); context = UIGraphics.GetCurrentContext(); //Set antialias or not context.SetShouldAntialias(textDef.isShouldAntialias); stringWithAttributes.DrawString(drawRect); image = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); // 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); } catch (Exception exc) { CCLog.Log("CCLabel: Error creating native label:{0}\n{1}", exc.Message, exc.StackTrace); } finally { // clean up the resources if (image != null) { image.Dispose(); image = null; } if (context != null) { context.Dispose(); context = null; } if (stringWithAttributes != null) { stringWithAttributes.Dispose(); stringWithAttributes = null; } } return(new CCTexture2D()); }
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 *= 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 { 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 foregroundColor = NSColor.White; // 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) { CCLog.Log("Native string:", "Dimensions of native NSAttributedString can not be 0,0"); return(new CCTexture2D()); } 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; stringWithAttributes.Dispose(); stringWithAttributes = null; stringWithAttributes = new NSAttributedString(text, nsAttributes); } 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; stringWithAttributes.Dispose(); stringWithAttributes = null; stringWithAttributes = new NSAttributedString(text, nsAttributes); } 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); NSImage image = null; try { //Set antialias or not NSGraphicsContext.CurrentContext.ShouldAntialias = textDef.isShouldAntialias; 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); } catch (Exception exc) { CCLog.Log("CCLabel: Error creating native label:{0}\n{1}", exc.Message, exc.StackTrace); } finally { // clean up the resources if (image != null) { image.Dispose(); image = null; } if (stringWithAttributes != null) { stringWithAttributes.Dispose(); stringWithAttributes = null; } } return(new CCTexture2D()); }