Jump to content
pyscripter

High-level interface-based encapsulation of Direct2D Svg functionality

Recommended Posts

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

Edited by pyscripter
  • Like 15

Share this post


Link to post

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?

Share this post


Link to post
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

Edited by pyscripter
  • Thanks 1

Share this post


Link to post

 good job! coupe of things:

 

  D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT is first introduced in Delphi 20.0, maybe you should declare it somewhere with a conditional

 

  TOSVersion.Build returns 0 on my system, reporting wrongly that SVG is not supported o.O

 

  functions:

  -SetId()

  -CreateChild()

  -IsAttributeSpecified()

  -RemoveAttribute()

  -SetAttributeValue() *all

  -GetAttributeValue() *all?

  -GetAttributeValueLength()

  -FindElementById()

  -CreatePaint()

  

  should have LPCWSTR parameters instead of LPWSTR. (just to be pedantic)

 

 

Edited by Attila Kovacs

Share this post


Link to post

@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?

 

Edited by pyscripter

Share this post


Link to post

Well.. I'm affraid the Interface ID2D1SvgElement declaration is not correct. And a reason why it it doesn't work as expected by the latest SDK.

This the complete interface according to SDK 10.0.19041.0.

 

type

  // Interface ID2D1SvgElement
  // =========================
  // Interface for all SVG elements.
  //
  {$HPPEMIT 'DECLARE_DINTERFACE_TYPE(ID2D1SvgElement);'}
  {$EXTERNALSYM ID2D1SvgElement}
  ID2D1SvgElement = interface(ID2D1Resource)
   ['{ac7b67a6-183e-49c1-a823-0ebe40b0db29}']


    // Gets the document that contains this element. Returns nil if the element has
    // been removed from the tree.
    procedure GetDocument(document: ID2D1SvgDocument); stdcall;
    {$EXTERNALSYM GetDocument}

    // Gets the tag name.
    function GetTagName(out name: PWideChar;
                        nameCount: UINT32): HResult; stdcall;
    {$EXTERNALSYM GetTagName}

    // Gets the string length of the tag name. The returned string length does not
    // include room for the null terminator.
    function GetTagNameLength(): UINT32; stdcall;
    {$EXTERNALSYM GetTagNameLength}

    // Returns TRUE if this element represents text content, e.g. the content of a
    // 'title' or 'desc' element. Text content does not have a tag name.
    function IsTextContent(): BOOL; stdcall;
    {$EXTERNALSYM IsTextContent}

    // Gets the parent element.
    procedure GetParent(out parent: ID2D1SvgElement); stdcall;
    {$EXTERNALSYM GetParent}

    // Returns whether this element has children.
    function HasChildren(): BOOL; stdcall;
    {$EXTERNALSYM HasChildren}

    // Gets the first child of this element.
    procedure GetFirstChild(out child: ID2D1SvgElement); stdcall;
    {$EXTERNALSYM GetFirstChild}

    // Gets the last child of this element.
    procedure GetLastChild(out child: ID2D1SvgElement); stdcall;
    {$EXTERNALSYM GetLastChild}

    // Gets the previous sibling of the referenceChild element.
    // <param name="referenceChild">The referenceChild must be an immediate child of
    // this element.</param>
    // <param name="previousChild">The output previousChild element will be non-nil if
    // the referenceChild has a previous sibling. If the referenceChild is the first
    // child, the output is nil.</param>
    function GetPreviousChild(const referenceChild: ID2D1SvgElement;
                              out previousChild: ID2D1SvgElement): HResult; stdcall;
    {$EXTERNALSYM GetPreviousChild}

    // Gets the next sibling of the referenceChild element.
    // <param name="referenceChild">The referenceChild must be an immediate child of
    // this element.</param>
    // <param name="nextChild">The output nextChild element will be non-nil if the
    // referenceChild has a next sibling. If the referenceChild is the last child, the
    // output is nil.</param>
    function GetNextChild(const referenceChild: ID2D1SvgElement;
                          out nextChild: ID2D1SvgElement): HResult; stdcall;
    {$EXTERNALSYM GetNextChild}

    // Inserts newChild as a child of this element, before the referenceChild element.
    // If the newChild element already has a parent, it is removed from this parent as
    // part of the insertion. Returns an error if this element cannot accept children
    // of the type of newChild. Returns an error if the newChild is an ancestor of this
    // element.
    // <param name="newChild">The element to be inserted.</param>
    // <param name="referenceChild">The element that the child should be inserted
    // before. If referenceChild is nil, the newChild is placed as the last child. If
    // referenceChild is non-nil, it must be an immediate child of this element.
    // </param>
    function InsertChildBefore(newChild: ID2D1SvgElement;
                               {In_opt} referenceChild: PID2D1SvgElement = Nil): HResult; stdcall;
     {$EXTERNALSYM InsertChildBefore}

    // Appends newChild to the list of children. If the newChild element already has a
    // parent, it is removed from this parent as part of the append operation. Returns
    // an error if this element cannot accept children of the type of newChild. Returns
    // an error if the newChild is an ancestor of this element.
    // <param name="newChild">The element to be appended.</param>
    function AppendChild(newChild: ID2D1SvgElement): HResult; stdcall;
    {$EXTERNALSYM AppendChild}

    // Replaces the oldChild element with the newChild. This operation removes the
    // oldChild from the tree. If the newChild element already has a parent, it is
    // removed from this parent as part of the replace operation. Returns an error if
    // this element cannot accept children of the type of newChild. Returns an error if
    // the newChild is an ancestor of this element.
    // <param name="newChild">The element to be inserted.</param>
    // <param name="oldChild">The child element to be replaced. The oldChild element
    // must be an immediate child of this element.</param>
    function ReplaceChild(newChild: ID2D1SvgElement;
                          oldChild: ID2D1SvgElement): HResult; stdcall;
     {$EXTERNALSYM ReplaceChild}

    // Removes the oldChild from the tree. Children of oldChild remain children of
    // oldChild.
    // <param name="oldChild">The child element to be removed. The oldChild element
    // must be an immediate child of this element.</param>
    function RemoveChild(oldChild: ID2D1SvgElement): HResult; stdcall;
    {$EXTERNALSYM RemoveChild}

    // Creates an element from a tag name. The element is appended to the list of
    // children. Returns an error if this element cannot accept children of the
    // specified type.
    // <param name="tagName">The tag name of the new child. An empty string is
    // interpreted to be a text content element.</param>
    // <param name="newChild">The new child element.</param>
    function CreateChild(tagName: PCWSTR;
                         out newChild: ID2D1SvgElement): HResult; stdcall;
    {$EXTERNALSYM CreateChild}

    // Returns true if the attribute is explicitly set on the element or if it is
    // present within an inline style. Returns FALSE if the attribute is not a valid
    // attribute on this element.
    // <param name="name">The name of the attribute.</param>
    // <param name="inherited">Outputs whether the attribute is set to the 'inherit'
    // value.</param>
    function IsAttributeSpecified(name: PCWSTR;
                                  _inherited: PBOOL = Nil): BOOL; stdcall;
    {$EXTERNALSYM IsAttributeSpecified}

    // Returns the number of specified attributes on this element. Attributes are only
    // considered specified if they are explicitly set on the element or present within
    // an inline style. Properties that receive their value through CSS inheritance are
    // not considered specified. An attribute can become specified if it is set through
    // a method call. It can become unspecified if it is removed via RemoveAttribute.
    function GetSpecifiedAttributeCount(): UINT32; stdcall;
    {$EXTERNALSYM GetSpecifiedAttributeCount}

    // Gets the name of the specified attribute at the given index.
    // <param name="index">The specified index of the attribute.</param>
    // <param name="name">Outputs the name of the attribute.</param>
    // <param name="inherited">Outputs whether the attribute is set to the 'inherit'
    // value.</param>
    function GetSpecifiedAttributeName(index: UINT32;
                                       out name: PWSTR;
                                       nameCount: UINT32;
                                       _inherited: PBOOL = Nil): HResult; stdcall;
    {$EXTERNALSYM GetSpecifiedAttributeName}

    // Gets the string length of the name of the specified attribute at the given
    // index. The output string length does not include room for the null terminator.
    // <param name="index">The specified index of the attribute.</param>
    // <param name="nameLength">Outputs the string length of the name of the specified
    // attribute.</param>
    // <param name="inherited">Outputs whether the attribute is set to the 'inherit'
    // value.</param>
    function GetSpecifiedAttributeNameLength(index: UINT32;
                                             out nameLength: UINT32;
                                             {out_opt} _inherited: PBOOL = Nil): HResult; stdcall;
    {$EXTERNALSYM GetSpecifiedAttributeNameLength}

    // Removes the attribute from this element. Also removes this attribute from within
    // an inline style if present. Returns an error if the attribute name is not valid
    // on this element.
    function RemoveAttribute(name: PCWSTR): HResult; stdcall;
    {$EXTERNALSYM RemoveAttribute}

    // Sets the value of a text content element.
    function SetTextValue(name: WCHAR;
                          nameCount: UINT32): HResult; stdcall;
    {$EXTERNALSYM SetTextValue}

    // Gets the value of a text content element.
    function GetTextValue(out name: PWSTR;
                          nameCount: UINT32): HResult; stdcall;
    {$EXTERNALSYM GetTextValue}

    // Gets the length of the text content value. The returned string length does not
    // include room for the null terminator.
    function GetTextValueLength(): UINT32; stdcall;
    {$EXTERNALSYM GetTextValueLength}

    // Sets an attribute of this element using a string. Returns an error if the
    // attribute name is not valid on this element. Returns an error if the attribute
    // cannot be expressed as the specified type.
    function SetAttributeValue(name: PCWSTR;
                               _type: D2D1_SVG_ATTRIBUTE_STRING_TYPE;
                               value: PCWSTR): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a string. Returns an error if the attribute
    // is not specified. Returns an error if the attribute name is not valid on this
    // element. Returns an error if the attribute cannot be expressed as the specified
    // string type.
    function GetAttributeValue(name: PCWSTR;
                               _type: D2D1_SVG_ATTRIBUTE_STRING_TYPE;
                               {out} out value: PWSTR;
                               valueCount: UINT32): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Gets the string length of an attribute of this element. The returned string
    // length does not include room for the null terminator. Returns an error if the
    // attribute is not specified. Returns an error if the attribute name is not valid
    // on this element. Returns an error if the attribute cannot be expressed as the
    // specified string type.
    function GetAttributeValueLength(name: PCWSTR;
                                     _type: D2D1_SVG_ATTRIBUTE_STRING_TYPE;
                                     out valueLength: UINT32): HResult; stdcall;
    {$EXTERNALSYM GetAttributeValueLength}

    /// <summary>
    /// Sets an attribute of this element using a POD type. Returns an error if the
    /// attribute name is not valid on this element. Returns an error if the attribute
    /// cannot be expressed as the specified type.
    /// </summary>
    function SetAttributeValue({_In_} name: PCWSTR;
                               _type: D2D1_SVG_ATTRIBUTE_POD_TYPE;
                               value: Pointer;
                               valueSizeInBytes: UINT32): HResult; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a POD type. Returns an error if the
    // attribute is not specified. Returns an error if the attribute name is not valid
    // on this element. Returns an error if the attribute cannot be expressed as the
    // specified POD type.
    function GetAttributeValue(name: PCWSTR;
                               _type: D2D1_SVG_ATTRIBUTE_POD_TYPE;
                               value: Pointer;
                               valueSizeInBytes: UINT32): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}


    // Sets an attribute of this element using an interface. Returns an error if the
    // attribute name is not valid on this element. Returns an error if the attribute
    // cannot be expressed as the specified interface type. Returns an error if the
    // attribute object is already set on an element. A given attribute object may only
    // be set on one element in one attribute location at a time.
    function SetAttributeValue({_In_} name: PCWSTR;
                               {_In_} value: ID2D1SvgAttribute): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as an interface type. Returns an error if the
    // attribute is not specified. Returns an error if the attribute name is not valid
    // on this element. Returns an error if the attribute cannot be expressed as the
    // specified interface type.
    // <param name="riid">The interface ID of the attribute value.</param>
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_In_} const riid: REFIID;
                               {_COM_Outptr_result_maybenull_} value: Pointer = nil): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element using a float.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: FLOAT): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a float.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: FLOAT): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a color.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: PD2D1_COLOR_F): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a color.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_COLOR_F): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a fill mode. This method can be used to set
    // the value of the 'fill-rule' or 'clip-rule' properties.
    function SetAttributeValue({_In_}name: PCWSTR;
                               value: D2D1_FILL_MODE): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a fill mode. This method can be used to get
    // the value of the 'fill-rule' or 'clip-rule' properties.
    function GetAttributeValue({_In_} name: PCWSTR;
                              {_Out_} out value: PD2D1_FILL_MODE): HResult; overload; stdcall;
      {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a display value. This method can be used to
    // set the value of the 'display' property.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: D2D1_SVG_DISPLAY): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a display value. This method can be used to
    // get the value of the 'display' property.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_SVG_DISPLAY): HResult; overload; stdcall;
     {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as an overflow value. This method can be used
    // to set the value of the 'overflow' property.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: D2D1_SVG_OVERFLOW): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as an overflow value. This method can be used
    // to get the value of the 'overflow' property.

    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_SVG_OVERFLOW): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a line join value. This method can be used
    // to set the value of the 'stroke-linejoin' property.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: D2D1_SVG_LINE_JOIN): HResult; overload; stdcall;
     {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a line join value. This method can be used
    // to get the value of the 'stroke-linejoin' property.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_SVG_LINE_JOIN): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a line cap value. This method can be used
    // to set the value of the 'stroke-linecap' property.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: D2D1_SVG_LINE_CAP): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a line cap value. This method can be used
    // to get the value of the 'stroke-linecap' property.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_SVG_LINE_CAP): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a visibility value. This method can be used
    // to set the value of the 'visibility' property.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: D2D1_SVG_VISIBILITY): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a visibility value. This method can be used
    // to get the value of the 'visibility' property.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_SVG_VISIBILITY): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a matrix value. This method can be used to
    // set the value of a 'transform' or 'gradientTransform' attribute.
    function SetAttributeValue({_In_} PCWSTR name,
                               value: PD2D1_MATRIX_3X2_F): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    /// Gets an attribute of this element as a matrix value. This method can be used to
    /// get the value of a 'transform' or 'gradientTransform' attribute.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_MATRIX_3X2_F): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a unit type value. This method can be used
    // to set the value of a 'gradientUnits' or 'clipPathUnits' attribute.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: D2D1_SVG_UNIT_TYPE): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a unit type value. This method can be used
    // to get the value of a 'gradientUnits' or 'clipPathUnits' attribute.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_SVG_UNIT_TYPE): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as an extend mode value. This method can be
    // used to set the value of a 'spreadMethod' attribute.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: D2D1_EXTEND_MODE): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a extend mode value. This method can be
    // used to get the value of a 'spreadMethod' attribute.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_EXTEND_MODE): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a preserve aspect ratio value. This method
    // can be used to set the value of a 'preserveAspectRatio' attribute.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: PD2D1_SVG_PRESERVE_ASPECT_RATIO): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as a preserve aspect ratio value. This method
    // can be used to get the value of a 'preserveAspectRatio' attribute.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_SVG_PRESERVE_ASPECT_RATIO): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Sets an attribute of this element as a length value.
    function SetAttributeValue({_In_} name: PCWSTR;
                               value: PD2D1_SVG_LENGTH): HResult; overload; stdcall;
    {$EXTERNALSYM SetAttributeValue}

    // Gets an attribute of this element as length value.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_Out_} out value: PD2D1_SVG_LENGTH): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Gets an attribute of this element.
    function GetAttributeValue({_In_} PCWSTR name,
                               {_COM_Outptr_result_maybenull_} value: ID2D1SvgAttribute = nil): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Gets an attribute of this element as a paint. This method can be used to get the
    // value of the 'fill' or 'stroke' properties.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_COM_Outptr_result_maybenull_} value: ID2D1SvgPaint = nil): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Gets an attribute of this element as a stroke dash array. This method can be
    // used to get the value of the 'stroke-dasharray' property.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_COM_Outptr_result_maybenull_} value: ID2D1SvgStrokeDashArray = nil): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Gets an attribute of this element as points. This method can be used to get the
    // value of the 'points' attribute on a 'polygon' or 'polyline' element.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_COM_Outptr_result_maybenull_} value: ID2D1SvgPointCollection = nil): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}

    // Gets an attribute of this element as path data. This method can be used to get
    // the value of the 'd' attribute on a 'path' element.
    function GetAttributeValue({_In_} name: PCWSTR;
                               {_COM_Outptr_result_maybenull_} value: ID2D1SvgPathData = nil): HResult; overload; stdcall;
    {$EXTERNALSYM GetAttributeValue}


end; // interface ID2D1SvgElement

 

It needs some polishing, but gives you the idea!

Edited by maXcomX

Share this post


Link to post
Guest
5 hours ago, maXcomX said:

Well.. I'm affraid the Interface ID2D1SvgElement declaration is not correct. And a reason why it it doesn't work as expected by the latest SDK.

I am afraid that Delphi compiler is wrong when it comes to COM interfaces since day one, and hasn't been not been tested for overloaded functions with Microsoft COM's.

 

To read more and it is highly recommend to know

To some this up Visual Studio reverse does reorder the overloaded functions in this was: 

the overloaded functions will be consequential not following the declaration order

the overloaded functions will be in reverse order, means last declared will be the first

 

example

when the declaration order is like this

Quote

A

B overload (B1)

C

B overload (B2)

D

they will be order after compilation like this

Quote

A

B overload (B2)

B overload (B1)

C

D

( may be i am wrong here, but this what i believe is right for now)

Share this post


Link to post

Hello pyscripter,

many thanks for this library. I've downloaded the example and enhanced it to draw the SVG onto a metafile canvas; but I get always a black background. When painting on the form's canvas or a paintbox canvas the drawing is transparent as I expected.

Any idea how to remove the black background when painting to a metafile canvas?

 

And btw:

SVGInterfaces.pas: property "Heigth" is spelled wrong; should be "Height".

 

 

SVG Drawing.png

Edited by Achim Kalwa

Share this post


Link to post

you should paint a background to the metafile canvas first, or copy (play) the metafile to its final destination where you already have a background (maybe you already doing that, in this case try to save it to a file and look into it with a wmf viewer, maybe you find something)

Edited by Attila Kovacs

Share this post


Link to post
41 minutes ago, Attila Kovacs said:

try to save it to a file and look into it with a wmf viewer, maybe you find something)

That was a good hint: Enumerating the emf file shows a EMR_BITBLT as the main graphics command. I was hoping that painting the SVG to a GDI canvas will result in a bunch of GDI commands/operations, but the SVG is rendered to a bitmap representation instead. That's OK for me.

svg_emf.thumb.png.972dad96b92644dd0fe090d58d55d1c0.png

 

  • Like 1

Share this post


Link to post

Today I've merged the great work made by @pyscripter and @Vincent Parrett into SVGIconImageList project and released 1.8 version.
Now with the new components SVGIconImageCollection and SVGIconVirtualImageList it's possibile to build multi-form High-DPI app in a multi-monitor environment using a single ImageCollection shared by the forms.
Many SVG rendering problems are now fixed!

 

Edited by Carlo Barazzetta
  • Like 2
  • Thanks 1

Share this post


Link to post

Can you add to Github a note of precisely which operating systems this supports?  At the start of this thread Windows 10 Creators Update or later was mentioned, but this is not made clear as far as I can find.  What is the fallback on an unsupported OS?

Share this post


Link to post

It still supports older versions of windows (not sure which but I would imagine windows 7+. The work to integrate  Direct2D support has not been done yet.. more refactoring required to abstract the rendering so that different svg engines can be used. @pyscripter has made some major improvements to the existing svg engine, fixing several bugs and improving performance. 

Share this post


Link to post
On 8/12/2020 at 11:54 AM, Achim Kalwa said:

That was a good hint: Enumerating the emf file shows a EMR_BITBLT as the main graphics command. I was hoping that painting the SVG to a GDI canvas will result in a bunch of GDI commands/operations, but the SVG is rendered to a bitmap representation instead. That's OK for me.

svg_emf.thumb.png.972dad96b92644dd0fe090d58d55d1c0.png

 

 Hello, which tool do you use to do this enumeration?, thanks.

Share this post


Link to post
22 hours ago, Alberto Fornés said:

 Hello, which tool do you use to do this enumeration?, thanks. 

It is something I created myself with Delphi 10.3.

In the past I used a tool named MetaFileExplorer, but it always crashed on some of the files I need to handle. In a first step I tried to fix that bug in the C++ code, but finally decided to create my own EMF explorer using Delphi. It is not public available; and is far from complete (it only handles ~50% of all possible EMR commands; mainly what the VCL Graphics uses when painting on Canvas).

  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×