private static YogaSize MeasureText(ReactTextShadowNode textNode, YogaNode node, float width, YogaMeasureMode widthMode, float height, YogaMeasureMode heightMode) { // TODO: Measure text with DirectWrite or other API that does not // require dispatcher access. Currently, we're instantiating a // second CoreApplicationView (that is never activated) and using // its Dispatcher thread to calculate layout. var textBlock = new TextBlock { TextAlignment = TextAlignment.Left, TextWrapping = TextWrapping.Wrap, TextTrimming = TextTrimming.CharacterEllipsis, }; textNode.UpdateTextBlockCore(textBlock, true); for (var i = 0; i < textNode.ChildCount; ++i) { var child = textNode.GetChildAt(i); textBlock.Inlines.Add(ReactInlineShadowNodeVisitor.Apply(child)); } var normalizedWidth = YogaConstants.IsUndefined(width) ? double.PositiveInfinity : width; var normalizedHeight = YogaConstants.IsUndefined(height) ? double.PositiveInfinity : height; textBlock.Measure(new Size(normalizedWidth, normalizedHeight)); return(MeasureOutput.Make( (float)Math.Ceiling(textBlock.DesiredSize.Width), (float)Math.Ceiling(textBlock.DesiredSize.Height))); }
private static void buildSpannedFromTextCSSNode(ReactTextShadowNode textShadowNode, ref string sb) { if (textShadowNode._textProperty != null) { sb += textShadowNode._textProperty; } if (textShadowNode._text != null) { sb += textShadowNode._text; } for (int i = 0, length = textShadowNode.TotalNativeChildren; i < length; i++) { ReactShadowNode child = textShadowNode.GetChildAt(i); if (child is ReactTextShadowNode) { buildSpannedFromTextCSSNode((ReactTextShadowNode)child, ref sb); } child.MarkUpdateSeen(); } if (textShadowNode._textProperty != null) { sb += _textPropertyTail; } }
/// <summary> /// Formats an inline instance with shadow properties. /// </summary> /// <param name="textNode">The text shadow node.</param> /// <param name="inline">The inline.</param> /// <param name="measureOnly">Signals if the operation is used only for measurement.</param> protected static void FormatInline(ReactTextShadowNode textNode, Inline inline, bool measureOnly) { if (!measureOnly && textNode._color.HasValue) { inline.Foreground = new SolidColorBrush(ColorHelpers.Parse(textNode._color.Value)); } if (textNode._fontSize != FontSizeUnset) { var fontSize = textNode._fontSize; inline.FontSize = fontSize; } if (textNode._fontStyle.HasValue) { var fontStyle = textNode._fontStyle.Value; inline.FontStyle = fontStyle; } if (textNode._fontWeight.HasValue) { var fontWeight = textNode._fontWeight.Value; inline.FontWeight = fontWeight; } if (textNode._fontFamily != null) { var fontFamily = new FontFamily(textNode._fontFamily); inline.FontFamily = fontFamily; } }
protected static string fromTextCSSNode(ReactTextShadowNode textCSSNode) { string span = ""; buildSpannedFromTextCSSNode(textCSSNode, ref span); if (!span.StartsWith("<span")) { span = _textPropertyHead + span + _textPropertyTail; } return(span); }
private static YogaSize MeasureText(ReactTextShadowNode textNode, YogaNode node, float width, YogaMeasureMode widthMode, float height, YogaMeasureMode heightMode) { Log.Info(ReactConstants.Tag, "MeasureText node=" + textNode.ReactTag); // This is not a terribly efficient way of projecting the height of // the text elements. It requires that we have access to the // dispatcher in order to do measurement, which, for obvious // reasons, can cause perceived performance issues as it will block // the UI thread from handling other work. // // TODO: determine another way to measure text elements. var task = DispatcherHelpers.CallOnDispatcher(() => { if (textView == null) { textView = new ReactTextView(ReactProgram.RctWindow); textView.LineWrapType = WrapType.Mixed; } var normalizedWidth = YogaConstants.IsUndefined(width) ? ReactProgram.RctWindow.ScreenSize.Width : width; var normalizedHeight = YogaConstants.IsUndefined(height) ? ReactProgram.RctWindow.ScreenSize.Height : height; textView.Resize((int)normalizedWidth, (int)normalizedHeight); textView.Text = textNode._preparedSpannableText; var textPartObject = textView.EdjeObject["elm.text"]; if (textPartObject == null) { throw new Exception("Invalid ReactTextView.EdjeObject[\"elm.text\"]"); } Size size = textPartObject.TextBlockFormattedSize; Log.Info(ReactConstants.Tag, "MeasureText result : width: " + size.Width + " height:" + size.Height); //textView.Unrealize(); return(MeasureOutput.Make( (float)size.Width, (float)size.Height)); }); return(task.Result); }
private static YogaSize MeasureText(ReactTextShadowNode textNode, YogaNode node, float width, YogaMeasureMode widthMode, float height, YogaMeasureMode heightMode) { // This is not a terribly efficient way of projecting the height of // the text elements. It requires that we have access to the // dispatcher in order to do measurement, which, for obvious // reasons, can cause perceived performance issues as it will block // the UI thread from handling other work. // // TODO: determine another way to measure text elements. var task = DispatcherHelpers.CallOnDispatcher(() => { var textBlock = new RichTextBlock { TextWrapping = TextWrapping.Wrap, TextAlignment = TextAlignment.DetectFromContent, TextTrimming = TextTrimming.CharacterEllipsis, }; textNode.UpdateTextBlockCore(textBlock, true); var block = new Paragraph(); for (var i = 0; i < textNode.ChildCount; ++i) { var child = textNode.GetChildAt(i); block.Inlines.Add(ReactInlineShadowNodeVisitor.Apply(child)); } textBlock.Blocks.Add(block); var normalizedWidth = YogaConstants.IsUndefined(width) ? double.PositiveInfinity : width; var normalizedHeight = YogaConstants.IsUndefined(height) ? double.PositiveInfinity : height; textBlock.Measure(new Size(normalizedWidth, normalizedHeight)); return(MeasureOutput.Make( (float)Math.Ceiling(textBlock.DesiredSize.Width), (float)Math.Ceiling(textBlock.DesiredSize.Height))); }); return(task.Result); }