9#include <bgfx/embedded_shader.h>
19#include <tinystl/allocator.h>
20#include <tinystl/unordered_map.h>
21#include <tinystl/vector.h>
22namespace stl = tinystl;
44static const bgfx::EmbeddedShader s_embedded_shaders[] = {
45 BGFX_EMBEDDED_SHADER(vs_font_basic),
46 BGFX_EMBEDDED_SHADER(fs_font_basic),
47 BGFX_EMBEDDED_SHADER(vs_font_distance_field),
48 BGFX_EMBEDDED_SHADER(fs_font_distance_field),
49 BGFX_EMBEDDED_SHADER(vs_font_distance_field_subpixel),
50 BGFX_EMBEDDED_SHADER(fs_font_distance_field_subpixel),
51 BGFX_EMBEDDED_SHADER(vs_font_distance_field_outline),
52 BGFX_EMBEDDED_SHADER(fs_font_distance_field_outline),
53 BGFX_EMBEDDED_SHADER(vs_font_distance_field_outline_image),
54 BGFX_EMBEDDED_SHADER(fs_font_distance_field_outline_image),
55 BGFX_EMBEDDED_SHADER(vs_font_distance_field_drop_shadow),
56 BGFX_EMBEDDED_SHADER(fs_font_distance_field_drop_shadow),
57 BGFX_EMBEDDED_SHADER(vs_font_distance_field_drop_shadow_image),
58 BGFX_EMBEDDED_SHADER(fs_font_distance_field_drop_shadow_image),
59 BGFX_EMBEDDED_SHADER(vs_font_distance_field_outline_drop_shadow_image),
60 BGFX_EMBEDDED_SHADER(fs_font_distance_field_outline_drop_shadow_image),
62 BGFX_EMBEDDED_SHADER_END()};
69 size_t initial(8192 - 5);
75 vertex_buffer_.resize(max_buffered_characters * 4);
76 index_buffer_.resize(max_buffered_characters * 6);
77 style_buffer_.resize(max_buffered_characters * 4);
82 return vertex_buffer_.size() / 4;
87 return outline_color_;
92 return outline_width_;
97 return drop_shadow_color_;
102 return drop_shadow_offset_[0];
107 return drop_shadow_offset_[1];
112 return drop_shadow_softener_;
117 style_flags_ = flags;
127 background_color_ = rgba;
132 foreground_color_ = rgba;
137 overline_color_ = rgba;
142 underline_color_ = rgba;
147 strike_through_color_ = rgba;
152 outline_color_ = rgba;
157 outline_width_ = outline_width;
162 drop_shadow_color_ = rgba;
167 drop_shadow_offset_[0] = u;
168 drop_shadow_offset_[1] = v;
173 drop_shadow_softener_ = smoother;
196 apply_kerning_ = apply_kerning;
199 void append_text(font_handle font_handle,
const char* str,
const char*
end =
nullptr);
201 void append_text(font_handle font_handle,
const wchar_t* str,
const wchar_t*
end =
nullptr);
209 return (uint8_t*)vertex_buffer_.data();
214 return vertex_count_;
219 return sizeof(text_vertex);
224 return index_buffer_.data();
229 return buffers_dirty_;
234 buffers_dirty_ = dirty;
244 return sizeof(uint16_t);
259 void vertical_center_last_line(
float dy,
float top,
float bottom);
261 static auto to_abgr(uint32_t rgba) -> uint32_t
263 return (((rgba >> 0) & 0xff) << 24) | (((rgba >> 8) & 0xff) << 16) | (((rgba >> 16) & 0xff) << 8) |
264 (((rgba >> 24) & 0xff) << 0);
267 void set_vertex(uint32_t i,
float x,
float y, uint32_t rgba, uint8_t style =
style_normal)
269 vertex_buffer_[i].x =
x;
270 vertex_buffer_[i].y =
y;
271 vertex_buffer_[i].rgba = rgba;
272 style_buffer_[i] = style;
277 vertex_buffer_[
i].rgba_outline = rgba_outline;
283 int16_t u{}, v{}, w{}, t{};
284 int16_t u1{}, v1{}, w1{}, t1{};
285 int16_t u2{}, v2{}, w2{}, t2{};
287 uint32_t rgba_outline{};
292 uint32_t text_color_{0xffffffff};
293 uint32_t background_color_{0x00000000};
294 uint32_t foreground_color_{0x00000000};
295 uint32_t overline_color_{0xffffffff};
296 uint32_t underline_color_{0xffffffff};
297 uint32_t strike_through_color_{0xffffffff};
299 float outline_width_{0.0f};
300 uint32_t outline_color_{0xff000000};
302 float drop_shadow_offset_[2] = {0.00f, 0.00f};
303 uint32_t drop_shadow_color_{0xff000000};
304 float drop_shadow_softener_{1.0f};
306 bool apply_kerning_{
true};
313 float line_ascender_{};
314 float line_descender_{};
319 text_rectangle rectangle_{};
320 font_manager* font_manager_;
322 stl::vector<text_vertex> vertex_buffer_;
323 stl::vector<uint16_t> index_buffer_;
324 stl::vector<uint8_t> style_buffer_;
326 bool buffers_dirty_{};
328 uint32_t index_count_{};
329 uint32_t line_start_index_{};
330 uint16_t vertex_count_{};
336 if(vertex_count_ == 0)
341 previous_code_point_ = 0;
349 end = str + bx::strLen(str);
351 BX_ASSERT(
end >= str,
"");
356 float save_pen_x = pen_x_;
357 float save_pen_y = pen_y_;
358 code_point save_previous_code_point = previous_code_point_;
361 const char* orig_string = str;
362 for(; *str && str <
end; ++str)
366 append_glyph(
handle, codepoint,
true);
373 previous_code_point_ = save_previous_code_point;
374 rectangle_ = save_rectangle;
377 for(; *str && str <
end; ++str)
381 append_glyph(
handle, codepoint,
false);
385 BX_ASSERT(state ==
UTF8_ACCEPT,
"The string is not well-formed");
390 if(vertex_count_ == 0)
395 previous_code_point_ = 0;
400 end = str + wcslen(str);
402 BX_ASSERT(
end >= str,
"");
407 float save_pen_x = pen_x_;
408 float save_pen_y = pen_y_;
409 code_point save_previous_code_point = previous_code_point_;
412 for(
const wchar_t* current = str; current <
end; ++current)
420 previous_code_point_ = save_previous_code_point;
421 rectangle_ = save_rectangle;
424 for(
const wchar_t* current = str; current <
end; ++current)
436 size_t max_quads_per_glyph = 1;
437 size_t capacity_growth = 10;
449 (uint8_t*)vertex_buffer_.data(),
450 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
451 sizeof(text_vertex));
453 set_vertex(vertex_count_ + 0, x0, y0, background_color_);
454 set_vertex(vertex_count_ + 1, x0, y1, background_color_);
455 set_vertex(vertex_count_ + 2, x1, y1, background_color_);
456 set_vertex(vertex_count_ + 3, x1, y0, background_color_);
458 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
459 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
460 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
461 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
462 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
463 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
466 buffers_dirty_ =
true;
480 line_start_index_ = 0;
484 previous_code_point_ = 0;
485 rectangle_.
width = 0;
489void text_buffer::append_glyph(font_handle
handle,
code_point codepoint,
bool shadow)
491 if(codepoint == L
'\t')
493 for(uint32_t ii = 0; ii < 4; ++ii)
495 append_glyph(
handle, L
' ', shadow);
501 BX_WARN(NULL != glyph,
"Glyph not found (font handle %d, code point %d)",
handle.idx, codepoint);
504 previous_code_point_ = 0;
511 size_t max_quads_per_glyph = 6;
512 size_t capacity_growth = 100;
518 if(codepoint == L
'\n')
520 line_gap_ =
font.line_gap;
521 line_descender_ =
font.descender;
522 line_ascender_ =
font.ascender;
523 line_start_index_ = vertex_count_;
524 previous_code_point_ = 0;
526 pen_y_ += line_gap_ + line_ascender_ - line_descender_;
531 if(
font.ascender > line_ascender_ || (
font.descender < line_descender_))
533 if(
font.descender < line_descender_)
535 line_descender_ =
font.descender;
536 line_gap_ =
font.line_gap;
539 float txtDecals = (
font.ascender - line_ascender_);
540 line_ascender_ =
font.ascender;
541 line_gap_ =
font.line_gap;
542 vertical_center_last_line((txtDecals),
543 (pen_y_ - line_ascender_),
544 (pen_y_ + line_ascender_ - line_descender_ + line_gap_));
547 float kerning = 0.0f;
556 const AtlasRegion& atlasRegion = atlas->getRegion(glyph->region_index);
558 const bool is_drop_shadow_font =
561 if((shadow || !is_drop_shadow_font) && style_flags_ &
style_background && background_color_ & 0xff000000)
563 float x0 = pen_x_ - kerning;
565 float x1 = x0 + glyph->advance_x;
566 float y1 = pen_y_ + line_ascender_ - line_descender_ + line_gap_;
568 atlas->packUV(whiteGlyph.region_index,
569 (uint8_t*)vertex_buffer_.data(),
570 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
571 sizeof(text_vertex));
578 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
579 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
580 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
581 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
582 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
583 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
586 buffers_dirty_ =
true;
594 float extra_x_offset = drop_shadow_offset_[0] *
font.scale;
595 float extra_y_offset = drop_shadow_offset_[1] *
font.scale;
597 uint32_t adjusted_drop_shadow_color =
598 ((((drop_shadow_color_ & 0xff000000) >> 8) * (text_color_ >> 24)) & 0xff000000) |
599 (drop_shadow_color_ & 0x00ffffff);
601 const uint8_t shadowA = (drop_shadow_color_ >> 24) & 0xFF;
603 if(shadowA > 0 || std::fabs(extra_x_offset) > 1e-6f || std::fabs(extra_y_offset) > 1e-6f)
605 float x0 = pen_x_ + glyph->offset_x + extra_x_offset;
606 float y0 = pen_y_ + line_ascender_ + glyph->offset_y + extra_y_offset;
607 float x1 = x0 + glyph->width;
608 float y1 = y0 + glyph->height;
610 bx::memSet(&vertex_buffer_[vertex_count_], 0,
sizeof(text_vertex) * 4);
612 atlas->packUV(glyph->region_index,
613 (uint8_t*)vertex_buffer_.data(),
614 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u2),
615 sizeof(text_vertex));
617 set_vertex(vertex_count_ + 0, x0, y0, adjusted_drop_shadow_color);
618 set_vertex(vertex_count_ + 1, x0, y1, adjusted_drop_shadow_color);
619 set_vertex(vertex_count_ + 2, x1, y1, adjusted_drop_shadow_color);
620 set_vertex(vertex_count_ + 3, x1, y0, adjusted_drop_shadow_color);
622 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
623 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
624 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
625 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
626 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
627 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
630 buffers_dirty_ =
true;
635 pen_x_ += glyph->advance_x;
637 float lineWidth = pen_x_ - origin_x_;
638 if(lineWidth > rectangle_.
width)
640 rectangle_.
width = lineWidth;
643 float lineHeight = pen_y_ + line_ascender_ - line_descender_ + line_gap_;
644 if(lineHeight > rectangle_.
height)
646 rectangle_.
height = lineHeight;
649 previous_code_point_ = codepoint;
656 float x0 = pen_x_ - kerning;
657 float y0 = pen_y_ + line_ascender_ - line_descender_ * 0.5f;
658 float x1 = x0 + glyph->advance_x;
659 float y1 = y0 +
font.underline_thickness;
661 atlas->packUV(whiteGlyph.region_index,
662 (uint8_t*)vertex_buffer_.data(),
663 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
664 sizeof(text_vertex));
666 set_vertex(vertex_count_ + 0, x0, y0, underline_color_,
style_underline);
667 set_vertex(vertex_count_ + 1, x0, y1, underline_color_,
style_underline);
668 set_vertex(vertex_count_ + 2, x1, y1, underline_color_,
style_underline);
669 set_vertex(vertex_count_ + 3, x1, y0, underline_color_,
style_underline);
671 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
672 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
673 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
674 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
675 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
676 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
679 buffers_dirty_ =
true;
685 float x0 = pen_x_ - kerning;
687 float x1 = x0 + glyph->advance_x;
688 float y1 = y0 +
font.underline_thickness;
690 atlas->packUV(whiteGlyph.region_index,
691 (uint8_t*)vertex_buffer_.data(),
692 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
693 sizeof(text_vertex));
695 set_vertex(vertex_count_ + 0, x0, y0, overline_color_,
style_overline);
696 set_vertex(vertex_count_ + 1, x0, y1, overline_color_,
style_overline);
697 set_vertex(vertex_count_ + 2, x1, y1, overline_color_,
style_overline);
698 set_vertex(vertex_count_ + 3, x1, y0, overline_color_,
style_overline);
700 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
701 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
702 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
703 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
704 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
705 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
708 buffers_dirty_ =
true;
714 bx::memSet(&vertex_buffer_[vertex_count_], 0,
sizeof(text_vertex) * 4);
716 atlas->packUV(glyph->region_index,
717 (uint8_t*)vertex_buffer_.data(),
718 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u1),
719 sizeof(text_vertex));
721 float glyph_scale = glyph->bitmap_scale;
722 float glyph_width = glyph->width * glyph_scale;
723 float glyph_height = glyph->height * glyph_scale;
724 float x0 = pen_x_ + glyph->offset_x;
725 float y0 = pen_y_ + (
font.ascender + -
font.descender - glyph_height) / 2;
726 float x1 = x0 + glyph_width;
727 float y1 = y0 + glyph_height;
729 set_vertex(vertex_count_ + 0, x0, y0, text_color_);
730 set_vertex(vertex_count_ + 1, x0, y1, text_color_);
731 set_vertex(vertex_count_ + 2, x1, y1, text_color_);
732 set_vertex(vertex_count_ + 3, x1, y0, text_color_);
736 bx::memSet(&vertex_buffer_[vertex_count_], 0,
sizeof(text_vertex) * 4);
738 atlas->packUV(glyph->region_index,
739 (uint8_t*)vertex_buffer_.data(),
740 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
741 sizeof(text_vertex));
743 float x0 = pen_x_ + glyph->offset_x;
744 float y0 = pen_y_ + line_ascender_ + glyph->offset_y;
745 float x1 = x0 + glyph->width;
746 float y1 = y0 + glyph->height;
748 set_vertex(vertex_count_ + 0, x0, y0, text_color_);
749 set_vertex(vertex_count_ + 1, x0, y1, text_color_);
750 set_vertex(vertex_count_ + 2, x1, y1, text_color_);
751 set_vertex(vertex_count_ + 3, x1, y0, text_color_);
759 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
760 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
761 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
762 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
763 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
764 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
767 buffers_dirty_ =
true;
772 float x0 = pen_x_ - kerning;
774 float x1 = x0 + glyph->advance_x;
775 float y1 = pen_y_ + line_ascender_ - line_descender_ + line_gap_;
777 atlas->packUV(whiteGlyph.region_index,
778 (uint8_t*)vertex_buffer_.data(),
779 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
780 sizeof(text_vertex));
787 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
788 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
789 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
790 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
791 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
792 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
795 buffers_dirty_ =
true;
801 float x0 = pen_x_ - kerning;
802 float y0 = pen_y_ + 0.666667f *
font.ascender;
803 float x1 = x0 + glyph->advance_x;
804 float y1 = y0 +
font.underline_thickness;
806 atlas->packUV(whiteGlyph.region_index,
807 (uint8_t*)vertex_buffer_.data(),
808 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
809 sizeof(text_vertex));
816 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
817 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
818 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
819 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
820 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
821 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
824 buffers_dirty_ =
true;
828 pen_x_ += glyph->advance_x;
830 float line_width = pen_x_ - origin_x_;
831 if(line_width > rectangle_.
width)
833 rectangle_.
width = line_width;
836 float line_height = pen_y_ + line_ascender_ - line_descender_ + line_gap_;
837 if(line_height > rectangle_.
height)
839 rectangle_.
height = line_height;
842 previous_code_point_ = codepoint;
845void text_buffer::vertical_center_last_line(
float dy,
float top,
float bottom)
847 for(uint32_t ii = line_start_index_; ii < vertex_count_; ii += 4)
851 vertex_buffer_[ii + 0].y =
top;
852 vertex_buffer_[ii + 1].y =
bottom;
853 vertex_buffer_[ii + 2].y =
bottom;
854 vertex_buffer_[ii + 3].y =
top;
858 vertex_buffer_[ii + 0].y += dy;
859 vertex_buffer_[ii + 1].y += dy;
860 vertex_buffer_[ii + 2].y += dy;
861 vertex_buffer_[ii + 3].y += dy;
868 bgfx::RendererType::Enum
type = bgfx::getRendererType();
870 basic_program_ = bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_basic"),
871 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_basic"),
875 bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field"),
876 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field"),
879 distance_subpixel_program_ =
880 bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_subpixel"),
881 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_subpixel"),
884 distance_drop_shadow_program_ =
885 bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_drop_shadow"),
886 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_drop_shadow"),
889 distance_drop_shadow_image_program_ = bgfx::createProgram(
890 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_drop_shadow_image"),
891 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_drop_shadow_image"),
894 distance_outline_program_ =
895 bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_outline"),
896 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_outline"),
899 distance_outline_image_program_ = bgfx::createProgram(
900 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_outline_image"),
901 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_outline_image"),
904 distance_outline_drop_shadow_image_program_ = bgfx::createProgram(
905 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_outline_drop_shadow_image"),
906 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_outline_drop_shadow_image"),
909 vertex_layout_.begin()
910 .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
911 .add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Int16,
true)
912 .add(bgfx::Attrib::TexCoord1, 4, bgfx::AttribType::Int16,
true)
913 .add(bgfx::Attrib::TexCoord2, 4, bgfx::AttribType::Int16,
true)
914 .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8,
true)
915 .add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Uint8,
true)
918 s_tex_color_ = bgfx::createUniform(
"s_texColor", bgfx::UniformType::Sampler);
919 u_drop_shadow_color_ = bgfx::createUniform(
"u_dropShadowColor", bgfx::UniformType::Vec4);
920 u_params_ = bgfx::createUniform(
"u_params", bgfx::UniformType::Vec4);
925 BX_ASSERT(text_buffer_handles_.getNumHandles() == 0,
926 "All the text buffers must be destroyed before destroying the manager");
927 delete[] text_buffers_;
929 bgfx::destroy(u_params_);
931 bgfx::destroy(u_drop_shadow_color_);
932 bgfx::destroy(s_tex_color_);
934 bgfx::destroy(basic_program_);
935 bgfx::destroy(distance_program_);
936 bgfx::destroy(distance_subpixel_program_);
937 bgfx::destroy(distance_outline_program_);
938 bgfx::destroy(distance_outline_image_program_);
939 bgfx::destroy(distance_drop_shadow_program_);
940 bgfx::destroy(distance_drop_shadow_image_program_);
941 bgfx::destroy(distance_outline_drop_shadow_image_program_);
946 uint16_t text_idx = text_buffer_handles_.alloc();
947 buffer_cache& bc = text_buffers_[text_idx];
952 bc.index_buffer_handle_idx = bgfx::kInvalidHandle;
953 bc.vertex_buffer_handle_idx = bgfx::kInvalidHandle;
955 text_buffer_handle ret = {text_idx};
963 buffer_cache& bc = text_buffers_[
handle.idx];
964 text_buffer_handles_.free(
handle.idx);
968 if(bc.vertex_buffer_handle_idx == bgfx::kInvalidHandle)
977 bgfx::IndexBufferHandle ibh;
978 bgfx::VertexBufferHandle vbh;
979 ibh.idx = bc.index_buffer_handle_idx;
980 vbh.idx = bc.vertex_buffer_handle_idx;
988 bgfx::DynamicIndexBufferHandle ibh;
989 bgfx::DynamicVertexBufferHandle vbh;
990 ibh.idx = bc.index_buffer_handle_idx;
991 vbh.idx = bc.vertex_buffer_handle_idx;
1003 font_handle fhandle,
1010 buffer_cache& bc = text_buffers_[
handle.idx];
1015 if(0 == index_size || 0 == vertex_size)
1020 bgfx::setTexture(0, s_tex_color_, font_manager_->
get_atlas(fhandle)->getTextureHandle());
1022 bgfx::ProgramHandle
program = BGFX_INVALID_HANDLE;
1023 switch(bc.font_type)
1027 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1028 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1034 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1035 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1037 float params[4] = {0.0f, (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f, 0.0f, 0.0f};
1038 bgfx::setUniform(u_params_, ¶ms);
1043 program = distance_subpixel_program_;
1044 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1045 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_INV_SRC_COLOR),
1051 program = distance_outline_program_;
1052 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1053 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1055 float params[4] = {0.0f,
1056 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1059 bgfx::setUniform(u_params_, ¶ms);
1065 program = distance_outline_image_program_;
1066 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1067 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1069 float params[4] = {0.0f,
1070 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1073 bgfx::setUniform(u_params_, ¶ms);
1079 program = distance_drop_shadow_program_;
1080 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1081 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1084 float drop_shadow_color_vec[4] = {((drop_shadow_color >> 16) & 0xff) / 255.0f,
1085 ((drop_shadow_color >> 8) & 0xff) / 255.0f,
1086 (drop_shadow_color & 0xff) / 255.0f,
1087 (drop_shadow_color >> 24) / 255.0f};
1088 bgfx::setUniform(u_drop_shadow_color_, &drop_shadow_color_vec);
1090 float params[4] = {0.0f,
1091 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1094 bgfx::setUniform(u_params_, ¶ms);
1100 program = distance_drop_shadow_image_program_;
1101 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1102 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1105 float drop_shadow_color_vec[4] = {((drop_shadow_color >> 16) & 0xff) / 255.0f,
1106 ((drop_shadow_color >> 8) & 0xff) / 255.0f,
1107 (drop_shadow_color & 0xff) / 255.0f,
1108 (drop_shadow_color >> 24) / 255.0f};
1109 bgfx::setUniform(u_drop_shadow_color_, &drop_shadow_color_vec);
1111 float params[4] = {0.0f,
1112 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1115 bgfx::setUniform(u_params_, ¶ms);
1121 program = distance_outline_drop_shadow_image_program_;
1122 bgfx::setState(state | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_RGB |
1123 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1126 float drop_shadow_color_vec[4] = {((drop_shadow_color >> 16) & 0xff) / 255.0f,
1127 ((drop_shadow_color >> 8) & 0xff) / 255.0f,
1128 (drop_shadow_color & 0xff) / 255.0f,
1129 (drop_shadow_color >> 24) / 255.0f};
1130 bgfx::setUniform(u_drop_shadow_color_, &drop_shadow_color_vec);
1132 float params[4] = {0.0f,
1133 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1136 bgfx::setUniform(u_params_, ¶ms);
1148 bgfx::IndexBufferHandle ibh;
1149 bgfx::VertexBufferHandle vbh;
1151 if(bgfx::kInvalidHandle == bc.vertex_buffer_handle_idx)
1153 ibh = bgfx::createIndexBuffer(bgfx::copy(bc.buffer->
get_index_buffer(), index_size));
1155 vbh = bgfx::createVertexBuffer(bgfx::copy(bc.buffer->
get_vertex_buffer(), vertex_size), vertex_layout_);
1157 bc.vertex_buffer_handle_idx = vbh.idx;
1158 bc.index_buffer_handle_idx = ibh.idx;
1162 vbh.idx = bc.vertex_buffer_handle_idx;
1163 ibh.idx = bc.index_buffer_handle_idx;
1173 bgfx::DynamicIndexBufferHandle ibh;
1174 bgfx::DynamicVertexBufferHandle vbh;
1176 if(bgfx::kInvalidHandle == bc.vertex_buffer_handle_idx)
1178 ibh = bgfx::createDynamicIndexBuffer(bgfx::copy(bc.buffer->
get_index_buffer(), index_size),
1179 BGFX_BUFFER_ALLOW_RESIZE);
1181 vbh = bgfx::createDynamicVertexBuffer(bgfx::copy(bc.buffer->
get_vertex_buffer(), vertex_size),
1183 BGFX_BUFFER_ALLOW_RESIZE);
1185 bc.index_buffer_handle_idx = ibh.idx;
1186 bc.vertex_buffer_handle_idx = vbh.idx;
1190 ibh.idx = bc.index_buffer_handle_idx;
1191 vbh.idx = bc.vertex_buffer_handle_idx;
1193 bgfx::update(ibh, 0, bgfx::copy(bc.buffer->
get_index_buffer(), index_size));
1198 ibh.idx = bc.index_buffer_handle_idx;
1199 vbh.idx = bc.vertex_buffer_handle_idx;
1208 bgfx::TransientIndexBuffer tib;
1209 bgfx::TransientVertexBuffer tvb;
1211 bgfx::allocTransientVertexBuffer(&tvb, bc.buffer->
get_vertex_count(), vertex_layout_);
1220 bgfx::submit(
id,
program, depth);
1228 buffer_cache& bc = text_buffers_[
handle.idx];
1235 buffer_cache& bc = text_buffers_[
handle.idx];
1242 buffer_cache& bc = text_buffers_[
handle.idx];
1249 buffer_cache& bc = text_buffers_[
handle.idx];
1256 buffer_cache& bc = text_buffers_[
handle.idx];
1263 buffer_cache& bc = text_buffers_[
handle.idx];
1270 buffer_cache& bc = text_buffers_[
handle.idx];
1277 buffer_cache& bc = text_buffers_[
handle.idx];
1284 buffer_cache& bc = text_buffers_[
handle.idx];
1291 buffer_cache& bc = text_buffers_[
handle.idx];
1298 buffer_cache& bc = text_buffers_[
handle.idx];
1305 buffer_cache& bc = text_buffers_[
handle.idx];
1312 buffer_cache& bc = text_buffers_[
handle.idx];
1319 buffer_cache& bc = text_buffers_[
handle.idx];
1326 buffer_cache& bc = text_buffers_[
handle.idx];
1333 buffer_cache& bc = text_buffers_[
handle.idx];
1338 font_handle fhandle,
1339 const char* _string,
1343 buffer_cache& bc = text_buffers_[
handle.idx];
1348 font_handle fhandle,
1349 const wchar_t* _string,
1350 const wchar_t* _end)
1353 buffer_cache& bc = text_buffers_[
handle.idx];
1360 buffer_cache& bc = text_buffers_[
handle.idx];
1367 buffer_cache& bc = text_buffers_[
handle.idx];
1374 buffer_cache& bc = text_buffers_[
handle.idx];
void packFaceLayerUV(uint32_t _idx, uint8_t *_vertexBuffer, uint32_t _offset, uint32_t _stride) const
Same as packUV but pack a whole face of the atlas cube, mostly used for debugging and visualizing atl...
uint16_t getTextureSize() const
retrieve the size of side of a texture in pixels
auto get_glyph_info(font_handle handle, code_point code_point) -> const glyph_info *
auto get_white_glyph(font_handle handle) const -> const glyph_info &
auto get_atlas(font_handle handle) const -> Atlas *
Retrieve the atlas used by the font manager (e.g. to add stuff to it)
auto get_kerning(font_handle handle, code_point prev_code_point, code_point code_point) -> float
auto get_font_info(font_handle handle) const -> const font_info &
void set_pen_origin(text_buffer_handle handle, float x, float y)
void set_foreground_color(text_buffer_handle handle, uint32_t rgba=0x000000FF)
void destroy_text_buffer(text_buffer_handle handle)
void set_strike_through_color(text_buffer_handle handle, uint32_t rgba=0x000000FF)
void set_drop_shadow_softener(text_buffer_handle handle, float smoother=1.0f)
auto create_text_buffer(uint32_t type, buffer_type::Enum btype) -> text_buffer_handle
void set_style(text_buffer_handle handle, uint32_t flags=style_normal)
void clear_text_buffer(text_buffer_handle handle)
Clear the text buffer and reset its state (pen/color).
void set_outline_width(text_buffer_handle handle, float outline_width=3.0f)
void set_drop_shadow_offset(text_buffer_handle handle, float u, float v)
text_buffer_manager(font_manager *font_manager)
void submit_text_buffer(text_buffer_handle handle, font_handle fhandle, bgfx::ViewId id, uint64_t state=0, int32_t depth=0)
void set_drop_shadow_color(text_buffer_handle handle, uint32_t rgba=0x000000FF)
void set_apply_kerning(text_buffer_handle handle, bool apply_kerning)
void set_text_color(text_buffer_handle handle, uint32_t rgba=0x000000FF)
void set_background_color(text_buffer_handle handle, uint32_t rgba=0x000000FF)
void append_text(text_buffer_handle handle, font_handle fhandle, const char *string, const char *end=nullptr)
Append an ASCII/utf-8 string to the buffer using current pen position and color.
void get_pen_position(text_buffer_handle handle, float *x, float *y)
void set_pen_position(text_buffer_handle handle, float x, float y)
void set_underline_color(text_buffer_handle handle, uint32_t rgba=0x000000FF)
void set_outline_color(text_buffer_handle handle, uint32_t rgba=0x000000FF)
void set_overline_color(text_buffer_handle handle, uint32_t rgba=0x000000FF)
auto get_rectangle(text_buffer_handle handle) const -> text_rectangle
Return the rectangular size of the current text buffer (including all its content).
void append_atlas_face(text_buffer_handle handle, font_handle fhandle, uint16_t face_index)
Append a whole face of the atlas cube, mostly used for debugging and visualizing atlas.
void set_pen_origin(float x, float y)
auto get_drop_shadow_offset_v() -> float
auto get_index_buffer() const -> const uint16_t *
auto get_index_count() const -> uint32_t
auto get_drop_shadow_offset_u() -> float
auto get_drop_shadow_color() -> uint32_t
void set_drop_shadow_color(uint32_t rgba=0xff000000)
auto get_vertex_buffer() -> const uint8_t *
void set_text_color(uint32_t rgba=0xff000000)
void resize_buffers(size_t max_buffered_characters)
auto get_vertex_size() const -> uint32_t
void set_drop_shadow_softener(float smoother)
auto get_outline_color() -> uint32_t
void append_text(font_handle font_handle, const char *str, const char *end=nullptr)
void set_overline_color(uint32_t rgba=0xff000000)
auto get_drop_shadow_softener() -> float
auto get_vertex_count() const -> uint32_t
void set_buffers_dirty(bool dirty)
void get_pen_position(float *x, float *y)
auto get_text_color() const -> uint32_t
auto get_max_buffered_characters() const -> size_t
void set_strike_through_color(uint32_t rgba=0xff000000)
auto get_rectangle() const -> text_rectangle
void set_drop_shadow_offset(float u, float v)
text_buffer(font_manager *manager)
void set_pen_position(float x, float y)
auto get_index_size() const -> uint32_t
void append_atlas_face(font_handle font_handle, uint16_t face_index)
void set_foreground_color(uint32_t rgba=0xff000000)
void set_underline_color(uint32_t rgba=0xff000000)
auto get_outline_width() -> float
void set_outline_color(uint32_t rgba=0xff000000)
auto get_buffers_dirty() const -> bool
void set_outline_width(float outline_width=3.0f)
void set_apply_kerning(bool apply_kerning)
void set_background_color(uint32_t rgba=0xff000000)
void set_style(uint32_t flags=style_normal)
#define FONT_TYPE_DISTANCE_OUTLINE_DROP_SHADOW_IMAGE
#define FONT_TYPE_DISTANCE_DROP_SHADOW
#define FONT_TYPE_DISTANCE_OUTLINE_IMAGE
#define FONT_TYPE_DISTANCE
#define FONT_TYPE_DISTANCE_DROP_SHADOW_IMAGE
#define FONT_TYPE_DISTANCE_OUTLINE
#define FONT_TYPE_DISTANCE_SUBPIXEL
#define FONT_TYPE_MASK_DISTANCE_DROP_SHADOW
uint32_t code_point
Unicode value of a character.
void end(encoder *_encoder)
uint32_t utf8_decode(uint32_t *_state, uint32_t *_codep, uint8_t _ch)
bool isValid(SpriteHandle _handle)