Ignore:
Timestamp:
Apr 16, 2024, 10:57:39 AM (4 weeks ago)
Author:
chronos
Message:
  • Fixed: Map drawing in case of fractional scaling.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Packages/DpiControls/Dpi.Common.pas

    r523 r538  
    1111
    1212function BitBlt(DestDC: HDC; X, Y, Width, Height: Integer; SrcDC: HDC; XSrc,
    13     YSrc: Integer; Rop: DWORD = SRCCOPY): Boolean;
     13  YSrc: Integer; Rop: DWORD = SRCCOPY): Boolean;
    1414function BitBltCanvas(Dest: TCanvas; X, Y, Width, Height: Integer; Src: TCanvas;
    15     XSrc, YSrc: Integer; Rop: DWORD = SRCCOPY): Boolean;
     15  XSrc, YSrc: Integer; Rop: DWORD = SRCCOPY): Boolean;
     16function BitBltBitmap(Dest: TBitmap; X, Y, Width, Height: Integer; Src: TBitmap;
     17  XSrc, YSrc: Integer; Rop: DWORD = SRCCOPY): Boolean;
    1618function CreateRectRgn(X1, Y1, X2, Y2: Integer): HRGN;
    1719{$IFDEF WINDOWS}
     
    3941resourcestring
    4042  SNotImplemented = 'Not implemented';
     43  SUnsupportedPaintOperationType = 'Unsupported paint operation type';
    4144
    4245
    4346implementation
     47
     48uses
     49  NativePixelPointer;
    4450
    4551function BitBltCanvas(Dest: TCanvas; X, Y, Width, Height: Integer;
     
    4753begin
    4854  Result := BitBlt(Dest.Handle, X, Y, Width, Height, Src.Handle, XSrc, YSrc, Rop);
     55end;
     56
     57function BitBltBitmap(Dest: TBitmap; X, Y, Width, Height: Integer;
     58  Src: TBitmap; XSrc, YSrc: Integer; Rop: DWORD): Boolean;
     59var
     60  SrcPixel: TPixelPointer;
     61  DstPixel: TPixelPointer;
     62  DstWidth, DstHeight: Integer;
     63  SrcWidth, SrcHeight: Integer;
     64  XX, YY: Integer;
     65  DstPixelX, DstPixelY: Integer;
     66  XNative, YNative: Integer;
     67  DstPixelWidth, DstPixelHeight: Integer;
     68begin
     69  if Frac(ScreenInfo.Dpi / 96) = 0 then
     70  begin
     71    // Use faster non-fractional scaling
     72    Result := BitBlt(Dest.Canvas.Handle, X, Y, Width, Height, Src.Canvas.Handle, XSrc, YSrc, Rop);
     73    Exit;
     74  end;
     75
     76  if X < 0 then begin
     77    Width := Width + X;
     78    XSrc := XSrc - X;
     79    X := 0;
     80  end;
     81  if Y < 0 then begin
     82    Height := Height + Y;
     83    YSrc := YSrc - Y;
     84    Y := 0;
     85  end;
     86  if (X + Width) > Dest.Width then begin
     87    Width := Dest.Width - X;
     88  end;
     89  if (Y + Height) > Dest.Height then begin
     90    Height := Dest.Height - Y;
     91  end;
     92
     93  DstWidth := ScaleToNativeDist(X, Width);
     94  DstHeight := ScaleToNativeDist(Y, Height);
     95  SrcWidth := ScaleToNativeDist(XSrc, Width);
     96  SrcHeight := ScaleToNativeDist(YSrc, Height);
     97  XNative := ScaleToNative(X);
     98  YNative := ScaleToNative(Y);
     99
     100  Dest.BeginUpdate;
     101  SrcPixel := TPixelPointer.Create(Src.NativeBitmap);
     102  DstPixel := TPixelPointer.Create(Dest.NativeBitmap);
     103  for YY := 0 to Height - 1 do begin
     104    DstPixelHeight := ScaleToNative(Y + YY + 1) - ScaleToNative(Y + YY);
     105    for DstPixelY := 0 to DstPixelHeight - 1 do begin
     106      for XX := 0 to Width - 1 do begin
     107        SrcPixel.SetXY(ScaleToNative(XSrc + XX), ScaleToNative(YSrc + YY));
     108        DstPixel.SetXY(ScaleToNative(X + XX), ScaleToNative(Y + YY) + DstPixelY);
     109        DstPixelWidth := ScaleToNative(X + XX + 1) - ScaleToNative(X + XX);
     110        for DstPixelX := 0 to DstPixelWidth - 1 do begin
     111{$IFDEF DEBUG}
     112          if SrcPixel.PosValid and DstPixel.PosValid then
     113{$ENDIF}
     114            if Rop = SRCCOPY then begin
     115              DstPixel.PixelB := SrcPixel.PixelB;
     116              DstPixel.PixelG := SrcPixel.PixelG;
     117              DstPixel.PixelR := SrcPixel.PixelR;
     118            end else
     119            if Rop = SRCPAINT then begin
     120              DstPixel.PixelB := SrcPixel.PixelB or DstPixel.PixelB;
     121              DstPixel.PixelG := SrcPixel.PixelG or DstPixel.PixelG;
     122              DstPixel.PixelR := SrcPixel.PixelR or DstPixel.PixelR;
     123            end else
     124            if Rop = SRCAND then begin
     125              DstPixel.PixelB := SrcPixel.PixelB and DstPixel.PixelB;
     126              DstPixel.PixelG := SrcPixel.PixelG and DstPixel.PixelG;
     127              DstPixel.PixelR := SrcPixel.PixelR and DstPixel.PixelR;
     128            end else
     129            if Rop = DSTINVERT then begin
     130              DstPixel.PixelB := not DstPixel.PixelB;
     131              DstPixel.PixelG := not DstPixel.PixelG;
     132              DstPixel.PixelR := not DstPixel.PixelR;
     133            end else begin
     134              raise Exception.Create(SUnsupportedPaintOperationType);
     135            end;
     136          DstPixel.NextPixel;
     137        end;
     138      end;
     139      //DstPixel.NextLine;
     140    end;
     141  end;
     142  Dest.EndUpdate;
     143  Result := True;
    49144end;
    50145
     
    95190function ScaleToNative(Value: Integer): Integer;
    96191begin
    97   Result := Round(Value * ScreenInfo.Dpi / 96);
     192  Result := Ceil(Value * ScreenInfo.Dpi / 96);
    98193end;
    99194
Note: See TracChangeset for help on using the changeset viewer.