Jump to content

vfbb

Members
  • Content Count

    278
  • Joined

  • Last visited

  • Days Won

    30

Everything posted by vfbb

  1. vfbb

    ANN: Skia4Delphi 4.0.1 compilation error

    Hi David! What is the exact version you are using? It looks like 11.2, but here on 11.2 Enterprise it works fine. Does this occur on a blank project? Have you tried deleting the output folder of the project? (maybe there is conflict with old dcu)
  2. vfbb

    ANN: Skia4Delphi v4.0.0

    v4.0.1 Added option to "Enable Skia" in dll projects; [Plugin] Fixed AV with GPU canvas; [Render] Fixed exceptions with OpenGLES backend on Android; [Render] Fixed issue with creating bitmap cache (texture); [Render] Fixed 3D controls (TViewPort3D) rendering with OpenGLES backend; [Render] Fixed wrong draw of text with attributes in TTextLayout; [Render] Minor improvements. Skia version: 107.0.0
  3. vfbb

    How can i add a custom font to a windows fmx application

    You should use the font family name (which is not necessarily the same as the file name) in family property of controls. One problem you will face is that this property in designtime only lists the fonts registered on your system, so you must install the font on your system (by double clicking on it), and reopen your IDE, so that you can select your font on the Family property. Note: only you will install the font on the system (to be able to select it inside the IDE), your clients will not need it.
  4. vfbb

    How can i add a custom font to a windows fmx application

    @Linuxuser1234 To be clearer, follow the steps: Install Skia4Delphi via GetIt or by downloading the installer from github. Enable the use of Skia in your project: right click on the project > "Enable Skia" Open your project's dpr to enable Skia as your app's renderer and to register the custom font you want: uses System.StartUpCopy, FMX.Forms, Skia, // << Skia.FMX, // << Unit1 in 'Unit1.pas' {Form1}; {$R *.res} begin GlobalUseSkia := True; // << TSkTypefaceManager.RegisterTypeface('C:\Boltgui\Popups\Font\DSEG14ClassicMini-Bold.ttf'); // << Application.Initialize; ...
  5. vfbb

    How can i add a custom font to a windows fmx application

    Another option that works in XE7+ and cross-platform is use the Skia4delphi as your app render. Then you only need to add the follow code in the app initialization: initialization TSkTypefaceManager.RegisterTypeface('Material Design Icons Desktop.ttf');
  6. You can try with refit unit https://github.com/viniciusfbb/ipub-refit The implementation could be something like this: unit MerchantApi; interface uses iPub.Rtl.Refit; // https://github.com/viniciusfbb/ipub-refit type TCountry = (MG); TCurrency = (MGA); TPaymentSubscriber = record Country: TCountry; Currency: TCurrency; Msisdn: Cardinal; end; TPaymentTransaction = record Amount: Integer; Country: TCountry; Currency: TCurrency; Id: string; end; TPaymentRequest = record Reference: string; Subscriber: TPaymentSubscriber; Transaction: TPaymentTransaction; end; [BaseUrl('https://API_server_host/merchant/v1')] IMerchantApi = interface(IipRestApi) ['{1D10C463-1567-4DE0-88F2-099CC0442E43}'] [Post('/payments')] [Headers('Authorization', 'Bearer {AuthToken}')] [Headers('X-Country', '{XCountry}')] [Headers('X-Currency', '{XCurrency}')] function Payments(AXCountry: TCountry; AXCurrency: TCurrency; const ABody: TPaymentRequest): string; function GetAuthToken: string; procedure SetAuthToken(const AValue: string); property AuthToken: string read GetAuthToken write SetAuthToken; end; var FMerchantApi: IMerchantApi; implementation initialization FMerchantApi := GRestService.&For<IMerchantApi>; end. And your code could be this: uses MerchantApi; procedure TForm1.FormCreate(Sender: TObject); var LPaymentRequest: TPaymentRequest; begin LPaymentRequest.Reference := 'Testing API'; LPaymentRequest.Subscriber.Country := TCountry.MG; LPaymentRequest.Subscriber.Currency := TCurrency.MGA; LPaymentRequest.Subscriber.Msisdn := 331170348; LPaymentRequest.Transaction.Amount := 1000; LPaymentRequest.Transaction.Country := TCountry.MG; LPaymentRequest.Transaction.Currency := TCurrency.MGA; LPaymentRequest.Transaction.Id := 'FE9833FE-D5A3-4450-9786-90735F75EBFB'; FMerchantApi.AuthToken := 'koeQidreesddfzsbxOXKjccccccc'; ShowMessage(FMerchantApi.Payments(TCountry.MG, TCurrency.MGA, LPaymentRequest)); end;
  7. Yes! See a very simple sample: uses System.Net.HttpClient, System.Net.Mime, Skia, Skia.FMX {or Skia.Vcl}; function SendBitmap(const AUrl: string; ABitmap: TBitmap): string; var LRequest: THTTPClient; LFormData: TMultipartFormData; LResponse: TStringStream; begin LRequest := THTTPClient.Create; LFormData := TMultipartFormData.Create; LResponse := TStringStream.Create; try LFormData.AddBytes('img', ABitmap.ToSkImage.EncodeToStream(LImageStream, TSkEncodedImageFormat.WEBP, 80)); LRequest.Post(AUrl, LFormData, LResponse); Result := LResponse.DataString; finally LFormData.Free; LResponse.Free; LRequest.Free; end; end; This is a simple example for you to understand how it works. In practice I use something different. On the client (API consumer), I declare the whole API in a single unit using the Refit library. This removes a lot of complexity throughout the project, as it already magically serializes records and classes, query parameters, headers automatically. The example above using Refit would look like this: This is the unit of your api for the client-side (consumer): unit MyApiConsumer; interface uses System.SysUtils, iPub.Rtl.Refit; // https://github.com/viniciusfbb/ipub-refit type [BaseUrl('http://localhost/api/v1')] IMyAPI = interface(IipRestApi) ['{1D10C463-1567-4DE0-88F2-099CC0442E43}'] [Post('/image-upload')] [ContentType(TBodyKind.MultipartFormData)] function TryImageUpload(const [Body] AImg: TBytes; out AResponse: string): Boolean; end; var FMyApi: IMyAPI; implementation initialization FMyApi := GRestService.&For<IMyAPI>; end. And in your code: uses MyApiConsumer, Skia, Skia.FMX {or Skia.Vcl}; function SendBitmap(ABitmap: TBitmap): string; begin if not FMyApi.TryImageUpload(ABitmap.ToSkImage.EncodeToStream(LImageStream, TSkEncodedImageFormat.WEBP, 80), Result) then Result := 'Failed!'; end;
  8. Don't use json. I usually send via MultipartFormData, encoded in WebP with 80% quality, as it is practically identical to the original. See attached the original png image of 2292 KB and the WebP with 80% quality resulting in 61 KB. photo.webp
  9. Goal: I have configured my app to be opened by some links in iOS, like myapp://lala (using custom scheme), or https://myapp.com/c/lala using universal links, and is already opening my app, but i need to know which url that opened my app. (There is even a tutorial in FMX Express) Problem: I'm trying to handle incoming url from my ios app unsuccessfully. On iOS this should be done by capturing event TApplicationEvent.OpenURL like: procedure TipUrlHandler.ApplicationEventMessageHandler(const ASender: TObject; const AMessage: TMessage); begin case TApplicationEventData(TApplicationEventMessage(AMessage).Value).Event of TApplicationEvent.OpenUrl: HandleUrl(TiOSOpenApplicationContext(TApplicationEventData(TApplicationEventMessage(AMessage).Value).Context).URL); else end; end; Mas o TApplicationEvent.OpenUrl nunca é chamado. So I checked the class TApplicationDelegate in the unit FMX.Platform.iOS.pas in which the TApplicationDelegate.applicationOpenURLWithOptions function should be called every time the app is opened by a url as Apple documents: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application?language=objc class function TApplicationDelegate.applicationOpenURLWithOptions(self: id; _cmd: SEL; application: PUIApplication; url: Pointer; options: PNSDictionary): Boolean; So I went to check if the applicationOpenURLWithOptions method is being added correctly in TApplicationDelegate.CreateDelegateMetaClass: class procedure TApplicationDelegate.CreateDelegateMetaClass; begin ... // Opening a URL-Specified Resource if TOSVersion.Major >= 9 then class_addMethod(DelegateClass, sel_getUid('application:openURL:options:'), @applicationOpenURLWithOptions, 'B@:@@@@') else ... end; And then I was able to prove it wrong! The number of arguments declared is wrong, as the correct one should be B@:@@@ Then I made the modification to FMX.Platform.iOS.pas, being as follows: class procedure TApplicationDelegate.CreateDelegateMetaClass; begin ... // Opening a URL-Specified Resource if TOSVersion.Major >= 9 then class_addMethod(DelegateClass, sel_getUid('application:openURL:options:'), @applicationOpenURLWithOptions, 'B@:@@@') else ... end; But the TApplicationDelegate.applicationOpenURLWithOptions function is not yet called. What is wrong? @EDIT Sorry! It is working for custom schemes like "myapp://lala" (with or without the correction in FMX.Platform.iOS.pas) but it is not working for universal links like https://myapp.com/c/lalala. Although I have already configured the universal link correctly and when I click on this universal link, the iOS open my app, but the url can't be handle with TApplicationEvent.OpenUrl, but I discovered that the handling of incoming url of a universal link is different: Handling Universal Links
  10. vfbb

    svg

    Also Skia4Delphi (FMX & VCL). If it's just VCL, SVGIconImageList is the one that has better integration with Delphi controls because it has a TSVGIconImageCollection and TSVGIconVirtualImageList.
  11. vfbb

    Printing from Android Device

    I've never tried to print anything on Android, but on iOS, when sharing a PDF, the "Print" option appears in the system menu. If this happens on Android, it would be a very simple solution to implement. To make the PDF just use Skia4delphi, and to share the PDF, it's very simple, I even have a code ready (if you confirm that this solution works, I'll send it to you).
  12. v3.4.0 Added StrokeColor property to TSkLabel; Added LetterSpacing property to TSkLabel; Added automatically Skia to uses when use controls in form; Added EncodedImageFormat property and MakeFromStream to SkCodec; Added MakeRawShader to SkImage; Added MakeImage to SkRuntimeEffects; Exposed DirectContext in TGrCanvasCustom class to run code on the GPU more easily; Fixed BackgroundColor property of TSkLabel; Fixed issue loading bitmaps from stream when using Skia in Vcl project; Fixed build script with python3 as default; Minor improvements and fixes. New StrokeColor property of TSkLabel Github: github.com/skia4delphi/skia4delphi Website: skia4delphi.org
  13. vfbb

    ANN: Skia4Delphi v3.4.0

    Skia.pas has a version: https://github.com/skia4delphi/skia4delphi/blob/d6feb7784c90623cef5b8948b12a5239eea2e4a0/Source/Skia.pas#L36 The latest version is 3.4.0. We will release a major version in few weeks.
  14. That's why I made a topic warning that Weak is not thread safe (confirmed by @Dalija Prasnikar). So cast Weak to strong reference, and even if the strong reference is not nil, it can represent a destroyed object, generating a totally random AV, and this is not documented anywhere on the internet. More information: https://en.delphipraxis.net/topic/4020-weak-reference-is-dangerous/?tab=comments#comment-34379
  15. @3delite Loading dynamic libraries on Android is not that trivial, you will still have problems on some devices of some manufacturers. Here are 3 main tips: 1) Filename: ALWAYS suffix "lib", like "libbass.so" 2) Deployment: On 32bit, the remote path "library\lib\armeabi-v7a\" On 64bit, the remote path "library\lib\arm64-v8a\" Also on 64bit, add the 32bit binary with the remote path "library\lib\armeabi-v7a\" and the condition "'$(AndroidAppBundle)''==''true'" (with the quotes). The condition you can only change via ToolsApi or manually in .dproj. See how we do it: https://github.com/skia4delphi/skia4delphi/blob/eed4afbf8a34137a9bfa308bcb5ef87cee84abcb/Source/VCL/Designtime/Skia.Vcl.Designtime.ProjectMenu.pas#L219-L221 3) Loading: First try to load using only the filename, and in case of failure use the library path + filename. See how we do it: https://github.com/skia4delphi/skia4delphi/blob/eed4afbf8a34137a9bfa308bcb5ef87cee84abcb/Source/Skia.API.pas#L2119-L2124
  16. vfbb

    Performance monitor for FMX macOS?

    Moving away from the profile issue and talking specifically about the CPU usage of FMX on macOS, the same can be related to the use or not of metal. I advise using GlobalUseMetal := True; to take some of the CPU load off.
  17. vfbb

    Rounded polygon

    Here's an example: uses Skia; function MakeCubicSplineInterpolation(const APoints: TArray<TPointF>): ISkPath; var LPathBuilder: ISkPathBuilder; LSegments: Integer; I: Integer; mx: Single; my: Single; LScratches: array of record a, b, c, r, p: TPointF; end; begin LPathBuilder := TSkPathBuilder.Create; if Length(APoints) < 2 then Exit(LPathBuilder.Detach); if Length(APoints) = 2 then begin LPathBuilder.MoveTo(APoints[0]); LPathBuilder.LineTo(APoints[1]); Exit(LPathBuilder.Detach); end; LSegments := Length(APoints) - 1; SetLength(LScratches, LSegments); LScratches[0].a := PointF(0, 0); LScratches[0].b := PointF(2, 2); LScratches[0].c := PointF(1, 1); LScratches[0].r := PointF(APoints[0].X + 2 * APoints[1].X, APoints[0].Y + 2 * APoints[1].Y); for I := 1 to LSegments - 2 do begin LScratches[I].a := PointF(1, 1); LScratches[I].b := PointF(4, 4); LScratches[I].c := PointF(1, 1); LScratches[I].r := PointF(4 * APoints[i].X + 2 * APoints[I + 1].X, 4 * APoints[I].Y + 2 * APoints[I + 1].Y); end; LScratches[LSegments - 1].a := PointF(2, 2); LScratches[LSegments - 1].b := PointF(7, 7); LScratches[LSegments - 1].c := PointF(0, 0); LScratches[LSegments - 1].r := PointF(8 * APoints[LSegments - 1].X + APoints[LSegments].X, 8 * APoints[LSegments - 1].Y + APoints[LSegments].Y); for I := 1 to LSegments - 1 do begin mx := LScratches[I].a.X / LScratches[I - 1].b.X; my := LScratches[I].a.Y / LScratches[I - 1].b.Y; LScratches[I].b := LScratches[I].b - PointF(mx * LScratches[I - 1].c.X, my * LScratches[I - 1].c.Y); LScratches[I].r := LScratches[I].r - PointF(mx * LScratches[I - 1].r.X, my * LScratches[I - 1].r.Y); end; LScratches[LSegments - 1].p := PointF(LScratches[LSegments - 1].r.X / LScratches[LSegments - 1].b.X, LScratches[LSegments - 1].r.Y / LScratches[LSegments - 1].b.Y); for I := Length(APoints) - 3 downto 0 do begin LScratches[I].p := PointF((LScratches[I].r.X - LScratches[I].c.X * LScratches[I + 1].p.X) / LScratches[I].b.X, (LScratches[I].r.Y - LScratches[I].c.Y * LScratches[I + 1].p.Y) / LScratches[I].b.Y); end; LPathBuilder.MoveTo(APoints[0]); for I := 0 to LSegments - 2 do begin LPathBuilder.CubicTo(LScratches[I].p, PointF(2 * APoints[I + 1].X - LScratches[I + 1].p.X, 2 * APoints[I + 1].Y - LScratches[I + 1].p.Y), APoints[I + 1]); end; LPathBuilder.CubicTo(LScratches[LSegments - 1].p, PointF(0.5 * (APoints[LSegments].X + LScratches[LSegments - 1].p.X), 0.5 * (APoints[LSegments].Y + LScratches[LSegments - 1].p.Y)), APoints[LSegments]); Result := LPathBuilder.Detach; end; procedure TForm1.SkPaintBox1Draw(ASender: TObject; const ACanvas: ISkCanvas; const ADest: TRectF; const AOpacity: Single); var LPaint: ISkPaint; LMyPoints: TArray<TPointF>; begin LMyPoints := [PointF(62, 511), PointF(162, 605), PointF(262, 610), PointF(362, 402), PointF(462, 959), PointF(562, 58), PointF(662, 272), PointF(762, 99), PointF(862, 759), PointF(962, 945)]; LPaint := TSkPaint.Create(TSkPaintStyle.Stroke); LPaint.Color := TAlphaColors.Red; LPaint.AntiAlias := True; LPaint.StrokeWidth := 3; LPaint.StrokeCap := TSkStrokeCap.Round; ACanvas.DrawPath(MakeCubicSplineInterpolation(LMyPoints), LPaint); LPaint.StrokeWidth := 10; LPaint.Color := TAlphaColors.Black; ACanvas.DrawPoints(TSkDrawPointsMode.Points, LMyPoints, LPaint); end; Result: Note: You don't need to use Skia, it was just a facilitator for the example.
  18. vfbb

    Rounded polygon

    If you don't mind third-party solutions, Skia has an effect that applies rounded edges automatically and works for Console, Vcl and FMX: https://github.com/skia4delphi/skia4delphi/blob/eed4afbf8a34137a9bfa308bcb5ef87cee84abcb/Samples/Demo/FMX/Source/Sample.Form.PathsAndEffects.pas#L193 Result:
  19. We started porting the Skia4Delphi library to C++Builder and we came across a problem in the static linking of objects, specifically linking the file “/usr/lib/clang/lib/darwin/libclang_rt.ios.a” which is in the SDK path (ex: “C:\Users\<username>\Documents\Embarcadero\Studio\SDKs\iPhoneOS15.2.sdk\usr\lib\clang\lib\darwin\libclang_rt.ios.a”) In Delphi, this linking is very simple to do. We can simply declare a fake method and add the external '/<sdk_sub_path>/<filename>.a', which is exactly what we do in our Delphi implementation: procedure libcompiler_rt; external '/usr/lib/clang/lib/darwin/libclang_rt.ios.a'; In C++Builder however, we didn't find anything similar. So far we've only been able to force this link in two different (but very rudimentary) ways: Method 1 - Configuring project linking: Adding to the project library path “$(BDSPLATFORMSDKSDIR)\<DefaultPlatformSDK>\usr\lib\clang\lib\darwin\” Note: This is necessary because although some SDK paths are automatically passed to the linker, this is not. Adding the command -lclang_rt.ios to the project link The problem with this method is that apparently there is no environment variable for the <DefaultPlatformSDK>, and adding only relative paths, in this case “\usr\lib\clang\lib\darwin\”, doesn't work. We also tried “$(SDKROOT)\usr\lib\clang\lib\darwin\” but to no avail. Method 2 – Adding objects to the project Directly add the file “libclang_rt.ios.a” to the project. It also works, but this is also a bad option. Questions Is there any other way to force link an SDK object in C++Builder? It would be nice to have a simple solution that requires no configuration: #pragma link "/usr/lib/clang/lib/darwin/libclang_rt.ios.a" // But this don't work Would there be any variables we could use to represent the path of the SDK being used? (Ex: “$(SDKROOT)\usr\lib\clang\lib\darwin\”)
  20. vfbb

    Change splash_image_def.xml by default

    This can be avoided by simply disabling it from the project deployment and creating yours with the same remotedir and remotename. Whenever possible, it's better to do this in your project than in the default delphi files, because you won't be able to share your project with someone else without them having the same issue unless they also edit their default splash . Here's a practical example of a project that does this: https://github.com/skia4delphi/skia4delphi/tree/main/Samples/Webinar - Demo/FMX
  21. Make a cool demo using Skia4Delphi and Delphi 11.1 Alexandria, post it on GitHub, be the envy of all your friends, and maybe win a new M1 Mac Mini! Visit the official contest page: Skia4Delphi GUI Beauty Contest See also the latest Skia4Delphi webinar: Supercharge Your User Interface with Skia4Delphi - Webinar Replay - YouTube
  22. vfbb

    ANN: Skia4Delphi v3.4.0

    Can you send me your lottie file? Official skia documentation is incomplete, but it helps. The official skia api is very similar to Skia4Delphi, just few methods and functions have been renamed for readability. I imagine you want to know more about custom shaders. They are made in SKSL language, using the SkRuntimeEffect class to build the shader. See some useful links below: SKSL doc: https://skia.org/docs/user/sksl/ SKSL playground: https://shaders.skia.org/ SkiaSimpleShaderViewer - Demo using custom shaders in skia4delphi: https://github.com/jimmckeeth/SkiaSimpleShaderViewer BricksGame - Game using custom shaders in skia4delphi: https://github.com/skia4delphi/skia4delphi/tree/main/Samples/Webinar - Game/FMX Skia4Delphi Demo using custom shaders in two units: https://github.com/skia4delphi/skia4delphi/blob/main/Samples/Demo/FMX/Source/Sample.Form.RuntimeEffects.pas https://github.com/skia4delphi/skia4delphi/blob/main/Samples/Demo/FMX/Source/Sample.Form.Filter.pas There is also new documentation from the android team, which is AGSL section. Android Graphics Shader Language (AGSL) is Skia Shader Language (SKSL), the android team just changed the name: https://developer.android.com/guide/topics/graphics/agsl You can also solve all your doubts on our telegram channel: https://t.me/skia4delphi
  23. vfbb

    ANN: Skia4Delphi v3.4.0

    AE covers all kinds of animation, there are effects and raster features, for example, that would not even make sense to be supported in lottie, because the idea of lottie is to be vectorized and lightweight. Lastly, lottie and the bodymovin plugin are constantly developing and adding new features every day, so blogs from 1 year ago may no longer reflect reality.
  24. vfbb

    ANN: Skia4Delphi v3.4.0

    There are several limitations of Adobe After Effects to lottie (using bodymovin plugin) and they are not very well documented. This site lists some: https://www.elpassion.com/blog/lottie-who-common-mistakes-in-after-effects-animation-for-lottie Your case may have something to do with Keyframe or expressions...
  25. vfbb

    ANN: Skia4Delphi v3.4.0

    No truly interactive animations. But you could create these iterations artificially. Consider this example: https://lottiefiles.com/5222-switch between progress 0% to 50% is the animation enabling a switch, and progress 50% to 100% is the animation disabling a switch. Based on that you can configure the animation in your control so that when you click it execute the progress from 0% to 50% or from 50% to 100%. Note: Currently our TSkAnimatedImage control is capable of running lottie animations but it is not "so tunable". Either it automatically runs the entire animation or you activate the manual mode and change the progress on your own (for example by adding a timer and changing the progress manually every 15 ms). In our next release (in a few weeks) we will improve this a lot, we will add new properties to get better control of the animations in the TSkAnimatedImage control. Yes it is possible with Skia4Delphi. Excluding experimental or deprecated modules, 99% of the library is exposed.
×