Jump to content

pyscripter

Members
  • Content Count

    785
  • Joined

  • Last visited

  • Days Won

    42

Posts posted by pyscripter


  1. 2 hours ago, Andrea Raimondi said:

    This is why I don't necessarily agree with what you're saying. 

    Where exactly do we disagree?  I started by saying the features are great.  But if xml processing is a performance bottleneck you can improve performance drastically (see below) by accessing the underlying implementation directly with minimal changes to your code, since implementations follow the standard DOM interfaces.


  2. XML used to be considered the universal data format.  Now is a bit passé with JSON, YAML etc being "in".   I got involved in XML parsing, since SVG files are in XML format.

     

    XML Delphi support

    At the surface the XML support in Delphi is very good:

    • You have TXMLDocument/IXMLDocument offering high-level support (Xml.xmldoc)
    • Support for the standard DOM interfaces (Xml.XmlDom)
    • Multiple implementations including (MSXML, OmniXML, OpenXML and more)
    • Ability to plug in your own implementation
    • Multiple platform support.

    The most common way of accessing XML is through TXMLDocument/IXMLDocument.   However there is a big catch: PERFORMANCE.  Say you want to use MSXML and you specify 'MSXML' as your DefaultDomVendor.  (or you simply include the implementation unit Xml.Win.msxmldom in your uses clause).  Your create an XML document and you access the top node:

    var Doc: IXMLDocument = TXMLDocument.Create(nil);
    var Node: IXMLNode := Doc.DocumentElement;

    Node is an IXMLInterface implemented by TXMLNode (TInterfacedObject defined in Xml.XmlDoc).

    TXMLNode wraps an IDOMNode stored in a private field FDOMNode.  IDOMNode is defined in Xml.Xmldom.

    The IDOMNode is implemented by the used vendor in this case Xml.Win.msxmldom by a class TMSDOMNode

    TMSDOMNode (also a TInterfacedObject) wraps IXMLDOMNode stored in a private field FMSNode.  IXMLDOMNode is defined in Winapi.msxml.

     

    As a result when you create any IXMLNode, a TXMLNode is created and this creates a TMSDOMNode which points to an IXMLDOMNode.   Any call/property access to IXMLNode translates in a call of IDOMNode which then calls IXMLDOMNode.  The created TInterfaced objects also need to be destroyed when you release your XML Node. The same two-level indirection applies to all XML objects (attributes, Children) and cause a huge degradation of performance.

     

    Conclusion

    If you care about speed forget about TXMLDocument.  You can access the Vendor implementation or even better in the case of MSXML the Microsoft ActiveX objects directly:

    uses WinAPI.msxml
    var  XML: IXMLDOMDocument3 := CoDOMDocument60.Create;
    XML.loadXML(XMLString);
    var   DocNode: IXMLDOMNode := XML.documentElement;

    In SVG parsing and processing accessing directly the ActiveX objects reduced processing time by more than 50%.

     

    Additional tip

    A common performance pitfall with MSXML is explained in http://www.gerixsoft.com/blog/delphi/msxml.   The fastest way to iterate through ChildNodes is via getFirstChild/nextSibling and Attributes via nextNode.

     

     

     

     

     

    • Like 4

  3. 3 hours ago, Ondrej Kelle said:

    If you wanted to avoid the requirement of having the fonts installed globally in Windows you could write a design package with the fonts linked in as resources. The package, when loaded by the IDE, could load the fonts from the resources (using the code shown by @Attila Kovacs) and call Screen.ResetFonts to signal the IDE to reinitialize its font list . After that the fonts would be available to the IDE.

    Indeed:

    From https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-addfontmemresourceex

    Quote

     

    This function allows an application to get a font that is embedded in a document or a webpage. A font that is added by AddFontMemResourceEx is always private to the process that made the call and is not enumerable.

    A memory image can contain more than one font. When this function succeeds, pcFonts is a pointer to a DWORD whose value is the number of fonts added to the system as a result of this call. For example, this number could be 2 for the vertical and horizontal faces of an Asian font.

    When the function succeeds, the caller of this function can free the memory pointed to by pbFont because the system has made its own copy of the memory. To remove the fonts that were installed, call RemoveFontMemResourceEx. However, when the process goes away, the system will unload the fonts even if the process did not call RemoveFontMemResource.

     

     


  4.  dic.Items['aaa']:=l2;

    dic.Items['aaa'] already contains l2 and l2 is freed before it is readded, since you set 

    doOwnsValues

    Also an issue would occur if you do

    dic.Items['bbb']:=l2;

     

    When the dictionary is destroyed the list will be freed twice.


  5. In an earlier thread I presented an Interface-based access to native Windows (Direct2D) SVG support for Delphi applications.  This has now been integrated into the SVGIconImageList components by @Carlo Barazzetta.  Carlo is a kind of master of ImageLists (among other things).  Have a look at his IconFontsImageList for instance. His SVGIconImageList component was based on the work of Martin Walter who must be a great programmer.  His SVG component covered almost every SVG element and was well structured and cleanly written.  There were numerous bugs and issues though, which, to a large extent, were fixed over the last few weeks and the code was refactored and optimized.  Finally, @Vincent Parrett contributed a virtual version of the Image List, mirroring Delphi's VirtualImageList.

     

    So in its current form the component features:

    • An SVGImageCollection component that inherits from Delphi's CustomImageCollection and thus is compatible with VirtualImageList
    • A choice of SVG engines:  the pascal one based on Martin's work which is using GDI+ and the native Windows one which is using Direct2D.
    • Other SVG engines can be plugged-in with minimum effort.
    • Excellent design support with a nice and effective SVGImageCollection editor developed by Carlo and the built-in VirtualImageList editor.
    • Support for changing the opacity and color of the SVGs including using GrayScale.  If you adopt  Material Design for example and you use VCL styles, you can adjust the icon color to the style.
    • Compatibility with older Delphi versions going back to XE6.
    • It is free and open-source

     

    Svgs are vastly superior to bitmaps because they are typically tiny text files and scale perfectly.  So, you do not need to ship with your application multiple resolutions of your images to match the DPI of the monitors.  And there is a vast number of free SVGs to cover most needs.  IMHO the combination of SVGImageCollection with Delphi's VirtualImageList is the best available solution (commercial ones included) for building DPI-aware Windows applications.  Give it a try.

    • Like 12
    • Thanks 7

  6. PyScripter, an Open Source, freely available Python IDE written in Delphi, has reached 1 million downloads from Sourceforge.  This is in addition to many millions of downloads from its earlier home at the now defunct Google Code and an unknown number of downloads from other distribution channels.

     

    Historic note:

     

    The initial motivation was to build a good scripting solution for Delphi applications.   About 20 years ago Microsoft was still promoting ActiveX scripting and Windows Script Engines (such as vbScript and jScript) as the way of building scripting solutions for Windows applications (one of many Microsoft technologies that was all but abandoned).  At that time Python was relatively unknown, but it so happened that it was available as a Windows Script Engine and I looked into it.  I loved the clean syntax, the expressiveness and conciseness of the language.  Other things I liked were duck typing, batteries included, strong object orientation (everything is an object) etc..   The first iteration was an IDE (editor/debugger) for ActiveX Script Engines.   But there were many bugs and limitations of Active Scripting both on the Microsoft/Windows side and the Python side.

     

    I then came across Python4Delphi which at the time was maintained by a Canadian developer Morgan Martinet.    I started contributing to that project and later become its main maintainer, when Morgan's interested shifted to other things.  I also developed a simple Python IDE which was named PyScripter and was originally distributed alongside Python4Delphi.  There was very few Python IDEs available at the time and somehow the project became known in the Python community and instantly popular.   For me, developing PyScripter was just a hobby, but I received a lot of encouragement and kept on improving it.  I was also making some income from donations and Google AdSense.  Both PyScripter and Python4Delphi were later moved to Google Code.  Python popularity was steadily increasing and at the peak of PyScripter's popularity around 2010, there were hundreds of thousands of downloads the days following each new release.

     

    More recently as we all know Python became one of the most popular programming languages, but at the same time there was strong competition to PyScripter from freely available commercial grade IDE's such as Jetbrains PyCharm and Microsoft's Visual Studio and Visual Studio Code.  PyScripter was almost abandoned when Google Code closed down due to my frustration,  but after a couple of years of inactivity the project was moved to Github and development resumed.  Downloads are available through Sourceforge, since 2016.  Through the years PyScripter has kept a large and loyal group of followers.   I get many comments along the lines "I have tried VSCode, I have tried PyCharm, but I keep going back to PyScripter".   PyScripter is also quite widely used in many Universities for introducing Python to students. 

     

    And almost 20 years after its first release, PyScripter is still going strong...

    • Like 29
    • Thanks 3

  7. 14 hours ago, Rollo62 said:

    Maybe you could clarify what that "Python" note really means ?

    It refers to the intention to promote Python4Delphi as a means of bringing Python and Delphi closer together:

     

    Python for Delphi (P4D) is a set of free components that wrap up the Python dll into Delphi and Lazarus (FPC). They let you easily execute Python scripts, create new Python modules and new Python types. You can create Python extensions as dlls and much more. P4D provides different levels of functionality:

    • Low-level access to the python API
    • High-level bi-directional interaction with Python
    • Access to Python objects using Delphi custom variants (VarPyth.pas)
    • Wrapping of Delphi objects for use in python scripts using RTTI (WrapDelphi.pas)
    • Creating python extension modules with Delphi classes and functions

    P4D makes it very easy to use python as a scripting language for Delphi applications. It comes with an extensive range of demos and tutorials.

     

    • Like 6
    • Thanks 1

  8. @Attila KovacsThanks.

     

    Just replace D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT with $00000004.

    And of course both LPCWSTR and LPWSTR are cast to PWideChar.  But you are right!

     

    I would like to add that the purpose of Winapi.D2DMissing is not to provide for the missing D2D API, but to include just enough to serve the purpose of handling svg files.   Warning: there are many translation errors in the the parts not used in this project.

     

    "TOSVersion.Build returns 0 on my system".

    Any idea why?  Is this a Delphi bug?  

     

    A more reliable way would be:

    if Supports(RenderTarget, ID2D1DeviceContext5) then
      //Supported

    But that would involve creating the Factory and the Render Target.

     

    Any other suggestions?

     


  9. 1 hour ago, Gustav Schubert said:

    Works for me! Except for two minor observations:

     

    a) in Winapi.D2DMissing there are references to some enum values (const) which are not available in my Rio installation, but those can be looked up on the Internet.

    
      const 
        D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR    = 0; //D2D1_INTERPOLATION_MODE_DEFINITION_NEAREST_NEIGHBOR;
        ...

    b) GrayScale can be set only once, thereafter it fails with EOSError, Code 87, Wrong Parameter?

    The attached fixes both issues.

     

    Svg.zip

    • Thanks 1

  10. In the attachment you can find a high-level interface-based encapsulation of the Direct2D SVG functionality.  It allows you to parse SVG files and draw them to a GDI/GDI+ DC.  Requires Windows 10 with Creators Update or later.

     

    Main form code  to display SVG files:

    { TForm1 }
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      fSVG := GetD2DSVGHandler.NewSvg;
      fSVG.LoadFromFile('..\..\browser.svg');
      //fSVG.FixedColor := TAlphaColorRec.Red;
      //fSVG.Opacity := 0.5;
      fSVG.GrayScale := True;
    end;
    
    procedure TForm1.Paint;
    begin
      inherited;
      fSvg.PaintTo(Canvas.Handle, TRectF.Create(ClientRect), True);
    end;
    
    procedure TForm1.Resize;
    begin
      inherited;
      Invalidate;
    end;

    Features:

    • Scale to any size
    • Keep aspect ratio (optionally)
    • Control opacity
    • Recolor to any color
    • Draw in gray scale

     

    Samples:

    image.thumb.png.d599fed793f9dc6ac1cd12c09f4b4827.png

     

    The above in grayscale:

    image.thumb.png.6b4ea11cb573e3f1b90e5d9ecee3f9f4.png

     

    Svg.zip

     

    image.png

    • Like 15

  11. 40 minutes ago, Dalija Prasnikar said:

    There is TOSVersion record in SysUtils that holds OS version information. But you cannot check for particular version by name, you need to know its build number.

    In Jcl there is something called Windows10ReleaseId (1703 for Creators Update).   Is this same as the build number?  (I think not)


  12. @Attila Kovacs

    RecolorSubtree(Root, D2D1ColorF(0.5, 80, 80, 80)); 

    does not make sense

    The Values need to be between 0 and 1 for instance.

    D2D1ColorF(clRed) = D2D1ColorF(1,0,0,1)

     

    I will doing drawing in GrayScale.

    Does anyone know how to draw the svg with opacity say 0.5?  Everything not just the fill color possibly using D2D primitives?

     


  13. @Kas Ob.order which is the same as shown by IDA works here.  I can recolor both ways:

     

        if Succeeded(Element.GetAttributeValue('fill', D2D1_SVG_ATTRIBUTE_POD_TYPE_COLOR,
           @OldColor, SizeOf(OldColor)))
         then
         begin
           if (OldColor.r <> 0) or (OldColor.g <> 0) or (OldColor.b <> 0)  then
             Assert(Succeeded(Element.SetAttributeValue('fill', D2D1_SVG_ATTRIBUTE_POD_TYPE_COLOR,
               @NewColor, SizeOf(NewColor))));
         end;

    and

     

        Assert(Succeeded(Element.GetAttributeValue('fill', IID_ID2D1SvgPaint, Pointer(Paint))));
        if Assigned(Paint) then begin
          Paint._AddRef;
          if Paint.GetPaintType = D2D1_SVG_PAINT_TYPE_COLOR then
          begin
            Paint.GetColor(OldColor);
            if (OldColor.r <> 0) or (OldColor.g <> 0) or (OldColor.b <> 0)  then
              Paint.SetColor(NewColor);
          end;
        end;
      end;

    The declaration of SetColor needs to be changed:

     

     

      function SetColor(Const color: D2D1_COLOR_F): HResult; stdcall;

     


  14. 20 minutes ago, Mahdi Safsafi said:

    Those are not stored inside vtable ... you need to skip them(don't declare them).

    Exactly! 

    That's my bad man ... I'm a little bit bad at explaining since I'm not a native English speaker.

    First step, add all methods in the order they declared(skip all overloaded versions but keep the original). second step for each added method "A" add just after it "A" all its overloaded versions in the order they declared too.

    Here is how your vtable looks like.

     

    vtbl.PNG

    The functions seem to work now (Succeeded) but still no recoloring though).

    What is strange is that the order of the overloads in the VTable is the reverse than that in the include file.  

    What is the tool you are using to inspect the Vtables?


  15. 28 minutes ago, Mahdi Safsafi said:

    function GetAttributeValue(name: LPWSTR; const riid: TGUID; var value: Pointer😞 HResult; overload; stdcall; // overloaded3

    This is the one I was getting before at $78 I think.

    Also when I call it using the commented code it does not succeed.

     

        Assert(Succeeded(
          Element.GetAttributeValue('fill', IID_ID2D1SvgPaint, Pointer(Paint))
        ))

    fails.
     

    It does not appear to be in the right order now.  

     

    Do you get the recoloring to work.

×