Jump to content

vfbb

Members
  • Content Count

    266
  • Joined

  • Last visited

  • Days Won

    30

Posts posted by vfbb


  1. You can use OnClick normally with this code:

    uses
      FMX.Objects, FMX.Math, FMX.Math.Vectors;
    
    type
      TipControl = class(TRectangle)
      private const
        DEFAULT_MOVEMENT_TOLERANCE = 4;
      private
        FAbsolutePressedPoint: TPointF;
        FIsMouseDown: Boolean;
        FIsValidClick: Boolean;
        FLastMouseActivePoint: TPointF;
        FMovementTolerance: Single;
        function IsMovementToleranceStored: Boolean;
      protected
        function CheckHasValidClick: Boolean; virtual;
        procedure Click; override;
        procedure DoClick; virtual;
        procedure MouseDown(AButton: TMouseButton; AShift: TShiftState; X, Y: Single); override;
        procedure MouseMove(AShift: TShiftState; X, Y: Single); override;
        procedure MouseUp(AButton: TMouseButton; AShift: TShiftState; X, Y: Single); override;
      public
        constructor Create(AOwner: TComponent); override;
        property IsValidClick: Boolean read FIsValidClick;
      published
        property MovementTolerance: Single read FMovementTolerance write FMovementTolerance stored IsMovementToleranceStored;
      end;
    
    function TipControl.CheckHasValidClick: Boolean;
    
      function CheckIsMouseOver: Boolean;
      begin
        Result := FIsMouseOver and TouchTargetExpansion.MarginRect(LocalRect).Contains(FLastMouseActivePoint);
      end;
    
    begin
      Result := FIsValidClick and FIsMouseDown and CheckIsMouseOver and
        ((FMovementTolerance = 0) or ((PressedPosition.Distance(FLastMouseActivePoint) <= FMovementTolerance) and
        (FAbsolutePressedPoint.Distance(LocalToAbsolute(FLastMouseActivePoint)) <= FMovementTolerance)));
    end;
    
    procedure TipControl.Click;
    begin
      if Pressed then
      begin
        if not CheckHasValidClick then
          FIsValidClick := False;
        if IsValidClick then
          DoClick;
      end
      else
        DoClick;
    end;
    
    constructor TipControl.Create(AOwner: TComponent);
    begin
      inherited;
      FMovementTolerance := DEFAULT_MOVEMENT_TOLERANCE;
      FLastMouseActivePoint := PointF(-10000,-10000);
    end;
    
    procedure TipControl.DoClick;
    begin
      inherited Click;
    end;
    
    function TipControl.IsMovementToleranceStored: Boolean;
    begin
      Result := not SameValue(FMovementTolerance, DEFAULT_MOVEMENT_TOLERANCE, TEpsilon.Position);
    end;
    
    procedure TipControl.MouseDown(AButton: TMouseButton; AShift: TShiftState; X,
      Y: Single);
    begin
      FAbsolutePressedPoint := LocalToAbsolute(PointF(X, Y));
      FIsValidClick := True;
      FIsMouseDown := True;
      FLastMouseActivePoint := PointF(X, Y);
      inherited;
    end;
    
    procedure TipControl.MouseMove(AShift: TShiftState; X, Y: Single);
    begin
      if CheckHasValidClick then
      begin
        FLastMouseActivePoint := PointF(X, Y);
        if not CheckHasValidClick then
          FIsValidClick := False;
      end
      else
        FLastMouseActivePoint := PointF(X, Y);
      inherited;
    end;
    
    procedure TipControl.MouseUp(AButton: TMouseButton; AShift: TShiftState; X,
      Y: Single);
    var
      LInvalidPressed: Boolean;
    begin
      FLastMouseActivePoint := PointF(X, Y);
      LInvalidPressed := not CheckHasValidClick;
      if LInvalidPressed then
        FIsValidClick := False;
      FIsMouseDown := False;
      inherited;
    end;

     

    • Like 1

  2. 13 hours ago, Antonello said:

    Hello, I would like to integrate freehand drawing into my firemonkey mobile application.

    I tried with the standard tools drawing on a Canvas using the onMouseDown and onMouseMove events ... but the result is always very jagged lines.

    Is it possible with Skia4Delphi to have a better result? I get the drawing like the picture attached here

    Thank you

    Antonello

    Schermata 2021-10-01 alle 18.55.18.png

     

    Made sample here: https://github.com/viniciusfbb/skia4delphi/issues/12#issuecomment-933528854

     

    Result:

    135866542-1ecbe2fe-d8c0-49ac-bad9-b2a3fe0745a1.thumb.png.8e1a5a89c477ff549e8d2035110572c3.png

     

     

    • Like 1

  3. Skia4Delphi-Black.png.94bc9658491fe9fbfdfc4795bb44c97d.png

     

     

    We are very pleased to announce the 2.0 release of the Skia4Delphi project. The library was almost completely rewritten, bringing many new features such as visual components (VCL/FMX), easy installation, easy configuration, miscellaneous error handling, and much more. Now it also has many more features as well as more examples. See main changes:

     

    v2.0.0

     

    • Added support for Delphi 11
    • Added support for OSX ARM 64-bit
    • Added Setup (friendly install)
    • Added IDE plugin to enable the skia in your project: replacing manual changes in project settings, deployment and dlls that were needed before. Now it's automatic, just right click on your project inside the IDE then "Enable Skia"
    • Built-in by default the "icudtl.dat" file in dll
    • Added the controls TSkLottieAnimation, TSkPaintBox and TSkSvg
    • Added SkParagraph (multiple styles in text)
    • Added support for Telegram stickers (using TSkLottieAnimation)
    • Added error handling in sensitive methods
    • Added the source of our website: https://skia4delphi.org
    • Library rewritted
    • Improved the integration with apple's MetalKit
    • Improved library usage, like replacing SkStream to TStream
    • Fixed AccessViolation using TStream
    • Fixed issue with transparent bitmap in Vcl sample
    • Fixed minor issues
    • Explained Svg limitations in documentation
    • We are now using the latest inactive milestone release of Skia (M88), because the others are updated frequently.
    • Deprecated non-windows platforms in Delphi 10.3 Rio or older

     

    Homepage: skia4delphi.org

    GitHub: https://github.com/viniciusfbb/skia4delphi

     

     

     

     

     

    A liittle preview

     

     

    Setup

    installation1.png.9390e469a1285c330adf0cccfbf0eda7.pnginstallation2.png.7f89039665d6b0ee61f099d21e793df8.png

    Just download the Skia4Delphi_2.0.0_Setup.exe attached in Releases page.

     

     

    Enabling your project

    enabling_project.png.d13c060749e8d6be67f55bbae9814729.png

     

     

    Telegram sticker (tgs files):

    telegram_sticker.gif.63664ff8398d45a0504fcc0501c9e302.gif

     

     

    SkParagraph:

    textparagraph.png.0f740e24c74d14c23f542e2316281a76.png

     

     

    WebP:

    kung_fu_panda.webp

    kung_fu_panda.thumb.png.2042f6ab8ba50506d0c20e21d608fcca.png

     

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

     

     

    Controls

    controls.png.78c132e3b402d1a2241c49ff2e8d88ee.png

     

     

     

     

    And much more...

     

     

    • Like 8
    • Thanks 1

  4. 58 minutes ago, Rollo62 said:

    IWhat prerequisites do you need for that, does all modern browser have PDF viewer already integrated ?

    I think Firefox can do that without any AddOn, but I'm not so sure about all the others ( Chrome, Edge ).

    Edge, Firefox and Chrome open any pdf without addon.

    • Like 1

  5. Try this:

    uses
      System.SysUtils, System.IOUtils, Winapi.Windows, Winapi.ShellAPI;
    
    procedure OpenPdf(const AFileName: string);
    var
      LURL: string;
    begin
      LURL := TPath.GetFullPath(AFileName).Replace('\', '/', [rfReplaceAll]);
      LURL := 'file://' + LURL;
      ShellExecute(0, 'open', PChar(LURL), nil, nil, SW_SHOWNORMAL);
    end;

     

    • Sad 1

  6. 4 hours ago, Rollo62 said:

    Do You mean raster images, that have been "vectorized", or any Adobe SVG in general ?

     

    Have you figured out what exactly went wrong in those Adobe files ?

    Maybe there are easy ways to re-convert it ( like open/save with InkScape) to make them running, I will try to check that later.

    I didn't really investigate enough, I just noticed that more complex SVGs converted by Adobe programs weren't being read correctly. I reported this issue to skia and sent two examples of .eps files converted to SVG by adobe and another converter, where adobe's SVG is not rendered and other converters' SVG is rendered.

     

    Examples are attached.

    incompatible_svgs.zip


  7. @Rollo62 @dwrbudr @RDP1974 @Edwin Yip @Kas Ob. @hsauro

     

    I finally released version 1.1 which has been extensively tested on all platforms, which includes a complete demo project, demonstrating how to render svg files, lottie files and more, as well as fixing the issues with backwards compatibility, at the moment the library works on version XE6+ VCL or FMX.

    Skia's SVG module is still in the experimental phase, even though it works extremely well with most SVG files. Some bugs we detected in Skia's SVG module will be reported later today, however, some issues I'll expose here so you can help the community:

    1. Apparently, there is a format incompatibility - vectorized files exported as SVG by Adobe programs are not supported by Skia, however, if you use other online converters (like cloudconvert.com) to convert the .eps or the .ai to svg, it will probably works perfectly.
    2. In macOS depending on the language, the decimal separator is not dot (.), ie the conversion from string to float happens wrong depending on the macOS default system language

    Remarks: These errors are only in relation to the SVG module, which is still in the experimental phase, in addition, Skia is a robust and stable library; If the SVG file works on one platform, it will work the same on all.

     

     

    Changelog

     

    • Added FMX sample (working from delphi XE6 and above, with platforms Win32, Win64, OSX64, iOS64, Android32, Android64);
    • Added VCL sample (working from delphi XE6 and above);
    • Added pre-built binaries of skia to repository, to facilitate implementation and to serve the samples;
    • Updated skia to version 0.29.0;
    • Added icudtl.dat file to windows platform;
    • Fixed text shaping with RTL language;
    • Fixed compilation in iOS;
    • Fixed backwards compatibility with delphi XE6 above;

     

     

    About samples

     

    The samples already have the binaries configured. They are ready to Run.

    • Like 1
    • Thanks 2

  8. 2 hours ago, Edwin Yip said:

    Very very very nice! And thanks for your great efforts in providing the Delphi community this powerful 2D library wrapper!

     

     Two questions:

    - What's the most convenient way to obtain the skia dll without building from source?
      Update:  Sorry, I didn't notice the external skia repository since I use TortoiseSVN to checkout github repos, but there is still not any DLL inside that repository...
     

    - What's the oldest Delphi compiler supported?

     

    Thanks!

     

    Just download the .zip file attached to the release tag, it contains the .dlls, .so and .a.  Externals has an edited version of Skia, with a flat api exclusive to the library. There are instructions for compiling in BUILD.md


     

    2 hours ago, Kas Ob. said:

    Impressive work, and i have 2 points to point

     

    1) While the library mentioned as for XE6+, i can't compile it on XE8 or Seattle, so couldn't try it for myself.

     

    2) About Right to Left Language support 

    textshaping (edit: can't paste the image of the wrong rendered text.)

     

    Well this can't be right, and to my knowledge about Skia itself that it depend on the International Components for Unicode (ICU) project http://site.icu-project.org/ 

    Hence, it will need the ICU data to render such text, combine that with Google Chrome does in fact include a dedicated file contain the ICU project data, also searching the internet i think you will need to provide the ICU data and Skia will be able to render RTL text right.

    Peeking into the included Skia dynamic library, i say it does for a fact look for a file "icudtl.dat" (around 10mb file), which happen to be included in Google Chrome binary folder.

     

    So i would suggest to investigate this and try to make the RTL text render right.

     

     

    Hope that help.

     

     

    ps: @Alexander Sviridenkov Thank you ! you nailed it.

     

     

     

    1. I confess that I only tested the first versions on the XE6, but in fact the code has changed a lot since then. I will fix it.

    2. SkShaper uses Harfbuzz, but your comment was great, because although the example works without icu data, investigating, I realize that to use Harfbuzz there is still a dependency on ICU. For macOS and iOS SkShaper uses CoreText, dispensing with ICU and Harfbuzz, which is great because in the case of iOS the library is static. Anyway, I'm going to investigate and test it on all platforms, even though it worked without icu data. It seems to me that PDF Subset also uses ICU, I'll investigate anyway.

     

    1 hour ago, dwrbudr said:

    Could you please add the source of the Skia Demo to the repository?

    I'll clean up the demo code and create a little more robust example and add it to the repository.

    • Like 1

  9. logo.png.a02d77fbc0197dccce683e74856483dd.png

    Website: github.com/viniciusfbb/skia4delphi

     

    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.

     

    Skia provides a more robust Canvas, being very fast and very stable, with hundreds of features for drawing 2D graphics, in addition to a text shaping engine designed to render texts in the most diverse languages with right-to-left support (such as the Persian language), full support for loading SVG files, support for creating PDF files, support for rendering Lottie files (verotized animations created in Adobe After Effects), integration with the GPU, among countless other cool features.

     

    Skia's idea is similar to Firemonkey's, the same codebase used in an OS will work the same on other platforms. It is also possible to design using the CPU in independent background threads.

     

    Skia also has native codecs, of course if you don't use the SKCodec class, when loading an encoded image it will give priority to using the platform's native codec, but it is possible to use its codec, for example for jpeg files it uses libjpeg-turbo and for png files libpng which maybe in certain environments may perform better than native.

     

    See some examples:

     

     

    Advanced shapes

    stars.thumb.png.31752e6e8c45d5fe26f7e99182267295.png 

     

     

    Advanced text rendering / shaping

    text.png.0dfc8171fc4d3c75d48994ed2098fb61.png

     

     

    Svg

    svg.thumb.png.7300fa0398aeca72b85245e1433df911.png

     

     

    Lottie files

    happy_birthday_white.gif.13a81a12c2feca956ecc1ff4420bb561.gifrocket_white.gif.e7f4391c6ac246a7e70ce0db64d00b48.gifcheck_white.gif.08d88ded1aac70530669ec239b665a7a.gif

     

    And much more...

    • Like 12
    • Thanks 5

  10. 1 hour ago, toufik said:

     

    
    TDialogService.MessageDialog('you are gonna edit something ', TMsgDlgType.mtInformation, [TMsgDlgBtn.mbYes], TMsgDlgBtn.mbYes,0,

    to 

     

     TDialogService.MessageDialog('you are gonna edit something ', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], TMsgDlgBtn.mbYes, 0,

     

     

    Yes, the only button combinations that work on Windows are:

    const
      mbYesNo = [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo];
      mbYesNoCancel = [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo, TMsgDlgBtn.mbCancel];
      mbYesAllNoAllCancel = [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbYesToAll, TMsgDlgBtn.mbNo,
        TMsgDlgBtn.mbNoToAll, TMsgDlgBtn.mbCancel];
      mbOKCancel = [TMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel];
      mbAbortRetryIgnore = [TMsgDlgBtn.mbAbort, TMsgDlgBtn.mbRetry, TMsgDlgBtn.mbIgnore];
      mbAbortIgnore = [TMsgDlgBtn.mbAbort, TMsgDlgBtn.mbIgnore];

     

    • Like 1
    • Thanks 1

  11. If you just want the device model name, I made a function just for it:

     

    uses
      System.SysUtils,
      System.Generics.Collections,
      System.Generics.Defaults,
      Posix.SysSysctl,
      Posix.StdDef;
    
      function GetDeviceModelString: string;
    
        // Pretty names list in https://gist.github.com/adamawolf/3048717
        function GetPrettyName(const AMachine: string): string;
        type
          TAppleDevice = record
            Machine: string;
            Name: string;
          end;
        const
          AppleDevices: array[0..145] of TAppleDevice = (
            (Machine: 'arm64'; Name: 'iPhone Simulator'),
            (Machine: 'i386'; Name: 'iPhone Simulator'),
            (Machine: 'ipad1,1'; Name: 'iPad'),
            (Machine: 'ipad1,2'; Name: 'iPad 3G'),
            (Machine: 'ipad11,1'; Name: 'iPad mini 5th Gen (WiFi)'),
            (Machine: 'ipad11,2'; Name: 'iPad mini 5th Gen'),
            (Machine: 'ipad11,3'; Name: 'iPad Air 3rd Gen (WiFi)'),
            (Machine: 'ipad11,4'; Name: 'iPad Air 3rd Gen'),
            (Machine: 'ipad11,6'; Name: 'iPad 8th Gen (WiFi)'),
            (Machine: 'ipad11,7'; Name: 'iPad 8th Gen (WiFi+Cellular)'),
            (Machine: 'ipad13,1'; Name: 'iPad air 4th Gen (WiFi)'),
            (Machine: 'ipad13,10'; Name: 'iPad Pro 12.9 inch 5th Gen'),
            (Machine: 'ipad13,11'; Name: 'iPad Pro 12.9 inch 5th Gen'),
            (Machine: 'ipad13,2'; Name: 'iPad air 4th Gen (WiFi+Cellular)'),
            (Machine: 'ipad13,4'; Name: 'iPad Pro 11 inch 3rd Gen'),
            (Machine: 'ipad13,5'; Name: 'iPad Pro 11 inch 3rd Gen'),
            (Machine: 'ipad13,6'; Name: 'iPad Pro 11 inch 3rd Gen'),
            (Machine: 'ipad13,7'; Name: 'iPad Pro 11 inch 3rd Gen'),
            (Machine: 'ipad13,8'; Name: 'iPad Pro 12.9 inch 5th Gen'),
            (Machine: 'ipad13,9'; Name: 'iPad Pro 12.9 inch 5th Gen'),
            (Machine: 'ipad2,1'; Name: '2nd Gen iPad'),
            (Machine: 'ipad2,2'; Name: '2nd Gen iPad GSM'),
            (Machine: 'ipad2,3'; Name: '2nd Gen iPad CDMA'),
            (Machine: 'ipad2,4'; Name: '2nd Gen iPad New Revision'),
            (Machine: 'ipad2,5'; Name: 'iPad mini'),
            (Machine: 'ipad2,6'; Name: 'iPad mini GSM+LTE'),
            (Machine: 'ipad2,7'; Name: 'iPad mini CDMA+LTE'),
            (Machine: 'ipad3,1'; Name: '3rd Gen iPad'),
            (Machine: 'ipad3,2'; Name: '3rd Gen iPad CDMA'),
            (Machine: 'ipad3,3'; Name: '3rd Gen iPad GSM'),
            (Machine: 'ipad3,4'; Name: '4th Gen iPad'),
            (Machine: 'ipad3,5'; Name: '4th Gen iPad GSM+LTE'),
            (Machine: 'ipad3,6'; Name: '4th Gen iPad CDMA+LTE'),
            (Machine: 'ipad4,1'; Name: 'iPad Air (WiFi)'),
            (Machine: 'ipad4,2'; Name: 'iPad Air (GSM+CDMA)'),
            (Machine: 'ipad4,3'; Name: '1st Gen iPad Air (China)'),
            (Machine: 'ipad4,4'; Name: 'iPad mini Retina (WiFi)'),
            (Machine: 'ipad4,5'; Name: 'iPad mini Retina (GSM+CDMA)'),
            (Machine: 'ipad4,6'; Name: 'iPad mini Retina (China)'),
            (Machine: 'ipad4,7'; Name: 'iPad mini 3 (WiFi)'),
            (Machine: 'ipad4,8'; Name: 'iPad mini 3 (GSM+CDMA)'),
            (Machine: 'ipad4,9'; Name: 'iPad Mini 3 (China)'),
            (Machine: 'ipad5,1'; Name: 'iPad mini 4 (WiFi)'),
            (Machine: 'ipad5,2'; Name: '4th Gen iPad mini (WiFi+Cellular)'),
            (Machine: 'ipad5,3'; Name: 'iPad Air 2 (WiFi)'),
            (Machine: 'ipad5,4'; Name: 'iPad Air 2 (Cellular)'),
            (Machine: 'ipad6,11'; Name: 'iPad (2017)'),
            (Machine: 'ipad6,12'; Name: 'iPad (2017)'),
            (Machine: 'ipad6,3'; Name: 'iPad Pro (9.7 inch, WiFi)'),
            (Machine: 'ipad6,4'; Name: 'iPad Pro (9.7 inch, WiFi+LTE)'),
            (Machine: 'ipad6,7'; Name: 'iPad Pro (12.9 inch, WiFi)'),
            (Machine: 'ipad6,8'; Name: 'iPad Pro (12.9 inch, WiFi+LTE)'),
            (Machine: 'ipad7,1'; Name: 'iPad Pro 2nd Gen (WiFi)'),
            (Machine: 'ipad7,11'; Name: 'iPad 7th Gen 10.2-inch (WiFi)'),
            (Machine: 'ipad7,12'; Name: 'iPad 7th Gen 10.2-inch (WiFi+Cellular)'),
            (Machine: 'ipad7,2'; Name: 'iPad Pro 2nd Gen (WiFi+Cellular)'),
            (Machine: 'ipad7,3'; Name: 'iPad Pro 10.5-inch'),
            (Machine: 'ipad7,4'; Name: 'iPad Pro 10.5-inch'),
            (Machine: 'ipad7,5'; Name: 'iPad 6th Gen (WiFi)'),
            (Machine: 'ipad7,6'; Name: 'iPad 6th Gen (WiFi+Cellular)'),
            (Machine: 'ipad8,1'; Name: 'iPad Pro 11 inch 3rd Gen (WiFi)'),
            (Machine: 'ipad8,10'; Name: 'iPad Pro 11 inch 4th Gen (WiFi+Cellular)'),
            (Machine: 'ipad8,11'; Name: 'iPad Pro 12.9 inch 4th Gen (WiFi)'),
            (Machine: 'ipad8,12'; Name: 'iPad Pro 12.9 inch 4th Gen (WiFi+Cellular)'),
            (Machine: 'ipad8,2'; Name: 'iPad Pro 11 inch 3rd Gen (1TB, WiFi)'),
            (Machine: 'ipad8,3'; Name: 'iPad Pro 11 inch 3rd Gen (WiFi+Cellular)'),
            (Machine: 'ipad8,4'; Name: 'iPad Pro 11 inch 3rd Gen (1TB, WiFi+Cellular)'),
            (Machine: 'ipad8,5'; Name: 'iPad Pro 12.9 inch 3rd Gen (WiFi)'),
            (Machine: 'ipad8,6'; Name: 'iPad Pro 12.9 inch 3rd Gen (1TB, WiFi)'),
            (Machine: 'ipad8,7'; Name: 'iPad Pro 12.9 inch 3rd Gen (WiFi+Cellular)'),
            (Machine: 'ipad8,8'; Name: 'iPad Pro 12.9 inch 3rd Gen (1TB, WiFi+Cellular)'),
            (Machine: 'ipad8,9'; Name: 'iPad Pro 11 inch 4th Gen (WiFi)'),
            (Machine: 'iphone1,1'; Name: 'iPhone'),
            (Machine: 'iphone1,2'; Name: 'iPhone 3G'),
            (Machine: 'iphone10,1'; Name: 'iPhone 8'),
            (Machine: 'iphone10,2'; Name: 'iPhone 8 Plus'),
            (Machine: 'iphone10,3'; Name: 'iPhone X Global'),
            (Machine: 'iphone10,4'; Name: 'iPhone 8'),
            (Machine: 'iphone10,5'; Name: 'iPhone 8 Plus'),
            (Machine: 'iphone10,6'; Name: 'iPhone X GSM'),
            (Machine: 'iphone11,2'; Name: 'iPhone XS'),
            (Machine: 'iphone11,4'; Name: 'iPhone XS Max'),
            (Machine: 'iphone11,6'; Name: 'iPhone XS Max Global'),
            (Machine: 'iphone11,8'; Name: 'iPhone XR'),
            (Machine: 'iphone12,1'; Name: 'iPhone 11'),
            (Machine: 'iphone12,3'; Name: 'iPhone 11 Pro'),
            (Machine: 'iphone12,5'; Name: 'iPhone 11 Pro Max'),
            (Machine: 'iphone12,8'; Name: 'iPhone SE 2nd Gen'),
            (Machine: 'iphone13,1'; Name: 'iPhone 12 Mini'),
            (Machine: 'iphone13,2'; Name: 'iPhone 12'),
            (Machine: 'iphone13,3'; Name: 'iPhone 12 Pro'),
            (Machine: 'iphone13,4'; Name: 'iPhone 12 Pro Max'),
            (Machine: 'iphone2,1'; Name: 'iPhone 3GS'),
            (Machine: 'iphone3,1'; Name: 'iPhone 4'),
            (Machine: 'iphone3,2'; Name: 'iPhone 4 GSM Rev A'),
            (Machine: 'iphone3,3'; Name: 'iPhone 4 CDMA'),
            (Machine: 'iphone4,1'; Name: 'iPhone 4S'),
            (Machine: 'iphone5,1'; Name: 'iPhone 5 (GSM)'),
            (Machine: 'iphone5,2'; Name: 'iPhone 5 (GSM+CDMA)'),
            (Machine: 'iphone5,3'; Name: 'iPhone 5C (GSM)'),
            (Machine: 'iphone5,4'; Name: 'iPhone 5C (Global)'),
            (Machine: 'iphone6,1'; Name: 'iPhone 5S (GSM)'),
            (Machine: 'iphone6,2'; Name: 'iPhone 5S (Global)'),
            (Machine: 'iphone7,1'; Name: 'iPhone 6 Plus'),
            (Machine: 'iphone7,2'; Name: 'iPhone 6'),
            (Machine: 'iphone8,1'; Name: 'iPhone 6s'),
            (Machine: 'iphone8,2'; Name: 'iPhone 6s Plus'),
            (Machine: 'iphone8,4'; Name: 'iPhone SE (GSM)'),
            (Machine: 'iphone9,1'; Name: 'iPhone 7'),
            (Machine: 'iphone9,2'; Name: 'iPhone 7 Plus'),
            (Machine: 'iphone9,3'; Name: 'iPhone 7'),
            (Machine: 'iphone9,4'; Name: 'iPhone 7 Plus'),
            (Machine: 'ipod1,1'; Name: '1st Gen iPod'),
            (Machine: 'ipod2,1'; Name: '2nd Gen iPod'),
            (Machine: 'ipod3,1'; Name: '3rd Gen iPod'),
            (Machine: 'ipod4,1'; Name: '4th Gen iPod'),
            (Machine: 'ipod5,1'; Name: '5th Gen iPod'),
            (Machine: 'ipod7,1'; Name: '6th Gen iPod'),
            (Machine: 'ipod9,1'; Name: '7th Gen iPod'),
            (Machine: 'watch1,1'; Name: 'Apple Watch 38mm case'),
            (Machine: 'watch1,2'; Name: 'Apple Watch 42mm case'),
            (Machine: 'watch2,3'; Name: 'Apple Watch Series 2 38mm case'),
            (Machine: 'watch2,4'; Name: 'Apple Watch Series 2 42mm case'),
            (Machine: 'watch2,6'; Name: 'Apple Watch Series 1 38mm case'),
            (Machine: 'watch2,7'; Name: 'Apple Watch Series 1 42mm case'),
            (Machine: 'watch3,1'; Name: 'Apple Watch Series 3 38mm case (GPS+Cellular)'),
            (Machine: 'watch3,2'; Name: 'Apple Watch Series 3 42mm case (GPS+Cellular)'),
            (Machine: 'watch3,3'; Name: 'Apple Watch Series 3 38mm case (GPS)'),
            (Machine: 'watch3,4'; Name: 'Apple Watch Series 3 42mm case (GPS)'),
            (Machine: 'watch4,1'; Name: 'Apple Watch Series 4 40mm case (GPS)'),
            (Machine: 'watch4,2'; Name: 'Apple Watch Series 4 44mm case (GPS)'),
            (Machine: 'watch4,3'; Name: 'Apple Watch Series 4 40mm case (GPS+Cellular)'),
            (Machine: 'watch4,4'; Name: 'Apple Watch Series 4 44mm case (GPS+Cellular)'),
            (Machine: 'watch5,1'; Name: 'Apple Watch Series 5 40mm case (GPS)'),
            (Machine: 'watch5,10'; Name: 'Apple Watch SE 44mm case (GPS)'),
            (Machine: 'watch5,11'; Name: 'Apple Watch SE 40mm case (GPS+Cellular)'),
            (Machine: 'watch5,12'; Name: 'Apple Watch SE 44mm case (GPS+Cellular)'),
            (Machine: 'watch5,2'; Name: 'Apple Watch Series 5 44mm case (GPS)'),
            (Machine: 'watch5,3'; Name: 'Apple Watch Series 5 40mm case (GPS+Cellular)'),
            (Machine: 'watch5,4'; Name: 'Apple Watch Series 5 44mm case (GPS+Cellular)'),
            (Machine: 'watch5,9'; Name: 'Apple Watch SE 40mm case (GPS)'),
            (Machine: 'watch6,1'; Name: 'Apple Watch Series 6 40mm case (GPS)'),
            (Machine: 'watch6,2'; Name: 'Apple Watch Series 6 44mm case (GPS)'),
            (Machine: 'watch6,3'; Name: 'Apple Watch Series 6 40mm case (GPS+Cellular)'),
            (Machine: 'watch6,4'; Name: 'Apple Watch Series 6 44mm case (GPS+Cellular)'),
            (Machine: 'x86_64'; Name: 'iPhone Simulator'));
        var
          LDevice: TAppleDevice;
          LIndex: Integer;
          LStringComparer: IComparer<string>;
        begin
          LDevice.Machine := AMachine.ToLower;
          LDevice.Name := '';
          LStringComparer := TComparer<string>.Default;
          if TArray.BinarySearch<TAppleDevice>(AppleDevices, LDevice, LIndex, TComparer<TAppleDevice>.Construct(
            function(const ALeft, ARight: TAppleDevice): Integer
            begin
              Result := LStringComparer.Compare(ALeft.Machine, ARight.Machine);
            end)) then
          begin
            Result := AppleDevices[LIndex].Name;
          end
          else if AMachine.IsEmpty then
            Result := ''
          else
          begin
            {$IFDEF DEBUG}
            for LIndex := 0 to Length(AppleDevices)-1 do
              if (AppleDevices[LIndex].Machine <> AppleDevices[LIndex].Machine.ToLower) then
                raise Exception.Create('Apple device list is wrong (the "Machine" field don''t allow upper case)');
            for LIndex := 1 to Length(AppleDevices)-1 do
              if LStringComparer.Compare(AppleDevices[LIndex-1].Machine, AppleDevices[LIndex].Machine) <> -1 then
                raise Exception.Create('Apple device list is wrong (it isn''t ordered or have duplicate item)');
            {$ENDIF}
            Result := '[' + AMachine + ']';
          end;
        end;
    
      var
        LSize: size_t;
        LDeviceModelBuffer: array of Byte;
      begin
        sysctlbyname('hw.machine', nil, @LSize, nil, 0);
        if LSize > 0 then
        begin
          SetLength(LDeviceModelBuffer, LSize);
          sysctlbyname('hw.machine', @LDeviceModelBuffer[0], @LSize, nil, 0);
          Result := GetPrettyName(UTF8ToString(MarshaledAString(LDeviceModelBuffer)));
        end
        else
          Result := '';
      end;

     


  12. Dave, on iOS it works the same way, and with the increase in privacy controls year after year, I think there will be no regressions.

     

    What many apps do is show a form before the permission request saying that it is necessary to grant X permission and if the user clicks on proceed, then requests the permission. This will avoid almost all permissions being denied. And when that happens, there's nothing to do but ask the user to grant permission on the settings (even Telegram does that).

    • Like 1

  13. A possible problem could be memory leaks due to the ARC that existed in 10.2 and now doesn't exist anymore, you have to Free the objects. There may come a point where your application crashes due to excessive use of memory.


    I advise you to run on windows with ReportMemoryLeaksOnShutDown to confirm. If you can't run the entire app, at least part of the code.


  14. If you set TRESTClient's SynchronizedEvents property to False, you can do this directly:

      // FRequest: TRESTRequest
      // FClient: TRESTClient
      // FCanRaiseException: Boolean = {$IFDEF DEBUG}True{$ELSE}False{$ENDIF}
    
    function TryRequest: Boolean
    begin
      FClient.SynchronizedEvents := False;
      FRequest.Client := FClient;
      try
        FRequest.Execute;
      except
        on E: ERESTException do
        begin
          if FCanRaiseException then
            Exception.RaiseOuterException(Exception.Create('Service or connection failed'))
          else
            Exit(False);
        end;
      end;
      Result := True;
    end;

    This code is blocking, so it must be executed in a task in the background, and communicating with the UI through a queue.

    Just a question, what rest api do you is integrating? You may be able to make this integration faster with the Refit library: viniciusfbb/ipub-refit: Simple way to consume REST services (github.com)

    • Like 1
    • Thanks 1

  15. @Fabian1648 Apparently you don't know anything about vector manipulation. You cannot directly transform a .png to .svg. I advise you to download the GIMP and go on learning...

    But I'll help you, I vectored an icon similar to yours. See your new icon:

     android.svg android.png.5883c409604fe956ccca14620d850fbe.png


    Now what you have to do is change the ic_background.xml and ic_foreground.xml.

    ic_background.xml:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="108dp"
        android:height="108dp"
        android:viewportWidth="108.0"
        android:viewportHeight="108.0">
        <path android:name="background" android:fillColor="#1570a6" android:pathData="M0,0L108,0L108,108L0,108z"/>
    </vector>


    ic_foreground.xml:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="108dp"
        android:height="108dp"
        android:viewportWidth="108.0"
        android:viewportHeight="108.0">
        <path android:name="robot" android:fillColor="#ffffff" android:pathData="M63.56,62.94C63.56,63.72 62.94,64.35 62.16,64.35 62.16,64.35 45.85,64.35 45.85,64.35 45.08,64.35 44.45,63.72 44.45,62.94 44.45,62.94 44.45,48.37 44.45,48.37 48.72,48.36 58.69,48.36 63.56,48.37 63.56,48.37 63.56,62.94 63.56,62.94 63.56,62.94 63.56,62.94 63.56,62.94ZM50.49,40.91C50.57,41.06 50.5,41.26 50.34,41.34 50.34,41.34 50.34,41.34 50.34,41.34 50.19,41.42 49.99,41.36 49.91,41.2 49.91,41.2 47.85,37.18 47.85,37.18 47.77,37.02 47.83,36.83 47.99,36.75 47.99,36.75 47.99,36.75 47.99,36.75 48.15,36.67 48.34,36.73 48.43,36.89 48.43,36.89 50.49,40.91 50.49,40.91 50.49,40.91 50.49,40.91 50.49,40.91ZM57.99,41.07C57.9,41.23 57.7,41.28 57.55,41.19 57.55,41.19 57.55,41.19 57.55,41.19 57.39,41.1 57.34,40.91 57.43,40.75 57.43,40.75 59.69,36.84 59.69,36.84 59.78,36.69 59.98,36.63 60.13,36.72 60.13,36.72 60.13,36.72 60.13,36.72 60.29,36.81 60.34,37.01 60.25,37.17 60.25,37.17 57.99,41.07 57.99,41.07 57.99,41.07 57.99,41.07 57.99,41.07ZM68.54,58.99C68.54,60.12 67.62,61.04 66.49,61.04 66.49,61.04 66.49,61.04 66.49,61.04 65.35,61.04 64.43,60.12 64.43,58.99 64.43,58.99 64.43,50.01 64.43,50.01 64.43,48.87 65.35,47.95 66.49,47.95 66.49,47.95 66.49,47.95 66.49,47.95 67.62,47.95 68.54,48.87 68.54,50.01 68.54,50.01 68.54,58.99 68.54,58.99ZM43.56,58.99C43.56,60.12 42.64,61.04 41.51,61.04 41.51,61.04 41.51,61.04 41.51,61.04 40.38,61.04 39.46,60.12 39.46,58.99 39.46,58.99 39.46,50.01 39.46,50.01 39.46,48.87 40.38,47.95 41.51,47.95 41.51,47.95 41.51,47.95 41.51,47.95 42.64,47.95 43.56,48.87 43.56,50.01 43.56,50.01 43.56,58.99 43.56,58.99ZM52.5,69.27C52.5,70.4 51.58,71.32 50.45,71.32 50.45,71.32 50.45,71.32 50.45,71.32 49.31,71.32 48.4,70.4 48.4,69.27 48.4,69.27 48.4,60.29 48.4,60.29 48.4,59.15 49.31,58.23 50.45,58.23 50.45,58.23 50.45,58.23 50.45,58.23 51.58,58.23 52.5,59.15 52.5,60.29 52.5,60.29 52.5,69.27 52.5,69.27ZM59.62,69.27C59.62,70.4 58.7,71.32 57.57,71.32 57.57,71.32 57.57,71.32 57.57,71.32 56.43,71.32 55.51,70.4 55.51,69.27 55.51,69.27 55.51,60.29 55.51,60.29 55.51,59.15 56.43,58.23 57.57,58.23 57.57,58.23 57.57,58.23 57.57,58.23 58.7,58.23 59.62,59.15 59.62,60.29 59.62,60.29 59.62,69.27 59.62,69.27ZM54.01,38.78C49.01,38.78 44.9,42.58 44.35,47.46 44.35,47.46 63.66,47.46 63.66,47.46 63.11,42.58 59,38.78 54.01,38.78 54.01,38.78 54.01,38.78 54.01,38.78ZM49.65,44.04C49.2,44.04 48.85,43.68 48.85,43.24 48.85,42.8 49.2,42.44 49.65,42.44 50.09,42.44 50.45,42.8 50.45,43.24 50.45,43.68 50.09,44.04 49.65,44.04 49.65,44.04 49.65,44.04 49.65,44.04ZM58.38,44.04C57.94,44.04 57.58,43.68 57.58,43.24 57.58,42.8 57.94,42.44 58.38,42.44 58.82,42.44 59.18,42.8 59.18,43.24 59.18,43.68 58.82,44.04 58.38,44.04 58.38,44.04 58.38,44.04 58.38,44.04Z"/>
        <path android:name="gear" android:fillColor="#1570a6" android:pathData="M57.83,54.26C57.83,54.26 57.56,53.63 57.56,53.63 57.56,53.63 58.18,52.23 58.13,52.17 58.13,52.17 57.3,51.37 57.3,51.37 57.25,51.31 55.84,51.95 55.84,51.95 55.84,51.95 55.2,51.69 55.2,51.69 55.2,51.69 54.62,50.27 54.54,50.27 54.54,50.27 53.38,50.27 53.38,50.27 53.3,50.27 52.77,51.7 52.77,51.7 52.77,51.7 52.13,51.96 52.13,51.96 52.13,51.96 50.69,51.35 50.64,51.4 50.64,51.4 49.81,52.21 49.81,52.21 49.76,52.26 50.41,53.64 50.41,53.64 50.41,53.64 50.14,54.27 50.14,54.27 50.14,54.27 48.69,54.83 48.69,54.91 48.69,54.91 48.69,56.05 48.69,56.05 48.69,56.13 50.15,56.65 50.15,56.65 50.15,56.65 50.42,57.28 50.42,57.28 50.42,57.28 49.79,58.68 49.85,58.74 49.85,58.74 50.67,59.54 50.67,59.54 50.73,59.6 52.13,58.96 52.13,58.96 52.13,58.96 52.78,59.22 52.78,59.22 52.78,59.22 53.35,60.64 53.43,60.64 53.43,60.64 54.59,60.64 54.59,60.64 54.67,60.64 55.2,59.21 55.2,59.21 55.2,59.21 55.85,58.95 55.85,58.95 55.85,58.95 57.28,59.56 57.34,59.51 57.34,59.51 58.16,58.7 58.16,58.7 58.22,58.65 57.56,57.27 57.56,57.27 57.56,57.27 57.83,56.64 57.83,56.64 57.83,56.64 59.29,56.08 59.29,56 59.29,56 59.29,54.86 59.29,54.86 59.29,54.78 57.83,54.26 57.83,54.26ZM53.99,57.12C53.05,57.12 52.29,56.37 52.29,55.45 52.29,54.54 53.05,53.79 53.99,53.79 54.92,53.79 55.69,54.54 55.69,55.45 55.69,56.37 54.92,57.12 53.99,57.12Z"/>
    </vector>

     

    • Like 1

  16. @Fabian1648 The adaptive icon is the way to have your icon full quality in all devices of all manufacturers.

     

    You did something wrong during the steps as it works on a blank project (you can test). 
     

    Remembering that in some versions of android it is necessary to uninstall the old application for the icon to be updated. Also, on some androids (like LG's Android 10) when you click beyond uninstall, the android only disables the application, so you must go to Settings > Applications, and uninstall.

     

    Please provide more information, print the deployment and the manifest and the print also, after a Run, the generated files in the output folder, example: (project)\Android64\Release\(project)\res

    • Like 1

  17. Adaptive Icon

     

    First of all, don’t uncheck the icons in deployment and don’t change the manifest.

     

    1) Add your icons in .png format in Project Options normally. This is necessary to keep the compatibility with android 7.1 and oldest.

    2) You need to create 3 files "ic_launcher.xml", "ic_launcher_background.xml" and "ic_launcher_foreground.xml"

    3) ic_launcher.xml example:

    <?xml version="1.0" encoding="utf-8"?>
    <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
        <background android:drawable="@drawable/ic_launcher_background" />
        <foreground android:drawable="@drawable/ic_launcher_foreground" />
    </adaptive-icon>

    Add it in deployment with remote path "res\drawable-anydpi-v26"

     

    4) ic_background.xml example:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="108dp"
        android:height="108dp"
        android:viewportWidth="108.0"
        android:viewportHeight="108.0">
        <path android:name="square"
            android:fillColor="#ff3657f4"
            android:pathData="M0,0 L108,0 L108,108 L0,108 z" />
    </vector>

    Note that I fixed a solid color (#ff3657f4), but you can put gradients in this xml or an image in place the background (not recomended).

    Add it in deployment with remote path "res\drawable"

     

    5) ic_foreground.xml example:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="108dp"
        android:height="108dp"
        android:viewportWidth="108.0"
        android:viewportHeight="108.0">
        <path android:name="square"
            android:fillColor="#ffffffff"
            android:pathData="M 53.91,32.73
               C 54.35,32.75 54.49,33.06 54.75,33.39
                 54.75,33.39 56.18,35.17 56.18,35.17
                 56.18,35.17 62.30,42.80 62.30,42.80
                 62.30,42.80 65.32,46.57 65.32,46.57
                 67.71,49.56 69.15,51.35 69.99,55.19
                 70.19,56.06 70.35,56.97 70.35,57.86
                 70.35,60.63 70.34,61.92 69.39,64.60
                 67.61,69.60 63.19,73.48 58.06,74.76
                 56.05,75.26 54.85,75.23 52.81,75.20
                 51.89,75.19 50.64,74.92 49.74,74.70
                 44.14,73.29 39.76,68.84 38.20,63.31
                 37.95,62.41 37.66,60.97 37.65,60.04
                 37.62,57.15 37.69,55.37 38.79,52.61
                 39.86,49.91 41.15,48.49 42.92,46.27
                 42.92,46.27 48.17,39.73 48.17,39.73
                 48.17,39.73 51.98,34.98 51.98,34.98
                 52.41,34.44 53.40,33.04 53.91,32.73 Z
               M 46.57,58.86
               C 46.57,58.86 43.70,58.86 43.70,58.86
                 43.70,58.86 43.70,59.45 43.70,59.45
                 43.70,63.37 46.54,66.93 50.04,68.42
                 50.88,68.79 51.80,69.02 52.71,69.13
                 53.27,69.20 53.36,69.10 54.00,69.26
                 54.00,69.26 54.00,66.29 54.00,66.29
                 52.87,66.29 51.97,66.13 50.93,65.66
                 48.53,64.57 46.57,61.94 46.57,59.25
                 46.57,59.25 46.57,58.86 46.57,58.86 Z" />
    </vector>

    You can change the white color (#ffffffff) and the pathData. Note: this pathData is the same path data inside the .svg. If you have your icon in .svg, just open it in notepad and copy the "d" field inside the "path" to the pathData of xml (only if the svg has size 108x108).

    Add it in deployment with remote path "res\drawable"

     

     

    Result

    2021-06-30-14-50-591.thumb.gif.f6add0257c64bdd78b101c2f18ff9586.gif

    (the low quality is due to the gif format)

     

    Extra

    You can do the same with the splash screen (vector splash screen). The vector splash screen works in all android versions supported by Delphi.

    • Like 4

  18. 8 hours ago, David Heffernan said:

    What's your usage scenario? 

     

    8 hours ago, pyscripter said:

    Notepad and VSCode have similar issues.

    There are really few apps on Windows, except for chat apps, which fully support unicode (including MS apps), but in my case I really need to deal with this because it will be just a cross platform chat (Win, Android, iOS).

     

    Today's problem is to fix TEdit, but it is not just that, but the safe way to manipulate any string received from the user. It is the same as using AnsiString/AnsiChar when the input is string (unicode), you are at risk of generating an unexpected string.

     

     

    To clarify the problem, follow an example on TEdit:

    1) Select a TEdit, press Windows key +. to open the emoji window
    2) Select for example the "White man raising his hand" which is represented by 7 characters, that is, 14 bytes)

    3) Proceed:

    TEdit_problem.thumb.png.fcdea122f8574d0830bbf35a6b4319de.png

     

     

    Example string manipulation:

    In a string manipulation it is very common, for example, to take x first characters, so suppose I want to take the first 8 chars:

    S := S.Substring(0, 8);

    But if S is "🙋🏻‍♂️🙋🏻‍♂️", which incredibly has 14 chars, and which is the same as:

    S := #55357 + #56907 + #55356 + #57339 + #8205 + #9794 + #65039 + #55357 + #56907 + #55356 + #57339 + #8205 + #9794 + #65039;

    When I give the substring (0, 8), the result will be:

    S := #55357 + #56907 + #55356 + #57339 + #8205 + #9794 + #65039 + #55357;

    Which is represented by:

    🙋🏻‍♂️

    But a Substring (1, 7) would be even worse in this case:

    Substring1_7.png.c720aa91e723a8c451b37576f599d33b.png

     

     

    The problem is very clear and a modern application, mainly of chat, has to know how to deal with it.

     

×