mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 08:19:53 +01:00 
			
		
		
		
	fpvectorial-svg: Structural work for linear gradient support
git-svn-id: trunk@47214 -
This commit is contained in:
		
							parent
							
								
									acfee8fe08
								
							
						
					
					
						commit
						5969afd322
					
				@ -118,7 +118,7 @@ type
 | 
			
		||||
    Width: Integer;
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  TvBrushKind = (bkSimpleBrush, bkRadialGradient);
 | 
			
		||||
  TvBrushKind = (bkSimpleBrush, bkHorizontalGradient, bkVerticalGradient, vkOtherLinearGradient, bkRadialGradient);
 | 
			
		||||
  TvCoordinateUnit = (vcuDocumentUnit, vcuPercentage);
 | 
			
		||||
 | 
			
		||||
  TvBrush = record
 | 
			
		||||
@ -150,7 +150,7 @@ type
 | 
			
		||||
  TvSetStyleElement = (
 | 
			
		||||
    // Pen, Brush and Font
 | 
			
		||||
    spbfPenColor, spbfPenStyle, spbfPenWidth,
 | 
			
		||||
    spbfBrushColor, spbfBrushStyle, spbfBrushGradient,
 | 
			
		||||
    spbfBrushColor, spbfBrushStyle, spbfBrushGradient, spbfBrushKind,
 | 
			
		||||
    spbfFontColor, spbfFontSize, spbfFontName, spbfFontBold, spbfFontItalic,
 | 
			
		||||
    spbfFontUnderline, spbfFontStrikeThrough, spbfAlignment,
 | 
			
		||||
    // TextAnchor
 | 
			
		||||
@ -1809,6 +1809,8 @@ begin
 | 
			
		||||
    Brush.Style := AFrom.Brush.Style;
 | 
			
		||||
  {if spbfBrushGradient in AFrom.SetElements then
 | 
			
		||||
    Brush.Gra := AFrom.Brush.Style;}
 | 
			
		||||
  if spbfBrushKind in AFrom.SetElements then
 | 
			
		||||
    Brush.Kind := AFrom.Brush.Kind;
 | 
			
		||||
 | 
			
		||||
  // Font
 | 
			
		||||
 | 
			
		||||
@ -1871,6 +1873,8 @@ begin
 | 
			
		||||
    ADest.Brush.Style := Brush.Style;
 | 
			
		||||
  {if spbfBrushGradient in SetElements then
 | 
			
		||||
    Brush.Gra := AFrom.Brush.Style;}
 | 
			
		||||
  if spbfBrushKind in SetElements then
 | 
			
		||||
    ADest.Brush.Kind := Brush.Kind;
 | 
			
		||||
 | 
			
		||||
  // Font
 | 
			
		||||
 | 
			
		||||
@ -3723,6 +3727,14 @@ begin
 | 
			
		||||
  begin
 | 
			
		||||
    ADest.Ellipse(x1, y1, x2, y2);
 | 
			
		||||
  end;
 | 
			
		||||
  // Apply brush gradient
 | 
			
		||||
  if Brush.Kind in [bkHorizontalGradient, bkVerticalGradient] then
 | 
			
		||||
  begin
 | 
			
		||||
    {PrepareBrushBitmap(x2, y2);
 | 
			
		||||
    BrushBitmap.Canvas.Ellipse(0, 0, x2-x1, y2-y1);
 | 
			
		||||
    AlphaBlendBrushBitmap(ADest, x1, y1);
 | 
			
		||||
    FreeAndNil(BrushBitmap);}
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
{ TvRectangle }
 | 
			
		||||
 | 
			
		||||
@ -935,10 +935,34 @@ function TvSVGVectorialReader.ReadSVGBrushStyleWithKeyAndValue(AKey,
 | 
			
		||||
  AValue: string; ADestEntity: TvEntityWithPenAndBrush): TvSetPenBrushAndFontElements;
 | 
			
		||||
var
 | 
			
		||||
  OldAlpha: Word;
 | 
			
		||||
  Len: Integer;
 | 
			
		||||
  lDefName: String;
 | 
			
		||||
  i: Integer;
 | 
			
		||||
  lCurBrush: TvEntityWithPenAndBrush;
 | 
			
		||||
begin
 | 
			
		||||
  Result := [];
 | 
			
		||||
  if AKey = 'fill' then
 | 
			
		||||
  begin
 | 
			
		||||
    // Suppose for fill="url(#grad2)"
 | 
			
		||||
    lDefName := Trim(AValue);
 | 
			
		||||
    if Copy(lDefName, 0, 3) = 'url' then
 | 
			
		||||
    begin
 | 
			
		||||
      lDefName := StringReplace(AValue, 'url(#', '', []);
 | 
			
		||||
      lDefName := StringReplace(lDefName, ')', '', []);
 | 
			
		||||
      if lDefName = '' then Exit;
 | 
			
		||||
 | 
			
		||||
      for i := 0 to FBrushDefs.Count-1 do
 | 
			
		||||
      begin
 | 
			
		||||
        lCurBrush := TvEntityWithPenAndBrush(FBrushDefs.Items[i]);
 | 
			
		||||
        if lCurBrush.Name = lDefName then
 | 
			
		||||
        begin
 | 
			
		||||
          ADestEntity.Brush := lCurBrush.Brush;
 | 
			
		||||
          Exit;
 | 
			
		||||
        end;
 | 
			
		||||
      end;
 | 
			
		||||
      Exit;
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
    // We store and restore the old alpha to support the "-opacity" element
 | 
			
		||||
    OldAlpha := ADestEntity.Brush.Color.Alpha;
 | 
			
		||||
    if ADestEntity.Brush.Style = bsClear then ADestEntity.Brush.Style := bsSolid;
 | 
			
		||||
@ -953,7 +977,14 @@ begin
 | 
			
		||||
    Result := Result + [spbfBrushColor, spbfBrushStyle];
 | 
			
		||||
  end
 | 
			
		||||
  else if AKey = 'fill-opacity' then
 | 
			
		||||
    ADestEntity.Brush.Color.Alpha := StringFloatZeroToOneToWord(AValue);
 | 
			
		||||
    ADestEntity.Brush.Color.Alpha := StringFloatZeroToOneToWord(AValue)
 | 
			
		||||
  // For linear gradient => stop-color:rgb(255,255,0);stop-opacity:1
 | 
			
		||||
  else if AKey = 'stop-color' then
 | 
			
		||||
  begin
 | 
			
		||||
    Len := Length(ADestEntity.Brush.Gradient_colors);
 | 
			
		||||
    SetLength(ADestEntity.Brush.Gradient_colors, Len+1);
 | 
			
		||||
    ADestEntity.Brush.Gradient_colors[Len] := ReadSVGColor(AValue);
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function TvSVGVectorialReader.ReadSVGFontStyleWithKeyAndValue(AKey,
 | 
			
		||||
@ -1232,13 +1263,15 @@ var
 | 
			
		||||
  lCurNode, lCurSubNode: TDOMNode;
 | 
			
		||||
  lBrushEntity: TvEntityWithPenAndBrush;
 | 
			
		||||
  lCurEntity: TvEntity;
 | 
			
		||||
  lOffset: Double;
 | 
			
		||||
  x1, x2, y1, y2: string;
 | 
			
		||||
begin
 | 
			
		||||
  lCurNode := ANode.FirstChild;
 | 
			
		||||
  while Assigned(lCurNode) do
 | 
			
		||||
  begin
 | 
			
		||||
    lEntityName := LowerCase(lCurNode.NodeName);
 | 
			
		||||
    case lEntityName of
 | 
			
		||||
      'RadialGradient':
 | 
			
		||||
      'radialgradient':
 | 
			
		||||
      begin
 | 
			
		||||
        lBrushEntity := TvEntityWithPenAndBrush.Create(nil);
 | 
			
		||||
        lBrushEntity.Brush.Kind := bkRadialGradient;
 | 
			
		||||
@ -1292,6 +1325,59 @@ begin
 | 
			
		||||
 | 
			
		||||
        FBrushDefs.Add(lBrushEntity);
 | 
			
		||||
      end;
 | 
			
		||||
      {
 | 
			
		||||
      <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
 | 
			
		||||
        <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
 | 
			
		||||
        <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
 | 
			
		||||
      </linearGradient>
 | 
			
		||||
      }
 | 
			
		||||
      'lineargradient':
 | 
			
		||||
      begin
 | 
			
		||||
        lBrushEntity := TvEntityWithPenAndBrush.Create(nil);
 | 
			
		||||
 | 
			
		||||
        // <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
 | 
			
		||||
        for i := 0 to lCurNode.Attributes.Length - 1 do
 | 
			
		||||
        begin
 | 
			
		||||
          lAttrName := lCurNode.Attributes.Item[i].NodeName;
 | 
			
		||||
          lAttrValue := lCurNode.Attributes.Item[i].NodeValue;
 | 
			
		||||
          if lAttrName = 'id' then
 | 
			
		||||
            lBrushEntity.Name := lAttrValue
 | 
			
		||||
          else if lAttrName = 'x1' then
 | 
			
		||||
            x1 := lAttrValue
 | 
			
		||||
          else if lAttrName = 'x2' then
 | 
			
		||||
            x2 := lAttrValue
 | 
			
		||||
          else if lAttrName = 'y1' then
 | 
			
		||||
            y1 := lAttrValue
 | 
			
		||||
          else if lAttrName = 'y2' then
 | 
			
		||||
            y2 := lAttrValue;
 | 
			
		||||
        end;
 | 
			
		||||
        if x2 = '0%' then lBrushEntity.Brush.Kind := bkVerticalGradient
 | 
			
		||||
        else lBrushEntity.Brush.Kind := bkHorizontalGradient;
 | 
			
		||||
 | 
			
		||||
        // <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
 | 
			
		||||
        // <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
 | 
			
		||||
        lCurSubNode := lCurNode.FirstChild;
 | 
			
		||||
        while Assigned(lCurSubNode) do
 | 
			
		||||
        begin
 | 
			
		||||
          lNodeName := LowerCase(lCurSubNode.NodeName);
 | 
			
		||||
 | 
			
		||||
          for i := 0 to lCurSubNode.Attributes.Length - 1 do
 | 
			
		||||
          begin
 | 
			
		||||
            lAttrName := lCurSubNode.Attributes.Item[i].NodeName;
 | 
			
		||||
            lAttrValue := lCurSubNode.Attributes.Item[i].NodeValue;
 | 
			
		||||
            if lAttrName = 'offset' then
 | 
			
		||||
            begin
 | 
			
		||||
              lOffset := StringWithUnitToFloat(lAttrValue);
 | 
			
		||||
            end
 | 
			
		||||
            else if lAttrName = 'style' then
 | 
			
		||||
              ReadSVGStyle(lAttrValue, lBrushEntity);
 | 
			
		||||
          end;
 | 
			
		||||
 | 
			
		||||
          lCurSubNode := lCurSubNode.NextSibling;
 | 
			
		||||
        end;
 | 
			
		||||
 | 
			
		||||
        FBrushDefs.Add(lBrushEntity);
 | 
			
		||||
      end;
 | 
			
		||||
      // Sometime entities are also put in the defs
 | 
			
		||||
      'circle', 'ellipse', 'g', 'line', 'path',
 | 
			
		||||
      'polygon', 'polyline', 'rect', 'text', 'use', 'symbol':
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user