⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 awfview.pas

📁 测试用例
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    sub   esi,BytesPerRow

    xor   dl,dl
    shl   ax,1
    rcr   dl,cl
    or    [esi],dl
    sub   esi,BytesPerRow

    dec   ebx             {decrement counter}
    jnz   @1              {any data left? jump if so}

    pop   edi
    pop   esi
    pop   ebx
  end;

{$ENDIF}

  function TViewer.vRotatePage(const PageNum, Direction : Cardinal) : Integer;
    {-Rotate a page}
  var
    NewWidth        : Cardinal;
    NewHeight       : Cardinal;
    NewBitmap       : HBitmap;
    BytesPerLine    : Cardinal;
    NewBytesPerLine : Cardinal;
    BmpHandle       : THandle;
    BmpPtr          : Pointer;
    NewHandle       : THandle;
    NewPtr          : Pointer;
    SrcBuf          : Pointer;
    DestBuf         : Pointer;

    function AllocTemporary(var B : TMemoryBitmapDesc) : Boolean;
    var
      Sz      : LongInt;
      BmpInfo : TBitmap;

    begin
      AllocTemporary := False;

      with B do begin
        {get information about this bitmap}
        GetObject(B.Bitmap, SizeOf(TBitmap), @BmpInfo);
        BytesPerLine := BmpInfo.bmWidthBytes;
        Sz           := LongInt(BytesPerLine) * LongInt(Height);    

        {allocate a buffer to hold the bitmap bits}
        BmpHandle := GlobalAlloc(gmem_Moveable or gmem_ZeroInit, Sz);
        if (BmpHandle = 0) then
          Exit;
        BmpPtr := GlobalLock(BmpHandle);
        if (BmpPtr = nil) then begin
          GlobalFree(BmpHandle);
          Exit;
        end;

        if (Direction = 2) then begin
          {allocate two temporary buffers for reversing bit patterns}
          SrcBuf := AllocMem(BytesPerLine);
          DestBuf := AllocMem(BytesPerLine);
        end else begin
          NewHeight := BytesPerLine * 8;
          NewWidth  := Height;

          NewBitmap := CreateBitmap(NewWidth, NewHeight, 1, 1, nil);
          GetObject(NewBitmap, SizeOf(TBitmap), @BmpInfo);
          NewBytesPerLine := BmpInfo.bmWidthBytes;

          {allocate temporary buffer to hold new bitmap}
          Sz := LongInt(NewBytesPerLine) * LongInt(NewHeight);    
          NewHandle := GlobalAlloc(gmem_Moveable or gmem_ZeroInit, Sz);
          if (NewHandle = 0) then begin
            GlobalUnlock(BmpHandle);
            GlobalFree(BmpHandle);
            Exit;
          end;
          NewPtr := GlobalLock(NewHandle);
          if (NewPtr = nil) then begin
            GlobalFree(NewHandle);
            GlobalUnlock(BmpHandle);
            GlobalFree(BmpHandle);
            Exit;
          end;
        end;

        GetBitmapBits(Bitmap, Sz, BmpPtr);
      end;

      AllocTemporary := True;
    end;

    procedure FreeTemporary;
    begin
      GlobalUnlock(BmpHandle);
      GlobalFree(BmpHandle);
      if (Direction = 2) then begin
        FreeMem(SrcBuf, BytesPerLine);
        FreeMem(DestBuf, BytesPerLine);
      end else begin
        GlobalUnlock(NewHandle);
        GlobalFree(NewHandle);
      end;
    end;

    {$IFNDEF Win32}
    procedure HugeFill(Dest : Pointer; Len : Integer; Value : Byte); assembler;
    asm
      mov   dx,Len
      les   di,Dest

  @1: or    dx,dx
      jz    @4
      xor   cx,cx
      sub   cx,di
      or    cx,cx
      jnz   @2
      mov   cx,dx
      jmp   @3

  @2: cmp   cx,dx
      jbe   @3
      mov   cx,dx

  @3: sub   dx,cx
      mov   al,Value
      mov   ah,al
      shr   cx,1
      rep   stosw
      adc   cx,cx
      rep   stosb

      or    dx,dx
      jz    @4
      mov   bx,es
      add   bx,8
      mov   es,bx
      xor   di,di
      mov   cx,dx
      shr   cx,1
      rep   stosw
      adc   cx,cx
      rep   stosb
  @4:
    end;
    {$ELSE}
    procedure HugeFill(Dest : Pointer; Len : Integer; Value : Byte);
    begin
      FillChar(Dest^, Len, Value);
    end;
    {$ENDIF}

    procedure Rotate90(var B : TMemoryBitmapDesc);
    var
      I        : LongInt;                                         
      Col      : Cardinal;
      Bit      : Cardinal;
      ActBytes : Cardinal;
      DestCol  : Pointer;

    begin
      Col      := (NewWidth - 1) div 8;
      Bit      := (NewWidth - 1) mod 8;  
      DestCol  := GetPtr(NewPtr, Col);
      ActBytes := (B.Width div 8) + Cardinal(Ord((B.Width mod 8) <> 0)); 

      {$IFOPT Q+}
      {$DEFINE QOn}
      {$ENDIF}
      {$Q-}
      for I := 0 to Pred(NewWidth) do begin 
        BitBltRot90(DestCol, GetPtr(BmpPtr, LongInt(BytesPerLine) * I), Bit, NewBytesPerLine, ActBytes);
        if (Bit = 0) then begin
          Bit := 7;
          Dec(Col);
          DestCol := GetPtr(NewPtr, Col);
        end else
          Dec(Bit);
      end;
      for I := (B.Width - (B.Width mod 8)) to Pred(NewHeight) do
        HugeFill(GetPtr(NewPtr, LongInt(NewBytesPerLine) * I), NewBytesPerLine, $FF);
      {$IFDEF QOn}
      {$Q+}
      {$ENDIF}

      B.Width  := NewWidth;
      B.Height := NewHeight;
      DeleteObject(B.Bitmap);
      B.Bitmap := NewBitmap;
      SetBitmapBits(B.Bitmap,
        LongInt(NewBytesPerLine) * LongInt(NewHeight), NewPtr);      
    end;

    procedure Rotate180(var B : TMemoryBitmapDesc);
    var
      I         : LongInt;
      J         : LongInt;
      ActBytes  : Cardinal;
      Ofs       : LongInt;
      IOfs      : LongInt;
      JOfs      : LongInt;
      Remaining : Byte;
      Mask      : Byte;

    begin
      Remaining := (B.Width mod 8);
      ActBytes  := (B.Width div 8) + Cardinal(Ord(Remaining <> 0));
      I         := 0;
      J         := Pred(B.Height);

      if (Remaining <> 0) then
        Mask := ($FF shr Remaining)
      else
        Mask := 0;                                                  

      while (I < J) do begin
        IOfs := LongInt(BytesPerLine) * I;
        JOfs := LongInt(BytesPerLine) * J;

        {$IFNDEF Win32}
        hmemcpy(SrcBuf, GetPtr(BmpPtr, IOfs), ActBytes);
        if (Remaining <> 0) then
          PByteArray(SrcBuf)^[ActBytes-1] := PByteArray(SrcBuf)^[ActBytes-1] or Mask;
        if (ActBytes <> BytesPerLine) then
          FillChar(GetPtr(SrcBuf, ActBytes)^, BytesPerLine - ActBytes, $FF);
        ReverseBits(DestBuf, SrcBuf, BytesPerLine);
        hmemcpy(SrcBuf, GetPtr(BmpPtr, JOfs), ActBytes);
        if (Remaining <> 0) then
          PByteArray(SrcBuf)^[ActBytes-1] := PByteArray(SrcBuf)^[ActBytes-1] or Mask;
        if (ActBytes <> BytesPerLine) then
          FillChar(GetPtr(SrcBuf, ActBytes)^, BytesPerLine - ActBytes, $FF);
        hmemcpy(GetPtr(BmpPtr, JOfs), DestBuf, BytesPerLine);
        ReverseBits(DestBuf, SrcBuf, BytesPerLine);
        hmemcpy(GetPtr(BmpPtr, IOfs), DestBuf, BytesPerLine);
        {$ELSE}
        Move(GetPtr(BmpPtr, IOfs)^, SrcBuf^, ActBytes);
        if (Remaining <> 0) then
          PByteArray(SrcBuf)^[ActBytes-1] := PByteArray(SrcBuf)^[ActBytes-1] or Mask;
        if (ActBytes <> BytesPerLine) then
          FillChar(GetPtr(SrcBuf, ActBytes)^, BytesPerLine - ActBytes, $FF);
        ReverseBits(DestBuf, SrcBuf, BytesPerLine);
        Move(GetPtr(BmpPtr, JOfs)^, SrcBuf^, ActBytes);
        if (Remaining <> 0) then
          PByteArray(SrcBuf)^[ActBytes-1] := PByteArray(SrcBuf)^[ActBytes-1] or Mask;
        if (ActBytes <> BytesPerLine) then
          FillChar(GetPtr(SrcBuf, ActBytes)^, BytesPerLine - ActBytes, $FF);
        Move(DestBuf^, GetPtr(BmpPtr, JOfs)^, BytesPerLine);
        ReverseBits(DestBuf, SrcBuf, BytesPerLine);
        Move(DestBuf^, GetPtr(BmpPtr, IOfs)^, BytesPerLine);
        {$ENDIF}

        Inc(I);
        Dec(J);
      end;

      {if there's a stray line, reverse it}
      if Odd(B.Height) then begin
        Ofs := LongInt(BytesPerLine) * LongInt(B.Height div 2);   

        {$IFNDEF Win32}
        hmemcpy(SrcBuf, GetPtr(BmpPtr, Ofs), BytesPerLine);
        if (Remaining <> 0) then
          PByteArray(SrcBuf)^[ActBytes-1] := PByteArray(SrcBuf)^[ActBytes-1] or Mask;
        if (ActBytes <> BytesPerLine) then
          FillChar(GetPtr(SrcBuf, ActBytes)^, BytesPerLine - ActBytes, $FF);
        ReverseBits(DestBuf, SrcBuf, BytesPerLine);
        hmemcpy(GetPtr(BmpPtr, Ofs), DestBuf, BytesPerLine);
        {$ELSE}
        Move(GetPtr(BmpPtr, Ofs)^, SrcBuf^, BytesPerLine);
        if (Remaining <> 0) then
          PByteArray(SrcBuf)^[ActBytes-1] := PByteArray(SrcBuf)^[ActBytes-1] or Mask;
        if (ActBytes <> BytesPerLine) then
          FillChar(GetPtr(SrcBuf, ActBytes)^, BytesPerLine - ActBytes, $FF);
        ReverseBits(DestBuf, SrcBuf, BytesPerLine);
        Move(DestBuf^, GetPtr(BmpPtr, Ofs)^, BytesPerLine);
        {$ENDIF}
      end;

      SetBitmapBits(B.Bitmap, LongInt(BytesPerLine) * LongInt(B.Height), BmpPtr);
    end;

    procedure Rotate270(var B : TMemoryBitmapDesc);
    var
      I        : LongInt;                                            
      Col      : Cardinal;
      Bit      : Cardinal;
      ActBytes : Cardinal;
      DestCol  : Pointer;

    begin
      Col      := 0;
      Bit      := 0;
      DestCol  := GetPtr(NewPtr, DWORD(NewBytesPerLine) * Pred(NewHeight));
      ActBytes := (B.Width div 8) + Cardinal(Ord((B.Width mod 8) <> 0));   

      {$IFOPT Q+}
      {$DEFINE QOn}
      {$ENDIF}
      {$Q-}
      for I := 0 to Pred(NewWidth) do begin
        BitBltRot270(DestCol, GetPtr(BmpPtr, LongInt(BytesPerLine) * I), Bit, NewBytesPerLine, ActBytes);
        if (Bit = 7) then begin
          Bit := 0;
          Inc(Col);
          DestCol := GetPtr(NewPtr, (DWORD(NewBytesPerLine) * Pred(NewHeight)) + Col);
        end else
          Inc(Bit);
      end;
      if (NewHeight > (B.Width - (B.Width mod 8))) then
        for I := 0 to (NewHeight - (B.Width - (B.Width mod 8))) do
          HugeFill(GetPtr(NewPtr, LongInt(NewBytesPerLine) * I), NewBytesPerLine, $FF);
      {$IFDEF QOn}
      {$Q+}
      {$ENDIF}

      B.Width  := NewWidth;
      B.Height := NewHeight;
      DeleteObject(B.Bitmap);
      B.Bitmap := NewBitmap;
      SetBitmapBits(B.Bitmap, LongInt(NewBytesPerLine) * LongInt(NewHeight), NewPtr);
    end;

  begin
    if not AllocTemporary(vImage^[PageNum]) then begin
      vRotatePage := ecOutOfMemory;
      Exit;
    end;

    vRotatePage := ecOK;

    case Direction of
      1: Rotate90(vImage^[PageNum]);
      2: Rotate180(vImage^[PageNum]);
      3: Rotate270(vImage^[PageNum]);
    end;

    FreeTemporary;
  end;

  procedure TViewer.vUpdateMarkRect(Client : TRect; X, Y : Integer);
    {-Update the mark rectangle}
  var
    NewMark : TRect;
    Total   : TRect;
    Dest    : TRect;

  begin
    if (vImage = nil) then
      Exit;
    NewMark := vMarkRect;

    {change the anchor corner's coordinate}
    case vAnchorCorner of
      1: begin NewMark.Right := X; NewMark.Bottom := Y; end;
      2: begin NewMark.Left  := X; NewMark.Bottom := Y; end;
      3: begin NewMark.Left  := X; NewMark.Top    := Y; end;
      4: begin NewMark.Right := X; NewMark.Top    := Y; end;
    end;

    {fix the rectangle}
    if (NewMark.Right < NewMark.Left) then
      ExchangeInts(NewMark.Right, NewMark.Left);
    if (NewMark.Bottom < NewMark.Top) then
      ExchangeInts(NewMark.Bottom, NewMark.Top);

    {find the new anchor corner}
    if (X = NewMark.Right) and (Y = NewMark.Bottom) then
      vAnchorCorner := 1
    else if (X = NewMark.Right) and (Y = NewMark.Top) then
      vAnchorCorner := 4
    else if (X = NewMark.Left) and (Y = NewMark.Bottom) then
      vAnchorCorner := 2
    else if (X = NewMark.Left) and (Y = NewMark.Top) then
      vAnchorCorner := 3;

    {adjust the new marked rectangle so it doesn't exceed the image maximums}
    if (NewMark.Right >= Integer(vScaledWidth)) then
      NewMark.Right := Pred(vScaledWidth);
    if (NewMark.Bottom >= Integer(vScaledHeight)) then               
      NewMark.Bottom := Pred(vScaledHeight);
    if (NewMark.Left < 0) then
      NewMark.Left := 0;
    if (NewMark.Top < 0) then
      NewMark.Top := 0;

    {find the area that needs updating}
    UnionRect(Total, NewMark, vMarkRect);
    vMarkRect := NewMark;

    vGetMarkClientIntersection(Dest, Total);
    if (Dest.Left <> Dest.Right) and (Dest.Top <> Dest.Bottom) then begin
      InvalidateRect(vWnd, @Dest, False);
      UpdateWindow(vWnd);
    end;
  end;

  procedure TViewer.vCopyToClipboard;
    {-Copy the marked bitmap to the clipboard}
  var
    W      : Word;
    H      : Word;
    B      : HBitmap;
    TempDC : HDC;
    DC1    : HDC;
    DC2    : HDC;

  begin
    if (vImage = nil) or not vMarked then
      Exit;

    {calculate width and height of clipbitmap}
    W := Succ(vMarkRect.Right - vMarkRect.Left);
    H := Succ(vMarkRect.Bottom - vMarkRect.Top);

    {create the destination monochrome bitmap}
    B := CreateBitmap(W, H, 1, 1, nil);

    {create a temporary DC compatible with the diplay}
    TempDC := GetDC(vWnd);

    {create two memory DCs for the copy of the bitmap}
    DC1 := CreateCompatibleDC(TempDC);
    ReleaseDC(vWnd, TempDC);
    DC2 := CreateCompatibleDC(DC1);

    {select the source bitmap into the source context}
    SelectObject(DC1, vImage^[vOnPage].Bitmap);

    {select the destination bitmap into the destination context}
    SelectObject(DC2, B);

    SafeYield;                                                         

    {copy the bitmap}
    if (vVMult = 1) and (vHMult = 1) and (vVDiv = 1) and (vHMult = 1) then
      BitBlt(DC2, 0, 0, W, H, DC1, vMarkRect.Left, vMarkRect.Top, SrcCopy)
    else
      StretchBlt(DC2, 0, 0, W, H, DC1,
                 (DWORD(vMarkRect.Left) * vHDiv) div vHMult,
                 (DWORD(vMarkRect.Top)  * vVDiv) div vVMult,
                 (DWORD(W) * vHDiv) div vHMult,
                 (DWORD(H) * vVDiv) div vVMult,
                 SrcCopy);

    SafeYield;                                                         

    {free resources}
    DeleteDC(DC1);
    DeleteDC(DC2);

    {put the data in the clipboard}
    if not OpenClipboard(vWnd) then exit;
    SetClipboardData(cf_Bitmap, B);
    CloseClipboard;
  end;

  procedure TViewer.vInvalidateAll;
    {-Invalidate the entire viewer window}
  begin
    InvalidateRect(vWnd, nil, True);
  end;

  procedure TViewer.vPaint(PaintDC : HDC; var PaintInfo : TPaintStruct);
    {-Paint a rectangle of image}
  var
    Width       : Integer;
    Height      : Integer;
    CWidth      : Integer;

⌨️ 快捷键说明

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