Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render emoji with SVG #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "noto-emoji"]
path = noto-emoji
url = [email protected]:googlefonts/noto-emoji.git
1 change: 1 addition & 0 deletions noto-emoji
Submodule noto-emoji added at 9a5261
2 changes: 1 addition & 1 deletion src/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function App() {
key={emoji}
>
<div
className="emoji"
className={"emoji emoji-"+encodeURI(emoji).replace(/%/g, '')}
style={{
opacity,
transform: `scale(${calculatedScale}) translateY(10%)`
Expand Down
100 changes: 100 additions & 0 deletions src/emoji.css

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "./style.css";
import "./emoji.css";

import React from 'react';
import ReactDOM from 'react-dom';
Expand Down
8 changes: 8 additions & 0 deletions src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ a {
text-align: center;
line-height: 256px;
transform-origin: bottom center;

color: transparent;
margin-bottom: 32px;
}

.emoji::selection {
color: transparent;
background: grey;
}

.emoji span {
Expand Down
97 changes: 97 additions & 0 deletions svg_pack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#!/usr/bin/python3

import csv
import glob
import json
import os
import re
import subprocess
import sys
import unicodedata


def munge_svg(path, e=None, verbose=False):
svg_data = open(path).read()
svg_data = svg_data.replace('\n', ' ').strip()
if re.search(r'<svg[^>]*width', svg_data):
if 'ENTITY' in svg_data and False:
svg_data = subprocess.check_output(
['npx', 'svgo', '-o', '-', path]).decode('utf8')
svg_data_before = svg_data
# explicit width/height screws up automatic scaling
dim_re = re.compile(r' (width|height)="[^"]*"')

def fix_header(m):
attrib = dict(re.findall(r'(\S+)="([^"]*)"', m.group(0)))
if 'viewBox' not in attrib:
attrib['viewBox'] = '0 0 %s %s' % (attrib['width'],
attrib['height'])
attrib.pop('width')
attrib.pop('height')
return '<svg %s>' % ' '.join('%s="%s"' % i for i in attrib.items())

svg_data = re.sub(r'<svg[^>]*>', fix_header, svg_data)
if e and verbose:
print('stripping header dimensions from', e['char'], e['name'],
svg_data == svg_data_before)
return svg_data


def pack_svg(verbose=False):
ems = []
for fname in glob.glob('src/data/*.csv'):
ems.extend(csv.reader(open(fname)))

print(ems)

char_ems = {e[0]: e for e in ems}
svgs = {}

ems.sort(key=lambda e: float(e[1]) if e[1].isdigit() else 0)

aliases = {}
for line in open('noto-emoji/emoji_aliases.txt'):
m = re.match(r'(.*);(\S*)', line)
if m:
aliases[m.group(1)] = m.group(2)

c = 0
for e in ems:
em, size, name = e
em = unicodedata.normalize('NFKD', em)
if em == 'EMOJI' or size == '?':
continue
svg_path = ''
em_code = '_'.join('%04x' % ord(c) for c in em)
svg_path = 'noto-emoji/svg/emoji_u%s.svg' % em_code
print(svg_path)
if not os.path.exists(svg_path) and em_code in aliases:
svg_path = svg_path.replace(em_code, aliases[em_code])
if not os.path.exists(svg_path) and '_fe0f.' in svg_path:
svg_path = svg_path.replace('_fe0f.', '.')
assert os.path.exists(svg_path), (em, svg_path)
svg_data = munge_svg(svg_path, e, verbose)
if verbose:
print(em, e['name'], json.dumps(em), svg_path, len(svg_data))
svgs[em] = svg_data

with open('src/emoji.css', 'w') as f:
for char, svg in sorted(svgs.items()):
# based on https://yoksel.github.io/url-encoder/
# and https://mathiasbynens.be/notes/css-escapes
svg = svg.strip().replace("'", "\\'")
svg = svg.replace('\n', '\\A').replace('#', '%23')
f.write(
".emoji-%s{background-image:url('data:image/svg+xml,%s')}\n" %
(''.join('%02X'%c for c in char_ems[char][0].encode('utf8')), svg))
size = f.tell()
print('wrote %.1dK (%d emoji, %dB each) to %s' %
(size / 1024, len(svgs), size / len(svgs), f.name))


if __name__ == '__main__':
if sys.argv[1:]:
for fname in sys.argv[1:]:
print(fname, munge_svg(fname))
else:
pack_svg()