2
0

lcvectorialfill.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit LCVectorialFill;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Classes, SysUtils, BGRATransform, BGRAGradientOriginal, BGRABitmap, BGRABitmapTypes,
  7. BGRALayerOriginal;
  8. type
  9. TTextureRepetition = (trNone, trRepeatX, trRepeatY, trRepeatBoth);
  10. TTransparentMode = (tmEnforeAllChannelsZero, tmAlphaZeroOnly, tmNoFill);
  11. TVectorialFillType = (vftNone, vftSolid, vftGradient, vftTexture);
  12. TVectorialFillTypes = set of TVectorialFillType;
  13. TVectorialFill = class;
  14. TCustomVectorialFillDiff = class
  15. procedure Apply(AFill: TVectorialFill); virtual; abstract;
  16. procedure Unapply(AFill: TVectorialFill); virtual; abstract;
  17. function IsIdentity: boolean; virtual; abstract;
  18. function CanAppend(ADiff: TCustomVectorialFillDiff): boolean; virtual; abstract;
  19. procedure Append(ADiff: TCustomVectorialFillDiff); virtual; abstract;
  20. end;
  21. TVectorialFillChangeEvent = procedure(ASender: TObject; var ADiff: TCustomVectorialFillDiff) of object;
  22. { TVectorialFillGradientDiff }
  23. TVectorialFillGradientDiff = class(TCustomVectorialFillDiff)
  24. protected
  25. FGradientDiff: TBGRAGradientOriginalDiff;
  26. public
  27. constructor Create(AGradientDiff: TBGRAGradientOriginalDiff);
  28. destructor Destroy; override;
  29. procedure Apply(AFill: TVectorialFill); override;
  30. procedure Unapply(AFill: TVectorialFill); override;
  31. function IsIdentity: boolean; override;
  32. function CanAppend(ADiff: TCustomVectorialFillDiff): boolean; override;
  33. procedure Append(ADiff: TCustomVectorialFillDiff); override;
  34. end;
  35. { TVectorialFillDiff }
  36. TVectorialFillDiff = class(TCustomVectorialFillDiff)
  37. protected
  38. FStart,FEnd: TVectorialFill;
  39. FTransparentMode: TTransparentMode;
  40. public
  41. constructor Create(AFrom: TVectorialFill);
  42. procedure ComputeDiff(ATo: TVectorialFill);
  43. destructor Destroy; override;
  44. procedure Apply(AFill: TVectorialFill); override;
  45. procedure Unapply(AFill: TVectorialFill); override;
  46. function IsIdentity: boolean; override;
  47. function CanAppend(ADiff: TCustomVectorialFillDiff): boolean; override;
  48. procedure Append(ADiff: TCustomVectorialFillDiff); override;
  49. end;
  50. { TVectorialFill }
  51. TVectorialFill = class
  52. protected
  53. FColor: TBGRAPixel;
  54. FIsSolid: boolean;
  55. FTexture: TBGRABitmap;
  56. FTextureMatrix: TAffineMatrix;
  57. FTextureMatrixBackup: TAffineMatrix;
  58. FTextureOpacity: byte;
  59. FTextureRepetition: TTextureRepetition;
  60. FTextureAverageColor: TBGRAPixel;
  61. FTextureAverageColorComputed: boolean;
  62. FTransparentMode: TTransparentMode;
  63. FGradient: TBGRALayerGradientOriginal;
  64. FOnChange: TVectorialFillChangeEvent;
  65. FOnBeforeChange: TNotifyEvent;
  66. FDiff: TVectorialFillDiff;
  67. procedure GradientChange({%H-}ASender: TObject; {%H-}ABounds: PRectF; var ADiff: TBGRAOriginalDiff);
  68. procedure Init; virtual;
  69. function GetFillType: TVectorialFillType;
  70. function GetIsEditable: boolean;
  71. function GetAverageColor: TBGRAPixel;
  72. procedure SetOnChange(AValue: TVectorialFillChangeEvent);
  73. procedure SetTextureMatrix(AValue: TAffineMatrix);
  74. procedure SetTextureOpacity(AValue: byte);
  75. procedure SetTextureRepetition(AValue: TTextureRepetition);
  76. procedure SetTransparentMode(AValue: TTransparentMode);
  77. procedure InternalClear;
  78. procedure BeginUpdate;
  79. procedure EndUpdate;
  80. procedure NotifyChangeWithoutDiff;
  81. procedure ConfigureTextureEditor(AEditor: TBGRAOriginalEditor);
  82. procedure TextureMoveOrigin({%H-}ASender: TObject; {%H-}APrevCoord,
  83. ANewCoord: TPointF; {%H-}AShift: TShiftState);
  84. procedure TextureMoveXAxis({%H-}ASender: TObject; {%H-}APrevCoord,
  85. ANewCoord: TPointF; AShift: TShiftState);
  86. procedure TextureMoveYAxis({%H-}ASender: TObject; {%H-}APrevCoord,
  87. ANewCoord: TPointF; AShift: TShiftState);
  88. procedure TextureStartMove({%H-}ASender: TObject; {%H-}AIndex: integer;
  89. {%H-}AShift: TShiftState);
  90. public
  91. constructor Create;
  92. procedure Clear;
  93. constructor CreateAsSolid(AColor: TBGRAPixel);
  94. constructor CreateAsTexture(ATexture: TBGRABitmap; AMatrix: TAffineMatrix; AOpacity: byte = 255;
  95. ATextureRepetition: TTextureRepetition = trRepeatBoth);
  96. constructor CreateAsGradient(AGradient: TBGRALayerGradientOriginal; AOwned: boolean);
  97. procedure SetSolid(AColor: TBGRAPixel);
  98. procedure SetTexture(ATexture: TBGRABitmap; AMatrix: TAffineMatrix; AOpacity: byte = 255;
  99. ATextureRepetition: TTextureRepetition = trRepeatBoth);
  100. procedure SetGradient(AGradient: TBGRALayerGradientOriginal; AOwned: boolean);
  101. procedure ConfigureEditor(AEditor: TBGRAOriginalEditor);
  102. function CreateScanner(AMatrix: TAffineMatrix; ADraft: boolean): TBGRACustomScanner;
  103. function IsSlow(AMatrix: TAffineMatrix): boolean;
  104. function IsFullyTransparent: boolean;
  105. procedure Transform(AMatrix: TAffineMatrix);
  106. function Duplicate: TVectorialFill; virtual;
  107. destructor Destroy; override;
  108. function Equals(Obj: TObject): boolean; override;
  109. class function Equal(AFill1, AFill2: TVectorialFill): boolean;
  110. procedure Assign(Obj: TObject);
  111. procedure AssignExceptGeometry(Obj: TObject);
  112. procedure FitGeometry(const ABox: TAffineBox);
  113. procedure ApplyOpacity(AOpacity: Byte);
  114. property FillType: TVectorialFillType read GetFillType;
  115. property IsEditable: boolean read GetIsEditable;
  116. property Gradient: TBGRALayerGradientOriginal read FGradient;
  117. property SolidColor: TBGRAPixel read FColor write SetSolid;
  118. property AverageColor: TBGRAPixel read GetAverageColor;
  119. property Texture: TBGRABitmap read FTexture;
  120. property TextureMatrix: TAffineMatrix read FTextureMatrix write SetTextureMatrix;
  121. property TextureOpacity: byte read FTextureOpacity write SetTextureOpacity;
  122. property TextureRepetition: TTextureRepetition read FTextureRepetition write SetTextureRepetition;
  123. property OnChange: TVectorialFillChangeEvent read FOnChange write SetOnChange;
  124. property OnBeforeChange: TNotifyEvent read FOnBeforeChange write FOnBeforeChange;
  125. property TransparentMode: TTransparentMode read FTransparentMode write SetTransparentMode;
  126. end;
  127. implementation
  128. uses BGRAGradientScanner, BGRABlend, LCResourceString;
  129. { TVectorialFillDiff }
  130. constructor TVectorialFillDiff.Create(AFrom: TVectorialFill);
  131. begin
  132. FStart := TVectorialFill.Create;
  133. FStart.TransparentMode:= AFrom.TransparentMode;
  134. FStart.Assign(AFrom);
  135. end;
  136. procedure TVectorialFillDiff.ComputeDiff(ATo: TVectorialFill);
  137. begin
  138. FEnd := TVectorialFill.Create;
  139. FEnd.TransparentMode := ATo.TransparentMode;
  140. FEnd.Assign(ATo);
  141. end;
  142. destructor TVectorialFillDiff.Destroy;
  143. begin
  144. FStart.Free;
  145. FEnd.Free;
  146. inherited Destroy;
  147. end;
  148. procedure TVectorialFillDiff.Apply(AFill: TVectorialFill);
  149. var
  150. oldChange: TVectorialFillChangeEvent;
  151. begin
  152. oldChange := AFill.OnChange;
  153. AFill.OnChange := nil;
  154. AFill.Assign(FEnd);
  155. AFill.OnChange := oldChange;
  156. AFill.NotifyChangeWithoutDiff;
  157. end;
  158. procedure TVectorialFillDiff.Unapply(AFill: TVectorialFill);
  159. var
  160. oldChange: TVectorialFillChangeEvent;
  161. begin
  162. oldChange := AFill.OnChange;
  163. AFill.OnChange := nil;
  164. AFill.Assign(FStart);
  165. AFill.OnChange := oldChange;
  166. AFill.NotifyChangeWithoutDiff;
  167. end;
  168. function TVectorialFillDiff.IsIdentity: boolean;
  169. begin
  170. result := TVectorialFill.Equal(FStart,FEnd);
  171. end;
  172. function TVectorialFillDiff.CanAppend(ADiff: TCustomVectorialFillDiff
  173. ): boolean;
  174. begin
  175. result := ADiff is TVectorialFillDiff;
  176. end;
  177. procedure TVectorialFillDiff.Append(ADiff: TCustomVectorialFillDiff);
  178. begin
  179. FEnd.Assign((ADiff as TVectorialFillDiff).FEnd);
  180. end;
  181. { TVectorialFillGradientDiff }
  182. constructor TVectorialFillGradientDiff.Create(
  183. AGradientDiff: TBGRAGradientOriginalDiff);
  184. begin
  185. FGradientDiff := AGradientDiff;
  186. end;
  187. destructor TVectorialFillGradientDiff.Destroy;
  188. begin
  189. FGradientDiff.Free;
  190. inherited Destroy;
  191. end;
  192. procedure TVectorialFillGradientDiff.Apply(AFill: TVectorialFill);
  193. begin
  194. if AFill.FillType = vftGradient then
  195. FGradientDiff.Apply(AFill.Gradient);
  196. end;
  197. procedure TVectorialFillGradientDiff.Unapply(AFill: TVectorialFill);
  198. begin
  199. if AFill.FillType = vftGradient then
  200. FGradientDiff.Unapply(AFill.Gradient);
  201. end;
  202. function TVectorialFillGradientDiff.IsIdentity: boolean;
  203. begin
  204. result := false;
  205. end;
  206. function TVectorialFillGradientDiff.CanAppend(ADiff: TCustomVectorialFillDiff): boolean;
  207. begin
  208. result := (ADiff is TVectorialFillGradientDiff) and
  209. FGradientDiff.CanAppend(TVectorialFillGradientDiff(ADiff).FGradientDiff);
  210. end;
  211. procedure TVectorialFillGradientDiff.Append(ADiff: TCustomVectorialFillDiff);
  212. var
  213. nextDiff: TVectorialFillGradientDiff;
  214. begin
  215. nextDiff := ADiff as TVectorialFillGradientDiff;
  216. FGradientDiff.Append(nextDiff.FGradientDiff);
  217. end;
  218. { TVectorialFill }
  219. procedure TVectorialFill.SetOnChange(AValue: TVectorialFillChangeEvent);
  220. begin
  221. if FOnChange=AValue then Exit;
  222. FOnChange:=AValue;
  223. end;
  224. procedure TVectorialFill.SetTextureMatrix(AValue: TAffineMatrix);
  225. begin
  226. if FillType <> vftTexture then raise exception.Create(rsNotTextureFill);
  227. if FTextureMatrix=AValue then Exit;
  228. BeginUpdate;
  229. FTextureMatrix:=AValue;
  230. EndUpdate;
  231. end;
  232. procedure TVectorialFill.SetTextureOpacity(AValue: byte);
  233. begin
  234. if FillType <> vftTexture then raise exception.Create(rsNotTextureFill);
  235. if FTextureOpacity=AValue then Exit;
  236. BeginUpdate;
  237. FTextureOpacity:=AValue;
  238. EndUpdate;
  239. end;
  240. procedure TVectorialFill.InternalClear;
  241. begin
  242. if Assigned(FTexture) then
  243. begin
  244. FTexture.FreeReference;
  245. FTexture := nil;
  246. end;
  247. if Assigned(FGradient) then
  248. begin
  249. FGradient.OnChange := nil;
  250. FreeAndNil(FGradient);
  251. end;
  252. FIsSolid := false;
  253. FColor := BGRAPixelTransparent;
  254. FTextureMatrix := AffineMatrixIdentity;
  255. FTextureRepetition:= trRepeatBoth;
  256. FTextureAverageColorComputed:= false;
  257. end;
  258. procedure TVectorialFill.BeginUpdate;
  259. begin
  260. if Assigned(OnBeforeChange) then
  261. OnBeforeChange(self);
  262. if Assigned(OnChange) and (FDiff = nil) then
  263. FDiff := TVectorialFillDiff.Create(self);
  264. end;
  265. procedure TVectorialFill.EndUpdate;
  266. begin
  267. if Assigned(OnChange) then
  268. begin
  269. if Assigned(FDiff) then
  270. begin
  271. FDiff.ComputeDiff(self);
  272. if not FDiff.IsIdentity then OnChange(self, FDiff);
  273. end
  274. else
  275. OnChange(self, FDiff);
  276. end;
  277. FreeAndNil(FDiff);
  278. end;
  279. procedure TVectorialFill.NotifyChangeWithoutDiff;
  280. var diff: TCustomVectorialFillDiff;
  281. begin
  282. if Assigned(FOnChange) then
  283. begin
  284. diff := nil;
  285. FOnChange(self, diff);
  286. end;
  287. end;
  288. procedure TVectorialFill.ConfigureTextureEditor(AEditor: TBGRAOriginalEditor);
  289. var
  290. origin, xAxisRel, yAxisRel: TPointF;
  291. begin
  292. if Assigned(FTexture) then
  293. begin
  294. origin := PointF(FTextureMatrix[1,3],FTextureMatrix[2,3]);
  295. xAxisRel := PointF(FTextureMatrix[1,1],FTextureMatrix[2,1]);
  296. yAxisRel := PointF(FTextureMatrix[1,2],FTextureMatrix[2,2]);
  297. AEditor.AddPoint(origin, @TextureMoveOrigin, true);
  298. if FTexture.Width > 0 then
  299. AEditor.AddArrow(origin, origin+xAxisRel*FTexture.Width, @TextureMoveXAxis);
  300. if FTexture.Height > 0 then
  301. AEditor.AddArrow(origin, origin+yAxisRel*FTexture.Height, @TextureMoveYAxis);
  302. AEditor.AddStartMoveHandler(@TextureStartMove);
  303. end;
  304. end;
  305. procedure TVectorialFill.TextureMoveOrigin(ASender: TObject; APrevCoord,
  306. ANewCoord: TPointF; AShift: TShiftState);
  307. begin
  308. BeginUpdate;
  309. FTextureMatrix[1,3] := ANewCoord.x;
  310. FTextureMatrix[2,3] := ANewCoord.y;
  311. EndUpdate;
  312. end;
  313. procedure TVectorialFill.TextureMoveXAxis(ASender: TObject; APrevCoord,
  314. ANewCoord: TPointF; AShift: TShiftState);
  315. var
  316. origin, xAxisRel: TPointF;
  317. begin
  318. BeginUpdate;
  319. FTextureMatrix := FTextureMatrixBackup;
  320. origin := PointF(FTextureMatrix[1,3],FTextureMatrix[2,3]);
  321. xAxisRel := (ANewCoord - origin)*(1/FTexture.Width);
  322. if ssAlt in AShift then
  323. begin
  324. FTextureMatrix[1,1] := xAxisRel.x;
  325. FTextureMatrix[2,1] := xAxisRel.y;
  326. end
  327. else
  328. FTextureMatrix := AffineMatrixTranslation(origin.x,origin.y)*
  329. AffineMatrixScaledRotation(PointF(FTextureMatrix[1,1],FTextureMatrix[2,1]), xAxisRel)*
  330. AffineMatrixLinear(FTextureMatrix);
  331. EndUpdate;
  332. end;
  333. procedure TVectorialFill.TextureMoveYAxis(ASender: TObject; APrevCoord,
  334. ANewCoord: TPointF; AShift: TShiftState);
  335. var
  336. origin, yAxisRel: TPointF;
  337. begin
  338. BeginUpdate;
  339. FTextureMatrix := FTextureMatrixBackup;
  340. origin := PointF(FTextureMatrix[1,3],FTextureMatrix[2,3]);
  341. yAxisRel := (ANewCoord - origin)*(1/FTexture.Height);
  342. if ssAlt in AShift then
  343. begin
  344. FTextureMatrix[1,2] := yAxisRel.x;
  345. FTextureMatrix[2,2] := yAxisRel.y;
  346. end
  347. else
  348. FTextureMatrix := AffineMatrixTranslation(origin.x,origin.y)*
  349. AffineMatrixScaledRotation(PointF(FTextureMatrix[1,2],FTextureMatrix[2,2]), yAxisRel)*
  350. AffineMatrixLinear(FTextureMatrix);
  351. EndUpdate;
  352. end;
  353. procedure TVectorialFill.TextureStartMove(ASender: TObject; AIndex: integer;
  354. AShift: TShiftState);
  355. begin
  356. FTextureMatrixBackup := FTextureMatrix;
  357. end;
  358. procedure TVectorialFill.Init;
  359. begin
  360. FColor := BGRAPixelTransparent;
  361. FTexture := nil;
  362. FTextureMatrix := AffineMatrixIdentity;
  363. FTextureOpacity:= 255;
  364. FTextureAverageColorComputed:= false;
  365. FGradient := nil;
  366. FIsSolid := false;
  367. FTransparentMode := tmEnforeAllChannelsZero;
  368. end;
  369. function TVectorialFill.GetIsEditable: boolean;
  370. begin
  371. result:= FillType in [vftGradient, vftTexture];
  372. end;
  373. procedure TVectorialFill.SetTextureRepetition(AValue: TTextureRepetition);
  374. begin
  375. if FillType <> vftTexture then raise exception.Create(rsNotTextureFill);
  376. if FTextureRepetition=AValue then Exit;
  377. BeginUpdate;
  378. FTextureRepetition:=AValue;
  379. EndUpdate;
  380. end;
  381. function TVectorialFill.GetFillType: TVectorialFillType;
  382. begin
  383. if FIsSolid then result:= vftSolid
  384. else if Assigned(FGradient) then result := vftGradient
  385. else if Assigned(FTexture) then result := vftTexture
  386. else result := vftNone;
  387. end;
  388. function TVectorialFill.GetAverageColor: TBGRAPixel;
  389. begin
  390. case FillType of
  391. vftNone: result := BGRAPixelTransparent;
  392. vftGradient: result := Gradient.AverageColor;
  393. vftTexture: begin
  394. if not FTextureAverageColorComputed then
  395. begin
  396. if Assigned(FTexture) then
  397. FTextureAverageColor := FTexture.AverageColor
  398. else
  399. FTextureAverageColor := BGRAPixelTransparent;
  400. FTextureAverageColorComputed := true;
  401. end;
  402. result := FTextureAverageColor;
  403. result.alpha := BGRABlend.ApplyOpacity(result.alpha, TextureOpacity);
  404. end
  405. else {vftSolid} result := SolidColor;
  406. end;
  407. end;
  408. procedure TVectorialFill.SetTransparentMode(AValue: TTransparentMode);
  409. begin
  410. if FTransparentMode=AValue then Exit;
  411. if (FillType = vftSolid) and (SolidColor.alpha = 0) then
  412. begin
  413. case FTransparentMode of
  414. tmNoFill: Clear;
  415. tmEnforeAllChannelsZero: SolidColor := BGRAPixelTransparent;
  416. end;
  417. end;
  418. FTransparentMode:=AValue;
  419. end;
  420. procedure TVectorialFill.GradientChange(ASender: TObject; ABounds: PRectF; var ADiff: TBGRAOriginalDiff);
  421. var
  422. fillDiff: TVectorialFillGradientDiff;
  423. begin
  424. if Assigned(FDiff) then
  425. begin
  426. FreeAndNil(ADiff);
  427. exit;
  428. end;
  429. if Assigned(OnChange) then
  430. begin
  431. if Assigned(ADiff) then
  432. begin
  433. fillDiff := TVectorialFillGradientDiff.Create(ADiff as TBGRAGradientOriginalDiff);
  434. ADiff := nil;
  435. end else
  436. fillDiff := nil;
  437. FOnChange(self, fillDiff);
  438. fillDiff.Free;
  439. end;
  440. end;
  441. constructor TVectorialFill.Create;
  442. begin
  443. Init;
  444. end;
  445. procedure TVectorialFill.Clear;
  446. begin
  447. if FillType <> vftNone then
  448. begin
  449. BeginUpdate;
  450. InternalClear;
  451. EndUpdate;
  452. end else
  453. InternalClear;
  454. end;
  455. constructor TVectorialFill.CreateAsSolid(AColor: TBGRAPixel);
  456. begin
  457. Init;
  458. SetSolid(AColor);
  459. end;
  460. constructor TVectorialFill.CreateAsTexture(ATexture: TBGRABitmap;
  461. AMatrix: TAffineMatrix; AOpacity: byte; ATextureRepetition: TTextureRepetition);
  462. begin
  463. Init;
  464. SetTexture(ATexture,AMatrix,AOpacity,ATextureRepetition);
  465. end;
  466. constructor TVectorialFill.CreateAsGradient(
  467. AGradient: TBGRALayerGradientOriginal; AOwned: boolean);
  468. begin
  469. Init;
  470. SetGradient(AGradient,AOwned);
  471. end;
  472. procedure TVectorialFill.SetSolid(AColor: TBGRAPixel);
  473. begin
  474. if AColor.alpha = 0 then
  475. case TransparentMode of
  476. tmNoFill: begin Clear; exit; end;
  477. tmEnforeAllChannelsZero: AColor := BGRAPixelTransparent;
  478. end;
  479. if (FillType = vftSolid) and SolidColor.EqualsExactly(AColor) then exit;
  480. BeginUpdate;
  481. InternalClear;
  482. FColor := AColor;
  483. FIsSolid:= true;
  484. EndUpdate;
  485. end;
  486. procedure TVectorialFill.SetTexture(ATexture: TBGRABitmap;
  487. AMatrix: TAffineMatrix; AOpacity: byte; ATextureRepetition: TTextureRepetition);
  488. begin
  489. BeginUpdate;
  490. InternalClear;
  491. FTexture := ATexture.NewReference as TBGRABitmap;
  492. FTextureMatrix := AMatrix;
  493. FTextureOpacity:= AOpacity;
  494. FTextureRepetition:= ATextureRepetition;
  495. FTextureAverageColorComputed:= false;
  496. EndUpdate;
  497. end;
  498. procedure TVectorialFill.SetGradient(AGradient: TBGRALayerGradientOriginal;
  499. AOwned: boolean);
  500. begin
  501. BeginUpdate;
  502. InternalClear;
  503. if AOwned then FGradient := AGradient
  504. else FGradient := AGradient.Duplicate as TBGRALayerGradientOriginal;
  505. FGradient.OnChange:= @GradientChange;
  506. EndUpdate;
  507. end;
  508. procedure TVectorialFill.ConfigureEditor(AEditor: TBGRAOriginalEditor);
  509. begin
  510. case FillType of
  511. vftGradient: Gradient.ConfigureEditor(AEditor);
  512. vftTexture: ConfigureTextureEditor(AEditor);
  513. end;
  514. end;
  515. function TVectorialFill.CreateScanner(AMatrix: TAffineMatrix; ADraft: boolean
  516. ): TBGRACustomScanner;
  517. var
  518. bmpTransf: TBGRAAffineBitmapTransform;
  519. filter: TResampleFilter;
  520. m: TAffineMatrix;
  521. begin
  522. if Assigned(FTexture) then
  523. begin
  524. m := AMatrix*FTextureMatrix;
  525. if ADraft or TBGRABitmap.IsAffineRoughlyTranslation(m, rect(0,0,FTexture.Width,FTexture.Height)) then filter := rfBox
  526. else filter := rfHalfCosine;
  527. bmpTransf := TBGRAAffineBitmapTransform.Create(FTexture,
  528. FTextureRepetition in[trRepeatX,trRepeatBoth],
  529. FTextureRepetition in[trRepeatY,trRepeatBoth], filter);
  530. bmpTransf.ViewMatrix := m;
  531. if FTextureOpacity <> 255 then
  532. result:= TBGRAOpacityScanner.Create(bmpTransf, FTextureOpacity, true)
  533. else
  534. result := bmpTransf;
  535. end else
  536. if Assigned(FGradient) then
  537. result := FGradient.CreateScanner(AMatrix, ADraft)
  538. else if FIsSolid then
  539. result := TBGRAConstantScanner.Create(FColor)
  540. else
  541. result := nil;
  542. end;
  543. function TVectorialFill.IsSlow(AMatrix: TAffineMatrix): boolean;
  544. var
  545. m: TAffineMatrix;
  546. begin
  547. if Assigned(FTexture) then
  548. begin
  549. m := AMatrix*FTextureMatrix;
  550. result := not TBGRABitmap.IsAffineRoughlyTranslation(m, rect(0,0,FTexture.Width,FTexture.Height));
  551. end else
  552. result := (FillType = vftGradient);
  553. end;
  554. function TVectorialFill.IsFullyTransparent: boolean;
  555. begin
  556. case FillType of
  557. vftNone: result := true;
  558. vftSolid: result:= SolidColor.alpha = 0;
  559. else result:= false;
  560. end;
  561. end;
  562. procedure TVectorialFill.Transform(AMatrix: TAffineMatrix);
  563. begin
  564. case FillType of
  565. vftGradient: Gradient.Transform(AMatrix);
  566. vftTexture:
  567. begin
  568. BeginUpdate;
  569. FTextureMatrix := AMatrix*FTextureMatrix;
  570. EndUpdate;
  571. end;
  572. end;
  573. end;
  574. function TVectorialFill.Duplicate: TVectorialFill;
  575. begin
  576. result := TVectorialFill.Create;
  577. result.Assign(self);
  578. end;
  579. destructor TVectorialFill.Destroy;
  580. begin
  581. InternalClear;
  582. inherited Destroy;
  583. end;
  584. function TVectorialFill.Equals(Obj: TObject): boolean;
  585. var
  586. other: TVectorialFill;
  587. begin
  588. if inherited Equals(Obj) then
  589. result := true
  590. else
  591. if Obj = nil then
  592. result := (FillType = vftNone)
  593. else
  594. if Obj is TVectorialFill then
  595. begin
  596. other := TVectorialFill(Obj);
  597. if Self = nil then
  598. result := (other.FillType = vftNone)
  599. else
  600. begin
  601. case other.FillType of
  602. vftSolid: result := (FillType = vftSolid) and other.SolidColor.EqualsExactly(SolidColor);
  603. vftGradient: result := (FillType = vftGradient) and (other.Gradient.Equals(Gradient));
  604. vftTexture: result := (FillType = vftTexture) and (other.Texture = Texture) and
  605. (other.TextureMatrix = TextureMatrix) and (other.TextureOpacity = TextureOpacity)
  606. and (other.TextureRepetition = TextureRepetition);
  607. else
  608. result := FillType = vftNone;
  609. end;
  610. end;
  611. end else
  612. result:= false;
  613. end;
  614. class function TVectorialFill.Equal(AFill1, AFill2: TVectorialFill): boolean;
  615. begin
  616. if AFill1 = nil then
  617. begin
  618. if AFill2 = nil then result := true
  619. else result := (AFill2.FillType = vftNone);
  620. end else
  621. result := AFill1.Equals(AFill2);
  622. end;
  623. procedure TVectorialFill.Assign(Obj: TObject);
  624. var
  625. other: TVectorialFill;
  626. begin
  627. if Obj = nil then Clear else
  628. if Obj is TVectorialFill then
  629. begin
  630. other := TVectorialFill(Obj);
  631. case other.FillType of
  632. vftSolid: SetSolid(other.SolidColor);
  633. vftGradient: SetGradient(other.Gradient, false);
  634. vftTexture: SetTexture(other.Texture, other.TextureMatrix, other.TextureOpacity, other.TextureRepetition);
  635. else Clear;
  636. end;
  637. end else
  638. raise exception.Create(rsIncompatibleType);
  639. end;
  640. procedure TVectorialFill.AssignExceptGeometry(Obj: TObject);
  641. var
  642. other: TVectorialFill;
  643. tempGrad: TBGRALayerGradientOriginal;
  644. begin
  645. if Obj = nil then Clear else
  646. if Obj is TVectorialFill then
  647. begin
  648. other := TVectorialFill(Obj);
  649. case other.FillType of
  650. vftSolid: SetSolid(other.SolidColor);
  651. vftGradient: begin
  652. if self.FillType = vftGradient then
  653. tempGrad := self.Gradient.Duplicate as TBGRALayerGradientOriginal
  654. else
  655. tempGrad := TBGRALayerGradientOriginal.Create;
  656. tempGrad.AssignExceptGeometry(other.Gradient);
  657. SetGradient(tempGrad, true);
  658. end;
  659. vftTexture: if self.FillType = vftTexture then
  660. SetTexture(other.Texture, self.TextureMatrix, other.TextureOpacity, other.TextureRepetition)
  661. else SetTexture(other.Texture, AffineMatrixIdentity, other.TextureOpacity, other.TextureRepetition);
  662. else Clear;
  663. end;
  664. end else
  665. raise exception.Create(rsIncompatibleType);
  666. end;
  667. procedure TVectorialFill.FitGeometry(const ABox: TAffineBox);
  668. var
  669. sx,sy: single;
  670. u, v: TPointF;
  671. begin
  672. case FillType of
  673. vftTexture:
  674. if Assigned(Texture) then
  675. begin
  676. if not (TextureRepetition in [trRepeatX,trRepeatBoth]) and (Texture.Width > 0) then
  677. sx:= 1/Texture.Width else if ABox.Width > 0 then sx:= 1/ABox.Width else sx := 1;
  678. if not (TextureRepetition in [trRepeatY,trRepeatBoth]) and (Texture.Height > 0) then
  679. sy:= 1/Texture.Height else if ABox.Height > 0 then sy:= 1/ABox.Height else sy := 1;
  680. u := (ABox.TopRight-ABox.TopLeft)*sx;
  681. v := (ABox.BottomLeft-ABox.TopLeft)*sy;
  682. TextureMatrix := AffineMatrix(u, v, ABox.TopLeft);
  683. end;
  684. vftGradient:
  685. Gradient.FitGeometry(ABox);
  686. end;
  687. end;
  688. procedure TVectorialFill.ApplyOpacity(AOpacity: Byte);
  689. var
  690. c: TBGRAPixel;
  691. begin
  692. case FillType of
  693. vftSolid: begin
  694. c := SolidColor;
  695. c.alpha := BGRABlend.ApplyOpacity(c.alpha, AOpacity);
  696. SolidColor := c;
  697. end;
  698. vftGradient: Gradient.ApplyOpacity(AOpacity);
  699. vftTexture: TextureOpacity := BGRABlend.ApplyOpacity(TextureOpacity, AOpacity);
  700. end;
  701. end;
  702. end.