Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e85635643 | ||
|
|
df1b6fac6e | ||
|
|
eda537e1a9 | ||
|
|
9967b2ef28 | ||
|
|
d41a53d459 | ||
|
|
06a2df3427 | ||
|
|
757584d2b9 | ||
|
|
f5092b7aa4 | ||
|
|
8a9a8572aa | ||
|
|
3d35b9f862 | ||
|
|
5dea160045 | ||
|
|
6984758915 | ||
|
|
29c25127d0 |
@@ -2,5 +2,6 @@ script: script/test
|
||||
rvm:
|
||||
- 1.9.3
|
||||
- 2.1.2
|
||||
- 2.2
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
1
Gemfile
@@ -1,5 +1,6 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "ttfunk", "~> 1.4.0"
|
||||
gem "rake"
|
||||
gem "minitest"
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ GEM
|
||||
specs:
|
||||
minitest (5.3.5)
|
||||
rake (10.3.2)
|
||||
ttfunk (1.4.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -16,3 +17,4 @@ DEPENDENCIES
|
||||
gemoji!
|
||||
minitest
|
||||
rake
|
||||
ttfunk (~> 1.4.0)
|
||||
|
||||
23
Rakefile
@@ -1,4 +1,5 @@
|
||||
require 'rake/testtask'
|
||||
require 'rake/extensiontask'
|
||||
|
||||
task :default => :test
|
||||
|
||||
@@ -27,3 +28,25 @@ end
|
||||
file 'db/NamesList.txt' do |t|
|
||||
system "curl -fsSL '#{nameslist_url}' -o '#{t.name}'"
|
||||
end
|
||||
|
||||
namespace :images do
|
||||
desc %(Extract PNG images from Apple's "Apple Color Emoji.ttf" font)
|
||||
task :extract do
|
||||
require 'emoji/extractor'
|
||||
gem_dir = File.dirname(File.realpath(__FILE__))
|
||||
Emoji::Extractor.new(64, "#{gem_dir}/images/emoji/unicode").extract!
|
||||
end
|
||||
end
|
||||
|
||||
namespace :c do
|
||||
task :headers do
|
||||
require 'emoji/tables'
|
||||
gem_dir = File.dirname(File.realpath(__FILE__))
|
||||
|
||||
File.open(File.join(gem_dir, "ext/gemoji/emoji.h"), "w") do |file|
|
||||
file.puts(Emoji::Tables.generate_length_tables)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Rake::ExtensionTask.new('gemoji')
|
||||
|
||||
@@ -8119,6 +8119,20 @@
|
||||
, "tags": [
|
||||
]
|
||||
}
|
||||
, {
|
||||
"aliases": [
|
||||
"basecamp"
|
||||
]
|
||||
, "tags": [
|
||||
]
|
||||
}
|
||||
, {
|
||||
"aliases": [
|
||||
"basecampy"
|
||||
]
|
||||
, "tags": [
|
||||
]
|
||||
}
|
||||
, {
|
||||
"aliases": [
|
||||
"bowtie"
|
||||
|
||||
11
ext/gemoji/emoji.h
Normal file
@@ -0,0 +1,11 @@
|
||||
static const long emoji_byte_lengths[][5] = {
|
||||
{0},
|
||||
{11, 8, 7, 4, 0},
|
||||
{6, 3, 0},
|
||||
{7, 0},
|
||||
{6, 0},
|
||||
{5, 0},
|
||||
};
|
||||
|
||||
static const int8_t emoji_magic_bytes[] =
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
6
ext/gemoji/extconf.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
require 'mkmf'
|
||||
|
||||
$CFLAGS << ' -ggdb3 -O0 '
|
||||
|
||||
dir_config('gemoji')
|
||||
create_makefile('gemoji')
|
||||
125
ext/gemoji/gemoji.c
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <ruby.h>
|
||||
#include <ruby/encoding.h>
|
||||
#include "emoji.h"
|
||||
|
||||
#define unlikely(x) __builtin_expect((x),0)
|
||||
|
||||
static long
|
||||
lookup_emoji(VALUE *rb_emoji, VALUE rb_bytes, VALUE rb_unicode_map, const long *possible_len)
|
||||
{
|
||||
const uint8_t *src = (uint8_t *)RSTRING_PTR(rb_bytes);
|
||||
|
||||
for (; *possible_len; ++possible_len) {
|
||||
const long emoji_size = *possible_len;
|
||||
|
||||
if (emoji_size > RSTRING_LEN(rb_bytes))
|
||||
continue;
|
||||
|
||||
if ((src[emoji_size - 1] & 0xC0) != 0x80)
|
||||
continue;
|
||||
|
||||
rb_str_set_len(rb_bytes, emoji_size);
|
||||
|
||||
*rb_emoji = rb_hash_lookup(rb_unicode_map, rb_bytes);
|
||||
if (!NIL_P(*rb_emoji))
|
||||
return emoji_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
replace_emoji(const uint8_t *src, long size, VALUE rb_unicode_map)
|
||||
{
|
||||
VALUE rb_emoji, rb_bytes, rb_out = Qnil;
|
||||
long i = 0, org, emoji_len;
|
||||
int8_t emoji_byte;
|
||||
|
||||
while (i < size) {
|
||||
org = i;
|
||||
|
||||
retry_search:
|
||||
while (i < size && (emoji_byte = emoji_magic_bytes[(int)src[i]]) == 0)
|
||||
i++;
|
||||
|
||||
if (i + 1 < size && (src[i + 1] & 0x80) != 0x80) {
|
||||
i++;
|
||||
goto retry_search;
|
||||
}
|
||||
|
||||
if (unlikely(org == 0)) {
|
||||
if (i == size)
|
||||
return Qnil;
|
||||
|
||||
rb_out = rb_str_buf_new(size * 4 / 3);
|
||||
rb_enc_associate(rb_out, rb_utf8_encoding());
|
||||
|
||||
rb_bytes = rb_str_buf_new(16);
|
||||
rb_enc_associate(rb_bytes, rb_utf8_encoding());
|
||||
}
|
||||
|
||||
if (i > org)
|
||||
rb_str_buf_cat(rb_out, (const char *)src + org, i - org);
|
||||
|
||||
if (unlikely(i == size))
|
||||
break;
|
||||
|
||||
emoji_len = size - i;
|
||||
if (emoji_len > 12)
|
||||
emoji_len = 12;
|
||||
|
||||
memcpy(RSTRING_PTR(rb_bytes), src + i, emoji_len);
|
||||
rb_str_set_len(rb_bytes, emoji_len);
|
||||
|
||||
emoji_len = lookup_emoji(&rb_emoji, rb_bytes, rb_unicode_map, emoji_byte_lengths[(int)emoji_byte]);
|
||||
|
||||
if (emoji_len) {
|
||||
VALUE rb_repl = rb_yield(rb_emoji);
|
||||
|
||||
if (NIL_P(rb_repl)) {
|
||||
rb_str_buf_cat(rb_out, (const char *)src + i, emoji_len);
|
||||
} else {
|
||||
Check_Type(rb_repl, T_STRING);
|
||||
rb_str_buf_append(rb_out, rb_repl);
|
||||
}
|
||||
|
||||
i += emoji_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
rb_str_buf_cat(rb_out, (const char *)src + i, 1);
|
||||
i++;
|
||||
}
|
||||
|
||||
return rb_out;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_gemoji_replace_unicode(VALUE klass, VALUE rb_source)
|
||||
{
|
||||
VALUE rb_output;
|
||||
VALUE rb_unicode_map = rb_funcall(klass, rb_intern("unicodes_index"), 0);
|
||||
|
||||
Check_Type(rb_source, T_STRING);
|
||||
Check_Type(rb_unicode_map, T_HASH);
|
||||
|
||||
rb_must_asciicompat(rb_source);
|
||||
|
||||
if (ENC_CODERANGE_ASCIIONLY(rb_source))
|
||||
return rb_source;
|
||||
|
||||
if (rb_enc_get(rb_source) != rb_utf8_encoding())
|
||||
rb_raise(rb_eEncCompatError, "expected UTF-8 encoding");
|
||||
|
||||
rb_output = replace_emoji((uint8_t *)RSTRING_PTR(rb_source), RSTRING_LEN(rb_source), rb_unicode_map);
|
||||
if (NIL_P(rb_output))
|
||||
return rb_source;
|
||||
|
||||
return rb_output;
|
||||
}
|
||||
|
||||
void Init_gemoji(void)
|
||||
{
|
||||
VALUE rb_mEmoji = rb_define_module("Emoji");
|
||||
rb_define_method(rb_mEmoji, "gsub_unicode", rb_gemoji_replace_unicode, 1);
|
||||
}
|
||||
BIN
images/emoji/basecamp.png
Normal file
|
After Width: | Height: | Size: 898 B |
BIN
images/emoji/basecampy.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 1016 B After Width: | Height: | Size: 1004 B |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 3.5 KiB |