MetadataRepo


@AnyThread
public final class MetadataRepo


Class to hold the emoji metadata required to process and draw emojis.

Flat Trie Optimization Design

The trie data structure used to detect emoji sequences is packed into a single, contiguous primitive int[] array (mTrieArray) and a flat array of data references (TypefaceEmojiRasterizer[]). This design replaces the previous object-oriented trie representation (where every node allocated a Node object and a SparseArray) to eliminate startup memory spikes and runtime pointer-chasing.

1. Flat Node Representation

A node starting at a given offset in mTrieArray is packed sequentially:
[offset + 0] : packedHeader   (Packs 16-bit dataIndex + 1 and childrenCount)
                              Note: Limits total emojis to 65,534.
[offset + 1] : codepoint_0    (Transition key)
[offset + 2] : childOffset_0  (Offset of child node in mTrieArray)
...
[offset + 1 + 2*i] : codepoint_i
[offset + 2 + 2*i] : childOffset_i

2. Root Node Optimization

The root node has a high branching factor (~900 children). To keep the start of searches O(1), we bypass the flat array for the root and keep flat jump tables as class fields:
  • mRootPlane1DirectOffset: Direct offset lookup for Plane 1 codepoints (U+1F300 to U+1FFFF).
  • mRootPlane0DirectOffset: Direct offset lookup for Plane 0 codepoints (U+2600 to U+27BF).
  • mRootSparseKeys / mRootSparseOffsets: Sorted primitive arrays for remaining root children.

3. Direct Allocation-Free Construction

To build the flat trie without temporary object overhead at startup:
  1. We sort the indices of mEmojiList lexicographically by their codepoint sequences. Contiguous ranges in the sorted list naturally represent the prefix subranges.
  2. We pre-calculate the exact final size of the flat trie array using a fast pre-scan pass, allocate mTrieArray to its exact size once, and write directly into it.
  3. A stack-confined scratch buffer is used to track DFS recursion states inside FlatTrieBuilder. This achieves absolute zero heap garbage during the traversal.
  4. We lazily instantiate TypefaceEmojiRasterizer objects on demand during lookups and cache them in mEmojiCache, avoiding the creation of 7,025 objects at startup and saving ~168 KB of permanent heap overhead.

4. Complexity &Memory Comparison

  • Memory Footprint: Reduced from ~488 KB (original OO Trie) to ~78 KB (Flat Trie). Heap objects reduced from 9,400+ to just 5 primitive arrays.
  • Search Complexity: Root search is O(1) via direct plane tables. Non-root search is O(log C) via primitive binary search in mTrieArray.
  • Cache Locality: Contiguous array slots eliminate pointer chasing across the heap, which is highly CPU-cache-friendly.

Summary

Public methods

static @NonNull MetadataRepo
create(@NonNull AssetManager assetManager, @NonNull String assetPath)

Construct MetadataRepo from an asset.

static @NonNull MetadataRepo
create(@NonNull Typeface typeface, @NonNull ByteBuffer byteBuffer)

Construct MetadataRepo from a byte buffer.

static @NonNull MetadataRepo
create(@NonNull Typeface typeface, @NonNull InputStream inputStream)

Construct MetadataRepo from an input stream.

Public methods

create

Added in 1.0.0
public static @NonNull MetadataRepo create(@NonNull AssetManager assetManager, @NonNull String assetPath)

Construct MetadataRepo from an asset.

Parameters
@NonNull AssetManager assetManager

AssetManager instance

@NonNull String assetPath

asset manager path of the file that the Typeface and metadata will be created from

create

Added in 1.0.0
public static @NonNull MetadataRepo create(@NonNull Typeface typeface, @NonNull ByteBuffer byteBuffer)

Construct MetadataRepo from a byte buffer. The position of the ByteBuffer will change, it is caller's responsibility to reposition the buffer if required.

Parameters
@NonNull Typeface typeface

Typeface to be used to render emojis

@NonNull ByteBuffer byteBuffer

ByteBuffer to read emoji metadata from

create

Added in 1.0.0
public static @NonNull MetadataRepo create(@NonNull Typeface typeface, @NonNull InputStream inputStream)

Construct MetadataRepo from an input stream. The library does not close the given InputStream, therefore it is caller's responsibility to properly close the stream.

Parameters
@NonNull Typeface typeface

Typeface to be used to render emojis

@NonNull InputStream inputStream

InputStream to read emoji metadata from