void UpdateFont() { var elementType = Element.GetType(); var familyProperty = elementType.GetProperty("FontFamily"); if (familyProperty == null) { System.Console.WriteLine("Element of type [" + elementType + "] does not have FontFamily property"); return; } var sizeProperty = elementType.GetProperty("FontSize"); if (sizeProperty == null) { System.Console.WriteLine("Element of type [" + elementType + "] does not have FontSize property"); return; } var attrProperty = elementType.GetProperty("FontAttributes"); if (attrProperty == null) { System.Console.WriteLine("Element of type [" + elementType + "] does not have FontAttributes property"); return; } var controlType = Control.GetType(); var fontProperty = controlType.GetProperty("Font"); if (fontProperty != null) { var fontFamily = (string)familyProperty.GetValue(Element); var fontSize = (double)sizeProperty.GetValue(Element); var fontAttributes = (FontAttributes)attrProperty.GetValue(Element); if (fontSize < 0) { if (Control is UIButton) { fontSize = UIFont.ButtonFontSize * Math.Abs(fontSize); } else { fontSize = UIFont.LabelFontSize * Math.Abs(fontSize); } } if (Math.Abs(fontSize) <= double.Epsilon * 10) { fontSize = UIFont.LabelFontSize; } foreach (var effect in Element.Effects) { if (effect is Forms9Patch.EmbeddedResourceFontEffect fontEffect) { var newFont = FontExtensions.BestFont(fontFamily, (float)fontSize, (fontAttributes & FontAttributes.Bold) != 0, (fontAttributes & FontAttributes.Italic) != 0, fontEffect.Assembly); fontProperty.SetValue(Control, newFont, null); return; } } } }
/// <summary> /// Lines the space. /// </summary> /// <returns>The space.</returns> /// <param name="fontFamily">Font family.</param> /// <param name="fontSize">Font size.</param> /// <param name="fontAttributes">Font attributes.</param> public double LineSpace(string fontFamily, double fontSize, FontAttributes fontAttributes) { var font = FontExtensions.BestFont(fontFamily, (nfloat)fontSize, (fontAttributes & FontAttributes.Bold) != 0, (fontAttributes & FontAttributes.Italic) != 0); return(font.Leading); }
internal static NSAttributedString ToNSAttributedString(this F9PFormattedString formattedString, UIFont baseFont, UIColor baseColor) //, EllipsePlacement ellipsePlacement = EllipsePlacement.None, int secondToLastEnd = -1, int lastLineStart = 0, int lastLineEnd = -1, int startLastVisible = -1, int midLastVisible = -1, bool twice=false) { { var text = formattedString?.Text; if (string.IsNullOrEmpty(text)) { return(null); } if (formattedString is HTMLMarkupString hTMLMarkupString) { text = hTMLMarkupString.UnmarkedText; } var result = new NSMutableAttributedString(text); result.AddAttribute(UIStringAttributeKey.Font, baseFont, new NSRange(0, text.Length)); result.AddAttribute(UIStringAttributeKey.ForegroundColor, baseColor, new NSRange(0, text.Length)); #region Layout font-spans (MetaFonts) var metaFonts = new List <MetaFont>(); var baseMetaFont = new MetaFont( baseFont.FamilyName, (float)baseFont.PointSize, (baseFont.FontDescriptor.Traits.SymbolicTrait & UIFontDescriptorSymbolicTraits.Bold) > 0, (baseFont.FontDescriptor.Traits.SymbolicTrait & UIFontDescriptorSymbolicTraits.Italic) > 0); MathMetaFont = MathMetaFont ?? new MetaFont("STIXGeneral", (float)baseFont.PointSize); for (int i = 0; i < text.Length; i++) { if (i + 1 < text.Length && text[i] == '\ud835' && text[i + 1] >= '\udc00' && text[i + 1] <= '\udeff') { metaFonts.Add(new MetaFont(MathMetaFont)); metaFonts.Add(new MetaFont(MathMetaFont)); // there are two because we're using a double byte unicode character i++; } else { metaFonts.Add(new MetaFont(baseMetaFont)); } } #endregion #region Apply non-font Spans foreach (var span in formattedString._spans) { int spanStart = span.Start; int spanEnd = span.End; spanEnd++; if (spanEnd > result.Length) { spanEnd = (int)result.Length - 1; } NSDictionary attr; switch (span.Key) { #region Spans that change UIFont attributes case FontFamilySpan.SpanKey: for (int i = spanStart; i < spanEnd; i++) { metaFonts[i].Family = ((FontFamilySpan)span).FontFamilyName; } break; case FontSizeSpan.SpanKey: for (int i = spanStart; i < spanEnd; i++) { float size = ((FontSizeSpan)span).Size; metaFonts[i].Size = (size < 0 ? metaFonts[i].Size * (-size) : size); } break; case BoldSpan.SpanKey: for (int i = spanStart; i < spanEnd; i++) { metaFonts[i].Bold = true; } break; case ItalicsSpan.SpanKey: for (int i = spanStart; i < spanEnd; i++) { metaFonts[i].Italic = true; } break; case SuperscriptSpan.SpanKey: for (int i = spanStart; i < spanEnd; i++) { metaFonts[i].Baseline = FontBaseline.Superscript; } break; case SubscriptSpan.SpanKey: for (int i = spanStart; i < spanEnd; i++) { metaFonts[i].Baseline = FontBaseline.Subscript; } break; case NumeratorSpan.SpanKey: for (int i = spanStart; i < spanEnd; i++) { metaFonts[i].Baseline = FontBaseline.Numerator; } break; case DenominatorSpan.SpanKey: for (int i = spanStart; i < spanEnd; i++) { metaFonts[i].Baseline = FontBaseline.Denominator; } break; case ActionSpan.SpanKey: attr = new NSMutableDictionary(); attr[UIStringAttributeKey.ForegroundColor] = Xamarin.Forms.Color.Blue.ToUIColor(); attr[UIStringAttributeKey.UnderlineColor] = Xamarin.Forms.Color.Blue.ToUIColor(); attr[UIStringAttributeKey.StrikethroughColor] = Xamarin.Forms.Color.Blue.ToUIColor(); var uAttr = new NSDictionary(UIStringAttributeKey.UnderlineStyle, NSUnderlineStyle.Single); attr[UIStringAttributeKey.UnderlineStyle] = uAttr[UIStringAttributeKey.UnderlineStyle]; result.AddAttributes(attr, new NSRange(spanStart, spanEnd - spanStart)); break; #endregion #region Font Color case FontColorSpan.SpanKey: var fontColorSpan = span as FontColorSpan; attr = new NSMutableDictionary(); attr[UIStringAttributeKey.ForegroundColor] = fontColorSpan.Color.ToUIColor(); attr[UIStringAttributeKey.UnderlineColor] = fontColorSpan.Color.ToUIColor(); attr[UIStringAttributeKey.StrikethroughColor] = fontColorSpan.Color.ToUIColor(); result.AddAttributes(attr, new NSRange(spanStart, spanEnd - spanStart)); break; #endregion #region Background Color case BackgroundColorSpan.SpanKey: var backgroundColorSpan = span as BackgroundColorSpan; attr = new NSDictionary(UIStringAttributeKey.BackgroundColor, backgroundColorSpan.Color.ToUIColor()); result.AddAttributes(attr, new NSRange(spanStart, spanEnd - spanStart)); break; #endregion #region Underline case UnderlineSpan.SpanKey: attr = new NSDictionary(UIStringAttributeKey.UnderlineStyle, NSUnderlineStyle.Single); result.AddAttributes(attr, new NSRange(spanStart, spanEnd - spanStart)); break; #endregion #region Strikethrough case StrikethroughSpan.SpanKey: attr = new NSDictionary(UIStringAttributeKey.StrikethroughStyle, NSUnderlineStyle.Single); result.AddAttributes(attr, new NSRange(spanStart, spanEnd - spanStart)); break; #endregion } } #endregion #region Apply MetaFonts // run through MetaFonts to see if we need to set new Font attributes var lastMetaFont = baseMetaFont; int startIndex = 0; for (int i = 0; i < metaFonts.Count; i++) { var metaFont = metaFonts[i]; if (lastMetaFont != metaFont) { // we are at the start of a new span if (i > 0 && lastMetaFont != baseMetaFont) { // and we've been inside of a metaFont span var font = FontExtensions.BestFont(lastMetaFont, baseFont); var size = lastMetaFont.Size; var range = new NSRange(startIndex, i - startIndex); switch (lastMetaFont.Baseline) { case FontBaseline.Superscript: result.AddAttributes(new NSDictionary(UIStringAttributeKey.BaselineOffset, size / 2.22f, UIStringAttributeKey.Font, font), range); break; case FontBaseline.Subscript: result.AddAttributes(new NSDictionary(UIStringAttributeKey.BaselineOffset, -size / 6f, UIStringAttributeKey.Font, font), range); break; case FontBaseline.Numerator: result.AddAttributes(new NSDictionary(UIStringAttributeKey.BaselineOffset, size / 4f, UIStringAttributeKey.Font, font), range); break; //case FontBaseline.Denominator: // result.AddAttributes(new NSDictionary(UIStringAttributeKey.BaselineOffset, -size / 6f, UIStringAttributeKey.Font, font), range); // break; default: result.AddAttribute(UIStringAttributeKey.Font, font, range); break; } //System.Diagnostics.Debug.WriteLine("\tRANGE["+range.Location+","+range.Length+"]"); } lastMetaFont = metaFont; startIndex = i; } } if (lastMetaFont != baseMetaFont) { // and we've been inside of a metaFont span var font = FontExtensions.BestFont(lastMetaFont, baseFont); var size = lastMetaFont.Size; var range = new NSRange(startIndex, metaFonts.Count - startIndex); switch (lastMetaFont.Baseline) { case FontBaseline.Superscript: result.AddAttributes(new NSDictionary(UIStringAttributeKey.BaselineOffset, size / 2.22f, UIStringAttributeKey.Font, font), range); break; case FontBaseline.Subscript: result.AddAttributes(new NSDictionary(UIStringAttributeKey.BaselineOffset, -size / 6f, UIStringAttributeKey.Font, font), range); break; case FontBaseline.Numerator: result.AddAttributes(new NSDictionary(UIStringAttributeKey.BaselineOffset, size / 4f, UIStringAttributeKey.Font, font), range); break; //case FontBaseline.Denominator: // result.AddAttributes(new NSDictionary(UIStringAttributeKey.BaselineOffset, -size / 6f, UIStringAttributeKey.Font, font), range); // break; default: result.AddAttribute(UIStringAttributeKey.Font, font, range); break; } //System.Diagnostics.Debug.WriteLine("\tRANGE[" + range.Location + "," + range.Length + "]"); } #endregion return(result); }