| 1 | unit GR32_Blend;
|
|---|
| 2 |
|
|---|
| 3 | (* ***** BEGIN LICENSE BLOCK *****
|
|---|
| 4 | * Version: MPL 1.1 or LGPL 2.1 with linking exception
|
|---|
| 5 | *
|
|---|
| 6 | * The contents of this file are subject to the Mozilla Public License Version
|
|---|
| 7 | * 1.1 (the "License"); you may not use this file except in compliance with
|
|---|
| 8 | * the License. You may obtain a copy of the License at
|
|---|
| 9 | * http://www.mozilla.org/MPL/
|
|---|
| 10 | *
|
|---|
| 11 | * Software distributed under the License is distributed on an "AS IS" basis,
|
|---|
| 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|---|
| 13 | * for the specific language governing rights and limitations under the
|
|---|
| 14 | * License.
|
|---|
| 15 | *
|
|---|
| 16 | * Alternatively, the contents of this file may be used under the terms of the
|
|---|
| 17 | * Free Pascal modified version of the GNU Lesser General Public License
|
|---|
| 18 | * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
|
|---|
| 19 | * of this license are applicable instead of those above.
|
|---|
| 20 | * Please see the file LICENSE.txt for additional information concerning this
|
|---|
| 21 | * license.
|
|---|
| 22 | *
|
|---|
| 23 | * The Original Code is Graphics32
|
|---|
| 24 | *
|
|---|
| 25 | * The Initial Developer of the Original Code is
|
|---|
| 26 | * Alex A. Denisov
|
|---|
| 27 | *
|
|---|
| 28 | * Portions created by the Initial Developer are Copyright (C) 2000-2009
|
|---|
| 29 | * the Initial Developer. All Rights Reserved.
|
|---|
| 30 | *
|
|---|
| 31 | * Contributor(s):
|
|---|
| 32 | * Mattias Andersson
|
|---|
| 33 | * - 2004/07/07 - MMX Blendmodes
|
|---|
| 34 | * - 2004/12/10 - _MergeReg, M_MergeReg
|
|---|
| 35 | *
|
|---|
| 36 | * Michael Hansen <dyster_tid@hotmail.com>
|
|---|
| 37 | * - 2004/07/07 - Pascal Blendmodes, function setup
|
|---|
| 38 | * - 2005/08/19 - New merge table concept and reference implementations
|
|---|
| 39 | *
|
|---|
| 40 | * Bob Voigt
|
|---|
| 41 | * - 2004/08/25 - ColorDiv
|
|---|
| 42 | *
|
|---|
| 43 | * Christian-W. Budde
|
|---|
| 44 | * - 2019/04/01 - Refactoring
|
|---|
| 45 | *
|
|---|
| 46 | * ***** END LICENSE BLOCK ***** *)
|
|---|
| 47 |
|
|---|
| 48 | interface
|
|---|
| 49 |
|
|---|
| 50 | {$I GR32.inc}
|
|---|
| 51 |
|
|---|
| 52 | uses
|
|---|
| 53 | GR32, GR32_Bindings, SysUtils;
|
|---|
| 54 |
|
|---|
| 55 | var
|
|---|
| 56 | MMX_ACTIVE: Boolean;
|
|---|
| 57 |
|
|---|
| 58 | type
|
|---|
| 59 | { Function Prototypes }
|
|---|
| 60 | TBlendReg = function(F, B: TColor32): TColor32;
|
|---|
| 61 | TBlendMem = procedure(F: TColor32; var B: TColor32);
|
|---|
| 62 | TBlendMems = procedure(F: TColor32; B: PColor32; Count: Integer);
|
|---|
| 63 | TBlendRegEx = function(F, B, M: TColor32): TColor32;
|
|---|
| 64 | TBlendMemEx = procedure(F: TColor32; var B: TColor32; M: TColor32);
|
|---|
| 65 | TBlendRegRGB = function(F, B, W: TColor32): TColor32;
|
|---|
| 66 | TBlendMemRGB = procedure(F: TColor32; var B: TColor32; W: TColor32);
|
|---|
| 67 | {$IFDEF TEST_BLENDMEMRGB128SSE4}
|
|---|
| 68 | TBlendMemRGB128 = procedure(F: TColor32; var B: TColor32; W: UInt64);
|
|---|
| 69 | {$ENDIF}
|
|---|
| 70 | TBlendLine = procedure(Src, Dst: PColor32; Count: Integer);
|
|---|
| 71 | TBlendLineEx = procedure(Src, Dst: PColor32; Count: Integer; M: TColor32);
|
|---|
| 72 | TBlendLine1 = procedure(Src: TColor32; Dst: PColor32; Count: Integer);
|
|---|
| 73 | TCombineReg = function(X, Y, W: TColor32): TColor32;
|
|---|
| 74 | TCombineMem = procedure(X: TColor32; var Y: TColor32; W: TColor32);
|
|---|
| 75 | TCombineLine = procedure(Src, Dst: PColor32; Count: Integer; W: TColor32);
|
|---|
| 76 | TLightenReg = function(C: TColor32; Amount: Integer): TColor32;
|
|---|
| 77 |
|
|---|
| 78 | var
|
|---|
| 79 | {$IFNDEF OMIT_MMX}
|
|---|
| 80 | EMMS: procedure;
|
|---|
| 81 | {$ENDIF}
|
|---|
| 82 |
|
|---|
| 83 | { Function Variables }
|
|---|
| 84 | BlendReg: TBlendReg;
|
|---|
| 85 | BlendMem: TBlendMem;
|
|---|
| 86 | BlendMems: TBlendMems;
|
|---|
| 87 |
|
|---|
| 88 | BlendRegEx: TBlendRegEx;
|
|---|
| 89 | BlendMemEx: TBlendMemEx;
|
|---|
| 90 |
|
|---|
| 91 | BlendRegRGB: TBlendRegRGB;
|
|---|
| 92 | BlendMemRGB: TBlendMemRGB;
|
|---|
| 93 | {$IFDEF TEST_BLENDMEMRGB128SSE4}
|
|---|
| 94 | BlendMemRGB128: TBlendMemRGB128;
|
|---|
| 95 | {$ENDIF}
|
|---|
| 96 |
|
|---|
| 97 | BlendLine: TBlendLine;
|
|---|
| 98 | BlendLineEx: TBlendLineEx;
|
|---|
| 99 | BlendLine1: TBlendLine1;
|
|---|
| 100 |
|
|---|
| 101 | CombineReg: TCombineReg;
|
|---|
| 102 | CombineMem: TCombineMem;
|
|---|
| 103 | CombineLine: TCombineLine;
|
|---|
| 104 |
|
|---|
| 105 | MergeReg: TBlendReg;
|
|---|
| 106 | MergeMem: TBlendMem;
|
|---|
| 107 |
|
|---|
| 108 | MergeRegEx: TBlendRegEx;
|
|---|
| 109 | MergeMemEx: TBlendMemEx;
|
|---|
| 110 |
|
|---|
| 111 | MergeLine: TBlendLine;
|
|---|
| 112 | MergeLineEx: TBlendLineEx;
|
|---|
| 113 | MergeLine1: TBlendLine1;
|
|---|
| 114 |
|
|---|
| 115 | { Color algebra functions }
|
|---|
| 116 | ColorAdd: TBlendReg;
|
|---|
| 117 | ColorSub: TBlendReg;
|
|---|
| 118 | ColorDiv: TBlendReg;
|
|---|
| 119 | ColorModulate: TBlendReg;
|
|---|
| 120 | ColorMax: TBlendReg;
|
|---|
| 121 | ColorMin: TBlendReg;
|
|---|
| 122 | ColorDifference: TBlendReg;
|
|---|
| 123 | ColorAverage: TBlendReg;
|
|---|
| 124 | ColorExclusion: TBlendReg;
|
|---|
| 125 | ColorScale: TBlendReg;
|
|---|
| 126 | ColorScreen: TBlendReg;
|
|---|
| 127 | ColorDodge: TBlendReg;
|
|---|
| 128 | ColorBurn: TBlendReg;
|
|---|
| 129 |
|
|---|
| 130 | { Blended color algebra functions }
|
|---|
| 131 | BlendColorAdd: TBlendReg;
|
|---|
| 132 | BlendColorModulate: TBlendReg;
|
|---|
| 133 |
|
|---|
| 134 | { Special LUT pointers }
|
|---|
| 135 | AlphaTable: Pointer;
|
|---|
| 136 | bias_ptr: Pointer;
|
|---|
| 137 | alpha_ptr: Pointer;
|
|---|
| 138 |
|
|---|
| 139 |
|
|---|
| 140 | { Misc stuff }
|
|---|
| 141 | LightenReg: TLightenReg;
|
|---|
| 142 |
|
|---|
| 143 | function Lighten(C: TColor32; Amount: Integer): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
|
|---|
| 144 |
|
|---|
| 145 | { Access to alpha composite functions corresponding to a combine mode }
|
|---|
| 146 |
|
|---|
| 147 | type
|
|---|
| 148 | PBlendReg = ^TBlendReg;
|
|---|
| 149 | PBlendMem = ^TBlendMem;
|
|---|
| 150 | PBlendRegEx = ^TBlendRegEx;
|
|---|
| 151 | PBlendMemEx = ^TBlendMemEx;
|
|---|
| 152 | PBlendLine = ^TBlendLine;
|
|---|
| 153 | PBlendLineEx = ^TBlendLineEx;
|
|---|
| 154 |
|
|---|
| 155 | TBlendRegCombineModeArray = array[TCombineMode] of PBlendReg;
|
|---|
| 156 | TBlendMemCombineModeArray = array[TCombineMode] of PBlendMem;
|
|---|
| 157 | TBlendRegExCombineModeArray = array[TCombineMode] of PBlendRegEx;
|
|---|
| 158 | TBlendMemExCombineModeArray = array[TCombineMode] of PBlendMemEx;
|
|---|
| 159 | TBlendLineCombineModeArray = array[TCombineMode] of PBlendLine;
|
|---|
| 160 | TBlendLineExCombineModeArray = array[TCombineMode] of PBlendLineEx;
|
|---|
| 161 |
|
|---|
| 162 | const
|
|---|
| 163 | BLEND_REG: TBlendRegCombineModeArray = ((@@BlendReg),(@@MergeReg));
|
|---|
| 164 | BLEND_MEM: TBlendMemCombineModeArray = ((@@BlendMem),(@@MergeMem));
|
|---|
| 165 | BLEND_REG_EX: TBlendRegExCombineModeArray = ((@@BlendRegEx),(@@MergeRegEx));
|
|---|
| 166 | BLEND_MEM_EX: TBlendMemExCombineModeArray = ((@@BlendMemEx),(@@MergeMemEx));
|
|---|
| 167 | BLEND_LINE: TBlendLineCombineModeArray = ((@@BlendLine),(@@MergeLine));
|
|---|
| 168 | BLEND_LINE_EX: TBlendLineExCombineModeArray = ((@@BlendLineEx),(@@MergeLineEx));
|
|---|
| 169 |
|
|---|
| 170 | var
|
|---|
| 171 | BlendRegistry: TFunctionRegistry;
|
|---|
| 172 |
|
|---|
| 173 | {$IFDEF OMIT_MMX}
|
|---|
| 174 | procedure EMMS; {$IFDEF USEINLINING} inline; {$ENDIF}
|
|---|
| 175 | {$ENDIF}
|
|---|
| 176 |
|
|---|
| 177 | var
|
|---|
| 178 | RcTable: array [Byte, Byte] of Byte;
|
|---|
| 179 | DivTable: array [Byte, Byte] of Byte;
|
|---|
| 180 |
|
|---|
| 181 | implementation
|
|---|
| 182 |
|
|---|
| 183 | uses
|
|---|
| 184 | GR32_LowLevel,
|
|---|
| 185 | {$IFNDEF PUREPASCAL}
|
|---|
| 186 | GR32_BlendASM,
|
|---|
| 187 | {$IFNDEF OMIT_MMX}
|
|---|
| 188 | GR32_BlendMMX,
|
|---|
| 189 | {$ENDIF}
|
|---|
| 190 | {$IFNDEF OMIT_SSE2}
|
|---|
| 191 | GR32_BlendSSE2,
|
|---|
| 192 | {$ENDIF}
|
|---|
| 193 | {$ENDIF}
|
|---|
| 194 | GR32_System;
|
|---|
| 195 |
|
|---|
| 196 | {$IFDEF OMIT_MMX}
|
|---|
| 197 | procedure EMMS;
|
|---|
| 198 | begin
|
|---|
| 199 | end;
|
|---|
| 200 | {$ENDIF}
|
|---|
| 201 |
|
|---|
| 202 | { Pure Pascal }
|
|---|
| 203 |
|
|---|
| 204 | function BlendReg_Pas(F, B: TColor32): TColor32;
|
|---|
| 205 | var
|
|---|
| 206 | FX: TColor32Entry absolute F;
|
|---|
| 207 | BX: TColor32Entry absolute B;
|
|---|
| 208 | Af, Ab: PByteArray;
|
|---|
| 209 | FA : Byte;
|
|---|
| 210 | begin
|
|---|
| 211 | FA := FX.A;
|
|---|
| 212 |
|
|---|
| 213 | if FA = 0 then
|
|---|
| 214 | begin
|
|---|
| 215 | Result := B;
|
|---|
| 216 | Exit;
|
|---|
| 217 | end;
|
|---|
| 218 |
|
|---|
| 219 | if FA = $FF then
|
|---|
| 220 | begin
|
|---|
| 221 | Result := F;
|
|---|
| 222 | Exit;
|
|---|
| 223 | end;
|
|---|
| 224 |
|
|---|
| 225 | Af := @DivTable[FA];
|
|---|
| 226 | Ab := @DivTable[not FA];
|
|---|
| 227 | with BX do
|
|---|
| 228 | begin
|
|---|
| 229 | R := Af[FX.R] + Ab[R];
|
|---|
| 230 | G := Af[FX.G] + Ab[G];
|
|---|
| 231 | B := Af[FX.B] + Ab[B];
|
|---|
| 232 | A := $FF;
|
|---|
| 233 | end;
|
|---|
| 234 | Result := B;
|
|---|
| 235 | end;
|
|---|
| 236 |
|
|---|
| 237 | procedure BlendMem_Pas(F: TColor32; var B: TColor32);
|
|---|
| 238 | var
|
|---|
| 239 | FX: TColor32Entry absolute F;
|
|---|
| 240 | BX: TColor32Entry absolute B;
|
|---|
| 241 | Af, Ab: PByteArray;
|
|---|
| 242 | FA : Byte;
|
|---|
| 243 | begin
|
|---|
| 244 | FA := FX.A;
|
|---|
| 245 |
|
|---|
| 246 | if FA = 0 then Exit;
|
|---|
| 247 |
|
|---|
| 248 | if FA = $FF then
|
|---|
| 249 | begin
|
|---|
| 250 | B := F;
|
|---|
| 251 | Exit;
|
|---|
| 252 | end;
|
|---|
| 253 |
|
|---|
| 254 | Af := @DivTable[FA];
|
|---|
| 255 | Ab := @DivTable[not FA];
|
|---|
| 256 | with BX do
|
|---|
| 257 | begin
|
|---|
| 258 | R := Af[FX.R] + Ab[R];
|
|---|
| 259 | G := Af[FX.G] + Ab[G];
|
|---|
| 260 | B := Af[FX.B] + Ab[B];
|
|---|
| 261 | A := $FF;
|
|---|
| 262 | end;
|
|---|
| 263 | end;
|
|---|
| 264 |
|
|---|
| 265 | procedure BlendMems_Pas(F: TColor32; B: PColor32; Count: Integer);
|
|---|
| 266 | begin
|
|---|
| 267 | while Count > 0 do
|
|---|
| 268 | begin
|
|---|
| 269 | BlendMem(F, B^);
|
|---|
| 270 | Inc(B);
|
|---|
| 271 | Dec(Count);
|
|---|
| 272 | end;
|
|---|
| 273 | end;
|
|---|
| 274 |
|
|---|
| 275 | function BlendRegEx_Pas(F, B, M: TColor32): TColor32;
|
|---|
| 276 | var
|
|---|
| 277 | FX: TColor32Entry absolute F;
|
|---|
| 278 | BX: TColor32Entry absolute B;
|
|---|
| 279 | Af, Ab: PByteArray;
|
|---|
| 280 | begin
|
|---|
| 281 | Af := @DivTable[M];
|
|---|
| 282 |
|
|---|
| 283 | M := Af[FX.A];
|
|---|
| 284 |
|
|---|
| 285 | if M = 0 then
|
|---|
| 286 | begin
|
|---|
| 287 | Result := B;
|
|---|
| 288 | Exit;
|
|---|
| 289 | end;
|
|---|
| 290 |
|
|---|
| 291 | if M = $FF then
|
|---|
| 292 | begin
|
|---|
| 293 | Result := F;
|
|---|
| 294 | Exit;
|
|---|
| 295 | end;
|
|---|
| 296 |
|
|---|
| 297 | Ab := @DivTable[255 - M];
|
|---|
| 298 | with BX do
|
|---|
| 299 | begin
|
|---|
| 300 | R := Af[FX.R] + Ab[R];
|
|---|
| 301 | G := Af[FX.G] + Ab[G];
|
|---|
| 302 | B := Af[FX.B] + Ab[B];
|
|---|
| 303 | A := $FF;
|
|---|
| 304 | end;
|
|---|
| 305 | Result := B;
|
|---|
| 306 | end;
|
|---|
| 307 |
|
|---|
| 308 | procedure BlendMemEx_Pas(F: TColor32; var B: TColor32; M: TColor32);
|
|---|
| 309 | var
|
|---|
| 310 | FX: TColor32Entry absolute F;
|
|---|
| 311 | BX: TColor32Entry absolute B;
|
|---|
| 312 | Af, Ab: PByteArray;
|
|---|
| 313 | begin
|
|---|
| 314 | Af := @DivTable[M];
|
|---|
| 315 |
|
|---|
| 316 | M := Af[FX.A];
|
|---|
| 317 |
|
|---|
| 318 | if M = 0 then
|
|---|
| 319 | begin
|
|---|
| 320 | Exit;
|
|---|
| 321 | end;
|
|---|
| 322 |
|
|---|
| 323 | if M = $FF then
|
|---|
| 324 | begin
|
|---|
| 325 | B := F;
|
|---|
| 326 | Exit;
|
|---|
| 327 | end;
|
|---|
| 328 |
|
|---|
| 329 | Ab := @DivTable[255 - M];
|
|---|
| 330 | with BX do
|
|---|
| 331 | begin
|
|---|
| 332 | R := Af[FX.R] + Ab[R];
|
|---|
| 333 | G := Af[FX.G] + Ab[G];
|
|---|
| 334 | B := Af[FX.B] + Ab[B];
|
|---|
| 335 | A := $FF;
|
|---|
| 336 | end;
|
|---|
| 337 | end;
|
|---|
| 338 |
|
|---|
| 339 | function BlendRegRGB_Pas(F, B, W: TColor32): TColor32;
|
|---|
| 340 | var
|
|---|
| 341 | FX: TColor32Entry absolute F;
|
|---|
| 342 | BX: TColor32Entry absolute B;
|
|---|
| 343 | WX: TColor32Entry absolute W;
|
|---|
| 344 | RX: TColor32Entry absolute Result;
|
|---|
| 345 | begin
|
|---|
| 346 | RX.R := (FX.R - BX.R) * WX.B div 255 + BX.R;
|
|---|
| 347 | RX.G := (FX.G - BX.G) * WX.G div 255 + BX.G;
|
|---|
| 348 | RX.B := (FX.B - BX.B) * WX.R div 255 + BX.B;
|
|---|
| 349 | end;
|
|---|
| 350 |
|
|---|
| 351 | procedure BlendMemRGB_Pas(F: TColor32; var B: TColor32; W: TColor32);
|
|---|
| 352 | var
|
|---|
| 353 | FX: TColor32Entry absolute F;
|
|---|
| 354 | BX: TColor32Entry absolute B;
|
|---|
| 355 | WX: TColor32Entry absolute W;
|
|---|
| 356 | begin
|
|---|
| 357 | BX.R := (FX.R - BX.R) * WX.B div 255 + BX.R;
|
|---|
| 358 | BX.G := (FX.G - BX.G) * WX.G div 255 + BX.G;
|
|---|
| 359 | BX.B := (FX.B - BX.B) * WX.R div 255 + BX.B;
|
|---|
| 360 | end;
|
|---|
| 361 |
|
|---|
| 362 | procedure BlendLine1_Pas(Src: TColor32; Dst: PColor32; Count: Integer);
|
|---|
| 363 | begin
|
|---|
| 364 | while Count > 0 do
|
|---|
| 365 | begin
|
|---|
| 366 | BlendMem(Src, Dst^);
|
|---|
| 367 | Inc(Dst);
|
|---|
| 368 | Dec(Count);
|
|---|
| 369 | end;
|
|---|
| 370 | end;
|
|---|
| 371 |
|
|---|
| 372 | procedure BlendLine_Pas(Src, Dst: PColor32; Count: Integer);
|
|---|
| 373 | begin
|
|---|
| 374 | while Count > 0 do
|
|---|
| 375 | begin
|
|---|
| 376 | BlendMem(Src^, Dst^);
|
|---|
| 377 | Inc(Src);
|
|---|
| 378 | Inc(Dst);
|
|---|
| 379 | Dec(Count);
|
|---|
| 380 | end;
|
|---|
| 381 | end;
|
|---|
| 382 |
|
|---|
| 383 | procedure BlendLineEx_Pas(Src, Dst: PColor32; Count: Integer; M: TColor32);
|
|---|
| 384 | begin
|
|---|
| 385 | while Count > 0 do
|
|---|
| 386 | begin
|
|---|
| 387 | BlendMemEx(Src^, Dst^, M);
|
|---|
| 388 | Inc(Src);
|
|---|
| 389 | Inc(Dst);
|
|---|
| 390 | Dec(Count);
|
|---|
| 391 | end;
|
|---|
| 392 | end;
|
|---|
| 393 |
|
|---|
| 394 | function CombineReg_Pas(X, Y, W: TColor32): TColor32;
|
|---|
| 395 | var
|
|---|
| 396 | Xe: TColor32Entry absolute X;
|
|---|
| 397 | Ye: TColor32Entry absolute Y;
|
|---|
| 398 | Af, Ab: PByteArray;
|
|---|
| 399 | begin
|
|---|
| 400 | if W = 0 then
|
|---|
| 401 | begin
|
|---|
| 402 | Result := Y;
|
|---|
| 403 | Exit;
|
|---|
| 404 | end;
|
|---|
| 405 |
|
|---|
| 406 | if W >= $FF then
|
|---|
| 407 | begin
|
|---|
| 408 | Result := X;
|
|---|
| 409 | Exit;
|
|---|
| 410 | end;
|
|---|
| 411 |
|
|---|
| 412 | Af := @DivTable[W];
|
|---|
| 413 | Ab := @DivTable[255 - W];
|
|---|
| 414 | with Xe do
|
|---|
| 415 | begin
|
|---|
| 416 | R := Ab[Ye.R] + Af[R];
|
|---|
| 417 | G := Ab[Ye.G] + Af[G];
|
|---|
| 418 | B := Ab[Ye.B] + Af[B];
|
|---|
| 419 | A := Ab[Ye.A] + Af[A];
|
|---|
| 420 | end;
|
|---|
| 421 | Result := X;
|
|---|
| 422 | end;
|
|---|
| 423 |
|
|---|
| 424 | procedure CombineMem_Pas(X: TColor32; var Y: TColor32; W: TColor32);
|
|---|
| 425 | var
|
|---|
| 426 | Xe: TColor32Entry absolute X;
|
|---|
| 427 | Ye: TColor32Entry absolute Y;
|
|---|
| 428 | Af, Ab: PByteArray;
|
|---|
| 429 | begin
|
|---|
| 430 | if W = 0 then
|
|---|
| 431 | begin
|
|---|
| 432 | Exit;
|
|---|
| 433 | end;
|
|---|
| 434 |
|
|---|
| 435 | if W >= $FF then
|
|---|
| 436 | begin
|
|---|
| 437 | Y := X;
|
|---|
| 438 | Exit;
|
|---|
| 439 | end;
|
|---|
| 440 |
|
|---|
| 441 | Af := @DivTable[W];
|
|---|
| 442 | Ab := @DivTable[255 - W];
|
|---|
| 443 | with Xe do
|
|---|
| 444 | begin
|
|---|
| 445 | R := Ab[Ye.R] + Af[R];
|
|---|
| 446 | G := Ab[Ye.G] + Af[G];
|
|---|
| 447 | B := Ab[Ye.B] + Af[B];
|
|---|
| 448 | A := Ab[Ye.A] + Af[A];
|
|---|
| 449 | end;
|
|---|
| 450 | Y := X;
|
|---|
| 451 | end;
|
|---|
| 452 |
|
|---|
| 453 | procedure CombineLine_Pas(Src, Dst: PColor32; Count: Integer; W: TColor32);
|
|---|
| 454 | begin
|
|---|
| 455 | while Count > 0 do
|
|---|
| 456 | begin
|
|---|
| 457 | CombineMem(Src^, Dst^, W);
|
|---|
| 458 | Inc(Src);
|
|---|
| 459 | Inc(Dst);
|
|---|
| 460 | Dec(Count);
|
|---|
| 461 | end;
|
|---|
| 462 | end;
|
|---|
| 463 |
|
|---|
| 464 | function MergeReg_Pas(F, B: TColor32): TColor32;
|
|---|
| 465 | var
|
|---|
| 466 | Fa, Ba, Wa: TColor32;
|
|---|
| 467 | Fw, Bw: PByteArray;
|
|---|
| 468 | Fx: TColor32Entry absolute F;
|
|---|
| 469 | Bx: TColor32Entry absolute B;
|
|---|
| 470 | Rx: TColor32Entry absolute Result;
|
|---|
| 471 | begin
|
|---|
| 472 | Fa := F shr 24;
|
|---|
| 473 | Ba := B shr 24;
|
|---|
| 474 | if Fa = $FF then
|
|---|
| 475 | Result := F
|
|---|
| 476 | else if Fa = $0 then
|
|---|
| 477 | Result := B
|
|---|
| 478 | else if Ba = $0 then
|
|---|
| 479 | Result := F
|
|---|
| 480 | else
|
|---|
| 481 | begin
|
|---|
| 482 | Rx.A := DivTable[Fa xor 255, Ba xor 255] xor 255;
|
|---|
| 483 | Wa := RcTable[Rx.A, Fa];
|
|---|
| 484 | Fw := @DivTable[Wa];
|
|---|
| 485 | Bw := @DivTable[Wa xor $FF];
|
|---|
| 486 | Rx.R := Fw[Fx.R] + Bw[Bx.R];
|
|---|
| 487 | Rx.G := Fw[Fx.G] + Bw[Bx.G];
|
|---|
| 488 | Rx.B := Fw[Fx.B] + Bw[Bx.B];
|
|---|
| 489 | end;
|
|---|
| 490 | end;
|
|---|
| 491 |
|
|---|
| 492 | function MergeRegEx_Pas(F, B, M: TColor32): TColor32;
|
|---|
| 493 | begin
|
|---|
| 494 | Result := MergeReg(DivTable[M, F shr 24] shl 24 or F and $00FFFFFF, B);
|
|---|
| 495 | end;
|
|---|
| 496 |
|
|---|
| 497 | procedure MergeMem_Pas(F: TColor32; var B: TColor32);
|
|---|
| 498 | begin
|
|---|
| 499 | B := MergeReg(F, B);
|
|---|
| 500 | end;
|
|---|
| 501 |
|
|---|
| 502 | procedure MergeMemEx_Pas(F: TColor32; var B: TColor32; M: TColor32);
|
|---|
| 503 | begin
|
|---|
| 504 | B := MergeReg(DivTable[M, F shr 24] shl 24 or F and $00FFFFFF, B);
|
|---|
| 505 | end;
|
|---|
| 506 |
|
|---|
| 507 | procedure MergeLine1_Pas(Src: TColor32; Dst: PColor32; Count: Integer);
|
|---|
| 508 | begin
|
|---|
| 509 | while Count > 0 do
|
|---|
| 510 | begin
|
|---|
| 511 | Dst^ := MergeReg(Src, Dst^);
|
|---|
| 512 | Inc(Dst);
|
|---|
| 513 | Dec(Count);
|
|---|
| 514 | end;
|
|---|
| 515 | end;
|
|---|
| 516 |
|
|---|
| 517 | procedure MergeLine_Pas(Src, Dst: PColor32; Count: Integer);
|
|---|
| 518 | begin
|
|---|
| 519 | while Count > 0 do
|
|---|
| 520 | begin
|
|---|
| 521 | Dst^ := MergeReg(Src^, Dst^);
|
|---|
| 522 | Inc(Src);
|
|---|
| 523 | Inc(Dst);
|
|---|
| 524 | Dec(Count);
|
|---|
| 525 | end;
|
|---|
| 526 | end;
|
|---|
| 527 |
|
|---|
| 528 | procedure MergeLineEx_Pas(Src, Dst: PColor32; Count: Integer; M: TColor32);
|
|---|
| 529 | var
|
|---|
| 530 | PM: PByteArray absolute M;
|
|---|
| 531 | begin
|
|---|
| 532 | PM := @DivTable[M];
|
|---|
| 533 | while Count > 0 do
|
|---|
| 534 | begin
|
|---|
| 535 | Dst^ := MergeReg((PM[Src^ shr 24] shl 24) or (Src^ and $00FFFFFF), Dst^);
|
|---|
| 536 | Inc(Src);
|
|---|
| 537 | Inc(Dst);
|
|---|
| 538 | Dec(Count);
|
|---|
| 539 | end;
|
|---|
| 540 | end;
|
|---|
| 541 |
|
|---|
| 542 | procedure EMMS_Pas;
|
|---|
| 543 | begin
|
|---|
| 544 | // Dummy
|
|---|
| 545 | end;
|
|---|
| 546 |
|
|---|
| 547 | function LightenReg_Pas(C: TColor32; Amount: Integer): TColor32;
|
|---|
| 548 | var
|
|---|
| 549 | r, g, b: Integer;
|
|---|
| 550 | CX: TColor32Entry absolute C;
|
|---|
| 551 | RX: TColor32Entry absolute Result;
|
|---|
| 552 | begin
|
|---|
| 553 | r := CX.R;
|
|---|
| 554 | g := CX.G;
|
|---|
| 555 | b := CX.B;
|
|---|
| 556 |
|
|---|
| 557 | Inc(r, Amount);
|
|---|
| 558 | Inc(g, Amount);
|
|---|
| 559 | Inc(b, Amount);
|
|---|
| 560 |
|
|---|
| 561 | if r > 255 then r := 255 else if r < 0 then r := 0;
|
|---|
| 562 | if g > 255 then g := 255 else if g < 0 then g := 0;
|
|---|
| 563 | if b > 255 then b := 255 else if b < 0 then b := 0;
|
|---|
| 564 |
|
|---|
| 565 | // preserve alpha
|
|---|
| 566 | RX.A := CX.A;
|
|---|
| 567 | RX.R := r;
|
|---|
| 568 | RX.G := g;
|
|---|
| 569 | RX.B := b;
|
|---|
| 570 | end;
|
|---|
| 571 |
|
|---|
| 572 | { Color algebra }
|
|---|
| 573 |
|
|---|
| 574 | function ColorAdd_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 575 | var
|
|---|
| 576 | Xe: TColor32Entry absolute C1;
|
|---|
| 577 | Ye: TColor32Entry absolute C2;
|
|---|
| 578 | R: TColor32Entry absolute Result;
|
|---|
| 579 | begin
|
|---|
| 580 | R.A := Clamp(Xe.A + Ye.A, 255);
|
|---|
| 581 | R.R := Clamp(Xe.R + Ye.R, 255);
|
|---|
| 582 | R.G := Clamp(Xe.G + Ye.G, 255);
|
|---|
| 583 | R.B := Clamp(Xe.B + Ye.B, 255);
|
|---|
| 584 | end;
|
|---|
| 585 |
|
|---|
| 586 | function ColorSub_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 587 | var
|
|---|
| 588 | Xe: TColor32Entry absolute C1;
|
|---|
| 589 | Ye: TColor32Entry absolute C2;
|
|---|
| 590 | R: TColor32Entry absolute Result;
|
|---|
| 591 | Temp: SmallInt;
|
|---|
| 592 | begin
|
|---|
| 593 | Temp := Xe.A - Ye.A;
|
|---|
| 594 | if Temp < 0 then
|
|---|
| 595 | R.A := 0
|
|---|
| 596 | else
|
|---|
| 597 | R.A := Temp;
|
|---|
| 598 | Temp := Xe.R - Ye.R;
|
|---|
| 599 | if Temp < 0 then
|
|---|
| 600 | R.R := 0
|
|---|
| 601 | else
|
|---|
| 602 | R.R := Temp;
|
|---|
| 603 | Temp := Xe.G - Ye.G;
|
|---|
| 604 | if Temp < 0 then
|
|---|
| 605 | R.G := 0
|
|---|
| 606 | else
|
|---|
| 607 | R.G := Temp;
|
|---|
| 608 | Temp := Xe.B - Ye.B;
|
|---|
| 609 | if Temp < 0 then
|
|---|
| 610 | R.B := 0
|
|---|
| 611 | else
|
|---|
| 612 | R.B := Temp;
|
|---|
| 613 | end;
|
|---|
| 614 |
|
|---|
| 615 | function ColorDiv_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 616 | var
|
|---|
| 617 | C1e: TColor32Entry absolute C1;
|
|---|
| 618 | C2e: TColor32Entry absolute C2;
|
|---|
| 619 | Re: TColor32Entry absolute Result;
|
|---|
| 620 | Temp: Word;
|
|---|
| 621 | begin
|
|---|
| 622 | if C1e.A = 0 then
|
|---|
| 623 | Re.A := $FF
|
|---|
| 624 | else
|
|---|
| 625 | begin
|
|---|
| 626 | Temp := (C2e.A shl 8) div C1e.A;
|
|---|
| 627 | if Temp > $FF then
|
|---|
| 628 | Re.A := $FF
|
|---|
| 629 | else
|
|---|
| 630 | Re.A := Temp;
|
|---|
| 631 | end;
|
|---|
| 632 |
|
|---|
| 633 | if C1e.R = 0 then
|
|---|
| 634 | Re.R := $FF
|
|---|
| 635 | else
|
|---|
| 636 | begin
|
|---|
| 637 | Temp := (C2e.R shl 8) div C1e.R;
|
|---|
| 638 | if Temp > $FF then
|
|---|
| 639 | Re.R := $FF
|
|---|
| 640 | else
|
|---|
| 641 | Re.R := Temp;
|
|---|
| 642 | end;
|
|---|
| 643 |
|
|---|
| 644 | if C1e.G = 0 then
|
|---|
| 645 | Re.G := $FF
|
|---|
| 646 | else
|
|---|
| 647 | begin
|
|---|
| 648 | Temp := (C2e.G shl 8) div C1e.G;
|
|---|
| 649 | if Temp > $FF then
|
|---|
| 650 | Re.G := $FF
|
|---|
| 651 | else
|
|---|
| 652 | Re.G := Temp;
|
|---|
| 653 | end;
|
|---|
| 654 |
|
|---|
| 655 | if C1e.B = 0 then
|
|---|
| 656 | Re.B := $FF
|
|---|
| 657 | else
|
|---|
| 658 | begin
|
|---|
| 659 | Temp := (C2e.B shl 8) div C1e.B;
|
|---|
| 660 | if Temp > $FF then
|
|---|
| 661 | Re.B := $FF
|
|---|
| 662 | else
|
|---|
| 663 | Re.B := Temp;
|
|---|
| 664 | end;
|
|---|
| 665 | end;
|
|---|
| 666 |
|
|---|
| 667 | function ColorModulate_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 668 | var
|
|---|
| 669 | C1e: TColor32Entry absolute C2;
|
|---|
| 670 | C2e: TColor32Entry absolute C2;
|
|---|
| 671 | Re: TColor32Entry absolute Result;
|
|---|
| 672 | begin
|
|---|
| 673 | Re.A := (C2e.A * C1e.A + $80) shr 8;
|
|---|
| 674 | Re.R := (C2e.R * C1e.R + $80) shr 8;
|
|---|
| 675 | Re.G := (C2e.G * C1e.G + $80) shr 8;
|
|---|
| 676 | Re.B := (C2e.B * C1e.B + $80) shr 8;
|
|---|
| 677 | end;
|
|---|
| 678 |
|
|---|
| 679 | function ColorMax_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 680 | var
|
|---|
| 681 | REnt: TColor32Entry absolute Result;
|
|---|
| 682 | C2Ent: TColor32Entry absolute C2;
|
|---|
| 683 | begin
|
|---|
| 684 | Result := C1;
|
|---|
| 685 | with C2Ent do
|
|---|
| 686 | begin
|
|---|
| 687 | if A > REnt.A then REnt.A := A;
|
|---|
| 688 | if R > REnt.R then REnt.R := R;
|
|---|
| 689 | if G > REnt.G then REnt.G := G;
|
|---|
| 690 | if B > REnt.B then REnt.B := B;
|
|---|
| 691 | end;
|
|---|
| 692 | end;
|
|---|
| 693 |
|
|---|
| 694 | function ColorMin_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 695 | var
|
|---|
| 696 | REnt: TColor32Entry absolute Result;
|
|---|
| 697 | C2Ent: TColor32Entry absolute C2;
|
|---|
| 698 | begin
|
|---|
| 699 | Result := C1;
|
|---|
| 700 | with C2Ent do
|
|---|
| 701 | begin
|
|---|
| 702 | if A < REnt.A then REnt.A := A;
|
|---|
| 703 | if R < REnt.R then REnt.R := R;
|
|---|
| 704 | if G < REnt.G then REnt.G := G;
|
|---|
| 705 | if B < REnt.B then REnt.B := B;
|
|---|
| 706 | end;
|
|---|
| 707 | end;
|
|---|
| 708 |
|
|---|
| 709 | function ColorDifference_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 710 | var
|
|---|
| 711 | Xe: TColor32Entry absolute C1;
|
|---|
| 712 | Ye: TColor32Entry absolute C2;
|
|---|
| 713 | R: TColor32Entry absolute Result;
|
|---|
| 714 | begin
|
|---|
| 715 | R.A := Abs(Xe.A - Ye.A);
|
|---|
| 716 | R.R := Abs(Xe.R - Ye.R);
|
|---|
| 717 | R.G := Abs(Xe.G - Ye.G);
|
|---|
| 718 | R.B := Abs(Xe.B - Ye.B);
|
|---|
| 719 | end;
|
|---|
| 720 |
|
|---|
| 721 | function ColorExclusion_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 722 | var
|
|---|
| 723 | Xe: TColor32Entry absolute C1;
|
|---|
| 724 | Ye: TColor32Entry absolute C2;
|
|---|
| 725 | R: TColor32Entry absolute Result;
|
|---|
| 726 | begin
|
|---|
| 727 | R.A := Xe.A + Ye.A - ((Xe.A * Ye.A) shl 7);
|
|---|
| 728 | R.R := Xe.R + Ye.R - ((Xe.R * Ye.R) shr 7);
|
|---|
| 729 | R.G := Xe.G + Ye.G - ((Xe.G * Ye.G) shr 7);
|
|---|
| 730 | R.B := Xe.B + Ye.B - ((Xe.B * Ye.B) shr 7);
|
|---|
| 731 | end;
|
|---|
| 732 |
|
|---|
| 733 | function ColorAverage_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 734 | //(A + B)/2 = (A and B) + (A xor B)/2
|
|---|
| 735 | var
|
|---|
| 736 | C3 : TColor32;
|
|---|
| 737 | begin
|
|---|
| 738 | C3 := C1;
|
|---|
| 739 | C1 := C1 xor C2;
|
|---|
| 740 | C1 := C1 shr 1;
|
|---|
| 741 | C1 := C1 and $7F7F7F7F;
|
|---|
| 742 | C3 := C3 and C2;
|
|---|
| 743 | Result := C3 + C1;
|
|---|
| 744 | end;
|
|---|
| 745 |
|
|---|
| 746 | function ColorScale_Pas(C, W: TColor32): TColor32;
|
|---|
| 747 | var
|
|---|
| 748 | Ce: TColor32Entry absolute C;
|
|---|
| 749 | var
|
|---|
| 750 | r1, g1, b1, a1: Cardinal;
|
|---|
| 751 | begin
|
|---|
| 752 | a1 := Ce.A * W shr 8;
|
|---|
| 753 | r1 := Ce.R * W shr 8;
|
|---|
| 754 | g1 := Ce.G * W shr 8;
|
|---|
| 755 | b1 := Ce.B * W shr 8;
|
|---|
| 756 |
|
|---|
| 757 | if a1 > 255 then a1 := 255;
|
|---|
| 758 | if r1 > 255 then r1 := 255;
|
|---|
| 759 | if g1 > 255 then g1 := 255;
|
|---|
| 760 | if b1 > 255 then b1 := 255;
|
|---|
| 761 |
|
|---|
| 762 | Result := a1 shl 24 + r1 shl 16 + g1 shl 8 + b1;
|
|---|
| 763 | end;
|
|---|
| 764 |
|
|---|
| 765 | function ColorScreen_Pas(B, S: TColor32): TColor32;
|
|---|
| 766 | var
|
|---|
| 767 | Be: TColor32Entry absolute B;
|
|---|
| 768 | Se: TColor32Entry absolute S;
|
|---|
| 769 | R: TColor32Entry absolute Result;
|
|---|
| 770 | begin
|
|---|
| 771 | R.A := Be.A + Se.A - (Be.A * Se.A) div 255;
|
|---|
| 772 | R.R := Be.R + Se.R - (Be.R * Se.R) div 255;
|
|---|
| 773 | R.G := Be.G + Se.G - (Be.G * Se.G) div 255;
|
|---|
| 774 | R.B := Be.B + Se.B - (Be.B * Se.B) div 255;
|
|---|
| 775 | end;
|
|---|
| 776 |
|
|---|
| 777 | function ColorDodge_Pas(B, S: TColor32): TColor32;
|
|---|
| 778 |
|
|---|
| 779 | function Dodge(B, S: Byte): Byte;
|
|---|
| 780 | begin
|
|---|
| 781 | if B = 0 then
|
|---|
| 782 | Result := 0
|
|---|
| 783 | else
|
|---|
| 784 | if S = 255 then
|
|---|
| 785 | Result := 255
|
|---|
| 786 | else
|
|---|
| 787 | Result := Clamp((255 * B) div (255 - S), 255);
|
|---|
| 788 | end;
|
|---|
| 789 |
|
|---|
| 790 | var
|
|---|
| 791 | Be: TColor32Entry absolute B;
|
|---|
| 792 | Se: TColor32Entry absolute S;
|
|---|
| 793 | R: TColor32Entry absolute Result;
|
|---|
| 794 | begin
|
|---|
| 795 | R.A := Dodge(Be.A, Se.A);
|
|---|
| 796 | R.R := Dodge(Be.R, Se.R);
|
|---|
| 797 | R.G := Dodge(Be.G, Se.G);
|
|---|
| 798 | R.B := Dodge(Be.B, Se.B);
|
|---|
| 799 | end;
|
|---|
| 800 |
|
|---|
| 801 | function ColorBurn_Pas(B, S: TColor32): TColor32;
|
|---|
| 802 |
|
|---|
| 803 | function Burn(B, S: Byte): Byte;
|
|---|
| 804 | begin
|
|---|
| 805 | if B = 255 then
|
|---|
| 806 | Result := 255
|
|---|
| 807 | else
|
|---|
| 808 | if S = 0 then
|
|---|
| 809 | Result := 0
|
|---|
| 810 | else
|
|---|
| 811 | Result := 255 - Clamp(255 * (255 - B) div S, 255);
|
|---|
| 812 | end;
|
|---|
| 813 |
|
|---|
| 814 | var
|
|---|
| 815 | Be: TColor32Entry absolute B;
|
|---|
| 816 | Se: TColor32Entry absolute S;
|
|---|
| 817 | R: TColor32Entry absolute Result;
|
|---|
| 818 | begin
|
|---|
| 819 | R.A := Burn(Be.A, Se.A);
|
|---|
| 820 | R.R := Burn(Be.R, Se.R);
|
|---|
| 821 | R.G := Burn(Be.G, Se.G);
|
|---|
| 822 | R.B := Burn(Be.B, Se.B);
|
|---|
| 823 | end;
|
|---|
| 824 |
|
|---|
| 825 |
|
|---|
| 826 | { Blended color algebra }
|
|---|
| 827 |
|
|---|
| 828 | function BlendColorAdd_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 829 | var
|
|---|
| 830 | Xe: TColor32Entry absolute C1;
|
|---|
| 831 | Ye: TColor32Entry absolute C2;
|
|---|
| 832 | R: TColor32Entry absolute Result;
|
|---|
| 833 | Af, Ab: PByteArray;
|
|---|
| 834 | begin
|
|---|
| 835 | Af := @DivTable[Xe.A];
|
|---|
| 836 | Ab := @DivTable[not Xe.A];
|
|---|
| 837 | R.A := Af[Clamp(Xe.A + Ye.A, 255)] + Ab[Ye.A];
|
|---|
| 838 | R.R := Af[Clamp(Xe.R + Ye.R, 255)] + Ab[Ye.R];
|
|---|
| 839 | R.G := Af[Clamp(Xe.G + Ye.G, 255)] + Ab[Ye.G];
|
|---|
| 840 | R.B := Af[Clamp(Xe.B + Ye.B, 255)] + Ab[Ye.B];
|
|---|
| 841 | end;
|
|---|
| 842 |
|
|---|
| 843 | function BlendColorModulate_Pas(C1, C2: TColor32): TColor32;
|
|---|
| 844 | var
|
|---|
| 845 | C1e: TColor32Entry absolute C1;
|
|---|
| 846 | C2e: TColor32Entry absolute C2;
|
|---|
| 847 | R: TColor32Entry absolute Result;
|
|---|
| 848 | Af, Ab: PByteArray;
|
|---|
| 849 | begin
|
|---|
| 850 | Af := @DivTable[C1e.A];
|
|---|
| 851 | Ab := @DivTable[not C1e.A];
|
|---|
| 852 | R.A := Af[(C2e.A * C1e.A + $80) shr 8] + Ab[C2e.A];
|
|---|
| 853 | R.R := Af[(C2e.R * C1e.R + $80) shr 8] + Ab[C2e.R];
|
|---|
| 854 | R.G := Af[(C2e.G * C1e.G + $80) shr 8] + Ab[C2e.G];
|
|---|
| 855 | R.B := Af[(C2e.B * C1e.B + $80) shr 8] + Ab[C2e.B];
|
|---|
| 856 | end;
|
|---|
| 857 |
|
|---|
| 858 | {$IFNDEF PUREPASCAL}
|
|---|
| 859 |
|
|---|
| 860 | procedure GenAlphaTable;
|
|---|
| 861 | var
|
|---|
| 862 | I: Integer;
|
|---|
| 863 | L: LongWord;
|
|---|
| 864 | P: PLongWord;
|
|---|
| 865 | begin
|
|---|
| 866 | GetMem(AlphaTable, 257 * 8 * SizeOf(Cardinal));
|
|---|
| 867 | {$IFDEF HAS_NATIVEINT}
|
|---|
| 868 | alpha_ptr := Pointer(NativeUInt(AlphaTable) and (not $F));
|
|---|
| 869 | if NativeUInt(alpha_ptr) < NativeUInt(AlphaTable) then
|
|---|
| 870 | alpha_ptr := Pointer(NativeUInt(alpha_ptr) + 16);
|
|---|
| 871 | {$ELSE}
|
|---|
| 872 | alpha_ptr := Pointer(Cardinal(AlphaTable) and (not $F));
|
|---|
| 873 | if Cardinal(alpha_ptr) < Cardinal(AlphaTable) then
|
|---|
| 874 | Inc(Cardinal(alpha_ptr), 16);
|
|---|
| 875 | {$ENDIF}
|
|---|
| 876 | P := alpha_ptr;
|
|---|
| 877 | for I := 0 to 255 do
|
|---|
| 878 | begin
|
|---|
| 879 | L := I + I shl 16;
|
|---|
| 880 | P^ := L;
|
|---|
| 881 | Inc(P);
|
|---|
| 882 | P^ := L;
|
|---|
| 883 | Inc(P);
|
|---|
| 884 | P^ := L;
|
|---|
| 885 | Inc(P);
|
|---|
| 886 | P^ := L;
|
|---|
| 887 | Inc(P);
|
|---|
| 888 | end;
|
|---|
| 889 | bias_ptr := alpha_ptr;
|
|---|
| 890 | Inc(PLongWord(bias_ptr), 4 * $80);
|
|---|
| 891 | end;
|
|---|
| 892 |
|
|---|
| 893 | procedure FreeAlphaTable;
|
|---|
| 894 | begin
|
|---|
| 895 | FreeMem(AlphaTable);
|
|---|
| 896 | end;
|
|---|
| 897 | {$ENDIF}
|
|---|
| 898 |
|
|---|
| 899 | { Misc stuff }
|
|---|
| 900 |
|
|---|
| 901 | function Lighten(C: TColor32; Amount: Integer): TColor32;
|
|---|
| 902 | begin
|
|---|
| 903 | Result := LightenReg(C, Amount);
|
|---|
| 904 | end;
|
|---|
| 905 |
|
|---|
| 906 | procedure MakeMergeTables;
|
|---|
| 907 | var
|
|---|
| 908 | I, J: Integer;
|
|---|
| 909 | begin
|
|---|
| 910 | for J := 0 to 255 do
|
|---|
| 911 | begin
|
|---|
| 912 | DivTable[0, J] := 0;
|
|---|
| 913 | RcTable[0, J] := 0;
|
|---|
| 914 | end;
|
|---|
| 915 | for J := 0 to 255 do
|
|---|
| 916 | for I := 1 to 255 do
|
|---|
| 917 | begin
|
|---|
| 918 | DivTable[I, J] := Round(I * J * COne255th);
|
|---|
| 919 | RcTable[I, J] := Round(J * 255 / I)
|
|---|
| 920 | end;
|
|---|
| 921 | end;
|
|---|
| 922 |
|
|---|
| 923 | const
|
|---|
| 924 | FID_EMMS = 0;
|
|---|
| 925 | FID_MERGEREG = 1;
|
|---|
| 926 | FID_MERGEMEM = 2;
|
|---|
| 927 | FID_MERGELINE = 3;
|
|---|
| 928 | FID_MERGELINE1 = 4;
|
|---|
| 929 | FID_MERGEREGEX = 5;
|
|---|
| 930 | FID_MERGEMEMEX = 6;
|
|---|
| 931 | FID_MERGELINEEX = 7;
|
|---|
| 932 | FID_COMBINEREG = 8;
|
|---|
| 933 | FID_COMBINEMEM = 9;
|
|---|
| 934 | FID_COMBINELINE = 10;
|
|---|
| 935 |
|
|---|
| 936 | FID_BLENDREG = 11;
|
|---|
| 937 | FID_BLENDMEM = 12;
|
|---|
| 938 | FID_BLENDMEMS = 13;
|
|---|
| 939 | FID_BLENDLINE = 14;
|
|---|
| 940 | FID_BLENDREGEX = 15;
|
|---|
| 941 | FID_BLENDMEMEX = 16;
|
|---|
| 942 | FID_BLENDLINEEX = 17;
|
|---|
| 943 | FID_BLENDLINE1 = 18;
|
|---|
| 944 |
|
|---|
| 945 | FID_COLORMAX = 19;
|
|---|
| 946 | FID_COLORMIN = 20;
|
|---|
| 947 | FID_COLORAVERAGE = 21;
|
|---|
| 948 | FID_COLORADD = 22;
|
|---|
| 949 | FID_COLORSUB = 23;
|
|---|
| 950 | FID_COLORDIV = 24;
|
|---|
| 951 | FID_COLORMODULATE = 25;
|
|---|
| 952 | FID_COLORDIFFERENCE = 26;
|
|---|
| 953 | FID_COLOREXCLUSION = 27;
|
|---|
| 954 | FID_COLORSCALE = 28;
|
|---|
| 955 | FID_COLORSCREEN = 29;
|
|---|
| 956 | FID_COLORDODGE = 30;
|
|---|
| 957 | FID_COLORBURN = 31;
|
|---|
| 958 | FID_BLENDCOLORADD = 32;
|
|---|
| 959 | FID_BLENDCOLORMODULATE = 33;
|
|---|
| 960 | FID_LIGHTEN = 34;
|
|---|
| 961 |
|
|---|
| 962 | FID_BLENDREGRGB = 35;
|
|---|
| 963 | FID_BLENDMEMRGB = 36;
|
|---|
| 964 | {$IFDEF TEST_BLENDMEMRGB128SSE4}
|
|---|
| 965 | FID_BLENDMEMRGB128 = 37;
|
|---|
| 966 | {$ENDIF}
|
|---|
| 967 |
|
|---|
| 968 | const
|
|---|
| 969 | BlendBindingFlagPascal = $0001;
|
|---|
| 970 |
|
|---|
| 971 |
|
|---|
| 972 | procedure RegisterBindings;
|
|---|
| 973 | begin
|
|---|
| 974 | BlendRegistry := NewRegistry('GR32_Blend bindings');
|
|---|
| 975 | {$IFNDEF OMIT_MMX}
|
|---|
| 976 | BlendRegistry.RegisterBinding(FID_EMMS, @@EMMS);
|
|---|
| 977 | {$ENDIF}
|
|---|
| 978 | BlendRegistry.RegisterBinding(FID_MERGEREG, @@MergeReg);
|
|---|
| 979 | BlendRegistry.RegisterBinding(FID_MERGEMEM, @@MergeMem);
|
|---|
| 980 | BlendRegistry.RegisterBinding(FID_MERGELINE, @@MergeLine);
|
|---|
| 981 | BlendRegistry.RegisterBinding(FID_MERGEREGEX, @@MergeRegEx);
|
|---|
| 982 | BlendRegistry.RegisterBinding(FID_MERGEMEMEX, @@MergeMemEx);
|
|---|
| 983 | BlendRegistry.RegisterBinding(FID_MERGELINEEX, @@MergeLineEx);
|
|---|
| 984 | BlendRegistry.RegisterBinding(FID_COMBINEREG, @@CombineReg);
|
|---|
| 985 | BlendRegistry.RegisterBinding(FID_COMBINEMEM, @@CombineMem);
|
|---|
| 986 | BlendRegistry.RegisterBinding(FID_COMBINELINE, @@CombineLine);
|
|---|
| 987 |
|
|---|
| 988 | BlendRegistry.RegisterBinding(FID_BLENDREG, @@BlendReg);
|
|---|
| 989 | BlendRegistry.RegisterBinding(FID_BLENDMEM, @@BlendMem);
|
|---|
| 990 | BlendRegistry.RegisterBinding(FID_BLENDMEMS, @@BlendMems);
|
|---|
| 991 | BlendRegistry.RegisterBinding(FID_BLENDLINE, @@BlendLine);
|
|---|
| 992 | BlendRegistry.RegisterBinding(FID_BLENDREGEX, @@BlendRegEx);
|
|---|
| 993 | BlendRegistry.RegisterBinding(FID_BLENDMEMEX, @@BlendMemEx);
|
|---|
| 994 | BlendRegistry.RegisterBinding(FID_BLENDLINEEX, @@BlendLineEx);
|
|---|
| 995 | BlendRegistry.RegisterBinding(FID_BLENDLINE1, @@BlendLine1);
|
|---|
| 996 |
|
|---|
| 997 | BlendRegistry.RegisterBinding(FID_COLORMAX, @@ColorMax);
|
|---|
| 998 | BlendRegistry.RegisterBinding(FID_COLORMIN, @@ColorMin);
|
|---|
| 999 | BlendRegistry.RegisterBinding(FID_COLORAVERAGE, @@ColorAverage);
|
|---|
| 1000 | BlendRegistry.RegisterBinding(FID_COLORADD, @@ColorAdd);
|
|---|
| 1001 | BlendRegistry.RegisterBinding(FID_COLORSUB, @@ColorSub);
|
|---|
| 1002 | BlendRegistry.RegisterBinding(FID_COLORDIV, @@ColorDiv);
|
|---|
| 1003 | BlendRegistry.RegisterBinding(FID_COLORMODULATE, @@ColorModulate);
|
|---|
| 1004 | BlendRegistry.RegisterBinding(FID_COLORDIFFERENCE, @@ColorDifference);
|
|---|
| 1005 | BlendRegistry.RegisterBinding(FID_COLOREXCLUSION, @@ColorExclusion);
|
|---|
| 1006 | BlendRegistry.RegisterBinding(FID_COLORSCALE, @@ColorScale);
|
|---|
| 1007 | BlendRegistry.RegisterBinding(FID_COLORSCREEN, @@ColorScreen);
|
|---|
| 1008 | BlendRegistry.RegisterBinding(FID_COLORDODGE, @@ColorDodge);
|
|---|
| 1009 | BlendRegistry.RegisterBinding(FID_COLORBURN, @@ColorBurn);
|
|---|
| 1010 |
|
|---|
| 1011 | BlendRegistry.RegisterBinding(FID_BLENDCOLORADD, @@BlendColorAdd);
|
|---|
| 1012 | BlendRegistry.RegisterBinding(FID_BLENDCOLORMODULATE, @@BlendColorModulate);
|
|---|
| 1013 |
|
|---|
| 1014 | BlendRegistry.RegisterBinding(FID_LIGHTEN, @@LightenReg);
|
|---|
| 1015 | BlendRegistry.RegisterBinding(FID_BLENDREGRGB, @@BlendRegRGB);
|
|---|
| 1016 | BlendRegistry.RegisterBinding(FID_BLENDMEMRGB, @@BlendMemRGB);
|
|---|
| 1017 | {$IFDEF TEST_BLENDMEMRGB128SSE4}
|
|---|
| 1018 | BlendRegistry.RegisterBinding(FID_BLENDMEMRGB128, @@BlendMemRGB128);
|
|---|
| 1019 | {$ENDIF}
|
|---|
| 1020 |
|
|---|
| 1021 | // pure pascal
|
|---|
| 1022 | BlendRegistry.Add(FID_EMMS, @EMMS_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1023 | BlendRegistry.Add(FID_MERGEREG, @MergeReg_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1024 | BlendRegistry.Add(FID_MERGEMEM, @MergeMem_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1025 | BlendRegistry.Add(FID_MERGEMEMEX, @MergeMemEx_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1026 | BlendRegistry.Add(FID_MERGEREGEX, @MergeRegEx_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1027 | BlendRegistry.Add(FID_MERGELINE, @MergeLine_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1028 | BlendRegistry.Add(FID_MERGELINEEX, @MergeLineEx_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1029 | BlendRegistry.Add(FID_MERGELINE1, @MergeLine1_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1030 | BlendRegistry.Add(FID_COLORDIV, @ColorDiv_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1031 | BlendRegistry.Add(FID_COLORAVERAGE, @ColorAverage_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1032 | BlendRegistry.Add(FID_COMBINEREG, @CombineReg_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1033 | BlendRegistry.Add(FID_COMBINEMEM, @CombineMem_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1034 | BlendRegistry.Add(FID_COMBINELINE, @CombineLine_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1035 | BlendRegistry.Add(FID_BLENDREG, @BlendReg_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1036 | BlendRegistry.Add(FID_BLENDMEM, @BlendMem_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1037 | BlendRegistry.Add(FID_BLENDMEMS, @BlendMems_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1038 | BlendRegistry.Add(FID_BLENDLINE, @BlendLine_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1039 | BlendRegistry.Add(FID_BLENDREGEX, @BlendRegEx_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1040 | BlendRegistry.Add(FID_BLENDMEMEX, @BlendMemEx_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1041 | BlendRegistry.Add(FID_BLENDLINEEX, @BlendLineEx_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1042 | BlendRegistry.Add(FID_BLENDLINE1, @BlendLine1_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1043 | BlendRegistry.Add(FID_COLORMAX, @ColorMax_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1044 | BlendRegistry.Add(FID_COLORMIN, @ColorMin_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1045 | BlendRegistry.Add(FID_COLORADD, @ColorAdd_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1046 | BlendRegistry.Add(FID_COLORSUB, @ColorSub_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1047 | BlendRegistry.Add(FID_COLORMODULATE, @ColorModulate_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1048 | BlendRegistry.Add(FID_COLORDIFFERENCE, @ColorDifference_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1049 | BlendRegistry.Add(FID_COLOREXCLUSION, @ColorExclusion_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1050 | BlendRegistry.Add(FID_COLORSCALE, @ColorScale_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1051 | BlendRegistry.Add(FID_COLORSCREEN, @ColorScreen_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1052 | BlendRegistry.Add(FID_COLORDODGE, @ColorDodge_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1053 | BlendRegistry.Add(FID_COLORBURN, @ColorBurn_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1054 | BlendRegistry.Add(FID_BLENDCOLORADD, @BlendColorAdd_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1055 | BlendRegistry.Add(FID_BLENDCOLORMODULATE, @BlendColorModulate_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1056 | BlendRegistry.Add(FID_LIGHTEN, @LightenReg_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1057 | BlendRegistry.Add(FID_BLENDREGRGB, @BlendRegRGB_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1058 | BlendRegistry.Add(FID_BLENDMEMRGB, @BlendMemRGB_Pas, [], BlendBindingFlagPascal);
|
|---|
| 1059 |
|
|---|
| 1060 | {$IFNDEF PUREPASCAL}
|
|---|
| 1061 | BlendRegistry.Add(FID_EMMS, @EMMS_ASM, []);
|
|---|
| 1062 | BlendRegistry.Add(FID_COMBINEREG, @CombineReg_ASM, []);
|
|---|
| 1063 | BlendRegistry.Add(FID_COMBINEMEM, @CombineMem_ASM, []);
|
|---|
| 1064 | BlendRegistry.Add(FID_BLENDREG, @BlendReg_ASM, []);
|
|---|
| 1065 | BlendRegistry.Add(FID_BLENDMEM, @BlendMem_ASM, []);
|
|---|
| 1066 | BlendRegistry.Add(FID_BLENDMEMS, @BlendMems_ASM, []);
|
|---|
| 1067 | BlendRegistry.Add(FID_BLENDREGEX, @BlendRegEx_ASM, []);
|
|---|
| 1068 | BlendRegistry.Add(FID_BLENDMEMEX, @BlendMemEx_ASM, []);
|
|---|
| 1069 | BlendRegistry.Add(FID_BLENDLINE, @BlendLine_ASM, []);
|
|---|
| 1070 | BlendRegistry.Add(FID_BLENDLINE1, @BlendLine1_ASM, []);
|
|---|
| 1071 | {$IFNDEF TARGET_x64}
|
|---|
| 1072 | BlendRegistry.Add(FID_MERGEREG, @MergeReg_ASM, []);
|
|---|
| 1073 | {$ENDIF}
|
|---|
| 1074 | {$IFNDEF OMIT_MMX}
|
|---|
| 1075 | BlendRegistry.Add(FID_EMMS, @EMMS_MMX, [ciMMX]);
|
|---|
| 1076 | BlendRegistry.Add(FID_COMBINEREG, @CombineReg_MMX, [ciMMX]);
|
|---|
| 1077 | BlendRegistry.Add(FID_COMBINEMEM, @CombineMem_MMX, [ciMMX]);
|
|---|
| 1078 | BlendRegistry.Add(FID_COMBINELINE, @CombineLine_MMX, [ciMMX]);
|
|---|
| 1079 | BlendRegistry.Add(FID_BLENDREG, @BlendReg_MMX, [ciMMX]);
|
|---|
| 1080 | BlendRegistry.Add(FID_BLENDMEM, @BlendMem_MMX, [ciMMX]);
|
|---|
| 1081 | BlendRegistry.Add(FID_BLENDREGEX, @BlendRegEx_MMX, [ciMMX]);
|
|---|
| 1082 | BlendRegistry.Add(FID_BLENDMEMEX, @BlendMemEx_MMX, [ciMMX]);
|
|---|
| 1083 | BlendRegistry.Add(FID_BLENDLINE, @BlendLine_MMX, [ciMMX]);
|
|---|
| 1084 | BlendRegistry.Add(FID_BLENDLINEEX, @BlendLineEx_MMX, [ciMMX]);
|
|---|
| 1085 | BlendRegistry.Add(FID_COLORMAX, @ColorMax_EMMX, [ciEMMX]);
|
|---|
| 1086 | BlendRegistry.Add(FID_COLORMIN, @ColorMin_EMMX, [ciEMMX]);
|
|---|
| 1087 | BlendRegistry.Add(FID_COLORADD, @ColorAdd_MMX, [ciMMX]);
|
|---|
| 1088 | BlendRegistry.Add(FID_COLORSUB, @ColorSub_MMX, [ciMMX]);
|
|---|
| 1089 | BlendRegistry.Add(FID_COLORMODULATE, @ColorModulate_MMX, [ciMMX]);
|
|---|
| 1090 | BlendRegistry.Add(FID_COLORDIFFERENCE, @ColorDifference_MMX, [ciMMX]);
|
|---|
| 1091 | BlendRegistry.Add(FID_COLOREXCLUSION, @ColorExclusion_MMX, [ciMMX]);
|
|---|
| 1092 | BlendRegistry.Add(FID_COLORSCALE, @ColorScale_MMX, [ciMMX]);
|
|---|
| 1093 | BlendRegistry.Add(FID_LIGHTEN, @LightenReg_MMX, [ciMMX]);
|
|---|
| 1094 | BlendRegistry.Add(FID_BLENDREGRGB, @BlendRegRGB_MMX, [ciMMX]);
|
|---|
| 1095 | BlendRegistry.Add(FID_BLENDMEMRGB, @BlendMemRGB_MMX, [ciMMX]);
|
|---|
| 1096 | {$ENDIF}
|
|---|
| 1097 | {$IFNDEF OMIT_SSE2}
|
|---|
| 1098 | BlendRegistry.Add(FID_EMMS, @EMMS_SSE2, [ciSSE2]);
|
|---|
| 1099 | BlendRegistry.Add(FID_MERGEREG, @MergeReg_SSE2, [ciSSE2]);
|
|---|
| 1100 | BlendRegistry.Add(FID_COMBINEREG, @CombineReg_SSE2, [ciSSE2]);
|
|---|
| 1101 | BlendRegistry.Add(FID_COMBINEMEM, @CombineMem_SSE2, [ciSSE2]);
|
|---|
| 1102 | BlendRegistry.Add(FID_COMBINELINE, @CombineLine_SSE2, [ciSSE2]);
|
|---|
| 1103 | BlendRegistry.Add(FID_BLENDREG, @BlendReg_SSE2, [ciSSE2]);
|
|---|
| 1104 | BlendRegistry.Add(FID_BLENDMEM, @BlendMem_SSE2, [ciSSE2]);
|
|---|
| 1105 | BlendRegistry.Add(FID_BLENDMEMS, @BlendMems_SSE2, [ciSSE2]);
|
|---|
| 1106 | BlendRegistry.Add(FID_BLENDMEMEX, @BlendMemEx_SSE2, [ciSSE2]);
|
|---|
| 1107 | BlendRegistry.Add(FID_BLENDLINE, @BlendLine_SSE2, [ciSSE2]);
|
|---|
| 1108 | BlendRegistry.Add(FID_BLENDLINEEX, @BlendLineEx_SSE2, [ciSSE2]);
|
|---|
| 1109 | BlendRegistry.Add(FID_BLENDREGEX, @BlendRegEx_SSE2, [ciSSE2]);
|
|---|
| 1110 | BlendRegistry.Add(FID_COLORMAX, @ColorMax_SSE2, [ciSSE2]);
|
|---|
| 1111 | BlendRegistry.Add(FID_COLORMIN, @ColorMin_SSE2, [ciSSE2]);
|
|---|
| 1112 | BlendRegistry.Add(FID_COLORADD, @ColorAdd_SSE2, [ciSSE2]);
|
|---|
| 1113 | BlendRegistry.Add(FID_COLORSUB, @ColorSub_SSE2, [ciSSE2]);
|
|---|
| 1114 | BlendRegistry.Add(FID_COLORMODULATE, @ColorModulate_SSE2, [ciSSE2]);
|
|---|
| 1115 | BlendRegistry.Add(FID_COLORDIFFERENCE, @ColorDifference_SSE2, [ciSSE2]);
|
|---|
| 1116 | BlendRegistry.Add(FID_COLOREXCLUSION, @ColorExclusion_SSE2, [ciSSE2]);
|
|---|
| 1117 | BlendRegistry.Add(FID_COLORSCALE, @ColorScale_SSE2, [ciSSE2]);
|
|---|
| 1118 | BlendRegistry.Add(FID_LIGHTEN, @LightenReg_SSE2, [ciSSE]);
|
|---|
| 1119 | BlendRegistry.Add(FID_BLENDREGRGB, @BlendRegRGB_SSE2, [ciSSE2]);
|
|---|
| 1120 | BlendRegistry.Add(FID_BLENDMEMRGB, @BlendMemRGB_SSE2, [ciSSE2]);
|
|---|
| 1121 | {$IFDEF TEST_BLENDMEMRGB128SSE4}
|
|---|
| 1122 | BlendRegistry.Add(FID_BLENDMEMRGB128, @BlendMemRGB128_SSE4, [ciSSE2]);
|
|---|
| 1123 | {$ENDIF}
|
|---|
| 1124 | {$ENDIF}
|
|---|
| 1125 | {$ENDIF}
|
|---|
| 1126 |
|
|---|
| 1127 | BlendRegistry.RebindAll;
|
|---|
| 1128 | end;
|
|---|
| 1129 |
|
|---|
| 1130 | initialization
|
|---|
| 1131 | BlendColorAdd := BlendColorAdd_Pas;
|
|---|
| 1132 |
|
|---|
| 1133 | RegisterBindings;
|
|---|
| 1134 | MakeMergeTables;
|
|---|
| 1135 |
|
|---|
| 1136 | {$IFNDEF PUREPASCAL}
|
|---|
| 1137 | MMX_ACTIVE := (ciMMX in CPUFeatures);
|
|---|
| 1138 | if [ciMMX, ciSSE2] * CPUFeatures <> [] then
|
|---|
| 1139 | GenAlphaTable;
|
|---|
| 1140 | {$ELSE}
|
|---|
| 1141 | MMX_ACTIVE := False;
|
|---|
| 1142 | {$ENDIF}
|
|---|
| 1143 |
|
|---|
| 1144 | finalization
|
|---|
| 1145 | {$IFNDEF PUREPASCAL}
|
|---|
| 1146 | if [ciMMX, ciSSE2] * CPUFeatures <> [] then
|
|---|
| 1147 | FreeAlphaTable;
|
|---|
| 1148 | {$ENDIF}
|
|---|
| 1149 |
|
|---|
| 1150 | end.
|
|---|