用Direct2D绘制SVG (1)

矢量图形绘制, 首先想到使用SVG作为图像格式,起步需要的就是SVG文件格式。

GitHub找了一圈,nanosvg是一个很好的C库。
nanosvg是一个很符合KISS的库,分为parser 和 Rasterizer,
Parser部分,都在 #include "nanosvg.h" 头文件中,记得要#define NANOSVG_IMPLEMENTATION
Rasterizer部分,都在 #include "nanosvgrast.h" 头文件中,同样要定义 #define NANOSVGRAST_IMPLEMENTATION

如果需求是 SVG to PNG,这2者用上,加个PNG的write库(这里面是stb_image_write.h)即可。
然而,如果每次绘制都需要把矢量搞成点阵图,非常消耗资源。

另外: nanosvg只支持SVG v1.1,各种Filter就别想了。因此最大的用处在于参考价值。
对照着http://www.w3school.com.cn/svg/
Parser部分, SVG既然是矢量绘制,按图形学的常识,基本图形就是line和 cubic bezier。
再预定义的形状元素,可被开发者使用和操作:
矩形 <rect>
圆形 <circle>
椭圆 <ellipse>
线 <line>
折线 <polyline>
多边形 <polygon>
路径 <path>

Path特别强大,直接以命令方式几乎可以组成任何图形。
M = moveto
L = lineto
H = horizontal lineto
V = vertical lineto
C = curveto
S = smooth curveto
Q = quadratic Belzier curve
T = smooth quadratic Belzier curveto
A = elliptical Arc
Z = closepath
看Parser代码,nanosvg非常简单粗暴,所有图形一律规整为cubic bezier。

Trace出Path代码,尝试使用D2d绘制这些CubicBezier。
按MSDN说明,先从ID2D1Factory, CreatePathGeometry出一个ID2D1PathGeometry
再通过这个ID2D1PathGeometry, Open一个ID2D1GeometrySink
注意这个ID2D1GeometrySink,包含实际功能,可以直接使用。
而对应的ID2D1SimplifiedGeometrySink,则不包含实际功能,必须继承实现接口作为sink回调。

  CComPtr<ID2D1PathGeometry> path;
  _factory->CreatePathGeometry(&path);

  {
    CComPtr<ID2D1GeometrySink> sink;
    path->Open(&sink);

    float af[] = {4.00,52,
      4.00,38, 4.00,31, 6.36,26, 9.29,19, 14.72,13, 21.54,10, 27.03, 8, 
      34.02, 8, 48.00, 8, 61.98, 8, 68.97, 8, 74.46,10, 81.28,13, 86.71,19, 89.64,26, 92.00,31, 
      92.00,38, 92.00,52, 92.00,66, 92.00,73, 89.64,78, 86.71,85, 81.28,91, 74.46,94, 68.97,96, 
      61.98,96, 48.00,96, 34.02,96, 27.03,96, 21.54,94, 14.72,91, 9.29,85, 6.36,78, 4.00,73, 
      4.00,66, 4.00,52, 4.00,52, 4.00,52, 4.00,52};

    sink->BeginFigure(
      D2D1::Point2F(af[0],af[1]),
      D2D1_FIGURE_BEGIN_FILLED
      );

    for( int i = 0; i < 12; i++ ) {
      sink->AddBezier( BezierSegment( Point2F(af[i*6+2],af[i*6+3]),
                                      Point2F(af[i*6+4],af[i*6+5]), 
                                      Point2F(af[i*6+6],af[i*6+7])));
    }

    sink->EndFigure(D2D1_FIGURE_END_OPEN);
    sink->Close();

须注意, BezierSegment是一个 (controlpoint1, controlpoint2, endpoint) 的序列。
其中上一个endpoint(或者moveTo Point) 作为startpoint,也算是cubic bezier在各种图形库的一个使用常态。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 可以使用 Batik 库来绘制 SVG。Batik 是一个开源的 Java 库,用于处理 SVG 文件。它提供了一组 API,可以将 SVG 文件转换为 Java2D 命令,以便在 Java 应用程序中显示和操作 SVG 图像。 以下是一个简单的例子,演示如何使用 Batik 库在 Java 中绘制 SVG: ```java import org.apache.batik.dom.svg.SVGDOMImplementation; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.Writer; public class SVGDemo { public static void main(String[] args) throws Exception { // 创建 SVG 文档 DOMImplementation domImpl = SVGDOMImplementation.getDOMImplementation(); Document document = domImpl.createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null); Element svgRoot = document.getDocumentElement(); // 绘制一个矩形 Element rectangle = document.createElementNS(SVGDOMImplementation.SVG_NAMESPACE_URI, "rect"); rectangle.setAttributeNS(null, "x", "10"); rectangle.setAttributeNS(null, "y", "10"); rectangle.setAttributeNS(null, "width", "100"); rectangle.setAttributeNS(null, "height", "50"); rectangle.setAttributeNS(null, "fill", "red"); svgRoot.appendChild(rectangle); // 保存 SVG 文件 FileOutputStream fos = new FileOutputStream("output.svg"); Writer out = new OutputStreamWriter(fos, "UTF-8"); document.write(out); out.flush(); out.close(); } } ``` 这个例子创建了一个 SVG 文档,并在其中绘制了一个红色矩形。最后将 SVG 文件保存到 output.svg 文件中。 注意,这个例子只是一个简单的演示,实际上可以使用 Batik 库绘制复杂的 SVG 图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值