Ignore:
Timestamp:
Dec 22, 2016, 8:49:19 PM (7 years ago)
Author:
chronos
Message:
  • Modified: Updated BGRABitmap package.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • GraphicTest/Packages/bgrabitmap/bgragradientscanner.pas

    r472 r494  
    1616  private
    1717    FColor1,FColor2: TBGRAPixel;
     18    ec1,ec2: TExpandedPixel;
    1819  public
    1920    constructor Create(Color1,Color2: TBGRAPixel);
    2021    function GetColorAt(position: integer): TBGRAPixel; override;
    2122    function GetColorAtF(position: single): TBGRAPixel; override;
     23    function GetExpandedColorAt(position: integer): TExpandedPixel; override;
     24    function GetExpandedColorAtF(position: single): TExpandedPixel; override;
    2225    function GetAverageColor: TBGRAPixel; override;
    2326    function GetMonochrome: boolean; override;
     
    3538    function GetColorAtF(position: single): TBGRAPixel; override;
    3639    function GetAverageColor: TBGRAPixel; override;
     40    function GetExpandedColorAt(position: integer): TExpandedPixel; override;
     41    function GetExpandedColorAtF(position: single): TExpandedPixel; override;
     42    function GetAverageExpandedColor: TExpandedPixel; override;
    3743    function GetMonochrome: boolean; override;
    3844  end;
     
    4652  private
    4753    FColor1,FColor2: TBGRAPixel;
     54    ec1,ec2: TExpandedPixel;
    4855    hsla1,hsla2: THSLAPixel;
    4956    hue1,hue2: longword;
    5057    FOptions: THueGradientOptions;
    5158    procedure Init(c1,c2: THSLAPixel; AOptions: THueGradientOptions);
     59    function GetColorNoBoundCheck(position: integer): THSLAPixel;
    5260  public
    5361    constructor Create(Color1,Color2: TBGRAPixel; options: THueGradientOptions); overload;
     
    5765    function GetColorAtF(position: single): TBGRAPixel; override;
    5866    function GetAverageColor: TBGRAPixel; override;
     67    function GetExpandedColorAt(position: integer): TExpandedPixel; override;
     68    function GetExpandedColorAtF(position: single): TExpandedPixel; override;
     69    function GetAverageExpandedColor: TExpandedPixel; override;
    5970    function GetMonochrome: boolean; override;
    6071  end;
     72
     73  TGradientInterpolationFunction = function(t: single): single of object;
    6174
    6275  { TBGRAMultiGradient }
     
    6982    FEColors: array of TExpandedPixel;
    7083    FCycle: Boolean;
     84    FInterpolationFunction: TGradientInterpolationFunction;
    7185    procedure Init(Colors: array of TBGRAPixel; Positions0To1: array of single; AGammaCorrection, ACycle: boolean);
    7286  public
    7387    GammaCorrection: boolean;
     88    function CosineInterpolation(t: single): single;
     89    function HalfCosineInterpolation(t: single): single;
    7490    constructor Create(Colors: array of TBGRAPixel; Positions0To1: array of single; AGammaCorrection: boolean; ACycle: boolean = false);
    7591    function GetColorAt(position: integer): TBGRAPixel; override;
     92    function GetExpandedColorAt(position: integer): TExpandedPixel; override;
    7693    function GetAverageColor: TBGRAPixel; override;
    7794    function GetMonochrome: boolean; override;
     95    property InterpolationFunction: TGradientInterpolationFunction read FInterpolationFunction write FInterpolationFunction;
    7896  end;
    7997
     
    88106    len,aFactor,aFactorF: single;
    89107    mergedColor: TBGRAPixel;
     108    mergedExpandedColor: TExpandedPixel;
    90109    FGradient: TBGRACustomGradient;
    91110    FGradientOwner: boolean;
    92111    FHorizColor: TBGRAPixel;
     112    FHorizExpandedColor: TExpandedPixel;
    93113    FVertical: boolean;
    94114    FDotProduct,FDotProductPerp: Single;
     
    96116    procedure InitScanInline(x,y: integer);
    97117    function ScanNextInline: TBGRAPixel; inline;
     118    function ScanNextExpandedInline: TExpandedPixel; inline;
    98119  public
    99120    constructor Create(c1, c2: TBGRAPixel; gtype: TGradientType; o1, o2: TPointF;
     
    103124    procedure ScanMoveTo(X, Y: Integer); override;
    104125    function ScanNextPixel: TBGRAPixel; override;
     126    function ScanNextExpandedPixel: TExpandedPixel; override;
    105127    function ScanAt(X, Y: Single): TBGRAPixel; override;
     128    function ScanAtExpanded(X, Y: Single): TExpandedPixel; override;
    106129    procedure ScanPutPixels(pdest: PBGRAPixel; count: integer; mode: TDrawMode); override;
    107130    function IsScanPutPixelsDefined: boolean; override;
     
    140163    function ScanAt(X,Y: Single): TBGRAPixel; override;
    141164    function ScanNextPixel: TBGRAPixel; override;
     165    function ScanNextExpandedPixel: TExpandedPixel; override;
    142166  end;
    143167
     
    151175    FScanNext : TScanNextPixelFunction;
    152176    FScanAt : TScanAtFunction;
     177    FMemMask: packed array of TBGRAPixel;
    153178  public
    154179    constructor Create(AMask: TBGRACustomBitmap; AOffset: TPoint; ASolidColor: TBGRAPixel);
     
    172197    FMaskScanAt,FTextureScanAt : TScanAtFunction;
    173198    FGlobalOpacity: Byte;
     199    FMemMask, FMemTex: packed array of TBGRAPixel;
    174200  public
    175201    constructor Create(AMask: TBGRACustomBitmap; AOffset: TPoint; ATexture: IBGRAScanner; AGlobalOpacity: Byte = 255);
     
    190216      FScanNext : TScanNextPixelFunction;
    191217      FScanAt : TScanAtFunction;
     218      FMemTex: packed array of TBGRAPixel;
    192219  public
    193220    constructor Create(ATexture: IBGRAScanner; AGlobalOpacity: Byte = 255);
     
    202229implementation
    203230
    204 uses BGRABlend;
     231uses BGRABlend, Math;
    205232
    206233{ TBGRAConstantScanner }
     
    247274  FColor1 := HSLAToBGRA(c1);
    248275  FColor2 := HSLAToBGRA(c2);
     276  ec1 := GammaExpansion(FColor1);
     277  ec2 := GammaExpansion(FColor2);
    249278  FOptions:= AOptions;
    250279  if (hgoLightnessCorrection in AOptions) then
     
    276305end;
    277306
     307function TBGRAHueGradient.GetColorNoBoundCheck(position: integer): THSLAPixel;
     308var b,b2: LongWord;
     309begin
     310  b      := position shr 2;
     311  b2     := 16384-b;
     312  result.hue := ((hue1 * b2 + hue2 * b + 8191) shr 14) and $ffff;
     313  result.saturation := (hsla1.saturation * b2 + hsla2.saturation * b + 8191) shr 14;
     314  result.lightness := (hsla1.lightness * b2 + hsla2.lightness * b + 8191) shr 14;
     315  result.alpha := (hsla1.alpha * b2 + hsla2.alpha * b + 8191) shr 14;
     316  if hgoLightnessCorrection in FOptions then
     317  begin
     318    if not (hgoHueCorrection in FOptions) then
     319      result.hue := HtoG(result.hue);
     320  end else
     321  begin
     322    if hgoHueCorrection in FOptions then
     323      result.hue := GtoH(result.hue);
     324  end;
     325end;
     326
    278327constructor TBGRAHueGradient.Create(Color1, Color2: TBGRAPixel;options: THueGradientOptions);
    279328begin
     
    293342
    294343function TBGRAHueGradient.GetColorAt(position: integer): TBGRAPixel;
    295 var b,b2: cardinal;
    296     interm: THSLAPixel;
     344var interm: THSLAPixel;
    297345begin
    298346  if hgoRepeat in FOptions then
     
    317365    end;
    318366  end;
    319   b      := position shr 2;
    320   b2     := 16384-b;
    321   interm.hue := ((hue1 * b2 + hue2 * b + 8191) shr 14) and $ffff;
    322   interm.saturation := (hsla1.saturation * b2 + hsla2.saturation * b + 8191) shr 14;
    323   interm.lightness := (hsla1.lightness * b2 + hsla2.lightness * b + 8191) shr 14;
    324   interm.alpha := (hsla1.alpha * b2 + hsla2.alpha * b + 8191) shr 14;
     367  interm := GetColorNoBoundCheck(position);
    325368  if hgoLightnessCorrection in FOptions then
    326   begin
    327     if not (hgoHueCorrection in FOptions) then
    328       interm.hue := HtoG(interm.hue);
    329     result := GSBAToBGRA(interm);
    330   end else
    331   begin
    332     if hgoHueCorrection in FOptions then
    333       interm.hue := GtoH(interm.hue);
     369    result := GSBAToBGRA(interm)
     370  else
    334371    result := HSLAToBGRA(interm);
    335   end;
    336372end;
    337373
    338374function TBGRAHueGradient.GetColorAtF(position: single): TBGRAPixel;
    339 var b,b2: cardinal;
    340     interm: THSLAPixel;
     375var interm: THSLAPixel;
    341376begin
    342377  if hgoRepeat in FOptions then
     
    361396    end;
    362397  end;
    363   b      := round(position*16384);
    364   b2     := 16384-b;
    365   interm.hue := ((hue1 * b2 + hue2 * b + 8191) shr 14) and $ffff;
    366   interm.saturation := (hsla1.saturation * b2 + hsla2.saturation * b + 8191) shr 14;
    367   interm.lightness := (hsla1.lightness * b2 + hsla2.lightness * b + 8191) shr 14;
    368   interm.alpha := (hsla1.alpha * b2 + hsla2.alpha * b + 8191) shr 14;
     398  interm := GetColorNoBoundCheck(round(position*65536));
    369399  if hgoLightnessCorrection in FOptions then
    370   begin
    371     if not (hgoHueCorrection in FOptions) then
    372       interm.hue := HtoG(interm.hue);
    373     result := GSBAToBGRA(interm);
    374   end else
    375   begin
    376     if hgoHueCorrection in FOptions then
    377       interm.hue := GtoH(interm.hue);
     400    result := GSBAToBGRA(interm)
     401  else
    378402    result := HSLAToBGRA(interm);
    379   end;
    380403end;
    381404
     
    383406begin
    384407  Result:= GetColorAt(32768);
     408end;
     409
     410function TBGRAHueGradient.GetExpandedColorAt(position: integer): TExpandedPixel;
     411var interm: THSLAPixel;
     412begin
     413  if hgoRepeat in FOptions then
     414  begin
     415    position := position and $ffff;
     416    if position = 0 then
     417    begin
     418      result := ec1;
     419      exit;
     420    end;
     421  end else
     422  begin
     423    if position <= 0 then
     424    begin
     425      result := ec1;
     426      exit
     427    end else
     428    if position >= 65536 then
     429    begin
     430      result := ec2;
     431      exit
     432    end;
     433  end;
     434  interm := GetColorNoBoundCheck(position);
     435  if hgoLightnessCorrection in FOptions then
     436    result := GSBAToExpanded(interm)
     437  else
     438    result := HSLAToExpanded(interm);
     439end;
     440
     441function TBGRAHueGradient.GetExpandedColorAtF(position: single): TExpandedPixel;
     442var interm: THSLAPixel;
     443begin
     444  if hgoRepeat in FOptions then
     445  begin
     446    position := frac(position);
     447    if position = 0 then
     448    begin
     449      result := ec1;
     450      exit;
     451    end;
     452  end else
     453  begin
     454    if position <= 0 then
     455    begin
     456      result := ec1;
     457      exit;
     458    end else
     459    if position >= 1 then
     460    begin
     461      result := ec2;
     462      exit
     463    end;
     464  end;
     465  interm := GetColorNoBoundCheck(round(position*65536));
     466  if hgoLightnessCorrection in FOptions then
     467    result := GSBAToExpanded(interm)
     468  else
     469    result := HSLAToExpanded(interm);
     470end;
     471
     472function TBGRAHueGradient.GetAverageExpandedColor: TExpandedPixel;
     473begin
     474  Result:= GetExpandedColorAt(32768);
    385475end;
    386476
     
    417507end;
    418508
     509function TBGRAMultiGradient.CosineInterpolation(t: single): single;
     510begin
     511  result := (1-cos(t*Pi))*0.5;
     512end;
     513
     514function TBGRAMultiGradient.HalfCosineInterpolation(t: single): single;
     515begin
     516  result := (1-cos(t*Pi))*0.25 + t*0.5;
     517end;
     518
    419519constructor TBGRAMultiGradient.Create(Colors: array of TBGRAPixel;
    420520  Positions0To1: array of single; AGammaCorrection: boolean; ACycle: boolean);
     
    424524
    425525function TBGRAMultiGradient.GetColorAt(position: integer): TBGRAPixel;
    426 var i: integer;
     526var i: NativeInt;
    427527    ec: TExpandedPixel;
     528    curPos,posDiff: NativeInt;
    428529begin
    429530  if FCycle then
     
    435536  begin
    436537    i := 0;
    437     while (i < high(FPositions)) and (position > FPositions[i+1]) do
     538    while (i < high(FPositions)-1) and (position >= FPositions[i+1]) do
    438539      inc(i);
    439540
    440     if Position = FPositions[i+1] then
    441       result := FColors[i+1]
     541    if Position = FPositions[i] then
     542      result := FColors[i]
    442543    else
    443     if GammaCorrection then
    444     begin
    445       ec.red := FEColors[i].red + (position-FPositions[i])*(FEColors[i+1].red-FEColors[i].red) div (FPositions[i+1]-FPositions[i]);
    446       ec.green := FEColors[i].green + (position-FPositions[i])*(FEColors[i+1].green-FEColors[i].green) div (FPositions[i+1]-FPositions[i]);
    447       ec.blue := FEColors[i].blue + (position-FPositions[i])*(FEColors[i+1].blue-FEColors[i].blue) div (FPositions[i+1]-FPositions[i]);
    448       ec.alpha := FEColors[i].alpha + (position-FPositions[i])*(FEColors[i+1].alpha-FEColors[i].alpha) div (FPositions[i+1]-FPositions[i]);
    449       result := GammaCompression(ec);
    450     end else
    451     begin
    452       result.red := FColors[i].red + (position-FPositions[i])*(FColors[i+1].red-FColors[i].red) div (FPositions[i+1]-FPositions[i]);
    453       result.green := FColors[i].green + (position-FPositions[i])*(FColors[i+1].green-FColors[i].green) div (FPositions[i+1]-FPositions[i]);
    454       result.blue := FColors[i].blue + (position-FPositions[i])*(FColors[i+1].blue-FColors[i].blue) div (FPositions[i+1]-FPositions[i]);
    455       result.alpha := FColors[i].alpha + (position-FPositions[i])*(FColors[i+1].alpha-FColors[i].alpha) div (FPositions[i+1]-FPositions[i]);
     544    begin
     545      curPos := position-FPositions[i];
     546      posDiff := FPositions[i+1]-FPositions[i];
     547      if FInterpolationFunction <> nil then
     548      begin
     549        curPos := round(FInterpolationFunction(curPos/posDiff)*65536);
     550        posDiff := 65536;
     551      end;
     552      if GammaCorrection then
     553      begin
     554        if FEColors[i+1].red < FEColors[i].red then
     555          ec.red := FEColors[i].red - NativeUInt(curPos)*NativeUInt(FEColors[i].red-FEColors[i+1].red) div NativeUInt(posDiff) else
     556          ec.red := FEColors[i].red + NativeUInt(curPos)*NativeUInt(FEColors[i+1].red-FEColors[i].red) div NativeUInt(posDiff);
     557        if FEColors[i+1].green < FEColors[i].green then
     558          ec.green := FEColors[i].green - NativeUInt(curPos)*NativeUInt(FEColors[i].green-FEColors[i+1].green) div NativeUInt(posDiff) else
     559          ec.green := FEColors[i].green + NativeUInt(curPos)*NativeUInt(FEColors[i+1].green-FEColors[i].green) div NativeUInt(posDiff);
     560        if FEColors[i+1].blue < FEColors[i].blue then
     561          ec.blue := FEColors[i].blue - NativeUInt(curPos)*NativeUInt(FEColors[i].blue-FEColors[i+1].blue) div NativeUInt(posDiff) else
     562          ec.blue := FEColors[i].blue + NativeUInt(curPos)*NativeUInt(FEColors[i+1].blue-FEColors[i].blue) div NativeUInt(posDiff);
     563        if FEColors[i+1].alpha < FEColors[i].alpha then
     564          ec.alpha := FEColors[i].alpha - NativeUInt(curPos)*NativeUInt(FEColors[i].alpha-FEColors[i+1].alpha) div NativeUInt(posDiff) else
     565          ec.alpha := FEColors[i].alpha + NativeUInt(curPos)*NativeUInt(FEColors[i+1].alpha-FEColors[i].alpha) div NativeUInt(posDiff);
     566        result := GammaCompression(ec);
     567      end else
     568      begin
     569        result.red := FColors[i].red + (curPos)*(FColors[i+1].red-FColors[i].red) div (posDiff);
     570        result.green := FColors[i].green + (curPos)*(FColors[i+1].green-FColors[i].green) div (posDiff);
     571        result.blue := FColors[i].blue + (curPos)*(FColors[i+1].blue-FColors[i].blue) div (posDiff);
     572        result.alpha := FColors[i].alpha + (curPos)*(FColors[i+1].alpha-FColors[i].alpha) div (posDiff);
     573      end;
     574    end;
     575  end;
     576end;
     577
     578function TBGRAMultiGradient.GetExpandedColorAt(position: integer
     579  ): TExpandedPixel;
     580var i: NativeInt;
     581    curPos,posDiff: NativeInt;
     582    rw,gw,bw: NativeUInt;
     583begin
     584  if FCycle then
     585    position := (position-FPositions[0]) mod (FPositions[high(FPositions)] - FPositions[0]) + FPositions[0];
     586  if position <= FPositions[0] then
     587    result := FEColors[0] else
     588  if position >= FPositions[high(FPositions)] then
     589    result := FEColors[high(FColors)] else
     590  begin
     591    i := 0;
     592    while (i < high(FPositions)-1) and (position >= FPositions[i+1]) do
     593      inc(i);
     594
     595    if Position = FPositions[i] then
     596      result := FEColors[i]
     597    else
     598    begin
     599      curPos := position-FPositions[i];
     600      posDiff := FPositions[i+1]-FPositions[i];
     601      if FInterpolationFunction <> nil then
     602      begin
     603        curPos := round(FInterpolationFunction(curPos/posDiff)*65536);
     604        posDiff := 65536;
     605      end;
     606      if GammaCorrection then
     607      begin
     608        if FEColors[i+1].red < FEColors[i].red then
     609          result.red := FEColors[i].red - NativeUInt(curPos)*NativeUInt(FEColors[i].red-FEColors[i+1].red) div NativeUInt(posDiff) else
     610          result.red := FEColors[i].red + NativeUInt(curPos)*NativeUInt(FEColors[i+1].red-FEColors[i].red) div NativeUInt(posDiff);
     611        if FEColors[i+1].green < FEColors[i].green then
     612          result.green := FEColors[i].green - NativeUInt(curPos)*NativeUInt(FEColors[i].green-FEColors[i+1].green) div NativeUInt(posDiff) else
     613          result.green := FEColors[i].green + NativeUInt(curPos)*NativeUInt(FEColors[i+1].green-FEColors[i].green) div NativeUInt(posDiff);
     614        if FEColors[i+1].blue < FEColors[i].blue then
     615          result.blue := FEColors[i].blue - NativeUInt(curPos)*NativeUInt(FEColors[i].blue-FEColors[i+1].blue) div NativeUInt(posDiff) else
     616          result.blue := FEColors[i].blue + NativeUInt(curPos)*NativeUInt(FEColors[i+1].blue-FEColors[i].blue) div NativeUInt(posDiff);
     617        if FEColors[i+1].alpha < FEColors[i].alpha then
     618          result.alpha := FEColors[i].alpha - NativeUInt(curPos)*NativeUInt(FEColors[i].alpha-FEColors[i+1].alpha) div NativeUInt(posDiff) else
     619          result.alpha := FEColors[i].alpha + NativeUInt(curPos)*NativeUInt(FEColors[i+1].alpha-FEColors[i].alpha) div NativeUInt(posDiff);
     620      end else
     621      begin
     622        rw := NativeInt(FColors[i].red shl 8) + (((curPos) shl 8)*(FColors[i+1].red-FColors[i].red)) div (posDiff);
     623        gw := NativeInt(FColors[i].green shl 8) + (((curPos) shl 8)*(FColors[i+1].green-FColors[i].green)) div (posDiff);
     624        bw := NativeInt(FColors[i].blue shl 8) + (((curPos) shl 8)*(FColors[i+1].blue-FColors[i].blue)) div (posDiff);
     625
     626        if rw >= $ff00 then result.red := $ffff
     627        else result.red := (GammaExpansionTab[rw shr 8]*NativeUInt(255 - (rw and 255)) + GammaExpansionTab[(rw shr 8)+1]*NativeUInt(rw and 255)) shr 8;
     628        if gw >= $ff00 then result.green := $ffff
     629        else result.green := (GammaExpansionTab[gw shr 8]*NativeUInt(255 - (gw and 255)) + GammaExpansionTab[(gw shr 8)+1]*NativeUInt(gw and 255)) shr 8;
     630        if bw >= $ff00 then result.blue := $ffff
     631        else result.blue := (GammaExpansionTab[bw shr 8]*NativeUInt(255 - (bw and 255)) + GammaExpansionTab[(bw shr 8)+1]*NativeUInt(bw and 255)) shr 8;
     632        result.alpha := NativeInt(FColors[i].alpha shl 8) + (((curPos) shl 8)*(FColors[i+1].alpha-FColors[i].alpha)) div (posDiff);
     633        result.alpha := result.alpha + (result.alpha shr 8);
     634      end;
    456635    end;
    457636  end;
     
    544723end;
    545724
     725function TBGRASimpleGradientWithGammaCorrection.GetExpandedColorAt(
     726  position: integer): TExpandedPixel;
     727var b,b2: cardinal;
     728begin
     729  if position <= 0 then
     730    result := ec1 else
     731  if position >= 65536 then
     732    result := ec2 else
     733  begin
     734    b      := position;
     735    b2     := 65536-b;
     736    result.red := (ec1.red * b2 + ec2.red * b + 32767) shr 16;
     737    result.green := (ec1.green * b2 + ec2.green * b + 32767) shr 16;
     738    result.blue := (ec1.blue * b2 + ec2.blue * b + 32767) shr 16;
     739    result.alpha := (ec1.alpha * b2 + ec2.alpha * b + 32767) shr 16;
     740  end;
     741end;
     742
     743function TBGRASimpleGradientWithGammaCorrection.GetExpandedColorAtF(
     744  position: single): TExpandedPixel;
     745var b,b2: cardinal;
     746begin
     747  if position <= 0 then
     748    result := ec1 else
     749  if position >= 1 then
     750    result := ec2 else
     751  begin
     752    b      := round(position*65536);
     753    b2     := 65536-b;
     754    result.red := (ec1.red * b2 + ec2.red * b + 32767) shr 16;
     755    result.green := (ec1.green * b2 + ec2.green * b + 32767) shr 16;
     756    result.blue := (ec1.blue * b2 + ec2.blue * b + 32767) shr 16;
     757    result.alpha := (ec1.alpha * b2 + ec2.alpha * b + 32767) shr 16;
     758  end;
     759end;
     760
     761function TBGRASimpleGradientWithGammaCorrection.GetAverageExpandedColor: TExpandedPixel;
     762begin
     763  result := MergeBGRA(ec1,ec2);
     764end;
     765
    546766function TBGRASimpleGradientWithGammaCorrection.GetMonochrome: boolean;
    547767begin
     
    556776  FColor1 := Color1;
    557777  FColor2 := Color2;
     778  ec1 := GammaExpansion(Color1);
     779  ec2 := GammaExpansion(Color2);
    558780end;
    559781
     
    577799
    578800function TBGRASimpleGradientWithoutGammaCorrection.GetColorAtF(position: single): TBGRAPixel;
    579 var b,b2: cardinal;
    580801begin
    581802  if position <= 0 then
     
    583804  if position >= 1 then
    584805    result := FColor2 else
    585   begin
    586     b      := round(position*1024);
     806    result := GetColorAt(round(position*65536));
     807end;
     808
     809function TBGRASimpleGradientWithoutGammaCorrection.GetExpandedColorAt(
     810  position: integer): TExpandedPixel;
     811var b,b2: cardinal;
     812    rw,gw,bw: word;
     813begin
     814  if position <= 0 then
     815    result := ec1 else
     816  if position >= 65536 then
     817    result := ec2 else
     818  begin
     819    b      := position shr 6;
    587820    b2     := 1024-b;
    588     result.red  := (FColor1.red * b2 + FColor2.red * b + 511) shr 10;
    589     result.green := (FColor1.green * b2 + FColor2.green * b + 511) shr 10;
    590     result.blue := (FColor1.blue * b2 + FColor2.blue * b + 511) shr 10;
    591     result.alpha := (FColor1.alpha * b2 + FColor2.alpha * b + 511) shr 10;
    592   end;
     821    rw  := (FColor1.red * b2 + FColor2.red * b + 511) shr 2;
     822    gw := (FColor1.green * b2 + FColor2.green * b + 511) shr 2;
     823    bw := (FColor1.blue * b2 + FColor2.blue * b + 511) shr 2;
     824
     825    result.red := (GammaExpansionTab[rw shr 8]*NativeUInt(255 - (rw and 255)) + GammaExpansionTab[(rw shr 8)+1]*NativeUInt(rw and 255)) shr 8;
     826    result.green := (GammaExpansionTab[gw shr 8]*NativeUInt(255 - (gw and 255)) + GammaExpansionTab[(gw shr 8)+1]*NativeUInt(gw and 255)) shr 8;
     827    result.blue := (GammaExpansionTab[bw shr 8]*NativeUInt(255 - (bw and 255)) + GammaExpansionTab[(bw shr 8)+1]*NativeUInt(bw and 255)) shr 8;
     828    result.alpha := (FColor1.alpha * b2 + FColor2.alpha * b + 511) shr 2;
     829  end;
     830end;
     831
     832function TBGRASimpleGradientWithoutGammaCorrection.GetExpandedColorAtF(
     833  position: single): TExpandedPixel;
     834begin
     835  if position <= 0 then
     836    result := ec1 else
     837  if position >= 1 then
     838    result := ec2 else
     839    result := GetExpandedColorAt(round(position*65536));
    593840end;
    594841
     
    675922end;
    676923
     924function TBGRAGradientTriangleScanner.ScanNextExpandedPixel: TExpandedPixel;
     925var r,g,b,a: int64;
     926begin
     927  r := round(FCurColor[1]);
     928  g := round(FCurColor[2]);
     929  b := round(FCurColor[3]);
     930  a := round(FCurColor[4]);
     931  if r > 65535 then r := 65535 else
     932  if r < 0 then r := 0;
     933  if g > 65535 then g := 65535 else
     934  if g < 0 then g := 0;
     935  if b > 65535 then b := 65535 else
     936  if b < 0 then b := 0;
     937  if a > 65535 then a := 65535 else
     938  if a < 0 then a := 0;
     939  result.red := r;
     940  result.green := g;
     941  result.blue := b;
     942  result.alpha := a;
     943  FCurColor += FStep;
     944end;
     945
    677946{ TBGRAGradientScanner }
    678947
     
    704973  FVertical := (((gtype =gtLinear) or (gtype=gtReflected)) and (o1.x=o2.x)) or FGradient.Monochrome;
    705974  mergedColor := FGradient.GetAverageColor;
     975  mergedExpandedColor := FGradient.GetAverageExpandedColor;
    706976end;
    707977
     
    7631033end;
    7641034
     1035function TBGRAGradientScanner.ScanNextExpandedInline: TExpandedPixel;
     1036var
     1037  a,a2: single;
     1038  ai: integer;
     1039begin
     1040  if FGradientType >= gtDiamond then
     1041  begin
     1042    if FGradientType = gtRadial then
     1043    begin
     1044      a := sqrt(sqr(FDotProduct) + sqr(FDotProductPerp));
     1045      FDotProduct += u.x;
     1046      FDotProductPerp += u.y;
     1047    end else
     1048    begin
     1049      a   := abs(FDotProduct);
     1050      a2  := abs(FDotProductPerp);
     1051      if a2 > a then a := a2;
     1052      FDotProduct += u.x;
     1053      FDotProductPerp += u.y;
     1054    end;
     1055  end else
     1056  if FGradientType = gtReflected then
     1057  begin
     1058    a := abs(FDotProduct);
     1059    FDotProduct += u.x;
     1060  end else
     1061  begin
     1062    a := FDotProduct;
     1063    FDotProduct += u.x;
     1064  end;
     1065
     1066  if FSinus then
     1067  begin
     1068    a *= aFactor;
     1069    if a <= low(int64) then
     1070      result := FGradient.GetAverageExpandedColor
     1071    else
     1072    if a >= high(int64) then
     1073      result := FGradient.GetAverageExpandedColor
     1074    else
     1075    begin
     1076      ai := Sin65536(round(a));
     1077      result := FGradient.GetExpandedColorAt(ai);
     1078    end;
     1079  end else
     1080    result := FGradient.GetExpandedColorAtF(a*aFactorF);
     1081end;
     1082
    7651083constructor TBGRAGradientScanner.Create(c1, c2: TBGRAPixel;
    7661084  gtype: TGradientType; o1, o2: TPointF; gammaColorCorrection: boolean;
     
    8141132  InitScanInline(X,Y);
    8151133  if FVertical then
     1134  begin
    8161135    FHorizColor := ScanNextInline;
     1136    FHorizExpandedColor := ScanNextExpandedInline;
     1137  end;
    8171138end;
    8181139
     
    8231144  else
    8241145    result := ScanNextInline;
     1146end;
     1147
     1148function TBGRAGradientScanner.ScanNextExpandedPixel: TExpandedPixel;
     1149begin
     1150  if FVertical then
     1151    result := FHorizExpandedColor
     1152  else
     1153    result := ScanNextExpandedInline;
    8251154end;
    8261155
     
    8531182  begin
    8541183    a := a*aFactor;
    855     if a <= low(int64) then
    856       result := FGradient.GetAverageColor
    857     else
    858     if a >= high(int64) then
    859       result := FGradient.GetAverageColor
     1184    if (a <= low(int64)) or (a >= high(int64)) then
     1185      result := mergedColor
    8601186    else
    8611187    begin
     
    8651191  end else
    8661192    result := FGradient.GetColorAtF(a*aFactorF);
     1193end;
     1194
     1195function TBGRAGradientScanner.ScanAtExpanded(X, Y: Single): TExpandedPixel;
     1196var p: TPointF;
     1197    a,a2: single;
     1198    ai: integer;
     1199begin
     1200  if len = 0 then
     1201  begin
     1202    result := mergedExpandedColor;
     1203    exit;
     1204  end;
     1205
     1206  p.x := X - FOrigin1.x;
     1207  p.y := Y - FOrigin1.y;
     1208  case FGradientType of
     1209    gtLinear:    a := p.x * u.x + p.y * u.y;
     1210    gtReflected: a := abs(p.x * u.x + p.y * u.y);
     1211    gtDiamond:
     1212        begin
     1213          a   := abs(p.x * u.x + p.y * u.y);
     1214          a2  := abs(p.x * u.y - p.y * u.x);
     1215          if a2 > a then a := a2;
     1216        end;
     1217    gtRadial:    a := sqrt(sqr(p.x * u.x + p.y * u.y) + sqr(p.x * u.y - p.y * u.x));
     1218  end;
     1219
     1220  if FSinus then
     1221  begin
     1222    a := a*aFactor;
     1223    if (a <= low(int64)) or (a >= high(int64)) then
     1224      result := mergedExpandedColor
     1225    else
     1226    begin
     1227      ai := Sin65536(round(a));
     1228      result := FGradient.GetExpandedColorAt(ai);
     1229    end;
     1230  end else
     1231    result := FGradient.GetExpandedColorAtF(a*aFactorF);
    8671232end;
    8681233
     
    9611326var c: TBGRAPixel;
    9621327    alpha: byte;
    963     MemMask, pmask, MemTex, ptex: pbgrapixel;
     1328    pmask, ptex: pbgrapixel;
    9641329
    9651330  function GetNext: TBGRAPixel; inline;
     
    9821347
    9831348begin
    984   getmem(MemMask, count*sizeof(TBGRAPixel));
    985   ScannerPutPixels(FMask,MemMask,count,dmSet);
    986   getmem(MemTex, count*sizeof(TBGRAPixel));
    987   ScannerPutPixels(FTexture,MemTex,count,dmSet);
    988 
    989   pmask := MemMask;
    990   ptex := MemTex;
     1349  if count > length(FMemMask) then setlength(FMemMask, max(length(FMemMask)*2,count));
     1350  if count > length(FMemTex) then setlength(FMemTex, max(length(FMemTex)*2,count));
     1351  ScannerPutPixels(FMask,@FMemMask[0],count,dmSet);
     1352  ScannerPutPixels(FTexture,@FMemTex[0],count,dmSet);
     1353
     1354  pmask := @FMemMask[0];
     1355  ptex := @FMemTex[0];
    9911356
    9921357  if FGlobalOpacity <> 255 then
     
    10711436    end;
    10721437  end;
    1073 
    1074   freemem(MemMask);
    1075   freemem(MemTex);
    10761438end;
    10771439
     
    11251487var c: TBGRAPixel;
    11261488    alpha: byte;
    1127     MemMask, pmask: pbgrapixel;
     1489    pmask: pbgrapixel;
    11281490
    11291491  function GetNext: TBGRAPixel; inline;
     
    11361498
    11371499begin
    1138   getmem(MemMask, count*sizeof(TBGRAPixel));
    1139   ScannerPutPixels(FMask,MemMask,count,dmSet);
    1140 
    1141   pmask := MemMask;
     1500  if count > length(FMemMask) then setlength(FMemMask, max(length(FMemMask)*2,count));
     1501  ScannerPutPixels(FMask,@FMemMask[0],count,dmSet);
     1502
     1503  pmask := @FMemMask[0];
    11421504
    11431505  case mode of
     
    11791541      end;
    11801542  end;
    1181 
    1182   freemem(MemMask);
    11831543end;
    11841544
     
    12291589  mode: TDrawMode);
    12301590var c: TBGRAPixel;
    1231     MemTex, ptex: pbgrapixel;
     1591    ptex: pbgrapixel;
    12321592
    12331593  function GetNext: TBGRAPixel; inline;
     
    12391599
    12401600begin
    1241   getmem(MemTex, count*sizeof(TBGRAPixel));
    1242   ScannerPutPixels(FTexture,MemTex,count,dmSet);
    1243 
    1244   ptex := MemTex;
     1601  if count > length(FMemTex) then setlength(FMemTex, max(length(FMemTex)*2,count));
     1602  ScannerPutPixels(FTexture,@FMemTex[0],count,dmSet);
     1603
     1604  ptex := @FMemTex[0];
    12451605
    12461606  case mode of
     
    12821642      end;
    12831643  end;
    1284 
    1285   freemem(MemTex);
    12861644end;
    12871645
Note: See TracChangeset for help on using the changeset viewer.