【Inkscape 扩展开发】SVG导入 - 链接SVG(linked SVG)转包含SVG(included SVG)

背景

在 Stack Overflow 上问了个问题然后尝试自己解决,发现除了在链接SVG上右键选择“嵌入图像”选项之外,并没有其他的解法。“嵌入图像”其实也不能解决问题,只是将原图转为 base64 格式,并不能实现子图内容可编辑。所幸 Inkscape 支持使用 Python 作为脚本开发扩展,最后还是转向了用自定义扩展解决问题。同时也发现国内关于 Inkscape 扩展开发的内容实在是凤毛麟角,故写下一点使用心得,希望能够抛砖引玉。入门相对来说还是容易的,即使教程不多,通过阅读源码,也能够了解到一些用法,在两天之内便能够写出一个简单的实现上述功能的扩展。

代码

伸手党可以直接访问我的仓库
Inkscape 扩展开发教程资源示例:

原型

扩展原型来自 Inkscape 官方 Gitlab 仓库的《My First Effect Extension》教程项目压缩包直接下载链接。跟着教程就能初步定制自己的扩展界面了。

debug

一旦按照上述教程将项目文件夹放到 Inkscape 指定的扩展目录并重启 Inkscape 使之识别以后,每当我们修改了代码,可以不必重启 Inkscape,只需要重新运行自己的扩展,代码的改变就能立马显现出来。
想查看自己扩展的运行信息,可以使用self.msg这个函数将自己想 debug 的信息输出来,方便查错。

XPath

在SVG文件中查找特定节点可以用self.document.xpath函数,第一个参数是 XPath 表达式字符串,第二个参数是inkex.NSS,这个参数在下文会介绍。

xlink:href

链接SVG使用xlink:href链接源图片,虽然对于一个节点,获取其属性可以使用类似node.attrib['id']这样的方法,但是xlink:href中冒号前面的xlink属于“命名空间”,使用node.attrib['xlink:href']是获取不到值的。其实xlink:href全写是{http://www.w3.org/1999/xlink}href,使用该键才能获取到其值。

inkex.NSS

inkexinkscape+extension的缩写,是一个 Python 的 Inkscape 扩展包。字典inkex.NSS存储了SVG的命名空间,即SVG代码中下面这部分的字典化:

<svg
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">

为了防止xlink这个命名空间以后发生变化,可以不硬编码{http://www.w3.org/1999/xlink}href,而是用'{{{0}}}href'.format(inkex.NSS['xlink'])这样的方法来获取xlink:href的全写。

tag

修改标签名可以通过类似element.tag = 'xxx'这样的写法来修改,这里将标签名修改成了xxx。不过要注意的是,这里同样需要带上svg的命名空间,即element.tag = '{{{0}}}g'.format(inkex.NSS['svg']),这里将标签名修改成了群组,即svg:g

通过插件导入 SVG

这里可以看到inkex.elements下有个load_svg函数,可以将 SVG 地址链接(可通过node.attrib['{{{0}}}href'.format(inkex.NSS['xlink'])]获取)通过lxml包转为 XML 节点对象,方便我们查询与引用、插入。在父元素下插入新的节点使用的是father.append(child)这样的方式。

Image 对象转 Group 对象的注意事项

需要注意的是,将 image 标签转为 g 标签以后,xywidthheight这些属性对 g 标签是无法生效的,需要转换为transform属性,即设置该属性值为translate(x,y) scale(width/oWidth, height/oHeight)xywidthheight从原 image 标签获取,oWidthoHeight从 image 标签所引用的 SVG 图像的svg:svg节点中获取。注意一开始获取到的值是字符串类型,需要转换为 float 类型才能进行运算;还要注意度量单位,这里我偷懒,默认我获取到的值的单位都是px,不排除有些是mmcm,自己注意写代码检测与转换。如此设置以后,便能得到与 image 标签一样的图像大小、位置效果,实现从 linked SVG 到 included SVG 的无缝转换。

便捷模块

Inkscape 除了 inkex 模块以外,还有一些便捷模块方便你的开发,如simpletransform,可以将上述的 transform 由文本设置改为用函数设置(详情)。但由于官方 Wiki 的这则公告,我不打算使用这些便捷模块。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章