malcolmyu / iconfont-builder

a tool to build fonts via svg
17 stars 4 forks source link

SVGO file and unicode codepoints. #1

Open Ashung opened 7 years ago

Ashung commented 7 years ago

我使用 iconfont-builder 处理 SVGO 压缩过的 SVG 文件,最终 TTF 文件中有些图标会出问题 (使用未压缩的 SVG 不会出问题)。

我另外一种方式直接使用 svgicons2svgfont 和 svg2ttf 的,使用 SVGO 压缩过的 SVG 文件生成的 TTF,并没有问题。

代码如下:

var fs = require("fs");
var path = require("path");
var yaml = require("js-yaml");
var svgicons2svgfont = require('svgicons2svgfont');
var svg2ttf = require('svg2ttf');

var svgFolder = "./assets/svg";
var fontFolder = "./assets/font";
var codepoints = yaml.safeLoad(fs.readFileSync("codepoints.yaml"));

var fontStream = svgicons2svgfont({
    fontName: 'hello',
    fontHeight: 960,
    normalize: true
});

// Setting the font destination
fontStream.pipe(fs.createWriteStream('./assets/font/hello.svg'))
    .on('finish',function() {
        var ttf = svg2ttf(fs.readFileSync('./assets/font/hello.svg').toString());
        fs.writeFileSync('./assets/font/myfont.ttf', new Buffer(ttf.buffer));
        console.log('Font successfully created!');
    })
    .on('error',function(err) {
        console.log(err);
    });

fs.readdirSync(svgFolder).forEach(function (file) {
    var svgFile = path.join(svgFolder, file);
    if (fs.statSync(svgFile).isFile() && path.extname(svgFile) == ".svg") {
        var glyphName = path.basename(file, ".svg");
        var glyphCode = codepoints[glyphName];
        if (glyphCode) {
            var unicode = "0x" + glyphCode;
            var glyph = fs.createReadStream(svgFile);
            glyph.metadata = {
                unicode: [String.fromCodePoint(unicode)],
                name: glyphName
            };
            fontStream.write(glyph);
        }
    }
});

fontStream.end();

使用 iconfont-builder 的代码

var fs = require("fs");
var path = require("path");
var yaml = require("js-yaml");
var builder = require('iconfont-builder');
var codepoints = yaml.safeLoad(fs.readFileSync("codepoints.yaml"));
var svgFolder = "./assets/svg";
var fontFolder = "./assets/font";
var glyphs = [];

fs.readdirSync(svgFolder).forEach(function (file) {
    var svgFile = path.join(svgFolder, file);
    if (fs.statSync(svgFile).isFile() && path.extname(svgFile) == ".svg") {
        var glyphName = path.basename(file, ".svg");
        var glyphCode = codepoints[glyphName];
        if (glyphCode) {
            console.log(glyphCode);
            glyphs.push({
                name: glyphName,
                file: file,
                codepoint: "0x" + glyphCode 
            });
        }
    }
});

var options = {
    icons: glyphs,
    src: path.join(__dirname, svgFolder),
    fontName: 'iconfont',
    descent: 0,
    dest: path.join(__dirname, fontFolder)
};

builder(options).then().catch();

codepoints.yaml

house: 2302
check: f050
print: f036
hourglass: 231b
watch: 231a
play: 25b6
plus: 2795
cross: f04f
info: 2139

出错的图标是 svgo 压缩后的 info.svg

<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm-1-8.5h2V17h-2v-5.5zm1-1.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/></svg>

原始的 info.svg, 从 Sketch 导出的。

<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <rect id="#" fill="none" x="0" y="0" width="24" height="24"></rect>
    <path d="M12,22 C6.4771525,22 2,17.5228475 2,12 C2,6.4771525 6.4771525,2 12,2 C17.5228475,2 22,6.4771525 22,12 C22,17.5228475 17.5228475,22 12,22 Z M12,20 C16.418278,20 20,16.418278 20,12 C20,7.581722 16.418278,4 12,4 C7.581722,4 4,7.581722 4,12 C4,16.418278 7.581722,20 12,20 Z M11,11.5 L13,11.5 L13,17 L11,17 L11,11.5 Z M12,10 C11.1715729,10 10.5,9.32842712 10.5,8.5 C10.5,7.67157288 11.1715729,7 12,7 C12.8284271,7 13.5,7.67157288 13.5,8.5 C13.5,9.32842712 12.8284271,10 12,10 Z" id="Combined-Shape" fill="#000000" fill-rule="nonzero"></path>
</svg>

另外一个问题是,设计从 Unicode 网站查找到的或者 macOS Fontbook 是编码都是 16 进值的。我使用 16 进值码之后,HTML 文件显示图标就有问题。

malcolmyu commented 7 years ago

第一个问题我看一下,有同事也遇到 sketch 上的图标导出不能用的问题。

第二个问题能更详细描述下么?咱们在 HTML 上是怎么写字体的呢。

Ashung commented 7 years ago

sketch 上的图标导出不能用,可能跟设计有关吧。我目前只发现被 SVGO 压缩过的 SVG,用原始的svgicons2svgfont 和 svg2ttf 是转的字体是完整的,而 iconfont-builder 却出问题,这个比较奇怪。

我参考 Google material-design-icons 使用 16 进值,我在 Unicode 完整下载的码表也是 16 进值。

改成这样就可以显示。

<i class="icon iconfont">&#xF050;</i>
<div class="name">check</div>
<div class="code">&amp;#xF050;</div>

原来是这样的。

<i class="icon iconfont">&#x0xf050;</i>
<div class="name">check</div>
<div class="code">&amp;#x0xf050;</div>
malcolmyu commented 7 years ago

@Ashung 是这样,&# 是 html 转义的起始字符,后面一般跟的是十进制,如果要使用十六进制,需要以 &#x 最为起始字符。也就是说,咱们之前的写法 &#x0xf050 冗余了。

Ashung commented 7 years ago

对,问题是生产的HTML好像没区分用户使用十进制或十六进制。可是你为什么要用十进制?

malcolmyu commented 7 years ago

@Ashung 这里是生成字体的输入,而且也支持 16 进制,我看你传的就是 16 进制嘛,这个会进行转换的。采用十进制是考虑到我们的 code 可能会从数据库里取,库里是十进制的。

malcolmyu commented 7 years ago

@Ashung 你说用 svgo 压过的样式有问题,这个后来我看了下:现在我们内部的解决方案还是规范 SVG 的设计,在设计时路径一定要闭合,形状必须合并。其实我这个也是依赖 svgicons2svgfont 和 svg2ttf,理论上生成的结果应该是一样的。