MeshUtilities.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "../../Include/RmlUi/Core/MeshUtilities.h"
  2. #include "../../Include/RmlUi/Core/Box.h"
  3. #include "../../Include/RmlUi/Core/Core.h"
  4. #include "../../Include/RmlUi/Core/FontEngineInterface.h"
  5. #include "../../Include/RmlUi/Core/Types.h"
  6. #include "GeometryBackgroundBorder.h"
  7. namespace Rml {
  8. void MeshUtilities::GenerateQuad(Mesh& mesh, Vector2f origin, Vector2f dimensions, ColourbPremultiplied colour)
  9. {
  10. GenerateQuad(mesh, origin, dimensions, colour, Vector2f(0, 0), Vector2f(1, 1));
  11. }
  12. void MeshUtilities::GenerateQuad(Mesh& mesh, Vector2f origin, Vector2f dimensions, ColourbPremultiplied colour, Vector2f top_left_texcoord,
  13. Vector2f bottom_right_texcoord)
  14. {
  15. const int v0 = (int)mesh.vertices.size();
  16. const int i0 = (int)mesh.indices.size();
  17. mesh.vertices.resize(mesh.vertices.size() + 4);
  18. mesh.indices.resize(mesh.indices.size() + 6);
  19. Vertex* vertices = mesh.vertices.data();
  20. int* indices = mesh.indices.data();
  21. vertices[v0 + 0].position = origin;
  22. vertices[v0 + 0].colour = colour;
  23. vertices[v0 + 0].tex_coord = top_left_texcoord;
  24. vertices[v0 + 1].position = Vector2f(origin.x + dimensions.x, origin.y);
  25. vertices[v0 + 1].colour = colour;
  26. vertices[v0 + 1].tex_coord = Vector2f(bottom_right_texcoord.x, top_left_texcoord.y);
  27. vertices[v0 + 2].position = origin + dimensions;
  28. vertices[v0 + 2].colour = colour;
  29. vertices[v0 + 2].tex_coord = bottom_right_texcoord;
  30. vertices[v0 + 3].position = Vector2f(origin.x, origin.y + dimensions.y);
  31. vertices[v0 + 3].colour = colour;
  32. vertices[v0 + 3].tex_coord = Vector2f(top_left_texcoord.x, bottom_right_texcoord.y);
  33. indices[i0 + 0] = v0 + 0;
  34. indices[i0 + 1] = v0 + 3;
  35. indices[i0 + 2] = v0 + 1;
  36. indices[i0 + 3] = v0 + 1;
  37. indices[i0 + 4] = v0 + 3;
  38. indices[i0 + 5] = v0 + 2;
  39. }
  40. void MeshUtilities::GenerateLine(Mesh& mesh, Vector2f position, Vector2f size, ColourbPremultiplied color)
  41. {
  42. Math::SnapToPixelGrid(position, size);
  43. MeshUtilities::GenerateQuad(mesh, position, size, color);
  44. }
  45. void MeshUtilities::GenerateBackgroundBorder(Mesh& out_mesh, const RenderBox& render_box, ColourbPremultiplied background_color,
  46. const ColourbPremultiplied border_colors[4])
  47. {
  48. RMLUI_ASSERT(border_colors);
  49. Vector<Vertex>& vertices = out_mesh.vertices;
  50. Vector<int>& indices = out_mesh.indices;
  51. const EdgeSizes& border_widths = render_box.GetBorderWidths();
  52. int num_borders = 0;
  53. for (int i = 0; i < 4; i++)
  54. if (border_colors[i].alpha > 0 && border_widths[i] > 0)
  55. num_borders += 1;
  56. const Vector2f fill_size = render_box.GetFillSize();
  57. const bool has_background = (background_color.alpha > 0 && fill_size.x > 0 && fill_size.y > 0);
  58. const bool has_border = (num_borders > 0);
  59. if (!has_background && !has_border)
  60. return;
  61. // Reserve geometry. A conservative estimate, does not take border-radii into account and assumes same-colored borders.
  62. const int estimated_num_vertices = 4 * int(has_background) + 2 * num_borders;
  63. const int estimated_num_triangles = 2 * int(has_background) + 2 * num_borders;
  64. vertices.reserve((int)vertices.size() + estimated_num_vertices);
  65. indices.reserve((int)indices.size() + 3 * estimated_num_triangles);
  66. // Generate the geometry.
  67. GeometryBackgroundBorder geometry(vertices, indices);
  68. const BorderMetrics metrics =
  69. GeometryBackgroundBorder::ComputeBorderMetrics(render_box.GetBorderOffset(), border_widths, fill_size, render_box.GetBorderRadius());
  70. if (has_background)
  71. geometry.DrawBackground(metrics, background_color);
  72. if (has_border)
  73. geometry.DrawBorder(metrics, border_widths, border_colors);
  74. #if 0
  75. // Debug draw vertices
  76. if (render_box.border_radius != CornerSizes{})
  77. {
  78. const int num_vertices = (int)vertices.size();
  79. const int num_indices = (int)indices.size();
  80. vertices.reserve(num_vertices + 4 * num_vertices);
  81. indices.reserve(num_indices + 6 * num_indices);
  82. for (int i = 0; i < num_vertices; i++)
  83. MeshUtilities::GenerateQuad(out_mesh, vertices[i].position, Vector2f(3, 3), ColourbPremultiplied(255, 0, (i % 2) == 0 ? 0 : 255));
  84. }
  85. #endif
  86. #ifdef RMLUI_DEBUG
  87. const int num_vertices = (int)vertices.size();
  88. for (int index : indices)
  89. {
  90. RMLUI_ASSERT(index < num_vertices);
  91. }
  92. #endif
  93. }
  94. void MeshUtilities::GenerateBackground(Mesh& out_mesh, const RenderBox& render_box, ColourbPremultiplied color)
  95. {
  96. const Vector2f fill_size = render_box.GetFillSize();
  97. const bool has_background = (color.alpha > 0 && fill_size.x > 0 && fill_size.y > 0);
  98. if (!has_background)
  99. return;
  100. const BorderMetrics metrics = GeometryBackgroundBorder::ComputeBorderMetrics(render_box.GetBorderOffset(), render_box.GetBorderWidths(),
  101. fill_size, render_box.GetBorderRadius());
  102. Vector<Vertex>& vertices = out_mesh.vertices;
  103. Vector<int>& indices = out_mesh.indices;
  104. // Reserve geometry. A conservative estimate, does not take border-radii into account.
  105. vertices.reserve((int)vertices.size() + 4);
  106. indices.reserve((int)indices.size() + 6);
  107. // Generate the geometry
  108. GeometryBackgroundBorder geometry(vertices, indices);
  109. geometry.DrawBackground(metrics, color);
  110. }
  111. } // namespace Rml