Ignore:
Timestamp:
Apr 16, 2024, 10:57:39 AM (7 months ago)
Author:
chronos
Message:
  • Fixed: Map drawing in case of fractional scaling.
Location:
trunk/Packages/DpiControls
Files:
4 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
  • trunk/Packages/DpiControls/Dpi.Graphics.pas

    r506 r538  
    692692  SrcPtr: TPixelPointer;
    693693  DstPtr: TPixelPointer;
    694   xx, yy: Integer;
    695   SrcX, SrcY: Integer;
    696   DstX, DstY: Integer;
    697   DstWidth, DstHeight: Integer;
    698 begin
    699   //Dst.Canvas.StretchDraw(Rect(0, 0, ScaleToNative(Dst.Width), ScaleToNative(Dst.Height)), Src);
    700   //Exit;
     694  XX, YY: Integer;
     695  DstPixelX, DstPixelY: Integer;
     696  DstPixelWidth, DstPixelHeight: Integer;
     697begin
    701698  Dst.BeginUpdate;
    702699  SrcPtr := TPixelPointer.Create(Src, 0, 0);
    703700  DstPtr := TPixelPointer.Create(Dst, 0, 0);
    704   {for yy := 0 to Dst.Height - 1 do begin
    705     for xx := 0 to Dst.Width - 1 do begin
    706       SrcPtr.SetXY(Min(ScaleFromNative(xx), Src.Width - 1),
    707         Min(ScaleFromNative(yy), Src.Height - 1));
    708       DstPtr.PixelB := SrcPtr.PixelB;
    709       DstPtr.PixelG := SrcPtr.PixelG;
    710       DstPtr.PixelR := SrcPtr.PixelR;
    711       DstPtr.NextPixel;
    712     end;
    713     DstPtr.NextLine;
    714   end;
    715   }
    716   for SrcY := 0 to Src.Height - 1 do begin
    717     DstHeight := ScaleToNative(SrcY + 1) - ScaleToNative(SrcY);
    718     for DstY := 0 to DstHeight - 1 do begin
    719       for SrcX := 0 to Src.Width - 1 do begin
    720         DstWidth := ScaleToNative(SrcX + 1) - ScaleToNative(SrcX);
    721         for DstX := 0 to DstWidth - 1 do begin
     701  for YY := 0 to Src.Height - 1 do begin
     702    DstPixelHeight := ScaleToNative(YY + 1) - ScaleToNative(YY);
     703    for DstPixelY := 0 to DstPixelHeight - 1 do begin
     704      for XX := 0 to Src.Width - 1 do begin
     705        DstPixelWidth := ScaleToNative(XX + 1) - ScaleToNative(XX);
     706        for DstPixelX := 0 to DstPixelWidth - 1 do begin
    722707          DstPtr.PixelB := SrcPtr.PixelB;
    723708          DstPtr.PixelG := SrcPtr.PixelG;
  • trunk/Packages/DpiControls/Dpi.PixelPointer.pas

    r507 r538  
    9393
    9494resourcestring
    95   SOutOfRange = 'Pixel pointer out of range [X: %d. Y: %d]';
     95  SOutOfRange = 'Pixel pointer out of range [X: %d, Y: %d, Width: %d, Height: %d]';
    9696  SWrongBitmapSize = 'Wrong bitmap size [width: %d, height: %d]';
    9797
     
    160160    X := B - Y * BytesPerLine;
    161161    X := Floor(X / BytesPerPixel);
    162     raise Exception.Create(Format(SOutOfRange, [X, Y]));
     162    raise Exception.Create(Format(SOutOfRange, [X, Y, Width, Height]));
    163163  end;
    164164  {$ENDIF}
  • trunk/Packages/DpiControls/NativePixelPointer.pas

    r506 r538  
    6363    procedure SetX(X: Integer); inline; // Set horizontal pixel position relative to base
    6464    procedure CheckRange; inline; // Check if current pixel position is not out of range
     65    function PosValid: Boolean;
    6566    class function Create(Bitmap: TRasterImage; BaseX: Integer = 0; BaseY: Integer = 0): TPixelPointer; static;
    6667    property PixelARGB: TColor32 read GetPixelARGB write SetPixelARGB;
     
    9394
    9495resourcestring
    95   SOutOfRange = 'Pixel pointer out of range [X: %d. Y: %d]';
     96  SOutOfRange = 'Pixel pointer out of range [X: %d, Y: %d, Width: %d, Height: %d]';
    9697  SWrongBitmapSize = 'Wrong bitmap size [width: %d, height: %d]';
    9798
     
    159160    X := X - Y * BytesPerLine;
    160161    X := Floor(X / BytesPerPixel);
    161     raise Exception.Create(Format(SOutOfRange, [X, Y]));
     162    raise Exception.Create(Format(SOutOfRange, [X, Y, Width, Height]));
    162163  end;
    163164  {$ENDIF}
     165end;
     166
     167function TPixelPointer.PosValid: Boolean;
     168begin
     169  Result := not ((PByte(Pixel) < PByte(Data)) or
     170    (PByte(Pixel) >= PByte(Data) + Height * BytesPerLine));
    164171end;
    165172
Note: See TracChangeset for help on using the changeset viewer.