styleun.pas

来自「查看html文件的控件」· PAS 代码 · 共 2,197 行 · 第 1/5 页

PAS
2,197
字号
        begin
        A[I].Cl := System.Copy(A[I].Tg, J+1, Length(A[I].Tg));
        A[I].Tg := System.Copy(A[I].Tg, 1, J-1);
        end
      else A[I].Cl := '';
      end;
    end;

  begin
  Result := False;
  Split(Styles[I]); //split contextual selectors into parts in array A
  if (A[1].Tg <> Tag) and (A[1].Cl <> AClass) and (A[1].PS <> PSeudo) then 
    Exit
  else Result := True;
  if (N > 1)   //it's a contextual selector.  N is count of selectors
        and ((A[1].Tg = Tag) or (A[1].Tg = ''))
        and ((A[1].Cl = AClass) or (A[1].Cl = ''))
        and ((A[1].ID = AnID) or (A[1].ID = ''))
        and ((A[1].PS = PSeudo) or (A[1].PS = '')) then
    begin //look thru the stack to see if this contextual selector is appropriate
    K := 2;   //K is selector index in the sequence
    J := PropStack.Count-2;  // start on stack item below this one
    while (K <= N) and (J >= 1) do
      begin
      with PropStack[J] do
        if ((A[K].Tg = PropTag) or (A[K].Tg = '')) and ((A[K].Cl = PropClass) or (A[K].Cl = ''))
              and ((A[K].ID = PropID) or (A[K].ID = ''))
              and ((A[K].PS = PropPseudo) or (A[K].PS = '')) then
          begin
          if K = N then  //all parts of contextual selector match
            Merge(Styles.Objects[I] as TProperties);
          Inc(K);
          end;
      Dec(J);
      end;
    end
  end;

  procedure MergeItems(Const Item: string);
  {look up items in the Style list.  If found, merge them in this TProperties.
   Items may be duplicated in which case the last has priority.  Items may be
   simple tags like 'p', 'blockquote', 'em', etc or they may be more complex
   like  p.class, em#id, a.class:link, etc}
  var
    X: integer;
  begin
  if Styles.Find(Item, X) then
    begin
    Merge(Styles.Objects[X] as TProperties);
    Inc(X);
    while (X < Styles.Count) and (Styles[X] = Item) do
      begin  //duplicates, last one has highest priority
      Merge(Styles.Objects[X] as TProperties);
      Inc(X);
      end;
    end;
  end;

begin
{$ifdef Quirk}
if (Tag = 'td') or (Tag = 'th') then   
  OldSize := DefPointSize else
{$endif}
if (VarType(Props[FontSize]) = VarDouble) and (Props[FontSize] > 0.0) then    {should be true}
  OldSize := Props[FontSize]
else OldSize := DefPointSize;

{Some hover and visited items adequately taken care of when link processed}
NoHoverVisited := (Pseudo = '') or ((Pseudo <> 'hover') and (Pseudo <> 'visited'));

// in the following, lowest priority on top, highest towards bottom.

if (Tag = 'a') and (Pseudo <> '') then
  MergeItems('::'+Pseudo); {default Pseudo definition}

if NoHoverVisited then
  MergeItems(Tag);

if Pseudo <> '' then
  MergeItems(':'+Pseudo);

if (AClass <> '') and NoHoverVisited then
  MergeItems('.'+AClass);

if (AClass <> '') and NoHoverVisited then
  MergeItems(Tag+'.'+AClass);

if Pseudo <> '' then
  MergeItems(Tag+':'+Pseudo);

if (AClass <> '') and (PSeudo <> '') then
    MergeItems('.'+AClass+':'+Pseudo);

if (AClass <> '') and (Pseudo <> '') then
  MergeItems(Tag+'.'+AClass+':'+Pseudo);

if AnID <> '' then
  begin
  MergeItems('#'+AnID);
  MergeItems(Tag+'#'+AnID);
  if (AClass <> '') then
    MergeItems('.'+AClass+'#'+AnID);
  if (Pseudo <> '') then
    begin
    MergeItems('#'+AnID+':'+Pseudo);
    MergeItems(Tag+'#'+AnID+':'+Pseudo);
    end;
  if (AClass <> '') then
    MergeItems(Tag+'.'+AClass+'#'+AnID);
  MergeItems('.'+AClass+'#'+AnID+':'+Pseudo);
  MergeItems(Tag+'.'+AClass+'#'+AnID+':'+Pseudo);
  end;

{process the entries in Styles to see if they are contextual selectors}
Styles.Find(Tag, IX);    //place to start
while (IX < Styles.Count) and (Pos(Tag, Styles[IX]) = 1) and CheckForContextual(IX) do
  Inc(IX);

Styles.Find('.'+AClass, IX);    //place to start
while (IX < Styles.Count) and (Pos('.'+AClass, Styles[IX]) = 1) and CheckForContextual(IX) do
  Inc(IX);

Styles.Find(':'+PSeudo, IX);    //place to start           
while (IX < Styles.Count) and (Pos(':'+PSeudo, Styles[IX]) = 1) and CheckForContextual(IX) do
  Inc(IX);

If Assigned(AProp) then   //the Style= attribute
  Merge(AProp);

if not ((VarType(Props[FontSize]) = VarDouble) or
      (VarType(Props[FontSize]) in varInt)) then  {if still a string, hasn't been converted}
  Props[FontSize] := FontSizeConv(Props[FontSize], OldSize);
end;

function TProperties.GetFont: TMyFont;
var
  Font: ThtFontInfo;
  Save: THandle;
  SaveCharSet: TFontCharSet;
  tm : TTextmetric;
  DC: HDC;
  V: Variant;
begin      {call only if all things valid}
if not Assigned(TheFont) then
  begin
  Font := ThtFontInfo.Create;
  try
    GetSingleFontInfo(Font);
    TheFont := TMyFont.Create;
    with TheFont, Font do
      begin
      Name := iName;
      Height := -Round(iSize * Screen.PixelsPerInch / 72);   
      Style := iStyle;
      bgColor := ibgColor;
      Color := iColor;
      Charset := iCharSet;
      V := iCharExtra;
      end;
  finally
    Font.Free;
    end;
  {if this is a Symbol charset, then keep it that way.  To check the font's real
   charset, use Default_Charset} 
  SaveCharSet := TheFont.CharSet;
  TheFont.CharSet := Default_Charset;
  DC := GetDC(0);
  try
    Save := SelectObject(DC, TheFont.Handle);
    try
      GetTextMetrics(DC, tm);
    finally
      SelectObject(DC, Save);
      end;
    if tm.tmCharset = Symbol_Charset then
      TheFont.Charset := Symbol_CharSet
    else
      TheFont.Charset := SaveCharSet;
    {now get the info on the finalized font}
    if TheFont.Charset <> Default_Charset then  {else already have the textmetrics}
      begin
      Save := SelectObject(DC, TheFont.Handle);
      try
        GetTextMetrics(DC, tm);
      finally
        SelectObject(DC, Save);
        end;
      end;
  finally
    ReleaseDC(0, DC);
    end;
  {calculate EmSize with current font rather than inherited}
  EmSize := tm.tmHeight-tm.tmInternalLeading;
  ExSize := EmSize div 2; {apparently correlates with what browsers are doing}
  TheFont.tmHeight := tm.tmHeight;  
  TheFont.tmDescent := tm.tmDescent;
  TheFont.tmExternalLeading := tm.tmExternalLeading;
  TheFont.tmMaxCharWidth := tm.tmMaxCharWidth;
  TheFont.tmAveCharWidth := tm.tmAveCharWidth;
  TheFont.tmCharset := tm.tmCharset;
  if VarType(V) in VarInt then
    TheFont.CharExtra := V
  else if VarType(V) = VarString then
    if V = 'normal' then
      TheFont.CharExtra := 0
    else TheFont.CharExtra := LengthConv(V, False, EmSize, EmSize, ExSize, 0)
  else TheFont.CharExtra := 0;
  end;
Result := TMyFont.Create;
Result.Assign(TheFont);
end; 

{----------------ReadFontName}
function ReadFontName(S: string): string;
var
  S1: string;
  Done: boolean;

  function NextFontName: string;
  const
    Generic1: array[1..4] of string = ('serif', 'monospace', 'sans-serif', 'cursive');
    Generic2: array[1..4] of string = ('Times New Roman', 'Courier New', 'Arial', 'Lucida Handwriting');
  var
    I: integer;
  begin
  I := Pos(',', S);        {read up to the comma}
  if I > 0 then
    begin
    Result := Trim(System.Copy(S, 1, I-1));
    Delete(S, 1, I);
    end
  else
    begin   {last item}
    Result := Trim(S);
    S := '';
    end;
  for I := 1 to 4 do
    if CompareText(Result, Generic1[I]) = 0 then
      begin
      Result :=  Generic2[I];
      break;
      end;
  if (Result <> '') and (Result[Length(Result)] in ['"', '''']) then
    SetLength(Result, Length(Result)-1);
  if (Result <> '') and (Result[1] in ['"', '''']) then
    Delete(Result, 1, 1);
  end;

begin
Done := False;
S1 := NextFontName;
while (S1 <> '') and not Done do
  begin
  Done := Screen.Fonts.IndexOf(S1) >= 0;
  if Done then
    Result := S1
  else S1 := NextFontName;
  end;
end;

{----------------TProperties.GetSingleFontInfo}
procedure TProperties.GetSingleFontInfo(var Font: ThtFontInfo);  
var
  S, S1: string;
  Done: boolean;
  Wt: integer;
  Style: TFontStyles;

  function NextFontName: string;
  const
    Generic1: array[1..4] of string = ('serif', 'monospace', 'sans-serif', 'cursive');
    Generic2: array[1..4] of string = ('Times New Roman', 'Courier New', 'Arial', 'Lucida Handwriting');
  var
    I: integer;
  begin
  I := Pos(',', S);        {read up to the comma}
  if I > 0 then
    begin
    Result := Trim(System.Copy(S, 1, I-1));
    Delete(S, 1, I);
    end
  else
    begin   {last item}
    Result := Trim(S);
    S := '';
    end;
  for I := 1 to 4 do
    if CompareText(Result, Generic1[I]) = 0 then
      begin
      Result :=  Generic2[I];
      break;
      end;
  if (Result <> '') and (Result[Length(Result)] in ['"', '''']) then
    SetLength(Result, Length(Result)-1);
  if (Result <> '') and (Result[1] in ['"', '''']) then
    Delete(Result, 1, 1);
  end;

begin      {call only if all things valid}
Font.ibgColor := FontBG;
Font.iColor := Props[Color];
Style := [];
if Pos('bold', Props[FontWeight]) > 0 then
  Style := [fsBold]
else
  begin
  Wt := StrToIntDef(Props[FontWeight], 0);
  if Wt >= 600 then
    Style := [fsBold];
  end;
if (Props[FontStyle] = 'italic') or (Props[FontStyle] = 'oblique') then
  Style := Style + [fsItalic];
if Props[TextDecoration] = 'underline' then
  Style := Style + [fsUnderline]
else if Props[TextDecoration] = 'line-through' then
  Style := Style + [fsStrikeOut];
Font.iStyle := Style;
Font.iSize := Props[FontSize];
Font.iCharset := CharSet;
Font.iCharExtra := Props[LetterSpacing];  

Done := False;
S := Props[FontFamily];
S1 := NextFontName;
while (S1 <> '') and not Done do
  begin
  Done := Screen.Fonts.IndexOf(S1) >= 0;
  if Done then
    begin
    Font.iName := S1;
    end
  else S1 := NextFontName;
  end;
if Font.iName = '' then        
  Font.iName := DefFontname;  
end;

procedure TProperties.CalcLinkFontInfo(Styles: TStyleList; I: integer);
{I is index in PropStack for this item}    
  procedure InsertNewProp(N: integer; const Pseudo: string);
  begin
  PropStack.Insert(N, TProperties.Create);
  PropStack[N].Inherit('', PropStack[N-1]);   
  PropStack[N].Combine(Styles, PropTag, PropClass, PropID, Pseudo, PropTitle, PropStyle);
  end;

begin
PropStack[I].SetFontBG;    
GetSingleFontInfo(FIArray.Ar[LFont]);
InsertNewProp(I+1, 'visited');
PropStack[I+1].SetFontBG;
PropStack[I+1].GetSingleFontInfo(FIArray.Ar[VFont]);
InsertNewProp(I+2, 'hover');
PropStack[I+2].SetFontBG;
PropStack[I+2].GetSingleFontInfo(FIArray.Ar[HVFont]);
PropStack.Delete(I+2);
PropStack.Delete(I+1);
InsertNewProp(I+1, 'hover');
PropStack[I+1].SetFontBG;
PropStack[I+1].GetSingleFontInfo(FIArray.Ar[HLFont]);
PropStack.Delete(I+1);
end;

procedure TProperties.GetFontInfo(AFI: TFontInfoArray);
begin
AFI.Assign(FIArray);
end;

procedure TProperties.GetVMarginArray(var MArray: TVMarginArray);
var
  I: PropIndices;
begin
for I := Low(Marray) to High(MArray) do
  case I of
    BorderTopStyle..BorderLeftStyle:
      if VarType(Props[I]) = VarString then
        MArray[I] := BorderStyleFromString(Props[I])
      else MArray[I] := bssNone;
    else
      MArray[I] := Props[I];
    end;
end;

procedure TProperties.AddPropertyByIndex(Index: PropIndices; PropValue: string);
var
  NewColor: TColor;
begin
case Index of
  BorderColor:
    if ColorFromString(PropValue, False, NewColor) then
      begin
      Props[BorderColor] := NewColor;
      Props[BorderLeftColor] := NewColor;
      Props[BorderTopColor] := NewColor;
      Props[BorderRightColor] := NewColor;
      Props[BorderBottomColor] := NewColor;
      end;
  BorderTopColor .. BorderLeftColor:
    if ColorFromString(PropValue, False, NewColor) then
      Props[Index] := NewColor;
  Color, BackgroundColor:
    if ColorFromString(PropValue, False, NewColor) then
      Props[Index] := NewColor
    else if Index = Color then
      Props[Index] := clBlack
    else Props[Index] := clNone;
  MarginTop..BorderLeftWidth, Width..LeftPos:
    Props[Index] := PropValue;
  FontSize:
    Props[FontSize] := PropValue;
  Visibility:
    begin
    if PropValue = 'visible' then
      Props[Visibility] := viVisible
    else if PropValue = 'hidden' then
      Props[Visibility] := viHidden;
    end;
  TextTransform:
    begin
    if PropValue = 'uppercase' then
      Props[TextTransform] := txUpper
    else if PropValue = 'lowercase' then
      Props[TextTransform] := txLower
    else Props[TextTransform] := txNone;
    end;
  WordWrap:                           
    if PropValue = 'break-word' then
      Props[WordWrap] := PropValue
    else Props[WordWrap] := 'normal';
  FontVariant:
    if PropValue = 'small-caps' then
      Props[FontVariant] := PropValue
    else if PropValue = 'normal' then
      Props[FontVariant] := 'normal';
  BorderTopStyle..BorderLeftStyle:
    begin
    if PropValue <> 'none' then      
      Props[BorderStyle] := PropValue;
    Props[Index] := PropValue;
    end;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?