Esempio n. 1
0
        // return true if control needs to be redrawn
        public bool CalculateBounds(object graphics, int width, bool enableHatEmotes)
        {
            var emotesChanged = EmoteBoundsChanged;
            var redraw        = false;

            var mediumTextLineHeight = GuiEngine.Current.MeasureStringSize(null, FontType.Medium, "X").Height;

            if (Width != width)
            {
                Width  = width;
                redraw = true;
            }

            // check if any words need to be recalculated
            if (emotesChanged || measureText || _measureImages)
            {
                foreach (var word in Words)
                {
                    if (word.Type == SpanType.Text)
                    {
                        if (measureText)
                        {
                            var size = GuiEngine.Current.MeasureStringSize(graphics, word.Font, (string)word.Value);
                            word.Width  = size.Width;
                            word.Height = size.Height;
                        }
                    }
                    else if (word.Type == SpanType.LazyLoadedImage)
                    {
                        if (emotesChanged || _measureImages)
                        {
                            var emote = word.Value as LazyLoadedImage;
                            var image = emote?.Image;
                            if (image == null)
                            {
                                word.Width = word.Height = 16;
                            }
                            else
                            {
                                var size = GuiEngine.Current.GetImageSize(image);

                                double w = size.Width, h = size.Height;

                                if (emote.IsEmote)
                                {
                                    if (AppSettings.EmoteScaleByLineHeight)
                                    {
                                        w = size.Width * ((float)mediumTextLineHeight / size.Height);
                                        h = mediumTextLineHeight;
                                    }
                                    else
                                    {
                                        w *= emote.Scale;
                                        h *= emote.Scale;
                                    }

                                    w = w * AppSettings.EmoteScale;
                                    h = h * AppSettings.EmoteScale;
                                }

                                word.Width  = (int)w;
                                word.Height = (int)h;
                            }
                        }
                    }
                }

                measureText    = false;
                _measureImages = false;

                redraw = true;
            }

            if (redraw)
            {
                var x = 0;
                var y = 4;
                var lineStartIndex = 0;

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

                var i = 0;

                Func <int> fixCurrentLineHeight = () =>
                {
                    var lineHeight = 0;

                    for (var j = lineStartIndex; j < i; j++)
                    {
                        var h = Words[j].Height;
                        lineHeight = h > lineHeight ? h : lineHeight;
                    }

                    for (var j = lineStartIndex; j < i; j++)
                    {
                        var word = Words[j];
                        if (j == lineStartIndex && word.Type == SpanType.Text && word.SplitSegments != null)
                        {
                            var segment = word.SplitSegments[word.SplitSegments.Length - 1];
                            var rec     = segment.Item2;
                            word.SplitSegments[word.SplitSegments.Length - 1] = Tuple.Create(segment.Item1, new CommonRectangle(rec.X, rec.Y + lineHeight - word.Height, rec.Width, rec.Height));
                        }
                        else
                        {
                            word.Y += lineHeight - word.Height;
                        }
                    }

                    return(lineHeight);
                };

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

                    word.SplitSegments = null;

                    Margin margin = null;

                    if (word.Type == SpanType.LazyLoadedImage && enableHatEmotes && (i > 0 && Words[i - 1].Type != SpanType.Text))
                    {
                        var img = (LazyLoadedImage)word.Value;

                        if (img.IsHat)
                        {
#warning emote size
                            x -= word.Width + 2;
                        }
                        else if (img.Margin != null)
                        {
                            margin = img.Margin;
                        }
                    }

                    // word wrapped text
                    if (word.Width > width && word.Type == SpanType.Text && ((string)word.Value).Length > 2)
                    {
                        y += fixCurrentLineHeight();

                        lineStartIndex = i;

                        word.X = 0;
                        word.Y = y;

                        var text       = (string)word.Value;
                        var startIndex = 0;
                        var items      = new List <Tuple <string, CommonRectangle> >();

                        string s;

                        var widths = word.CharacterWidths;

                        // calculate word widths
                        if (widths == null)
                        {
                            widths = new int[text.Length];

                            var lastW = 0;
                            for (var j = 0; j < text.Length; j++)
                            {
                                var w = GuiEngine.Current.MeasureStringSize(graphics, word.Font, text.Remove(j)).Width;
                                widths[j] = w - lastW;
                                lastW     = w;
                            }

                            word.CharacterWidths = widths;
                        }

                        // create word splits
                        {
                            var w = widths[0];

                            for (var j = 1; j < text.Length; j++)
                            {
                                w += widths[j];
                                if (w > width - spaceWidth - spaceWidth - spaceWidth)
                                {
                                    items.Add(Tuple.Create(text.Substring(startIndex, j - startIndex), new CommonRectangle(0, y, w, word.Height)));
                                    startIndex = j;
                                    y         += word.Height;
                                    w          = 0;
                                }
                            }

                            s = text.Substring(startIndex);

                            for (var j = startIndex; j < text.Length; j++)
                            {
                                w += widths[j];
                            }

                            items.Add(Tuple.Create(s, new CommonRectangle(0, y, w, word.Height)));
                        }

                        x = GuiEngine.Current.MeasureStringSize(graphics, word.Font, s).Width + spaceWidth;

                        if (items.Count > 1)
                        {
                            word.SplitSegments = items.ToArray();
                        }
                    }
                    // word in new line
                    else if (word.Width > width - x)
                    {
                        y += fixCurrentLineHeight();

                        word.X = 0 + (margin?.Left ?? 0);
                        word.Y = y + (margin?.Top ?? 0);

                        x = word.Width + spaceWidth + (margin == null ? 0 : (margin.Left + margin.Right));

                        lineStartIndex = i;
                    }
                    // word fits in current line
                    else
                    {
                        word.X = x + (margin?.Left ?? 0);
                        word.Y = y + (margin?.Top ?? 0);

                        x += word.Width + spaceWidth + (margin == null ? 0 : (margin.Left + margin.Right));
                    }
                }

                y     += fixCurrentLineHeight();
                Height = y + 4;
            }

            if (redraw)
            {
                buffer = null;
            }

            return(redraw);
        }
Esempio n. 2
0
        public static IEnumerable <LazyLoadedImage> GetFfzEmoteFromDynamic(dynamic d, bool global)
        {
            List <LazyLoadedImage> emotes = new List <LazyLoadedImage>();

            foreach (var emote in d)
            {
                var name = emote["name"];

                dynamic urls = emote["urls"];

                int maxScale = 1;

                var urlX1 = "https:" + urls["1"];

                string urlX2 = null;
                if (urls.ContainsKey("2"))
                {
                    urlX2    = "https:" + urls["2"];
                    maxScale = 2;
                }

                string urlX4 = null;
                if (urls.ContainsKey("4"))
                {
                    urlX4    = "https:" + urls["4"];
                    maxScale = 4;
                }

                var _scale = AppSettings.EmoteScale > 2 ? 4 : (AppSettings.EmoteScale > 1 ? 2 : 1);

                string url;
                if (maxScale >= 2 && _scale == 2)
                {
                    _scale = 2;
                    url    = urlX2;
                }
                else if (maxScale == 4 && _scale == 4)
                {
                    _scale = 4;
                    url    = urlX4;
                }
                else
                {
                    _scale = 1;
                    url    = urlX1;
                }

                var scale = 1.0 / _scale;

                string margins = emote["margins"];

                Margin margin = null;

                if (!string.IsNullOrEmpty(margins))
                {
                    var S = margins.Split(' ');

                    if (S.Length == 4)
                    {
                        try
                        {
                            var ints = S.Select(x =>
                            {
                                var index = x.Length;
                                for (var i = 0; i < x.Length; i++)
                                {
                                    if (x[i] != '-' && (x[i] < '0' || x[i] > '9'))
                                    {
                                        index = i - 1;
                                    }
                                }

                                return(int.Parse(index == x.Length ? x : x.Remove(index)));
                            }).ToArray();

                            margin = new Margin(ints[0], ints[1], ints[2], ints[3]);
                        }
                        catch
                        {
                        }
                    }
                }

                emotes.Add(new LazyLoadedImage {
                    Name = name, Url = url, Scale = scale, Margin = margin, Tooltip = name + $"\nFrankerFaceZ {(global ? "Global" : "Channel")} Emote", IsEmote = true
                });
            }

            return(emotes);
        }