private NSAttributedString GetAttributedText(NSAttributedStringTarget target) { if (target == NSAttributedStringTarget.UILabel && UseInlinesFastPath && LineHeight == 0 && CharacterSpacing == 0) { // Fast path in case everything can be set directly on UILabel without using NSAttributedString. return(null); } else { var mutableAttributedString = new NSMutableAttributedString(Text); mutableAttributedString.BeginEditing(); mutableAttributedString.AddAttributes(GetAttributes(target), new NSRange(0, mutableAttributedString.Length)); // Apply Inlines foreach (var inline in GetEffectiveInlines()) { mutableAttributedString.AddAttributes(inline.inline.GetAttributes(), new NSRange(inline.start, inline.end - inline.start)); } mutableAttributedString.EndEditing(); return(mutableAttributedString); } }
private UIStringAttributes GetAttributes(NSAttributedStringTarget target) { var attributes = new UIStringAttributes(); // We only apply these values to NSTextStorage, as they're already applied to UILabel. // See: UpdateFont, UpdateTextColor, etc. if (target == NSAttributedStringTarget.NSTextStorage) { attributes.Font = _currentFont; attributes.ForegroundColor = _currentColor; } if (target == NSAttributedStringTarget.NSTextStorage || LineHeight != 0) { var paragraphStyle = new NSMutableParagraphStyle() { MinimumLineHeight = (nfloat)LineHeight, Alignment = TextAlignment.ToNativeTextAlignment(), LineBreakMode = GetLineBreakMode(), }; // For unknown reasons, the LineBreakMode must be set to WordWrap // when applied to a NSTextStorage for text to wrap (but not when applied to a UILabel). if (target == NSAttributedStringTarget.NSTextStorage) { paragraphStyle.LineBreakMode = UILineBreakMode.WordWrap; } if (LineStackingStrategy != LineStackingStrategy.MaxHeight) { paragraphStyle.MaximumLineHeight = (nfloat)LineHeight; } attributes.ParagraphStyle = paragraphStyle; if (Font != null) { // iOS puts text at the bottom of the line box, whereas Windows puts it at the top. // Empirically this offset gives similar positioning to Windows. // Note: Descender is typically a negative value. var verticalOffset = LineHeight - Font.LineHeight + Font.Descender; // For unknown reasons, the verticalOffset must be divided by 2 // when applied to a UILabel (but not when applied to a NSTextStorage). if (target == NSAttributedStringTarget.UILabel) { verticalOffset /= 2; } // Because we're trying to move the text up (toward the top of the line box), // we only set BaselineOffset to a positive value. // A negative value indicates that the the text is already bottom-aligned. attributes.BaselineOffset = Math.Max(0, (float)verticalOffset); } } if (CharacterSpacing != 0) { //CharacterSpacing is in 1/1000 of an em, iOS KerningAdjustment is in points. 1 em = 12 points attributes.KerningAdjustment = (CharacterSpacing / 1000f) * 12; } return(attributes); }