This patch updates CachedFont to now use an std::map for cached glyphs,
instead of an std::vector. std::map allows O(log n) lookup, whereas
std::vector only allows O(n) lookup.
Note: std::unordered_map technically has better lookup complexity here,
with amortized O(1) lookup. However, hashmaps have a higher inherent
overhead than red-black trees so this would only be viable when going
above around 100 entries, which should never happen here for ASCII
glyphs.
This patch rewrites text rendering for J2D::DrawString to now construct
a texture atlas for all ASCII-range glyphs in the FT font face, instead
of cosntructing a texture for every glyph.
This improves text rendering performance for several reasons:
1. Binding textures is relatively expensive as the GPU is required to do
a context switch for internal data like texture parameters, and also
cannot optimize for accesses to the same texture across draw calls.
This patch removes the need to call glBindTexture more than once per
call to J2D::DrawString.
2. As a consequence of the above, all glyphs for a given string can now
be rendered in a single call to glDrawArrays. This is done by storing
the cached texture coordinates on CachedGlyph and constructing a full
array of vertices and texture coordinates for the entire string at
once, resulting in only /one/ set of client-to-device attribute
uploads and only one draw call, instead of being required to upload
attribute data for each glyph separately.