Beispiel #1
0
        public static void DrawMessage(object graphics, Common.Message message, int xOffset, int yOffset,
                                       Selection selection, int currentLine, bool drawText, List <GifEmoteState> gifEmotesOnScreen = null,
                                       bool allowMessageSeperator = true)
        {
            message.X = xOffset;
            message.Y = yOffset;

            var g = (Graphics)graphics;

            var spaceWidth =
                GuiEngine.Current.MeasureStringSize(g, FontType.Medium, " ").Width;

            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.None;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            message.X = xOffset;
            var textColor = App.ColorScheme.Text;

            Brush highlightBrush = null;

            if (message.HasAnyHighlightType(HighlightType.SearchResult))
            {
                highlightBrush = App.ColorScheme.ChatBackgroundSearchResult;
            }
            else if (message.HasAnyHighlightType(HighlightType.Highlighted))
            {
                highlightBrush = App.ColorScheme.ChatBackgroundHighlighted;
            }
            else if (message.HasAnyHighlightType(HighlightType.UsernameHighlighted))
            {
                highlightBrush = App.ColorScheme.ChatBackgroundUsernameHighlighted;
            }
            else if (message.HasAnyHighlightType(HighlightType.Resub))
            {
                highlightBrush = App.ColorScheme.ChatBackgroundResub;
            }
            else if (message.HasAnyHighlightType(HighlightType.Whisper))
            {
                highlightBrush = App.ColorScheme.ChatBackgroundWhisper;
            }
            else if (message.HasAnyHighlightType(HighlightType.HighlightedMessage))
            {
                highlightBrush = App.ColorScheme.ChatBackgroundHighlightedMessage;
            }

            if (highlightBrush != null)
            {
                g.FillRectangle(highlightBrush, 0, yOffset, g.ClipBounds.Width, message.Height);
            }

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;

            for (var i = 0; i < message.Words.Count; i++)
            {
                var word = message.Words[i];

                if (word.Type == SpanType.Text)
                {
                    if (drawText)
                    {
                        var font = Fonts.GetFont(word.Font);

                        var color = textColor;

                        if (word.Color.HasValue)
                        {
                            var hsl = word.Color.Value;

                            if (App.ColorScheme.IsLightTheme)
                            {
                                if (hsl.Luminosity > 0.5f)
                                {
                                    hsl = hsl.WithLuminosity(0.5f);
                                }
                            }
                            else
                            {
                                if (hsl.Luminosity < 0.3f)
                                {
                                    hsl = hsl.WithLuminosity(0.3f);
                                }
                            }

                            float r, _g, b;
                            hsl.ToRGB(out r, out _g, out b);
                            color = Color.FromArgb((int)(r * 255), (int)(_g * 255), (int)(b * 255));
                        }

                        if (word.SplitSegments == null)
                        {
                            TextRenderer.DrawText(g, (string)word.Value, font,
                                                  new Point(xOffset + word.X, yOffset + word.Y), color, App.DefaultTextFormatFlags);
                        }
                        else
                        {
                            var segments = word.SplitSegments;
                            for (var x = 0; x < segments.Length; x++)
                            {
                                TextRenderer.DrawText(g, segments[x].Item1, font,
                                                      new Point(xOffset + segments[x].Item2.X, yOffset + segments[x].Item2.Y), color,
                                                      App.DefaultTextFormatFlags);
                            }
                        }
                    }
                }
                else if (word.Type == SpanType.LazyLoadedImage)
                {
                    var emote = (LazyLoadedImage)word.Value;
                    var img   = (ChatterinoImage)emote.Image;
                    if (img != null)
                    {
                        try
                        {
                            lock (img) {
                                img.DrawImage(g, word.X + xOffset, word.Y + yOffset, word.Width, word.Height);
                            }
                        }
                        catch { }
                    }
                }
            }

            Action <int, bool, LazyLoadedImage> addWordToGifList = (i, selected, emote) =>
            {
                var word  = message.Words[i];
                var words = new List <Word>();

                for (var j = i - 1; j >= 0; j--)
                {
                    if (message.Words[j].Intersects(word))
                    {
                        words.Insert(0, message.Words[j]);
                    }
                    else
                    {
                        break;
                    }
                }

                words.Add(word);

                for (var j = i + 1; j < message.Words.Count; j++)
                {
                    if (message.Words[j].Intersects(word))
                    {
                        words.Add(message.Words[j]);
                    }
                    else
                    {
                        break;
                    }
                }

                gifEmotesOnScreen?.Add(new GifEmoteState(word.X + xOffset, word.Y + yOffset, word.Width, word.Height, words, selected, message.HighlightType, message.Disabled, yOffset, xOffset));

                GuiEngine.Current.GifEmotesOnScreen.Add(emote);
            };

            if (selection != null && !selection.IsEmpty && selection.First.MessageIndex <= currentLine &&
                selection.Last.MessageIndex >= currentLine)
            {
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;

                var first = selection.First;
                var last  = selection.Last;
                for (var i = 0; i < message.Words.Count; i++)
                {
                    var word = message.Words[i];

                    if ((currentLine != first.MessageIndex || i >= first.WordIndex) &&
                        (currentLine != last.MessageIndex || i <= last.WordIndex))
                    {
                        if (word.Type == SpanType.Text)
                        {
                            for (var j = 0; j < (word.SplitSegments?.Length ?? 1); j++)
                            {
                                if ((first.MessageIndex == currentLine && first.WordIndex == i && first.SplitIndex > j) ||
                                    (last.MessageIndex == currentLine && last.WordIndex == i && last.SplitIndex < j))
                                {
                                    continue;
                                }

                                var split = word.SplitSegments?[j];
                                var text  = split?.Item1 ?? (string)word.Value;
                                var rect  = split?.Item2 ??
                                            new CommonRectangle(word.X, word.Y, word.Width, word.Height);

                                var textLength = text.Length;

                                var offset = (first.MessageIndex == currentLine && first.SplitIndex == j &&
                                              first.WordIndex == i)
                                    ? first.CharIndex
                                    : 0;
                                var length = ((last.MessageIndex == currentLine && last.SplitIndex == j &&
                                               last.WordIndex == i)
                                                 ? last.CharIndex
                                                 : textLength) - offset;

                                if (offset == 0 && length == text.Length)
                                {
                                    g.FillRectangle(_selectionBrush, rect.X + xOffset, rect.Y + yOffset,
                                                    GuiEngine.Current.MeasureStringSize(App.UseDirectX ? null : g, word.Font, text)
                                                    .Width + spaceWidth - 1, rect.Height);
                                }
                                else if (offset == text.Length)
                                {
                                    g.FillRectangle(_selectionBrush, rect.X + xOffset + rect.Width, rect.Y + yOffset,
                                                    spaceWidth, rect.Height);
                                }
                                else
                                {
                                    g.FillRectangle(_selectionBrush,
                                                    rect.X + xOffset +
                                                    (offset == 0
                                            ? 0
                                            : GuiEngine.Current.MeasureStringSize(App.UseDirectX ? null : g, word.Font,
                                                                                  text.Remove(offset)).Width),
                                                    rect.Y + yOffset,
                                                    GuiEngine.Current.MeasureStringSize(App.UseDirectX ? null : g, word.Font,
                                                                                        text.Substring(offset, length)).Width +
                                                    ((last.MessageIndex > currentLine || last.SplitIndex > j || last.WordIndex > i)
                                            ? spaceWidth
                                            : 0),
                                                    rect.Height);
                                }
                            }
                        }
                        //else if (word.Type == SpanType.Image)
                        //{
                        //    var textLength = 2;

                        //    var offset = (first.MessageIndex == currentLine && first.WordIndex == i)
                        //        ? first.CharIndex
                        //        : 0;
                        //    var length = ((last.MessageIndex == currentLine && last.WordIndex == i)
                        //                     ? last.CharIndex
                        //                     : textLength) - offset;

                        //    g.FillRectangle(_selectionBrush, word.X + xOffset + (offset == 0 ? 0 : word.Width),
                        //        word.Y + yOffset,
                        //        (offset == 0 ? word.Width : 0) + (offset + length == 2 ? spaceWidth : 0) - 1,
                        //        word.Height);
                        //}
                        else if (word.Type == SpanType.LazyLoadedImage)
                        {
                            var textLength = 2;

                            var offset = (first.MessageIndex == currentLine && first.WordIndex == i)
                                ? first.CharIndex
                                : 0;
                            var length = ((last.MessageIndex == currentLine && last.WordIndex == i)
                                             ? last.CharIndex
                                             : textLength) - offset;

                            var emote = (LazyLoadedImage)word.Value;

                            if (emote.IsAnimated)
                            {
                                addWordToGifList(i, true, emote);
                            }
                            else
                            {
                                g.FillRectangle(_selectionBrush, word.X + xOffset, word.Y + yOffset,
                                                word.Width + spaceWidth - 1, word.Height);
                            }
                        }
                    }
                    else
                    {
                        if (word.Type == SpanType.LazyLoadedImage)
                        {
                            var emote = (LazyLoadedImage)word.Value;
                            if (emote.IsAnimated)
                            {
                                addWordToGifList(i, true, emote);
                            }
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < message.Words.Count; i++)
                {
                    var word = message.Words[i];
                    if (word.Type == SpanType.LazyLoadedImage)
                    {
                        var emote = (LazyLoadedImage)word.Value;
                        if (emote.IsAnimated)
                        {
                            addWordToGifList(i, false, emote);
                        }
                    }
                }
            }

            if (allowMessageSeperator && AppSettings.ChatSeperateMessages)
            {
                g.DrawLine(App.ColorScheme.ChatMessageSeperatorBorder, 0, yOffset + 1, message.Width + 128, yOffset + 1);
                g.DrawLine(App.ColorScheme.ChatMessageSeperatorBorderInner, 0, yOffset, message.Width + 128, yOffset);
            }
        }
Beispiel #2
0
        public CommonSize MeasureStringSize(object graphics, FontType font, string text)
        {
            var isGdi = graphics is Graphics;

            var sizeCache = (isGdi ? gdiSizeCaches : dwSizeCaches).GetOrAdd(font, f =>
            {
                int lineHeight;

                if (isGdi)
                {
                    lineHeight = TextRenderer.MeasureText((Graphics)graphics, "X", Fonts.GetFont(font), Size.Empty, App.DefaultTextFormatFlags).Height;
                }
                else
                {
                    using (var layout = new SharpDX.DirectWrite.TextLayout(Fonts.Factory, "X", Fonts.GetTextFormat(font), 1000000, 1000000))
                    {
                        var metrics = layout.Metrics;
                        lineHeight  = (int)metrics.Height;
                        //lineHeight = (int)Math.Ceiling(Fonts.GetTextFormat(font).FontSize);
                    }
                }

                return(Tuple.Create(new ConcurrentDictionary <string, CommonSize>(), new ConcurrentStack <string>(), lineHeight));
            });

            return(sizeCache.Item1.GetOrAdd(text, s =>
            {
                if (sizeCache.Item2.Count >= sizeCacheStackLimit)
                {
                    string value;
                    if (sizeCache.Item2.TryPop(out value))
                    {
                        CommonSize _s;
                        sizeCache.Item1.TryRemove(value, out _s);
                    }
                }

                sizeCache.Item2.Push(s);

                if (isGdi)
                {
                    var size = TextRenderer.MeasureText((IDeviceContext)graphics, text, Fonts.GetFont(font), Size.Empty, App.DefaultTextFormatFlags);
                    return new CommonSize(size.Width, sizeCache.Item3);
                }
                else
                {
                    using (var layout = new SharpDX.DirectWrite.TextLayout(Fonts.Factory, text, Fonts.GetTextFormat(font), 1000000, 1000000))
                    {
                        var metrics = layout.Metrics;

                        return new CommonSize((int)metrics.WidthIncludingTrailingWhitespace, sizeCache.Item3);
                    }
                }
            }));
        }