SVGIconImageList icon indicating copy to clipboard operation
SVGIconImageList copied to clipboard

Code not compiling under latest version

Open birbilis opened this issue 2 years ago • 11 comments

After upgrading to latest version, this code breaks:

  var bitmap := Glyph.MultiResBitmap[0] as TSVGIconFixedBitmapItem;
  bitmap.SVG.LoadFromStream(Stream);

[dcc32 Error] READCOM.Views.VectorImageStoryItem.pas(103): E2362 Cannot access protected symbol TFmxImageSVG.LoadFromStream

can try re-building http://github.com/zoomicon/READCOM_App to see this

the reason is the LoadFromStream method is protected and abstract now (which is strange since one may not just want to load from a file or from text)

I guess I can use a memory stream or something, but would be nice if I could directly use LoadFromStream as before

birbilis avatar Mar 28 '22 09:03 birbilis

btw, I may remove that code anyway and use direct drawing like in SVGViewer demo's FrameViewer.pas, since the above approach seems to cause pixelization upon zooming into the container https://youtu.be/0vXp5jUf8cU?t=710

birbilis avatar Mar 28 '22 09:03 birbilis

ahem, tried to use FrameViewer.pas code, but seems one can't adapt it to FMX from VCL, since it uses ISVG.PaintTo method that expects a Handle. How would one go to port that to FMX and draw directly into an FMX PaintBox's Canvas?

image

birbilis avatar Mar 28 '22 10:03 birbilis

The FMX implementation does not use interfaces but according to the compilation directive:

  • {$DEFINE Image32_SVGEngine} uses TFmxImage32SVG class.
  • {$DEFINE Skia_SVGEngine} uses TFmxImageSkiaSVG class. At the moment there is no easy way to draw directly on a FMX PaintBox, but you must use a TSVGIconImage component or a TGliph component linked to an ImageList. A refactoring of FMX painting engine using interfaces is on the roadmap...

carloBarazzetta avatar Mar 29 '22 12:03 carloBarazzetta

Problem is how can I stretch an image with FMX TSVGIconImage? I can't use TGlyph and ImageList in my case. Note the last parameter of PaintTo above, it was for stretching if I remember well

birbilis avatar Apr 03 '22 16:04 birbilis

to answer my own question, since TSVGIconImage descends from TImage (hadn't noticed) one can just do MySVGImg.WrapMode := TImageWrapMode.Stretch;

birbilis avatar Apr 04 '22 17:04 birbilis

So one thing that remains problematic in my case is this pixelization upon zooming in the container (I do zoom via ScaleLayout). Seems TSVGIconImage draws pixelized graphics when I zoom in, probably it treats FMX graphics as if they were integers (instead of singles). I'd expect it to always create a background buffer (and update it on resize) that is (widthscaleX, heightscaleY) sized. It also has some zoom parameter that I don't really understand what is supposed to do, it causes even more pixelization (plus that zoom param is integer and not single, so can't set it to 1/n in case it would do oversampling)

image

birbilis avatar Apr 04 '22 17:04 birbilis

I am not an FMX expert and I have implemented the BitmapZoom property (10 to 100%) to "reduce" the size of the image inside the container, when WrapMode is Original, Place or Tile... It is the same property used for the VCL version of the same component. If you use BitmapZoom instead of Scale probably the image is not pixelated ... Try and give me some feedback ...

carloBarazzetta avatar Apr 09 '22 17:04 carloBarazzetta

Not sure I understand how that BitmapZoom works, last time I tried BitmapZoom (is an integer, not a single number so can't use 0,5 for example) with a value>1 it resulted in even more pixelation.

From my perspective, the SVG is an infinite resolution image source. Since you inherit TImage I think you should be able to make it behave similarly to how it does when one loads a high resolution image and draw it in a smaller area (note I treat SVG as infinite res image), by generating the buffer not based on boundsrect, but on absoluterect (aka how big something shows on the screen - https://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.Controls.TControl.AbsoluteRect).

Question is though how do you get notified that absolutrect changed. Now I see in your code you redraw the buffer when the bounds change (being in a scaled parent doesn't change children bounds) and in some other cases. Probably in all cases where the backbuffer is redrawn it should use AbsoluteRect. Might even save some memory and avoid scaling down artefacts when user has zoomed out (in which case AbsoluteRect is smaller than Local BoundsRect). Note in my case I have AbsoluteRect>>BoundsRect (have a zoom in by using a ScaledLayout container)

Since you also seem to use MultiScale bitmaps maybe you don't even need to listen for bounds changes and FMX will ask you for the proper resolution drawing (if you could tell it to do in small steps even better, not sure if it's configurable). But haven't read much on how MultiScale bitmaps work (e.g. don't how Scale/ScaleRange of bitmaps work that are mentioned here https://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.MultiResBitmap.TCustomBitmapItem.Scale), so not sure

birbilis avatar Apr 10 '22 21:04 birbilis

At first I guessed you might need a TCustomMultiResBitmap descendent that spits out bitmaps of any resolution.

However, it seems that FMX asks what bitmap Scales are provided to judge which bitmap to use and then you have to pass it the Scale it asks for. Even if you used RegisterScale (and just provide one based on the AbsoluteRect) on the fly when it asked for a list of scales, not sure how often it will ask you for the list of scales. Aka if it will ask for that at each repaint due to parent control rescaling (FMX controls have Scale property and there is also ScaledLayout that scales its children [multiplying the scaling effect their own - or their children/grandchildren etc. - Scale setting may already have])

UPDATE: now that I see it again, I see a RegisterScaleName (https://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.MultiResBitmap.RegisterScaleName) that probably is more design-oriented (I hope). Instead TCustomMultiResBitmap has ItemByScale and ScaleArray at https://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.MultiResBitmap.TCustomMultiResBitmap_Methods so if one made the ScaleArray property only return one scale value based on the AbsoluteScale (https://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.Controls.TControl.AbsoluteScale) and the ItemByScale to return the appropriate bitmap (could have it then cached till other AbsoluteScale is detected at ScaleArray getter upon which it would be dropped), then it might work to have infinite resolution images

birbilis avatar Apr 10 '22 21:04 birbilis

btw, Skia4Delphi also has some image drawing control, not sure if that descends from TImage or not. If it does, have they done this infinite resolution thing I'm taking about maybe already in their code?

birbilis avatar Apr 10 '22 21:04 birbilis

Can I close this issue?

carloBarazzetta avatar Sep 14 '22 06:09 carloBarazzetta