forked from googlefonts/noto-emoji
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
879 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "base", | ||
"extension": "", | ||
"tolerance": 5, | ||
"colors": | ||
{ | ||
"skin": "#FEE133", | ||
"stroke": "#eb8f00", | ||
"dark": "#242424", | ||
"tongue": "#e04c74", | ||
"tongue_dark": "#ab3d2e", | ||
"blue": "#40c0e7", | ||
"blue_stroke": "#47a9b0", | ||
"water": "#5f7aff", | ||
"water_stroke": "#4864ed" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "blob", | ||
"extension": "blob", | ||
"colors": | ||
{ | ||
"skin": "#fcc21b", | ||
"stroke": "#fcc21b", | ||
"dark": "#2f2f2f", | ||
"tongue": "#d7598b", | ||
"tongue_dark": "#d7598b", | ||
"blue": "#4fafd8", | ||
"blue_stroke": "#4fafd8", | ||
"water": "#ffffff", | ||
"water_stroke": "#ffffff" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import generate_skincolor | ||
import remove_gradient | ||
import emoji | ||
import argparse | ||
import os | ||
|
||
|
||
def main(): | ||
""" | ||
Die main-Funktion, welche die Skin-Modifier verarbeitet | ||
:return: Nix | ||
""" | ||
# Alle Kommandozeilenargumente hinzufügen | ||
parser = argparse.ArgumentParser() | ||
group = parser.add_mutually_exclusive_group(required = True) | ||
group.add_argument('--input_file', '-i', help='Input file', metavar='ifile') | ||
group.add_argument('--input_dir', '-d', help='Input directory', metavar='idir', default = '.') | ||
parser.add_argument('--mod_dir', '-m', help='Modifier directory', metavar='mdir', default = './blob') | ||
parser.add_argument('--base_name', '-b', help='Name of the base skin color', metavar='bname', default='base') | ||
# Zu dict verarbeiten | ||
args = vars(parser.parse_args()) | ||
# SKin-Modifier erstellen | ||
modifiers = generate_skincolor.generate_modifiers(args['mod_dir']) | ||
# Wurde ein Verzeichnis gewählt? | ||
if args['input_dir']: | ||
process_folder(args['input_dir'], modifiers, args['base_name']) | ||
else: | ||
process_file(modifiers, modifiers, args['base_name']) | ||
|
||
|
||
def process_folder(path: str, modifiers, base) -> None: | ||
""" | ||
Entfernt die Verläufe für alle Dateien eines Ordners | ||
:param path: Der Pfad zur Datei | ||
:param modifiers: Die Modifikatoren | ||
:param base: Der Basistyp | ||
:return: Nix (ändert die Datei) | ||
""" | ||
files = os.listdir(path) | ||
errors = [] | ||
for file in files: | ||
# Nur SVG wird derzeit unterstützt | ||
if os.path.splitext(file)[-1].lower() in {'.svg'}: | ||
err = process_file(os.path.join(path, file), modifiers, base, True) | ||
if err: | ||
errors.append(err) | ||
print('Es sind {} Fehler aufgetreten bei folgenden Dateien:\n {}'.format(len(errors), '\n '.join(errors))) | ||
|
||
|
||
def process_file(path, modifiers, base, folder = False): | ||
try: | ||
# Entferne Verläufe | ||
remove_gradient.process_file(path) | ||
# Erstelle ein Emoji-Objekt | ||
emoji_ = emoji.Emoji(modifiers, path, base) | ||
# Und wende die Modifier an | ||
emoji_.batch_modify() | ||
except Exception as e: | ||
print('Es ist ein Fehler aufgetreten beim Bearbeiten von: {}'.format(path)) | ||
print(e) | ||
return path | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
from modifier import * | ||
import re | ||
|
||
|
||
class Emoji: | ||
|
||
# There are some cases where an FE0F character has to be applied. | ||
# This is the case for gender symbols which should be represented as emojis and not as characters | ||
fe0f_chars = {'♀', '♂'} | ||
|
||
def __init__(self, modifiers: dict, path: str, base: str, end: bool = False): | ||
""" | ||
Create a new Emoji | ||
:param modifiers: All skin modifiers available to this emoji | ||
:param path: The path of the base SVG file | ||
:param base: Name of the base type | ||
:param end: True/False explicitly sets the FE0F character. fe0f_chars is used if None | ||
""" | ||
# Assignments | ||
self.modifiers = modifiers | ||
self.path = path | ||
self.directory = os.path.dirname(path) | ||
self.base = modifiers[base] | ||
self.name = os.path.splitext(os.path.basename(path))[0] | ||
self.fextension = os.path.splitext(os.path.basename(path))[1] | ||
self.content = self.load() | ||
if end is not None: | ||
# Explicit | ||
self.end = end | ||
else: | ||
# Implicit | ||
self.end = False | ||
# Does it contain an "FE0F indicator"? | ||
for char in Emoji.fe0f_chars: | ||
if(char in path): | ||
self.end = True | ||
break | ||
|
||
def batch_modify(self): | ||
""" | ||
new_modified_file for all Modifiers | ||
:return: None | ||
""" | ||
for name, modifier in self.modifiers.items(): | ||
# You don't need to convert from base to base | ||
if modifier != self.base: | ||
self.new_modified_file(modifier) | ||
print('{} auf Emoji {} angewendet.'.format(name, self.name)) | ||
|
||
def new_modified_file(self, modifier: Modifier): | ||
""" | ||
Creates a new skin tone variant file | ||
:param modifier: The Modifier | ||
:return: None | ||
""" | ||
# Update the SVG file | ||
new_content = self.generate_modified(modifier) | ||
# Save file | ||
self.save(new_content, modifier.extension) | ||
|
||
def load(self) -> str: | ||
"""Gets the (text) content of the base SVG file of this Emoji. | ||
:return: the SVG file's content""" | ||
try: | ||
with open(self.path) as file: | ||
return file.read() | ||
except FileNotFoundError: | ||
print('File "{}" not found!'.format(self.path)) | ||
|
||
def generate_modified(self, modifier: Modifier): | ||
""" | ||
Creates a new skin tone variant of this Emoji | ||
:param modifier: The Modifier which has to be applied | ||
:return: The altered SVG file's content | ||
""" | ||
# We're going to work on a copy of the content | ||
content = self.content | ||
# All colors are indexed by their name. We'll replace one by one | ||
for old, new in modifier.replace(self.base).items(): | ||
# Create the regular expression which will be used | ||
old_regex = re.compile(old, re.IGNORECASE) | ||
# ...Apply it | ||
content = old_regex.sub(new, content) | ||
return content | ||
|
||
def save(self, content: str, extension: str) -> None: | ||
""" | ||
Save the new skin tone variant | ||
:param content: The new content which has been created | ||
:param extension: Any new characters which have to be added (usually 200d + the skin tone modifier) | ||
:return: None (writes the file) | ||
""" | ||
# Well, this should be obvious... | ||
with open(self.generate_path(extension), 'w') as file: | ||
file.write(content) | ||
|
||
def generate_path(self, extension: str) -> str: | ||
""" | ||
Creates the file path of the newly created variant | ||
:param extension: All characters which have to be added to this emoji. | ||
:return: A str containing the path/to/emoji_variant.svg | ||
""" | ||
# Which directory? (It will be saved in the same one as the base emoji) | ||
directory = self.directory | ||
# Which is the base name of the file? (e.g. emoji_u1f973) | ||
basename = self.name | ||
# The file extension (.svg) | ||
fileextension = self.fextension | ||
base_seq = basename.split('_') | ||
base_seq.insert(2, extension) | ||
# Add FE0F? | ||
if self.end: | ||
base_seq.append('fe0f') | ||
basename = '_'.join(base_seq) | ||
# Stitch it together and return the whole file path | ||
return os.path.join(directory, basename) + fileextension |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
import os | ||
import sys | ||
import argparse | ||
from modifier import * | ||
from emoji import * | ||
|
||
|
||
def main(): | ||
""" | ||
The main function doing all the work | ||
:return: Nothing | ||
""" | ||
# We'll need all those command line arguments | ||
parser = argparse.ArgumentParser() | ||
group = parser.add_mutually_exclusive_group(required = True) | ||
group.add_argument('--input_file', '-i', help='Input file.svg', metavar='ifile') | ||
group.add_argument('--input_dir', '-d', help='Directory containing all base files.svg', metavar='idir', default = '.') | ||
parser.add_argument('--mod_dir', '-m', help='Directory containing all modifier.json', metavar='mdir', default = './skins') | ||
parser.add_argument('--base_name', '-b', help='Name of the base skin color (without file extensions)', metavar='bname', default='base') | ||
parser.add_argument('--add_end', '-e', help='Do you want to add an fe0f ZWJ-sequence?', default='auto', choices=['y','n','auto'], required=False) | ||
# Make a dict out of it | ||
args = vars(parser.parse_args()) | ||
end = False if args['add_end'].lower() == 'n' else (True if args['add_end'].lower() == 'y' else None) | ||
# Create skin-Modifiers | ||
modifiers = generate_modifiers(args['mod_dir']) | ||
# Did the user chose a dir or a file? | ||
if args['input_dir']: | ||
multi_process(args['input_dir'], modifiers, args['base_name'], end) | ||
else: | ||
# Create this one Emoji object | ||
emoji = Emoji(modifiers, args['input_file'], args['base_name'], end) | ||
# Apply modifiers | ||
emoji.batch_modify() | ||
|
||
|
||
def generate_modifiers(path: str) -> dict: | ||
""" | ||
Parses all skin modifiers in their directory | ||
:param path: Directory containing the JSON files for the modifiers | ||
:return: A str-Modifier dict containing the modifiers, sorted by their name (name: modifier) | ||
""" | ||
modifiers = {} | ||
for file in os.listdir(path): | ||
# Ignore non-JSON files | ||
if os.path.splitext(file)[-1].lower() == '.json': | ||
# Create one Modifier out of this JSON file | ||
modifier = Modifier.generate_from_json(os.path.join(path, file)) | ||
modifiers.update({modifier.name: modifier}) | ||
return modifiers | ||
|
||
|
||
def multi_process(directory: str, modifiers: dict, base: str, end: bool = False): | ||
""" | ||
Processes one directory of Emoji files | ||
:param directory: The directory containing the base SVG files | ||
:param modifiers: All Modifiers (probably provided by generate_modifiers) | ||
:param base: The name of the base skin color used in the base SVG files | ||
:param end: If an FE0F sequence should be added | ||
:return: Nothing (Files will be written) | ||
""" | ||
files = os.listdir(directory) | ||
for file in files: | ||
# Ignore non-SVG-files | ||
if os.path.splitext(file)[-1].lower() in {'.svg'}: | ||
# Create a new Emoji-object | ||
emoji = Emoji(modifiers, os.path.join(directory, file), base, end) | ||
# Apply modifiers | ||
emoji.batch_modify() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
import os | ||
import sys | ||
import argparse | ||
from modifier import * | ||
from emoji import * | ||
|
||
|
||
def main(): | ||
""" | ||
Die main-Funktion, welche die Skin-Modifier verarbeitet | ||
:return: Nix | ||
""" | ||
# Alle Kommandozeilenargumente hinzufügen | ||
parser = argparse.ArgumentParser() | ||
group = parser.add_mutually_exclusive_group(required = True) | ||
group.add_argument('--input_file', '-i', help='Input file', metavar='ifile') | ||
group.add_argument('--input_dir', '-d', help='Input directory', metavar='idir', default = '.') | ||
parser.add_argument('--mod_dir', '-m', help='Modifier directory', metavar='mdir', default = './skins') | ||
parser.add_argument('--base_name', '-b', help='Name of the base skin color', metavar='bname', default='base') | ||
parser.add_argument('--add_end', '-e', help='Do you want to add an fe0f ZWJ-sequence?', default='n', choices=['y','n','auto'], required=False) | ||
# Zu dict verarbeiten | ||
args = vars(parser.parse_args()) | ||
end = False if args['add_end'].lower() == 'n' else (True if args['add_end'].lower() == 'y' else None) | ||
# Skin-Modifier erstellen | ||
modifiers = generate_modifiers(args['mod_dir']) | ||
# Wurde ein Verzeichnis gewählt? | ||
if args['input_dir']: | ||
multi_process(args['input_dir'], modifiers, args['base_name'], end) | ||
else: | ||
# Erstelle ein Emoji-Objekt | ||
emoji = Emoji(modifiers, args['input_file'], args['base_name'], end) | ||
# Und wende die Modifier an | ||
emoji.batch_modify() | ||
|
||
|
||
def generate_modifiers(path: str) -> dict: | ||
""" | ||
Holt alle Skin-Modifier aus dem Ordner | ||
:param path: Der Ordner mit den JSON-Dateien | ||
:return: Ein dict mit name: Modifier | ||
""" | ||
modifiers = {} | ||
for file in os.listdir(path): | ||
# Ist es überhaupt eine JSON-Datei? | ||
if os.path.splitext(file)[-1].lower() == '.json': | ||
# Erstelle aus der JSON-Datei und füge es ein | ||
modifier = Modifier.generate_from_json(os.path.join(path, file)) | ||
modifiers.update({modifier.name: modifier}) | ||
return modifiers | ||
|
||
|
||
def multi_process(directory: str, modifiers: dict, base: str, end: bool = False): | ||
""" | ||
Verarbeitet ein ganzes Verzeichnis mit Emojis | ||
:param directory: Der Ordner | ||
:param modifiers: Die Skin-Modifier | ||
:param base: Der Name des Basis-Typen | ||
:param end: Ob noch eine fe0f-Sequenz angefügt werden soll. | ||
:return: Nix | ||
""" | ||
files = os.listdir(directory) | ||
for file in files: | ||
# Nur SVG wird derzeit unterstützt | ||
if os.path.splitext(file)[-1].lower() in {'.svg'}: | ||
# Erstelle ein Emoji-Objekt | ||
emoji = Emoji(modifiers, os.path.join(directory, file), base, end) | ||
# Und wende die Modifier an | ||
emoji.batch_modify() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Oops, something went wrong.