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(21 - 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)
437 size_t max_quads_per_glyph = 1;
438 size_t capacity_growth = bx::min<size_t>(10, dif);
450 (uint8_t*)vertex_buffer_.data(),
451 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
452 sizeof(text_vertex));
454 set_vertex(vertex_count_ + 0, x0, y0, background_color_);
455 set_vertex(vertex_count_ + 1, x0, y1, background_color_);
456 set_vertex(vertex_count_ + 2, x1, y1, background_color_);
457 set_vertex(vertex_count_ + 3, x1, y0, background_color_);
459 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
460 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
461 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
462 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
463 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
464 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
467 buffers_dirty_ =
true;
481 line_start_index_ = 0;
485 previous_code_point_ = 0;
486 rectangle_.
width = 0;
490void text_buffer::append_glyph(font_handle
handle,
code_point codepoint,
bool shadow)
492 if(codepoint == L
'\t')
494 for(uint32_t ii = 0; ii < 4; ++ii)
496 append_glyph(
handle, L
' ', shadow);
502 BX_WARN(NULL != glyph,
"Glyph not found (font handle %d, code point %d)",
handle.idx, codepoint);
505 previous_code_point_ = 0;
512 size_t max_quads_per_glyph = 6;
514 size_t capacity_growth = bx::min<size_t>(10, dif);
520 if(codepoint == L
'\n')
522 line_gap_ =
font.line_gap;
523 line_descender_ =
font.descender;
524 line_ascender_ =
font.ascender;
525 line_start_index_ = vertex_count_;
526 previous_code_point_ = 0;
528 pen_y_ += line_gap_ + line_ascender_ - line_descender_;
533 if(
font.ascender > line_ascender_ || (
font.descender < line_descender_))
535 if(
font.descender < line_descender_)
537 line_descender_ =
font.descender;
538 line_gap_ =
font.line_gap;
541 float txtDecals = (
font.ascender - line_ascender_);
542 line_ascender_ =
font.ascender;
543 line_gap_ =
font.line_gap;
544 vertical_center_last_line((txtDecals),
545 (pen_y_ - line_ascender_),
546 (pen_y_ + line_ascender_ - line_descender_ + line_gap_));
549 float kerning = 0.0f;
558 const AtlasRegion& atlasRegion = atlas->getRegion(glyph->region_index);
560 const bool is_drop_shadow_font =
563 if((shadow || !is_drop_shadow_font) && style_flags_ &
style_background && background_color_ & 0xff000000)
565 float x0 = pen_x_ - kerning;
567 float x1 = x0 + glyph->advance_x;
568 float y1 = pen_y_ + line_ascender_ - line_descender_ + line_gap_;
570 atlas->packUV(whiteGlyph.region_index,
571 (uint8_t*)vertex_buffer_.data(),
572 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
573 sizeof(text_vertex));
580 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
581 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
582 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
583 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
584 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
585 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
588 buffers_dirty_ =
true;
596 float extra_x_offset = drop_shadow_offset_[0] *
font.scale;
597 float extra_y_offset = drop_shadow_offset_[1] *
font.scale;
599 uint32_t adjusted_drop_shadow_color =
600 ((((drop_shadow_color_ & 0xff000000) >> 8) * (text_color_ >> 24)) & 0xff000000) |
601 (drop_shadow_color_ & 0x00ffffff);
603 const uint8_t shadowA = (drop_shadow_color_ >> 24) & 0xFF;
605 if(shadowA > 0 || std::fabs(extra_x_offset) > 1e-6f || std::fabs(extra_y_offset) > 1e-6f)
607 float x0 = pen_x_ + glyph->offset_x + extra_x_offset;
608 float y0 = pen_y_ + line_ascender_ + glyph->offset_y + extra_y_offset;
609 float x1 = x0 + glyph->width;
610 float y1 = y0 + glyph->height;
612 bx::memSet(&vertex_buffer_[vertex_count_], 0,
sizeof(text_vertex) * 4);
614 atlas->packUV(glyph->region_index,
615 (uint8_t*)vertex_buffer_.data(),
616 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u2),
617 sizeof(text_vertex));
619 set_vertex(vertex_count_ + 0, x0, y0, adjusted_drop_shadow_color);
620 set_vertex(vertex_count_ + 1, x0, y1, adjusted_drop_shadow_color);
621 set_vertex(vertex_count_ + 2, x1, y1, adjusted_drop_shadow_color);
622 set_vertex(vertex_count_ + 3, x1, y0, adjusted_drop_shadow_color);
624 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
625 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
626 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
627 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
628 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
629 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
632 buffers_dirty_ =
true;
637 pen_x_ += glyph->advance_x;
639 float lineWidth = pen_x_ - origin_x_;
640 if(lineWidth > rectangle_.
width)
642 rectangle_.
width = lineWidth;
645 float lineHeight = pen_y_ + line_ascender_ - line_descender_ + line_gap_;
646 if(lineHeight > rectangle_.
height)
648 rectangle_.
height = lineHeight;
651 previous_code_point_ = codepoint;
658 float x0 = pen_x_ - kerning;
659 float y0 = pen_y_ + line_ascender_ - line_descender_ * 0.5f;
660 float x1 = x0 + glyph->advance_x;
661 float y1 = y0 +
font.underline_thickness;
663 atlas->packUV(whiteGlyph.region_index,
664 (uint8_t*)vertex_buffer_.data(),
665 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
666 sizeof(text_vertex));
668 set_vertex(vertex_count_ + 0, x0, y0, underline_color_,
style_underline);
669 set_vertex(vertex_count_ + 1, x0, y1, underline_color_,
style_underline);
670 set_vertex(vertex_count_ + 2, x1, y1, underline_color_,
style_underline);
671 set_vertex(vertex_count_ + 3, x1, y0, underline_color_,
style_underline);
673 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
674 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
675 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
676 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
677 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
678 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
681 buffers_dirty_ =
true;
687 float x0 = pen_x_ - kerning;
689 float x1 = x0 + glyph->advance_x;
690 float y1 = y0 +
font.underline_thickness;
692 atlas->packUV(whiteGlyph.region_index,
693 (uint8_t*)vertex_buffer_.data(),
694 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
695 sizeof(text_vertex));
697 set_vertex(vertex_count_ + 0, x0, y0, overline_color_,
style_overline);
698 set_vertex(vertex_count_ + 1, x0, y1, overline_color_,
style_overline);
699 set_vertex(vertex_count_ + 2, x1, y1, overline_color_,
style_overline);
700 set_vertex(vertex_count_ + 3, x1, y0, overline_color_,
style_overline);
702 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
703 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
704 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
705 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
706 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
707 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
710 buffers_dirty_ =
true;
716 bx::memSet(&vertex_buffer_[vertex_count_], 0,
sizeof(text_vertex) * 4);
718 atlas->packUV(glyph->region_index,
719 (uint8_t*)vertex_buffer_.data(),
720 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u1),
721 sizeof(text_vertex));
723 float glyph_scale = glyph->bitmap_scale;
724 float glyph_width = glyph->width * glyph_scale;
725 float glyph_height = glyph->height * glyph_scale;
726 float x0 = pen_x_ + glyph->offset_x;
727 float y0 = pen_y_ + (
font.ascender + -
font.descender - glyph_height) / 2;
728 float x1 = x0 + glyph_width;
729 float y1 = y0 + glyph_height;
731 set_vertex(vertex_count_ + 0, x0, y0, text_color_);
732 set_vertex(vertex_count_ + 1, x0, y1, text_color_);
733 set_vertex(vertex_count_ + 2, x1, y1, text_color_);
734 set_vertex(vertex_count_ + 3, x1, y0, text_color_);
738 bx::memSet(&vertex_buffer_[vertex_count_], 0,
sizeof(text_vertex) * 4);
740 atlas->packUV(glyph->region_index,
741 (uint8_t*)vertex_buffer_.data(),
742 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
743 sizeof(text_vertex));
745 float x0 = pen_x_ + glyph->offset_x;
746 float y0 = pen_y_ + line_ascender_ + glyph->offset_y;
747 float x1 = x0 + glyph->width;
748 float y1 = y0 + glyph->height;
750 set_vertex(vertex_count_ + 0, x0, y0, text_color_);
751 set_vertex(vertex_count_ + 1, x0, y1, text_color_);
752 set_vertex(vertex_count_ + 2, x1, y1, text_color_);
753 set_vertex(vertex_count_ + 3, x1, y0, text_color_);
761 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
762 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
763 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
764 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
765 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
766 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
769 buffers_dirty_ =
true;
774 float x0 = pen_x_ - kerning;
776 float x1 = x0 + glyph->advance_x;
777 float y1 = pen_y_ + line_ascender_ - line_descender_ + line_gap_;
779 atlas->packUV(whiteGlyph.region_index,
780 (uint8_t*)vertex_buffer_.data(),
781 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
782 sizeof(text_vertex));
789 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
790 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
791 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
792 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
793 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
794 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
797 buffers_dirty_ =
true;
803 float x0 = pen_x_ - kerning;
804 float y0 = pen_y_ + 0.666667f *
font.ascender;
805 float x1 = x0 + glyph->advance_x;
806 float y1 = y0 +
font.underline_thickness;
808 atlas->packUV(whiteGlyph.region_index,
809 (uint8_t*)vertex_buffer_.data(),
810 sizeof(text_vertex) * vertex_count_ + offsetof(text_vertex, u),
811 sizeof(text_vertex));
818 index_buffer_[index_count_ + 0] = vertex_count_ + 0;
819 index_buffer_[index_count_ + 1] = vertex_count_ + 1;
820 index_buffer_[index_count_ + 2] = vertex_count_ + 2;
821 index_buffer_[index_count_ + 3] = vertex_count_ + 0;
822 index_buffer_[index_count_ + 4] = vertex_count_ + 2;
823 index_buffer_[index_count_ + 5] = vertex_count_ + 3;
826 buffers_dirty_ =
true;
830 pen_x_ += glyph->advance_x;
832 float line_width = pen_x_ - origin_x_;
833 if(line_width > rectangle_.
width)
835 rectangle_.
width = line_width;
838 float line_height = pen_y_ + line_ascender_ - line_descender_ + line_gap_;
839 if(line_height > rectangle_.
height)
841 rectangle_.
height = line_height;
844 previous_code_point_ = codepoint;
847void text_buffer::vertical_center_last_line(
float dy,
float top,
float bottom)
849 for(uint32_t ii = line_start_index_; ii < vertex_count_; ii += 4)
853 vertex_buffer_[ii + 0].y =
top;
854 vertex_buffer_[ii + 1].y =
bottom;
855 vertex_buffer_[ii + 2].y =
bottom;
856 vertex_buffer_[ii + 3].y =
top;
860 vertex_buffer_[ii + 0].y += dy;
861 vertex_buffer_[ii + 1].y += dy;
862 vertex_buffer_[ii + 2].y += dy;
863 vertex_buffer_[ii + 3].y += dy;
870 bgfx::RendererType::Enum
type = bgfx::getRendererType();
872 basic_program_ = bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_basic"),
873 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_basic"),
877 bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field"),
878 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field"),
881 distance_subpixel_program_ =
882 bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_subpixel"),
883 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_subpixel"),
886 distance_drop_shadow_program_ =
887 bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_drop_shadow"),
888 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_drop_shadow"),
891 distance_drop_shadow_image_program_ = bgfx::createProgram(
892 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_drop_shadow_image"),
893 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_drop_shadow_image"),
896 distance_outline_program_ =
897 bgfx::createProgram(bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_outline"),
898 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_outline"),
901 distance_outline_image_program_ = bgfx::createProgram(
902 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_outline_image"),
903 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_outline_image"),
906 distance_outline_drop_shadow_image_program_ = bgfx::createProgram(
907 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"vs_font_distance_field_outline_drop_shadow_image"),
908 bgfx::createEmbeddedShader(s_embedded_shaders,
type,
"fs_font_distance_field_outline_drop_shadow_image"),
911 vertex_layout_.begin()
912 .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
913 .add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Int16,
true)
914 .add(bgfx::Attrib::TexCoord1, 4, bgfx::AttribType::Int16,
true)
915 .add(bgfx::Attrib::TexCoord2, 4, bgfx::AttribType::Int16,
true)
916 .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8,
true)
917 .add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Uint8,
true)
920 s_tex_color_ = bgfx::createUniform(
"s_texColor", bgfx::UniformType::Sampler);
921 u_drop_shadow_color_ = bgfx::createUniform(
"u_dropShadowColor", bgfx::UniformType::Vec4);
922 u_params_ = bgfx::createUniform(
"u_params", bgfx::UniformType::Vec4);
927 BX_ASSERT(text_buffer_handles_.getNumHandles() == 0,
928 "All the text buffers must be destroyed before destroying the manager");
929 delete[] text_buffers_;
931 bgfx::destroy(u_params_);
933 bgfx::destroy(u_drop_shadow_color_);
934 bgfx::destroy(s_tex_color_);
936 bgfx::destroy(basic_program_);
937 bgfx::destroy(distance_program_);
938 bgfx::destroy(distance_subpixel_program_);
939 bgfx::destroy(distance_outline_program_);
940 bgfx::destroy(distance_outline_image_program_);
941 bgfx::destroy(distance_drop_shadow_program_);
942 bgfx::destroy(distance_drop_shadow_image_program_);
943 bgfx::destroy(distance_outline_drop_shadow_image_program_);
948 uint16_t text_idx = text_buffer_handles_.alloc();
949 buffer_cache& bc = text_buffers_[text_idx];
954 bc.index_buffer_handle_idx = bgfx::kInvalidHandle;
955 bc.vertex_buffer_handle_idx = bgfx::kInvalidHandle;
957 text_buffer_handle ret = {text_idx};
965 buffer_cache& bc = text_buffers_[
handle.idx];
966 text_buffer_handles_.free(
handle.idx);
970 if(bc.vertex_buffer_handle_idx == bgfx::kInvalidHandle)
979 bgfx::IndexBufferHandle ibh;
980 bgfx::VertexBufferHandle vbh;
981 ibh.idx = bc.index_buffer_handle_idx;
982 vbh.idx = bc.vertex_buffer_handle_idx;
990 bgfx::DynamicIndexBufferHandle ibh;
991 bgfx::DynamicVertexBufferHandle vbh;
992 ibh.idx = bc.index_buffer_handle_idx;
993 vbh.idx = bc.vertex_buffer_handle_idx;
1005 font_handle fhandle,
1012 buffer_cache& bc = text_buffers_[
handle.idx];
1017 if(0 == index_size || 0 == vertex_size)
1022 bgfx::setTexture(0, s_tex_color_, font_manager_->
get_atlas(fhandle)->getTextureHandle());
1024 bgfx::ProgramHandle
program = BGFX_INVALID_HANDLE;
1025 switch(bc.font_type)
1029 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1030 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1036 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1037 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1039 float params[4] = {0.0f, (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f, 0.0f, 0.0f};
1040 bgfx::setUniform(u_params_, ¶ms);
1045 program = distance_subpixel_program_;
1046 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1047 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_INV_SRC_COLOR),
1053 program = distance_outline_program_;
1054 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1055 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1057 float params[4] = {0.0f,
1058 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1061 bgfx::setUniform(u_params_, ¶ms);
1067 program = distance_outline_image_program_;
1068 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1069 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1071 float params[4] = {0.0f,
1072 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1075 bgfx::setUniform(u_params_, ¶ms);
1081 program = distance_drop_shadow_program_;
1082 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1083 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1086 float drop_shadow_color_vec[4] = {((drop_shadow_color >> 16) & 0xff) / 255.0f,
1087 ((drop_shadow_color >> 8) & 0xff) / 255.0f,
1088 (drop_shadow_color & 0xff) / 255.0f,
1089 (drop_shadow_color >> 24) / 255.0f};
1090 bgfx::setUniform(u_drop_shadow_color_, &drop_shadow_color_vec);
1092 float params[4] = {0.0f,
1093 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1096 bgfx::setUniform(u_params_, ¶ms);
1102 program = distance_drop_shadow_image_program_;
1103 bgfx::setState(state | BGFX_STATE_WRITE_RGB |
1104 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1107 float drop_shadow_color_vec[4] = {((drop_shadow_color >> 16) & 0xff) / 255.0f,
1108 ((drop_shadow_color >> 8) & 0xff) / 255.0f,
1109 (drop_shadow_color & 0xff) / 255.0f,
1110 (drop_shadow_color >> 24) / 255.0f};
1111 bgfx::setUniform(u_drop_shadow_color_, &drop_shadow_color_vec);
1113 float params[4] = {0.0f,
1114 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1117 bgfx::setUniform(u_params_, ¶ms);
1123 program = distance_outline_drop_shadow_image_program_;
1124 bgfx::setState(state | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_RGB |
1125 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
1128 float drop_shadow_color_vec[4] = {((drop_shadow_color >> 16) & 0xff) / 255.0f,
1129 ((drop_shadow_color >> 8) & 0xff) / 255.0f,
1130 (drop_shadow_color & 0xff) / 255.0f,
1131 (drop_shadow_color >> 24) / 255.0f};
1132 bgfx::setUniform(u_drop_shadow_color_, &drop_shadow_color_vec);
1134 float params[4] = {0.0f,
1135 (float)font_manager_->
get_atlas(fhandle)->getTextureSize() / 512.0f,
1138 bgfx::setUniform(u_params_, ¶ms);
1150 bgfx::IndexBufferHandle ibh;
1151 bgfx::VertexBufferHandle vbh;
1153 if(bgfx::kInvalidHandle == bc.vertex_buffer_handle_idx)
1155 ibh = bgfx::createIndexBuffer(bgfx::copy(bc.buffer->
get_index_buffer(), index_size));
1157 vbh = bgfx::createVertexBuffer(bgfx::copy(bc.buffer->
get_vertex_buffer(), vertex_size), vertex_layout_);
1159 bc.vertex_buffer_handle_idx = vbh.idx;
1160 bc.index_buffer_handle_idx = ibh.idx;
1164 vbh.idx = bc.vertex_buffer_handle_idx;
1165 ibh.idx = bc.index_buffer_handle_idx;
1175 bgfx::DynamicIndexBufferHandle ibh;
1176 bgfx::DynamicVertexBufferHandle vbh;
1178 if(bgfx::kInvalidHandle == bc.vertex_buffer_handle_idx)
1180 ibh = bgfx::createDynamicIndexBuffer(bgfx::copy(bc.buffer->
get_index_buffer(), index_size),
1181 BGFX_BUFFER_ALLOW_RESIZE);
1183 vbh = bgfx::createDynamicVertexBuffer(bgfx::copy(bc.buffer->
get_vertex_buffer(), vertex_size),
1185 BGFX_BUFFER_ALLOW_RESIZE);
1187 bc.index_buffer_handle_idx = ibh.idx;
1188 bc.vertex_buffer_handle_idx = vbh.idx;
1192 ibh.idx = bc.index_buffer_handle_idx;
1193 vbh.idx = bc.vertex_buffer_handle_idx;
1195 bgfx::update(ibh, 0, bgfx::copy(bc.buffer->
get_index_buffer(), index_size));
1200 ibh.idx = bc.index_buffer_handle_idx;
1201 vbh.idx = bc.vertex_buffer_handle_idx;
1210 bgfx::TransientIndexBuffer tib;
1211 bgfx::TransientVertexBuffer tvb;
1213 bgfx::allocTransientVertexBuffer(&tvb, bc.buffer->
get_vertex_count(), vertex_layout_);
1222 bgfx::submit(
id,
program, depth);
1230 buffer_cache& bc = text_buffers_[
handle.idx];
1237 buffer_cache& bc = text_buffers_[
handle.idx];
1244 buffer_cache& bc = text_buffers_[
handle.idx];
1251 buffer_cache& bc = text_buffers_[
handle.idx];
1258 buffer_cache& bc = text_buffers_[
handle.idx];
1265 buffer_cache& bc = text_buffers_[
handle.idx];
1272 buffer_cache& bc = text_buffers_[
handle.idx];
1279 buffer_cache& bc = text_buffers_[
handle.idx];
1286 buffer_cache& bc = text_buffers_[
handle.idx];
1293 buffer_cache& bc = text_buffers_[
handle.idx];
1300 buffer_cache& bc = text_buffers_[
handle.idx];
1307 buffer_cache& bc = text_buffers_[
handle.idx];
1314 buffer_cache& bc = text_buffers_[
handle.idx];
1321 buffer_cache& bc = text_buffers_[
handle.idx];
1328 buffer_cache& bc = text_buffers_[
handle.idx];
1335 buffer_cache& bc = text_buffers_[
handle.idx];
1340 font_handle fhandle,
1341 const char* _string,
1345 buffer_cache& bc = text_buffers_[
handle.idx];
1350 font_handle fhandle,
1351 const wchar_t* _string,
1352 const wchar_t* _end)
1355 buffer_cache& bc = text_buffers_[
handle.idx];
1362 buffer_cache& bc = text_buffers_[
handle.idx];
1369 buffer_cache& bc = text_buffers_[
handle.idx];
1376 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)