使用cairo、librsvg和delphi绘制SVG,更改所有路径的颜色

3

我正在从SVG文件中绘制矢量图像到TImage。我希望在运行时将所有路径的颜色更改为不同的颜色,但是以下代码仅更改SVG的第一个路径的颜色。SVG中的所有路径都具有相同的颜色(黑色-#000000)。有人知道如何更改所有路径的颜色吗?

... 
img1: TImage; // TImage placed on the TForm1
...

procedure TForm1.DrawSVG(const aFileName: TFileName);
var
    wSVGObject:        IRSVGObject;
    wSurface:          IWin32Surface;
    wContext:          ICairoContext;
    wRect:             TRect;
begin
    wSVGObject := TRSVGObject.Create(aFileName);
    // img1 initialization
    wRect.Left := 0;
    wRect.Top := 0;
    wRect.width := img1.width;
    wRect.height := img1.height;
    img1.Canvas.Brush.Color := clWhite;
    img1.Canvas.FillRect(wRect);

    wSurface := TWin32Surface.CreateHDC(img1.Canvas.Handle);
    wContext := TCairoContext.Create(wSurface);
    wContext.Antialias := CAIRO_ANTIALIAS_DEFAULT;

    // try to change color of vector image, but only first path changes color
    wContext.SetSourceRGB(0.5, 0.5, 0.5);
    wContext.Rectangle(wRect.Left, wRect.Top, wRect.width, wRect.height);
    wSurface.Flush;
    wContext.FillPreserve;

    wContext.RenderSVG(wSVGObject);
end;

我的解决方案添加了18.8。 - vnc
请问您能否分享cairo和librsvg的最新版本下载地址,以便我们也可以测试这段代码? - zig
1
请点击此链接查看与 Delphi GNOME 矢量图形相关的程序内容:https://code.google.com/p/delphignomevectorgraphic/source/browse/trunk/?r=4,其中包含二进制文件和 Delphi 单元。如果您想使用代码,则必须定义以下两个指令:{$Define CAIRO_HAS_RSVG_FUNCTIONS} 和 {$Define CAIRO_HAS_WIN32_SURFACE}。 - vnc
1个回答

0

我通过将SVG文件(类似于XML)加载到TStringList中,替换fill:#000000和stroke:#000000为新颜色,保存到TMemoryStream,然后使用TMemoryStream作为参数创建TRSVGObject来解决了这个问题:

procedure TForm1.ChangeImageColor(const aMStream: TMemoryStream; const aFileName: TFileName; const aOldColor, aNewColor: TColor);
var
    wStringList:          TStringList;
    wNewColor, wOldColor: string;
const
    cHEX_NUMBERS = 6;
begin
    wOldColor := IntToHex(ColorToRGB(aOldColor), cHEX_NUMBERS);
    wNewColor := IntToHex(ColorToRGB(aNewColor), cHEX_NUMBERS);

    wStringList := TStringList.Create;
    try
        wStringList.LoadFromFile(aFileName);
        wStringList.Text := StringReplace(wStringList.Text, 'fill:#' + wOldColor, 'fill:#' + wNewColor,
        [rfReplaceAll, rfIgnoreCase]);
        wStringList.Text := StringReplace(wStringList.Text, 'stroke:#' + wOldColor, 'stroke:#' + wNewColor,
        [rfReplaceAll, rfIgnoreCase]);

        wStringList.SaveToStream(aMStream);
    finally
        FreeAndNil(wStringList);
    end;
end;

然后:

    wMemStream := TMemoryStream.Create;
    try
        if aOldColor <> aNewColor then
            ChangeImageColor(wMemStream, aFileName, aOldColor, aNewColor)
        else
            wMemStream.LoadFromFile(aFileName);

        wSVGObject := TRSVGObject.Create(wMemStream);
...
...
        // try to change color of vector image, but only first path changes color
        // wContext.SetSourceRGB(0.5, 0.5, 0.5);
        // wContext.Rectangle(wRect.Left, wRect.Top, wRect.width, wRect.height);
        // wSurface.Flush;
        // wContext.FillPreserve;

        wContext.RenderSVG(wSVGObject);
    finally
        FreeAndNil(wMemStream);
    end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接