Parcourir la source

element: attribute color

mattias il y a 2 ans
Parent
commit
c48ff60abb
2 fichiers modifiés avec 187 ajouts et 9 suppressions
  1. 175 4
      src/fresnel.dom.pas
  2. 12 5
      src/fresnel.renderer.pas

+ 175 - 4
src/fresnel.dom.pas

@@ -42,6 +42,7 @@ type
   EFresnel = class(Exception)
   end;
 
+
   EFresnelFont = class(EFresnel)
   end;
 
@@ -113,7 +114,8 @@ type
     fcaPaddingRight,
     fcaPaddingBottom,
     fcaVisibility,
-    fcaBackgroundColor
+    fcaBackgroundColor,
+    fcaColor
     );
   TFresnelCSSAttributes = set of TFresnelCSSAttribute;
 
@@ -181,7 +183,8 @@ const
     'padding-right',
     'padding-bottom',
     'visibility',
-    'background-color'
+    'background-color',
+    'color'
     );
 
 type
@@ -357,6 +360,7 @@ type
     function CheckOrSetCSSPadding(const AValue: string; Check: boolean): boolean; virtual;
     function CheckCSSVisibility(const AValue: string): boolean; virtual;
     function CheckCSSBackgroundColor(const AValue: string): boolean; virtual;
+    function CheckCSSColor(const AValue: string): boolean; virtual;
     function GetComputedCSSValue(AttrID: TCSSNumericalID): TCSSString;
     procedure SetComputedCSSValue(AttrID: TCSSNumericalID; const Value: TCSSString);
     procedure SetCSSClasses(const AValue: TStrings);
@@ -581,6 +585,9 @@ function CSSStrToFloat(const s: string; out l: TFresnelLength): boolean;
 function CompareFresnelPoint(const A, B: TFresnelPoint): integer;
 function CompareFresnelRect(const A, B: TFresnelRect): integer;
 
+function FPColorToCSS(const c: TFPColor): string;
+function CSSToFPColor(const s: string; out c: TFPColor): boolean;
+
 implementation
 
 function FloatToCSSStr(const f: TFresnelLength): string;
@@ -638,6 +645,159 @@ begin
     Result:=0;
 end;
 
+function FPColorToCSS(const c: TFPColor): string;
+const
+  hex: array[0..15] of char = '0123456789abcdef';
+var
+  br, bg, bb, ba: Byte;
+begin
+  if (lo(c.Red)=hi(c.Red))
+      and (lo(c.Green)=hi(c.Green))
+      and (lo(c.Blue)=hi(c.Blue))
+      and (lo(c.Alpha)=hi(c.Alpha)) then
+  begin
+    br:=lo(c.Red);
+    bg:=lo(c.Green);
+    bb:=lo(c.Blue);
+    ba:=lo(c.Alpha);
+    if (br and 15 = br shr 4)
+        and (bg and 15 = bg shr 4)
+        and (bb and 15 = bb shr 4)
+        and (ba and 15 = ba shr 4) then
+    begin
+      Result:='#'+hex[br and 15]+hex[bg and 15]+hex[bb and 15];
+      if c.Alpha<>alphaOpaque then
+        Result:=Result+hex[ba and 15];
+    end else begin
+      Result:='#'+hex[br shr 4]+hex[br and 15]
+                 +hex[bg shr 4]+hex[bg and 15]
+                 +hex[bb shr 4]+hex[bb and 15];
+      if c.Alpha<>alphaOpaque then
+        Result:=Result+hex[ba shr 4]+hex[ba and 15];
+    end;
+  end else begin
+    Result:='#'+HexStr(c.Red,4)+HexStr(c.Green,4)+HexStr(c.Blue,4);
+    if c.Alpha<>alphaOpaque then
+      Result:=Result+HexStr(c.Alpha,4);
+  end;
+end;
+
+function CSSToFPColor(const s: string; out c: TFPColor): boolean;
+
+  function ReadColor(var p: PChar; Count: byte): word;
+  var
+    i: Integer;
+    ch: Char;
+    v: word;
+  begin
+    Result:=0;
+    for i:=1 to Count do
+    begin
+      ch:=p^;
+      case ch of
+      '0'..'9': v:=ord(ch)-ord('0');
+      'a'..'f': v:=ord(ch)-ord('a')+10;
+      'A'..'F': v:=ord(ch)-ord('A')+10;
+      end;
+      Result:=Result shl 4+v;
+      inc(p);
+    end;
+  end;
+
+var
+  HexPerColor: byte;
+  p, StartP: PChar;
+  HasAlpha: Boolean;
+begin
+  Result := False;
+  c.Red := 0;
+  c.Green := 0;
+  c.Blue := 0;
+  c.Alpha := alphaOpaque;
+  if s='' then
+    exit;
+  p:=@s[1];
+  if p^='#' then
+  begin
+    inc(p);
+    StartP:=p;
+    repeat
+      case p^ of
+      #0:
+        if p-StartP+1=length(s) then
+          break
+        else
+          exit;
+      '0'..'9','a'..'f','A'..'F': inc(p);
+      else
+        exit;
+      end;
+    until false;
+    p:=StartP;
+    case length(s) of
+    4:
+      begin
+        HexPerColor:=1;
+        HasAlpha:=false;
+      end;
+    5:
+      begin
+        HexPerColor:=1;
+        HasAlpha:=true;
+      end;
+    7:
+      begin
+        HexPerColor:=2;
+        HasAlpha:=false;
+      end;
+    9:
+      begin
+        HexPerColor:=2;
+        HasAlpha:=true;
+      end;
+    13:
+      begin
+        HexPerColor:=4;
+        HasAlpha:=false;
+      end;
+    17:
+      begin
+        HexPerColor:=4;
+        HasAlpha:=true;
+      end;
+    else
+      exit;
+    end;
+    c.Red:=ReadColor(p,HexPerColor);
+    c.Green:=ReadColor(p,HexPerColor);
+    c.Blue:=ReadColor(p,HexPerColor);
+    if HasAlpha then
+      c.Alpha:=ReadColor(p,HexPerColor);
+  end else begin
+    case LowerCase(s) of
+      'aqua'   : c := colAqua;
+      'black'  : c := colBlack;
+      'blue'   : c := colBlue;
+      'fuchsia': c := colFuchsia;
+      'gray'   : c := colGray;
+      'green'  : c := colGreen;
+      'lime'   : c := colLime;
+      'maroon' : c := colMaroon;
+      'navy'   : c := colNavy;
+      'olive'  : c := colOlive;
+      'purple' : c := colPurple;
+      'red'    : c := colRed;
+      'silver' : c := colSilver;
+      'teal'   : c := colTeal;
+      'white'  : c := colWhite;
+      'yellow' : c := colYellow;
+    else
+      exit;
+    end;
+  end;
+  Result:=true;
+end;
+
 { TFresnelLayoutNode }
 
 procedure TFresnelLayoutNode.SetElement(const AValue: TFresnelElement);
@@ -931,6 +1091,7 @@ begin
   FCSSComputed[fcaHeight]:=FloatToCSSStr(Height);
   FCSSComputed[fcaFontFamily]:='arial';
   FCSSComputed[fcaFontSize]:='12';
+  FCSSComputed[fcaColor]:='#000';
 end;
 
 procedure TFresnelViewport.DomChanged;
@@ -1486,7 +1647,7 @@ function TFresnelElement.CheckCSSBorderColor(const AValue: string): boolean;
 var
   aColor: TFPColor;
 begin
-  Result:=TryHtmlToFPColor(AValue,aColor);
+  Result:=CSSToFPColor(AValue,aColor);
 end;
 
 function TFresnelElement.CheckCSSBoxSizing(const AValue: string): boolean;
@@ -1895,7 +2056,15 @@ begin
   // ToDo: hsl(), hsla()
   // ToDo: transparent
   // ToDo: currentcolor
-  Result:=TryHtmlToFPColor(AValue,aColor);
+  Result:=CSSToFPColor(AValue,aColor);
+end;
+
+function TFresnelElement.CheckCSSColor(const AValue: string): boolean;
+var
+  aColor: TFPColor;
+begin
+  // ToDo: rgb(r,g,b), rgba(r,g,b,a), ...
+  Result:=CSSToFPColor(AValue,aColor);
 end;
 
 function TFresnelElement.GetComputedCSSValue(AttrID: TCSSNumericalID
@@ -2926,6 +3095,7 @@ begin
     fcaPaddingBottom: Result:=CheckCSSLength(Attr,s,[flcNoNegative]);
     fcaVisibility: Result:=CheckCSSVisibility(s);
     fcaBackgroundColor: Result:=CheckCSSBackgroundColor(s);
+    fcaColor: Result:=CheckCSSColor(s);
     end;
   finally
     FCSSPosElement:=nil;
@@ -2953,6 +3123,7 @@ begin
   fcaPaddingTop,
   fcaPaddingRight,
   fcaPaddingBottom: Result:='0';
+  fcaColor: Result:='#000';
   else
     Result:='';
   end;

+ 12 - 5
src/fresnel.renderer.pas

@@ -51,8 +51,8 @@ end;
 procedure TFresnelRenderer.DrawElement(El: TFresnelElement);
 var
   LNode: TSimpleFresnelLayoutNode;
-  aBackgroundColor, aBorderColor, aCaption: String;
-  aBackgroundColorFP, aBorderColorFP: TFPColor;
+  aBackgroundColor, aBorderColor, aCaption, aColor: String;
+  aBackgroundColorFP, aBorderColorFP, aColorFP: TFPColor;
   aLeft, aTop, aRight, aBottom,
     aMarginLeft, aMarginTop, aMarginRight, aMarginBottom,
     aBorderLeft, aBorderRight, aBorderTop, aBorderBottom,
@@ -112,7 +112,7 @@ begin
     //debugln(['TFresnelRenderer.DrawElement ',El.Name,' Border=',dbgs(aBorderBox),' Content=',dbgs(aContentBox)]);
 
     aBackgroundColor:=El.CSSRenderedAttribute[fcaBackgroundColor];
-    if not TryHtmlToFPColor(aBackgroundColor,aBackgroundColorFP) then
+    if not CSSToFPColor(aBackgroundColor,aBackgroundColorFP) then
       aBackgroundColorFP:=colTransparent;
     if aBackgroundColorFP.Alpha<>alphaTransparent then
     begin
@@ -120,7 +120,7 @@ begin
     end;
 
     aBorderColor:=El.CSSRenderedAttribute[fcaBorderColor];
-    if not TryHtmlToFPColor(aBorderColor,aBorderColorFP) then
+    if not CSSToFPColor(aBorderColor,aBorderColorFP) then
       aBorderColorFP:=colTransparent;
     if aBorderColorFP.Alpha<>alphaTransparent then
     begin
@@ -144,7 +144,14 @@ begin
       aCaption:=TCustomLabel(El).RenderedCaption;
       if aCaption<>'' then
       begin
-        TextOut(aContentBox.Left,aContentBox.Top,El.Font,colBlack,aCaption);
+        aColor:=El.GetRenderedCSString(fcaColor,true);
+        if not CSSToFPColor(aColor,aColorFP) then
+          aColorFP:=colTransparent;
+        writeln('TFresnelRenderer.DrawElement aColor="',aColor,'" aColorFP=',FPColorToCSS(aColorFP));
+        if aColorFP.Alpha<>alphaTransparent then
+        begin
+          TextOut(aContentBox.Left,aContentBox.Top,El.Font,aColorFP,aCaption);
+        end;
       end;
     end;
   end;