Browse Source

retina scaling of image preview

Johann ELSASS 5 years ago
parent
commit
545f00cc7f
2 changed files with 47 additions and 18 deletions
  1. 2 2
      lazpaint/ugraph.pas
  2. 45 16
      lazpaint/uimagepreview.pas

+ 2 - 2
lazpaint/ugraph.pas

@@ -1207,8 +1207,8 @@ var fx: TBGRATextEffect;
 begin
 begin
   f := TFont.Create;
   f := TFont.Create;
   f.Name := 'Arial';
   f.Name := 'Arial';
-  f.Height := DoScaleY(16,OriginalDPI);
-  ofs := DoScaleX(4,OriginalDPI);
+  f.Height := DoScaleY(16*CanvasScale,OriginalDPI);
+  ofs := DoScaleX(4*CanvasScale,OriginalDPI);
   fx := TBGRATextEffect.Create(s,f,true);
   fx := TBGRATextEffect.Create(s,f,true);
   if valign = tlBottom then y := y-fx.TextSize.cy else
   if valign = tlBottom then y := y-fx.TextSize.cy else
   if valign = tlCenter then y := y-fx.TextSize.cy div 2;
   if valign = tlCenter then y := y-fx.TextSize.cy div 2;

+ 45 - 16
lazpaint/uimagepreview.pas

@@ -11,14 +11,22 @@ uses
   BGRABitmap, BGRAAnimatedGif, BGRAIconCursor, BGRABitmapTypes, BGRAThumbnail,
   BGRABitmap, BGRAAnimatedGif, BGRAIconCursor, BGRABitmapTypes, BGRAThumbnail,
   UTiff, fgl;
   UTiff, fgl;
 
 
+const
+  IconSize = 32;
+  SubImageSize = 128;
+
 type
 type
   TBGRABitmapList = specialize TFPGObjectList<TBGRABitmap>;
   TBGRABitmapList = specialize TFPGObjectList<TBGRABitmap>;
 
 
   { TImagePreview }
   { TImagePreview }
 
 
   TImagePreview = class
   TImagePreview = class
+  private
+    function GetScaledIconSize: integer;
   protected
   protected
     FSurface: TBGRAVirtualScreen;
     FSurface: TBGRAVirtualScreen;
+    FScaling: single;
+    FSurfaceScaledHeight: Integer;
     FScrollbar: TVolatileScrollBar;
     FScrollbar: TVolatileScrollBar;
     FScrolling: boolean;
     FScrolling: boolean;
     FStatus: TLabel;
     FStatus: TLabel;
@@ -96,6 +104,7 @@ type
     property EntryCount: integer read GetEntryCount;
     property EntryCount: integer read GetEntryCount;
     function GetPreviewBitmap: TImageEntry;
     function GetPreviewBitmap: TImageEntry;
     property DuplicateEntrySourceIndex: integer read FDuplicateEntrySourceIndex write FDuplicateEntrySourceIndex;
     property DuplicateEntrySourceIndex: integer read FDuplicateEntrySourceIndex write FDuplicateEntrySourceIndex;
+    property ScaledIconSize: integer read GetScaledIconSize;
   end;
   end;
 
 
 implementation
 implementation
@@ -105,6 +114,11 @@ uses FPimage, BGRAReadJpeg, BGRAOpenRaster, BGRAPaintNet, BGRAReadLzp, Dialogs,
 
 
 { TImagePreview }
 { TImagePreview }
 
 
+function TImagePreview.GetScaledIconSize: integer;
+begin
+  result := round(IconSize * FScaling);
+end;
+
 function TImagePreview.GetPreviewDataLoss: boolean;
 function TImagePreview.GetPreviewDataLoss: boolean;
 begin
 begin
   FinishUpdatePreview;
   FinishUpdatePreview;
@@ -125,6 +139,8 @@ end;
 
 
 procedure TImagePreview.SurfaceRedraw(Sender: TObject; Bitmap: TBGRABitmap);
 procedure TImagePreview.SurfaceRedraw(Sender: TObject; Bitmap: TBGRABitmap);
 begin
 begin
+  FScaling := FSurface.GetCanvasScaleFactor;
+  FSurfaceScaledHeight := Bitmap.Height;
   if (Bitmap.Width = 0) or (Bitmap.Height = 0) then
   if (Bitmap.Width = 0) or (Bitmap.Height = 0) then
   begin
   begin
     ClearMenu;
     ClearMenu;
@@ -143,6 +159,8 @@ var
   i: Integer;
   i: Integer;
   scrollPos: integer;
   scrollPos: integer;
 begin
 begin
+  X := round(X*FScaling);
+  Y := round(Y*FScaling);
   if (Button = mbLeft) and Assigned(FScrollbar) and FScrollbar.MouseDown(X,Y) then
   if (Button = mbLeft) and Assigned(FScrollbar) and FScrollbar.MouseDown(X,Y) then
   begin
   begin
     FScrolling:= true;
     FScrolling:= true;
@@ -175,6 +193,8 @@ procedure TImagePreview.SurfaceMouseMove(Sender: TObject; Shift: TShiftState;
 var
 var
   i, scrollPos: Integer;
   i, scrollPos: Integer;
 begin
 begin
+  X := round(X*FScaling);
+  Y := round(Y*FScaling);
   if FScrolling and Assigned(FScrollbar) and FScrollbar.MouseMove(X,Y) then
   if FScrolling and Assigned(FScrollbar) and FScrollbar.MouseMove(X,Y) then
      FSurface.DiscardBitmap else
      FSurface.DiscardBitmap else
   begin
   begin
@@ -195,6 +215,8 @@ end;
 procedure TImagePreview.SurfaceMouseUp(Sender: TObject; Button: TMouseButton;
 procedure TImagePreview.SurfaceMouseUp(Sender: TObject; Button: TMouseButton;
   Shift: TShiftState; X, Y: Integer);
   Shift: TShiftState; X, Y: Integer);
 begin
 begin
+  X := round(X*FScaling);
+  Y := round(Y*FScaling);
   if (Button = mbLeft) and FScrolling and Assigned(FScrollbar) and FScrollbar.MouseUp(X,Y) then
   if (Button = mbLeft) and FScrolling and Assigned(FScrollbar) and FScrollbar.MouseUp(X,Y) then
   begin
   begin
      FSurface.DiscardBitmap;
      FSurface.DiscardBitmap;
@@ -293,6 +315,9 @@ begin
   else
   else
     exit;
     exit;
 
 
+  w := round(w*FScaling);
+  h := round(h*FScaling);
+
   if w > bitmap.Width then
   if w > bitmap.Width then
   begin
   begin
     h := round(h/w*bitmap.Width);
     h := round(h/w*bitmap.Width);
@@ -311,7 +336,7 @@ begin
   bitmap.FillRect(rect(x+w,y+ofs,x+ofs+w,y+ofs+h), BGRA(0,0,0,128),dmDrawWithTransparency);
   bitmap.FillRect(rect(x+w,y+ofs,x+ofs+w,y+ofs+h), BGRA(0,0,0,128),dmDrawWithTransparency);
   bitmap.FillRect(rect(x+ofs,y+h,x+w,y+ofs+h), BGRA(0,0,0,128),dmDrawWithTransparency);
   bitmap.FillRect(rect(x+ofs,y+h,x+w,y+ofs+h), BGRA(0,0,0,128),dmDrawWithTransparency);
 
 
-  DrawThumbnailCheckers(Bitmap, rect(x,y,x+w,y+h));
+  DrawThumbnailCheckers(Bitmap, rect(x,y,x+w,y+h), false, FScaling);
   bitmap.StretchPutImage(rect(x,y,x+w,y+h), frame, dmDrawWithTransparency)
   bitmap.StretchPutImage(rect(x,y,x+w,y+h), frame, dmDrawWithTransparency)
 end;
 end;
 
 
@@ -406,11 +431,11 @@ begin
     if i = FSelectedMenuIndex then
     if i = FSelectedMenuIndex then
     begin
     begin
       bitmap.FillRect(scrolledArea, ColorToRGB(clHighlight));
       bitmap.FillRect(scrolledArea, ColorToRGB(clHighlight));
-      if not IsNew and not IsLoopCount and not IsDuplicate and (Area.Right - IconArea.Right > 32) and CanDeleteEntry(FrameIndex) then
+      if not IsNew and not IsLoopCount and not IsDuplicate and (Area.Right - IconArea.Right > ScaledIconSize) and CanDeleteEntry(FrameIndex) then
       begin
       begin
         sh := (Area.Right - IconArea.Right - 8) div 4;
         sh := (Area.Right - IconArea.Right - 8) div 4;
-        if sh < 16 then sh := 16;
-        if sh > 32 then sh := 32;
+        if sh < ScaledIconSize div 2 then sh := ScaledIconSize div 2;
+        if sh > ScaledIconSize then sh := ScaledIconSize;
         if sh > Area.Bottom-Area.Top-4 then sh := Area.Bottom-Area.Top-4;
         if sh > Area.Bottom-Area.Top-4 then sh := Area.Bottom-Area.Top-4;
         sw := sh;
         sw := sh;
         DeleteArea := RectWithSize(Area.Right-8-sw,(Area.Top+Area.Bottom-sh) div 2, sw,sh);
         DeleteArea := RectWithSize(Area.Right-8-sw,(Area.Top+Area.Bottom-sh) div 2, sw,sh);
@@ -494,6 +519,8 @@ var x,y,i,frameIndex,h,w,sw,sh: integer;
   currentCol: integer;
   currentCol: integer;
 
 
   procedure ComputeColumn;
   procedure ComputeColumn;
+  var
+    scaledSubImageSize: integer;
   begin
   begin
     colLeft := (AWidth*currentCol) div AColCount;
     colLeft := (AWidth*currentCol) div AColCount;
     colRight := (AWidth*(currentCol+1)) div AColCount;
     colRight := (AWidth*(currentCol+1)) div AColCount;
@@ -501,8 +528,9 @@ var x,y,i,frameIndex,h,w,sw,sh: integer;
     y := 2;
     y := 2;
     maxWidth := colRight-colLeft-8;
     maxWidth := colRight-colLeft-8;
 
 
-    if maxWidth > 128 then maxWidth := 128;
-    maxHeight := 128;
+    scaledSubImageSize := round(SubImageSize*FScaling);
+    if maxWidth > scaledSubImageSize then maxWidth := scaledSubImageSize;
+    maxHeight := scaledSubImageSize;
   end;
   end;
 
 
 begin
 begin
@@ -522,29 +550,29 @@ begin
     begin
     begin
       frameIndex := -1;
       frameIndex := -1;
       FImageMenu[i].IsLoopCount := true;
       FImageMenu[i].IsLoopCount := true;
-      w := 32;
-      h := 32;
+      w := ScaledIconSize;
+      h := w;
     end else
     end else
     if (NewItem = 1) and (i = LoopCountItem) then
     if (NewItem = 1) and (i = LoopCountItem) then
     begin
     begin
       frameIndex := GetEntryCount;
       frameIndex := GetEntryCount;
       FImageMenu[i].IsNew := true;
       FImageMenu[i].IsNew := true;
-      w := 32;
-      h := 32;
+      w := ScaledIconSize;
+      h := w;
     end
     end
     else
     else
     if (DuplicateItem = 1) and (i = LoopCountItem + NewItem) then
     if (DuplicateItem = 1) and (i = LoopCountItem + NewItem) then
     begin
     begin
       frameIndex := GetEntryCount;
       frameIndex := GetEntryCount;
       FImageMenu[i].IsDuplicate := true;
       FImageMenu[i].IsDuplicate := true;
-      w := 32;
-      h := 32;
+      w := ScaledIconSize;
+      h := w;
     end
     end
     else
     else
     begin
     begin
       frameIndex := i-NewItem-LoopCountItem-DuplicateItem;
       frameIndex := i-NewItem-LoopCountItem-DuplicateItem;
-      w := GetEntryWidth(frameIndex);
-      h := GetEntryHeight(frameIndex);
+      w := round(GetEntryWidth(frameIndex)*FScaling);
+      h := round(GetEntryHeight(frameIndex)*FScaling);
     end;
     end;
     if w > maxWidth then
     if w > maxWidth then
     begin
     begin
@@ -1072,8 +1100,8 @@ begin
 
 
   if (FSelectedMenuIndex >= 0) and (FSelectedMenuIndex <= high(FImageMenu)) then
   if (FSelectedMenuIndex >= 0) and (FSelectedMenuIndex <= high(FImageMenu)) then
   begin
   begin
-    if scrollPos < FImageMenu[FSelectedMenuIndex].Area.Bottom-FSurface.Height then
-      scrollPos := FImageMenu[FSelectedMenuIndex].Area.Bottom-FSurface.Height;
+    if scrollPos < FImageMenu[FSelectedMenuIndex].Area.Bottom-FSurfaceScaledHeight then
+      scrollPos := FImageMenu[FSelectedMenuIndex].Area.Bottom-FSurfaceScaledHeight;
     if scrollPos > FImageMenu[FSelectedMenuIndex].Area.Top then
     if scrollPos > FImageMenu[FSelectedMenuIndex].Area.Top then
       scrollPos := FImageMenu[FSelectedMenuIndex].Area.Top;
       scrollPos := FImageMenu[FSelectedMenuIndex].Area.Top;
     if Assigned(FScrollbar) then FScrollbar.Position := scrollPos;
     if Assigned(FScrollbar) then FScrollbar.Position := scrollPos;
@@ -1084,6 +1112,7 @@ end;
 constructor TImagePreview.Create(ASurface: TBGRAVirtualScreen; AStatus: TLabel; AAnimate: boolean);
 constructor TImagePreview.Create(ASurface: TBGRAVirtualScreen; AStatus: TLabel; AAnimate: boolean);
 begin
 begin
   FSurface := ASurface;
   FSurface := ASurface;
+  FSurface.BitmapAutoScale:= false;
   FStatus := AStatus;
   FStatus := AStatus;
   FAnimate:= AAnimate;
   FAnimate:= AAnimate;
   FSelectedMenuIndex := -1;
   FSelectedMenuIndex := -1;