GR32_ColorPicker.pas 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149
  1. unit GR32_ColorPicker;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2009
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. * Christan-W. Budde <[email protected]>
  32. *
  33. * ***** END LICENSE BLOCK ***** *)
  34. interface
  35. {$I GR32.inc}
  36. uses
  37. {$IFDEF FPC}
  38. LCLIntf, LCLType, LMessages, Types,
  39. {$IFDEF MSWINDOWS}
  40. Windows,
  41. {$ENDIF}
  42. {$ELSE}
  43. Windows, Messages, Types,
  44. {$ENDIF}
  45. Classes, Controls, Forms, GR32, GR32_Polygons, GR32_Containers,
  46. GR32_ColorGradients;
  47. type
  48. TScreenColorPickerForm = class(TCustomForm)
  49. private
  50. FSelectedColor: TColor32;
  51. FOnColorSelected: TNotifyEvent;
  52. protected
  53. procedure CreateParams(var Params: TCreateParams); override;
  54. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  55. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer;
  56. Y: Integer); override;
  57. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  58. public
  59. constructor Create(AOwner: TComponent); override;
  60. property SelectedColor: TColor32 read FSelectedColor write FSelectedColor;
  61. property OnColorSelected: TNotifyEvent read FOnColorSelected write FOnColorSelected;
  62. published
  63. property OnKeyUp;
  64. property OnKeyPress;
  65. property OnKeyDown;
  66. property OnMouseMove;
  67. property OnMouseUp;
  68. property OnMouseDown;
  69. end;
  70. THueCirclePolygonFiller = class(TCustomPolygonFiller)
  71. private
  72. FCenter: TFloatPoint;
  73. FWebSafe: Boolean;
  74. protected
  75. function GetFillLine: TFillLineEvent; override;
  76. procedure FillLine(Dst: PColor32; DstX, DstY, Length: Integer;
  77. AlphaValues: PColor32; CombineMode: TCombineMode); virtual;
  78. procedure FillLineWebSafe(Dst: PColor32; DstX, DstY, Length: Integer;
  79. AlphaValues: PColor32; CombineMode: TCombineMode); virtual;
  80. public
  81. constructor Create(Center: TFloatPoint; WebSafe: Boolean = False);
  82. property Center: TFloatPoint read FCenter write FCenter;
  83. property WebSafe: Boolean read FWebSafe write FWebSafe;
  84. end;
  85. THueSaturationCirclePolygonFiller = class(THueCirclePolygonFiller)
  86. private
  87. FRadius: Single;
  88. FInvRadius: Single;
  89. FValue: Single;
  90. procedure SetRadius(const Value: Single);
  91. protected
  92. procedure FillLine(Dst: PColor32; DstX, DstY, Length: Integer;
  93. AlphaValues: PColor32; CombineMode: TCombineMode); override;
  94. procedure FillLineWebSafe(Dst: PColor32; DstX, DstY, Length: Integer;
  95. AlphaValues: PColor32; CombineMode: TCombineMode); override;
  96. public
  97. constructor Create(Center: TFloatPoint; Radius, Value: Single;
  98. WebSafe: Boolean = False);
  99. property Radius: Single read FRadius write SetRadius;
  100. property Value: Single read FValue write FValue;
  101. end;
  102. TBarycentricGradientPolygonFillerEx = class(TBarycentricGradientPolygonFiller)
  103. private
  104. FWebSafe: Boolean;
  105. protected
  106. function GetFillLine: TFillLineEvent; override;
  107. procedure FillLineWebSafe(Dst: PColor32; DstX, DstY, Length: Integer;
  108. AlphaValues: PColor32; CombineMode: TCombineMode);
  109. public
  110. property WebSafe: Boolean read FWebSafe write FWebSafe;
  111. end;
  112. TVisualAid = set of (vaHueLine, vaSaturationCircle, vaSelection);
  113. TVisualAidRenderType = (vatSolid, vatInvert, vatBW);
  114. TAdjustCalc = procedure (X, Y: Single) of object;
  115. TVisualAidOptions = class(TPersistent)
  116. private
  117. FOwner: TPersistent;
  118. FRenderType: TVisualAidRenderType;
  119. FColor: TColor32;
  120. FLineWidth: Single;
  121. procedure SetRenderType(const Value: TVisualAidRenderType);
  122. procedure SetColor(const Value: TColor32);
  123. procedure SetLineWidth(const Value: Single);
  124. protected
  125. function GetOwner: TPersistent; override;
  126. procedure Changed; virtual;
  127. public
  128. constructor Create(AOwner: TPersistent); virtual;
  129. property Owner: TPersistent read FOwner;
  130. published
  131. property RenderType: TVisualAidRenderType read FRenderType write SetRenderType default vatInvert;
  132. property Color: TColor32 read FColor write SetColor;
  133. property LineWidth: Single read FLineWidth write SetLineWidth;
  134. end;
  135. TCustomColorPicker = class(TCustomControl)
  136. private
  137. FBuffer: TBitmap32;
  138. FAdjustCalc: TAdjustCalc;
  139. FSelectedColor: TColor32;
  140. FBufferValid: Boolean;
  141. FVisualAidOptions: TVisualAidOptions;
  142. FWebSafe: Boolean;
  143. FBorder: Boolean;
  144. FOnChanged: TNotifyEvent;
  145. procedure SetBorder(const Value: Boolean);
  146. procedure SetWebSafe(const Value: Boolean);
  147. procedure SetSelectedColor(const Value: TColor32);
  148. {$IFDEF FPC}
  149. procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
  150. procedure WMGetDlgCode(var Msg: TLMessage); message LM_GETDLGCODE;
  151. {$ELSE}
  152. procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
  153. procedure WMGetDlgCode(var Msg: TWmGetDlgCode); message WM_GETDLGCODE;
  154. {$ENDIF}
  155. protected
  156. procedure Paint; override;
  157. procedure PaintColorPicker; virtual; abstract;
  158. procedure SelectedColorChanged; virtual;
  159. public
  160. constructor Create(AOwner: TComponent); override;
  161. destructor Destroy; override;
  162. procedure Invalidate; override;
  163. procedure Resize; override;
  164. property Border: Boolean read FBorder write SetBorder default False;
  165. property VisualAidOptions: TVisualAidOptions read FVisualAidOptions;
  166. property SelectedColor: TColor32 read FSelectedColor write SetSelectedColor;
  167. property WebSafe: Boolean read FWebSafe write SetWebSafe;
  168. property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
  169. end;
  170. TColorComponent = (ccRed, ccGreen, ccBlue, ccAlpha);
  171. TCustomColorPickerComponent = class(TCustomColorPicker)
  172. private
  173. FMouseDown: Boolean;
  174. FColorComponent: TColorComponent;
  175. procedure SetColorComponent(const Value: TColorComponent);
  176. protected
  177. procedure PaintColorPicker; override;
  178. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer;
  179. Y: Integer); override;
  180. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer;
  181. Y: Integer); override;
  182. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  183. public
  184. constructor Create(AOwner: TComponent); override;
  185. property ColorComponent: TColorComponent read FColorComponent write SetColorComponent;
  186. end;
  187. TCustomColorPickerRGBA = class(TCustomColorPicker)
  188. private
  189. FBarHeight: Integer;
  190. FSpaceHeight: Integer;
  191. procedure SetBarHeight(const Value: Integer);
  192. procedure SetSpaceHeight(const Value: Integer);
  193. procedure PickAlpha(X, Y: Single);
  194. procedure PickBlue(X, Y: Single);
  195. procedure PickGreen(X, Y: Single);
  196. procedure PickRed(X, Y: Single);
  197. protected
  198. procedure PaintColorPicker; override;
  199. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer;
  200. Y: Integer); override;
  201. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer;
  202. Y: Integer); override;
  203. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  204. public
  205. constructor Create(AOwner: TComponent); override;
  206. property BarHeight: Integer read FBarHeight write SetBarHeight default 24;
  207. property SpaceHeight: Integer read FSpaceHeight write SetSpaceHeight default 8;
  208. end;
  209. TMarkerType = (mtCross, mtCircle);
  210. TCustomColorPickerHS = class(TCustomColorPicker)
  211. private
  212. FHue: Single;
  213. FSaturation: Single;
  214. FLockValues: integer;
  215. FMarkerType: TMarkerType;
  216. procedure PickHue(X, Y: Single);
  217. procedure SetHue(const Value: Single);
  218. procedure SetSaturation(const Value: Single);
  219. procedure SetMarkerType(const Value: TMarkerType);
  220. procedure ApplyHS;
  221. protected
  222. procedure PaintColorPicker; override;
  223. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer;
  224. Y: Integer); override;
  225. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  226. procedure SelectedColorChanged; override;
  227. public
  228. constructor Create(AOwner: TComponent); override;
  229. property MarkerType: TMarkerType read FMarkerType write SetMarkerType;
  230. property Hue: Single read FHue write SetHue;
  231. property Saturation: Single read FSaturation write SetSaturation;
  232. end;
  233. TCustomColorPickerHSV = class(TCustomColorPicker)
  234. private
  235. FHue: Single;
  236. FSaturation: Single;
  237. FValue: Single;
  238. FLockValues: integer;
  239. FCenter: TFloatPoint;
  240. FRadius: TFloat;
  241. FCircleSteps: Integer;
  242. FVisualAid: TVisualAid;
  243. procedure PickHue(X, Y: Single);
  244. procedure PickValue(X, Y: Single);
  245. procedure SetHue(const Value: Single);
  246. procedure SetSaturation(const Value: Single);
  247. procedure SetValue(const Value: Single);
  248. procedure SetVisualAid(const Value: TVisualAid);
  249. procedure ApplyHSV;
  250. protected
  251. procedure PaintColorPicker; override;
  252. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer;
  253. Y: Integer); override;
  254. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer;
  255. Y: Integer); override;
  256. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  257. procedure SelectedColorChanged; override;
  258. public
  259. constructor Create(AOwner: TComponent); override;
  260. procedure Resize; override;
  261. property Hue: Single read FHue write SetHue;
  262. property Saturation: Single read FSaturation write SetSaturation;
  263. property Value: Single read FValue write SetValue;
  264. property VisualAid: TVisualAid read FVisualAid write SetVisualAid;
  265. end;
  266. TVisualAidGTK = set of (vagHueLine, vagSelection);
  267. TCustomColorPickerGTK = class(TCustomColorPicker)
  268. private
  269. FHue: Single;
  270. FSaturation: Single;
  271. FValue: Single;
  272. FLockValues: integer;
  273. FCenter: TFloatPoint;
  274. FRadius: TFloat;
  275. FInnerRadius: TFloat;
  276. FCircleSteps: Integer;
  277. FVisualAid: TVisualAidGTK;
  278. procedure PickHue(X, Y: Single);
  279. procedure PickSaturationValue(X, Y: Single);
  280. procedure SetHue(const Value: Single);
  281. procedure SetSaturation(const Value: Single);
  282. procedure SetValue(const Value: Single);
  283. procedure SetVisualAid(const Value: TVisualAidGTK);
  284. procedure SetRadius(const Value: TFloat);
  285. procedure ApplyHSV;
  286. protected
  287. procedure PaintColorPicker; override;
  288. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer;
  289. Y: Integer); override;
  290. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer;
  291. Y: Integer); override;
  292. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  293. procedure SelectedColorChanged; override;
  294. property Radius: TFloat read FRadius write SetRadius;
  295. property Center: TFloatPoint read FCenter write FCenter;
  296. public
  297. constructor Create(AOwner: TComponent); override;
  298. procedure Resize; override;
  299. property Hue: Single read FHue write SetHue;
  300. property Saturation: Single read FSaturation write SetSaturation;
  301. property Value: Single read FValue write SetValue;
  302. property VisualAid: TVisualAidGTK read FVisualAid write SetVisualAid;
  303. end;
  304. TColorPickerComponent = class(TCustomColorPickerComponent)
  305. published
  306. property Align;
  307. property Anchors;
  308. property Border;
  309. property ColorComponent;
  310. property DragCursor;
  311. property DragKind;
  312. property Enabled;
  313. {$IFDEF HasParentBackground}
  314. property ParentBackground;
  315. {$ENDIF}
  316. property ParentColor;
  317. property ParentShowHint;
  318. property PopupMenu;
  319. property SelectedColor;
  320. property TabOrder;
  321. property TabStop;
  322. property VisualAidOptions;
  323. property WebSafe default False;
  324. {$IFNDEF PLATFORM_INDEPENDENT}
  325. property OnCanResize;
  326. {$ENDIF}
  327. property OnChanged;
  328. property OnClick;
  329. property OnDblClick;
  330. property OnDragDrop;
  331. property OnDragOver;
  332. property OnEndDrag;
  333. property OnMouseDown;
  334. property OnMouseMove;
  335. property OnMouseUp;
  336. property OnMouseWheel;
  337. property OnMouseWheelDown;
  338. property OnMouseWheelUp;
  339. {$IFDEF COMPILER2005_UP}
  340. property OnMouseEnter;
  341. property OnMouseLeave;
  342. {$ENDIF}
  343. property OnResize;
  344. property OnStartDrag;
  345. end;
  346. TColorPickerRGBA = class(TCustomColorPickerRGBA)
  347. published
  348. property Align;
  349. property Anchors;
  350. property BarHeight;
  351. property Border;
  352. property DragCursor;
  353. property DragKind;
  354. property Enabled;
  355. {$IFDEF HasParentBackground}
  356. property ParentBackground;
  357. {$ENDIF}
  358. property ParentColor;
  359. property ParentShowHint;
  360. property PopupMenu;
  361. property SelectedColor;
  362. property SpaceHeight;
  363. property TabOrder;
  364. property TabStop;
  365. property VisualAidOptions;
  366. property WebSafe default False;
  367. {$IFNDEF PLATFORM_INDEPENDENT}
  368. property OnCanResize;
  369. {$ENDIF}
  370. property OnChanged;
  371. property OnClick;
  372. property OnDblClick;
  373. property OnDragDrop;
  374. property OnDragOver;
  375. property OnEndDrag;
  376. property OnMouseDown;
  377. property OnMouseMove;
  378. property OnMouseUp;
  379. property OnMouseWheel;
  380. property OnMouseWheelDown;
  381. property OnMouseWheelUp;
  382. {$IFDEF COMPILER2005_UP}
  383. property OnMouseEnter;
  384. property OnMouseLeave;
  385. {$ENDIF}
  386. property OnResize;
  387. property OnStartDrag;
  388. end;
  389. TColorPickerHS = class(TCustomColorPickerHS)
  390. published
  391. property Align;
  392. property Anchors;
  393. property DragCursor;
  394. property DragKind;
  395. property Enabled;
  396. property Hue;
  397. property MarkerType;
  398. {$IFDEF HasParentBackground}
  399. property ParentBackground;
  400. {$ENDIF}
  401. property ParentColor;
  402. property ParentShowHint;
  403. property PopupMenu;
  404. property Saturation;
  405. property SelectedColor;
  406. property TabOrder;
  407. property TabStop;
  408. property WebSafe default False;
  409. {$IFNDEF PLATFORM_INDEPENDENT}
  410. property OnCanResize;
  411. {$ENDIF}
  412. property OnChanged;
  413. property OnClick;
  414. property OnDblClick;
  415. property OnDragDrop;
  416. property OnDragOver;
  417. property OnEndDrag;
  418. property OnMouseDown;
  419. property OnMouseMove;
  420. property OnMouseUp;
  421. property OnMouseWheel;
  422. property OnMouseWheelDown;
  423. property OnMouseWheelUp;
  424. {$IFDEF COMPILER2005_UP}
  425. property OnMouseEnter;
  426. property OnMouseLeave;
  427. {$ENDIF}
  428. property OnResize;
  429. property OnStartDrag;
  430. end;
  431. TColorPickerHSV = class(TCustomColorPickerHSV)
  432. published
  433. property Align;
  434. property Anchors;
  435. property Border;
  436. property DragCursor;
  437. property DragKind;
  438. property Enabled;
  439. property Hue;
  440. {$IFDEF HasParentBackground}
  441. property ParentBackground;
  442. {$ENDIF}
  443. property ParentColor;
  444. property ParentShowHint;
  445. property PopupMenu;
  446. property Saturation;
  447. property SelectedColor;
  448. property TabOrder;
  449. property TabStop;
  450. property Value;
  451. property VisualAid default [vaHueLine, vaSaturationCircle, vaSelection];
  452. property VisualAidOptions;
  453. property WebSafe default False;
  454. {$IFNDEF PLATFORM_INDEPENDENT}
  455. property OnCanResize;
  456. {$ENDIF}
  457. property OnChanged;
  458. property OnClick;
  459. property OnDblClick;
  460. property OnDragDrop;
  461. property OnDragOver;
  462. property OnEndDrag;
  463. property OnMouseDown;
  464. property OnMouseMove;
  465. property OnMouseUp;
  466. property OnMouseWheel;
  467. property OnMouseWheelDown;
  468. property OnMouseWheelUp;
  469. {$IFDEF COMPILER2005_UP}
  470. property OnMouseEnter;
  471. property OnMouseLeave;
  472. {$ENDIF}
  473. property OnResize;
  474. property OnStartDrag;
  475. end;
  476. TColorPickerGTK = class(TCustomColorPickerGTK)
  477. published
  478. property Align;
  479. property Anchors;
  480. property Border;
  481. property DragCursor;
  482. property DragKind;
  483. property Enabled;
  484. property Hue;
  485. {$IFDEF HasParentBackground}
  486. property ParentBackground;
  487. {$ENDIF}
  488. property ParentColor;
  489. property ParentShowHint;
  490. property PopupMenu;
  491. property Saturation;
  492. property SelectedColor;
  493. property TabOrder;
  494. property TabStop;
  495. property Value;
  496. property VisualAid default [vagHueLine, vagSelection];
  497. property VisualAidOptions;
  498. property WebSafe default False;
  499. {$IFNDEF PLATFORM_INDEPENDENT}
  500. property OnCanResize;
  501. {$ENDIF}
  502. property OnChanged;
  503. property OnClick;
  504. property OnDblClick;
  505. property OnDragDrop;
  506. property OnDragOver;
  507. property OnEndDrag;
  508. property OnMouseDown;
  509. property OnMouseMove;
  510. property OnMouseUp;
  511. property OnMouseWheel;
  512. property OnMouseWheelDown;
  513. property OnMouseWheelUp;
  514. {$IFDEF COMPILER2005_UP}
  515. property OnMouseEnter;
  516. property OnMouseLeave;
  517. {$ENDIF}
  518. property OnResize;
  519. property OnStartDrag;
  520. end;
  521. implementation
  522. uses
  523. Math, Graphics, GR32_Backends, GR32_Math, GR32_Blend, GR32_VectorUtils;
  524. procedure RoundToWebSafe(var Color: TColor32);
  525. begin
  526. with TColor32Entry(Color) do
  527. begin
  528. R := ((R + $19) div $33) * $33;
  529. G := ((G + $19) div $33) * $33;
  530. B := ((B + $19) div $33) * $33;
  531. end;
  532. end;
  533. {$IFDEF MSWINDOWS}
  534. function GetDesktopColor(const x, y: Integer): TColor32;
  535. var
  536. c: TCanvas;
  537. begin
  538. c := TCanvas.Create;
  539. try
  540. c.Handle := GetWindowDC(GetDesktopWindow);
  541. Result := Color32(GetPixel(c.Handle, x, y));
  542. finally
  543. c.Free;
  544. end;
  545. end;
  546. {$ENDIF}
  547. { TVisualAidOptions }
  548. constructor TVisualAidOptions.Create(AOwner: TPersistent);
  549. begin
  550. inherited Create;
  551. FOwner := AOwner;
  552. FColor := $AF000000;
  553. FRenderType := vatInvert;
  554. FLineWidth := 2;
  555. end;
  556. procedure TVisualAidOptions.Changed;
  557. begin
  558. if Owner is TCustomColorPicker then
  559. TCustomColorPicker(Owner).Invalidate;
  560. end;
  561. function TVisualAidOptions.GetOwner: TPersistent;
  562. begin
  563. if FOwner is TPersistent then
  564. Result := TPersistent(FOwner)
  565. else
  566. Result := nil;
  567. end;
  568. procedure TVisualAidOptions.SetColor(const Value: TColor32);
  569. begin
  570. if FColor <> Value then
  571. begin
  572. FColor := Value;
  573. if FRenderType = vatSolid then
  574. Changed;
  575. end;
  576. end;
  577. procedure TVisualAidOptions.SetLineWidth(const Value: Single);
  578. begin
  579. if FLineWidth <> Value then
  580. begin
  581. FLineWidth := Value;
  582. Changed;
  583. end;
  584. end;
  585. procedure TVisualAidOptions.SetRenderType(const Value: TVisualAidRenderType);
  586. begin
  587. if FRenderType <> Value then
  588. begin
  589. FRenderType := Value;
  590. Changed;
  591. end;
  592. end;
  593. { TScreenColorPickerForm }
  594. constructor TScreenColorPickerForm.Create(AOwner: TComponent);
  595. begin
  596. inherited CreateNew(AOwner);
  597. Align := alClient;
  598. BorderIcons := [];
  599. BorderStyle := bsNone;
  600. Caption := 'Pick a color...';
  601. FormStyle := fsStayOnTop;
  602. Position := poDefault;
  603. FSelectedColor := 0;
  604. end;
  605. procedure TScreenColorPickerForm.CreateParams(var Params: TCreateParams);
  606. begin
  607. inherited CreateParams(Params);
  608. Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
  609. end;
  610. procedure TScreenColorPickerForm.KeyDown(var Key: Word; Shift: TShiftState);
  611. begin
  612. if (Key = VK_ESCAPE) then
  613. ModalResult := mrCancel
  614. else
  615. inherited;
  616. end;
  617. procedure TScreenColorPickerForm.MouseDown(Button: TMouseButton;
  618. Shift: TShiftState; X, Y: Integer);
  619. begin
  620. if Button = mbLeft then
  621. begin
  622. {$IFDEF MSWINDOWS}
  623. FSelectedColor := GetDesktopColor(X, Y);
  624. if Assigned(FOnColorSelected) then
  625. FOnColorSelected(Self);
  626. {$ENDIF}
  627. ModalResult := mrOk
  628. end
  629. else
  630. inherited;
  631. end;
  632. procedure TScreenColorPickerForm.MouseMove(Shift: TShiftState; X, Y: Integer);
  633. begin
  634. {$IFDEF MSWINDOWS}
  635. FSelectedColor := GetDesktopColor(X, Y);
  636. {$ENDIF}
  637. inherited;
  638. end;
  639. { THueCirclePolygonFiller }
  640. constructor THueCirclePolygonFiller.Create(Center: TFloatPoint;
  641. WebSafe: Boolean = False);
  642. begin
  643. FCenter := Center;
  644. FWebSafe := WebSafe;
  645. inherited Create;
  646. end;
  647. procedure THueCirclePolygonFiller.FillLine(Dst: PColor32; DstX, DstY,
  648. Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  649. var
  650. X: Integer;
  651. H: Single;
  652. const
  653. CTwoPiInv = 1 / (2 * Pi);
  654. begin
  655. for X := DstX to DstX + Length - 1 do
  656. begin
  657. // calculate squared distance
  658. H := 0.5 + ArcTan2(DstY - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  659. CombineMem(HSVtoRGB(H, 1, 1), Dst^, AlphaValues^);
  660. EMMS;
  661. Inc(Dst);
  662. Inc(AlphaValues);
  663. end;
  664. end;
  665. procedure THueCirclePolygonFiller.FillLineWebSafe(Dst: PColor32; DstX, DstY,
  666. Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  667. var
  668. X: Integer;
  669. H: Single;
  670. Color: TColor32;
  671. const
  672. CTwoPiInv = 1 / (2 * Pi);
  673. begin
  674. for X := DstX to DstX + Length - 1 do
  675. begin
  676. // calculate squared distance
  677. H := 0.5 + ArcTan2(DstY - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  678. Color := HSVtoRGB(H, 1, 1);
  679. RoundToWebSafe(Color);
  680. CombineMem(Color, Dst^, AlphaValues^);
  681. EMMS;
  682. Inc(Dst);
  683. Inc(AlphaValues);
  684. end;
  685. end;
  686. function THueCirclePolygonFiller.GetFillLine: TFillLineEvent;
  687. begin
  688. if FWebSafe then
  689. Result := FillLineWebSafe
  690. else
  691. Result := FillLine;
  692. end;
  693. { THueSaturationCirclePolygonFiller }
  694. constructor THueSaturationCirclePolygonFiller.Create(Center: TFloatPoint;
  695. Radius, Value: Single; WebSafe: Boolean = False);
  696. begin
  697. FRadius := Max(1, Radius);
  698. FInvRadius := 1 / FRadius;
  699. FValue := Value;
  700. inherited Create(Center, WebSafe);
  701. end;
  702. procedure THueSaturationCirclePolygonFiller.FillLine(Dst: PColor32; DstX, DstY,
  703. Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  704. var
  705. X: Integer;
  706. SqrYDist, H, S: Single;
  707. const
  708. CTwoPiInv = 1 / (2 * Pi);
  709. begin
  710. SqrYDist := Sqr(DstY - FCenter.Y);
  711. for X := DstX to DstX + Length - 1 do
  712. begin
  713. // calculate squared distance
  714. H := 0.5 + ArcTan2(DstY - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  715. S := Sqrt(Sqr(X - Center.X) + SqrYDist) * FInvRadius;
  716. if S > 1 then
  717. S := 1;
  718. CombineMem(HSVtoRGB(H, S, Value), Dst^, AlphaValues^);
  719. EMMS;
  720. Inc(Dst);
  721. Inc(AlphaValues);
  722. end;
  723. end;
  724. procedure THueSaturationCirclePolygonFiller.FillLineWebSafe(Dst: PColor32; DstX, DstY,
  725. Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  726. var
  727. X: Integer;
  728. SqrYDist, H, S: Single;
  729. Color: TColor32;
  730. const
  731. CTwoPiInv = 1 / (2 * Pi);
  732. begin
  733. SqrYDist := Sqr(DstY - FCenter.Y);
  734. for X := DstX to DstX + Length - 1 do
  735. begin
  736. // calculate squared distance
  737. H := 0.5 + ArcTan2(DstY - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  738. S := Sqrt(Sqr(X - Center.X) + SqrYDist) * FInvRadius;
  739. if S > 1 then
  740. S := 1;
  741. Color := HSVtoRGB(H, S, Value);
  742. RoundToWebSafe(Color);
  743. CombineMem(Color, Dst^, AlphaValues^);
  744. EMMS;
  745. Inc(Dst);
  746. Inc(AlphaValues);
  747. end;
  748. end;
  749. procedure THueSaturationCirclePolygonFiller.SetRadius(const Value: Single);
  750. begin
  751. if FRadius <> Value then
  752. begin
  753. FRadius := Value;
  754. FInvRadius := 1 / FRadius;
  755. end;
  756. end;
  757. { TBarycentricGradientPolygonFillerEx }
  758. procedure TBarycentricGradientPolygonFillerEx.FillLineWebSafe(Dst: PColor32; DstX,
  759. DstY, Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  760. var
  761. X: Integer;
  762. Color32: TColor32;
  763. Temp, DotY1, DotY2: TFloat;
  764. Barycentric: array [0..1] of TFloat;
  765. BlendMemEx: TBlendMemEx;
  766. begin
  767. BlendMemEx := BLEND_MEM_EX[CombineMode]^;
  768. Temp := DstY - FColorPoints[2].Point.Y;
  769. DotY1 := FDists[0].X * Temp;
  770. DotY2 := FDists[1].X * Temp;
  771. for X := DstX to DstX + Length - 1 do
  772. begin
  773. Temp := (X - FColorPoints[2].Point.X);
  774. Barycentric[0] := FDists[0].Y * Temp + DotY1;
  775. Barycentric[1] := FDists[1].Y * Temp + DotY2;
  776. Color32 := Linear3PointInterpolation(FColorPoints[0].Color32,
  777. FColorPoints[1].Color32, FColorPoints[2].Color32,
  778. Barycentric[0], Barycentric[1], 1 - Barycentric[1] - Barycentric[0]);
  779. RoundToWebSafe(Color32);
  780. BlendMemEx(Color32, Dst^, AlphaValues^);
  781. EMMS;
  782. Inc(Dst);
  783. Inc(AlphaValues);
  784. end;
  785. end;
  786. function TBarycentricGradientPolygonFillerEx.GetFillLine: TFillLineEvent;
  787. begin
  788. if FWebSafe then
  789. Result := FillLineWebSafe
  790. else
  791. Result := inherited GetFillLine;
  792. end;
  793. { TCustomColorPicker }
  794. constructor TCustomColorPicker.Create(AOwner: TComponent);
  795. begin
  796. inherited Create(AOwner);
  797. ControlStyle := ControlStyle + [csOpaque];
  798. FBuffer := TBitmap32.Create;
  799. FSelectedColor := clSalmon32;
  800. FVisualAidOptions := TVisualAidOptions.Create(Self);
  801. end;
  802. destructor TCustomColorPicker.Destroy;
  803. begin
  804. FVisualAidOptions.Free;
  805. FBuffer.Free;
  806. inherited;
  807. end;
  808. procedure TCustomColorPicker.Invalidate;
  809. begin
  810. FBufferValid := False;
  811. inherited;
  812. end;
  813. procedure TCustomColorPicker.Paint;
  814. begin
  815. if not Assigned(Parent) then
  816. Exit;
  817. if not FBufferValid then
  818. begin
  819. (FBuffer.Backend as IPaintSupport).ImageNeeded;
  820. PaintColorPicker;
  821. (FBuffer.Backend as IPaintSupport).CheckPixmap;
  822. FBufferValid := True;
  823. end;
  824. FBuffer.Lock;
  825. with Canvas do
  826. try
  827. (FBuffer.Backend as IDeviceContextSupport).DrawTo(Canvas.Handle, 0, 0);
  828. finally
  829. FBuffer.Unlock;
  830. end;
  831. end;
  832. procedure TCustomColorPicker.Resize;
  833. begin
  834. inherited;
  835. FBuffer.SetSize(Width, Height);
  836. FBufferValid := False;
  837. end;
  838. procedure TCustomColorPicker.SelectedColorChanged;
  839. begin
  840. if Assigned(FOnChanged) then
  841. FOnChanged(Self);
  842. Invalidate;
  843. end;
  844. procedure TCustomColorPicker.SetBorder(const Value: Boolean);
  845. begin
  846. if FBorder <> Value then
  847. begin
  848. FBorder := Value;
  849. Invalidate;
  850. end;
  851. end;
  852. procedure TCustomColorPicker.SetSelectedColor(const Value: TColor32);
  853. begin
  854. if FSelectedColor <> Value then
  855. begin
  856. FSelectedColor := Value;
  857. SelectedColorChanged;
  858. end;
  859. end;
  860. procedure TCustomColorPicker.SetWebSafe(const Value: Boolean);
  861. begin
  862. if FWebSafe <> Value then
  863. begin
  864. FWebSafe := Value;
  865. Invalidate;
  866. end;
  867. end;
  868. procedure TCustomColorPicker.WMEraseBkgnd(var Message: {$IFDEF FPC}TLmEraseBkgnd{$ELSE}TWmEraseBkgnd{$ENDIF});
  869. begin
  870. Message.Result := 1;
  871. end;
  872. procedure TCustomColorPicker.WMGetDlgCode(var Msg: {$IFDEF FPC}TLMessage{$ELSE}TWmGetDlgCode{$ENDIF});
  873. begin
  874. with Msg do
  875. Result := Result or DLGC_WANTARROWS;
  876. end;
  877. { TCustomColorPickerComponent }
  878. constructor TCustomColorPickerComponent.Create(AOwner: TComponent);
  879. begin
  880. inherited;
  881. FVisualAidOptions.Color := clBlack32;
  882. FVisualAidOptions.LineWidth := 1.5;
  883. end;
  884. procedure TCustomColorPickerComponent.MouseDown(Button: TMouseButton;
  885. Shift: TShiftState; X, Y: Integer);
  886. begin
  887. FMouseDown := (Button = mbLeft);
  888. inherited;
  889. end;
  890. procedure TCustomColorPickerComponent.MouseMove(Shift: TShiftState; X,
  891. Y: Integer);
  892. var
  893. Value: Single;
  894. Color: TColor32Entry;
  895. begin
  896. if FMouseDown then
  897. begin
  898. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  899. Color := TColor32Entry(SelectedColor);
  900. case FColorComponent of
  901. ccRed:
  902. Color.R := Round(Value * 255);
  903. ccGreen:
  904. Color.G := Round(Value * 255);
  905. ccBlue:
  906. Color.B := Round(Value * 255);
  907. ccAlpha:
  908. Color.A := Round(Value * 255);
  909. end;
  910. SelectedColor := Color.ARGB;
  911. end;
  912. inherited;
  913. end;
  914. procedure TCustomColorPickerComponent.MouseUp(Button: TMouseButton;
  915. Shift: TShiftState; X, Y: Integer);
  916. begin
  917. if (Button = mbLeft) then
  918. FMouseDown := False;
  919. inherited;
  920. end;
  921. procedure TCustomColorPickerComponent.PaintColorPicker;
  922. var
  923. Polygon: TArrayOfFloatPoint;
  924. InvertFiller: TInvertPolygonFiller;
  925. procedure RenderPolygon;
  926. begin
  927. case FVisualAidOptions.RenderType of
  928. vatInvert:
  929. PolygonFS(FBuffer, Polygon, InvertFiller);
  930. vatBW:
  931. if Intensity(FSelectedColor) < 127 then
  932. PolygonFS(FBuffer, Polygon, clWhite32)
  933. else
  934. PolygonFS(FBuffer, Polygon, clBlack32);
  935. else
  936. PolygonFS(FBuffer, Polygon, FVisualAidOptions.Color);
  937. end;
  938. end;
  939. var
  940. X, Y: Integer;
  941. ScanLine: PColor32Array;
  942. Value: Single;
  943. LeftColor, RightColor: TColor32Entry;
  944. OddY: Boolean;
  945. BorderOffset: Integer;
  946. GradientFiller: TLinearGradientPolygonFiller;
  947. const
  948. CByteScale = 1 / 255;
  949. CCheckerBoardColor: array [Boolean] of TColor32 = ($FFA0A0A0, $FF5F5F5F);
  950. begin
  951. FBuffer.Clear(Color32(Color));
  952. BorderOffset := Integer(FBorder);
  953. InvertFiller := TInvertPolygonFiller.Create;
  954. try
  955. LeftColor := TColor32Entry(FSelectedColor);
  956. RightColor := TColor32Entry(FSelectedColor);
  957. case FColorComponent of
  958. ccRed:
  959. begin
  960. Value := LeftColor.R * CByteScale;
  961. LeftColor.R := 0;
  962. RightColor.R := 255;
  963. LeftColor.A := 255;
  964. RightColor.A := 255;
  965. end;
  966. ccGreen:
  967. begin
  968. Value := LeftColor.G * CByteScale;
  969. LeftColor.G := 0;
  970. RightColor.G := 255;
  971. LeftColor.A := 255;
  972. RightColor.A := 255;
  973. end;
  974. ccBlue:
  975. begin
  976. Value := LeftColor.B * CByteScale;
  977. LeftColor.B := 0;
  978. RightColor.B := 255;
  979. LeftColor.A := 255;
  980. RightColor.A := 255;
  981. end;
  982. ccAlpha:
  983. begin
  984. Value := LeftColor.A * CByteScale;
  985. LeftColor.A := 0;
  986. RightColor.A := 255;
  987. for Y := 0 to Height - 1 do
  988. begin
  989. OddY := Odd(Y div 8);
  990. ScanLine := FBuffer.ScanLine[Y];
  991. for X := 3 to Width - 4 do
  992. ScanLine^[X] := CCheckerBoardColor[Odd(X shr 3) = OddY];
  993. end;
  994. end
  995. else
  996. Exit;
  997. end;
  998. GradientFiller := TLinearGradientPolygonFiller.Create;
  999. try
  1000. GradientFiller.SimpleGradientX(3, LeftColor.ARGB,
  1001. Width - 3, RightColor.ARGB);
  1002. PolygonFS(FBuffer, Rectangle(FloatRect(3, 0, Width - 3, Height)), GradientFiller);
  1003. finally
  1004. GradientFiller.Free;
  1005. end;
  1006. if FBorder then
  1007. begin
  1008. FBuffer.FrameRectTS(3, 0, Width - 3, Height, $DF000000);
  1009. FBuffer.RaiseRectTS(4, 0, Width - 4, Height - 1, 20);
  1010. end;
  1011. SetLength(Polygon, 3);
  1012. Polygon[0] := FloatPoint(3 + Value * (Width - 6), Height - BorderOffset - 5);
  1013. Polygon[1] := FloatPoint(Polygon[0].X - 3, Polygon[0].Y + 5);
  1014. Polygon[2] := FloatPoint(Polygon[0].X + 3, Polygon[0].Y + 5);
  1015. RenderPolygon;
  1016. Polygon[0].Y := BorderOffset + 5;
  1017. Polygon[1].Y := BorderOffset;
  1018. Polygon[2].Y := BorderOffset;
  1019. RenderPolygon;
  1020. finally
  1021. InvertFiller.Free;
  1022. end;
  1023. inherited;
  1024. end;
  1025. procedure TCustomColorPickerComponent.SetColorComponent(
  1026. const Value: TColorComponent);
  1027. begin
  1028. if FColorComponent <> Value then
  1029. begin
  1030. FColorComponent := Value;
  1031. Invalidate;
  1032. end;
  1033. end;
  1034. { TCustomColorPickerRGBA }
  1035. constructor TCustomColorPickerRGBA.Create(AOwner: TComponent);
  1036. begin
  1037. inherited;
  1038. FBarHeight := 24;
  1039. FSpaceHeight := 8;
  1040. FVisualAidOptions.Color := clBlack32;
  1041. FVisualAidOptions.LineWidth := 1.5;
  1042. end;
  1043. procedure TCustomColorPickerRGBA.PickRed(X, Y: Single);
  1044. var
  1045. Value: Single;
  1046. Color: TColor32Entry;
  1047. begin
  1048. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  1049. Color := TColor32Entry(SelectedColor);
  1050. Color.R := Round(Value * 255);
  1051. SelectedColor := Color.ARGB;
  1052. end;
  1053. procedure TCustomColorPickerRGBA.PickGreen(X, Y: Single);
  1054. var
  1055. Value: Single;
  1056. Color: TColor32Entry;
  1057. begin
  1058. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  1059. Color := TColor32Entry(SelectedColor);
  1060. Color.G := Round(Value * 255);
  1061. SelectedColor := Color.ARGB;
  1062. end;
  1063. procedure TCustomColorPickerRGBA.PickBlue(X, Y: Single);
  1064. var
  1065. Value: Single;
  1066. Color: TColor32Entry;
  1067. begin
  1068. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  1069. Color := TColor32Entry(SelectedColor);
  1070. Color.B := Round(Value * 255);
  1071. SelectedColor := Color.ARGB;
  1072. end;
  1073. procedure TCustomColorPickerRGBA.PickAlpha(X, Y: Single);
  1074. var
  1075. Value: Single;
  1076. Color: TColor32Entry;
  1077. begin
  1078. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  1079. Color := TColor32Entry(SelectedColor);
  1080. Color.A := Round(Value * 255);
  1081. SelectedColor := Color.ARGB;
  1082. end;
  1083. procedure TCustomColorPickerRGBA.MouseDown(Button: TMouseButton;
  1084. Shift: TShiftState; X, Y: Integer);
  1085. var
  1086. Index: Integer;
  1087. begin
  1088. if (Button = mbLeft) and (X >= 3) or (X <= Width - 3) then
  1089. begin
  1090. Index := Y div (FBarHeight + FSpaceHeight);
  1091. case Index of
  1092. 0:
  1093. FAdjustCalc := PickRed;
  1094. 1:
  1095. FAdjustCalc := PickGreen;
  1096. 2:
  1097. FAdjustCalc := PickBlue;
  1098. 3:
  1099. FAdjustCalc := PickAlpha;
  1100. end;
  1101. end;
  1102. if Assigned(FAdjustCalc) then
  1103. FAdjustCalc(X, Y);
  1104. inherited;
  1105. end;
  1106. procedure TCustomColorPickerRGBA.MouseMove(Shift: TShiftState; X, Y: Integer);
  1107. begin
  1108. if (ssLeft in Shift) and Assigned(FAdjustCalc) then
  1109. FAdjustCalc(X, Y);
  1110. inherited;
  1111. end;
  1112. procedure TCustomColorPickerRGBA.MouseUp(Button: TMouseButton;
  1113. Shift: TShiftState; X, Y: Integer);
  1114. begin
  1115. FAdjustCalc := nil;
  1116. inherited;
  1117. end;
  1118. procedure TCustomColorPickerRGBA.PaintColorPicker;
  1119. var
  1120. Polygon: TArrayOfFloatPoint;
  1121. InvertFiller: TInvertPolygonFiller;
  1122. procedure RenderPolygon;
  1123. begin
  1124. case FVisualAidOptions.RenderType of
  1125. vatInvert:
  1126. PolygonFS(FBuffer, Polygon, InvertFiller);
  1127. vatBW:
  1128. if Intensity(FSelectedColor) < 127 then
  1129. PolygonFS(FBuffer, Polygon, clWhite32)
  1130. else
  1131. PolygonFS(FBuffer, Polygon, clBlack32);
  1132. else
  1133. PolygonFS(FBuffer, Polygon, FVisualAidOptions.Color);
  1134. end;
  1135. end;
  1136. var
  1137. X, Y, Index: Integer;
  1138. ScanLine: PColor32Array;
  1139. Value: Single;
  1140. LeftColor, RightColor: TColor32Entry;
  1141. ValueRect: TRect;
  1142. OddY: Boolean;
  1143. BorderOffset: Integer;
  1144. GradientFiller: TLinearGradientPolygonFiller;
  1145. const
  1146. CByteScale = 1 / 255;
  1147. CCheckerBoardColor: array [Boolean] of TColor32 = ($FFA0A0A0, $FF5F5F5F);
  1148. begin
  1149. FBuffer.Clear(Color32(Color));
  1150. BorderOffset := Integer(FBorder);
  1151. SetLength(Polygon, 3);
  1152. InvertFiller := TInvertPolygonFiller.Create;
  1153. try
  1154. for Index := 0 to 3 do
  1155. begin
  1156. ValueRect := Rect(3, Index * (FBarHeight + FSpaceHeight),
  1157. Width - 3, Index * (FBarHeight + FSpaceHeight) + FBarHeight);
  1158. LeftColor := TColor32Entry(FSelectedColor);
  1159. RightColor := TColor32Entry(FSelectedColor);
  1160. case Index of
  1161. 0:
  1162. begin
  1163. Value := LeftColor.R * CByteScale;
  1164. LeftColor.R := 0;
  1165. RightColor.R := 255;
  1166. LeftColor.A := 255;
  1167. RightColor.A := 255;
  1168. end;
  1169. 1:
  1170. begin
  1171. Value := LeftColor.G * CByteScale;
  1172. LeftColor.G := 0;
  1173. RightColor.G := 255;
  1174. LeftColor.A := 255;
  1175. RightColor.A := 255;
  1176. end;
  1177. 2:
  1178. begin
  1179. Value := LeftColor.B * CByteScale;
  1180. LeftColor.B := 0;
  1181. RightColor.B := 255;
  1182. LeftColor.A := 255;
  1183. RightColor.A := 255;
  1184. end;
  1185. 3:
  1186. begin
  1187. Value := LeftColor.A * CByteScale;
  1188. LeftColor.A := 0;
  1189. RightColor.A := 255;
  1190. for Y := ValueRect.Top to Min(ValueRect.Bottom, Height) - 1 do
  1191. begin
  1192. OddY := Odd(Y div 8);
  1193. ScanLine := FBuffer.ScanLine[Y];
  1194. for X := ValueRect.Left to ValueRect.Right - 1 do
  1195. ScanLine^[X] := CCheckerBoardColor[Odd(X shr 3) = OddY];
  1196. end;
  1197. end;
  1198. else
  1199. Exit;
  1200. end;
  1201. GradientFiller := TLinearGradientPolygonFiller.Create;
  1202. try
  1203. GradientFiller.SimpleGradientX(ValueRect.Left, LeftColor.ARGB,
  1204. ValueRect.Right, RightColor.ARGB);
  1205. PolygonFS(FBuffer, Rectangle(FloatRect(ValueRect)), GradientFiller);
  1206. finally
  1207. GradientFiller.Free;
  1208. end;
  1209. if FBorder then
  1210. begin
  1211. FBuffer.FrameRectTS(ValueRect, $DF000000);
  1212. FBuffer.RaiseRectTS(ValueRect.Left + 1, ValueRect.Top + 1,
  1213. ValueRect.Right - 1, ValueRect.Bottom - 1, 20);
  1214. end;
  1215. Polygon[0] := FloatPoint(3 + Value * (Width - 6), ValueRect.Bottom - BorderOffset - 5);
  1216. Polygon[1] := FloatPoint(Polygon[0].X - 3, Polygon[0].Y + 5);
  1217. Polygon[2] := FloatPoint(Polygon[0].X + 3, Polygon[0].Y + 5);
  1218. RenderPolygon;
  1219. Polygon[0].Y := ValueRect.Top + BorderOffset + 5;
  1220. Polygon[1].Y := ValueRect.Top + BorderOffset;
  1221. Polygon[2].Y := ValueRect.Top + BorderOffset;
  1222. RenderPolygon;
  1223. end;
  1224. finally
  1225. InvertFiller.Free;
  1226. end;
  1227. inherited;
  1228. end;
  1229. procedure TCustomColorPickerRGBA.SetBarHeight(const Value: Integer);
  1230. begin
  1231. if FBarHeight <> Value then
  1232. begin
  1233. FBarHeight := Value;
  1234. Invalidate;
  1235. end;
  1236. end;
  1237. procedure TCustomColorPickerRGBA.SetSpaceHeight(const Value: Integer);
  1238. begin
  1239. if FSpaceHeight <> Value then
  1240. begin
  1241. FSpaceHeight := Value;
  1242. Invalidate;
  1243. end;
  1244. end;
  1245. { TCustomColorPickerHS }
  1246. constructor TCustomColorPickerHS.Create(AOwner: TComponent);
  1247. var
  1248. Luminance: Single;
  1249. begin
  1250. inherited;
  1251. FVisualAidOptions.Color := clBlack32;
  1252. FVisualAidOptions.LineWidth := 1.5;
  1253. RGBtoHSL(FSelectedColor, FHue, FSaturation, Luminance);
  1254. end;
  1255. procedure TCustomColorPickerHS.MouseDown(Button: TMouseButton;
  1256. Shift: TShiftState; X, Y: Integer);
  1257. begin
  1258. if Button = mbLeft then
  1259. PickHue(X, Y);
  1260. inherited;
  1261. end;
  1262. procedure TCustomColorPickerHS.MouseMove(Shift: TShiftState; X, Y: Integer);
  1263. begin
  1264. if (ssLeft in Shift) then
  1265. PickHue(X, Y);
  1266. inherited;
  1267. end;
  1268. procedure TCustomColorPickerHS.PaintColorPicker;
  1269. var
  1270. X, Y: Integer;
  1271. Saturation, InvWidth, InvHeight: Single;
  1272. Line: PColor32Array;
  1273. Pos: TFloatPoint;
  1274. VectorData: TArrayOfArrayOfFloatPoint;
  1275. InvertFiller: TInvertPolygonFiller;
  1276. begin
  1277. InvWidth := 1 / FBuffer.Width;
  1278. InvHeight := 1 / FBuffer.Height;
  1279. if FWebSafe then
  1280. for Y := 0 to FBuffer.Height - 1 do
  1281. begin
  1282. Line := FBuffer.ScanLine[Y];
  1283. Saturation := 1 - Y * InvHeight;
  1284. for X := 0 to FBuffer.Width - 1 do
  1285. begin
  1286. Line^[X] := HSLtoRGB(X * InvWidth, Saturation, 0.5);
  1287. RoundToWebSafe(Line^[X]);
  1288. end;
  1289. end
  1290. else
  1291. for Y := 0 to FBuffer.Height - 1 do
  1292. begin
  1293. Line := FBuffer.ScanLine[Y];
  1294. Saturation := 1 - Y * InvHeight;
  1295. for X := 0 to FBuffer.Width - 1 do
  1296. Line^[X] := HSLtoRGB(X * InvWidth, Saturation, 0.5);
  1297. end;
  1298. Pos.X := Round(FHue * FBuffer.Width);
  1299. Pos.Y := Round((1 - FSaturation) * FBuffer.Height);
  1300. case FMarkerType of
  1301. mtCross:
  1302. begin
  1303. SetLength(VectorData, 4);
  1304. VectorData[0] := HorzLine(Pos.X - 5, Pos.Y, Pos.X - 2);
  1305. VectorData[1] := HorzLine(Pos.X + 2, Pos.Y, Pos.X + 5);
  1306. VectorData[2] := VertLine(Pos.X, Pos.Y - 5, Pos.Y - 2);
  1307. VectorData[3] := VertLine(Pos.X, Pos.Y + 2, Pos.Y + 5);
  1308. case FVisualAidOptions.RenderType of
  1309. vatSolid:
  1310. PolyPolylineFS(FBuffer, VectorData, FVisualAidOptions.Color, False, FVisualAidOptions.LineWidth);
  1311. vatInvert:
  1312. begin
  1313. InvertFiller := TInvertPolygonFiller.Create;
  1314. try
  1315. PolyPolylineFS(FBuffer, VectorData, InvertFiller, False, FVisualAidOptions.LineWidth)
  1316. finally
  1317. InvertFiller.Free;
  1318. end;
  1319. end;
  1320. vatBW:
  1321. PolyPolylineFS(FBuffer, VectorData, FVisualAidOptions.Color, False, FVisualAidOptions.LineWidth);
  1322. end;
  1323. end;
  1324. mtCircle:
  1325. begin
  1326. SetLength(VectorData, 1);
  1327. VectorData[0] := Circle(Pos, 4, 12);
  1328. PolygonFS(FBuffer, VectorData[0], FSelectedColor);
  1329. case FVisualAidOptions.RenderType of
  1330. vatSolid:
  1331. PolylineFS(FBuffer, VectorData[0], FVisualAidOptions.Color, True, FVisualAidOptions.LineWidth);
  1332. vatInvert:
  1333. begin
  1334. InvertFiller := TInvertPolygonFiller.Create;
  1335. try
  1336. PolylineFS(FBuffer, VectorData[0], InvertFiller, True, 1.5)
  1337. finally
  1338. InvertFiller.Free;
  1339. end;
  1340. end;
  1341. vatBW:
  1342. PolylineFS(FBuffer, VectorData[0], FVisualAidOptions.Color, True, 1.5);
  1343. end;
  1344. end;
  1345. end;
  1346. end;
  1347. procedure TCustomColorPickerHS.ApplyHS;
  1348. var
  1349. H, S, L: Single;
  1350. begin
  1351. RGBtoHSL(FSelectedColor, H, S, L);
  1352. Inc(FLockValues);
  1353. try
  1354. SelectedColor := HSLtoRGB(FHue, FSaturation, L, SelectedColor shr 24);
  1355. finally
  1356. Dec(FLockValues);
  1357. end;
  1358. end;
  1359. procedure TCustomColorPickerHS.PickHue(X, Y: Single);
  1360. begin
  1361. FHue := EnsureRange(X / FBuffer.Width, 0, 1);
  1362. FSaturation := EnsureRange(1 - Y / FBuffer.Height, 0, 1);
  1363. ApplyHS;
  1364. end;
  1365. procedure TCustomColorPickerHS.SelectedColorChanged;
  1366. var
  1367. H, S, L: Single;
  1368. begin
  1369. if (FLockValues = 0) then
  1370. begin
  1371. RGBtoHSL(FSelectedColor, H, S, L);
  1372. FHue := H;
  1373. FSaturation := S;
  1374. end;
  1375. inherited;
  1376. end;
  1377. procedure TCustomColorPickerHS.SetHue(const Value: Single);
  1378. begin
  1379. if FHue <> Value then
  1380. begin
  1381. FHue := Value;
  1382. ApplyHS;
  1383. end;
  1384. end;
  1385. procedure TCustomColorPickerHS.SetSaturation(const Value: Single);
  1386. begin
  1387. if FSaturation <> Value then
  1388. begin
  1389. FSaturation := Value;
  1390. ApplyHS;
  1391. end;
  1392. end;
  1393. procedure TCustomColorPickerHS.SetMarkerType(const Value: TMarkerType);
  1394. begin
  1395. if FMarkerType <> Value then
  1396. begin
  1397. FMarkerType := Value;
  1398. Invalidate;
  1399. end;
  1400. end;
  1401. { TCustomColorPickerHSV }
  1402. constructor TCustomColorPickerHSV.Create(AOwner: TComponent);
  1403. begin
  1404. inherited Create(AOwner);
  1405. FVisualAid := [vaHueLine, vaSaturationCircle, vaSelection];
  1406. FVisualAidOptions.LineWidth := 1.5;
  1407. RGBToHSV(FSelectedColor, FHue, FSaturation, FValue);
  1408. { Setting a initial size here will cause the control to crash under LCL }
  1409. {$IFNDEF FPC}
  1410. Height := 192;
  1411. Width := 256;
  1412. {$ENDIF}
  1413. end;
  1414. procedure TCustomColorPickerHSV.PaintColorPicker;
  1415. var
  1416. Polygon: TArrayOfFloatPoint;
  1417. ValueRect: TRect;
  1418. GradientFiller: TLinearGradientPolygonFiller;
  1419. HueSaturationFiller: THueSaturationCirclePolygonFiller;
  1420. InvertFiller: TInvertPolygonFiller;
  1421. LineWidth: Single;
  1422. begin
  1423. FBuffer.Clear(Color32(Color));
  1424. Polygon := Circle(FCenter, FRadius, FCircleSteps);
  1425. HueSaturationFiller := THueSaturationCirclePolygonFiller.Create(FCenter,
  1426. FRadius, FValue, FWebSafe);
  1427. try
  1428. PolygonFS(FBuffer, Polygon, HueSaturationFiller);
  1429. finally
  1430. HueSaturationFiller.Free;
  1431. end;
  1432. if FBorder then
  1433. PolylineFS(FBuffer, Polygon, clBlack32, True, 1);
  1434. LineWidth := FVisualAidOptions.LineWidth;
  1435. InvertFiller := TInvertPolygonFiller.Create;
  1436. try
  1437. if vaSaturationCircle in FVisualAid then
  1438. begin
  1439. Polygon := Circle(FCenter, FSaturation * FRadius, -1);
  1440. case FVisualAidOptions.RenderType of
  1441. vatInvert:
  1442. PolylineFS(FBuffer, Polygon, InvertFiller, True, LineWidth);
  1443. vatBW:
  1444. if Intensity(FSelectedColor) < 127 then
  1445. PolylineFS(FBuffer, Polygon, clWhite32, True, LineWidth)
  1446. else
  1447. PolylineFS(FBuffer, Polygon, clBlack32, True, LineWidth);
  1448. else
  1449. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, True, LineWidth);
  1450. end;
  1451. end;
  1452. if vaHueLine in FVisualAid then
  1453. begin
  1454. SetLength(Polygon, 2);
  1455. Polygon[0] := FCenter;
  1456. Polygon[1] := FloatPoint(
  1457. FCenter.X - FRadius * Cos(2 * Pi * FHue),
  1458. FCenter.Y - FRadius * Sin(2 * Pi * FHue));
  1459. case FVisualAidOptions.RenderType of
  1460. vatInvert:
  1461. PolylineFS(FBuffer, Polygon, InvertFiller, False, LineWidth);
  1462. vatBW:
  1463. if Intensity(FSelectedColor) < 127 then
  1464. PolylineFS(FBuffer, Polygon, clWhite32, False, LineWidth)
  1465. else
  1466. PolylineFS(FBuffer, Polygon, clBlack32, False, LineWidth);
  1467. else
  1468. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, False, LineWidth);
  1469. end;
  1470. end;
  1471. if vaSelection in FVisualAid then
  1472. begin
  1473. Polygon := Circle(
  1474. FCenter.X - FSaturation * FRadius * Cos(2 * Pi * FHue),
  1475. FCenter.Y - FSaturation * FRadius * Sin(2 * Pi * FHue), 4, 8);
  1476. PolygonFS(FBuffer, Polygon, FSelectedColor);
  1477. case FVisualAidOptions.RenderType of
  1478. vatInvert:
  1479. PolylineFS(FBuffer, Polygon, InvertFiller, True, LineWidth);
  1480. vatBW:
  1481. if Intensity(FSelectedColor) < 127 then
  1482. PolylineFS(FBuffer, Polygon, clWhite32, True, LineWidth)
  1483. else
  1484. PolylineFS(FBuffer, Polygon, clBlack32, True, LineWidth);
  1485. else
  1486. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, True, LineWidth);
  1487. end;
  1488. end;
  1489. ValueRect := Rect(Width - 24, 8, Width - 8, Height - 8);
  1490. Polygon := Rectangle(FloatRect(ValueRect));
  1491. GradientFiller := TLinearGradientPolygonFiller.Create;
  1492. try
  1493. GradientFiller.SimpleGradientY(ValueRect.Top, clWhite32,
  1494. ValueRect.Bottom, clBlack32);
  1495. PolygonFS(FBuffer, Polygon, GradientFiller);
  1496. finally
  1497. GradientFiller.Free;
  1498. end;
  1499. SetLength(Polygon, 3);
  1500. Polygon[0] := FloatPoint(Width - 8, 8 + (1 - FValue) * (Height - 16));
  1501. Polygon[1] := FloatPoint(Polygon[0].X + 7, Polygon[0].Y - 4);
  1502. Polygon[2] := FloatPoint(Polygon[0].X + 7, Polygon[0].Y + 4);
  1503. case FVisualAidOptions.RenderType of
  1504. vatInvert:
  1505. PolygonFS(FBuffer, Polygon, InvertFiller);
  1506. vatBW:
  1507. if Intensity(FSelectedColor) < 127 then
  1508. PolygonFS(FBuffer, Polygon, clWhite32)
  1509. else
  1510. PolygonFS(FBuffer, Polygon, clBlack32);
  1511. else
  1512. PolygonFS(FBuffer, Polygon, FVisualAidOptions.Color);
  1513. end;
  1514. if FBorder then
  1515. begin
  1516. FBuffer.FrameRectTS(ValueRect, $DF000000);
  1517. FBuffer.RaiseRectTS(ValueRect.Left + 1, ValueRect.Top + 1,
  1518. ValueRect.Right - 1, ValueRect.Bottom - 1, 20);
  1519. end;
  1520. finally
  1521. InvertFiller.Free;
  1522. end;
  1523. inherited;
  1524. end;
  1525. procedure TCustomColorPickerHSV.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
  1526. Y: Integer);
  1527. begin
  1528. if Button = mbLeft then
  1529. begin
  1530. if X > Width - 28 then
  1531. FAdjustCalc := PickValue
  1532. else
  1533. FAdjustCalc := PickHue;
  1534. end;
  1535. if Assigned(FAdjustCalc) then
  1536. FAdjustCalc(X, Y);
  1537. inherited;
  1538. end;
  1539. procedure TCustomColorPickerHSV.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  1540. Y: Integer);
  1541. begin
  1542. FAdjustCalc := nil;
  1543. inherited;
  1544. end;
  1545. procedure TCustomColorPickerHSV.MouseMove(Shift: TShiftState; X, Y: Integer);
  1546. begin
  1547. if (ssLeft in Shift) and Assigned(FAdjustCalc) then
  1548. FAdjustCalc(X, Y);
  1549. inherited;
  1550. end;
  1551. procedure TCustomColorPickerHSV.Resize;
  1552. begin
  1553. inherited;
  1554. if Height < Width then
  1555. begin
  1556. FRadius := Min(0.5 * Width - 1 - 16, 0.5 * Height - 1);
  1557. FCircleSteps := CalculateCircleSteps(FRadius);
  1558. FCenter := FloatPoint(0.5 * Width - 16, 0.5 * Height);
  1559. end
  1560. else
  1561. begin
  1562. FRadius := Min(0.5 * Width - 1, 0.5 * Height - 1 - 16);
  1563. FCircleSteps := CalculateCircleSteps(FRadius);
  1564. FCenter := FloatPoint(0.5 * Width, 0.5 * Height - 16);
  1565. end;
  1566. end;
  1567. procedure TCustomColorPickerHSV.ApplyHSV;
  1568. begin
  1569. Inc(FLockValues);
  1570. try
  1571. SelectedColor := HSVtoRGB(FHue, FSaturation, FValue, SelectedColor shr 24);
  1572. finally
  1573. Dec(FLockValues);
  1574. end;
  1575. end;
  1576. procedure TCustomColorPickerHSV.PickHue(X, Y: Single);
  1577. const
  1578. CTwoPiInv = 1 / (2 * Pi);
  1579. begin
  1580. FHue := 0.5 + ArcTan2(Y - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  1581. FSaturation := Sqrt(Sqr(Y - FCenter.Y) + Sqr(X - FCenter.X)) / FRadius;
  1582. if FSaturation > 1 then
  1583. FSaturation := 1;
  1584. ApplyHSV;
  1585. end;
  1586. procedure TCustomColorPickerHSV.PickValue(X, Y: Single);
  1587. begin
  1588. Value := 1 - EnsureRange((Y - 8) / (Height - 16), 0, 1);
  1589. end;
  1590. procedure TCustomColorPickerHSV.SetHue(const Value: Single);
  1591. begin
  1592. if FHue <> Value then
  1593. begin
  1594. FHue := Value;
  1595. ApplyHSV;
  1596. end;
  1597. end;
  1598. procedure TCustomColorPickerHSV.SetSaturation(const Value: Single);
  1599. begin
  1600. if FSaturation <> Value then
  1601. begin
  1602. FSaturation := Value;
  1603. ApplyHSV;
  1604. end;
  1605. end;
  1606. procedure TCustomColorPickerHSV.SelectedColorChanged;
  1607. var
  1608. H, S, V: Single;
  1609. begin
  1610. if (FLockValues = 0) then
  1611. begin
  1612. RGBtoHSV(FSelectedColor, H, S, V);
  1613. FHue := H;
  1614. FSaturation := S;
  1615. FValue := V;
  1616. end;
  1617. inherited;
  1618. end;
  1619. procedure TCustomColorPickerHSV.SetValue(const Value: Single);
  1620. begin
  1621. if FValue <> Value then
  1622. begin
  1623. FValue := Value;
  1624. ApplyHSV;
  1625. end;
  1626. end;
  1627. procedure TCustomColorPickerHSV.SetVisualAid(const Value: TVisualAid);
  1628. begin
  1629. if FVisualAid <> Value then
  1630. begin
  1631. FVisualAid := Value;
  1632. Invalidate;
  1633. end;
  1634. end;
  1635. { TCustomColorPickerGTK }
  1636. constructor TCustomColorPickerGTK.Create(AOwner: TComponent);
  1637. begin
  1638. inherited Create(AOwner);
  1639. FVisualAid := [vagHueLine, vagSelection];
  1640. FVisualAidOptions.RenderType := vatBW;
  1641. FVisualAidOptions.LineWidth := 2;
  1642. RGBToHSV(FSelectedColor, FHue, FSaturation, FValue);
  1643. { Setting a initial size here will cause the control to crash under LCL }
  1644. {$IFNDEF FPC}
  1645. Height := 192;
  1646. Width := 192;
  1647. {$ENDIF}
  1648. end;
  1649. procedure TCustomColorPickerGTK.PaintColorPicker;
  1650. var
  1651. Polygon: TArrayOfFloatPoint;
  1652. HueBand: TArrayOfArrayOfFloatPoint;
  1653. GradientFiller: TBarycentricGradientPolygonFillerEx;
  1654. HueFiller: THueCirclePolygonFiller;
  1655. InvertFiller: TInvertPolygonFiller;
  1656. Pos: TFloatPoint;
  1657. HalfInnerRadius: Single;
  1658. LineWidth: Single;
  1659. const
  1660. CY = 1.7320508075688772935274463415059;
  1661. begin
  1662. FBuffer.Clear(Color32(Color));
  1663. Polygon := Circle(FCenter, 0.5 * (FRadius + FInnerRadius), FCircleSteps);
  1664. HueBand := BuildPolyPolyline(PolyPolygon(Polygon), True, FRadius - FInnerRadius);
  1665. HueFiller := THueCirclePolygonFiller.Create(FCenter, FWebSafe);
  1666. try
  1667. PolyPolygonFS(FBuffer, HueBand, HueFiller);
  1668. finally
  1669. HueFiller.Free;
  1670. end;
  1671. LineWidth := FVisualAidOptions.LineWidth;
  1672. if vagHueLine in FVisualAid then
  1673. begin
  1674. SetLength(Polygon, 2);
  1675. Polygon[0] := FloatPoint(
  1676. FCenter.X - FInnerRadius * Cos(2 * Pi * FHue),
  1677. FCenter.Y - FInnerRadius * Sin(2 * Pi * FHue));
  1678. Polygon[1] := FloatPoint(
  1679. FCenter.X - FRadius * Cos(2 * Pi * FHue),
  1680. FCenter.Y - FRadius * Sin(2 * Pi * FHue));
  1681. case FVisualAidOptions.RenderType of
  1682. vatSolid:
  1683. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, False, LineWidth);
  1684. vatInvert:
  1685. begin
  1686. InvertFiller := TInvertPolygonFiller.Create;
  1687. try
  1688. PolylineFS(FBuffer, Polygon, InvertFiller, False, LineWidth);
  1689. finally
  1690. InvertFiller.Free;
  1691. end;
  1692. end;
  1693. vatBW:
  1694. if Intensity(HSVtoRGB(FHue, 1, 1)) < 127 then
  1695. PolylineFS(FBuffer, Polygon, $F0FFFFFF, True, LineWidth)
  1696. else
  1697. PolylineFS(FBuffer, Polygon, $F0000000, True, LineWidth)
  1698. end;
  1699. end;
  1700. GR32_Math.SinCos(2 * Pi * FHue, Pos.Y, Pos.X);
  1701. SetLength(Polygon, 3);
  1702. Polygon[0] := FloatPoint(
  1703. FCenter.X - FInnerRadius * Pos.X,
  1704. FCenter.Y - FInnerRadius * Pos.Y);
  1705. HalfInnerRadius := 0.5 * FInnerRadius;
  1706. Pos := FloatPoint(Pos.X + CY * Pos.Y, Pos.X * CY - Pos.Y);
  1707. Polygon[1] := FloatPoint(
  1708. FCenter.X + HalfInnerRadius * Pos.X,
  1709. FCenter.Y - HalfInnerRadius * Pos.Y);
  1710. HalfInnerRadius := 0.5 * HalfInnerRadius;
  1711. Pos := FloatPoint(Pos.X - CY * Pos.Y, Pos.Y + Pos.X * CY);
  1712. Polygon[2] := FloatPoint(
  1713. FCenter.X - HalfInnerRadius * Pos.X,
  1714. FCenter.Y + HalfInnerRadius * Pos.Y);
  1715. GradientFiller := TBarycentricGradientPolygonFillerEx.Create;
  1716. try
  1717. GradientFiller.SetPoints(Polygon);
  1718. GradientFiller.Color[0] := HSVtoRGB(Hue, 1, 1);
  1719. GradientFiller.Color[1] := clWhite32;
  1720. GradientFiller.Color[2] := clBlack32;
  1721. GradientFiller.WebSafe := FWebSafe;
  1722. PolygonFS(FBuffer, Polygon, GradientFiller);
  1723. finally
  1724. GradientFiller.Free;
  1725. end;
  1726. if FBorder then
  1727. begin
  1728. PolyPolygonFS(FBuffer, BuildPolyPolyline(HueBand, True, 1), clBlack32);
  1729. PolylineFS(FBuffer, Polygon, clBlack32, True, 1);
  1730. end;
  1731. if vagSelection in FVisualAid then
  1732. begin
  1733. Polygon := Circle(
  1734. Polygon[2].X + FValue * (Polygon[1].X + FSaturation * (Polygon[0].X - Polygon[1].X) - Polygon[2].X),
  1735. Polygon[2].Y + FValue * (Polygon[1].Y + FSaturation * (Polygon[0].Y - Polygon[1].Y) - Polygon[2].Y),
  1736. 4, 12);
  1737. PolygonFS(FBuffer, Polygon, FSelectedColor);
  1738. case FVisualAidOptions.RenderType of
  1739. vatSolid:
  1740. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, True, LineWidth);
  1741. vatInvert:
  1742. begin
  1743. InvertFiller := TInvertPolygonFiller.Create;
  1744. try
  1745. PolylineFS(FBuffer, Polygon, InvertFiller, True, LineWidth);
  1746. finally
  1747. InvertFiller.Free;
  1748. end;
  1749. end;
  1750. vatBW:
  1751. if Intensity(FSelectedColor) < 127 then
  1752. PolylineFS(FBuffer, Polygon, clWhite32, True, LineWidth)
  1753. else
  1754. PolylineFS(FBuffer, Polygon, clBlack32, True, LineWidth)
  1755. end
  1756. end;
  1757. inherited;
  1758. end;
  1759. procedure TCustomColorPickerGTK.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
  1760. Y: Integer);
  1761. begin
  1762. if Button = mbLeft then
  1763. begin
  1764. if Sqrt(Sqr(X - FCenter.X) + Sqr(Y - FCenter.Y)) > FInnerRadius then
  1765. FAdjustCalc := PickHue
  1766. else
  1767. FAdjustCalc := PickSaturationValue;
  1768. end;
  1769. if Assigned(FAdjustCalc) then
  1770. FAdjustCalc(X, Y);
  1771. inherited;
  1772. end;
  1773. procedure TCustomColorPickerGTK.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  1774. Y: Integer);
  1775. begin
  1776. FAdjustCalc := nil;
  1777. inherited;
  1778. end;
  1779. procedure TCustomColorPickerGTK.MouseMove(Shift: TShiftState; X, Y: Integer);
  1780. begin
  1781. if (ssLeft in Shift) and Assigned(FAdjustCalc) then
  1782. FAdjustCalc(X, Y);
  1783. inherited;
  1784. end;
  1785. procedure TCustomColorPickerGTK.Resize;
  1786. begin
  1787. inherited;
  1788. Radius := Min(0.5 * Width - 1, 0.5 * Height - 1);
  1789. Center := FloatPoint(0.5 * Width, 0.5 * Height);
  1790. end;
  1791. procedure TCustomColorPickerGTK.ApplyHSV;
  1792. begin
  1793. Inc(FLockValues);
  1794. try
  1795. SelectedColor := HSVtoRGB(FHue, FSaturation, FValue, SelectedColor shr 24);
  1796. finally
  1797. Dec(FLockValues);
  1798. end;
  1799. end;
  1800. procedure TCustomColorPickerGTK.PickHue(X, Y: Single);
  1801. const
  1802. CTwoPiInv = 1 / (2 * Pi);
  1803. begin
  1804. Hue := 0.5 + ArcTan2(Y - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  1805. end;
  1806. procedure TCustomColorPickerGTK.PickSaturationValue(X, Y: Single);
  1807. var
  1808. Sampler: TBarycentricGradientSampler;
  1809. Pos: TFloatPoint;
  1810. Color: TColor32;
  1811. H: Single;
  1812. const
  1813. CY = 1.7320508075688772935274463415059;
  1814. begin
  1815. Sampler := TBarycentricGradientSampler.Create;
  1816. try
  1817. GR32_Math.SinCos(2 * Pi * FHue, Pos.Y, Pos.X);
  1818. Sampler.Point[0] := FloatPoint(
  1819. FCenter.X - FInnerRadius * Pos.X,
  1820. FCenter.Y - FInnerRadius * Pos.Y);
  1821. Pos := FloatPoint(-0.5 * (Pos.X + CY * Pos.Y), 0.5 * (Pos.X * CY - Pos.Y));
  1822. Sampler.Point[1] := FloatPoint(
  1823. FCenter.X - FInnerRadius * Pos.X,
  1824. FCenter.Y - FInnerRadius * Pos.Y);
  1825. Pos := FloatPoint(-0.5 * (Pos.X + CY * Pos.Y), 0.5 * (Pos.X * CY - Pos.Y));
  1826. Sampler.Point[2] := FloatPoint(
  1827. FCenter.X - FInnerRadius * Pos.X,
  1828. FCenter.Y - FInnerRadius * Pos.Y);
  1829. Sampler.Color[0] := HSVtoRGB(FHue, 1, 1);
  1830. Sampler.Color[1] := clWhite32;
  1831. Sampler.Color[2] := clBlack32;
  1832. Sampler.PrepareSampling;
  1833. Color := Sampler.GetSampleFloatInTriangle(X, Y);
  1834. finally
  1835. Sampler.Free;
  1836. end;
  1837. RGBtoHSV(Color, H, FSaturation, FValue);
  1838. ApplyHSV;
  1839. end;
  1840. procedure TCustomColorPickerGTK.SetHue(const Value: Single);
  1841. begin
  1842. if FHue <> Value then
  1843. begin
  1844. FHue := Value;
  1845. ApplyHSV;
  1846. end;
  1847. end;
  1848. procedure TCustomColorPickerGTK.SetRadius(const Value: TFloat);
  1849. begin
  1850. if FRadius <> Value then
  1851. begin
  1852. FRadius := Value;
  1853. FInnerRadius := 0.8 * FRadius;
  1854. FCircleSteps := CalculateCircleSteps(FRadius);
  1855. end;
  1856. end;
  1857. procedure TCustomColorPickerGTK.SetSaturation(const Value: Single);
  1858. begin
  1859. if FSaturation <> Value then
  1860. begin
  1861. FSaturation := Value;
  1862. ApplyHSV;
  1863. end;
  1864. end;
  1865. procedure TCustomColorPickerGTK.SelectedColorChanged;
  1866. var
  1867. H, S, V: Single;
  1868. begin
  1869. if (FLockValues = 0) then
  1870. begin
  1871. RGBtoHSV(FSelectedColor, H, S, V);
  1872. FHue := H;
  1873. FSaturation := S;
  1874. FValue := V;
  1875. end;
  1876. inherited;
  1877. end;
  1878. procedure TCustomColorPickerGTK.SetValue(const Value: Single);
  1879. begin
  1880. if FValue <> Value then
  1881. begin
  1882. FValue := Value;
  1883. ApplyHSV;
  1884. end;
  1885. end;
  1886. procedure TCustomColorPickerGTK.SetVisualAid(const Value: TVisualAidGTK);
  1887. begin
  1888. if FVisualAid <> Value then
  1889. begin
  1890. FVisualAid := Value;
  1891. Invalidate;
  1892. end;
  1893. end;
  1894. end.