/// <summary>
 /// Draws the outline of the polygon with the provided brush at the provided thickness.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="brush">The brush.</param>
 /// <param name="thickness">The thickness.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext Draw(
     this IImageProcessingContext source,
     IBrush brush,
     float thickness,
     IPathCollection paths) =>
 source.Draw(new Pen(brush, thickness), paths);
Exemple #2
0
 /// <summary>
 /// Creates a path rotated by the specified radians around its center.
 /// </summary>
 /// <param name="path">The path to rotate.</param>
 /// <param name="radians">The radians to rotate the path.</param>
 /// <returns>A <see cref="IPath"/> with a rotate transform applied.</returns>
 public static IPathCollection Rotate(this IPathCollection path, float radians)
 => path.Transform(Matrix3x2Extensions.CreateRotation(radians, RectangleF.Center(path.Bounds)));
 /// <summary>
 /// Flood fills the image in the shape of the provided polygon with the specified brush.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="color">The color.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext Fill(
     this IImageProcessingContext source,
     Color color,
     IPathCollection paths) =>
 source.Fill(new SolidBrush(color), paths);
 Draw(this IImageProcessingContext source, IPen pen, IPathCollection paths) =>
 source.Draw(GraphicsOptions.Default, pen, paths);
Exemple #5
0
 /// <summary>
 /// Draws the outline of the polygon with the provided brush at the provided thickness.
 /// </summary>
 /// <typeparam name="TPixel">The type of the color.</typeparam>
 /// <param name="source">The image this method extends.</param>
 /// <param name="color">The color.</param>
 /// <param name="thickness">The thickness.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext <TPixel> Draw <TPixel>(this IImageProcessingContext <TPixel> source, TPixel color, float thickness, IPathCollection paths)
     where TPixel : struct, IPixel <TPixel>
 {
     return(source.Draw(new SolidBrush <TPixel>(color), thickness, paths));
 }
Exemple #6
0
 /// <summary>
 /// Draws the outline of the polygon with the provided pen.
 /// </summary>
 /// <typeparam name="TPixel">The type of the color.</typeparam>
 /// <param name="source">The image this method extends.</param>
 /// <param name="pen">The pen.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext <TPixel> Draw <TPixel>(this IImageProcessingContext <TPixel> source, IPen <TPixel> pen, IPathCollection paths)
     where TPixel : struct, IPixel <TPixel>
 {
     return(source.Draw(pen, paths, GraphicsOptions.Default));
 }
Exemple #7
0
 /// <summary>
 /// Flood fills the image in the shape of the provided polygon with the specified brush.
 /// </summary>
 /// <typeparam name="TPixel">The type of the color.</typeparam>
 /// <param name="source">The image this method extends.</param>
 /// <param name="color">The color.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext <TPixel> Fill <TPixel>(this IImageProcessingContext <TPixel> source, TPixel color, IPathCollection paths)
     where TPixel : struct, IPixel <TPixel>
 => source.Fill(new SolidBrush <TPixel>(color), paths);
Exemple #8
0
 /// <summary>
 /// Creates a path translated by the supplied postion
 /// </summary>
 /// <param name="path">The path to translate.</param>
 /// <param name="x">The amount to translate along the X axis.</param>
 /// <param name="y">The amount to translate along the Y axis.</param>
 /// <returns>A <see cref="IPath"/> with a translate transform applied.</returns>
 public static IPathCollection Translate(this IPathCollection path, float x, float y)
 => path.Translate(new PointF(x, y));
Exemple #9
0
        /// <summary>
        /// Flood fills the image in the shape of the provided polygon with the specified brush.
        /// </summary>
        /// <typeparam name="TPixel">The type of the color.</typeparam>
        /// <param name="source">The image this method extends.</param>
        /// <param name="options">The graphics options.</param>
        /// <param name="brush">The brush.</param>
        /// <param name="paths">The shapes.</param>
        /// <returns>The <see cref="Image{TPixel}"/>.</returns>
        public static IImageProcessingContext <TPixel> Fill <TPixel>(this IImageProcessingContext <TPixel> source, GraphicsOptions options, IBrush <TPixel> brush, IPathCollection paths)
            where TPixel : struct, IPixel <TPixel>
        {
            foreach (IPath s in paths)
            {
                source.Fill(options, brush, s);
            }

            return(source);
        }
Exemple #10
0
 /// <summary>
 /// Flood fills the image in the shape of the provided polygon with the specified brush.
 /// </summary>
 /// <typeparam name="TPixel">The type of the color.</typeparam>
 /// <param name="source">The image this method extends.</param>
 /// <param name="brush">The brush.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext <TPixel> Fill <TPixel>(this IImageProcessingContext <TPixel> source, IBrush <TPixel> brush, IPathCollection paths)
     where TPixel : struct, IPixel <TPixel>
 => source.Fill(GraphicsOptions.Default, brush, paths);
 public DrawPathCollection()
 {
     this.pathCollection = new PathCollection(this.path1, this.path2);
 }
Exemple #12
0
        public async Task Profile(CommandContext ctx, [RemainingText] DiscordMember user = null)
        {
            try
            {
                if (user == null)
                {
                    user = ctx.Member;
                }

                SdlPlayer player;
                try
                {
                    player = await MySqlClient.RetrieveSdlPlayer(user.Id);
                }
                catch (Exception e)
                {
                    Logger.Warn(e);

                    /*if (e is SdlAirTableException airTableException)
                     *  await airTableException.Message;*/

                    throw;
                }

                await ctx.TriggerTypingAsync();

                Font powerFont      = KarlaFontFamily.CreateFont(160, FontStyle.Bold);
                Font nameFont       = KarlaFontFamily.CreateFont(80, FontStyle.Bold);
                Font winRateFont    = KarlaFontFamily.CreateFont(100, FontStyle.Bold);
                Font switchCodeFont = KarlaItalicFontFamily.CreateFont(50, FontStyle.Italic);
                Font classFont      = KarlaFontFamily.CreateFont(180, FontStyle.Bold);
                Font classNameFont  = KarlaFontFamily.CreateFont(26, FontStyle.Bold);
                Font roleFont       = KarlaFontFamily.CreateFont(100, FontStyle.Bold);
                Font placementFont  = KarlaFontFamily.CreateFont(113, FontStyle.Bold);
                Font ordinalFont    = KarlaFontFamily.CreateFont(57, FontStyle.Bold);

                WebClient webClient = new WebClient();

                string avatarUrl = string.IsNullOrWhiteSpace(user.GetAvatarUrl(ImageFormat.Png)) ? user.DefaultAvatarUrl : user.GetAvatarUrl(ImageFormat.Png);

                byte[] avatarBytes = await webClient.DownloadDataTaskAsync(avatarUrl);

                using (Image <Rgba32> image = Image.Load(Path.Combine(Globals.AppPath, "Data", "img", "profile-template.png")))
                {
                    using Image <Rgba32> rankImage   = new Image <Rgba32>(225, 225);
                    using Image <Rgba32> avatarImage = Image.Load(avatarBytes);
                    using Image <Rgba32> roleImage   = new Image <Rgba32>(455, 115);
                    using MemoryStream ms = new MemoryStream();

                    string name       = player.Nickname.ToUpper();
                    string powerLevel = Math.Round(player.PowerLevel, 1).ToString(CultureInfo.InvariantCulture);

                    SizeF nameTextSize = TextMeasurer.Measure(name, new RendererOptions(nameFont));

                    if (nameTextSize.Width > 700)
                    {
                        float nameScalingFactor = 700 / nameTextSize.Width;
                        nameFont = KarlaFontFamily.CreateFont(nameFont.Size * nameScalingFactor);
                    }

                    IPathCollection nameTextGlyphs = TextBuilder.GenerateGlyphs(name,
                                                                                new PointF(445, 45), new RendererOptions(nameFont));

                    SizeF powerLevelSize = TextMeasurer.Measure(powerLevel, new RendererOptions(powerFont));

                    float powerYDifference = 0;

                    if (powerLevelSize.Width > 480)
                    {
                        float powerScalingFactor = 480 / powerLevelSize.Width;
                        powerFont = KarlaFontFamily.CreateFont(powerFont.Size * powerScalingFactor, FontStyle.Bold);

                        powerYDifference = powerLevelSize.Height - TextMeasurer.Measure(powerLevel, new RendererOptions(powerFont)).Height;
                    }

                    IPathCollection powerTextGlyphs = TextBuilder.GenerateGlyphs(powerLevel,
                                                                                 new PointF(445, 110 + powerYDifference), new RendererOptions(powerFont));

                    IPathCollection switchCodeGlyphs = TextBuilder.GenerateGlyphs(player.SwitchFriendCode,
                                                                                  new PointF(420, 987), new RendererOptions(switchCodeFont));

                    // When centering, this is for if everything is off by the same amount.
                    const float offset = 0;

                    string splatZonesWr = player.WinRates.ContainsKey(GameMode.SplatZones) ?
                                          $"{player.WinRates[GameMode.SplatZones]:P0}" :
                                          "N/A";

                    SizeF szWrSize = TextMeasurer.Measure(splatZonesWr, new RendererOptions(winRateFont));

                    float szWrX = 379 + offset + (119F - szWrSize.Width / 2);

                    IPathCollection splatZonesGlyphs = TextBuilder.GenerateGlyphs(
                        splatZonesWr, new PointF(szWrX, 420), new RendererOptions(winRateFont));

                    string rainmakerWr = player.WinRates.ContainsKey(GameMode.Rainmaker) ?
                                         $"{player.WinRates[GameMode.Rainmaker]:P0}" :
                                         "N/A";

                    SizeF rmWrSize = TextMeasurer.Measure(rainmakerWr, new RendererOptions(winRateFont));

                    float rmWrX = 379 + offset + (119F - rmWrSize.Width / 2);

                    IPathCollection rainmakerGlyphs = TextBuilder.GenerateGlyphs(
                        rainmakerWr, new PointF(rmWrX, 587), new RendererOptions(winRateFont));

                    string towerControlWr = player.WinRates.ContainsKey(GameMode.TowerControl) ?
                                            $"{player.WinRates[GameMode.TowerControl]:P0}" :
                                            "N/A";

                    SizeF tcWrSize = TextMeasurer.Measure(towerControlWr, new RendererOptions(winRateFont));

                    float tcWrX = 1005 + offset + (119F - tcWrSize.Width / 2);

                    IPathCollection towerControlGlyphs = TextBuilder.GenerateGlyphs(
                        towerControlWr, new PointF(tcWrX, 420), new RendererOptions(winRateFont));

                    string clamBlitzWr = player.WinRates.ContainsKey(GameMode.ClamBlitz) ?
                                         $"{player.WinRates[GameMode.ClamBlitz]:P0}" :
                                         "N/A";

                    SizeF cbWrSize = TextMeasurer.Measure(clamBlitzWr, new RendererOptions(winRateFont));

                    float cbWrX = 1005 + offset + (119F - cbWrSize.Width / 2);

                    IPathCollection clamBlitzGlyphs = TextBuilder.GenerateGlyphs(
                        clamBlitzWr, new PointF(cbWrX, 587), new RendererOptions(winRateFont));

                    string overallWrText = Math.Abs(player.OverallWinRate + 1) < 0.1
                        ? "N/A"
                        : $"{player.OverallWinRate:P0}";

                    SizeF overallWrSize = TextMeasurer.Measure(overallWrText, new RendererOptions(winRateFont));

                    float overallWrX = 740 + offset + (119F - overallWrSize.Width / 2);

                    IPathCollection overallGlyphs = TextBuilder.GenerateGlyphs(
                        overallWrText, new PointF(overallWrX, 755), new RendererOptions(winRateFont));

                    Rgba32 classColor;
                    string classText;

                    if (player.PowerLevel >= 2200)
                    {
                        classColor = new Rgba32(255, 70, 75);
                        classText  = "1";
                    }
                    else if (player.PowerLevel >= 2000)
                    {
                        classColor = new Rgba32(255, 190, 52);
                        classText  = "2";
                    }
                    else if (player.PowerLevel >= 1800)
                    {
                        classColor = new Rgba32(61, 255, 99);
                        classText  = "3";
                    }
                    else
                    {
                        classColor = new Rgba32(21, 205, 227);
                        classText  = "4";
                    }

                    SizeF classSize = TextMeasurer.Measure(classText, new RendererOptions(classFont));

                    float classX = 1340 + ((float)rankImage.Width / 2 - classSize.Width / 2);

                    IPathCollection classNameGlyphs =
                        TextBuilder.GenerateGlyphs("CLASS", new PointF(1414.32F, 70), new RendererOptions(classNameFont));

                    IPathCollection classGlyphs =
                        TextBuilder.GenerateGlyphs(classText, new PointF(classX, 67.57F),
                                                   new RendererOptions(classFont));

                    Rgba32 roleColor;

                    string role = player.RoleOne ?? "Flex";

                    switch (role.ToLower())
                    {
                    case "back":
                        roleColor = Rgba32.FromHex("#4BDFFA");
                        break;

                    case "front":
                        roleColor = Rgba32.FromHex("#EB5F5F");
                        break;

                    case "mid":
                        roleColor = Rgba32.FromHex("#61E87B");
                        break;

                    case "flex":
                        roleColor = Rgba32.RebeccaPurple;
                        break;

                    default:
                        roleColor = Rgba32.Black;
                        break;
                    }

                    role = role.ToUpper();

                    SizeF roleNameSize = TextMeasurer.Measure(role, new RendererOptions(roleFont));

                    float roleNameX = (float)roleImage.Width / 2 - roleNameSize.Width / 2;
                    float roleNameY = (float)roleImage.Height / 2 - roleNameSize.Height / 2 - 10;

                    IPathCollection roleGlyphs = TextBuilder.GenerateGlyphs(role, new PointF(roleNameX, roleNameY),
                                                                            new RendererOptions(roleFont));

                    SdlPlayer[] players = await MySqlClient.RetrieveAllSdlPlayers();

                    List <SdlPlayer> orderedPlayers = players
                                                      .Where(x => ctx.Guild.Members.Any(y =>
                                                                                        y.Id == x.DiscordId &&
                                                                                        MySqlClient.CheckHasPlayedSet(x).Result&&
                                                                                        y.Roles.Any(z =>
                                                                                                    z.Name.Equals("player", StringComparison.InvariantCultureIgnoreCase))))
                                                      .OrderByDescending(x => x.PowerLevel).ToList();

                    var playerStandings = orderedPlayers.Select(x => new { Player = x, Rank = orderedPlayers.FindLastIndex(y => y.PowerLevel == x.PowerLevel) + 1 }).ToList();

                    string ordinal   = "";
                    int    placement = 0;

                    if (playerStandings.All(x => x.Player != player))
                    {
                        await ctx.RespondAsync("Note that you will not have a standing until you play a set.");
                    }
                    else
                    {
                        placement = playerStandings.First(x => x.Player == player).Rank;
                        ordinal   = placement.GetOrdinal();
                    }

                    SizeF placementSize =
                        TextMeasurer.Measure(placement == 0 ? "N/A" : placement.ToString(), new RendererOptions(placementFont));
                    SizeF ordinalSize =
                        TextMeasurer.Measure(ordinal, new RendererOptions(ordinalFont));

                    float standingsWidth =
                        placementSize.Width + ordinalSize.Width;

                    float placementX = 949 + (347 / 2F - standingsWidth / 2F);

                    IPathCollection placementGlyphs = TextBuilder.GenerateGlyphs(placement == 0 ? "N/A" : placement.ToString(),
                                                                                 new PointF(placementX, 140), new RendererOptions(placementFont));

                    float ordinalX = placementX + placementSize.Width;
                    float ordinalY = 140 + placementSize.Height - ordinalSize.Height - 5;

                    IPathCollection ordinalGlyphs = TextBuilder.GenerateGlyphs(ordinal, new PointF(ordinalX, ordinalY),
                                                                               new RendererOptions(ordinalFont));

                    TextGraphicsOptions textGraphicsOptions = new TextGraphicsOptions(true);

                    rankImage.Mutate(e => e
                                     .Fill(classColor)
                                     .Apply(f => ApplyRoundedCorners(f, 30))
                                     );

                    avatarImage.Mutate(e => e
                                       .Resize(new Size(268, 268))
                                       .Apply(img => ApplyRoundedCorners(img, 40))
                                       );

                    roleImage.Mutate(e => e
                                     .Fill(roleColor)
                                     .Apply(f => ApplyRoundedCorners(f, 30))
                                     .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.White, roleGlyphs)
                                     );

                    image.Mutate(e => e
                                 .DrawImage(avatarImage, new Point(48, 32), 1)
                                 .DrawImage(rankImage, new Point(1340, 50), 1)
                                 .DrawImage(roleImage, new Point(1111, 755), 1)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, powerTextGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, nameTextGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, switchCodeGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, splatZonesGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, rainmakerGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, towerControlGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, clamBlitzGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, overallGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.White, classGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.White, classNameGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, placementGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, ordinalGlyphs)
                                 );

                    image.SaveAsPng(ms);

                    using MemoryStream memory = new MemoryStream(ms.GetBuffer());
                    await ctx.Channel.SendFileAsync(memory, "profile.png");
                }

                Configuration.Default.MemoryAllocator.ReleaseRetainedResources();
            }
            catch (Exception e)
            {
                Logger.Error(e);
                throw;
            }
        }
Exemple #13
0
 public FillPathCollection()
 {
     this.pathCollection = new PathCollection(path1, path2);
     this.img            = new ProcessorWatchingImage(10, 10);
 }
Exemple #14
0
 /// <summary>
 /// Creates a path rotated by the specified degrees around its center.
 /// </summary>
 /// <param name="shape">The path to rotate.</param>
 /// <param name="degree">The degree to rotate the path.</param>
 /// <returns>A <see cref="IPath"/> with a rotate transform applied.</returns>
 public static IPathCollection RotateDegree(this IPathCollection shape, float degree)
 => shape.Rotate(GeometryUtilities.DegreeToRadian(degree));
Exemple #15
0
 Draw(this IImageProcessingContext source, IPen pen, IPathCollection paths) =>
 source.Draw(source.GetShapeGraphicsOptions(), pen, paths);
Exemple #16
0
 /// <summary>
 /// Creates a path translated by the supplied postion
 /// </summary>
 /// <param name="path">The path to translate.</param>
 /// <param name="position">The translation position.</param>
 /// <returns>A <see cref="IPath"/> with a translate transform applied.</returns>
 public static IPathCollection Translate(this IPathCollection path, PointF position)
 => path.Transform(Matrix3x2.CreateTranslation(position));
Exemple #17
0
 /// <summary>
 /// Creates a path rotated by the specified degrees around its center.
 /// </summary>
 /// <param name="shape">The path to rotate.</param>
 /// <param name="degrees">The degrees to rotate the path.</param>
 /// <returns>A <see cref="IPath"/> with a rotate transform applied.</returns>
 public static IPathCollection RotateDegree(this IPathCollection shape, float degrees)
 {
     return(shape.Rotate((float)(Math.PI * degrees / 180.0)));
 }
Exemple #18
0
 /// <summary>
 /// Creates a path translated by the supplied postion
 /// </summary>
 /// <param name="path">The path to translate.</param>
 /// <param name="scale">The amount to scale along both the x and y axis.</param>
 /// <returns>A <see cref="IPath"/> with a translate transform applied.</returns>
 public static IPathCollection Scale(this IPathCollection path, float scale)
 => path.Transform(Matrix3x2.CreateScale(scale, RectangleF.Center(path.Bounds)));
Exemple #19
0
 public FillPathCollection()
 {
     this.pathCollection = new PathCollection(this.path1, this.path2);
 }
Exemple #20
0
        /// <summary>
        /// Draws the outline of the polygon with the provided pen.
        /// </summary>
        /// <typeparam name="TPixel">The type of the color.</typeparam>
        /// <param name="source">The image this method extends.</param>
        /// <param name="pen">The pen.</param>
        /// <param name="paths">The paths.</param>
        /// <param name="options">The options.</param>
        /// <returns>The <see cref="Image{TPixel}"/>.</returns>
        public static IImageProcessingContext <TPixel> Draw <TPixel>(this IImageProcessingContext <TPixel> source, IPen <TPixel> pen, IPathCollection paths, GraphicsOptions options)
            where TPixel : struct, IPixel <TPixel>
        {
            foreach (IPath path in paths)
            {
                source.Draw(pen, path, options);
            }

            return(source);
        }
 /// <summary>
 /// Draws the outline of the polygon with the provided brush at the provided thickness.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="color">The color.</param>
 /// <param name="thickness">The thickness.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext Draw(
     this IImageProcessingContext source,
     Color color,
     float thickness,
     IPathCollection paths) =>
 source.Draw(new SolidBrush(color), thickness, paths);
Exemple #22
0
 /// <summary>
 /// Draws the outline of the polygon with the provided brush at the provided thickness.
 /// </summary>
 /// <typeparam name="TPixel">The type of the color.</typeparam>
 /// <param name="source">The image this method extends.</param>
 /// <param name="brush">The brush.</param>
 /// <param name="thickness">The thickness.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext <TPixel> Draw <TPixel>(this IImageProcessingContext <TPixel> source, IBrush <TPixel> brush, float thickness, IPathCollection paths)
     where TPixel : struct, IPixel <TPixel>
 {
     return(source.Draw(new Pen <TPixel>(brush, thickness), paths));
 }
 /// <summary>
 /// Flood fills the image in the shape of the provided polygon with the specified brush.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="brush">The brush.</param>
 /// <param name="paths">The paths.</param>
 /// <returns>The <see cref="Image{TPixel}"/>.</returns>
 public static IImageProcessingContext Fill(
     this IImageProcessingContext source,
     IBrush brush,
     IPathCollection paths) =>
 source.Fill(GraphicsOptions.Default, brush, paths);