Code Monkey home page Code Monkey logo

image32's Introduction

Image32

A 2D graphics library written in Delphi Pascal

Image32 is a comprehensive 2D graphics library written entirely in Delphi Pascal, and without dependencies on other libraries. It provides an extensive range of image manipulation and drawing functions that includes text rendering through native parsing of truetype font files.

Other significant features include

  1. An extensive list of image manipulation functions
  2. A polygon renderer that supports a very wide range of drawing options including tiled images, and linear and radial gradient fills
  3. Cross-platform support using either Delphi's FMX framework or the Lazarus pascal compiler

Documentation

Extensive documentation can be found here.

Images from demo sample applications

Layers201
Layers201 video

Layers301
Layers301 video

svg1
SVG101 video

Vectorize
Vectorize video

image32's People

Contributors

ahausladen avatar angusjohnson avatar escain avatar pierreyager avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

image32's Issues

SetRoundMode should be used with try/finally

Hello,

the Rasterize procedure in Img32.Draw alters the FPU rounding mode by calling SetRoundMode(rmDown):

savedRoundMode := SetRoundMode(rmDown);

At the end of the procedure, the rounding mode is set back to the original value. However, there may be conditions where the procedure exits prematurely, in particular when a zero-width rect was passed (for whatever reason), but also in case of an exception.

In this case, code execution never reaches the call which resets the rounding mode, and it is left in its rmDown state, which may lead to unexpected behavior in other parts of the application which use Delphi's Round() functions etc.

I think this issue can be solved easily by wrapping the entire code between the two SetRoundMode() calls into a try..finally..end block:

savedRoundMode := SetRoundMode(rmDown);
try
  // rest of the code
finally
  SetRoundMode(savedRoundMode);
end;

Let me know if you need a PR for this.

GetCompositeGlyph Result?

in the function "TFontReader.GetCompositeGlyph" nothing seems to be done with the Result var.

and thus:
if Result <> nil then
AffineTransform(a,b,c,d,e,f, result);
seems to me as a statement that is never executed.

Is this indeed "wrong" or do I overlook something?

edit: indeed you are right. I overlooked the main "while". thanks

Refresh Bug - Layer 301 example

Hi Angus,

it seems that there's a refresh problem when you have several nested group layers. The problem can be reproduced.
The problem occurs when a layer moves outside the bounds of the parent layer.

Have a look at the video:

Layer301-refresh.bug.mp4

and

Layer301-refresh.bug.2.mp4

No clue at the moment what leads to the 2nd situation.

Cheers,
Peter

FR: SVG Image element

When comparing SVG renderers, I've found that Image32 SVG is in many regards better than others, but the SVG Image element is missing. It would be very useful to have drawing if the xlink:href attribute points to an embedded base64-encoded image (would remove the need to use the Direct2D SVG api): Data Uri.

Double line path glitch

Tried to render SVG with a single path consisted of one long and one short lines:
<path d="m 160,720 h 120 v 0.025" style="stroke: #000000;" />
and got an unexpected result:
image

while rendering almost the same path:
<path d="m 160,720 h 120 v 0.028" style="stroke: #000000;" />
is ok and looks like this:
image

The whole SVG file is:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   width="800"
   height="800"
   viewBox="0 0 800 800"
>

<path d="m 160,720 h 120 v 0.025" style="stroke: #000000;" />
   
</svg>

Wrong Encoding Detection when file has no BOM

When using a file without a BOM and unicode string, the parser defaults to the default encoding. This results in a wrongly parsed svg due to the zeros of the surrogates.

A sample is attached. The parser creates a SVG instance with with and heigth zero even though a viewport is defined.

Test

Notepad and co evaluate the string encoding if no BOM can be found:

I added a hack in the current implementation of Img32.SVG.Core -> GetXmlEncoding and it works for me:

image

Can you integrate a fix into the next version so that I can remove my workaround ?

Negative index on array pointer can be unsupported

This issue is found only in latest source (from July 7).
Contrary to common practice over the last decades, negative index
on static-array pointer (eg. buf[ index]) is unsupported by certain compilers (at least 64bit-FPC):
To prevent wrong code generation, Range Checking can't be ignored on static array pointer.
for reference: graphics32/graphics32#51

If I reuse the existing type names, then supported alternative types look like this:
(Range Checking can stay enabled):

type
{$PointerMath on}  // support of negative index
PStaticByteArray = ^Byte;  // use this instead of PByteArray
PStaticDoubleArray = ^double;
PStaticInt64Array = ^int64; 
PStaticColor32Array = ^TColor32;
{$PointerMath off} 

Delphi 12.1 compilation for IOS and Android error

Hello,

Problem with 64 bits compilation in Delphi 12.1 ?

`unit
Img32.SVG.Core
function Base64Decode(const str: PAnsiChar; len: integer; memStream: TMemoryStream): Boolean;

...
memStream.SetSize((len div 4 * 3) - extra);
...

[DCC Error] Img32.SVG.Core.pas(348): E2251 Ambiguous overloaded call to 'SetSize'
System.Classes.pas(1238): Associated method : procedure TMemoryStream.SetSize(const Int64);
System.Classes.pas(1239): Associated method : procedure TMemoryStream.SetSize(LongInt);

On IOS 64 and Android 64

Couldn't get Img32.Fmt.SVG to open the image in native size as suggested by the help

Hey Angus, me again, here's what your help for Img32.Fmt.SVG says:

If you need an image rendered at the SVG image's native size, then make sure the TImage32 object is empty (ie zero width and height) before calling its load method.

Unfortunately I couldn't get this to work as announced, the image was always created in (defaultSvgWidth, defaultSvgHeight). After taking a look at your code I figured out that there couldn't be a proper solution unless checking for both the img32 object and the viewbox being empty, so here's the code I'm now using on lines 395/396 in Img32.Fmt.SVG:

  if **r.IsEmpty and** img32.IsEmpty then
    img32.SetSize(defaultSvgWidth, defaultSvgHeight);

I hope I didn't get anything wrong, if so please correct me ...

				Michael

--
PGP Key ID (RSA 2048): 0xC45D831B
IERenderer's Home https://www.pmpgp.de/renderer/History.htm
S/MIME Fingerprint: 94C6B471 0C623088 A5B27701 742B8666 3B7E657C

Duplicate Constants in Color List

//custom gray colors

I noticed that some constants in the color list are duplicated:

// custom gray colors
clDarkGray32 = TColor32($FF505050);
clDarkGrey32 = TColor32($FF505050);
// clGray32   = TColor32($FF808080);
// clSilver32 = TColor32($FFC0C0C0);
clLiteGray32 = TColor32($FFD3D3D3);
clLiteGrey32 = TColor32($FFD3D3D3);
clPaleGray32 = TColor32($FFE0E0E0);
clPaleGrey32 = TColor32($FFE0E0E0);
clDarkBtn32  = TColor32($FFE8E8E8);
clBtnFace32  = TColor32($FFF0F0F0);
clLiteBtn32  = TColor32($FFF8F8F8);

Specifically, the following pairs are duplicates:

  • clDarkGray32 and clDarkGrey32
  • clLiteGray32 and clLiteGrey32
  • clPaleGray32 and clPaleGrey32

Could you please confirm if this duplication is intentional? If not, it would be helpful to remove the duplicates to avoid confusion.

SVG: Implicit gradient boundaries should duplicate the adjacent color.

If vector boundary-stops (offsets 0, 1) are implicit, then boundary and adjacent inner stop (explicit) should have the same color.
SVG specs don't noticeably document this rule, but contains one compliant example:

If one stop is defined, then paint with the solid color fill using the color defined for that gradient stop.

For example, this single stop could be somewhere in the middle of the gradient vector,
but in any case, the whole vector will use the same color.
So, TGradientElement.prepareRenderer() needs something like this:

procedure TgradientElement.prepareRenderer_innerStops( renderer: TCustomGradientRenderer);
// assumes precise offsets (possibly already rounded)
var hiStops, i: integer;
begin
  hiStops := high(stops); if (hiStops < 1) then exit;
  if (stops[0].offset > 0) then  // input is inner first offset
      renderer.insertColorStop(stops[0].offset, stops[0].color);
  for i := 1 to hiStops -1 do with stops[i] do
      renderer.insertColorStop(offset, color);
  if (stops[hiStops].offset < 1) then // input is inner last offset
      renderer.insertColorStop(stops[hiStops].offset, stops[hiStops].color);
end;

SVG example in browser:
implicitBoundaryStops

Vectorize works but saves weird things to SVG

uses  ..., SimpleSvgWrite, Img32, Img32.Vector, Img32.Extra, Img32.Draw, Img32.Fmt.BMP, Img32.Fmt.SVG;

var Img: TImage32;
    RawPaths: TPathsD;
    flattenedPaths, bezierPaths: TPathsD;
    simplifiedPaths: TPathsD;
    Svg: TSimpleSvgWriter;
begin
  Img := TImage32.Create;
  Img.LoadFromFile('test.bmp');

  RawPaths := Vectorize(Img, $FF000000, @CompareRGB, $44);

  flattenedPaths := rawPaths;

  DrawPolygon(Img, flattenedPaths, frEvenOdd, clNavy32);
  Img.SaveToFile('out.bmp');

  Svg := TSimpleSvgWriter.Create(frEvenOdd);
  Svg.AddPaths(flattenedPaths, false, $40000033, $FF000033, 1.2);

  Svg.SaveToFile('test.svg');
  Svg.Free;
  Img.Free;

out.bmp shows correct image, test.svg shows a single line. Code tested in Lazarus.

Png file shows only part of the SVG file

I tried this coding to convert a SVG file to PNG:

uses Img32, Img32.Fmt.SVG, Img32.Fmt.PNG;
...
//change image format from SVG to PNG
img := TImage32.Create(800,600);
img.LoadFromFile('drawing.svg');
img.SaveToFile('drawing.png');
img.Free;

The SVG file looks like this in Chrome Webbrowser:

image

But the PNG file only shows this, independent of the provided pixel or any scale... methods I am calling:

image

The SVG file you can find in the attached zip file. What do I wrong?
drawing.zip

I use Delphi 10.2 and Image32 version 4.3

tspan tag text-anchor attribute invalid

 <text
     id="text3876"
     xml:space="preserve"
     font-size="10px"
     y="62"
     x="125"
     font-family="Arial"
     fill="#ff0000"
     style="line-height:0%;">
<tspan
       id="tspan3878"
       sodipodi:role="line"
       style="font-size:12px;line-height:1.25"
  fill="#00ff00"
       y="62.1"
       x="125.1">line1</tspan>
<tspan
       id="tspan3912"
       sodipodi:role="line"
       style="font-size:12px;line-height:1.25;text-align:end;text-anchor:end"
       y="75.2"
       x="125.2">line2</tspan>
</text>
</svg>

SVG: Stroke geometry does not fully respect transform

The found issue is caused in TShapeElement.DrawStroke().
SVG (and common APIs) demand that CTM affects strokes just like geometric shapes.
For example, under nonuniform scale or skew, the visual stroke-width should be varying.
(For authors, this is also needed to preserve gaps between lines and other objects regardless of scene-transform.)
Correct draw of affine circle in browser:
affineCircle

antialiasing issues when using imagepanel to Scaling

I noticed the usage of imagepanel in your example (svg.dpr), but the same aliasing appears when zooming, how can I keep its sharpness, I tried to redraw, but it seems that the pixels have become larger, Is scaling impossible? Finally, thank you very much for your contribution, this is excellent work

Latest git push is not compilable

I'm moving from sourceforge project to new github project.
Many new features, fix and improvements seems to be at now available.

But, cloning last code (96a2421)
the compilation of packages with Sydney 10.4.1 (just to know what I use for), get a lot of missing files and missing options
on project.

dpk are not enought to rebuild a project because missing of any dproj settings as well as list of units prefix.
So a import Graphics, is not enough, you have to add Vcl prefix in options or use Vcl.Graphics in unit import.

In dpk are requested Clipper files different than source projects and also SVG writer is missing.

Save dproj for your delphi version is a starting point, IDEs automatically promote to upper versions of Delphi.
Try to git clone your library in a new folder, change tools library to that and recompile all.
Don't miss to delete ANY library .dcu present in your PC to avoid a direct link to already compiled dcu in some path.

Why did Resource Hacker 5.1.8 got reverted to 5.1.7?

Asking here as this repository is probably what Resource Hacker is based on.

https://web.archive.org/web/20221224133731/http://www.angusj.com/resourcehacker/ now has version 5.1.7 first archived as https://web.archive.org/web/20190103025235/http://angusj.com/resourcehacker (downloadable as EXE install and ZIP install)

Up until https://web.archive.org/web/20221107224420/http://www.angusj.com/resourcehacker/ version 5.1.8 was available (downloadable as EXE install and ZIP install)

Why after almost 4 years the reversal?

Glitch when resizing TBitmap

Hello,

I am trying to use Image32 to scale images in our application. After integrating the library, I am facing some glitches on the resulting TBitmap with transparency.

The full question is described here: https://stackoverflow.com/questions/76818048/resizing-tbitmap-with-alpha-channel-in-delphi

Simplified, the code looks like :

function scaleBitmap( inPict: TPicture; scale: TSize; newRect: TRect ) : TPicture
begin
  var inBitmap: TImage32 := TImage32.Create;
  var outBitmap: TBitmap := TBitmap.Create;

  try
    inBitmap.CopyFromBitmap(inPict.Bitmap);

    inBitmap.Resampler := rBicubicResampler;
    inBitmap.Resize(scale.Width, scale.Height); // New size
    inBitmap.Crop(newRect); // Take only the required part.

    outBitmap.PixelFormat := pf32bit; // I think it's not required
    inBitmap.CopyToBitmap(Result); //Assume already created.
  finally
    FreeAndNil(inBitmap);
    FreeAndNil(outBitmap);
  end;
end

We have to interact with other components, that is why we use TBitmap and not TImage32 as the result.

The resulting image is scaled correctly, but alpha channel seems incorrect:

Original:
2vlDd

Scaled:
Pj9YH

Incorrect interpretation of USE_MY_METRICS

Image32/source/Img32.Text.pas

Lines 1885 to 1890 in 4e2ba14

if (flag and USE_MY_METRICS <> 0) then
begin
if Result <> nil then
AffineTransform(a,b,c,d,e,f, result);
end else
AffineTransform(a,b,c,d,e,f, componentPaths);

It is my understanding that the USE_MY_METRICS flag has nothing to do with the path transformation. As I read it, if a child glyph has the USE_MY_METRICS flag set it means that the parent glyph should use the metrics of the flagged child glyph. The metrics being the left side-bearing, right side-bearing, and advance width.
The Apple docs aren't very clear on this. The Microsoft docs are a bit better - but not much.

Feature request: How about an event for making the image object accessible

I'm sorry for not finding a more proper subject for this, Angus, but here's what I was looking for, what I aready tried, and why I'm asking for an additional event:

  1. First thing was my intention to access the TPngImage object for adjusting its compression level since it might not be desirable to use compression in certain situations, for a discussion about this cf. here.
  2. Next I took a look at your subclassing feature as provided using the TImageFormat() class: Now here I may be wrong, but I couldn't get it to work without apparently having to provide a completely rewritten (resp. copied) image format class since I never got to the point where registering a class derived from an existing one would replace the already existing one since the registering routine immediately exits if it detects an attempt to register the new one for replacing an already existing one. IOW: Since the inherited ancestor class is always registered before registering the derived one there's currently no way to replace it - or am I doing something wrong here?
  3. So finally, that's why I'm coming up to make my suggestion: If the "subclassing" cannot achieve what I'm looking for, how about implementing a final OnSaveToStream() event exposing the TPngImage object (and similar for any other image type) for applying further type specific options without creating the need for you to provide various different access points depending on the respective image type's capabilities?

PS: For now I've just added a single line setting the desired compression level directly into your code, but that's note really the way I would prefer if there's a better one to be shared ...

				Michael

--
PGP Key ID (RSA 2048): 0xC45D831B
IERenderer's Home https://www.pmpgp.de/renderer/History.htm
S/MIME Fingerprint: 94C6B471 0C623088 A5B27701 742B8666 3B7E657C

Documentation Examples Not Working

Hello,
I've been following the documentation examples provided at the following links:
http://www.angusj.com/image32/Docs/QuickStart.htm
http://www.angusj.com/image32/Docs/Units/Img32.Extra/Routines/Draw3D.htm
Unfortunately, none of these examples work as expected because the methods and functions mentioned seem to be unknown or missing. I am particularly interested in drawing the 3D text as shown in the image at http://www.angusj.com/image32/Images/text_3D.png. Could you please provide guidance on how to achieve this?

Thank you for your assistance.

rotate(270) does not adjust with and height for viewport and image when rendering

When I use the image attached, it looks fine in the web. But on a Canvas, the image is not rotates

Web:
b

Image
image
I debugged it an it seems, as if the viewport is not rotated. The same for the width and the height.
I now intercepted the width and height, but its quity hacky. I did not find a solution for the viewport now.
Can you fix this ?

Issues when building Mac Os 64 Bit

Hi!
We are using the SVG Icon Image List library which at its core uses the Image32 library from this repository.
We noticed that simply inserting a tsvgiconimage into an empty FMX project, using the default engine, builds for Windows but not for Mac.
This happens using version 4.1.2 of SVGIconImageList but not with 3.9.6
Version 4.1.2 includes Image32 version 4.4 (2023/12/17) while version 3.9.6 includes version 4.4 (2023/01/30).
The odd thing, which also happens on Windows, seems to be related to the FireMonkeyVersion define which is not read correctly and causes the Mac build to fail when the Img32 unit (Angus Johnson) tries to include Vcl.* units instead of FMX units as expected.

Problems

D10.2.3
Img32.Clipper>Img32.Clipper2
Img32.Ctrl.pas where is TStorageManager???
ON G:\Delphi Projects\AngusJohnson\Image32-main\Examples\SVG2\main.pas
Svg.width := 250;
Svg.height := 300; does not exsist

fontInfo.family := ttfSansSerif;
fontInfo.size := 12; not declare
and may be more

Use Img32 in a "VCL" dll ?

Hello,

When I compile my DLL that requires Img32 and Img32.FMT.PNG, the PNG file format seems not registered.

It looks like it's due to the test to detect whether Firemonkey is available :

{$ELSEIF declared(FireMonkeyVersion) OR DEFINED(FRAMEWORK_FMX)}
  {$DEFINE USING_FMX}
{$ELSE}
  {$DEFINE USING_VCL}
  {$DEFINE USING_VCL_LCL}
{$IFEND}

What causes {$IF declared(FireMonkeyVersion) OR DEFINED(FRAMEWORK_FMX)} to be true ? Maybe a require somewhere ?

Thanks for your help

Wrong colors

Hi there!

<svg width="128" height="128" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M0 0h128v128H0z"/></svg>
= 255, 255, 255

<svg width="2" height="2" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 .5h2M.5 0v2" stroke="#fff"/></svg>
= 254, 254, 254

0

Do you have any ideas how to fix it?

Source: Project1.zip
Original: EtheaDev/SVGIconImageList#273

Missing JtBevel

In the last repository Image32.Clipper2 requires for jtBevel which does not exists in Clipper.pas, neither in other repository Clipper.

TImageFormat_QOI.SaveToStream declaration error

Compiling the library i get this error in unit Img32.Fmt.QOI

procedure SaveToStream(stream: TStream; img32: TImage32); override;

procedure SaveToStream(stream: TStream; img32: TImage32; quality: integer = 0); override; base class

SetRoundMode should not be used at all ;)

Hi,

in an earlier issue (#41) I pointed out that a try/finally block was missing in the Rasterize procedure of Img32.Draw.pas, because there are situations where the rounding mode (altered with SetRoundMode) is not reset properly.

Even with the fix apply, I kept seeing incorrect rounding modes, in particular in background threads, so I did a bit more research.

TL;DR: SetRoundMode should not be used in a multi-threaded application, because it is not thread-safe at all.

The answer to this SO question by David Heffernan is a good starting point to understand the issue: https://stackoverflow.com/questions/39684161/why-an-application-starts-with-fpu-control-word-different-than-default8087cw

(The SO question deals with floating point exceptions, but these are also controlled by bits/flags in the 8087 control word, just like the current rounding mode.)

In a nutshell, using SetRoundMode (or more generally, any of Delphi's function to change the FPU flags, like Set8087CW) will store the current state in Default8087CW, which is a global variable in System.pas. And which is also used to initialize the FPU for any new thread being started (in _FpuInit in System.pas).

So when you temporarily change the rounding mode to rmDown via SetRoundMode, and a thread is started before you change it back to rmNearest, the thread will be initialized and run in rmDown mode. Here is a small console application that demostrates the problem: https://github.com/tweibert/RoundModeNotThreadSafe

Img32.Draw.pas does not use any threading, obviously, but it could be the case that there is an existing background thread that spawns another background thread, while the main thread is in the middle of executing the Rasterize function. Then the second background thread would suffer from this effect.

Now what is the solution? The bottom line is, the Delphi version of SetRoundMode should not be used. Instead, one could either:

or

  • Do not use Round() at all but rather Trunc(). I saw comments in the code saying that Trunc() was rather slow, and also some (commented out) more efficient __Trunc() function that was used in earlier versions of Image32. As a quick fix, I re-enabled that function now, and changed all calls from Round() to __Trunc() in Img32.Draw.pas.

Thanks for looking into this.

Torben

EDIT: Regarding the former possible solution (thread-safe version of SetRoundMode), the following code could be used:

procedure Set8087CWThreadSafe(ANewCW: Word);
var
  L8087CW: Word;
asm
  mov L8087CW, ANewCW
  fnclex
  fldcw L8087CW
end;

function SetRoundMode(const RoundMode: TRoundingMode): TRoundingMode;
var
  CtlWord: Word;
begin
  CtlWord := Get8087CW;
  Set8087CWThreadSafe((CtlWord and $F3FF) or (Ord(RoundMode) shl 10));
  Result := TFPURoundingMode((CtlWord shr 10) and 3);
end;

This is for 32-bit only. For x64, Delphi uses the MMX extensions instead. And other platforms? No idea, honestly.

Resize() produces wrong size

Hello,

I have found that the Resize() method, depending on the original and requested size, does not always produce an image of the request sized, but 1 pixel wider and/or higher.

It only happens when using one of the resamplers, e.g. the bilinear or bicubic one.

Here is some code to demonstrate the issue:

program Test1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Img32;

var
  img: TImage32;

begin
  try
    img := TImage32.Create(225, 225);
    try
      img.Resize(122, 122);

      WriteLn(Format('New size: %d / %d', [img.Width, img.Height])); // wrong: 123 / 123
    finally
      img.Free;
    end;

    img := TImage32.Create(225, 225);
    try
      img.Resampler := 0;
      img.Resize(122, 122);

      WriteLn(Format('New size: %d / %d', [img.Width, img.Height])); // correct: 122 / 122
    finally
      img.Free;
    end;

    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

I stepped through the code, and it appears that it is caused by rounding errors when going back to integer coordinates in GetBounds():

function GetBounds(const path: TPathD): TRect;
var
  recD: TRectD;
begin
  recD := GetBoundsD(path);
  Result := Rect(recD);
end;

In the above example, the calculated height and width (as Double) is just slightly larger than 122, so that Ceil() turns it into 123:

function Rect(const recD: TRectD): TRect;
begin
  Result.Left := Floor(recD.Left);
  Result.Top := Floor(recD.Top);
  Result.Right := Ceil(recD.Right);
  Result.Bottom := Ceil(recD.Bottom);
end;

The fact that Resize() does not work as expected causes trouble in other parts of the library. In particular, ScaleToFitCentered() assumes that the temporary resized image it creates has exactly the requested size, which it has not, and then CopyInternal() will corrupt the RAM by copying more pixels from the source than the destination can hold.

Suspicious code in TFontCache.UpdateScale

procedure TFontCache.UpdateScale;
begin
  if IsValidFont and (fFontHeight > 0) then
  begin
    [...]
    NotifyRecipients(inStateChange);
  end else
  begin
    [...]
    NotifyRecipients(inDestroy);
  end;
end;

The NotifyRecipients(inDestroy) should probably be NotifyRecipients(inStateChange).

(out of topic) Simple Sudoku

I see no section for the game, the best one found on y side...
The game is still playable on modern Windows editions, but F1 shortcut is no more working due to hlp format changing for Vista+.
To have access to the tips help, you have to done about, then access to your web site, thanks to the browser http to https redirection.
My question:
Did you plan to rework the game for better using on W10 + ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.