Jump to content

Anders Melander

Members
  • Content Count

    2946
  • Joined

  • Last visited

  • Days Won

    166

Posts posted by Anders Melander


  1. minutes ago, dwrbudr said:

    What do you think is the safest fix?

    Fix or work-around? The safest work-around is to not call TBitmap.SaveTo* more than once on the same bitmap:

    bmp.Assign(png);
    bmp.SaveToFile('out_1.bmp');
    bmp.Assign(png);
    bmp.SaveToFile('out_2.bmp');

    I would guess (I would need to examine the logic more than I have time for, to be sure) the quick-fix is to modify TBitmap.WriteStream so it only counts the palette size once:

    if (FDIB.dsbmih.biBitCount > 8) and (FDIB.dsbmih.biClrUsed = 0) then
    begin  // optional color palette for hicolor images (non OS2)
      Inc(Size, ColorCount * SizeOf(TRGBQuad));
      Inc(HeaderSize, ColorCount * SizeOf(TRGBQuad));
    end;

    but to be honest, if this was my code, I would throw out the current TBitmap.WriteStream implementation and rewrite it from scratch. It's a horrible mess.

    • Like 1

  2. Here's the algorithm used when saving a TBitmap:

    1. Calculate Size based on HeaderSize, the number of pixels, color depth, and current value of BitmapInfoHeader.biClrUsed (number of entries in the palette).
    2. Calculate number of entries in the palette: ColorCount
    3. Adjust Size with the value of ColorCount: Size := Size + ColorCount * SizeOf(Pixel)
    4. Set BitmapFileHeader.bfSize = Size
    5. Write BitmapFileHeader to file
    6. Set BitmapInfoHeader.biClrUsed = ColorCount
    7. Write BitmapInfoHeader to file
    8. Write palette entries
    9. Write pixels

    BitmapFileHeader is a local variable that is nilled and initialized each time. BitmapInfoHeader is a class variable that is used to store the bitmap properties.

     

    Can you spot the bug?

     



    The first time the bitmap is saved, BitmapInfoHeader.biClrUsed=0.

    The second time the bitmap is saved, BitmapInfoHeader.biClrUsed=ColorCount, so the palette size is counted twice.

    

    • Like 1

  3. 2 hours ago, Lars Fosdal said:

    Basically, it is making things as readable as possible

    Kudos on managing to avoid the one style we can all read.

     

     

    1 hour ago, dummzeuch said:

    Rename an identifier (that one always worked fine within a single unit and most of the time even for the whole project)

    Rename across units have never worked for anything but the most trivial code (okay, maybe in the first couple of versions). And without that it's useless. I can manage rename in a single unit on my own, without the help of refactoring (but of course I wouldn't mind it).

     

     

    16 minutes ago, Stano said:

    It's been mentioned several times. These things are handled by MMX. And good.

    MMX doesn't have rename refactoring.

    I haven't got it installed anymore, so I can't verify, but every time I install it it's because I need rename refactoring and every time I discover that it can't do it properly and uninstall again.

    What you are referring to as "rename refactoring" is just a text search/replace in MMX.

    • Sad 1

  4. 9 hours ago, Dalija Prasnikar said:

     

    
    function TBaseFoo.BrokenFoo: IFoo;
    var
      LOwner: TComponent;
    begin
      Result := nil;
      if Supports(Self, IFoo) then
        Result := Self as IFoo
      else
        LOwner := Owner;
        // if block execution will continue here !!!! 
        while LOwner <> nil do
        begin
          if Supports(LOwner, IFoo) then
          begin
            Result := LOwner as IFoo;
            Break;
          end
          else
            LOwner := LOwner.Owner;
        end;
    end;

     

    I know the actual implementation wasn't the point, but I just can't leave code like that unchallenged. It haunts me.

    function TBaseFoo.BetterFoo: IFoo;
    var
      Item: TComponent;
    begin
      Result := nil;
      Item := Self;
    
      while (Item <> nil) and (not Supports(Item, IFoo, Result)) do
        Item := Item.Owner;
    end;
    • Like 2

  5. 33 minutes ago, Dave Novo said:

    Of course I understand the Claude code snippet. It is pulling the info from the About box. What is not to understand? 

    I think we have a case of tunnel vision here.

    Extracting the version number from the About Box is obviously not the way to do it; There's no contract that specifies how the returned string is formatted and if they change the format, the code breaks.

    "Delphi 14.0 Version 12.34.567.890 by Embarcadero®"

     

    The solution is really, really simple and does not involve the ToolsAPI at all:

    1. Assuming this is being done from a package or a DLL, use GetModuleFilename to get the filename of the host application (i.e. bds.exe).
    2. Use GetFileVersionInfo to get the version info.

  6. 1 hour ago, Dave Novo said:

    This is what Claude said. No idea if its true or not since I have never looked into this

    Just like GPS navigation systems made people forget how to find direction, apparently AI has made people forget how to think for themselves 🤔

    From where do you think the about box gets its version number information?.


  7. 1 hour ago, Patrick PREMARTIN said:

    The reason is simple : it's disabled for Delphi (but can be used by IDE plugins or for next update or release)

    It should have been hidden for Delphi. Having it visible but but disabled, with no way to make it enabled, is just confusing; Poor UI design.

    https://learn.microsoft.com/en-us/windows/win32/uxguide/win-dialog-box#disabling-or-removing-controls-vs-giving-error-messages

    • Like 3

  8. 1 hour ago, david berneda said:

    Manual formatting for me is the best way to make sure the code is well done, calmly, as a final double-check there are no big bugs or something missing.

    That's nice. If I send you this 800.000 line legacy project I need to clean up, when can you have it ready for me? 🙂

    It was written by someone who apparently had a sporadically stuck shift key, didn't like white space, and couldn't make up his mind if 1, 2, 3, or 8 space indents were the way to go.

    • Like 1
    • Thanks 1
    • Haha 6

  9. 3 hours ago, Vincent Parrett said:

    Yes - applications should not be installing root certificates into windows - the only scenario where I can see this being needed is when using self signed code signing certificates - which is happening more an more in enterprises for internal applications/scripts - especially ones where internet access is limited. 

     

    A bit of Googling tells me that the purpose of the certificate is to enable it to scan encrypted HTTPS traffic.

     

    image.thumb.png.6ec2fb3b2ce7753410424840b5ab4caa.png


  10. There are so many bugs and limitations in TListView (the Windows control, not the VCL wrapper) that I have found that as soon as I spend more than 10 minutes trying to work around something in it, it's often a better idea to replace it with something else.

    Just yesterday I needed the first column in a listview right-aligned; Forgetaboutit - and out it went.


  11. 14 hours ago, HeartWare said:

    but do you really think that a MUL/DIV sequence takes less time than a JMP?

    As I said, I haven't timed it - and it depends. MUL is dirt cheap. DIV is a little more expensive but not nearly as bad as it once was. Branches are almost always bad but if OldDPI=NewDPI most of the time then the jump out is obviously worth it.

     

    I honestly wouldn't bother doing this in asm in the first place. Unless you are using it to scale graphics in real-time, or something like that, then it's a completely wasted effort. Also remember that pascal code can be inlined (avoiding the call overhead), while asm functions can't. I would replace the MulDiv with a simple expression; You likely don't need the 64-bit and overflow handling baked into MulDiv (which is a Windows API function, btw - not cheap).

×