mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 16:59:33 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1008 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1008 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
{$IFDEF CSS_INTERFACE}
 | 
						|
 TCSSGroup = class
 | 
						|
 end;
 | 
						|
 | 
						|
 TCSSFontStyle = (cfsNormal, cfsItalic, cfsOblique, cfsInherit);
 | 
						|
 TCSSFontWeight = (cfwNormal, cfwBold, cfwBolder, cfwLighter, cfw100, cfw200,
 | 
						|
                    cfw300, cfw400 , cfw500, cfw600, cfw700, cfw800, cfw900);
 | 
						|
 TCSSFontVariant = (cfvNormal, cfvSmallCaps, cfvInherit);
 | 
						|
 | 
						|
 TCSSBorderStyle = (cbsNone, cbsHidden, cbsDotted, cbsDashed, cbsSolid, cbsDouble,
 | 
						|
                   cbsGroove, cbsRidge, cbsInset, cbsOutset);
 | 
						|
 TCSSMarginStyle = (cmsNone,
 | 
						|
                    cmsAuto, // use default
 | 
						|
                    cmsPx,  // pixel
 | 
						|
                    cmsPt, cmsEm, cmsPercent // currently not supported
 | 
						|
                    );
 | 
						|
 | 
						|
 TCSSMargin = record
 | 
						|
   Style: TCSSMarginStyle;
 | 
						|
   Size: single; // negative values are allowed (not implemented)
 | 
						|
 end;
 | 
						|
 | 
						|
 | 
						|
 { TCSSFont }
 | 
						|
 | 
						|
 TCSSFont = class
 | 
						|
 private
 | 
						|
   FFamily: String;
 | 
						|
   FSize: String;
 | 
						|
   FStyle: TCSSFontStyle;
 | 
						|
   FWeight: TCSSFontWeight;
 | 
						|
 published
 | 
						|
   property Name: String read FFamily write FFamily;
 | 
						|
   property Size: String read FSize write FSize;
 | 
						|
   property Style: TCSSFontStyle read FStyle write FStyle;
 | 
						|
   //proprety Variant: TCSSFontVariant
 | 
						|
   property Weight: TCSSFontWeight read FWeight write FWeight;
 | 
						|
 end;
 | 
						|
 | 
						|
 { TCSSBorder }
 | 
						|
 | 
						|
 TCSSBorder = class
 | 
						|
 private
 | 
						|
   FColor: TColor;
 | 
						|
   FStyle: TCSSBorderStyle;
 | 
						|
   FWidth: Integer;
 | 
						|
 public
 | 
						|
   constructor Create;
 | 
						|
 published
 | 
						|
   property Color: TColor read FColor write FColor;
 | 
						|
   property Style: TCSSBorderStyle read FStyle write FStyle;
 | 
						|
   property Width: Integer read FWidth write FWidth;
 | 
						|
 end;
 | 
						|
 | 
						|
 { TCSSProps represents a set of properties from the CSS stylesheet, for
 | 
						|
   example everything within one selector or the contents of a style attribute
 | 
						|
   or even many applicable CSS styles for one node merged into one. It has
 | 
						|
   methods for parsing CSS text and for merging two such objects into one}
 | 
						|
 TCSSProps = class
 | 
						|
 private
 | 
						|
   FBorder: TCSSBorder;
 | 
						|
   FClassIDs: TStringList;
 | 
						|
   FBGColor: TColor;
 | 
						|
   FBorderBottom: TCSSBorderStyle;
 | 
						|
   FBorderLeft: TCSSBorderStyle;
 | 
						|
   FBorderRight: TCSSBorderStyle;
 | 
						|
   FBorderTop: TCSSBorderStyle;
 | 
						|
   FColor: TColor;
 | 
						|
   FFont: TCSSFont;
 | 
						|
   FAlignment: TIpHtmlAlign;
 | 
						|
   FMarginBottom: TCSSMargin;
 | 
						|
   FMarginLeft: TCSSMargin;
 | 
						|
   FMarginRight: TCSSMargin;
 | 
						|
   FMarginTop: TCSSMargin;
 | 
						|
   function GetCommandArgs(ACommand: String): TStringList;
 | 
						|
   function GetCommandName(ACommand: String): String;
 | 
						|
 public
 | 
						|
   property MarginTop: TCSSMargin read FMarginTop write FMarginTop;
 | 
						|
   property MarginLeft: TCSSMargin read FMarginLeft write FMarginLeft;
 | 
						|
   property MarginBottom: TCSSMargin read FMarginBottom write FMarginBottom;
 | 
						|
   property MarginRight: TCSSMargin read FMarginRight write FMarginRight;
 | 
						|
 published
 | 
						|
   property Font: TCSSFont read  FFont write FFont;
 | 
						|
   property Color: TColor read FColor write FColor;
 | 
						|
   property BGColor: TColor read FBGColor write FBGColor;
 | 
						|
   property Border: TCSSBorder read FBorder write FBorder;
 | 
						|
   property BorderTop: TCSSBorderStyle read FBorderTop write FBorderTop;
 | 
						|
   property BorderLeft: TCSSBorderStyle read FBorderLeft write FBorderLeft;
 | 
						|
   property BorderBottom: TCSSBorderStyle read FBorderBottom write FBorderBottom;
 | 
						|
   property BorderRight: TCSSBorderStyle read FBorderRight write FBorderRight;
 | 
						|
   property Alignment: TIpHtmlAlign read FAlignment write FAlignment;
 | 
						|
 public
 | 
						|
   constructor Create;
 | 
						|
   destructor Destroy; override;
 | 
						|
   procedure ReadCommands(ACommands: TStrings);
 | 
						|
   procedure MergeAdditionalProps(AProps: TCSSProps);
 | 
						|
 end;
 | 
						|
 | 
						|
 { TCSSGlobalProps serves as a global list of TCSSProps objects, it is
 | 
						|
   populated when parsing the CSS and then used to look up the CSS styles
 | 
						|
   for a certain CSS selector (the selector is supplied as a string and it
 | 
						|
   returns a reference to the TCSSProps object for this selector). The
 | 
						|
   contained TCSSProps objects are created and owned by TCSSGlobalProps }
 | 
						|
 TCSSGlobalProps = class
 | 
						|
   FElements: TFPObjectHashTable;
 | 
						|
 public
 | 
						|
   constructor Create;
 | 
						|
   destructor Destroy; override;
 | 
						|
   {$IFDEF IP_LAZARUS_DBG}
 | 
						|
   procedure DumpProps;
 | 
						|
   {$ENDIF}
 | 
						|
   function GetPropsObject(ATagName: String; AClassID: String = ''; CreateIfNotExist: Boolean = False): TCSSProps;
 | 
						|
 end;
 | 
						|
 | 
						|
{$ELSE implementation}
 | 
						|
type
 | 
						|
 | 
						|
  { TCSSReader }
 | 
						|
 | 
						|
  TCSSReader = class
 | 
						|
    FStream: TStream;
 | 
						|
    FGlobalProps: TCSSGlobalProps;
 | 
						|
    function GetStatementElements(AStatement: String): TStringList;
 | 
						|
    function GetStatementCommands(AStatement: String): TStringList;
 | 
						|
    function CheckIsComment: Boolean;
 | 
						|
    procedure EatWhiteSpace;
 | 
						|
    procedure ParseCSS;
 | 
						|
    procedure EatComment;
 | 
						|
    function FindStatement(out AStatement: String): Boolean;
 | 
						|
    function EOF: Boolean;
 | 
						|
    constructor Create(AStream: TStream; AGlobalProps: TCSSGlobalProps);
 | 
						|
  end;
 | 
						|
 | 
						|
function IsWhiteSpace(AChar: Char; ExcludeSpaces: Boolean = False): Boolean;
 | 
						|
begin
 | 
						|
  Result := AChar in [#9, #10, #11, #13];
 | 
						|
  if not Result and not ExcludeSpaces then
 | 
						|
    Result := AChar = ' ';
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function SeperateCommands(Commands: String): TStringList;
 | 
						|
var
 | 
						|
 i, fpos1, fpos2: Integer;
 | 
						|
 Command: String;
 | 
						|
begin
 | 
						|
  Result := TStringList.Create;
 | 
						|
  FPos1 := 1;
 | 
						|
 | 
						|
  for i := 1 to Length(Commands) do
 | 
						|
  begin
 | 
						|
    if Commands[i] = ';' then
 | 
						|
    begin
 | 
						|
      Command := Copy(Commands, FPos1, i-FPos1);
 | 
						|
      FPos1 := i+1;
 | 
						|
      for FPos2 := Length(Command) downto 1 do
 | 
						|
        if IsWhiteSpace(Command[FPos2], True) then
 | 
						|
          Delete(Command, FPos2, 1);
 | 
						|
      Result.Add(Trim(Command));
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  Command := Trim(Copy(Commands, FPos1, Length(Commands)));
 | 
						|
  if Command <> '' then
 | 
						|
  begin
 | 
						|
    Result.Add(Command);
 | 
						|
  end;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
function FontWeightFromString(S: String): TCSSFontWeight;
 | 
						|
begin
 | 
						|
  Result := cfwNormal;
 | 
						|
  S := trim(LowerCase(S));
 | 
						|
  case S[1] of
 | 
						|
    '1': if S = '100' then Result := cfw100;
 | 
						|
    '2': if S = '200' then Result := cfw200;
 | 
						|
    '3': if S = '300' then Result := cfw300;
 | 
						|
    '4': if S = '400' then Result := cfw400;
 | 
						|
    '5': if S = '500' then Result := cfw500;
 | 
						|
    '6': if S = '600' then Result := cfw600;
 | 
						|
    '7': if S = '700' then Result := cfw700;
 | 
						|
    '8': if S = '800' then Result := cfw800;
 | 
						|
    '9': if S = '900' then Result := cfw900;
 | 
						|
    'b': if S = 'bold' then Result := cfwBold
 | 
						|
         else if S = 'bolder' then Result := cfwBolder;
 | 
						|
    'l': if S = 'lighter' then Result := cfwLighter;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
const
 | 
						|
  htmlNamedColors : array[0..140] of record
 | 
						|
    s: string;
 | 
						|
    c: TColor;
 | 
						|
  end = ( // alphabetically ordered
 | 
						|
(s:'ALICEBLUE'; c:$FFF8F0),
 | 
						|
(s:'ANTIQUEWHITE'; c:$D7EBFA),
 | 
						|
(s:'AQUA'; c: $FFFF00),
 | 
						|
(s:'AQUAMARINE'; c:$D4FF7F),
 | 
						|
(s:'AZURE'; c:$FFFFF0),
 | 
						|
(s:'BEIGE'; c:$DCF5F5),
 | 
						|
(s:'BISQUE'; c:$C4E4FF),
 | 
						|
(s:'BLACK'; c:clBlack),
 | 
						|
(s:'BLANCHEDALMOND'; c:$CDEBFF),
 | 
						|
(s:'BLUE'; c:$FF0000),
 | 
						|
(s:'BLUEVIOLET'; c:$E22B8A),
 | 
						|
(s:'BROWN'; c:$2A2AA5),
 | 
						|
(s:'BURLYWOOD'; c:$87B8DE),
 | 
						|
(s:'CADETBLUE'; c:$A09E5F),
 | 
						|
(s:'CHARTREUSE'; c:$00FF7F),
 | 
						|
(s:'CHOCOLATE'; c:$1E69D2),
 | 
						|
(s:'CORAL'; c:$507FFF),
 | 
						|
(s:'CORNFLOWERBLUE'; c:$ED9564),
 | 
						|
(s:'CORNSILK'; c:$DCF8FF),
 | 
						|
(s:'CRIMSON'; c:$3C14DC),
 | 
						|
(s:'CYAN'; c: $FFFF00),
 | 
						|
(s:'DARKBLUE'; c:$8B0000),
 | 
						|
(s:'DARKCYAN'; c:$8B8B00),
 | 
						|
(s:'DARKGOLDENROD'; c:$0B86B8),
 | 
						|
(s:'DARKGRAY'; c:$A9A9A9),
 | 
						|
(s:'DARKGREEN'; c:$006400),
 | 
						|
(s:'DARKKHAKI'; c:$6BB7BD),
 | 
						|
(s:'DARKMAGENTA'; c:$8B008B),
 | 
						|
(s:'DARKOLIVEGREEN'; c:$2F6B55),
 | 
						|
(s:'DARKORANGE'; c:$008CFF),
 | 
						|
(s:'DARKORCHID'; c:$CC3299),
 | 
						|
(s:'DARKRED'; c:$00008B),
 | 
						|
(s:'DARKSALMON'; c:$7A96E9),
 | 
						|
(s:'DARKSEAGREEN'; c:$8FBC8F),
 | 
						|
(s:'DARKSLATEBLUE' ; c:$8B3D48),
 | 
						|
(s:'DARKSLATEGRAY'; c:$4F4F2F),
 | 
						|
(s:'DARKTURQUOISE'; c:$D1CE00),
 | 
						|
(s:'DARKVIOLET'; c:$D30094),
 | 
						|
(s:'DARKYELLOW'; c:$008080),
 | 
						|
(s:'DEEPPINK'; c:$9314FF),
 | 
						|
(s:'DEEPSKYBLUE'; c:$FFBF00),
 | 
						|
(s:'DIMGRAY'; c:$696969),
 | 
						|
(s:'DODGERBLUE'; c:$FF901E),
 | 
						|
(s:'FIREBRICK'; c:$2222B2),
 | 
						|
(s:'FLORALWHITE'; c:$F0FAFF),
 | 
						|
(s:'FORESTGREEN'; c:$228B22),
 | 
						|
(s:'FUCHSIA'; c:$FF00FF),
 | 
						|
(s:'GAINSBORO'; c:$DCDCDC),
 | 
						|
(s:'GHOSTWHITE'; c:$FFF8F8),
 | 
						|
(s:'GOLD'; c:$00D7FF),
 | 
						|
(s:'GOLDENROD'; c:$20A5DA),
 | 
						|
(s:'GRAY'; c:$808080),
 | 
						|
(s:'GREEN'; c:$008000),
 | 
						|
(s:'GREENYELLOW'; c:$2FFFAD),
 | 
						|
(s:'HONEYDEW'; c:$F0FFF0),
 | 
						|
(s:'HOTPINK'; c:$B469FF),
 | 
						|
(s:'INDIANRED'; c:$5C5CCD),
 | 
						|
(s:'INDIGO'; c:$82004B),
 | 
						|
(s:'IVORY'; c:$F0FFFF),
 | 
						|
(s:'KHAKI'; c:$8CE6F0),
 | 
						|
(s:'LAVENDER'; c:$FAE6E6),
 | 
						|
(s:'LAVENDERBLUSH'; c:$F5F0FF),
 | 
						|
(s:'LAWNGREEN'; c:$00FC7C),
 | 
						|
(s:'LEMONCHIFFON'; c:$CDFAFF),
 | 
						|
(s:'LIGHTBLUE'; c:$E6D8AD),
 | 
						|
(s:'LIGHTCORAL'; c:$8080F0),
 | 
						|
(s:'LIGHTCYAN'; c:$FFFFE0),
 | 
						|
(s:'LIGHTGOLDENRODYELLOW'; c:$D2FAFA),
 | 
						|
(s:'LIGHTGREEN'; c:$90EE90),
 | 
						|
(s:'LIGHTGREY'; c:$D3D3D3),
 | 
						|
(s:'LIGHTPINK'; c:$C1B6FF),
 | 
						|
(s:'LIGHTSALMON'; c:$7AA0FF),
 | 
						|
(s:'LIGHTSEAGREEN'; c:$AAB220),
 | 
						|
(s:'LIGHTSKYBLUE'; c:$FACE87),
 | 
						|
(s:'LIGHTSLATEGRAY'; c:$998877),
 | 
						|
(s:'LIGHTSTEELBLUE'; c:$DEC4B0),
 | 
						|
(s:'LIGHTYELLOW'; c:$E0FFFF),
 | 
						|
(s:'LIME'; c:$00FF00),
 | 
						|
(s:'LIMEGREEN'; c:$32CD32),
 | 
						|
(s:'LINEN'; c:$E6F0FA),
 | 
						|
(s:'MAGENTA'; c:$FF00FF),
 | 
						|
(s:'MAROON'; c:$000080),
 | 
						|
(s:'MEDIUMAQUAMARINE'; c:$AACD66),
 | 
						|
(s:'MEDIUMBLUE'; c:$CD0000),
 | 
						|
(s:'MEDIUMORCHID'; c:$D355BA),
 | 
						|
(s:'MEDIUMPURPLE'; c:$DB7093),
 | 
						|
(s:'MEDIUMSEAGREEN'; c:$71B33C),
 | 
						|
(s:'MEDIUMSLATEBLUE'; c:$EE687B),
 | 
						|
(s:'MEDIUMSPRINGGREEN'; c:$9AFA00),
 | 
						|
(s:'MEDIUMTURQUOISE'; c:$CCD148),
 | 
						|
(s:'MEDIUMVIOLETRED'; c:$8515C7),
 | 
						|
(s:'MIDNIGHTBLUE'; c:$701919),
 | 
						|
(s:'MINTCREAM'; c:$FAFFF5),
 | 
						|
(s:'MISTYROSE'; c:$E1E4FF),
 | 
						|
(s:'MOCCASIN'; c:$B5E4FF),
 | 
						|
(s:'NAVAJOWHITE'; c:$ADDEFF),
 | 
						|
(s:'NAVY'; c:$800000),
 | 
						|
(s:'OLDLACE'; c:$E6F5FD),
 | 
						|
(s:'OLIVE'; c:$008080),
 | 
						|
(s:'OLIVEDRAB'; c:$238E6B),
 | 
						|
(s:'ORANGE'; c:$00A5FF),
 | 
						|
(s:'ORANGERED'; c:$0045FF),
 | 
						|
(s:'ORCHID'; c:$D670DA),
 | 
						|
(s:'PALEGOLDENROD'; c:$AAE8EE),
 | 
						|
(s:'PALEGREEN'; c:$98FB98),
 | 
						|
(s:'PALETURQUOISE'; c:$EEEEAF),
 | 
						|
(s:'PALEVIOLETRED'; c:$9370DB),
 | 
						|
(s:'PAPAYAWHIP'; c:$D5EFFF),
 | 
						|
(s:'PEACHPUFF'; c:$B9DAFF),
 | 
						|
(s:'PERU'; c:$3F85CD),
 | 
						|
(s:'PINK'; c:$CBC0FF),
 | 
						|
(s:'PLUM'; c:$DDA0DD),
 | 
						|
(s:'POWDERBLUE'; c:$E6E0B0),
 | 
						|
(s:'PURPLE'; c:$800080),
 | 
						|
(s:'RED'; c:$0000FF),
 | 
						|
(s:'ROSYBROWN'; c:$8F8FBC),
 | 
						|
(s:'ROYALBLUE'; c:$901604),
 | 
						|
(s:'SADDLEBROWN'; c:$13458B),
 | 
						|
(s:'SALMON'; c:$7280FA),
 | 
						|
(s:'SANDYBROWN'; c:$60A4F4),
 | 
						|
(s:'SEAGREEN'; c:$578B2E),
 | 
						|
(s:'SEASHELL'; c:$EEF5FF),
 | 
						|
(s:'SIENNA'; c:$2D52A0),
 | 
						|
(s:'SILVER'; c:$C0C0C0),
 | 
						|
(s:'SKYBLUE'; c:$EBCE87),
 | 
						|
(s:'SLATEBLUE'; c:$CD5A6A),
 | 
						|
(s:'SLATEGRAY'; c:$908070),
 | 
						|
(s:'SNOW'; c:$FAFAFF),
 | 
						|
(s:'SPRINGGREEN'; c:$7FFF00),
 | 
						|
(s:'STEELBLUE'; c:$B48246),
 | 
						|
(s:'TAN'; c:$8CB4D2),
 | 
						|
(s:'TEAL'; c:$808000),
 | 
						|
(s:'THISTLE'; c:$D8BFD8),
 | 
						|
(s:'TOMATO'; c:$4763FF),
 | 
						|
(s:'TURQUOISE'; c:$D0E040),
 | 
						|
(s:'VIOLET'; c:$EE82EE),
 | 
						|
(s:'WHEAT'; c:$B3DEF5),
 | 
						|
(s:'WHITE'; c:$FFFFFF),
 | 
						|
(s:'WHITESMOKE'; c:$F5F5F5),
 | 
						|
(s:'YELLOW'; c:$00FFFF),
 | 
						|
(s:'YELLOWGREEN'; c:$32CD9A)
 | 
						|
);
 | 
						|
 | 
						|
function BinSearchNamedColor(const sColor: string; var color: TColor): boolean;
 | 
						|
var
 | 
						|
  First: Integer;
 | 
						|
  Last: Integer;
 | 
						|
  Pivot: Integer;
 | 
						|
begin
 | 
						|
  First  := Low(htmlNamedColors); //Sets the first item of the range
 | 
						|
  Last   := High(htmlNamedColors); //Sets the last item of the range
 | 
						|
  Result  := False; //Initializes the Found flag (Not found yet)
 | 
						|
 | 
						|
  //If First > Last then the searched item doesn't exist
 | 
						|
  //If the item is found the loop will stop
 | 
						|
  while (First <= Last) {and (not Result)} do
 | 
						|
  begin
 | 
						|
    //Gets the middle of the selected range
 | 
						|
    Pivot := (First + Last) div 2;
 | 
						|
    //Compares the String in the middle with the searched one
 | 
						|
    if htmlNamedColors[Pivot].s = sColor then
 | 
						|
    begin
 | 
						|
      Result  := True;
 | 
						|
      color := htmlNamedColors[Pivot].c;
 | 
						|
      exit;
 | 
						|
    end
 | 
						|
    //If the Item in the middle has a bigger value than
 | 
						|
    //the searched item, then select the first half
 | 
						|
    else if htmlNamedColors[Pivot].s > sColor then
 | 
						|
      Last := Pivot - 1
 | 
						|
        //else select the second half
 | 
						|
    else
 | 
						|
      First := Pivot + 1;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function ColorFromString(S: String): TColor;
 | 
						|
var
 | 
						|
  R, G, B, Err : Integer;
 | 
						|
begin
 | 
						|
  Result := -1;
 | 
						|
  if S = '' then
 | 
						|
    Exit;
 | 
						|
  S := UpperCase(S);
 | 
						|
  if S[1] = '#' then
 | 
						|
    if length(S) <> 7 then
 | 
						|
      exit
 | 
						|
    else begin
 | 
						|
      val('$'+Copy(S,2,2), R, Err);
 | 
						|
      if Err <> 0 then
 | 
						|
        R := 255;
 | 
						|
      val('$'+Copy(S,4,2), G, Err);
 | 
						|
      if Err <> 0 then
 | 
						|
        G := 255;
 | 
						|
      val('$'+Copy(S,6,2), B, Err);
 | 
						|
      if Err <> 0 then
 | 
						|
        B := 255;
 | 
						|
      Exit(RGB(R, G, B));
 | 
						|
    end
 | 
						|
  else
 | 
						|
  if BinSearchNamedColor(S, result) then exit
 | 
						|
  else
 | 
						|
  if length(S) = 6 then
 | 
						|
    try
 | 
						|
      val('$'+Copy(S,1,2), R, Err);
 | 
						|
      if Err <> 0 then
 | 
						|
        R := 255;
 | 
						|
      val('$'+Copy(S,3,2), G, Err);
 | 
						|
      if Err <> 0 then
 | 
						|
        G := 255;
 | 
						|
      val('$'+Copy(S,5,2), B, Err);
 | 
						|
      if Err <> 0 then
 | 
						|
        B := 255;
 | 
						|
      Result := RGB(R, G, B);
 | 
						|
    except
 | 
						|
        Result := -1;
 | 
						|
    end
 | 
						|
  //else WriteLn('>>>>> Unknwn Color! = ', S);
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
function SizePxFromString(S: String): Integer;
 | 
						|
begin
 | 
						|
  S := Copy(S, 1, Pos('PX', UpperCase(S)) - 1);
 | 
						|
  Result := StrToIntDef(S, 0);
 | 
						|
end;
 | 
						|
 | 
						|
function StrToCssMargin(S: string): TCSSMargin;
 | 
						|
var
 | 
						|
  i: SizeInt;
 | 
						|
begin
 | 
						|
  S:=lowercase(S);
 | 
						|
  Result.Style:=cmsAuto;
 | 
						|
  Result.Size:=0;
 | 
						|
  if (S='') or (S='auto') then exit;
 | 
						|
 | 
						|
  i:=Pos('px',S);
 | 
						|
  if i>0 then begin
 | 
						|
    Result.Style:=cmsPx;
 | 
						|
    Result.Size:=StrToIntDef(copy(S,1,i-1),0);
 | 
						|
    exit;
 | 
						|
  end;
 | 
						|
 | 
						|
  i:=Pos('em',S);
 | 
						|
  if i>0 then begin
 | 
						|
    Result.Style:=cmsEm;
 | 
						|
    Result.Size:=StrToIntDef(copy(S,1,i-1),0);
 | 
						|
    exit;
 | 
						|
  end;
 | 
						|
 | 
						|
  i:=Pos('%',S);
 | 
						|
  if i>0 then begin
 | 
						|
    Result.Style:=cmsPercent;
 | 
						|
    Result.Size:=StrToIntDef(copy(S,1,i-1),0);
 | 
						|
    exit;
 | 
						|
  end;
 | 
						|
 | 
						|
  // a number without unit is px
 | 
						|
  Result.Style:=cmsPx;
 | 
						|
  Result.Size:=StrToIntDef(S,0);
 | 
						|
end;
 | 
						|
 | 
						|
function CSSFontStyleFromName(S: String): TCSSFontStyle;
 | 
						|
begin
 | 
						|
  Result := cfsNormal;
 | 
						|
  if length(s)<2 then exit;
 | 
						|
  case S[2] of
 | 
						|
    'b': if S = 'oblique' then Result := cfsOblique;
 | 
						|
    'n': if S = 'inherit' then Result := cfsInherit;
 | 
						|
    't': if S = 'italic' then Result := cfsItalic;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function BorderStyleFromString(S: String): TCSSBorderStyle;
 | 
						|
begin
 | 
						|
  Result := cbsNone;
 | 
						|
  S := LowerCase(S);
 | 
						|
  case S[1] of
 | 
						|
    'd':
 | 
						|
      if S = 'dotted' then
 | 
						|
        Result := cbsDotted
 | 
						|
      else
 | 
						|
      if S = 'dashed' then
 | 
						|
        Result := cbsDashed
 | 
						|
      else
 | 
						|
      if S = 'double' then
 | 
						|
        Result := cbsDouble;
 | 
						|
    'g': if S = 'groove' then Result := cbsGroove;
 | 
						|
    'h': if S = 'hidden' then Result := cbsHidden;
 | 
						|
    'i': if S = 'inset' then Result := cbsInset;
 | 
						|
    'o': if S = 'outset' then Result := cbsOutset;
 | 
						|
    'r': if S = 'ridge' then Result := cbsRidge;
 | 
						|
    's': if S = 'solid' then Result := cbsSolid;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{ TCSSReader }
 | 
						|
 | 
						|
function TCSSReader.GetStatementElements(AStatement: String): TStringList;
 | 
						|
var
 | 
						|
 i, fpos: Integer;
 | 
						|
 Elements : String;
 | 
						|
 Element: String;
 | 
						|
 ElementClass: String;
 | 
						|
begin
 | 
						|
  Result := TStringList.Create;
 | 
						|
  fpos := Pos('{', AStatement);
 | 
						|
  if fpos > 0 then
 | 
						|
  begin
 | 
						|
    Elements := Copy(AStatement,1,fpos-1);
 | 
						|
    for i := Length(Elements) downto 1 do
 | 
						|
      if IsWhiteSpace(Elements[i]) then
 | 
						|
        Delete(Elements, i, 1);
 | 
						|
     Result.Delimiter := ',';
 | 
						|
     Result.DelimitedText := Elements;
 | 
						|
  end;
 | 
						|
 | 
						|
  for i := 0 to Result.Count-1 do begin
 | 
						|
    Element := LowerCase(Result[i]);
 | 
						|
    ElementClass := '';
 | 
						|
    fpos := Pos('.', Element);
 | 
						|
    if fpos = 0 then
 | 
						|
    begin
 | 
						|
      Result.Objects[i] := FGlobalProps.GetPropsObject(Element, '', True);
 | 
						|
    end
 | 
						|
    else begin
 | 
						|
      ElementClass := LowerCase(Copy(Element, FPos+1, Length(Element)));
 | 
						|
      Element := LowerCase(Copy(Element, 1, FPos-1));
 | 
						|
      Result.Objects[i] := FGlobalProps.GetPropsObject(Element, ElementClass, True);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
function TCSSReader.GetStatementCommands(AStatement: String): TStringList;
 | 
						|
var
 | 
						|
 fpos1, fpos2: Integer;
 | 
						|
 Commands: String;
 | 
						|
begin
 | 
						|
  fpos1 := Pos('{', AStatement)+1;
 | 
						|
  fpos2 := Pos('}', AStatement)-1;
 | 
						|
  Commands := Copy(AStatement, fpos1, fpos2-fpos1+1);
 | 
						|
  Result := SeperateCommands(Commands);
 | 
						|
end;
 | 
						|
 | 
						|
function TCSSProps.GetCommandArgs(ACommand: String): TStringList;
 | 
						|
var
 | 
						|
  i: Integer;
 | 
						|
  WantArg: Boolean;
 | 
						|
  Arg: String;
 | 
						|
  Start: Integer;
 | 
						|
  Quote: char;
 | 
						|
  WantChar: Boolean;
 | 
						|
  Len: Integer;
 | 
						|
begin
 | 
						|
  Result := TStringList.Create;
 | 
						|
  Start := Pos(':', ACommand)+1;
 | 
						|
 | 
						|
 | 
						|
  WantArg := True;
 | 
						|
  Quote := #0;
 | 
						|
  for i := Start to Length(ACommand) do
 | 
						|
  begin
 | 
						|
    if (Quote = #0) and (ACommand[i] in ['"','''']) then
 | 
						|
    begin
 | 
						|
      Quote := ACommand[i];
 | 
						|
      Start := i+1;
 | 
						|
      continue;
 | 
						|
    end;
 | 
						|
    if Quote<>#0 then begin
 | 
						|
      if ACommand[i]=Quote then begin
 | 
						|
        Quote:=#0;
 | 
						|
        Arg := Copy(ACommand, Start, i-Start);
 | 
						|
        Result.Add(Arg);
 | 
						|
      end;
 | 
						|
      continue;
 | 
						|
    end;
 | 
						|
    if WantArg then
 | 
						|
    begin
 | 
						|
      if IsWhiteSpace(ACommand[i]) then
 | 
						|
        Continue;
 | 
						|
      Start := i;
 | 
						|
      WantArg := False;
 | 
						|
      continue;
 | 
						|
    end
 | 
						|
    else // we have an arg we are reading ...
 | 
						|
    begin
 | 
						|
      WantChar:=not (ACommand[i] in [';',' ',#9]);
 | 
						|
      if (i<Length(ACommand)) and WantChar
 | 
						|
      then
 | 
						|
        continue;
 | 
						|
      WantArg := True;
 | 
						|
      Len:=i-Start;
 | 
						|
      if WantChar then inc(Len);
 | 
						|
      Arg := Copy(ACommand, Start, Len);
 | 
						|
      Result.Add(Arg);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function TCSSProps.GetCommandName(ACommand: String): String;
 | 
						|
begin
 | 
						|
  Result := Copy(ACommand, 1, Pos(':', ACommand)-1);
 | 
						|
end;
 | 
						|
 | 
						|
function TCSSReader.CheckIsComment: Boolean;
 | 
						|
begin
 | 
						|
  Result := False;
 | 
						|
  if EOF then
 | 
						|
    exit;
 | 
						|
  Result := char(FStream.ReadByte) = '*';
 | 
						|
  if not Result then
 | 
						|
    FStream.Position := FStream.Position-1;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TCSSReader.EatWhiteSpace;
 | 
						|
var
 | 
						|
  Buf: char;
 | 
						|
  //comment: integer;
 | 
						|
begin
 | 
						|
  //comment:=0;
 | 
						|
  while not EOF do
 | 
						|
  begin
 | 
						|
    Buf := char(FStream.ReadByte);
 | 
						|
    if (Buf = '/') and not EOF then
 | 
						|
    begin
 | 
						|
      if CheckIsComment then
 | 
						|
      begin
 | 
						|
        EatComment;
 | 
						|
        Buf := ' ';
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    if (IsWhiteSpace(Buf) = False) then
 | 
						|
    begin
 | 
						|
      FStream.Position := FStream.Position-1;
 | 
						|
      break;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TCSSReader.ParseCSS;
 | 
						|
var
 | 
						|
  Statement: String;
 | 
						|
  Elements: TStringList;
 | 
						|
  Commands: TStringList;
 | 
						|
  Element: TCSSProps;
 | 
						|
  I: Integer;
 | 
						|
begin
 | 
						|
  while FindStatement(Statement) do begin
 | 
						|
   Elements := GetStatementElements(Statement);
 | 
						|
   Commands := GetStatementCommands(Statement);
 | 
						|
   for I := 0 to Elements.Count-1 do
 | 
						|
   begin
 | 
						|
     Element := TCSSProps(Elements.Objects[I]);
 | 
						|
     Element.ReadCommands(Commands);
 | 
						|
   end;
 | 
						|
   Elements.Free;
 | 
						|
   Commands.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TCSSReader.EatComment;
 | 
						|
var
 | 
						|
  Buf: array[0..1] of char;
 | 
						|
begin
 | 
						|
  Buf := #0#0;
 | 
						|
  while (EOF = False) and (Buf <> '*/') do
 | 
						|
  begin
 | 
						|
    Buf[0] := Buf[1];
 | 
						|
    FStream.Read(Buf[1], 1);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function TCSSReader.FindStatement(out AStatement: String): Boolean;
 | 
						|
var
 | 
						|
 Buf: char;
 | 
						|
 Buf1: string;
 | 
						|
 RCount: Integer;
 | 
						|
 FStart, FEnd: Integer;
 | 
						|
begin
 | 
						|
  Result := False;
 | 
						|
  EatWhiteSpace;
 | 
						|
 | 
						|
  AStatement := '';
 | 
						|
 | 
						|
  SetLength(Buf1,1023);
 | 
						|
  FStart := FStream.Position;
 | 
						|
  while not EOF do
 | 
						|
  begin
 | 
						|
 | 
						|
    Buf := Char(FStream.ReadByte);
 | 
						|
    FEnd := FStream.Position;
 | 
						|
    if (Buf = '/') and CheckIsComment then
 | 
						|
    begin
 | 
						|
      FStream.Position := FStart;
 | 
						|
      if length(Buf1)<FEnd-FStart then
 | 
						|
        setlength(Buf1,FEnd-FStart);
 | 
						|
      RCount := FStream.Read(Buf1[1], FEnd-FStart-1);
 | 
						|
      AStatement := AStatement + Copy(Buf1,0,RCount);
 | 
						|
      FStream.Position := FEnd+1;
 | 
						|
      EatComment;
 | 
						|
      FStart := FStream.Position;
 | 
						|
    end
 | 
						|
    else if Buf = '}' then
 | 
						|
    begin
 | 
						|
      Result := True;
 | 
						|
      FStream.Position := FStart;
 | 
						|
      if length(Buf1)<FEnd-FStart then
 | 
						|
        setlength(Buf1,FEnd-FStart);
 | 
						|
      RCount := FStream.Read(Buf1[1], FEnd-FStart);
 | 
						|
      AStatement := AStatement + Copy(Buf1,0,RCount);
 | 
						|
      break;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function TCSSReader.EOF: Boolean;
 | 
						|
begin
 | 
						|
  Result := FStream.Position >= FStream.Size;
 | 
						|
end;
 | 
						|
 | 
						|
constructor TCSSReader.Create(AStream: TStream; AGlobalProps: TCSSGlobalProps);
 | 
						|
begin
 | 
						|
  inherited Create;
 | 
						|
  FStream := AStream;
 | 
						|
  FGlobalProps:= AGlobalProps;
 | 
						|
end;
 | 
						|
 | 
						|
{ TCSSProps }
 | 
						|
 | 
						|
constructor TCSSProps.Create;
 | 
						|
begin
 | 
						|
  FFont := TCSSFont.Create;
 | 
						|
  FBGColor := -1;
 | 
						|
  FColor := -1;
 | 
						|
  FAlignment := haUnknown;
 | 
						|
  FBorder := TCSSBorder.Create;
 | 
						|
end;
 | 
						|
 | 
						|
destructor TCSSProps.Destroy;
 | 
						|
var
 | 
						|
  i: Integer;
 | 
						|
begin
 | 
						|
  if Assigned(FClassIDs) then
 | 
						|
  begin
 | 
						|
    for i := 0 to FClassIDs.Count-1 do
 | 
						|
      FClassIDs.Objects[i].Free;
 | 
						|
    FClassIDs.Free;
 | 
						|
  end;
 | 
						|
  FFont.Free;
 | 
						|
  FBorder.Free;
 | 
						|
  inherited Destroy;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TCSSProps.ReadCommands(ACommands: TStrings);
 | 
						|
var
 | 
						|
  Args: TStringlist;
 | 
						|
  ACommand: String;
 | 
						|
  Command: String;
 | 
						|
  I: Integer;
 | 
						|
begin
 | 
						|
  for I := 0 to ACommands.Count-1 do
 | 
						|
  begin
 | 
						|
    ACommand := ACommands[I];
 | 
						|
    if ACommand='' then continue;
 | 
						|
    Command := LowerCase(GetCommandName(ACommand));
 | 
						|
    if Command='' then continue;
 | 
						|
 | 
						|
    Args := GetCommandArgs(ACommand);
 | 
						|
    try
 | 
						|
      case Command[1] of
 | 
						|
      'c': if Command = 'color' then
 | 
						|
             if Args.Count > 0 then
 | 
						|
               Color := ColorFromString(Args[0])
 | 
						|
             else
 | 
						|
               Color := clDefault;
 | 
						|
 | 
						|
      'b': if Command = 'background-color' then
 | 
						|
           begin
 | 
						|
             if Args.Count > 0 then
 | 
						|
               BGColor := ColorFromString(Args[0])
 | 
						|
             else
 | 
						|
               BGColor := clDefault
 | 
						|
           end
 | 
						|
           else if Command = 'background' then
 | 
						|
           begin
 | 
						|
             if Args.Count > 0 then BGColor := ColorFromString(Args[0]);
 | 
						|
             if Args.Count > 1 then ; // background image
 | 
						|
             if Args.Count > 2 then ; // background image repeat
 | 
						|
             if Args.Count > 3 then ; // background attachment
 | 
						|
             if Args.Count > 4 then ; // background position
 | 
						|
           end
 | 
						|
           else if Command = 'border' then
 | 
						|
           begin
 | 
						|
             if Args.Count > 0 then Border.Width := SizePxFromString(Args[0]);
 | 
						|
             if Args.Count > 1 then Border.Style := BorderStyleFromString(Args[1]);
 | 
						|
             if Args.Count > 2 then Border.Color := ColorFromString(Args[2]);
 | 
						|
           end
 | 
						|
           else if Command = 'border-width' then
 | 
						|
           begin
 | 
						|
             Border.Width := SizePxFromString(Args[0]);
 | 
						|
           end
 | 
						|
           else if Command = 'border-color' then
 | 
						|
           begin
 | 
						|
             Border.Color := ColorFromString(Args[0]);
 | 
						|
           end
 | 
						|
           else if Command = 'border-style' then
 | 
						|
           begin
 | 
						|
             Border.Style := BorderStyleFromString(Args[0]);
 | 
						|
           end;
 | 
						|
 | 
						|
      'm':
 | 
						|
        if Command = 'margin-top' then
 | 
						|
        begin
 | 
						|
          if Args.Count > 0 then MarginTop := StrToCssMargin(Args[0]);
 | 
						|
        end else if Command = 'margin-left' then
 | 
						|
        begin
 | 
						|
          if Args.Count > 0 then MarginLeft := StrToCssMargin(Args[0]);
 | 
						|
        end else if Command = 'margin-bottom' then
 | 
						|
        begin
 | 
						|
          if Args.Count > 0 then MarginBottom := StrToCssMargin(Args[0]);
 | 
						|
        end else if Command = 'margin-right' then
 | 
						|
        begin
 | 
						|
          if Args.Count > 0 then MarginRight := StrToCssMargin(Args[0]);
 | 
						|
        end else if Command = 'margin' then
 | 
						|
        begin
 | 
						|
          case Args.Count of
 | 
						|
          1:begin
 | 
						|
              // 1 arg: all four the same
 | 
						|
              MarginTop := StrToCssMargin(Args[0]);
 | 
						|
              MarginBottom := MarginTop;
 | 
						|
              MarginLeft := MarginTop;
 | 
						|
              MarginRight := MarginTop;
 | 
						|
            end;
 | 
						|
          2:begin
 | 
						|
              // 2 args: top+bottom and left+right
 | 
						|
              MarginTop := StrToCssMargin(Args[0]);
 | 
						|
              MarginBottom := MarginTop;
 | 
						|
              MarginLeft := StrToCssMargin(Args[1]);
 | 
						|
              MarginRight := MarginLeft;
 | 
						|
            end;
 | 
						|
          3:begin
 | 
						|
              // 3 args: top right bottom
 | 
						|
              MarginTop := StrToCssMargin(Args[0]);
 | 
						|
              MarginRight := StrToCssMargin(Args[1]);
 | 
						|
              MarginBottom := StrToCssMargin(Args[2]);
 | 
						|
            end;
 | 
						|
          4:begin
 | 
						|
              // 4 args: top right bottom left
 | 
						|
              MarginTop := StrToCssMargin(Args[0]);
 | 
						|
              MarginRight := StrToCssMargin(Args[1]);
 | 
						|
              MarginBottom := StrToCssMargin(Args[2]);
 | 
						|
              MarginLeft := StrToCssMargin(Args[3]);
 | 
						|
            end;
 | 
						|
          end;
 | 
						|
        end;
 | 
						|
 | 
						|
      't': if (Command = 'text-align') and (Args.Count = 1) then
 | 
						|
             if Args.Count > 0 then
 | 
						|
               Alignment := GetAlignmentForStr(Args[0])
 | 
						|
             else
 | 
						|
               Alignment := GetAlignmentForStr('');
 | 
						|
 | 
						|
 | 
						|
      'f':
 | 
						|
          if length(Command) > 7 then
 | 
						|
          begin
 | 
						|
            case Command[7] of
 | 
						|
              'a': if (Command = 'font-family')and (Args.Count > 0) then
 | 
						|
                     Font.Name := Args[0];
 | 
						|
              'i': if (Command = 'font-size') and (Args.Count > 0) then
 | 
						|
                     Font.Size := Args[0];
 | 
						|
              't': if (Command = 'font-style') and (Args.Count > 0) then
 | 
						|
                     Font.Style := CSSFontStyleFromName(Args[0]);
 | 
						|
              'e': if (Command = 'font-weight') and (Args.Count > 0) then
 | 
						|
                     Font.Weight := FontWeightFromString(Args[0]);
 | 
						|
            end;
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
    finally
 | 
						|
      Args.Free;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TCSSProps.MergeAdditionalProps(AProps: TCSSProps);
 | 
						|
begin
 | 
						|
  if AProps.Color <> -1 then Color := AProps.Color;
 | 
						|
  if AProps.BGColor <> -1 then BGColor := AProps.BGColor;
 | 
						|
  if AProps.Alignment <> haUnknown then Alignment := AProps.Alignment;
 | 
						|
  if AProps.Font.Name <> '' then Font.Name := AProps.Font.Name;
 | 
						|
  if AProps.Font.Size <> '' then Font.Size := AProps.Font.Size;
 | 
						|
  if AProps.Font.Style <> cfsNormal then Font.Style := AProps.Font.Style;
 | 
						|
  if AProps.Font.Weight <> cfwNormal then Font.Weight := AProps.Font.Weight;
 | 
						|
 | 
						|
  if AProps.MarginBottom.Style <> cmsNone then
 | 
						|
    FMarginBottom.Style := AProps.MarginBottom.Style;
 | 
						|
  if AProps.MarginBottom.Size <> 0 then
 | 
						|
    FMarginBottom.Size := AProps.MarginBottom.Size;
 | 
						|
 | 
						|
  if AProps.MarginLeft.Style <> cmsNone then
 | 
						|
    FMarginLeft.Style := AProps.MarginLeft.Style;
 | 
						|
  if AProps.MarginLeft.Size <> 0 then
 | 
						|
    FMarginLeft.Size := AProps.MarginLeft.Size;
 | 
						|
 | 
						|
  if AProps.MarginRight.Style <> cmsNone then
 | 
						|
    FMarginRight.Style := AProps.MarginRight.Style;
 | 
						|
  if AProps.MarginRight.Size <> 0 then
 | 
						|
    FMarginRight.Size := AProps.MarginRight.Size;
 | 
						|
 | 
						|
  if AProps.MarginTop.Style <> cmsNone then
 | 
						|
    FMarginTop.Style := AProps.MarginTop.Style;
 | 
						|
  if AProps.MarginTop.Size <> 0 then
 | 
						|
    FMarginTop.Size := AProps.MarginTop.Size;
 | 
						|
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ TCSSGlobalProps }
 | 
						|
 | 
						|
constructor TCSSGlobalProps.Create;
 | 
						|
begin
 | 
						|
  FElements := TFPObjectHashTable.Create(True);
 | 
						|
end;
 | 
						|
 | 
						|
destructor TCSSGlobalProps.Destroy;
 | 
						|
begin
 | 
						|
  FElements.Free;
 | 
						|
  inherited Destroy;
 | 
						|
end;
 | 
						|
 | 
						|
function TCSSGlobalProps.GetPropsObject(ATagName: String;
 | 
						|
  AClassID: String; CreateIfNotExist: Boolean): TCSSProps;
 | 
						|
var
 | 
						|
  Selector: String;
 | 
						|
 | 
						|
  procedure Lookup(const AName: String);
 | 
						|
  begin
 | 
						|
    if length(AClassID) > 0 then
 | 
						|
      Selector := AName + '.' + AClassID
 | 
						|
    else
 | 
						|
      Selector := AName;
 | 
						|
 | 
						|
    // The css selectors are already lowercase, this is
 | 
						|
    // already done in the css parser. And the html parser
 | 
						|
    // can only deliver its own built-in tag names anyways.
 | 
						|
    // Also the names are not expected to be longer than
 | 
						|
    // ShortString (this would need to be a ridiculously
 | 
						|
    // long ClassID), should this ever happen then
 | 
						|
    // it would be silently truncated in the following
 | 
						|
    // type conversion to ShortString.
 | 
						|
    Result := TCSSProps(FElements.Items[Selector]);
 | 
						|
  end;
 | 
						|
 | 
						|
begin
 | 
						|
  Result := nil;
 | 
						|
  if (length(AClassID) = 0) and (length(ATagName) = 0) then
 | 
						|
    exit;
 | 
						|
 | 
						|
  Lookup(ATagName);
 | 
						|
  if (Result=nil) and not CreateIfNotExist then
 | 
						|
    Lookup('*');
 | 
						|
 | 
						|
  if (Result = nil) and CreateIfNotExist then
 | 
						|
  begin
 | 
						|
    Result := TCSSProps.Create;
 | 
						|
    FElements.Add(Selector, Result);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
{ TCSSBorder }
 | 
						|
 | 
						|
constructor TCSSBorder.Create;
 | 
						|
begin
 | 
						|
  inherited Create;
 | 
						|
  FWidth := -1;
 | 
						|
  FColor := clBlack;
 | 
						|
  FStyle := cbsNone;
 | 
						|
end;
 | 
						|
 | 
						|
{$IFDEF IP_LAZARUS_DBG}
 | 
						|
procedure DumpTCSSProps(aProp: TCSSProps);
 | 
						|
var
 | 
						|
  str: string;
 | 
						|
begin
 | 
						|
    WriteLn('Color : ', aProp.Color);
 | 
						|
    WriteLn('BgColor : ', aProp.BGColor);
 | 
						|
    WriteLn('Font : ', aProp.Font.Name, ':', aProp.Font.FFamily, ':', aProp.Font.Size);
 | 
						|
    case aProp.Alignment of
 | 
						|
       haDefault: str:= 'haDefault';
 | 
						|
       haLeft: str:= 'haLeft';
 | 
						|
       haCenter: str:= 'haCenter';
 | 
						|
       haRight: str:= 'haRight';
 | 
						|
       haJustify: str:= 'haJustify';
 | 
						|
       haChar: str:= 'haChar';
 | 
						|
       else str:= 'haUnknow';
 | 
						|
    end;
 | 
						|
    WriteLn('Align : ', str);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TCSSGlobalProps.DumpProps;
 | 
						|
var
 | 
						|
   n: integer;
 | 
						|
begin
 | 
						|
   for n:=0 to FElements.Count-1 do
 | 
						|
   begin
 | 
						|
        WriteLn('CSS for >>>: ', FElements[n]);
 | 
						|
        DumpTCSSProps(TCSSProps(FElements.Objects[n]));
 | 
						|
   end;
 | 
						|
end;
 | 
						|
{$endif}
 | 
						|
{$ENDIF}
 |