diff --git a/components/fpvectorial/fpvectorial.pas b/components/fpvectorial/fpvectorial.pas index 8cfd594de8..12a33946d7 100644 --- a/components/fpvectorial/fpvectorial.pas +++ b/components/fpvectorial/fpvectorial.pas @@ -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 } diff --git a/components/fpvectorial/svgvectorialreader.pas b/components/fpvectorial/svgvectorialreader.pas index 1ef5caf6ae..a03da56988 100644 --- a/components/fpvectorial/svgvectorialreader.pas +++ b/components/fpvectorial/svgvectorialreader.pas @@ -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': + begin + lBrushEntity := TvEntityWithPenAndBrush.Create(nil); + + // + 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; + + // + // + 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':