salphagraph.pas

来自「Alpha Controls 5.40,delphi上的alpha开发源码控件包」· PAS 代码 · 共 1,529 行 · 第 1/5 页

PAS
1,529
字号
  SrcBmp : TBitmap;
  wl, wt, wr, wb : integer;
  procedure CopyTransCorner(SrcBmp: Graphics.TBitMap; X, Y : integer; SrcRect: TRect);
  var
    Dst, Src : PRGBArray;
    sX, sY, SrcX, DstX, DstY : Integer;
    MaskColor : TsColor;
    NewColor : TsRGB;
    h, w : integer;
    col : TsColor;
  begin
    MaskColor.C := ColorToRGB(clFuchsia);

    if SrcRect.Top < 0 then SrcRect.Top := 0;
    if SrcRect.Bottom > SrcBmp.Height - 1 then SrcRect.Bottom := SrcBmp.Height - 1;
    if SrcRect.Left < 0 then SrcRect.Left := 0;
    if SrcRect.Right > SrcBmp.Width - 1 then SrcRect.Right := SrcBmp.Width - 1;

    h := HeightOf(SrcRect);
    w := WidthOf(SrcRect);
    if ci.Ready then begin
      if CI.Bmp.PixelFormat = pf24bit then begin
        if Fast24Src.Attach(ci.Bmp) then for sY := 0 to h do begin //!!!
          DstY := sY + Y;
          if (DstY <= SkinData.FCacheBmp.Height - 1) and (DstY >= 0) then begin
            Dst := SkinData.FCacheBmp.ScanLine[DstY];
            Src := SrcBmp.ScanLine[sY + SrcRect.Top];
            for sX := 0 to w do begin
              DstX := sX + X;
              if (DstX <= SkinData.FCacheBmp.Width - 1) and (DstX >= 0) then begin
                SrcX := sX + SrcRect.Left;
                if (Src[SrcX].B = MaskColor.B) and (Src[SrcX].G = MaskColor.G) and (Src[SrcX].R = MaskColor.R) {if transparent pixel}
                  then begin
                    if ParentCenterColor <> clFuchsia then Dst[DstX] := ParentRGB else if CI.Ready then begin
                      if (ci.Y + DstY >= ci.Bmp.Height) or (ci.X + DstX >= ci.Bmp.Width) or (ci.Y + DstY < 0) or (ci.X + DstX < 0) then continue;
                      try
                        col := Fast24Src.Pixels[ci.X + DstX, ci.Y + DstY];// GetPixel(ci.Bmp.Canvas.Handle, ci.X + DstX, ci.Y + DstY);
                      finally
                        NewColor.R := col.R;
                        NewColor.G := col.G;
                        NewColor.B := col.B;
                        Dst[DstX] := NewColor
                      end
                    end
                end;
              end;
            end
          end;
        end
      end
      else begin
        if CI.Bmp.PixelFormat = pf32bit then begin
          if Fast32Src.Attach(ci.Bmp) then for sY := 0 to h do begin //!!!
            DstY := sY + Y;
            if (DstY <= SkinData.FCacheBmp.Height - 1) and (DstY >= 0) then begin
              Dst := SkinData.FCacheBmp.ScanLine[DstY];
              Src := SrcBmp.ScanLine[sY + SrcRect.Top];
              for sX := 0 to w do begin
                DstX := sX + X;
                if (DstX <= SkinData.FCacheBmp.Width - 1) and (DstX >= 0) then begin
                  SrcX := sX + SrcRect.Left;
                  if (Src[SrcX].B = MaskColor.B) and (Src[SrcX].G = MaskColor.G) and (Src[SrcX].R = MaskColor.R) {if transparent pixel}
                    then begin
                      if ParentCenterColor <> clFuchsia then Dst[DstX] := ParentRGB else if CI.Ready then begin
                        if (ci.Y + DstY >= ci.Bmp.Height) or (ci.X + DstX >= ci.Bmp.Width) or (ci.Y + DstY < 0) or (ci.X + DstX < 0) then continue;
                        try
                          col := Fast32Src.Pixels[ci.X + DstX, ci.Y + DstY];
                        finally
                          NewColor.R := col.R;
                          NewColor.G := col.G;
                          NewColor.B := col.B;
                          Dst[DstX] := NewColor
                        end
                      end
                  end;
                end;
              end
            end;
          end
        end
      end;
    end
    else if ParentColor.C <> clFuchsia then for sY := 0 to h do begin //!!!
      DstY := sY + Y;
      if (DstY <= SkinData.FCacheBmp.Height - 1) and (DstY >= 0) then begin
        Dst := SkinData.FCacheBmp.ScanLine[DstY];
        Src := SrcBmp.ScanLine[sY + SrcRect.Top];
        for sX := 0 to w do begin
          DstX := sX + X;
          if (DstX <= SkinData.FCacheBmp.Width - 1) and (DstX >= 0) then begin
            SrcX := sX + SrcRect.Left;
            if (Src[SrcX].B = MaskColor.B) and (Src[SrcX].G = MaskColor.G) and (Src[SrcX].R = MaskColor.R) then begin
              Dst[DstX] := ParentRGB
            end;
          end;
        end
      end;
    end;
  end;
  procedure CopyMasterCorner(R1, R2 : TRect; Bmp : TBitmap{v4.74});
  var
    S1, S2 : PRGBArray;
    X, Y, h, w: Integer;
    c : TsRGB;
    col : TsColor;
  begin
    h := Min(HeightOf(R1), HeightOf(R2));
    h := Min(h, SkinData.FCacheBmp.Height - R1.Top);
    h := Min(h, Bmp.Height - R2.Top) - 1; //!!!
    if h < 0 then Exit;
    w := Min(WidthOf(R1), WidthOf(R2));
    w := Min(w, SkinData.FCacheBmp.Width - R1.Left);
    w := Min(w, Bmp.Width - R2.Left) - 1; //!!!
    if w < 0 then Exit;
    if R1.Left < R2.Left then begin
      if (R1.Left < 0) then begin
        inc(R2.Left, - R1.Left);
        dec(h, - R1.Left);
        R1.Left := 0;
      end;
    end
    else begin
      if (R2.Left < 0) then begin
        inc(R1.Left, - R2.Left);
        dec(h, - R2.Left);
        R2.Left := 0;
      end;
    end;
    if R1.Top < R2.Top then begin
      if (R1.Top < 0) then begin
        inc(R2.Top, - R1.Top);
        dec(h, - R1.Top);
        R1.Top := 0;
      end;
    end
    else begin
      if (R2.Top < 0) then begin
        inc(R1.Top, - R2.Top);
        dec(h, - R2.Top);
        R2.Top := 0;
      end;
    end;
    c.R := 255; c.G := 0; c.B := 255; // clFuchsia
    col.C := ParentCenterColor;
    if not CI.Ready then begin
      if ParentCenterColor <> clFuchsia then for Y := 0 to h do begin
        S1 := SkinData.FCacheBmp.ScanLine[R1.Top + Y];
        S2 := Bmp.ScanLine[R2.Top + Y];
        for X := 0 to w do begin
          if (S2[R2.Left + X].R = c.R) and (S2[R2.Left + X].G = c.G) and (S2[R2.Left + X].B = c.B) then begin
            S1[R1.Left + X].R := col.R;
            S1[R1.Left + X].G := col.G;
            S1[R1.Left + X].B := col.B;
          end;
        end;
      end;
    end
    else begin
      if Fast24Src.Attach(ci.Bmp) then for Y := 0 to h do begin
        S1 := SkinData.FCacheBmp.ScanLine[R1.Top + Y];
        S2 := Bmp.ScanLine[R2.Top + Y];
        for X := 0 to w do begin
          if (S2[R2.Left + X].R = c.R) and (S2[R2.Left + X].G = c.G) and (S2[R2.Left + X].B = c.B) then begin
            if ParentCenterColor <> clFuchsia then begin
              S1[R1.Left + X].R := col.R;
              S1[R1.Left + X].G := col.G;
              S1[R1.Left + X].B := col.B;
            end
            else begin
              if (CI.Bmp.Height <= R1.Top + ci.Y + Y) then Continue;
              if (CI.Bmp.Width <= R1.Left + ci.X + X) then Break;
              if R1.Top + ci.Y + Y < 0 then Break;
              if R1.Left + ci.X + X < 0 then Continue;
              col := Fast24Src.Pixels[R1.Left + ci.X + X, R1.Top + ci.Y + Y];
              // GetPixel(ci.Bmp.Canvas.Handle, R1.Left + ci.X + X, R1.Top + ci.Y + Y);
              S1[R1.Left + X].R := col.R;
              S1[R1.Left + X].G := col.G;
              S1[R1.Left + X].B := col.B;
            end;
          end
        end;
      end;
    end;
  end;
begin
  if not Assigned(Skindata.SkinManager) then Exit;
  if (SkinData.BorderIndex < 0) or not Skindata.SkinManager.IsValidImgIndex(SkinData.BorderIndex) or // v4.74 (SkinData.SkinManager.ma[SkinData.BorderIndex].Bmp <> nil) or
       not Assigned(SkinData.FCacheBmp) or
       (SkinData.FOwnerControl = nil) or not (SkinData.FOwnerControl is TControl) or
         (SkinData.FOwnerControl.Width < 2) or (SkinData.FOwnerControl.Height < 2) then Exit;

  CI := GetParentCache(SkinData);
  if (SkinData.FOwnerControl <> nil) and (SkinData.FOwnerControl.Parent <> nil) then begin
    if not CI.Ready then begin
      ParentCenterColor := ColorToRGB(TsHackedControl(SkinData.FOwnerControl.Parent).Color);//CI.Bmp.Canvas.Pixels[CI.Bmp.Width div 2, CI.Bmp.Height div 2];
    end
    else if not SkinData.ParentTextured and (ParentCenterColor = clFuchsia{ParentCenterColor may be already defined}) then begin
      InitParentColor(SkinData.FOwnerControl.Parent);
    end else ParentCenterColor := clFuchsia;
  end else ParentCenterColor := clFuchsia;

  MaskData := SkinData.SkinManager.ma[SkinData.BorderIndex];
  Width := SkinData.FOwnerControl.Width;
  Height := SkinData.FOwnerControl.Height;
  wl := MaskData.WL; wt := MaskData.WT; wr := MaskData.WR; wb := MaskData.WB;

  if (MaskData.ImageCount = 0) and (MaskData.Bmp <> nil) then begin // if external
    MaskData.MaskType := 1;
    MaskData.ImageCount := 3;
    MaskData.R := Rect(0, 0, MaskData.Bmp.Width, MaskData.Bmp.Height);
  end;

  if ParentCenterColor <> clFuchsia then begin
    ParentColor.C := ColorToRGB(ParentCenterColor);
    ParentRGB.R := ParentColor.R;
    ParentRGB.G := ParentColor.G;
    ParentRGB.B := ParentColor.B;
  end
  else begin
    inc(CI.X, SkinData.FOwnerControl.Left);
    inc(CI.Y, SkinData.FOwnerControl.Top);
  end;

  if State >= MaskData.ImageCount then State := MaskData.ImageCount - 1;
  dw := State * WidthOf(MaskData.R) div (MaskData.ImageCount);        // Width of mask
  dh := HeightOf(MaskData.R) div (1 + MaskData.MaskType);             // Height of mask

  w := WidthOf(MaskData.R) div{ (3 * v5.10}MaskData.ImageCount - wl - wr;             // Width of piece of mask

  if MaskData.Bmp <> nil then SrcBmp := MaskData.Bmp else SrcBmp := SkinData.SkinManager.MasterBitmap;
  if MaskData.MaskType = 0 then begin // Copy without mask
    if (scLeftTop in Corners) then // left - top
      CopyTransCorner(SrcBmp, 0, 0,
                  Rect(MaskData.R.Left + dw,
                       MaskData.R.Top,
                       MaskData.R.Left + dw + wl - 1,
                       MaskData.R.Top + wt - 1));
    if (scLeftBottom in Corners) then // left - bottom
      CopyTransCorner(SrcBmp, 0, Height - wb,
                  Rect(MaskData.R.Left,
                       MaskData.R.Bottom - wb,
                       MaskData.R.Left + wl - 1,
                       MaskData.R.Bottom - 1));
    if (scRightBottom in Corners) then // right - bottom
      CopyTransCorner(SrcBmp, Width - wr, Height - wb,
                  Rect(MaskData.R.Left + dw + wl + w, //3 * w - wr, v5.10
                       MaskData.R.Bottom - wb,
                       MaskData.R.Left + dw + wl + w + wr{+ 3 * w v5.10} - 1,
                       MaskData.R.Bottom - 1));
    if (scRightTop in Corners) then // right - top
      CopyTransCorner(SrcBmp, Width - wr, 0,
                  Rect(MaskData.R.Left + dw + wl + w, // v5.10
                       MaskData.R.Top,
                       MaskData.R.Left + dw + wl + w + wr{+ 3 * w v5.10} - 1, // v5.10
                       MaskData.R.Top + wb - 1));
  end
  else begin
    if (scLeftTop in Corners) then
      CopyMasterCorner(Rect(0, 0, wl + 1, wt + 1), Rect(MaskData.R.Left + dw, MaskData.R.Top, MaskData.R.Left + dw + wl, MaskData.R.Top + wt), SrcBmp);
    if (scLeftBottom in Corners) then
    // left - bottom
      CopyMasterCorner(Rect(0, Height - wb, wl, Height), Rect(MaskData.R.Left + dw, MaskData.R.Top + dh - wb, MaskData.R.Left + dw + wl, MaskData.R.Top + dh), SrcBmp);
    if (scRightBottom in Corners) then
    // right - bottom
      CopyMasterCorner(Rect(Width - wr, Height - wb, Width, Height), Rect(MaskData.R.Left + dw + wl + w, MaskData.R.Top + dh - wb, MaskData.R.Left + dw + wl + w + wr, MaskData.R.Top + dh), SrcBmp);
    if (scRightTop in Corners) then
    // right - top
      CopyMasterCorner(Rect(Width - wr, 0, Width, wt), Rect(MaskData.R.Left + dw + wl + w, MaskData.R.Top, MaskData.R.Left + dw + wl + w + wr, MaskData.R.Top + wt), SrcBmp);
  end;
  ParentCenterColor := clFuchsia;
end;

{$ENDIF}

{ TacFast24 }

function TacFast24.Attach(Bmp: TBitmap) : boolean;
begin
  if (Bmp.Height > 1) and (Bmp.Width > 1) then begin
    FBitmap := Bmp;
    FWidth := FBitmap.Width;
    FHeight := FBitmap.Height;
    Assert(FBitmap.PixelFormat = pf24bit, 'Bitmap format is not supported');
    FStart := Integer(FBitmap.Scanline[0]);
    FDelta := Integer(FBitmap.Scanline[1]) - FStart;
    Result := True;
  end
  else begin
    FWidth := 0;
    Result := False;
  end;
end;

procedure TacFast24.SetPixel(X, Y: Integer; const Value: TsColor);
asm
  push eax
  push ebx
  push ecx
  push edx
  imul ecx,[eax].FDelta
  add ecx,[eax].FStart
  lea edx,[edx+edx*2]
  mov eax,[ebp+8]  //Value
  bswap eax
  shr eax, 8
  mov [ecx+edx],ax

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?