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

📄 _graphutils.pas

📁 East make Tray Icon in delphi
💻 PAS
📖 第 1 页 / 共 5 页
字号:
        AND     EAX, $00FF00FF  // EAX  <-  00 Xr 00 Xb
        AND     EBX, $FF00FF00  // EBX  <-  Xa 00 Xg 00
        IMUL    EAX, ECX        // EAX  <-  Pr ** Pb **
        SHR     EBX, 8          // EBX  <-  00 Xa 00 Xg
        IMUL    EBX, ECX        // EBX  <-  Pa ** Pg **
        ADD     EAX, Bias
        AND     EAX, $FF00FF00  // EAX  <-  Pr 00 Pb 00
        SHR     EAX, 8          // EAX  <-  00 Pr 00 Pb
        ADD     EBX, Bias
        AND     EBX, $FF00FF00  // EBX  <-  Pa 00 Pg 00
        OR      EAX, EBX        // EAX  <-  Pa Pr Pg Pb

  // W = 1 - W; Q = W * Y
        XOR     ECX, $000000FF  // ECX  <-  1 - ECX
        MOV     EBX, EDX        // EBX  <-  Ya Yr Yg Yb
        AND     EDX, $00FF00FF  // EDX  <-  00 Yr 00 Yb
        AND     EBX, $FF00FF00  // EBX  <-  Ya 00 Yg 00
        IMUL    EDX, ECX        // EDX  <-  Qr ** Qb **
        SHR     EBX, 8          // EBX  <-  00 Ya 00 Yg
        IMUL    EBX, ECX        // EBX  <-  Qa ** Qg **
        ADD     EDX, Bias
        AND     EDX, $FF00FF00  // EDX  <-  Qr 00 Qb 00
        SHR     EDX, 8          // EDX  <-  00 Qr ** Qb
        ADD     EBX, Bias
        AND     EBX, $FF00FF00  // EBX  <-  Qa 00 Qg 00
        OR      EBX, EDX        // EBX  <-  Qa Qr Qg Qb

  // Z = P + Q (assuming no overflow at each byte)
        ADD     EAX, EBX        // EAX  <-  Za Zr Zg Zb

        POP     EBX
        RET

@1:     MOV     EAX, EDX
@2:     RET
end;}
begin
  // combine RGBA channels of colors X and Y with the weight of X given in W
  // Result Z = W * X + (1 - W) * Y (all channels are combined, including alpha)

  if W = 0 then
    Result := Y        //May be if W <= 0 ???
  else
  if W = $FF then Result := X //May be if W >= $FF ??? Or if W > $FF ???
  else
  begin
    Result :=
      (((((X shr 8 {00Xa00Xg}) and $00FF00FF {00X100X2}) * W {P1**P2**}) +
        Bias) and $FF00FF00 {P100P200}) {Pa00Pg00} or
      (((((X {00Xr00Xb} and $00FF00FF {00X100X2}) * W {P1**P2**}) + Bias) and
        $FF00FF00 {P100P200}) shr 8 {00Pr00Pb}) {PaPrPgPb};

    W := W xor $FF; // W := 1 - W;
    //W := $100 - W; // May be so ???

    Result := Result {PaPrPgPb} + (
      (((((Y shr 8 {00Ya00Yg}) and $00FF00FF {00X100X2}) * W {P1**P2**}) +
        Bias) and $FF00FF00 {P100P200}) {Qa00Qg00} or
      (((((Y {00Yr00Yb} and $00FF00FF {00X100X2}) * W {P1**P2**}) + Bias) and
        $FF00FF00 {P100P200}) shr 8 {00Qr00Qb}) {QaQrQgQb}
      ) {ZaZrZgZb};
  end;
end;

procedure _CombineMem(F: TColor32; var B: TColor32; W: TColor32);
{asm
  // EAX <- F
  // [EDX] <- B
  // ECX <- W
        PUSH    EDX
        MOV     EDX, [EDX]
        CALL    _CombineReg
        POP     EDX
        MOV     [EDX], EAX
end;}
begin
  B := _CombineReg(F, B, W);
end;

function _BlendReg(F, B: TColor32): TColor32;
{asm
  // blend foreground color (F) to a background color (B),
  // using alpha channel value of F
  // Result Z = Fa * Frgb + (1 - Fa) * Brgb
  // EAX <- F
  // EDX <- B
        MOV     ECX, EAX        // ECX  <-  Fa Fr Fg Fb
        SHR     ECX, 24         // ECX  <-  00 00 00 Fa
        JMP    _CombineReg
end;}
begin
  Result := _CombineReg(F, B, F shr 24);
end;

procedure _BlendMem(F: TColor32; var B: TColor32);
{asm
  // EAX <- F
  // [EDX] <- B
        PUSH    EDX
        MOV     ECX, EAX        // ECX  <-  Fa Fr Fg Fb
        SHR     ECX, 24         // ECX  <-  00 00 00 Fa
        MOV     EDX, [EDX]
        CALL    _CombineReg
        POP     EDX
        MOV     [EDX], EAX
end;}
begin
  B := _CombineReg(F, B, F shr 24);
end;

function _BlendRegEx(F, B, M: TColor32): TColor32;
{asm
  // blend foreground color (F) to a background color (B),
  // using alpha channel value of F multiplied by master alpha (M)
  // no checking for M = $FF, if this is the case Graphics32 uses BlendReg
  // Result Z = Fa * M * Frgb + (1 - Fa * M) * Brgb
  // EAX <- F
  // EDX <- B
  // ECX <- M
        MOV     EBX, EAX        // EBX  <-  Fa Fr Fg Fb
        SHR     EBX, 24         // EBX  <-  00 00 00 Fa
        IMUL    ECX, EBX        // ECX  <-  00 00  W **
        SHR     ECX, 8          // ECX  <-  00 00 00  W
        JMP    _CombineReg
end;}
begin
  Result := _CombineReg(F, B, ((F shr 24) * M) shr 8);
end;

procedure _BlendMemEx(F: TColor32; var B: TColor32; M: TColor32);
{asm
  // EAX <- F
  // [EDX] <- B
  // ECX <- M
        PUSH    EBX
        MOV     EBX, EAX        // EBX  <-  Fa Fr Fg Fb
        SHR     EBX, 24         // EBX  <-  00 00 00 Fa
        IMUL    ECX, EBX        // ECX  <-  00 00  W **
        SHR     ECX, 8          // ECX  <-  00 00 00  W

        MOV     EBX, EDX
        MOV     EDX, [EDX]
        CALL    _BlendRegEx
        MOV     [EBX], EAX
        POP     EBX
end;}
begin
  B := _CombineReg(F, B, ((F shr 24) * M) shr 8);
end;


procedure _BlendLine(Src, Dst: PColor32; Count: Integer); assembler;
asm
  // EAX <- Src
  // EDX <- Dst
  // ECX <- Count

  // test the counter for zero or negativity
        TEST    ECX, ECX
        JS      @4

        PUSH    EBX
        PUSH    ESI
        PUSH    EDI

        MOV     ESI, EAX        // ESI <- Src
        MOV     EDI, EDX        // EDI <- Dst

  // loop start
@1:     MOV     EAX, [ESI]
        TEST    EAX, $FF000000
        JZ      @3              // complete transparency, proceed to next point

        PUSH    ECX             // store counter

  // Get weight W = Fa * M
        MOV     ECX, EAX        // ECX  <-  Fa Fr Fg Fb
        SHR     ECX, 24         // ECX  <-  00 00 00 Fa

  // Test Fa = 255 ?
        CMP     ECX, $FF
        JZ      @2

  // P = W * F
        MOV     EBX, EAX         // EBX  <-  Fa Fr Fg Fb
        AND     EAX, $00FF00FF   // EAX  <-  00 Fr 00 Fb
        AND     EBX, $FF00FF00   // EBX  <-  Fa 00 Fg 00
        IMUL    EAX, ECX         // EAX  <-  Pr ** Pb **
        SHR     EBX, 8           // EBX  <-  00 Fa 00 Fg
        IMUL    EBX, ECX         // EBX  <-  Pa ** Pg **
        ADD     EAX, Bias
        AND     EAX, $FF00FF00   // EAX  <-  Pr 00 Pb 00
        SHR     EAX, 8           // EAX  <-  00 Pr ** Pb
        ADD     EBX, Bias
        AND     EBX, $FF00FF00   // EBX  <-  Pa 00 Pg 00
        OR      EAX, EBX         // EAX  <-  Pa Pr Pg Pb

  // W = 1 - W; Q = W * B
        MOV     EDX, [EDI]
        XOR     ECX, $000000FF   // ECX  <-  1 - ECX
        MOV     EBX, EDX         // EBX  <-  Ba Br Bg Bb
        AND     EDX, $00FF00FF   // ESI  <-  00 Br 00 Bb
        AND     EBX, $FF00FF00   // EBX  <-  Ba 00 Bg 00
        IMUL    EDX, ECX         // ESI  <-  Qr ** Qb **
        SHR     EBX, 8           // EBX  <-  00 Ba 00 Bg
        IMUL    EBX, ECX         // EBX  <-  Qa ** Qg **
        ADD     EDX, Bias
        AND     EDX, $FF00FF00   // ESI  <-  Qr 00 Qb 00
        SHR     EDX, 8           // ESI  <-  00 Qr ** Qb
        ADD     EBX, Bias
        AND     EBX, $FF00FF00   // EBX  <-  Qa 00 Qg 00
        OR      EBX, EDX         // EBX  <-  Qa Qr Qg Qb

  // Z = P + Q (assuming no overflow at each byte)
        ADD     EAX, EBX        // EAX  <-  Za Zr Zg Zb
@2:     MOV     [EDI], EAX

        POP     ECX             // restore counter

@3:     ADD     ESI, 4
        ADD     EDI, 4

  // loop end
        DEC     ECX
        JNZ     @1

        POP     EDI
        POP     ESI
        POP     EBX

@4:     RET
end;

procedure _BlendLineEx(Src, Dst: PColor32; Count: Integer; M: TColor32);
begin
  while Count > 0 do
  begin
    _BlendMemEx(Src^, Dst^, M);
    Inc(Src);
    Inc(Dst);
    Dec(Count);
  end;
end;

{ MMX versions }

var
  AlphaTable: Pointer;
  bias_ptr: Pointer;
  alpha_ptr: Pointer;

procedure GenAlphaTable;
var
  I: Integer;
  L: Longword;
  P: ^Longword;
begin
  GetMem(AlphaTable, 257 * 8);
  alpha_ptr := Pointer(Integer(AlphaTable) and $FFFFFFF8);
  if Integer(alpha_ptr) < Integer(AlphaTable) then
    alpha_ptr := Pointer(Integer(alpha_ptr) + 8);
  P := alpha_ptr;
  for I := 0 to 255 do
  begin
    L := I + I shl 16;
    P^ := L;
    Inc(P);
    P^ := L;
    Inc(P);
  end;
  bias_ptr := Pointer(Integer(alpha_ptr) + $80 * 8);
end;

procedure FreeAlphaTable;
begin
  FreeMem(AlphaTable);
  AlphaTable := nil;
end;

procedure EMMS;
begin
  if MMX_ACTIVE then
  asm
          db      $0F, $77               // EMMS
  end;
end;

function M_CombineReg(X, Y, W: TColor32): TColor32; assembler;
asm
  // EAX - Color X
  // EDX - Color Y
  // ECX - Weight of X [0..255]
  // Result := W * (X - Y) + Y

        db $0F, $EF, $C0           // PXOR      MM0, MM0
        db $0F, $6E, $C8           // MOVD      MM1, EAX
        SHL       ECX, 3
        db $0F, $6E, $D2           // MOVD      MM2, EDX
        db $0F, $60, $C8           // PUNPCKLBW MM1, MM0
        db $0F, $60, $D0           // PUNPCKLBW MM2, MM0
        ADD       ECX, alpha_ptr
        db $0F, $F9, $CA           // PSUBW     MM1, MM2
        db $0F, $D5, $09           // PMULLW    MM1, [ECX]
        db $0F, $71, $F2,$08       // PSLLW     MM2, 8
        MOV       ECX, bias_ptr
        db $0F, $FD, $11           // PADDW     MM2, [ECX]
        db $0F, $FD, $CA           // PADDW     MM1, MM2
        db $0F, $71, $D1, $08      // PSRLW     MM1, 8
        db $0F, $67, $C8           // PACKUSWB  MM1, MM0
        db $0F, $7E, $C8           // MOVD      EAX, MM1
end;

procedure M_CombineMem(F: TColor32; var B: TColor32; W: TColor32);
{asm
  // EAX - Color X
  // [EDX] - Color Y
  // ECX - Weight of X [0..255]
  // Result := W * (X - Y) + Y
        PUSH    EDX
        MOV     EDX, [EDX]
        CALL    M_CombineReg
        POP     EDX
        MOV     [EDX], EAX
end;}
begin
  B := M_CombineReg(F, B, W);
end;

function M_BlendReg(F, B: TColor32): TColor32; assembler;
asm
  // blend foreground color (F) to a background color (B),
  // using alpha channel value of F
  // EAX <- F
  // EDX <- B
  // Result := Fa * (Frgb - Brgb) + Brgb
        db $0F, $EF, $DB           // PXOR      MM3, MM3
        db $0F, $6E, $C0           // MOVD      MM0, EAX
        db $0F, $6E, $D2           // MOVD      MM2, EDX
        db $0F, $60, $C3           // PUNPCKLBW MM0, MM3
        MOV     ECX, bias_ptr
        db $0F, $60, $D3           // PUNPCKLBW MM2, MM3
        db $0F, $6F, $C8           // MOVQ      MM1, MM0
        db $0F, $69, $C9           // PUNPCKHWD MM1, MM1
        db $0F, $F9, $C2           // PSUBW     MM0, MM2
        db $0F, $6A, $C9           // PUNPCKHDQ MM1, MM1
        db $0F, $71, $F2, $08      // PSLLW     MM2, 8
        db $0F, $D5, $C1           // PMULLW    MM0, MM1
        db $0F, $FD, $11           // PADDW     MM2, [ECX]
        db $0F, $FD, $D0           // PADDW     MM2, MM0
        db $0F, $71, $D2, $08      // PSRLW     MM2, 8
        db $0F, $67, $D3           // PACKUSWB  MM2, MM3
        db $0F, $7E, $D0           // MOVD      EAX, MM2
end;

procedure M_BlendMem(F: TColor32; var B: TColor32);
{asm
  // EAX - Color X
  // [EDX] - Color Y
  // Result := W * (X - Y) + Y
        PUSH    EDX
        MOV     EDX, [EDX]
        CALL    M_BlendReg
        POP     EDX
        MOV     [EDX], EAX
end;}
begin
  B := M_BlendReg(F, B);
end;

function M_BlendRegEx(F, B, M: TColor32): TColor32; assembler;
asm
  // blend foreground color (F) to a background color (B),
  // using alpha channel value of F
  // EAX <- F
  // EDX <- B
  // ECX <- M
  // Result := M * Fa * (Frgb - Brgb) + Brgb
        PUSH      EBX
        MOV       EBX, EAX
        SHR       EBX, 24
        IMUL      ECX, EBX
        SHR       ECX, 8
        JZ        @1

        db $0F, $EF, $C0           // PXOR      MM0, MM0
        db $0F, $6E, $C8           // MOVD      MM1, EAX
        SHL       ECX, 3
        db $0F, $6E, $D2           // MOVD      MM2, EDX
        db $0F, $60, $C8           // PUNPCKLBW MM1, MM0
        db $0F, $60, $D0           // PUNPCKLBW MM2, MM0
        ADD       ECX, alpha_ptr
        db $0F, $F9, $CA           // PSUBW     MM1, MM2
        db $0F, $D5, $09           // PMULLW    MM1, [ECX]
        db $0F, $71, $F2, $08      // PSLLW     MM2, 8
        MOV       ECX, bias_ptr
        db $0F, $FD, $11           // PADDW     MM2, [ECX]
        db $0F, $FD, $CA           // PADDW     MM1, MM2
        db $0F, $71, $D1, $08      // PSRLW     MM1, 8
        db $0F, $67, $C8           // PACKUSWB  MM1, MM0
        db $0F, $7E, $C8           // MOVD      EAX, MM1

@1:     MOV       EAX, EDX
        POP       EBX
end;

procedure M_BlendMemEx(F: TColor32; var B: TColor32; M: TColor32);
{asm
  // blend foreground color (F) to a background color (B),
  // using alpha channel value of F
  // EAX <- F
  // [EDX] <- B
  // ECX <- M
  // Result := M * Fa * (Frgb - Brgb) + Brgb
        PUSH    EDX
        MOV     EDX, [EDX]
        CALL    M_BlendRegEx
        POP     EDX
        MOV     [EDX], EAX
end;}
begin
  B := M_BlendRegEx(F, B, M);
end;

procedure M_BlendLine(Src, Dst: PColor32; Count: Integer); assembler;
asm
  // EAX <- Src
  // EDX <- Dst
  // ECX <- Count

  // test the counter for zero or negativity
        TEST      ECX, ECX
        JS        @4

        PUSH      ESI
        PUSH      EDI

        MOV       ESI, EAX        // ESI <- Src
        MOV       EDI, EDX        // EDI <- Dst

  // loop start
@1:     MOV       EAX, [ESI]
        TEST      EAX, $FF000000

⌨️ 快捷键说明

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