Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(TFMPrevious)-tizen$(TPVTizenPrevious);$(TFMCurrent)-tizen$(TPVTizenCurrent)</TargetFrameworks>
<TargetFrameworks>$(TFMPrevious)-tizen$(TPVTizenPrevious);$(TFMCurrent)-tizen$(TPVTizenCurrent);$(TFMMinimum)-tizen$(TPVTizenMinimum)</TargetFrameworks>
<PackagingGroup>HarfBuzzSharp</PackagingGroup>
<Title>$(PackagingGroup) - Native Assets for Tizen</Title>
</PropertyGroup>
<ItemGroup>
<PackageFile Include="..\..\output\native\tizen\armel\libHarfBuzzSharp.*" PackagePath="runtimes\tizen-armel\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\i586\libHarfBuzzSharp.*" PackagePath="runtimes\tizen-x86\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\i586\libHarfBuzzSharp.*" PackagePath="runtimes\linux-x86\native\%(Filename)%(Extension)" />
</ItemGroup>
<Target Name="IncludeAdditionalTfmSpecificPackageFiles">
<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions binding/IncludeNativeAssets.HarfBuzzSharp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<ItemGroup Condition="$(TargetFramework.Contains('-tizen'))">
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\i586\libHarfBuzzSharp.so">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\linux-x86\native\</TizenTpkSubDir>
<TizenTpkSubDir>bin\runtimes\tizen-x86\native\</TizenTpkSubDir>
<TizenTpkFileName>libHarfBuzzSharp.so</TizenTpkFileName>
</TizenTpkFiles>
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\armel\libHarfBuzzSharp.so">
Expand All @@ -58,7 +58,7 @@
</TizenTpkFiles>
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.Contains('-tvos')) and '$(RuntimeIdentifier)' != ''">
<ItemGroup Condition="$(TargetFramework.Contains('-tvos'))and '$(RuntimeIdentifier)' != ''">
<NativeReference Include="$(MSBuildThisFileDirectory)..\output\native\tvossimulator\libHarfBuzzSharp.framework" Kind="Framework" Condition="$(RuntimeIdentifier.StartsWith('tvossimulator'))" />
<NativeReference Include="$(MSBuildThisFileDirectory)..\output\native\tvos\libHarfBuzzSharp.framework" Kind="Framework" Condition="!$(RuntimeIdentifier.StartsWith('tvossimulator'))" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion binding/IncludeNativeAssets.SkiaSharp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<ItemGroup Condition="$(TargetFramework.Contains('-tizen'))">
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\i586\libSkiaSharp.so">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\linux-x86\native\</TizenTpkSubDir>
<TizenTpkSubDir>bin\runtimes\tizen-x86\native\</TizenTpkSubDir>
<TizenTpkFileName>libSkiaSharp.so</TizenTpkFileName>
</TizenTpkFiles>
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\armel\libSkiaSharp.so">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(TFMPrevious)-tizen$(TPVTizenPrevious);$(TFMCurrent)-tizen$(TPVTizenCurrent)</TargetFrameworks>
<TargetFrameworks>$(TFMPrevious)-tizen$(TPVTizenPrevious);$(TFMCurrent)-tizen$(TPVTizenCurrent);$(TFMMinimum)-tizen$(TPVTizenMinimum)</TargetFrameworks>
<PackagingGroup>SkiaSharp</PackagingGroup>
<Title>$(PackagingGroup) - Native Assets for Tizen</Title>
</PropertyGroup>
<ItemGroup>
<PackageFile Include="..\..\output\native\tizen\armel\libSkiaSharp.*" PackagePath="runtimes\tizen-armel\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\i586\libSkiaSharp.*" PackagePath="runtimes\tizen-x86\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\i586\libSkiaSharp.*" PackagePath="runtimes\linux-x86\native\%(Filename)%(Extension)" />
</ItemGroup>
<Target Name="IncludeAdditionalTfmSpecificPackageFiles">
<ItemGroup>
Expand Down
14 changes: 14 additions & 0 deletions binding/SkiaSharp/GRGlInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ private partial class EvasGlLoader
private readonly IntPtr glEvas;
private readonly EvasGlApi api;

#if NET7_0_OR_GREATER
[LibraryImport (libevas)]
internal static partial IntPtr evas_gl_api_get (IntPtr evas_gl);

Expand All @@ -221,6 +222,19 @@ private partial class EvasGlLoader

[LibraryImport(libevas)]
internal static partial IntPtr evas_gl_proc_address_get (IntPtr evas_gl, [MarshalAs (UnmanagedType.LPStr)] string name);
#else
[DllImport (libevas)]
internal static extern IntPtr evas_gl_api_get (IntPtr evas_gl);

[DllImport (libevas)]
internal static extern IntPtr evas_gl_context_api_get (IntPtr evas_gl, IntPtr ctx);

[DllImport (libevas)]
internal static extern IntPtr evas_gl_current_context_get (IntPtr evas_gl);

[DllImport (libevas)]
internal static extern IntPtr evas_gl_proc_address_get (IntPtr evas_gl, [MarshalAs (UnmanagedType.LPStr)] string name);
#endif

static EvasGlLoader ()
{
Expand Down
7 changes: 2 additions & 5 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,10 @@ Information($" {"GIT_URL".PadRight(30)} {{0}}", GIT_URL);

#load "./scripts/cake/msbuild.cake"
#load "./scripts/cake/UtilsManaged.cake"
#load "./scripts/cake/samples.cake"
#load "./scripts/cake/externals.cake"
#load "./scripts/cake/UpdateDocs.cake"
#load "./scripts/cake/samples.cake"


Task ("__________________________________")
.Description ("__________________________________________________");
Expand Down Expand Up @@ -465,10 +466,6 @@ Task ("tests-wasm")
}
});

////////////////////////////////////////////////////////////////////////////////////////////////////
// SAMPLES - the demo apps showing off the work (tasks defined in scripts/cake/samples.cake)
////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////
// NUGET - building the package for NuGet.org
////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
53 changes: 53 additions & 0 deletions samples/Basic/Tizen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SkiaSharp Tizen Sample

Demonstrates SkiaSharp views in a Tizen NUI app with a `TabView` for navigating between CPU rendering, GPU shader animation, and interactive drawing.

## Sample Pages

This sample uses `Tizen.NUI.Components.TabView` with three tabs, each demonstrating a different SkiaSharp rendering approach.

### CPU

A static scene rendered on the CPU — a radial gradient background overlaid with semi-transparent colored circles and centered "SkiaSharp" text.

**Features:**

- **`SKCanvasView`** — Software-rendered canvas integrated into the NUI view tree.
- **`SKShader`** — Radial gradient background created with `SKShader.CreateRadialGradient`.
- **`SKCanvas.DrawCircle`** — Semi-transparent colored circles composited over the gradient.
- **`SKCanvas.DrawText`** — Centered "SkiaSharp" text rendered with measured alignment.

### GPU

A real-time animated shader running at full frame rate via the NUI GPU surface, with touch interaction.

**Features:**

- **`SKGLSurfaceView`** — GPU-composited canvas using `NativeImageQueue` double-buffering through the NUI rendering pipeline.
- **`SKRuntimeEffect`** — SkSL metaball "lava lamp" shader compiled at runtime with `SKRuntimeEffect.BuildShader`.
- **Render loop** — Continuous animation driven by a `Timer` at ~60 fps with an FPS counter overlay.
- **Touch interaction** — Touch position is passed as a shader uniform (`iTouchPos`) to create an interactive white blob.

### Drawing

A freehand drawing canvas with a color palette toolbar and touch-based input.

**Features:**

- **`SKCanvasView`** — Software-rendered canvas invalidated on demand after each stroke or clear.
- **`SKPath`** — Freehand strokes captured as paths with `MoveTo` and `LineTo` from NUI touch events.
- **Color palette** — Six selectable color swatches with visual selection indicator.
- **Clear button** — Removes all strokes and resets the canvas.

## Requirements

- [.NET 10 SDK](https://dotnet.microsoft.com/download) or later
- Tizen workload: `dotnet workload install tizen`

## Running the Sample

Build:

```bash
dotnet build -f net10.0-tizen
```
83 changes: 28 additions & 55 deletions samples/Basic/Tizen/SkiaSharpSample/App.cs
Original file line number Diff line number Diff line change
@@ -1,72 +1,45 @@
using System;
using ElmSharp;
using Tizen.Applications;
using Tizen.NUI;
using Tizen.NUI.BaseComponents;
using Tizen.NUI.Components;

using SkiaSharp;
using SkiaSharp.Views.Tizen;
namespace SkiaSharpSample;

namespace SkiaSharpSample
public class App : NUIApplication
{
public class App : CoreUIApplication
{
public static void Main(string[] args)
{
Elementary.Initialize();
Elementary.ThemeOverlay();
public static SamplePage DefaultPage { get; set; } = SamplePage.Cpu;

var app = new App();
app.Run(args);
}
private GpuPage? gpuPage;

protected override void OnCreate()
{
base.OnCreate();
public static void Main(string[] args) => new App().Run(args);

Initialize();
}
protected override void OnCreate()
{
base.OnCreate();

private void Initialize()
{
var window = new Window("SkiaSharp");
window.BackButtonPressed += OnBackButtonPressed;
window.AvailableRotations = DisplayRotation.Degree_0 | DisplayRotation.Degree_180 | DisplayRotation.Degree_270 | DisplayRotation.Degree_90;
window.Show();
GetDefaultWindow().KeyEvent += OnKeyEvent;

var skiaView = new SKCanvasView(window);
skiaView.IgnorePixelScaling = true;
skiaView.PaintSurface += OnPaintSurface;
skiaView.Show();
var tabView = new TabView
{
WidthSpecification = LayoutParamPolicies.MatchParent,
HeightSpecification = LayoutParamPolicies.MatchParent,
};

var conformant = new Conformant(window);
conformant.Show();
conformant.SetContent(skiaView);
}
tabView.AddTab(new TabButton { Text = "CPU" }, new CpuPage());

private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
// the the canvas and properties
var canvas = e.Surface.Canvas;
gpuPage = new GpuPage();
tabView.AddTab(new TabButton { Text = "GPU" }, gpuPage);

// make sure the canvas is blank
canvas.Clear(SKColors.White);
tabView.AddTab(new TabButton { Text = "Drawing" }, new DrawingPage());

// draw some text
using var paint = new SKPaint
{
Color = SKColors.Black,
IsAntialias = true,
Style = SKPaintStyle.Fill
};
using var font = new SKFont
{
Size = 24
};
var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + font.Size) / 2);
canvas.DrawText("SkiaSharp", coord, SKTextAlign.Center, font, paint);
}
GetDefaultWindow().Add(tabView);
}

private void OnBackButtonPressed(object sender, EventArgs e)
void OnKeyEvent(object? sender, Window.KeyEventArgs e)
{
if (e.Key.State == Key.StateType.Down &&
(e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))
{
gpuPage?.StopAnimation();
Exit();
}
}
Expand Down
93 changes: 93 additions & 0 deletions samples/Basic/Tizen/SkiaSharpSample/CpuPage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System;
using Tizen.NUI;
using Tizen.NUI.BaseComponents;

using SkiaSharp;
using SkiaSharp.Views.Tizen;
using SKCanvasView = SkiaSharp.Views.Tizen.NUI.SKCanvasView;

namespace SkiaSharpSample;

public class CpuPage : View
{
static readonly (float X, float Y, float R, SKColor Color)[] circles =
{
(0.20f, 0.30f, 0.10f, new SKColor(0xFF, 0x4D, 0x66, 0xCC)),
(0.75f, 0.25f, 0.08f, new SKColor(0x4D, 0xB3, 0xFF, 0xCC)),
(0.15f, 0.70f, 0.07f, new SKColor(0xFF, 0x99, 0x1A, 0xCC)),
(0.80f, 0.70f, 0.12f, new SKColor(0x66, 0xFF, 0xB3, 0xCC)),
(0.50f, 0.15f, 0.06f, new SKColor(0xB3, 0x4D, 0xFF, 0xCC)),
(0.40f, 0.80f, 0.09f, new SKColor(0xFF, 0xE6, 0x33, 0xCC)),
};

static readonly SKColor[] gradientColors =
{
new SKColor(0x44, 0x88, 0xFF),
new SKColor(0x88, 0x33, 0xCC),
};

readonly FpsCounter fpsCounter = new();
readonly TextLabel fpsLabel;
readonly SKCanvasView skiaView;

public CpuPage()
{
WidthSpecification = LayoutParamPolicies.MatchParent;
HeightSpecification = LayoutParamPolicies.MatchParent;

skiaView = new SKCanvasView
{
WidthSpecification = LayoutParamPolicies.MatchParent,
HeightSpecification = LayoutParamPolicies.MatchParent,
};
skiaView.PaintSurface += OnPaintSurface;

fpsLabel = new TextLabel
{
Text = "FPS: --",
TextColor = Tizen.NUI.Color.White,
PointSize = 10,
Position = new Position(10, 10),
};

Add(skiaView);
Add(fpsLabel);

fpsCounter.Start();
}

void OnPaintSurface(object? sender, SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
var width = e.Info.Width;
var height = e.Info.Height;
var center = new SKPoint(width / 2f, height / 2f);
var radius = Math.Max(width, height) / 2f;

canvas.Clear(SKColors.White);

// Gradient background
using var shader = SKShader.CreateRadialGradient(
center, radius, gradientColors, SKShaderTileMode.Clamp);
using var bgPaint = new SKPaint { IsAntialias = true, Shader = shader };
canvas.DrawRect(0, 0, width, height, bgPaint);

// Translucent circles
using var circlePaint = new SKPaint { IsAntialias = true, Style = SKPaintStyle.Fill };
foreach (var (x, y, r, color) in circles)
{
circlePaint.Color = color;
canvas.DrawCircle(x * width, y * height, r * Math.Min(width, height), circlePaint);
}

// Centered title text
using var textPaint = new SKPaint { Color = SKColors.White, IsAntialias = true };
using var font = new SKFont { Size = width * 0.12f };
canvas.DrawText("SkiaSharp", center.X, center.Y + font.Size / 3f,
SKTextAlign.Center, font, textPaint);

// FPS
if (fpsCounter.Tick() is double fps)
fpsLabel.Text = $"FPS: {fps:F0}";
}
}
Loading
Loading