GithubHelp home page GithubHelp logo

winicius11 / skia4delphi Goto Github PK

View Code? Open in Web Editor NEW

This project forked from skia4delphi/skia4delphi

0.0 0.0 0.0 151.75 MB

Skia4Delphi is a cross-platform 2D graphics API for Delphi platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.

Home Page: https://skia4delphi.org

License: MIT License

Pascal 92.80% Batchfile 0.01% Inno Setup 5.85% JavaScript 0.19% HTML 0.11% Vue 1.05%

skia4delphi's Introduction

supported-platforms supported-platforms-old-versions supported-applications

Skia4Delphi is a cross-platform 2D graphics API for Delphi based on Google's Skia Graphics Library (skia.org).

Google's Skia Graphics Library serves as the graphics engine for Google Chrome and Chrome OS, Android, Flutter, Xamarin, Mozilla Firefox and Firefox OS, and many other products.

Motivation

Skia is a great open source library for drawing 2D Text, Geometries, Images, focused on accurate, high quality and high performance rendering, which provides common APIs that work across a variety of hardware and software platforms.

Summary

Installation

There are two recommended ways to install the library:

  • Install Skia4Delphi via GetIt (RAD Studio > Tools > GetIt Package Manager...)

    getit

  • Or just download and run our setup in releases page

But, if you want, you can also do the manual installation (although it's a lot of work). See the full documentation of installation.

Enabling your project

After install the Skia4Delphi, you need to enable your project to be able to run with the skia library. In your IDE, just right click in your application project and "Enable Skia".

enabling-project

Skipping this step, your application startup will get a "runtime error".

Note: You don't need to do this step in package projects that use our units. This step is exclusive for application projects.

Documentation

The APIs are very similar to Skia's, few methods and functions have been renamed for readability, so the Skia documentation can be used. Note: Some APIs were not exposed, some because they are deprecated.

Basic Usage

The code below is common code among all the examples in this section:

var
  LImage: ISkImage;
  LSurface: ISkSurface;
begin
  LSurface := TSkSurface.MakeRaster(256, 256);
  Draw(LSurface.Canvas);
  LImage := LSurface.MakeImageSnapshot;
  TFile.WriteAllBytes('output.png', LImage.EncodeToBytes(TSkEncodedImageFormat.PNG));
end;

Shapes

procedure Draw(const ACanvas: ISkCanvas);
var
  LOval: ISkRoundRect;
  LPaint: ISkPaint;
  LRect: TRectF;
begin
  ACanvas.Clear(TAlphaColors.Null);

  LPaint := TSkPaint.Create;
  LPaint.Style := TSkPaintStyle.Fill;
  LPaint.AntiAlias := True;
  LPaint.StrokeWidth := 4;
  LPaint.Color := $FF4285F4;

  LRect := TRectF.Create(TPointF.Create(10, 10), 100, 160);
  ACanvas.DrawRect(LRect, LPaint);

  LOval := TSkRoundRect.Create;
  LOval.SetOval(LRect);
  LOval.Offset(40, 80);
  LPaint.Color := $FFDB4437;
  ACanvas.DrawRoundRect(LOval, LPaint);

  LPaint.Color := $FF0F9D58;
  ACanvas.DrawCircle(180, 50, 25, LPaint);

  LRect.Offset(80, 50);
  LPaint.Color := $FFF4B400;
  LPaint.Style := TSkPaintStyle.Stroke;
  ACanvas.DrawRoundRect(LRect, 10, 10, LPaint);
end;

This code results in the output below:

Bézier Curves

procedure Draw(const ACanvas: ISkCanvas);
var
  LPaint: ISkPaint;
  LPath: ISkPath;
  LPathBuilder: ISkPathBuilder;
begin
  ACanvas.Clear(TAlphaColors.Null);

  LPaint := TSkPaint.Create;
  LPaint.Style := TSkPaintStyle.Stroke;
  LPaint.StrokeWidth := 8;
  LPaint.Color := $FF4285F4;
  LPaint.AntiAlias := True;
  LPaint.StrokeCap := TSkStrokeCap.Round;

  LPathBuilder := TSkPathBuilder.Create;
  LPathBuilder.MoveTo(10, 10);
  LPathBuilder.QuadTo(256, 64, 128, 128);
  LPathBuilder.QuadTo(10, 192, 250, 250);
  LPath := LPathBuilder.Detach;
  ACanvas.DrawPath(LPath, LPaint);
end;

This code results in the output below:

Translations and Rotations

procedure Draw(const ACanvas: ISkCanvas);
var
  LPaint: ISkPaint;
  LRect: TRectF;
begin
  ACanvas.Clear(TAlphaColors.Null);

  ACanvas.Translate(128, 0);
  ACanvas.Rotate(60);
  LRect := TRectF.Create(TPointF.Create(0, 0), 200, 100);

  LPaint := TSkPaint.Create;
  LPaint.AntiAlias := True;
  LPaint.Color := $FF4285F4;
  ACanvas.DrawRect(LRect, LPaint);

  ACanvas.Rotate(20);
  LPaint.Color := $FFDB4437;
  ACanvas.DrawRect(LRect, LPaint);
end;

This code results in the output below:

Text Rendering

procedure Draw(const ACanvas: ISkCanvas);
var
  LBlob1: ISkTextBlob;
  LBlob2: ISkTextBlob;
  LFont1: ISkFont;
  LFont2: ISkFont;
  LPaint1: ISkPaint;
  LPaint2: ISkPaint;
  LPaint3: ISkPaint;
  LTypeface: ISkTypeface;
begin
  LTypeface := TSkTypeface.MakeFromName('Monospace', TSkFontStyle.Normal);
  LFont1 := TSkFont.Create(LTypeface, 64, 1);
  LFont2 := TSkFont.Create(LTypeface, 64, 1.5);
  LFont1.Edging := TSkFontEdging.AntiAlias;
  LFont2.Edging := TSkFontEdging.AntiAlias;

  LBlob1 := TSkTextBlob.Make('Skia', LFont1);
  LBlob2 := TSkTextBlob.Make('Skia', LFont2);


  LPaint1 := TSkPaint.Create;
  LPaint1.AntiAlias := True;
  LPaint1.SetARGB($FF, $42, $85, $F4);

  LPaint2 := TSkPaint.Create;
  LPaint2.AntiAlias := True;
  LPaint2.SetARGB($FF, $DB, $44, $37);
  LPaint2.Style := TSkPaintStyle.Stroke;
  LPaint2.StrokeWidth := 3;

  LPaint3 := TSkPaint.Create;
  LPaint3.AntiAlias := True;
  LPaint3.SetARGB($FF, $0F, $9D, $58);

  ACanvas.Clear(TAlphaColors.White);
  ACanvas.DrawTextBlob(LBlob1, 20, 64, LPaint1);
  ACanvas.DrawSimpleText('Skia', 20, 154, LFont1, LPaint2);
  ACanvas.DrawTextBlob(LBlob2, 20, 244, LPaint3);
end;

This code results in the output below:

example4

Discrete Path Effects

function Star: ISkPath;
var
  I: Integer;
  LA: Single;
  LC: Single;
  LPathBuilder: ISkPathBuilder;
  LR: Single;
begin
  LR := 115.2;
  LC := 128.0;
  LPathBuilder := TSkPathBuilder.Create;
  LPathBuilder.MoveTo(LC + LR, LC);
  for I := 1 to 7 do
  begin
    LA := 2.6927937 * I;
    LPathBuilder.LineTo(LC + LR * Cos(LA), LC + LR * Sin(LA));
  end;
  Result := LPathBuilder.Detach;
end;

procedure Draw(const ACanvas: ISkCanvas);
var
  LPaint: ISkPaint;
  LPath: ISkPath;
begin
  LPaint := TSkPaint.Create;
  LPaint.PathEffect := TSkPathEffect.MakeDiscrete(10, 4);
  LPaint.Style := TSkPaintStyle.Stroke;
  LPaint.StrokeWidth := 2;
  LPaint.AntiAlias := True;
  LPaint.Color := $FF4285F4;
  ACanvas.Clear(TAlphaColors.White);
  LPath := Star;
  ACanvas.DrawPath(LPath, LPaint);
end;

This code results in the output below:

example5

Composed Path Effects

function Star: ISkPath;
var
  I: Integer;
  LA: Single;
  LC: Single;
  LPathBuilder: ISkPathBuilder;
  LR: Single;
begin
  LR := 115.2;
  LC := 128.0;
  LPathBuilder := TSkPathBuilder.Create;
  LPathBuilder.MoveTo(LC + LR, LC);
  for I := 1 to 7 do
  begin
    LA := 2.6927937 * I;
    LPathBuilder.LineTo(LC + LR * Cos(LA), LC + LR * Sin(LA));
  end;
  Result := LPathBuilder.Detach;
end;

procedure Draw(const ACanvas: ISkCanvas);
var
  LPaint: ISkPaint;
  LPath: ISkPath;
  LIntervals: TArray<Single>;
  LDashPathEffect: ISkPathEffect;
  LDiscretePathEffect: ISkPathEffect;
begin
  LIntervals := [10, 5, 2, 5];
  LDashPathEffect := TSkPathEffect.MakeDash(LIntervals, 0);
  LDiscretePathEffect := TSkPathEffect.MakeDiscrete(10, 4);
  LPaint := TSkPaint.Create;
  LPaint.PathEffect := TSkPathEffect.MakeCompose(LDashPathEffect, LDiscretePathEffect);
  LPaint.Style := TSkPaintStyle.Stroke;
  LPaint.StrokeWidth := 2;
  LPaint.AntiAlias := True;
  LPaint.Color := $FF4285F4;
  ACanvas.Clear(TAlphaColors.White);
  LPath := Star;
  ACanvas.DrawPath(LPath, LPaint);
end;

This code results in the output below:

example6

Sum Path Effects

function Star: ISkPath;
var
  I: Integer;
  LA: Single;
  LC: Single;
  LPathBuilder: ISkPathBuilder;
  LR: Single;
begin
  LR := 115.2;
  LC := 128.0;
  LPathBuilder := TSkPathBuilder.Create;
  LPathBuilder.MoveTo(LC + LR, LC);
  for I := 1 to 7 do
  begin
    LA := 2.6927937 * I;
    LPathBuilder.LineTo(LC + LR * Cos(LA), LC + LR * Sin(LA));
  end;
  Result := LPathBuilder.Detach;
end;

procedure Draw(const ACanvas: ISkCanvas);
var
  LPaint: ISkPaint;
  LPath: ISkPath;
  LIntervals: TArray<Single>;
  LDashPathEffect1: ISkPathEffect;
  LDashPathEffect2: ISkPathEffect;
begin
  LIntervals := [10, 5, 2, 5];
  LDashPathEffect1 := TSkPathEffect.MakeDiscrete(10, 4);
  LDashPathEffect2 := TSkPathEffect.MakeDiscrete(10, 4, 1245);
  LPaint := TSkPaint.Create;
  LPaint.PathEffect := TSkPathEffect.MakeSum(LDashPathEffect1, LDashPathEffect2);
  LPaint.Style := TSkPaintStyle.Stroke;
  LPaint.StrokeWidth := 2;
  LPaint.AntiAlias := True;
  LPaint.Color := $FF4285F4;
  ACanvas.Clear(TAlphaColors.White);
  LPath := Star;
  ACanvas.DrawPath(LPath, LPaint);
end;

This code results in the output below:

example7

Shaders

function Star: ISkPath;
var
  I: Integer;
  LA: Single;
  LC: Single;
  LPathBuilder: ISkPathBuilder;
  LR: Single;
  LR2: Single;
begin
  LR := 60;
  LC := 128.0;
  LPathBuilder := TSkPathBuilder.Create;
  LPathBuilder.MoveTo(LC + LR, LC);
  for I := 1 to 14 do
  begin
    LA := 0.44879895 * I;
    LR2 := LR + LR * (I mod 2);
    LPathBuilder.LineTo(LC + LR2 * Cos(LA), LC + LR2 * Sin(LA));
  end;
  Result := LPathBuilder.Detach;
end;

procedure Draw(const ACanvas: ISkCanvas);
var
  LPaint: ISkPaint;
  LPath: ISkPath;
begin
  LPaint := TSkPaint.Create;
  LPaint.PathEffect := TSkPathEffect.MakeDiscrete(10, 4);
  LPaint.Shader := TSkShader.MakeGradientLinear(TPointF.Create(0, 0), TPointF.Create(256, 256), [$ff4285F4, $ff0F9D58], TSkTileMode.Clamp);
  LPaint.AntiAlias := True;
  ACanvas.Clear(TAlphaColors.White);
  LPath := Star;
  ACanvas.DrawPath(LPath, LPaint);
end;

This code results in the output below:

example8

Text RTL

The example below demonstrates how to render a Persian sentence using a text-shaping engine:

procedure Draw(const ACanvas: ISkCanvas);
var
  LBlob: ISkTextBlob;
  LFont: ISkFont;
  LPaint: ISkPaint;
  LRunHandler: ISkTextBlobBuilderRunHandler;
  LShaper: ISkShaper;
  LText: string;
begin
  ACanvas.Clear(TAlphaColors.Null);
  LFont := TSkFont.Create(TSkTypeface.MakeDefault, 35, 1);
  LText := '!سلام دنیا';

  LRunHandler := TSkTextBlobBuilderRunHandler.Create(LText, TPointF.Create(0, 0));
  LShaper := TSkShaper.Create;
  LShaper.Shape(LText, LFont, True, MaxSingle, LRunHandler);
  LBlob := LRunHandler.Detach;

  LPaint := TSkPaint.Create;
  LPaint.AntiAlias := True;
  LPaint.Color := TAlphaColors.Tomato;

  ACanvas.DrawTextBlob(LBlob, 0, 0, LPaint);
end;

This code results in the output below:

text_rtl

Custom Fonts

With skia, you can easily use custom fonts in your texts, without having to install fonts, just have the ttf file. You will find an example of how to use custom font in our sample. See the result of the sample using 2 custom fonts:

text_custom_font

Paragraph

With the skia SkParagraph, you can render texts with multiple styles, fonts, sizes, and with many settings like the maximum number of lines. The example below demonstrates how to render with SkParagraph:

var
  LBitmap: TBitmap;
begin
  LBitmap := TBitmap.Create(440, 440);
  try
    LBitmap.SkiaDraw(
      procedure (const ACanvas: ISkCanvas)
      var
        LParagraph: ISkParagraph;
        LBuilder: ISkParagraphBuilder;
        LTextStyle: ISkTextStyle;
        LParagraphStyle: ISkParagraphStyle;
      begin
        LParagraphStyle := TSkParagraphStyle.Create;
        LParagraphStyle.TurnHintingOff;
        LParagraphStyle.MaxLines := 3;
        LParagraphStyle.Ellipsis := '...';
        LBuilder := TSkParagraphBuilder.Create(LParagraphStyle);

        LTextStyle := TSkTextStyle.Create;
        LTextStyle.Color := TAlphaColors.Black;
        LTextStyle.SetFontSize(28);
        LTextStyle.SetFontStyle(TSkFontStyle.Create(TSkFontWeight.Light, TSkFontWidth.Normal, TSkFontSlant.Upright));
        LBuilder.PushStyle(LTextStyle);
        LBuilder.AddText('English English 字典 字典 😀😅😂😂');

        LTextStyle := TSkTextStyle.Create;
        LTextStyle.Color := TAlphaColors.Crimson;
        LTextStyle.SetFontSize(22);
        LTextStyle.SetFontStyle(TSkFontStyle.Create(TSkFontWeight.SemiBold, TSkFontWidth.Normal, TSkFontSlant.Upright));
        LBuilder.PushStyle(LTextStyle);
        LBuilder.AddText(' !سلام دنیا');

        LTextStyle := TSkTextStyle.Create;
        LTextStyle.Color := TAlphaColors.Blueviolet;
        LTextStyle.SetFontSize(30);
        LTextStyle.SetFontStyle(TSkFontStyle.Create(TSkFontWeight.ExtraBold, TSkFontWidth.Normal, TSkFontSlant.Italic));
        LBuilder.PushStyle(LTextStyle);
        LBuilder.AddText(' World domination is such an ugly phrase - I prefer to call it world optimisation.');

        LParagraph := LBuilder.Detach;
        LParagraph.Layout(LBitmap.Width);
        LParagraph.Render(ACanvas, 0, 0);
      end);

    LBitmap.SaveToFile('output.png');
  finally
    LBitmap.Free;
  end;
end;

This code results in the output below:

text_paragraph

PDF

With skia you can create PDF documents and draw anything on them, from text to images. The example below demonstrates how to create an PDF document and draw an SVG inside it:

var
  LCanvas: ISkCanvas;
  LDocument: ISkDocument;
  LDOM: ISkSVGDOM;
  LPDFStream: TStream;
  LSize: TSizeF;
  LSVGStream: TStream;
begin
  LSVGStream := TFileStream.Create('Assets\Samples\lion.svg', fmOpenRead or fmShareDenyWrite);
  try
    LDOM := TSkSVGDOM.Make(LSVGStream);
  finally
    LSVGStream.Free;
  end;
  LSize := TSizeF.Create(600, 600);
  LDOM.SetContainerSize(LSize);

  LPDFStream := TFileStream.Create('output.pdf', fmCreate);
  try
    LDocument := TSkPDFDocument.Create(LPDFStream);
    try
      LCanvas := LDocument.BeginPage(LSize.Width, LSize.Height);
      try
        LDOM.Render(LCanvas);
      finally
        LDocument.EndPage;
      end;
    finally
      LDocument.Close;
    end;
  finally
    LPDFStream.Free;
  end;
end;

The example above with Assets/Samples/lion.svg SVG file results in the output below:

WebP

WebP is a modern image format that provides superior lossless and lossy compression for images. WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent quality.

The example below demonstrates how to encoder to WebP format:

var
  LImage: ISkImage;
begin
  LImage := TSkImage.MakeFromEncoded(TFile.ReadAllBytes('Assets\Samples\kung_fu_panda.png'));
  TFile.WriteAllBytes('output.webp', LImage.EncodeToBytes(TSkEncodedImageFormat.WEBP, 80));
  TFile.WriteAllBytes('output.jpg', LImage.EncodeToBytes(TSkEncodedImageFormat.JPEG, 80));
end;

This code results in the output below:

Format Size
Png (100% quality) 512 KB
Jpeg (80% quality) 65.1 KB
WebP (80% quality) 51.6 KB

Controls

Some controls that help implement skia in your VCL or FMX app:

PaintBox

TSkPaintBox is the ideal control for painting directly on the canvas with the event OnDraw:

procedure TForm1.SkPaintBox1Draw(ASender: TObject; const ACanvas: ISkCanvas;
  const ADest: TRectF; const AOpacity: Single);
var
  LPaint: ISkPaint;
begin
  LPaint := TSkPaint.Create;
  LPaint.setShader(TSkShader.MakeGradientSweep(ADest.CenterPoint,
    [$FFFCE68D, $FFF7CAA5, $FF2EBBC1, $FFFCE68D]));
  ACanvas.DrawPaint(LPaint);
end;

The example above results in the output below:

paintbox

Note: The TSkPaintBox has a drawing caching system. To force a drawing refresh, call TSkPaintBox.Redraw.

SVG

TSkSvg is the control to load and display svgs easily:

var
  LSvg: TSkSvg;
begin
  LSvg := TSkSvg.Create(Self);
  LSvg.Svg.Source := TFile.ReadAllText('Assets\Samples\gorilla.svg');
  LSvg.Parent := Self;
end;

The Assets/Samples/gorilla.svg svg file results in the output below:

Read more details in the svg documentation.

Lottie (animation player)

Lottie files are vector animations in json format exported from Adobe After Effects. Like SVG, Lottie file is also a small file but capable of producing high quality animations. The example below demonstrates how to play lottie files using our TSkLottieAnimation:

var
  LLottie: TSkLottieAnimation;
begin
  LLottie := TSkLottieAnimation.Create(Self);
  LLottie.LoadFromFile('Assets\Samples\rocket.json');
  LLottie.Parent := Self;
end;

The Assets/Samples/rocket.json file animation results in the output below:

skottie

We also improved TSkLottieAnimation to support Telegram stickers (tgs files). Read more about this and other details in the lottie documentation.

TBitmap integration

It is possible to edit TBitmap (VCL or FMX) with Skia's Canvas using the code below:

var
  LBitmap: TBitmap;
begin
  LBitmap := TBitmap.Create(100, 100);
  try
    LBitmap.SkiaDraw(
      procedure (const ACanvas: ISkCanvas)
      begin
        // Draw with skia canvas...
      end);

It is possible to convert an TBimap do ISkImage too, when you need to draw an TBitmap inside an skia draw, using LBitmap.ToSkImage

Debug

The TSkDebug.DebugMessageProc global property defines the procedure that intercepts messages sent by Skia's SkDebugf. By compiling the Skia library in Debug mode it will be possible to detect bugs easily.

Limitations

  • Unsupported platforms: iOS32, iOSSimulator and OSX32
  • Delphi 10.3 Rio or older, supports only windows platform
  • No support available for versions prior to Delphi XE6
  • SVG limitations

Version

Skia4Delphi Version 2.0.1

Skia Version used: chrome/m88 What has changed from the original code? Compare.

skia4delphi's People

Contributors

viniciusfbb avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.