TCFresnelCSS.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. {
  2. *****************************************************************************
  3. This file is part of Fresnel.
  4. See the file COPYING.modifiedLGPL.txt, included in this distribution,
  5. for details about the license.
  6. *****************************************************************************
  7. Examples:
  8. ./testfresnelbase --suite=TTestFresnelCSS.TestEmptyViewport
  9. }
  10. unit TCFresnelCSS;
  11. {$mode ObjFPC}{$H+}
  12. interface
  13. uses
  14. Classes, SysUtils, Math, fpcunit, testregistry, FpImage, Fresnel.DOM,
  15. Fresnel.Renderer, Fresnel.Layouter, Fresnel.Classes, Fresnel.Controls,
  16. Avl_Tree, UTF8Utils;
  17. type
  18. { TTestFont }
  19. TTestFont = class(TInterfacedObject,IFresnelFont)
  20. public
  21. Desc: TFresnelFontDesc;
  22. function GetAlternates: string;
  23. function GetCaps: TFresnelCSSFontVarCaps;
  24. function GetDescription: String;
  25. function GetEastAsians: TFresnelCSSFontVarEastAsians;
  26. function GetEmoji: TFresnelCSSFontVarEmoji;
  27. function GetFamily: string;
  28. function GetKerning: TFresnelCSSKerning;
  29. function GetLigatures: TFresnelCSSFontVarLigaturesSet;
  30. function GetNumerics: TFresnelCSSFontVarNumerics;
  31. function GetPosition: TFresnelCSSFontVarPosition;
  32. function GetSize: double;
  33. function GetStyle: string;
  34. function GetWidth: double;
  35. function GetWeight: double;
  36. function TextSize(const aText: string): TFresnelPoint;
  37. function TextSizeMaxWidth(const aText: string; MaxWidth: TFresnelLength): TFresnelPoint;
  38. function GetTool: TObject;
  39. end;
  40. { TTestFontEngine }
  41. TTestFontEngine = class(TFresnelFontEngine)
  42. private
  43. FFonts: TAVLTree; // tree of TTestFont sorted with CompareTestFont
  44. protected
  45. public
  46. constructor Create(AOwner: TComponent); override;
  47. destructor Destroy; override;
  48. function FindFont(const Desc: TFresnelFontDesc): TTestFont; virtual;
  49. function Allocate(const Desc: TFresnelFontDesc): IFresnelFont; override;
  50. end;
  51. { TTestRenderer }
  52. TTestRenderer = class(TFresnelRenderer)
  53. protected
  54. FSavedContexts: TFresnelRectDynArray;
  55. public
  56. ClipR: TFresnelRect;
  57. procedure Arc(const aColor: TFPColor; const aCenter, aRadii: TFresnelPoint;
  58. aStartAngle: TFresnelLength=0; aStopAngle: TFresnelLength=Tau); override;
  59. procedure ClipRect(const aRect: TFresnelRect); override;
  60. procedure FillRect(const aColor: TFPColor; const aRect: TFresnelRect); override;
  61. procedure Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength); override;
  62. procedure Polygon(const aColor: TFPColor; const p: PFresnelPoint;
  63. Count: integer); override;
  64. procedure Restore; override;
  65. procedure RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect; Fill: Boolean);
  66. override;
  67. procedure Save; override;
  68. procedure TextOut(const aLeft, aTop: TFresnelLength;
  69. const aFont: IFresnelFont; const aColor: TFPColor;
  70. const aText: string); override;
  71. procedure DrawImage(const aLeft, aTop, aWidth, aHeight: TFresnelLength; const aImage: TFPCustomImage); override;
  72. constructor Create(AOwner: TComponent); override;
  73. end;
  74. { TTestViewport }
  75. TTestViewport = class(TFresnelViewport)
  76. private
  77. fDrawing: Boolean;
  78. FLayoutQueued: boolean;
  79. FRenderer: TFresnelRenderer;
  80. protected
  81. procedure SetWidth(AValue: TFresnelLength); override;
  82. procedure SetHeight(AValue: TFresnelLength); override;
  83. public
  84. constructor Create(AOwner: TComponent); override;
  85. destructor Destroy; override;
  86. procedure DomChanged; override;
  87. procedure Draw; virtual;
  88. function IsDrawing: boolean; override;
  89. property LayoutQueued: boolean read FLayoutQueued write FLayoutQueued;
  90. property Renderer: TFresnelRenderer read FRenderer write FRenderer;
  91. end;
  92. { TCustomTestFresnelCSS }
  93. TCustomTestFresnelCSS = Class(TTestCase)
  94. protected
  95. procedure SetUp; override;
  96. procedure TearDown; override;
  97. public
  98. Viewport: TTestViewport;
  99. end;
  100. { TTestFresnelCSS }
  101. TTestFresnelCSS = class(TCustomTestFresnelCSS)
  102. published
  103. procedure TestEmptyViewport;
  104. procedure TestBody;
  105. procedure TestGetStyleAttr_OneValue;
  106. procedure TestGetStyleAttr_TwoValues;
  107. procedure TestGetStyleAttr_OneFunction;
  108. procedure TestGetStyleAttr_TwoFunctions;
  109. procedure TestGetStyleAttr_NestedFunctions;
  110. procedure TestSetStyleAttr_NewValueEmpty;
  111. procedure TestSetStyleAttr_NewValueFirst;
  112. procedure TestSetStyleAttr_NewValueAppend;
  113. procedure TestSetStyleAttr_NewValueAppendSemicolon;
  114. procedure TestSetStyleAttr_DeleteOnlyValue;
  115. procedure TestSetStyleAttr_DeleteFirstValue;
  116. procedure TestSetStyleAttr_DeleteLastValue;
  117. procedure TestSetStyleAttr_DeleteMiddleValue;
  118. procedure TestSetStyleAttr_ReplaceOnlyValue;
  119. procedure TestSetStyleAttr_ReplaceFirstValue;
  120. procedure TestSetStyleAttr_ReplaceLastValue;
  121. procedure TestSetStyleAttr_ReplaceMiddleValue;
  122. procedure Test_FontSize_Percentage;
  123. procedure Test_FontSize_AsString;
  124. procedure Test_Font_AsString;
  125. procedure Test_Overflow_AsString;
  126. procedure Test_BorderColor_AsString;
  127. procedure Test_BorderStyle_AsString;
  128. procedure Test_BorderWidth_AsString;
  129. procedure Test_Border_AsString;
  130. procedure Test_BorderRadius_AsString;
  131. procedure Test_Margin_AsString;
  132. procedure Test_MarginBlock_AsString; // todo
  133. //procedure Test_MarginInline_AsString; // todo
  134. procedure Test_Padding_AsString;
  135. procedure Test_BackgroundPosition_AsString;
  136. // todo: Test_Gap_AsString
  137. // todo: Test_PlaceContent_AsString
  138. // todo: Test_PlaceItems_AsString
  139. // todo: Test_PlaceSelf_AsString
  140. procedure TestVar_NoDefault;
  141. procedure TestVar_Initial;
  142. procedure TestVar_Inline;
  143. end;
  144. function LinesToStr(const Args: array of const): string;
  145. implementation
  146. const
  147. // char sizes for a font size of 1000
  148. CharHeight = 115;
  149. CharWidths: array[32..126] of word = (
  150. 278, // space
  151. 278, // !
  152. 355, // "
  153. 556, // #
  154. 556, // $
  155. 889, // %
  156. 667, // &
  157. 191, // '
  158. 333, // (
  159. 333, // )
  160. 389, // *
  161. 584, // +
  162. 278, // ,
  163. 333, // -
  164. 278, // .
  165. 278, // /
  166. 556, // 0
  167. 489, // 1
  168. 556, // 2
  169. 556, // 3
  170. 556, // 4
  171. 556, // 5
  172. 556, // 6
  173. 556, // 7
  174. 556, // 8
  175. 556, // 9
  176. 278, // :
  177. 278, // ;
  178. 584, // <
  179. 584, // =
  180. 584, // >
  181. 556, // ?
  182. 1015, // @
  183. 667, // A
  184. 667, // B
  185. 722, // C
  186. 722, // D
  187. 667, // E
  188. 611, // F
  189. 778, // G
  190. 722, // H
  191. 278, // I
  192. 500, // J
  193. 667, // K
  194. 556, // L
  195. 833, // M
  196. 722, // N
  197. 778, // O
  198. 667, // P
  199. 778, // Q
  200. 722, // R
  201. 667, // S
  202. 611, // T
  203. 722, // U
  204. 667, // V
  205. 944, // W
  206. 667, // X
  207. 667, // Y
  208. 611, // Z
  209. 278, // [
  210. 278, // \
  211. 278, // ]
  212. 469, // ^
  213. 556, // _
  214. 333, // `
  215. 556, // a
  216. 556, // b
  217. 500, // c
  218. 556, // d
  219. 556, // e
  220. 262, // f
  221. 556, // g
  222. 556, // h
  223. 222, // i
  224. 222, // j
  225. 500, // k
  226. 222, // l
  227. 833, // m
  228. 556, // n
  229. 556, // o
  230. 556, // p
  231. 556, // q
  232. 333, // r
  233. 500, // s
  234. 278, // t
  235. 556, // u
  236. 500, // v
  237. 722, // w
  238. 500, // x
  239. 500, // y
  240. 500, // z
  241. 334, // {
  242. 260, // |
  243. 334, // }
  244. 584 // ~
  245. );
  246. function CompareTestFont(Desc1, Desc2: Pointer): integer;
  247. var
  248. A: TTestFont absolute Desc1;
  249. B: TTestFont absolute Desc2;
  250. begin
  251. Result:=A.Desc.Compare(B.Desc);
  252. end;
  253. function CompareFontDescTestFont(aDesc, aFont: Pointer): integer;
  254. var
  255. Desc: PFresnelFontDesc absolute aDesc;
  256. Font: TTestFont absolute aFont;
  257. begin
  258. Result:=Desc^.Compare(Font.Desc);
  259. end;
  260. function LinesToStr(const Args: array of const): string;
  261. var
  262. s: String;
  263. i: Integer;
  264. begin
  265. s:='';
  266. for i:=Low(Args) to High(Args) do
  267. begin
  268. case Args[i].VType of
  269. vtChar: s += Args[i].VChar+LineEnding;
  270. vtString: s += Args[i].VString^+LineEnding;
  271. vtPChar: s += Args[i].VPChar+LineEnding;
  272. vtWideChar: s += String(Args[i].VWideChar)+LineEnding;
  273. vtPWideChar: s += String(Args[i].VPWideChar)+LineEnding;
  274. vtAnsiString: s += AnsiString(Args[i].VAnsiString)+LineEnding; // FPC uses encoding CP_UTF8 for TVarRec.VAnsiString
  275. vtWidestring: s += String(WideString(Args[i].VWideString))+LineEnding;
  276. vtUnicodeString:s += String(UnicodeString(Args[i].VUnicodeString))+LineEnding;
  277. end;
  278. end;
  279. Result:=s;
  280. end;
  281. { TTestFont }
  282. function TTestFont.GetFamily: string;
  283. begin
  284. Result:=Desc.Family;
  285. end;
  286. function TTestFont.GetDescription: String;
  287. begin
  288. Result:=Desc.Family;
  289. end;
  290. function TTestFont.GetAlternates: string;
  291. begin
  292. Result:='';
  293. end;
  294. function TTestFont.GetCaps: TFresnelCSSFontVarCaps;
  295. begin
  296. Result:=ffvcNormal;
  297. end;
  298. function TTestFont.GetEastAsians: TFresnelCSSFontVarEastAsians;
  299. begin
  300. Result:=[ffveaNormal];
  301. end;
  302. function TTestFont.GetEmoji: TFresnelCSSFontVarEmoji;
  303. begin
  304. Result:=ffveNormal;
  305. end;
  306. function TTestFont.GetKerning: TFresnelCSSKerning;
  307. begin
  308. Result:=Desc.Kerning;
  309. end;
  310. function TTestFont.GetLigatures: TFresnelCSSFontVarLigaturesSet;
  311. begin
  312. Result:=[ffvlNormal];
  313. end;
  314. function TTestFont.GetNumerics: TFresnelCSSFontVarNumerics;
  315. begin
  316. Result:=[ffvnNormal];
  317. end;
  318. function TTestFont.GetPosition: TFresnelCSSFontVarPosition;
  319. begin
  320. Result:=ffvpNormal;
  321. end;
  322. function TTestFont.GetSize: double;
  323. begin
  324. Result:=Desc.Size;
  325. end;
  326. function TTestFont.GetStyle: string;
  327. begin
  328. Result:=Desc.Style;
  329. end;
  330. function TTestFont.GetWidth: double;
  331. begin
  332. Result:=Desc.Width;
  333. end;
  334. function TTestFont.GetWeight: double;
  335. begin
  336. Result:=Desc.Weight;
  337. end;
  338. function TTestFont.TextSize(const aText: string): TFresnelPoint;
  339. begin
  340. Result:=TextSizeMaxWidth(aText,1000000);
  341. end;
  342. function TTestFont.TextSizeMaxWidth(const aText: string;
  343. MaxWidth: TFresnelLength): TFresnelPoint;
  344. var
  345. aSize, CurLineWidth, CurLineHeight: TFresnelLength;
  346. CodepointLen: Integer;
  347. p: PChar;
  348. CodePoint: Cardinal;
  349. procedure AddLineBreak;
  350. begin
  351. if CurLineWidth>Result.X then
  352. Result.X:=CurLineWidth;
  353. CurLineWidth:=0;
  354. Result.Y:=Result.Y+CurLineHeight;
  355. end;
  356. procedure AddChar(CharWidth: TFresnelLength);
  357. begin
  358. if (CurLineWidth>0) and (CurLineWidth+CharWidth>MaxWidth) then
  359. AddLineBreak;
  360. CurLineWidth:=CurLineWidth+CharWidth;
  361. end;
  362. begin
  363. aSize:=Desc.Size;
  364. if aSize<0 then
  365. raise EFresnelFont.CreateFmt('font size negative "%g"',[Desc.Size]);
  366. Result.X:=0;
  367. Result.Y:=0;
  368. if (aText='') or (SameValue(aSize,0)) then
  369. exit;
  370. CurLineHeight:=aSize*CharHeight/100;
  371. Result.Y:=CurLineHeight;
  372. p:=PChar(aText);
  373. CurLineWidth:=0;
  374. CodepointLen:=0;
  375. while p^<>#0 do
  376. begin
  377. CodePoint:=ord(p^);
  378. case CodePoint of
  379. 0: break;
  380. 10,13:
  381. begin
  382. AddLineBreak;
  383. if (p[1] in [#10,#13]) and (CodePoint<>ord(p[1])) then
  384. inc(p,2)
  385. else
  386. inc(p);
  387. end;
  388. 32..126:
  389. begin
  390. AddChar(aSize*CharWidths[CodePoint]/1000);
  391. inc(p);
  392. end
  393. else
  394. {$IFNDEF CPUWASM}
  395. CodePoint:=UTF8CodepointToUnicode(p,CodepointLen);
  396. {$ELSE}
  397. CodePoint:=0;
  398. {$ENDIF}
  399. AddChar(aSize*CharWidths[65]/1000);
  400. inc(p,CodepointLen);
  401. end;
  402. end;
  403. if CurLineWidth>Result.X then
  404. Result.X:=CurLineWidth;
  405. end;
  406. function TTestFont.GetTool: TObject;
  407. begin
  408. Result:=Self;
  409. end;
  410. { TTestFontEngine }
  411. constructor TTestFontEngine.Create(AOwner: TComponent);
  412. begin
  413. inherited Create(AOwner);
  414. FFonts:=TAVLTree.Create(@CompareTestFont);
  415. end;
  416. destructor TTestFontEngine.Destroy;
  417. begin
  418. FFonts.FreeAndClear;
  419. FreeAndNil(FFonts);
  420. inherited Destroy;
  421. end;
  422. function TTestFontEngine.FindFont(const Desc: TFresnelFontDesc): TTestFont;
  423. var
  424. Node: TAVLTreeNode;
  425. begin
  426. Node:=FFonts.FindKey(@Desc,@CompareFontDescTestFont);
  427. if Node=nil then
  428. Result:=nil
  429. else
  430. Result:=TTestFont(Node.Data);
  431. end;
  432. function TTestFontEngine.Allocate(const Desc: TFresnelFontDesc): IFresnelFont;
  433. var
  434. aFont: TTestFont;
  435. begin
  436. aFont:=FindFont(Desc);
  437. if aFont=nil then
  438. begin
  439. aFont:=TTestFont.Create;
  440. aFont.Desc:=Desc;
  441. FFonts.Add(aFont);
  442. end;
  443. Result:=aFont;
  444. end;
  445. { TTestRenderer }
  446. procedure TTestRenderer.Arc(const aColor: TFPColor; const aCenter, aRadii: TFresnelPoint;
  447. aStartAngle: TFresnelLength; aStopAngle: TFresnelLength);
  448. begin
  449. if aColor=colBlack then;
  450. if aCenter.X=0 then ;
  451. if aRadii.X=0 then;
  452. if aStartAngle=0 then;
  453. if aStopAngle=0 then;
  454. end;
  455. procedure TTestRenderer.ClipRect(const aRect: TFresnelRect);
  456. begin
  457. ClipR:=aRect;
  458. end;
  459. procedure TTestRenderer.FillRect(const aColor: TFPColor;
  460. const aRect: TFresnelRect);
  461. begin
  462. if aColor=colBlack then ;
  463. if aRect.IsEmpty then ;
  464. end;
  465. procedure TTestRenderer.Line(const aColor: TFPColor; const x1, y1, x2,
  466. y2: TFresnelLength);
  467. begin
  468. if aColor=colBlack then ;
  469. if x1+y1+x2+y2=0 then ;
  470. end;
  471. procedure TTestRenderer.Polygon(const aColor: TFPColor; const p: PFresnelPoint;
  472. Count: integer);
  473. begin
  474. if aColor=colBlack then ;
  475. if Count=0 then ;
  476. if p=nil then ;
  477. end;
  478. procedure TTestRenderer.Restore;
  479. var
  480. l: SizeInt;
  481. begin
  482. l:=Length(FSavedContexts)-1;
  483. if l<0 then
  484. raise Exception.Create('20250429101125 TTestRenderer.Restore');
  485. ClipR:=FSavedContexts[l];
  486. SetLength(FSavedContexts,l);
  487. end;
  488. procedure TTestRenderer.RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect;
  489. Fill: Boolean);
  490. begin
  491. if aColor=colBlack then;
  492. if aRect.Box.Left=0 then;
  493. if Fill then;
  494. end;
  495. procedure TTestRenderer.Save;
  496. var
  497. l: SizeInt;
  498. begin
  499. l:=Length(FSavedContexts);
  500. SetLength(FSavedContexts,l+1);
  501. FSavedContexts[l]:=ClipR;
  502. end;
  503. procedure TTestRenderer.TextOut(const aLeft, aTop: TFresnelLength;
  504. const aFont: IFresnelFont; const aColor: TFPColor; const aText: string);
  505. begin
  506. if aLeft=aTop then ;
  507. if aFont=nil then ;
  508. if aColor=colBlack then ;
  509. if aText='' then ;
  510. end;
  511. procedure TTestRenderer.DrawImage(const aLeft, aTop, aWidth, aHeight: TFresnelLength; const aImage: TFPCustomImage);
  512. begin
  513. if (aLeft=aTop) then ;
  514. if (aWidth=aHeight) then ;
  515. if (aImage=nil) then ;
  516. end;
  517. constructor TTestRenderer.Create(AOwner: TComponent);
  518. begin
  519. inherited Create(AOwner);
  520. end;
  521. { TTestViewport }
  522. procedure TTestViewport.SetWidth(AValue: TFresnelLength);
  523. begin
  524. inherited SetWidth(AValue);
  525. LayoutQueued:=true;
  526. end;
  527. procedure TTestViewport.SetHeight(AValue: TFresnelLength);
  528. begin
  529. inherited SetHeight(AValue);
  530. LayoutQueued:=true;
  531. end;
  532. constructor TTestViewport.Create(AOwner: TComponent);
  533. begin
  534. inherited Create(AOwner);
  535. Layouter:=TViewportLayouter.Create(nil);
  536. TViewportLayouter(Layouter).Viewport:=Self;
  537. FontEngine:=TTestFontEngine.Create(Self);
  538. Renderer:=TTestRenderer.Create(Self);
  539. DomChanged;
  540. end;
  541. destructor TTestViewport.Destroy;
  542. begin
  543. FreeAndNil(FRenderer);
  544. FontEngine.Free;
  545. FontEngine:=nil;
  546. Layouter.Free;
  547. Layouter:=nil;
  548. inherited Destroy;
  549. end;
  550. procedure TTestViewport.DomChanged;
  551. begin
  552. LayoutQueued:=true;
  553. inherited DomChanged;
  554. end;
  555. procedure TTestViewport.Draw;
  556. begin
  557. //debugln(['TTestViewport.WSDraw ',DbgSName(Self),' ',DbgSName(Renderer)]);
  558. if fDrawing then
  559. raise Exception.Create('20250429140551');
  560. fDrawing:=true;
  561. if LayoutQueued then
  562. begin
  563. LayoutQueued:=false;
  564. ApplyCSS;
  565. //Layouter.WriteLayoutTree;
  566. end;
  567. Renderer.Draw(Self);
  568. fDrawing:=false;
  569. end;
  570. function TTestViewport.IsDrawing: boolean;
  571. begin
  572. Result:=fDrawing;
  573. end;
  574. { TCustomTestFresnelCSS }
  575. procedure TCustomTestFresnelCSS.SetUp;
  576. begin
  577. inherited SetUp;
  578. Viewport:=TTestViewport.Create(nil);
  579. end;
  580. procedure TCustomTestFresnelCSS.TearDown;
  581. begin
  582. FreeAndNil(Viewport);
  583. inherited TearDown;
  584. end;
  585. { TTestFresnelCSS }
  586. procedure TTestFresnelCSS.TestEmptyViewport;
  587. begin
  588. Viewport.ApplyCSS;
  589. end;
  590. procedure TTestFresnelCSS.TestBody;
  591. var
  592. Body: TBody;
  593. begin
  594. writeln('TTestFresnelCSS.TestBody START');
  595. Body:=TBody.Create(Viewport);
  596. Body.Name:='Body';
  597. Body.Parent:=Viewport;
  598. Viewport.ApplyCSS;
  599. //Body.WriteComputedAttributes('Body');
  600. writeln('TTestFresnelCSS.TestBody END');
  601. end;
  602. procedure TTestFresnelCSS.TestGetStyleAttr_OneValue;
  603. begin
  604. if Viewport.Style<>'' then
  605. Fail('20240820190117');
  606. Viewport.Style:='padding:3px';
  607. AssertEquals('padding:3px',Viewport.Style);
  608. AssertEquals('3px',Viewport.GetStyleAttr('padding'));
  609. end;
  610. procedure TTestFresnelCSS.TestGetStyleAttr_TwoValues;
  611. begin
  612. Viewport.Style:='padding-left:3px; padding-top: 4px';
  613. AssertEquals('3px',Viewport.GetStyleAttr('padding-left'));
  614. AssertEquals('4px',Viewport.GetStyleAttr('padding-top'));
  615. end;
  616. procedure TTestFresnelCSS.TestGetStyleAttr_OneFunction;
  617. begin
  618. Viewport.Style:='padding-left:var(--bird)';
  619. AssertEquals('var(--bird)',Viewport.GetStyleAttr('padding-left'));
  620. end;
  621. procedure TTestFresnelCSS.TestGetStyleAttr_TwoFunctions;
  622. begin
  623. Viewport.Style:='padding-left:var(--bird); padding-right: min(10px, 20%) ';
  624. AssertEquals('var(--bird)',Viewport.GetStyleAttr('padding-left'));
  625. AssertEquals('min(10px, 20%)',Viewport.GetStyleAttr('padding-right'));
  626. end;
  627. procedure TTestFresnelCSS.TestGetStyleAttr_NestedFunctions;
  628. begin
  629. Viewport.Style:='padding-left: calc(var(--bird)*10%) ; padding-right: min(max(10%,3em), 20%) min(3px,5ch)';
  630. AssertEquals('calc(var(--bird)*10%)',Viewport.GetStyleAttr('padding-left'));
  631. AssertEquals('min(max(10%,3em), 20%) min(3px,5ch)',Viewport.GetStyleAttr('padding-right'));
  632. end;
  633. procedure TTestFresnelCSS.TestSetStyleAttr_NewValueEmpty;
  634. begin
  635. if not Viewport.SetStyleAttr('padding-left','') then
  636. Fail('20240820193346');
  637. AssertEquals('',Viewport.Style);
  638. end;
  639. procedure TTestFresnelCSS.TestSetStyleAttr_NewValueFirst;
  640. begin
  641. if not Viewport.SetStyleAttr('padding-left','3px') then
  642. Fail('20240820193354');
  643. AssertEquals('padding-left:3px',Viewport.Style);
  644. end;
  645. procedure TTestFresnelCSS.TestSetStyleAttr_NewValueAppend;
  646. begin
  647. Viewport.Style:='padding-left:4px';
  648. if not Viewport.SetStyleAttr('padding-right','7px') then
  649. Fail('20240820193401');
  650. AssertEquals('padding-left:4px; padding-right:7px',Viewport.Style);
  651. end;
  652. procedure TTestFresnelCSS.TestSetStyleAttr_NewValueAppendSemicolon;
  653. begin
  654. Viewport.Style:='padding-left:4px ;';
  655. if not Viewport.SetStyleAttr('padding-right','7px') then
  656. Fail('20240820194710');
  657. AssertEquals('padding-left:4px ; padding-right:7px',Viewport.Style);
  658. end;
  659. procedure TTestFresnelCSS.TestSetStyleAttr_DeleteOnlyValue;
  660. begin
  661. Viewport.Style:='padding-left:4px';
  662. if not Viewport.SetStyleAttr('padding-left','') then
  663. Fail('20240820193844');
  664. AssertEquals('',Viewport.Style);
  665. end;
  666. procedure TTestFresnelCSS.TestSetStyleAttr_DeleteFirstValue;
  667. begin
  668. Viewport.Style:='padding-left:4px; padding-top:3px';
  669. if not Viewport.SetStyleAttr('padding-left','') then
  670. Fail('20240820193847');
  671. AssertEquals('padding-top:3px',Viewport.Style);
  672. end;
  673. procedure TTestFresnelCSS.TestSetStyleAttr_DeleteLastValue;
  674. begin
  675. Viewport.Style:='padding-left:4px ; padding-top:3px';
  676. if not Viewport.SetStyleAttr('padding-top','') then
  677. Fail('20240820194509');
  678. AssertEquals('padding-left:4px ;',Viewport.Style);
  679. end;
  680. procedure TTestFresnelCSS.TestSetStyleAttr_DeleteMiddleValue;
  681. begin
  682. Viewport.Style:='padding-left:4px ; padding-top:3px; padding-right: 2px';
  683. if not Viewport.SetStyleAttr('padding-top','') then
  684. Fail('20240820195100');
  685. AssertEquals('padding-left:4px ;padding-right: 2px',Viewport.Style);
  686. end;
  687. procedure TTestFresnelCSS.TestSetStyleAttr_ReplaceOnlyValue;
  688. begin
  689. Viewport.Style:='padding-left: 4px;';
  690. if not Viewport.SetStyleAttr('padding-left','5em') then
  691. Fail('20240820195245');
  692. AssertEquals('padding-left:5em;',Viewport.Style);
  693. end;
  694. procedure TTestFresnelCSS.TestSetStyleAttr_ReplaceFirstValue;
  695. begin
  696. Viewport.Style:='padding-left: 4px ; padding-top:3px';
  697. if not Viewport.SetStyleAttr('padding-left','7em') then
  698. Fail('20240820195924');
  699. AssertEquals('padding-left:7em; padding-top:3px',Viewport.Style);
  700. end;
  701. procedure TTestFresnelCSS.TestSetStyleAttr_ReplaceLastValue;
  702. begin
  703. Viewport.Style:='padding-left: 4px ; padding-top: 3px ';
  704. if not Viewport.SetStyleAttr('padding-top','7em') then
  705. Fail('20240820200021');
  706. AssertEquals('padding-left: 4px ; padding-top:7em',Viewport.Style);
  707. end;
  708. procedure TTestFresnelCSS.TestSetStyleAttr_ReplaceMiddleValue;
  709. begin
  710. Viewport.Style:='padding-left:4px ; padding-top: 3px ; padding-right: 2px';
  711. if not Viewport.SetStyleAttr('padding-top','7em') then
  712. Fail('20240820200135');
  713. AssertEquals('padding-left:4px ; padding-top:7em; padding-right: 2px',Viewport.Style);
  714. end;
  715. procedure TTestFresnelCSS.Test_FontSize_Percentage;
  716. var
  717. Body: TBody;
  718. Div1: TDiv;
  719. begin
  720. Viewport.Stylesheet.Text:=LinesToStr([
  721. 'body {',
  722. 'font-size:30px;',
  723. '}',
  724. 'div {',
  725. 'font-size:200%;',
  726. '}']);
  727. Body:=TBody.Create(Viewport);
  728. Body.Name:='Body';
  729. Body.Parent:=Viewport;
  730. Div1:=TDiv.Create(Viewport);
  731. Div1.Name:='Div1';
  732. Div1.Parent:=Body;
  733. Viewport.ApplyCSS;
  734. AssertEquals('Body.Font.GetSize',Body.Font.GetSize,30);
  735. AssertEquals('Div1.Font.GetSize',Div1.Font.GetSize,60);
  736. end;
  737. procedure TTestFresnelCSS.Test_FontSize_AsString;
  738. var
  739. Body: TBody;
  740. begin
  741. Viewport.Stylesheet.Text:=LinesToStr([
  742. 'body {',
  743. 'font-size:3em;',
  744. '}']);
  745. Body:=TBody.Create(Viewport);
  746. Body.Name:='Body';
  747. Body.Parent:=Viewport;
  748. Viewport.ApplyCSS;
  749. AssertEquals('Body.Font.GetSize',30,Body.Font.GetSize);
  750. AssertEquals('Body.GetComputedString(fcaFontSize)','30px',Body.GetComputedString(fcaFontSize));
  751. end;
  752. procedure TTestFresnelCSS.Test_Font_AsString;
  753. var
  754. Body: TBody;
  755. begin
  756. Viewport.Stylesheet.Text:=LinesToStr([
  757. 'body {',
  758. 'font-family:Arial;',
  759. 'font-kerning:normal;',
  760. 'font-size:12px;',
  761. 'font-style:italic;',
  762. 'font-weight:250;',
  763. 'font-width:condensed;',
  764. 'line-height:20px;',
  765. '}']);
  766. Body:=TBody.Create(Viewport);
  767. Body.Name:='Body';
  768. Body.Parent:=Viewport;
  769. Viewport.ApplyCSS;
  770. AssertEquals('Body.Font.GetFamily','Arial',Body.Font.GetFamily);
  771. AssertEquals('Body.GetComputedString(fcaFontFamily)','Arial',Body.GetComputedString(fcaFontFamily));
  772. AssertEquals('Body.Font.GetKerning','normal',FresnelCSSKerningNames[Body.Font.GetKerning]);
  773. AssertEquals('Body.GetComputedString(fcaFontKerning)','normal',Body.GetComputedString(fcaFontKerning));
  774. AssertEquals('Body.Font.GetSize',12,Body.Font.GetSize);
  775. AssertEquals('Body.GetComputedString(fcaFontSize)','12px',Body.GetComputedString(fcaFontSize));
  776. AssertEquals('Body.Font.GetStyle','italic',Body.Font.GetStyle);
  777. AssertEquals('Body.GetComputedString(fcaFontStyle)','italic',Body.GetComputedString(fcaFontStyle));
  778. AssertEquals('Body.Font.GetWeight',250,Body.Font.GetWeight);
  779. AssertEquals('Body.GetComputedString(fcaFontWeight)','250',Body.GetComputedString(fcaFontWeight));
  780. AssertEquals('Body.Font.GetWidth',0.75,Body.Font.GetWidth);
  781. AssertEquals('Body.GetComputedString(fcaFontWidth)','75%',Body.GetComputedString(fcaFontWidth));
  782. AssertEquals('Body.GetComputedString(fcaFontStretch)','75%',Body.GetComputedString(fcaFontStretch));
  783. AssertEquals('Body.GetComputedString(fcaFont)','italic 250 12px/20px condensed Arial',Body.GetComputedString(fcaFont));
  784. end;
  785. procedure TTestFresnelCSS.Test_Overflow_AsString;
  786. var
  787. Body: TBody;
  788. begin
  789. Viewport.Stylesheet.Text:=LinesToStr([
  790. 'body {',
  791. 'overflow:visible hidden;',
  792. '}']);
  793. Body:=TBody.Create(Viewport);
  794. Body.Name:='Body';
  795. Body.Parent:=Viewport;
  796. Viewport.ApplyCSS;
  797. AssertEquals('Body.GetComputedString(fcaOverflowX)','visible',Body.GetComputedString(fcaOverflowX));
  798. AssertEquals('Body.GetComputedString(fcaOverflowY)','hidden',Body.GetComputedString(fcaOverflowY));
  799. AssertEquals('Body.GetComputedString(fcaOverflow)','auto hidden',Body.GetComputedString(fcaOverflow));
  800. end;
  801. procedure TTestFresnelCSS.Test_BorderColor_AsString;
  802. var
  803. Div1: TDiv;
  804. begin
  805. Viewport.Stylesheet.Text:=LinesToStr([
  806. 'div {',
  807. 'border-color:#111 #222 #333 #444;',
  808. '}']);
  809. Div1:=TDiv.Create(Viewport);
  810. Div1.Name:='Div1';
  811. Div1.Parent:=Viewport;
  812. Viewport.ApplyCSS;
  813. AssertEquals('Div1.GetComputedString(fcaBorderTopColor)','#111',Div1.GetComputedString(fcaBorderTopColor));
  814. AssertEquals('Div1.GetComputedString(fcaBorderRightColor)','#222',Div1.GetComputedString(fcaBorderRightColor));
  815. AssertEquals('Div1.GetComputedString(fcaBorderBottomColor)','#333',Div1.GetComputedString(fcaBorderBottomColor));
  816. AssertEquals('Div1.GetComputedString(fcaBorderLeftColor)','#444',Div1.GetComputedString(fcaBorderLeftColor));
  817. AssertEquals('Div1.GetComputedString(fcaBorderColor)','#111 #222 #333 #444',Div1.GetComputedString(fcaBorderColor));
  818. end;
  819. procedure TTestFresnelCSS.Test_BorderStyle_AsString;
  820. var
  821. Div1: TDiv;
  822. begin
  823. Viewport.Stylesheet.Text:=LinesToStr([
  824. 'div {',
  825. 'border-style:solid dashed ridge none;',
  826. '}']);
  827. Div1:=TDiv.Create(Viewport);
  828. Div1.Name:='Div1';
  829. Div1.Parent:=Viewport;
  830. Viewport.ApplyCSS;
  831. AssertEquals('Div1.GetComputedString(fcaBorderTopStyle)','solid',Div1.GetComputedString(fcaBorderTopStyle));
  832. AssertEquals('Div1.GetComputedString(fcaBorderRightStyle)','dashed',Div1.GetComputedString(fcaBorderRightStyle));
  833. AssertEquals('Div1.GetComputedString(fcaBorderBottomStyle)','ridge',Div1.GetComputedString(fcaBorderBottomStyle));
  834. AssertEquals('Div1.GetComputedString(fcaBorderLeftStyle)','none',Div1.GetComputedString(fcaBorderLeftStyle));
  835. AssertEquals('Div1.GetComputedString(fcaBorderStyle)','solid dashed ridge none',Div1.GetComputedString(fcaBorderStyle));
  836. end;
  837. procedure TTestFresnelCSS.Test_BorderWidth_AsString;
  838. var
  839. Div1: TDiv;
  840. begin
  841. Viewport.Stylesheet.Text:=LinesToStr([
  842. 'div {',
  843. 'border-width:1px 2px 3px 4px;',
  844. '}']);
  845. Div1:=TDiv.Create(Viewport);
  846. Div1.Name:='Div1';
  847. Div1.Parent:=Viewport;
  848. Viewport.ApplyCSS;
  849. AssertEquals('Div1.GetComputedString(fcaBorderTopWidth)','1px',Div1.GetComputedString(fcaBorderTopWidth));
  850. AssertEquals('Div1.GetComputedString(fcaBorderRightWidth)','2px',Div1.GetComputedString(fcaBorderRightWidth));
  851. AssertEquals('Div1.GetComputedString(fcaBorderBottomWidth)','3px',Div1.GetComputedString(fcaBorderBottomWidth));
  852. AssertEquals('Div1.GetComputedString(fcaBorderLeftWidth)','4px',Div1.GetComputedString(fcaBorderLeftWidth));
  853. AssertEquals('Div1.GetComputedString(fcaBorderWidth)','1px 2px 3px 4px',Div1.GetComputedString(fcaBorderWidth));
  854. end;
  855. procedure TTestFresnelCSS.Test_Border_AsString;
  856. var
  857. Div1: TDiv;
  858. begin
  859. Viewport.Stylesheet.Text:=LinesToStr([
  860. 'div {',
  861. 'border:1px red solid;',
  862. '}']);
  863. Div1:=TDiv.Create(Viewport);
  864. Div1.Name:='Div1';
  865. Div1.Parent:=Viewport;
  866. Viewport.ApplyCSS;
  867. AssertEquals('Div1.GetComputedString(fcaBorderTopWidth)','1px',Div1.GetComputedString(fcaBorderTopWidth));
  868. AssertEquals('Div1.GetComputedString(fcaBorderRightWidth)','1px',Div1.GetComputedString(fcaBorderRightWidth));
  869. AssertEquals('Div1.GetComputedString(fcaBorderBottomWidth)','1px',Div1.GetComputedString(fcaBorderBottomWidth));
  870. AssertEquals('Div1.GetComputedString(fcaBorderLeftWidth)','1px',Div1.GetComputedString(fcaBorderLeftWidth));
  871. AssertEquals('Div1.GetComputedString(fcaBorderTopStyle)','solid',Div1.GetComputedString(fcaBorderTopStyle));
  872. AssertEquals('Div1.GetComputedString(fcaBorderRightStyle)','solid',Div1.GetComputedString(fcaBorderRightStyle));
  873. AssertEquals('Div1.GetComputedString(fcaBorderBottomStyle)','solid',Div1.GetComputedString(fcaBorderBottomStyle));
  874. AssertEquals('Div1.GetComputedString(fcaBorderLeftStyle)','solid',Div1.GetComputedString(fcaBorderLeftStyle));
  875. AssertEquals('Div1.GetComputedString(fcaBorderTopColor)','red',Div1.GetComputedString(fcaBorderTopColor));
  876. AssertEquals('Div1.GetComputedString(fcaBorderRightColor)','red',Div1.GetComputedString(fcaBorderRightColor));
  877. AssertEquals('Div1.GetComputedString(fcaBorderBottomColor)','red',Div1.GetComputedString(fcaBorderBottomColor));
  878. AssertEquals('Div1.GetComputedString(fcaBorderLeftColor)','red',Div1.GetComputedString(fcaBorderLeftColor));
  879. AssertEquals('Div1.GetComputedString(fcaBorderTop)','red solid 1px',Div1.GetComputedString(fcaBorderTop));
  880. AssertEquals('Div1.GetComputedString(fcaBorderRight)','red solid 1px',Div1.GetComputedString(fcaBorderRight));
  881. AssertEquals('Div1.GetComputedString(fcaBorderBottom)','red solid 1px',Div1.GetComputedString(fcaBorderBottom));
  882. AssertEquals('Div1.GetComputedString(fcaBorderLeft)','red solid 1px',Div1.GetComputedString(fcaBorderLeft));
  883. AssertEquals('Div1.GetComputedString(fcaBorderWidth)','red solid 1px',Div1.GetComputedString(fcaBorder));
  884. end;
  885. procedure TTestFresnelCSS.Test_BorderRadius_AsString;
  886. var
  887. Div1: TDiv;
  888. p: TFresnelPoint;
  889. begin
  890. Viewport.Stylesheet.Text:=LinesToStr([
  891. 'div {',
  892. 'border-radius:1px 2px 3px 4px / 5px 6px 7px 8px;',
  893. '}']);
  894. Div1:=TDiv.Create(Viewport);
  895. Div1.Name:='Div1';
  896. Div1.Parent:=Viewport;
  897. Viewport.ApplyCSS;
  898. AssertEquals('Div1.GetComputedString(fcaBorderTopLeftRadius)','1px / 5px',Div1.GetComputedString(fcaBorderTopLeftRadius));
  899. AssertEquals('Div1.GetComputedString(fcaBorderTopRightRadius)','2px / 6px',Div1.GetComputedString(fcaBorderTopRightRadius));
  900. AssertEquals('Div1.GetComputedString(fcaBorderBottomRightRadius)','3px / 7px',Div1.GetComputedString(fcaBorderBottomRightRadius));
  901. AssertEquals('Div1.GetComputedString(fcaBorderBottomLeftRadius)','4px / 8px',Div1.GetComputedString(fcaBorderBottomLeftRadius));
  902. p:=Div1.GetComputedBorderRadius(fcsTopLeft);
  903. AssertEquals('Div1.GetComputedBorderRadius(fcsTopLeft)','(1,5)',p.ToString);
  904. AssertEquals('Div1.GetComputedString(fcaBorderRadius)','1px 2px 3px 4px / 5px 6px 7px 8px',Div1.GetComputedString(fcaBorderRadius));
  905. end;
  906. procedure TTestFresnelCSS.Test_Margin_AsString;
  907. var
  908. Div1: TDiv;
  909. begin
  910. Viewport.Stylesheet.Text:=LinesToStr([
  911. 'div {',
  912. 'margin:1px 2px 3px 4px;',
  913. '}']);
  914. Div1:=TDiv.Create(Viewport);
  915. Div1.Name:='Div1';
  916. Div1.Parent:=Viewport;
  917. Viewport.ApplyCSS;
  918. AssertEquals('Div1.GetComputedString(fcaMarginTop)','1px',Div1.GetComputedString(fcaMarginTop));
  919. AssertEquals('Div1.GetComputedString(fcaMarginRight)','2px',Div1.GetComputedString(fcaMarginRight));
  920. AssertEquals('Div1.GetComputedString(fcaMarginBottom)','3px',Div1.GetComputedString(fcaMarginBottom));
  921. AssertEquals('Div1.GetComputedString(fcaMarginLeft)','4px',Div1.GetComputedString(fcaMarginLeft));
  922. AssertEquals('Div1.GetComputedString(fcaMargin)','1px 2px 3px 4px',Div1.GetComputedString(fcaMargin));
  923. end;
  924. procedure TTestFresnelCSS.Test_MarginBlock_AsString;
  925. var
  926. Div1: TDiv;
  927. begin
  928. exit;
  929. Viewport.Stylesheet.Text:=LinesToStr([
  930. 'div {',
  931. 'margin-block:1px 2px;',
  932. '}']);
  933. Div1:=TDiv.Create(Viewport);
  934. Div1.Name:='Div1';
  935. Div1.Parent:=Viewport;
  936. Viewport.ApplyCSS;
  937. AssertEquals('Div1.GetComputedString(fcaMarginBlockStart)','1px',Div1.GetComputedString(fcaMarginBlockStart));
  938. AssertEquals('Div1.GetComputedString(fcaMarginBlockEnd)','2px',Div1.GetComputedString(fcaMarginBlockEnd));
  939. AssertEquals('Div1.GetComputedString(fcaMarginTop)','3px',Div1.GetComputedString(fcaMarginTop));
  940. AssertEquals('Div1.GetComputedString(fcaMarginRight)','4px',Div1.GetComputedString(fcaMarginRight));
  941. AssertEquals('Div1.GetComputedString(fcaMarginBottom)','3px',Div1.GetComputedString(fcaMarginBottom));
  942. AssertEquals('Div1.GetComputedString(fcaMarginLeft)','4px',Div1.GetComputedString(fcaMarginLeft));
  943. AssertEquals('Div1.GetComputedString(fcaMarginWidth)','1px 2px 3px 4px',Div1.GetComputedString(fcaMargin));
  944. end;
  945. procedure TTestFresnelCSS.Test_Padding_AsString;
  946. var
  947. Div1: TDiv;
  948. begin
  949. Viewport.Stylesheet.Text:=LinesToStr([
  950. 'div {',
  951. 'padding:1px 2px 3px 4px;',
  952. '}']);
  953. Div1:=TDiv.Create(Viewport);
  954. Div1.Name:='Div1';
  955. Div1.Parent:=Viewport;
  956. Viewport.ApplyCSS;
  957. AssertEquals('Div1.GetComputedString(fcaPaddingTop)','1px',Div1.GetComputedString(fcaPaddingTop));
  958. AssertEquals('Div1.GetComputedString(fcaPaddingRight)','2px',Div1.GetComputedString(fcaPaddingRight));
  959. AssertEquals('Div1.GetComputedString(fcaPaddingBottom)','3px',Div1.GetComputedString(fcaPaddingBottom));
  960. AssertEquals('Div1.GetComputedString(fcaPaddingLeft)','4px',Div1.GetComputedString(fcaPaddingLeft));
  961. AssertEquals('Div1.GetComputedString(fcaPadding)','1px 2px 3px 4px',Div1.GetComputedString(fcaPadding));
  962. end;
  963. procedure TTestFresnelCSS.Test_BackgroundPosition_AsString;
  964. var
  965. Div1: TDiv;
  966. begin
  967. Viewport.Stylesheet.Text:=LinesToStr([
  968. 'div {',
  969. 'background-position:left 10px bottom 15%;',
  970. '}']);
  971. Div1:=TDiv.Create(Viewport);
  972. Div1.Name:='Div1';
  973. Div1.Parent:=Viewport;
  974. Viewport.ApplyCSS;
  975. AssertEquals('Div1.GetComputedString(fcaBackgroundPositionX)','left 10px',Div1.GetComputedString(fcaBackgroundPositionX));
  976. AssertEquals('Div1.GetComputedString(fcaBackgroundPositionY)','bottom 15%',Div1.GetComputedString(fcaBackgroundPositionY));
  977. AssertEquals('Div1.GetComputedString(fcaBackgroundPosition)','left 10px bottom 15%',Div1.GetComputedString(fcaBackgroundPosition));
  978. end;
  979. procedure TTestFresnelCSS.TestVar_NoDefault;
  980. var
  981. Body: TBody;
  982. begin
  983. Viewport.Stylesheet.Text:=LinesToStr([
  984. ':root {',
  985. '--bird-color:red;',
  986. '}',
  987. 'body {',
  988. 'color:var(--bird-color);',
  989. '}']);
  990. Body:=TBody.Create(Viewport);
  991. Body.Name:='Body';
  992. Body.Parent:=Viewport;
  993. Viewport.ApplyCSS;
  994. AssertEquals('red',Viewport.GetComputedCSSString('--bird-color'));
  995. AssertEquals('red',Body.GetComputedCSSString('--bird-color'));
  996. AssertEquals('red',Body.GetComputedCSSString('color'));
  997. end;
  998. procedure TTestFresnelCSS.TestVar_Initial;
  999. var
  1000. Body: TBody;
  1001. Div1: TDiv;
  1002. begin
  1003. Viewport.Stylesheet.Text:=LinesToStr([
  1004. 'body {',
  1005. 'font-size:30px;',
  1006. '}',
  1007. 'div {',
  1008. 'font-size:var(--none,initial);',
  1009. '}']);
  1010. Body:=TBody.Create(Viewport);
  1011. Body.Name:='Body';
  1012. Body.Parent:=Viewport;
  1013. Div1:=TDiv.Create(Viewport);
  1014. Div1.Name:='Div1';
  1015. Div1.Parent:=Body;
  1016. Viewport.ApplyCSS;
  1017. AssertEquals('Body.GetComputedFontSize',Body.Font.GetSize,30);
  1018. AssertEquals('Div1.GetComputedFontSize',Div1.Font.GetSize,FresnelDefaultFontSize);
  1019. end;
  1020. procedure TTestFresnelCSS.TestVar_Inline;
  1021. var
  1022. Div1: TDiv;
  1023. begin
  1024. Viewport.Stylesheet.Text:=LinesToStr([
  1025. 'div {',
  1026. 'font-size:var(--size);',
  1027. '}']);
  1028. Div1:=TDiv.Create(Viewport);
  1029. Div1.Name:='Div1';
  1030. Div1.Parent:=Viewport;
  1031. Div1.Style:='--size:28px;';
  1032. Viewport.ApplyCSS;
  1033. AssertEquals('Div1.GetComputedFontSize',28,Div1.Font.GetSize);
  1034. end;
  1035. Initialization
  1036. RegisterTests([TTestFresnelCSS]);
  1037. end.