FontEffectBlur.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #include "FontEffectBlur.h"
  2. #include "../../Include/RmlUi/Core/PropertyDefinition.h"
  3. #include "Memory.h"
  4. namespace Rml {
  5. FontEffectBlur::FontEffectBlur()
  6. {
  7. width = 0;
  8. SetLayer(Layer::Back);
  9. }
  10. FontEffectBlur::~FontEffectBlur() {}
  11. bool FontEffectBlur::HasUniqueTexture() const
  12. {
  13. return true;
  14. }
  15. bool FontEffectBlur::Initialise(int _width)
  16. {
  17. if (_width <= 0)
  18. return false;
  19. width = _width;
  20. const float std_dev = .4f * float(width);
  21. const float two_variance = 2.f * std_dev * std_dev;
  22. const float gain = 1.f / Math::SquareRoot(Math::RMLUI_PI * two_variance);
  23. float sum_weight = 0.f;
  24. // We separate the blur filter into two passes, horizontal and vertical, for performance reasons.
  25. filter_x.Initialise(Vector2i(width, 0), FilterOperation::Sum);
  26. filter_y.Initialise(Vector2i(0, width), FilterOperation::Sum);
  27. for (int x = -width; x <= width; ++x)
  28. {
  29. float weight = gain * Math::Exp(-Math::SquareRoot(float(x * x) / two_variance));
  30. filter_x[0][x + width] = weight;
  31. filter_y[x + width][0] = weight;
  32. sum_weight += weight;
  33. }
  34. // Normalize the kernels
  35. for (int x = -width; x <= width; ++x)
  36. {
  37. filter_x[0][x + width] /= sum_weight;
  38. filter_y[x + width][0] /= sum_weight;
  39. }
  40. return true;
  41. }
  42. bool FontEffectBlur::GetGlyphMetrics(Vector2i& origin, Vector2i& dimensions, const FontGlyph& /*glyph*/) const
  43. {
  44. if (dimensions.x * dimensions.y > 0)
  45. {
  46. origin.x -= width;
  47. origin.y -= width;
  48. dimensions.y += 2 * width;
  49. dimensions.x += 2 * width;
  50. return true;
  51. }
  52. return false;
  53. }
  54. void FontEffectBlur::GenerateGlyphTexture(byte* destination_data, const Vector2i destination_dimensions, int destination_stride,
  55. const FontGlyph& glyph) const
  56. {
  57. const Vector2i buf_dimensions = destination_dimensions;
  58. const int buf_stride = buf_dimensions.x;
  59. const int buf_size = buf_dimensions.x * buf_dimensions.y;
  60. DynamicArray<byte, GlobalStackAllocator<byte>> x_output(buf_size);
  61. filter_x.Run(x_output.data(), buf_dimensions, buf_stride, ColorFormat::A8, glyph.bitmap_data, glyph.bitmap_dimensions, Vector2i(width),
  62. glyph.color_format);
  63. filter_y.Run(destination_data, destination_dimensions, destination_stride, ColorFormat::RGBA8, x_output.data(), buf_dimensions, Vector2i(0),
  64. ColorFormat::A8);
  65. FillColorValuesFromAlpha(destination_data, destination_dimensions, destination_stride);
  66. }
  67. FontEffectBlurInstancer::FontEffectBlurInstancer() : id_width(PropertyId::Invalid), id_color(PropertyId::Invalid)
  68. {
  69. id_width = RegisterProperty("width", "1px", true).AddParser("length").GetId();
  70. id_color = RegisterProperty("color", "white", false).AddParser("color").GetId();
  71. RegisterShorthand("font-effect", "width, color", ShorthandType::FallThrough);
  72. }
  73. FontEffectBlurInstancer::~FontEffectBlurInstancer() {}
  74. SharedPtr<FontEffect> FontEffectBlurInstancer::InstanceFontEffect(const String& /*name*/, const PropertyDictionary& properties)
  75. {
  76. float width = properties.GetProperty(id_width)->Get<float>();
  77. Colourb color = properties.GetProperty(id_color)->Get<Colourb>();
  78. auto font_effect = MakeShared<FontEffectBlur>();
  79. if (font_effect->Initialise(int(width)))
  80. {
  81. font_effect->SetColour(color);
  82. return font_effect;
  83. }
  84. return nullptr;
  85. }
  86. } // namespace Rml