{==============================================================================

  Base Bitmap               
  Copyright (C) 2000-2001 by Evgeny Kryukov
  All rights reserved

  All contents of this file and all other files included in this archive
  are Copyright (C) 2001 Evgeny Kryukov. Use and/or distribution of
  them requires acceptance of the License Agreement.

  See License.txt for licence information

===============================================================================}

unit KsLowLevel;

{$I KsCommonVer.Inc}

interface

uses Sysutils, Classes, Windows, Graphics;

procedure FillLongword(var X; Count: Integer; Value: Longword);
procedure FillLongwordRect(var X; W,H,X1,Y1,X2,Y2 : Integer; Value: Longword);

procedure FillAlpha(var X; Count: Integer; Alpha: byte);
procedure FillAlphaRect(var X; W,H,X1,Y1,X2,Y2: Integer; Alpha: byte); assembler;

function BlendPixel(F, B: Longword): Longword;

implementation {===============================================================}

{ Low-Level routines }

{ Blend two pixels }

const bias = $00800080;

function BlendPixel(F, B: Longword): Longword; assembler;
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

  // Test Fa = 255 ?
  CMP     EAX,$FF000000   // Fa = 255 ? => Result = EAX
  JNC     @2

  // Test Fa = 0 ?
  TEST    EAX,$FF000000   // Fa = 0 ?   => Result = EDX
  JZ      @1

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

  PUSH    EBX

  // 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
  XOR     ECX,$000000FF   // ECX  <-  1 - ECX
  MOV     EBX,EDX         // EBX  <-  Ba Br Bg Bb
  AND     EDX,$00FF00FF   // EDX  <-  00 Br 00 Bb
  AND     EBX,$FF00FF00   // EBX  <-  Ba 00 Bg 00
  IMUL    EDX,ECX         // EDX  <-  Qr ** Qb **
  SHR     EBX,8           // EBX  <-  00 Ba 00 Bg
  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;

procedure FillLongword(var X; Count: Integer; Value: Longword); assembler;
asm
  PUSH    EDI

  MOV     EDI,EAX  // Point EDI to destination
  MOV     EAX,ECX
  MOV     ECX,EDX
  TEST    ECX,ECX
  JS      @exit

  REP     STOSD    // Fill count dwords
@exit:
  POP     EDI
end;

procedure FillLongwordRect (var X; W,H,X1,Y1,X2,Y2 : Integer; Value: Longword); assembler;
asm
  PUSH    EDI
  PUSH    EAX
  PUSH    EBX
  PUSH    ECX
  PUSH    EDX
  {ÂÛ×ÈÑËßÅÌ ÀÄÐÅÑ ÍÀ×ÀËÀ ÇÀÏÎËÍÅÍÈß Â ÌÀÑÈÂÅ}
  MOV     EDI, EAX
  XOR     EBX, EBX
  XOR     EAX, EAX
  MOV     EBX, W
  MOV     EAX, Y1
  MUL     EBX
  ADD     EAX, X1
  ADD     EDI, EAX
  ADD     EDI, EAX
  ADD     EDI, EAX
  ADD     EDI, EAX
  {ÂÛ×ÈÑËßÅÌ ØÈÐÈÍÓ ÇÀÏÎËÍÅÍÈß}
  MOV     EBX, X2
  SUB     EBX, X1
  INC     EBX
  TEST    EBX,EBX
  JS      @exit
 
  {ÂÛ×ÈÑËßÅÌ ÂÛÑÎÒÓ ÇÀÏÎËÍÅÍÈß}
  MOV     EDX, Y2
  SUB     EDX, Y1
  INC     EDX
  TEST    EDX,EDX
  JS      @exit
  {Çàíîñèì â EAX çíà÷åíèå äëÿ çàïîëíåíèÿ}
  MOV     EAX, VALUE
 
@1:
  PUSH    EDI
  MOV     ECX, EBX
  CLD
  REP     STOSD
  POP     EDI
  POP     ECX
  ADD     EDI, ECX
  ADD     EDI, ECX
  ADD     EDI, ECX
  ADD     EDI, ECX
  PUSH    ECX
  DEC     EDX
  CMP     EDX, 0
  JNE     @1
 
@exit:
  POP     EDX
  POP     ECX
  POP     EBX
  POP     EAX
  POP     EDI
end;

procedure FillAlpha(var X; Count: Integer; Alpha: byte); assembler;
asm
  PUSH    EDI
 
  MOV     EDI,EAX  // Point EDI to destination
  MOV     AL, CL
  MOV     ECX,EDX
  TEST    ECX,ECX
  JS      @exit
 
@1:
  INC     EDI
  INC     EDI
  INC     EDI
  MOV     [EDI], AL
  INC     EDI
  LOOP    @1
 
@exit:
  POP     EDI
end;

procedure FillAlphaRect(var X; W,H,X1,Y1,X2,Y2 : Integer; Alpha: byte); assembler;
asm
  PUSH    EDI
  PUSH    EAX
  PUSH    EBX
  PUSH    ECX
  PUSH    EDX
  {ÂÛ×ÈÑËßÅÌ ÀÄÐÅÑ ÍÀ×ÀËÀ ÇÀÏÎËÍÅÍÈß Â ÌÀÑÈÂÅ}
  MOV     EDI, EAX
  XOR     EBX, EBX
  XOR     EAX, EAX
  MOV     EBX, W
  MOV     EAX, Y1
  MUL     EBX
  ADD     EAX, X1
  ADD     EDI, EAX
  ADD     EDI, EAX
  ADD     EDI, EAX
  ADD     EDI, EAX
 
  {ÂÛ×ÈÑËßÅÌ ØÈÐÈÍÓ ÇÀÏÎËÍÅÍÈß}
  MOV     EBX, X2
  SUB     EBX, X1
  INC     EBX
  TEST    EBX,EBX
  JS      @exit
 
  {ÂÛ×ÈÑËßÅÌ ÂÛÑÎÒÓ ÇÀÏÎËÍÅÍÈß}
  MOV     EDX, Y2
  SUB     EDX, Y1
  INC     EDX
  TEST    EDX,EDX
  JS      @exit
  mov     al, alpha
 
@1:
  PUSH    EDI
  MOV     ECX, EBX
 
@2:
  INC     EDI
  INC     EDI
  INC     EDI
  MOV     [EDI], AL
  INC     EDI
  LOOP    @2
 
  POP     EDI
  POP     ECX
  ADD     EDI, ECX
  ADD     EDI, ECX
  ADD     EDI, ECX
  ADD     EDI, ECX
  PUSH    ECX
  DEC     EDX
  CMP     EDX, 0
  JNE     @1
 
@exit:
  POP     EDX
  POP     ECX
  POP     EBX
  POP     EAX
  POP     EDI
end;

end.




