Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitmap support #127

Merged
merged 116 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 115 commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
17d9623
Avalonia 11.0.9
jinek Apr 13, 2024
bd8e2e3
Refactor multiple code files and update code comments
jinek Apr 14, 2024
395c6e2
Update helper method syntax and adjust bindings
jinek Apr 14, 2024
4dd755d
more fixes
jinek Apr 17, 2024
85d5eac
Add Avalonia threading and improve text shaping
jinek Apr 17, 2024
6e8aa2b
Refactor drawing and rendering methods
jinek Apr 17, 2024
6efaf75
application is now being run, but does not render
jinek Apr 17, 2024
b0cf503
Welcome page is rendered
jinek Apr 17, 2024
bb117b0
Window is painted when resized
jinek Apr 20, 2024
acfc4fd
Clickable button
jinek Apr 27, 2024
ed52281
- unused code
jinek May 1, 2024
259893e
- unused button
jinek May 1, 2024
dc51e56
Button shadow drawing
jinek May 1, 2024
773b1e6
Button drawing/ SymbolsControl.cs drawing
jinek May 1, 2024
2eff951
text trimming is fixed
jinek May 2, 2024
d69b033
Wild text rendering
jinek May 2, 2024
575f539
Initialize transform with Matrix Identity.
jinek May 6, 2024
7edf517
Platform settings for investigation
jinek May 6, 2024
40e45ec
LineBrush is rendered
jinek May 7, 2024
2a609ce
ScrollViewer now works
jinek Aug 12, 2024
52bf2fb
Null reference check brought back
jinek Aug 12, 2024
9204d7f
hit test for GlyphRun
jinek Aug 12, 2024
3a2579d
+1, similar to avalonia
jinek Aug 12, 2024
2b66acf
Textbox working
jinek Aug 14, 2024
d372108
more textbox
jinek Aug 14, 2024
d0d399f
keyboardnavigationhandler is back
jinek Aug 16, 2024
48d031f
combobox fix 1
jinek Aug 17, 2024
f15265e
ComboBox drop-down works fine
jinek Aug 20, 2024
874b29d
array in the combobox items
jinek Aug 20, 2024
478fd6a
Single test run. Buttons and TextBlock tests success separately.
jinek Aug 24, 2024
0e8f835
Multiple tests now can run
jinek Sep 4, 2024
1ffe787
ProgressBar.axaml adjusted
jinek Sep 8, 2024
afb4833
Separator
jinek Sep 8, 2024
d8e7eef
Dialog fixed
jinek Sep 15, 2024
82b946f
Entire list item is clickable
jinek Sep 15, 2024
bd34f74
Entire row in datagrid is clickable
jinek Sep 15, 2024
7871b19
Custom textbox Caret
jinek Sep 17, 2024
a807e3e
Comment removed
jinek Sep 20, 2024
4527aec
datagrid lines
jinek Oct 18, 2024
6cbff99
Calendar fixed
jinek Oct 19, 2024
5944506
build fixes
jinek Oct 20, 2024
eaefba3
more quality fixes
jinek Oct 20, 2024
112f9ad
TextBoxTests.cs
jinek Oct 20, 2024
456630a
ComboBoxTests.cs
jinek Oct 20, 2024
77af91f
FlyoutTests.cs
jinek Oct 20, 2024
e845e75
PR fixes
jinek Oct 20, 2024
8efff9e
build fixes
jinek Oct 20, 2024
121221a
refactoring
jinek Oct 20, 2024
8962d2c
formatting and small fixes
jinek Oct 21, 2024
d1cbe6b
Limits to run jobs
jinek Oct 21, 2024
5f0bd23
newer analysis version and null referene fix
jinek Oct 21, 2024
36cfbcc
Delegate error
jinek Oct 21, 2024
c1de176
other errors
jinek Oct 21, 2024
1b0ab64
PR fixes
jinek Oct 21, 2024
5a84e0f
last warning
jinek Oct 21, 2024
e9c3497
Automated JetBrains cleanup
github-actions[bot] Oct 21, 2024
2dcb1c8
newer jb version
jinek Oct 22, 2024
34c9336
Revert "Automated JetBrains cleanup"
jinek Oct 22, 2024
fc81b86
fix click scroll bug and wheel scroll bug.
tomlm Oct 29, 2024
0d834d6
Added full color support
tomlm Oct 29, 2024
8a79a69
cleanup brush detection code
tomlm Oct 29, 2024
8da4f66
add relative Shade()/Brighten() methods
tomlm Oct 29, 2024
ff2767f
add support for underline
tomlm Oct 29, 2024
98f6ae6
merge main into cryaon
tomlm Oct 29, 2024
242628b
merge with master
tomlm Oct 30, 2024
47de318
clean up sample#
tomlm Oct 30, 2024
32f020e
cleanup sample again
tomlm Oct 30, 2024
b38f9cd
cleanup switch statement
tomlm Oct 30, 2024
784fa2b
cleanup sample
tomlm Oct 30, 2024
0273b81
Consolidated code for converting IBrush in ConsoleBrush.FromBrush() m…
tomlm Oct 30, 2024
4cc39fe
Merge branch 'main' into tomlm/crayon
tomlm Oct 30, 2024
ab1617e
add suport for linearGradientBrush on rectangles.
tomlm Oct 30, 2024
2f5df27
Update src/Tests/Consolonia.TestsCore/Consolonia.TestsCore.csproj
tomlm Oct 30, 2024
b355163
Update src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs
tomlm Oct 30, 2024
ebf1499
Update src/Consolonia.Gallery/Gallery/GalleryViews/GalleryColors.axam…
tomlm Oct 30, 2024
21ab9bf
Update src/Tests/Consolonia.TestsCore/UnitTestConsole.cs
tomlm Oct 30, 2024
ac51348
plumb textdecorations through instead of using Oblique
tomlm Oct 30, 2024
be95d7b
Merge branch 'tomlm/crayon' of https://github.com/tomlm/Consolonia in…
tomlm Oct 30, 2024
e41651d
code review
tomlm Oct 30, 2024
7090b8f
fix bad auto-merge <sigh>
tomlm Oct 30, 2024
f08287d
update packages
tomlm Oct 30, 2024
7c22861
cleanup based on code review
tomlm Oct 30, 2024
9245be5
Update src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs
tomlm Oct 30, 2024
1b518d6
Merge branch 'tomlm/crayon' of https://github.com/tomlm/Consolonia in…
tomlm Oct 30, 2024
b6858fa
code review cleanup
tomlm Oct 30, 2024
c6b906c
final round of code reviews
tomlm Oct 30, 2024
5f1bd74
more cleanup
tomlm Oct 30, 2024
37501e3
more cleanup
tomlm Oct 30, 2024
cec48c2
removed consolebrush converter
tomlm Oct 30, 2024
8ef8a47
Consolidate Special character logic in Symbol.GetCharacer()
tomlm Oct 30, 2024
eea9ba7
add support for Radial and Conic brushs
tomlm Oct 30, 2024
3b45704
fix unit tests
tomlm Oct 30, 2024
2c28b9e
fix bug in gradient interpolation
tomlm Oct 30, 2024
56daa77
remove -1, it was not necessary
tomlm Oct 30, 2024
894317d
remove testsCore from packable list
tomlm Oct 30, 2024
c1564ff
first cut at bitmap seems to kinda work
tomlm Oct 30, 2024
c5d315c
lint fixes
tomlm Oct 31, 2024
d2580a4
code rabbit changes
tomlm Oct 31, 2024
baca3bb
more lint
tomlm Oct 31, 2024
d5dbd0b
sigh. try again.
tomlm Oct 31, 2024
274835d
Automated JetBrains cleanup
github-actions[bot] Oct 31, 2024
8befa4b
fix const
tomlm Oct 31, 2024
3307798
Merge branch 'tomlm/crayon' into tomlm/images
tomlm Oct 31, 2024
8c326f3
image works!
tomlm Oct 31, 2024
eac7395
cleanup for lint errors
tomlm Oct 31, 2024
363ac96
fix one more lint
tomlm Oct 31, 2024
8fa9eb0
Automated JetBrains cleanup
github-actions[bot] Oct 31, 2024
8269be1
code review changes
tomlm Oct 31, 2024
cdf9689
Merge branch 'main' into tomlm/images
tomlm Oct 31, 2024
5c61422
Merge branch 'tomlm/images' of https://github.com/jinek/Consolonia in…
tomlm Oct 31, 2024
6f3a4c7
merge with main
tomlm Oct 31, 2024
e05d357
Automated JetBrains cleanup
github-actions[bot] Oct 31, 2024
9217453
linter didn't like that
tomlm Oct 31, 2024
3dcecd3
merge
tomlm Oct 31, 2024
45f5f6d
fix release build
tomlm Oct 31, 2024
06383e9
remove unsued using
tomlm Oct 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Consolonia.Core/Consolonia.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
<ItemGroup>
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.FreeDesktop" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Skia" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersion)" />
<PackageReference Include="Crayon" Version="2.0.69" />
<PackageReference Include="NullLib.ConsoleEx" Version="1.0.4.4" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.8" />
</ItemGroup>

</Project>
Expand Down
100 changes: 100 additions & 0 deletions src/Consolonia.Core/Drawing/BitmapImpl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System;
using System.Globalization;

Check warning on line 2 in src/Consolonia.Core/Drawing/BitmapImpl.cs

View workflow job for this annotation

GitHub Actions / build

"[RedundantUsingDirective] Using directive is not required by the code and can be safely removed" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(2,1)
using System.IO;
using Avalonia;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Avalonia.Skia;
using SkiaSharp;

namespace Consolonia.Core.Drawing
{
internal class BitmapImpl : IWriteableBitmapImpl
{
public BitmapImpl(int width, int height, PixelFormat format, AlphaFormat? alphaFormat = null)
{
Bitmap = new SKBitmap(new SKImageInfo(width, height, format.ToSkColorType(),
alphaFormat?.ToSkAlphaType() ?? SKAlphaType.Unknown));
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved

public BitmapImpl(SKBitmap bitmap)
{
Bitmap = bitmap;
}

public BitmapImpl(Stream stream)
{
using var skStream = new SKManagedStream(stream);
Bitmap = SKBitmap.Decode(skStream);
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved

public BitmapImpl(string fileName)
{
Bitmap = SKBitmap.Decode(fileName);
}

public SKBitmap Bitmap { get; }

Vector IBitmapImpl.Dpi => new(96f, 96f);

public PixelSize PixelSize => new(Bitmap.Width, (int)(Bitmap.Height * .55));

public int Version => 1;

public AlphaFormat? AlphaFormat => Bitmap.Info.AlphaType.ToAlphaFormat();

public PixelFormat? Format => Bitmap.Info.ColorType.ToAvalonia();

public void Dispose()
{
Bitmap.Dispose();
}

public void Save(string fileName, int? quality = 100)
{
SKEncodedImageFormat format = GetFormatFromFileName(fileName);
using SKImage image = SKImage.FromBitmap(Bitmap);
using SKData data = image.Encode(format, quality ?? 100);
using FileStream stream = File.OpenWrite(fileName);
data.SaveTo(stream);
}

public void Save(Stream stream, int? quality = 100)
{
var format = SKEncodedImageFormat.Jpeg;

Check notice on line 64 in src/Consolonia.Core/Drawing/BitmapImpl.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertToConstant.Local] Convert into constant" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(64,17)
using SKImage image = SKImage.FromBitmap(Bitmap);
using SKData data = image.Encode(format, quality ?? 100);
data.SaveTo(stream);
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved

public ILockedFramebuffer Lock()
{
throw new NotImplementedException();
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved

public IBitmapImpl Resize(PixelSize pixelSize, BitmapInterpolationMode interpolationMode)
{
var resized = new SKBitmap(pixelSize.Width, pixelSize.Height);
using var canvas = new SKCanvas(resized);
canvas.DrawBitmap(Bitmap, new SKRect(0, 0, pixelSize.Width, pixelSize.Height),
new SKPaint { FilterQuality = interpolationMode.ToSKFilterQuality() });
return new BitmapImpl(resized);
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved

private static SKEncodedImageFormat GetFormatFromFileName(string fileName)
{
return Path.GetExtension(fileName).ToUpperInvariant() switch
{
".PNG" => SKEncodedImageFormat.Png,
".JPEG" => SKEncodedImageFormat.Jpeg,
".JPG" => SKEncodedImageFormat.Jpeg,
".GIF" => SKEncodedImageFormat.Gif,
".BMP" => SKEncodedImageFormat.Bmp,
".WBMP" => SKEncodedImageFormat.Wbmp,
".WEBP" => SKEncodedImageFormat.Webp,
".ICO" => SKEncodedImageFormat.Ico,
_ => throw new ArgumentException($"Unsupported file extension: {fileName}")
};
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}
}
12 changes: 8 additions & 4 deletions src/Consolonia.Core/Drawing/ConsoleBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@
throw new ArgumentOutOfRangeException(nameof(x), "x is out bounds");
if (y < 0 || y > height)
throw new ArgumentOutOfRangeException(nameof(y), "y is out bounds");
if (width <= 0)
throw new ArgumentOutOfRangeException(nameof(width), "Width must be positive");
if (height <= 0)
throw new ArgumentOutOfRangeException(nameof(height), "Height must be positive");

switch (brush)
{
case ILinearGradientBrush gradientBrush:
{
if (width <= 0)
width = 1;
if (height <= 0)
height = 1;
// Calculate the relative position within the gradient
double horizontalRelativePosition = (double)x / width;
double verticalRelativePosition = (double)y / height;
Expand Down Expand Up @@ -138,6 +138,10 @@
}
case IConicGradientBrush conicBrush:
{
if (width <= 0)
width = 1;
if (height <= 0)
height = 1;
// Calculate the relative position within the gradient
double horizontalRelativePosition = (double)x / width;
double verticalRelativePosition = (double)y / height;
Expand Down Expand Up @@ -179,7 +183,7 @@
break;
}

if (before == null && after == null)

Check notice on line 186 in src/Consolonia.Core/Drawing/ConsoleBrush.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertIfStatementToSwitchStatement] Convert 'if' statement into 'switch' statement" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoleBrush.cs(186,13)
throw new ArgumentException("no gradientstops defined");

if (before == null) return after.Color;
Expand Down
86 changes: 62 additions & 24 deletions src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Avalonia.Media.TextFormatting;
using Avalonia.Platform;
using Consolonia.Core.Text;
using SkiaSharp;

namespace Consolonia.Core.Drawing
{
Expand Down Expand Up @@ -50,75 +51,112 @@
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(PixelSize size, Vector dpi)
{
throw new NotImplementedException();
// return new ConsoleRenderTargetBitmapImpl(size, dpi);
}

public IWriteableBitmapImpl CreateWriteableBitmap(PixelSize size, Vector dpi, PixelFormat format,
AlphaFormat alphaFormat)
{
throw new NotImplementedException();
return new BitmapImpl(size.Width, size.Height, format, alphaFormat);
}

public IBitmapImpl LoadBitmap(string fileName)
{
throw new NotImplementedException();
using (FileStream stream = File.OpenRead(fileName))

Check notice on line 65 in src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(65,13)
{
return new BitmapImpl(stream);
}
Comment on lines +65 to +68
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify 'using' Statement with 'using' Declaration

You can simplify the using statement by converting it to a using declaration, reducing nesting and improving readability.

Apply this diff to update the code:

 public IBitmapImpl LoadBitmap(string fileName)
 {
-    using (FileStream stream = File.OpenRead(fileName))
-    {
-        return new BitmapImpl(stream);
-    }
+    using FileStream stream = File.OpenRead(fileName);
+    return new BitmapImpl(stream);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
using (FileStream stream = File.OpenRead(fileName))
{
return new BitmapImpl(stream);
}
using FileStream stream = File.OpenRead(fileName);
return new BitmapImpl(stream);
🧰 Tools
🪛 GitHub Check: build

[notice] 65-65:
"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(65,13)

}

public IBitmapImpl LoadBitmap(Stream stream)
{
throw new NotImplementedException();
return new BitmapImpl(stream);
}

IWriteableBitmapImpl IPlatformRenderInterface.LoadWriteableBitmapToHeight(Stream stream, int height,
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height,
BitmapInterpolationMode interpolationMode)
{
throw new NotImplementedException();
using (var skStream = new SKManagedStream(stream))

Check notice on line 79 in src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(79,13)
{
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
int width = (int)(height * ((double)originalBitmap.Width / originalBitmap.Height));
SKBitmap resizedBitmap =
originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
return new BitmapImpl(resizedBitmap);
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}

public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width,
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
{
throw new NotImplementedException();
using (var skStream = new SKManagedStream(stream))

Check notice on line 92 in src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(92,13)
{
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
int height = (int)(width * ((double)originalBitmap.Height / originalBitmap.Width));
SKBitmap resizedBitmap =
originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
return new BitmapImpl(resizedBitmap);
}
Comment on lines +92 to +99
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify 'using' Statement with 'using' Declaration

Streamline the using statement by converting it to a using declaration.

Apply this diff to update the code:

 public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width,
     BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality)
 {
-    using (var skStream = new SKManagedStream(stream))
-    {
-        SKBitmap originalBitmap = SKBitmap.Decode(skStream);
-        int height = (int)(width * ((double)originalBitmap.Height / originalBitmap.Width));
-        SKBitmap resizedBitmap =
-            originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
-        return new BitmapImpl(resizedBitmap);
-    }
+    using SKManagedStream skStream = new SKManagedStream(stream);
+    SKBitmap originalBitmap = SKBitmap.Decode(skStream);
+    int height = (int)(width * ((double)originalBitmap.Height / originalBitmap.Width));
+    SKBitmap resizedBitmap =
+        originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
+    return new BitmapImpl(resizedBitmap);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
using (var skStream = new SKManagedStream(stream))
{
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
int height = (int)(width * ((double)originalBitmap.Height / originalBitmap.Width));
SKBitmap resizedBitmap =
originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
return new BitmapImpl(resizedBitmap);
}
using SKManagedStream skStream = new SKManagedStream(stream);
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
int height = (int)(width * ((double)originalBitmap.Height / originalBitmap.Width));
SKBitmap resizedBitmap =
originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
return new BitmapImpl(resizedBitmap);

}

public IWriteableBitmapImpl LoadWriteableBitmap(string fileName)
{
throw new NotImplementedException();
using (FileStream stream = File.OpenRead(fileName))

Check notice on line 104 in src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(104,13)
{
return LoadWriteableBitmap(stream);
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}

public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream)
{
throw new NotImplementedException();
using (var skStream = new SKManagedStream(stream))

Check notice on line 112 in src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(112,13)
{
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
return new BitmapImpl(originalBitmap);
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}

IBitmapImpl IPlatformRenderInterface.LoadBitmapToWidth(Stream stream, int width,
BitmapInterpolationMode interpolationMode)
public IBitmapImpl LoadBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode)
{
throw new NotImplementedException();
using (var skStream = new SKManagedStream(stream))

Check notice on line 121 in src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(121,13)
{
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
int height = (int)(width * ((double)originalBitmap.Height / originalBitmap.Width));
SKBitmap resizedBitmap =
originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
return new BitmapImpl(resizedBitmap);
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}

IBitmapImpl IPlatformRenderInterface.LoadBitmapToHeight(Stream stream, int height,
BitmapInterpolationMode interpolationMode)
public IBitmapImpl LoadBitmapToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode)
{
throw new NotImplementedException();
using (var skStream = new SKManagedStream(stream))
{
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
int width = (int)(height * ((double)originalBitmap.Width / originalBitmap.Height));
SKBitmap resizedBitmap =
originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
return new BitmapImpl(resizedBitmap);
}
Comment on lines +133 to +140
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify 'using' Statement with 'using' Declaration

Convert the using statement to a using declaration to enhance readability.

Apply this diff to update the code:

 public IBitmapImpl LoadBitmapToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode)
 {
-    using (var skStream = new SKManagedStream(stream))
-    {
-        SKBitmap originalBitmap = SKBitmap.Decode(skStream);
-        int width = (int)(height * ((double)originalBitmap.Width / originalBitmap.Height));
-        SKBitmap resizedBitmap =
-            originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
-        return new BitmapImpl(resizedBitmap);
-    }
+    using SKManagedStream skStream = new SKManagedStream(stream);
+    SKBitmap originalBitmap = SKBitmap.Decode(skStream);
+    int width = (int)(height * ((double)originalBitmap.Width / originalBitmap.Height));
+    SKBitmap resizedBitmap =
+        originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
+    return new BitmapImpl(resizedBitmap);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
using (var skStream = new SKManagedStream(stream))
{
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
int width = (int)(height * ((double)originalBitmap.Width / originalBitmap.Height));
SKBitmap resizedBitmap =
originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
return new BitmapImpl(resizedBitmap);
}
using SKManagedStream skStream = new SKManagedStream(stream);
SKBitmap originalBitmap = SKBitmap.Decode(skStream);
int width = (int)(height * ((double)originalBitmap.Width / originalBitmap.Height));
SKBitmap resizedBitmap =
originalBitmap.Resize(new SKImageInfo(width, height), (SKFilterQuality)interpolationMode);
return new BitmapImpl(resizedBitmap);

}

IBitmapImpl IPlatformRenderInterface.ResizeBitmap(IBitmapImpl bitmapImpl, PixelSize destinationSize,
public IBitmapImpl ResizeBitmap(IBitmapImpl bitmapImpl, PixelSize destinationSize,
BitmapInterpolationMode interpolationMode)
{
throw new NotImplementedException();
var consoleBitmap = (BitmapImpl)bitmapImpl;
return consoleBitmap.Resize(destinationSize, interpolationMode);
Comment on lines +146 to +147
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure safe casting of bitmapImpl to BitmapImpl.

Directly casting bitmapImpl to BitmapImpl may cause an InvalidCastException if the provided IBitmapImpl is not of type BitmapImpl. Consider using the as operator and checking for null, or validate the type before casting.

Modify the code to safely handle casting:

var consoleBitmap = bitmapImpl as BitmapImpl;
if (consoleBitmap == null)
{
    throw new InvalidOperationException("bitmapImpl must be of type BitmapImpl.");
}

return consoleBitmap.Resize(destinationSize, interpolationMode);

}

public IBitmapImpl LoadBitmap(
PixelFormat format,
AlphaFormat alphaFormat,
IntPtr data,
PixelSize size,
Vector dpi,
int stride)
public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size,
Vector dpi, int stride)
{
throw new NotImplementedException();
var info = new SKImageInfo(size.Width, size.Height, SKColorType.Rgb888x, SKAlphaType.Opaque);
var bitmap = new SKBitmap();
bitmap.InstallPixels(info, data, stride);
return new BitmapImpl(bitmap);
Comment on lines +153 to +156
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle potential errors when installing pixels into SKBitmap.

The InstallPixels method might fail or result in an invalid SKBitmap. It's important to check the return value and handle any errors.

Include error handling after installing pixels:

var info = new SKImageInfo(size.Width, size.Height, SKColorType.Rgb888x, SKAlphaType.Opaque);
var bitmap = new SKBitmap();
bool result = bitmap.InstallPixels(info, data, stride);
if (!result)
{
    throw new InvalidOperationException("Failed to install pixels into SKBitmap.");
}
return new BitmapImpl(bitmap);

}


public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
IReadOnlyList<GlyphInfo> glyphInfos,
Point baselineOrigin)
Expand Down
60 changes: 33 additions & 27 deletions src/Consolonia.Core/Drawing/DrawingContextImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Consolonia.Core.Infrastructure;
using Consolonia.Core.InternalHelpers;
using Consolonia.Core.Text;
using SkiaSharp;

namespace Consolonia.Core.Drawing
{
Expand Down Expand Up @@ -47,27 +48,33 @@

public void DrawBitmap(IBitmapImpl source, double opacity, Rect sourceRect, Rect destRect)
{
throw new NotImplementedException();
/*
// prototype
Rect clip = _currentClip.Intersect(destRect);
for (int x = 0; x < sourceRect.Width; x++)
for (int y = 0; y < sourceRect.Height; y++)
{
var myRenderTarget = (RenderTarget)source.Item;

int left = (int)(x + destRect.Left);
int top = (int)(y + destRect.Top);
clip.ExecuteWithClipping(new Point(left, top), () =>
{
_pixelBuffer.Set(new PixelBufferCoordinate((ushort)left, (ushort)top), destPixel =>
{
return destPixel.Blend(
myRenderTarget._bufferBuffer[new PixelBufferCoordinate((ushort)(x + sourceRect.Left),
(ushort)(y + sourceRect.Top))]);
});
});
}*/
// resize bitmap to destination rect size
var targetRect = new Rect(Transform.Transform(new Point(destRect.TopLeft.X, destRect.TopLeft.Y)),
Transform.Transform(new Point(destRect.BottomRight.X, destRect.BottomRight.Y)));
var bmp = (BitmapImpl)source;
using var bitmap = new SKBitmap((int)targetRect.Width, (int)targetRect.Height);
tomlm marked this conversation as resolved.
Show resolved Hide resolved
using var canvas = new SKCanvas(bitmap);
canvas.DrawBitmap(bmp.Bitmap, new SKRect(0, 0, (float)targetRect.Width, (float)targetRect.Height),
new SKPaint { FilterQuality = SKFilterQuality.Medium });

// Rect clip = CurrentClip.Intersect(destRect);
int width = bitmap.Info.Width;
int height = bitmap.Info.Height;
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
int px = (int)targetRect.TopLeft.X + x;
int py = (int)targetRect.TopLeft.Y + y;
SKColor skColor = bitmap.GetPixel(x, y);
Color color = Color.FromRgb(skColor.Red, skColor.Green, skColor.Blue);
var imagePixel = new Pixel('█', color);
CurrentClip.ExecuteWithClipping(new Point(px, py),
() =>
{
_pixelBuffer.Set(new PixelBufferCoordinate((ushort)px, (ushort)py),
(existingPixel, _) => existingPixel.Blend(imagePixel), imagePixel.Background.Color);
});
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}

public void DrawBitmap(IBitmapImpl source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
Expand Down Expand Up @@ -139,7 +146,7 @@
CurrentClip.ExecuteWithClipping(new Point(px, py), () =>
{
_pixelBuffer.Set(new PixelBufferCoordinate((ushort)px, (ushort)py),
(pixel, bb) => { return pixel.Blend(new Pixel(new PixelBackground(bb.Mode, bb.Color))); },

Check notice on line 149 in src/Consolonia.Core/Drawing/DrawingContextImpl.cs

View workflow job for this annotation

GitHub Actions / build

"[ConvertToLambdaExpression] Use lambda expression" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/DrawingContextImpl.cs(149,46)
backgroundBrush);
});
}
Expand Down Expand Up @@ -357,7 +364,7 @@
return;
}

if (!Transform.IsTranslateOnly()) ConsoloniaPlatform.RaiseNotSupported(15);
//if (!Transform.IsTranslateOnly()) ConsoloniaPlatform.RaiseNotSupported(15);

Point whereToDraw = origin.Transform(Transform);
int currentXPosition = 0;
Expand Down Expand Up @@ -403,11 +410,10 @@
{
var consolePixel = new Pixel(c, foregroundColor, typeface.Style, typeface.Weight);
CurrentClip.ExecuteWithClipping(characterPoint, () =>
{
_pixelBuffer.Set((PixelBufferCoordinate)characterPoint,
(oldPixel, cp) => oldPixel.Blend(cp), consolePixel);
}
);
{
_pixelBuffer.Set((PixelBufferCoordinate)characterPoint,
(oldPixel, cp) => oldPixel.Blend(cp), consolePixel);
});
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}
break;
}
Expand Down
1 change: 1 addition & 0 deletions src/Consolonia.Core/Text/GlyphRunImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public void Dispose()

public IReadOnlyList<float> GetIntersections(float lowerLimit, float upperLimit)
{
// empty intersections defaults to entire span.
return new List<float>();
tomlm marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
5 changes: 5 additions & 0 deletions src/Consolonia.Gallery/Consolonia.Gallery.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<IsPackable>False</IsPackable>
</PropertyGroup>


<ItemGroup>
<AvaloniaResource Include="Resources\*" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Consolonia.Core\Consolonia.Core.csproj" />
<ProjectReference Include="..\Consolonia.PlatformSupport\Consolonia.PlatformSupport.csproj" />
Expand Down
Loading
Loading