/// <summary>
 /// Выполнить команду.
 /// </summary>
 /// <param name="command">Команда.</param>
 /// <returns>Остаток для последующего вызова.</returns>
 public ITextRenderCommand ExecuteCommand(ITextRenderCommand command)
 {
     if (command == null || command.Content == null || command.Attributes == null || command.Content.Id == null)
     {
         return null;
     }
     if (!CommonTextRenderContent.Text.Equals(command.Content.Id, StringComparison.OrdinalIgnoreCase))
     {
         ExecuteNonText(command);
         return null;
     }
     var txt = command.Content as ITextRenderTextContent;
     if (txt != null && txt.Text != null)
     {
         var remText = ExectuteText(command.Attributes, txt.Text);
         if (string.IsNullOrEmpty(remText))
         {
             return null;
         }
         return new TextRenderCommand(command.Attributes, new TextRenderTextContent(remText));
     }
     return null;
 }
 /// <summary>
 /// Выполнить не текстовую команду.
 /// </summary>
 /// <param name="command">Команда.</param>
 protected virtual void ExecuteNonText(ITextRenderCommand command)
 {
     if (CommonTextRenderContent.LineBreak.Equals(command.Content.Id))
     {
         NewLine(command.Attributes);
     }
 }
 private double GetElementWidth(ITextRenderCommand command)
 {
     return WidthCache.GetValue(Factory.GetCacheKey(command), () => Factory.MeasureCommand(command).Width);
 }
 private void AddElementToCanvas(ITextRenderCommand command)
 {
     if (command == null)
     {
         return;
     }
     Size size;
     if (IsMeasureMode)
     {
         size = Factory.MeasureCommand(command);
     }
     else
     {
         size = Factory.DrawCommand(new Point() { X = LineWidth, Y = Top }, Session, command);
     }
     LineWidth += size.Width;
     if (LineHeight < size.Height)
     {
         LineHeight = size.Height;
         SynCanvasHeight();
     }
     FirstInLine = false;
 }
 private double GetElementWidth(string key, ITextRenderCommand command)
 {
     return GetElementWidth(key, () => Factory.Create(command));
 }
 private void Execute(ITextRenderCommand command)
 {
     int counter = 1000;
     while (command != null && counter > 0 && !ExceedLines)
     {
         counter--;
         command = Executor.ExecuteCommand(command);
     }
 }
 private Func<FrameworkElement> ExtractElement(string key, ITextRenderCommand command)
 {
     return ExtractElement(key, () => Factory.Create(command));
 }
 private FrameworkElement GetElement(string key, ITextRenderCommand command)
 {
     return GetElement(key, () => Factory.Create(command));
 }
 private string GetElementKey(ITextRenderCommand command)
 {
     return Factory.GetCacheKey(command);
 }
 /// <summary>
 /// Инициализирует новый экземпляр класса <see cref="T:System.Object"/>.
 /// </summary>
 public RenderProgram(ITextRenderCommand[] commands)
 {
     if (commands == null) throw new ArgumentNullException(nameof(commands));
     this.commands = commands;
 }
        /// <summary>
        /// Создать элемент.
        /// </summary>
        /// <param name="command">Команда.</param>
        /// <returns>Элемент.</returns>
        public FrameworkElement Create(ITextRenderCommand command)
        {
            count++;
            string text;
            var textCnt = command.Content as ITextRenderTextContent;
            if (textCnt != null)
            {
                text = textCnt.Text ?? "";
            }
            else
            {
                text = "";
            }
            var r = new TextBlock()
            {
                Foreground = Application.Current.Resources["PostNormalTextBrush"] as Brush,
                TextWrapping = TextWrapping.NoWrap,
                TextTrimming = TextTrimming.None,
                FontSize = StyleManager.Text.PostFontSize,
                TextLineBounds = TextLineBounds.Full,
                IsTextSelectionEnabled = false,
                TextAlignment = TextAlignment.Left
            };

            FrameworkElement result = r;

            Border b = new Border();
            bool needBorder = false;

            Grid g = new Grid();
            bool needGrid = false;

            Grid g2 = new Grid();
            bool needOuterGrid = false;


            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Bold))
            {
                r.FontWeight = FontWeights.Bold;
            }
            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Italic))
            {
                r.FontStyle = FontStyle.Italic;
            }
            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Fixed))
            {
                r.FontFamily = new FontFamily("Courier New");
            }
            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Spoiler))
            {
                needBorder = true;
                b.Background = Application.Current.Resources["PostSpoilerBackgroundBrush"] as Brush;
                r.Foreground = Application.Current.Resources["PostSpoilerTextBrush"] as Brush;
            }
            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Quote))
            {
                r.Foreground = Application.Current.Resources["PostQuoteTextBrush"] as Brush;
            }
            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Link))
            {
                r.Foreground = Application.Current.Resources["PostLinkTextBrush"] as Brush;
            }

            b.BorderBrush = r.Foreground;
            b.BorderThickness = new Thickness(0);

            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Undeline) || command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Link))
            {
                needBorder = true;
                b.BorderThickness = new Thickness(b.BorderThickness.Left, b.BorderThickness.Top, b.BorderThickness.Right, 1.2);
            }
            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Overline))
            {
                needBorder = true;
                b.BorderThickness = new Thickness(b.BorderThickness.Left, 1.2, b.BorderThickness.Right, b.BorderThickness.Bottom);
            }

            Border strikeBorder = null;

            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Strikethrough))
            {
                needGrid = true;
                strikeBorder = new Border()
                {
                    Background = r.Foreground,
                    Height = 1.2,
                    HorizontalAlignment = HorizontalAlignment.Stretch,
                    VerticalAlignment = VerticalAlignment.Top,
                };
                g.Children.Add(strikeBorder);
            }
            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Subscript) || command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Superscript))
            {
                needOuterGrid = true;
                r.Measure(new Size(0, 0));
                var fh = r.ActualHeight;
                r.FontSize = r.FontSize * 2.0 / 3.0;
                r.Measure(new Size(0, 0));
                var fh2 = r.ActualHeight;
                var delta = fh - fh2;
                if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Subscript) &&
                    !command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Superscript))
                {
                    g2.Padding = new Thickness(0, delta, 0, 0);
                }
                else if (!command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Subscript) &&
                         command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Superscript))
                {
                    g2.Padding = new Thickness(0, 0, 0, delta);
                }
                else
                {
                    g2.Padding = new Thickness(0, delta / 2, 0, delta / 2);
                }
            }

            var spaceWidth = GetOWidth(command.Attributes, r);

            int endSpaces = 0;
            var s2 = text;
            while (s2.EndsWith(" "))
            {
                endSpaces++;
                s2 = s2.Substring(0, s2.Length - 1);
            }

            r.Text = s2;
            r.Measure(new Size(0, 0));

            r.Height = r.ActualHeight;
            r.Width = r.ActualWidth + endSpaces * spaceWidth;

            if (strikeBorder != null)
            {
                var oh = r.ActualHeight;
                const double koef = 0.6;
                strikeBorder.Margin = new Thickness(0, koef * oh, 0, 0);
            }

            if (needGrid)
            {
                g.Height = result.Height;
                g.Width = result.Width;
                g.Children.Add(result);
                result = g;
            }
            if (needBorder)
            {
                b.Height = result.Height;
                b.Width = result.Width;
                b.Child = result;
                result = b;
            }
            if (needOuterGrid)
            {
                g2.Height = result.Height + g2.Padding.Bottom + g2.Padding.Top;
                g2.Width = result.Width;
                g2.Children.Add(result);
                result = g2;
            }

            if (command.Attributes.Attributes.ContainsKey(CommonTextRenderAttributes.Link))
            {
                var linkAttribute = command.Attributes.Attributes[CommonTextRenderAttributes.Link] as ITextRenderLinkAttribute;
                if (linkAttribute != null)
                {
                    RenderLinkClickHelper.SetupLinkActions(result, linkAttribute, linkClickCallback);
                }
            }

            return result;
        }
 /// <summary>
 /// Создать элемент.
 /// </summary>
 /// <param name="command">Команда.</param>
 /// <returns>Элемент.</returns>
 FrameworkElement ICanvasElementFactory.Create(ITextRenderCommand command)
 {
     return Create(command);
 }
 /// <summary>
 /// Получить ключ кэша.
 /// </summary>
 /// <param name="command">Команда.</param>
 /// <returns>Ключ кэша.</returns>
 public string GetCacheKey(ITextRenderCommand command)
 {
     return command.GetCacheKey(isNarrow);
 }