Browse Source

Make font effects compatible with RGBA glyphs

Michael Ragazzon 3 years ago
parent
commit
a5821c5705

+ 3 - 1
Include/RmlUi/Core/ConvolutionFilter.h

@@ -79,7 +79,9 @@ public:
 	/// @param[in] source The opacity information for the source buffer.
 	/// @param[in] source The opacity information for the source buffer.
 	/// @param[in] source_dimensions The size of the source region (in pixels). The stride is assumed to be equivalent to the horizontal width.
 	/// @param[in] source_dimensions The size of the source region (in pixels). The stride is assumed to be equivalent to the horizontal width.
 	/// @param[in] source_offset The offset of the source region from the destination region. This is usually the same as the kernel size.
 	/// @param[in] source_offset The offset of the source region from the destination region. This is usually the same as the kernel size.
-	void Run(byte* destination, Vector2i destination_dimensions, int destination_stride, ColorFormat destination_color_format, const byte* source, Vector2i source_dimensions, Vector2i source_offset) const;
+	/// @param[in] source_color_format Determines the representation of the bytes in the source texture, only the alpha channel will be used.
+	void Run(byte* destination, Vector2i destination_dimensions, int destination_stride, ColorFormat destination_color_format, const byte* source,
+		Vector2i source_dimensions, Vector2i source_offset, ColorFormat source_color_format) const;
 
 
 private:
 private:
 	Vector2i kernel_size;
 	Vector2i kernel_size;

+ 15 - 16
Source/Core/ConvolutionFilter.cpp

@@ -54,8 +54,7 @@ bool ConvolutionFilter::Initialise(Vector2i _kernel_radii, FilterOperation _oper
 
 
 	kernel_size = _kernel_radii * 2 + Vector2i(1);
 	kernel_size = _kernel_radii * 2 + Vector2i(1);
 
 
-	kernel = UniquePtr<float[]>(new float[kernel_size.x * kernel_size.y]);
-	memset(kernel.get(), 0, kernel_size.x * kernel_size.y * sizeof(float));
+	kernel = UniquePtr<float[]>(new float[kernel_size.x * kernel_size.y]());
 
 
 	operation = _operation;
 	operation = _operation;
 	return true;
 	return true;
@@ -70,10 +69,17 @@ float* ConvolutionFilter::operator[](int kernel_y_index)
 	return kernel.get() + kernel_size.x * kernel_y_index;
 	return kernel.get() + kernel_size.x * kernel_y_index;
 }
 }
 
 
-void ConvolutionFilter::Run(byte* destination, const Vector2i destination_dimensions, const int destination_stride, const ColorFormat destination_color_format, const byte* source, const Vector2i source_dimensions, const Vector2i source_offset) const
+void ConvolutionFilter::Run(byte* destination, const Vector2i destination_dimensions, const int destination_stride,
+	const ColorFormat destination_color_format, const byte* source, const Vector2i source_dimensions, const Vector2i source_offset,
+	const ColorFormat source_color_format) const
 {
 {
 	RMLUI_ZoneScopedNC("ConvFilter::Run", 0xd6bf49);
 	RMLUI_ZoneScopedNC("ConvFilter::Run", 0xd6bf49);
 
 
+	const int destination_bytes_per_pixel = (destination_color_format == ColorFormat::RGBA8 ? 4 : 1);
+	const int destination_alpha_offset = (destination_color_format == ColorFormat::RGBA8 ? 3 : 0);
+	const int source_bytes_per_pixel = (source_color_format == ColorFormat::RGBA8 ? 4 : 1);
+	const int source_alpha_offset = (source_color_format == ColorFormat::RGBA8 ? 3 : 0);
+
 	const float initial_opacity = (operation == FilterOperation::Erosion ? FLT_MAX : 0.f);
 	const float initial_opacity = (operation == FilterOperation::Erosion ? FLT_MAX : 0.f);
 
 
 	const Vector2i kernel_radius = (kernel_size - Vector2i(1)) / 2;
 	const Vector2i kernel_radius = (kernel_size - Vector2i(1)) / 2;
@@ -86,20 +92,19 @@ void ConvolutionFilter::Run(byte* destination, const Vector2i destination_dimens
 
 
 			for (int kernel_y = 0; kernel_y < kernel_size.y; ++kernel_y)
 			for (int kernel_y = 0; kernel_y < kernel_size.y; ++kernel_y)
 			{
 			{
-				int source_y = y - source_offset.y - kernel_radius.y + kernel_y;
+				const int source_y = y - source_offset.y - kernel_radius.y + kernel_y;
 
 
 				for (int kernel_x = 0; kernel_x < kernel_size.x; ++kernel_x)
 				for (int kernel_x = 0; kernel_x < kernel_size.x; ++kernel_x)
 				{
 				{
-					float pixel_opacity;
+					float pixel_opacity = 0.f;
 
 
-					int source_x = x - source_offset.x - kernel_radius.x + kernel_x;
+					const int source_x = x - source_offset.x - kernel_radius.x + kernel_x;
 					if (source_y >= 0 && source_y < source_dimensions.y &&
 					if (source_y >= 0 && source_y < source_dimensions.y &&
 						source_x >= 0 && source_x < source_dimensions.x)
 						source_x >= 0 && source_x < source_dimensions.x)
 					{
 					{
-						pixel_opacity = float(source[source_y * source_dimensions.x + source_x]) * kernel[kernel_y * kernel_size.x + kernel_x];
+						const int source_index = (source_y * source_dimensions.x + source_x) * source_bytes_per_pixel + source_alpha_offset;
+						pixel_opacity = float(source[source_index]) * kernel[kernel_y * kernel_size.x + kernel_x];
 					}
 					}
-					else
-						pixel_opacity = 0;
 
 
 					switch (operation)
 					switch (operation)
 					{
 					{
@@ -112,13 +117,7 @@ void ConvolutionFilter::Run(byte* destination, const Vector2i destination_dimens
 
 
 			opacity = Math::Min(255.f, opacity);
 			opacity = Math::Min(255.f, opacity);
 
 
-			int destination_index = 0;
-			switch (destination_color_format)
-			{
-			case ColorFormat::RGBA8: destination_index = x * 4 + 3; break;
-			case ColorFormat::A8:    destination_index = x; break;
-			}
-
+			const int destination_index = x * destination_bytes_per_pixel + destination_alpha_offset;
 			destination[destination_index] = byte(opacity);
 			destination[destination_index] = byte(opacity);
 		}
 		}
 
 

+ 4 - 2
Source/Core/FontEffectBlur.cpp

@@ -108,9 +108,11 @@ void FontEffectBlur::GenerateGlyphTexture(byte* destination_data, const Vector2i
 	const int buf_size = buf_dimensions.x * buf_dimensions.y;
 	const int buf_size = buf_dimensions.x * buf_dimensions.y;
 	DynamicArray<byte, GlobalStackAllocator<byte>> x_output(buf_size);
 	DynamicArray<byte, GlobalStackAllocator<byte>> x_output(buf_size);
 
 
-	filter_x.Run(x_output.data(), buf_dimensions, buf_stride, ColorFormat::A8, glyph.bitmap_data, glyph.bitmap_dimensions, Vector2i(width));
+	filter_x.Run(x_output.data(), buf_dimensions, buf_stride, ColorFormat::A8, glyph.bitmap_data, glyph.bitmap_dimensions, Vector2i(width),
+		glyph.color_format);
 
 
-	filter_y.Run(destination_data, destination_dimensions, destination_stride, ColorFormat::RGBA8, x_output.data(), buf_dimensions, Vector2i(0));
+	filter_y.Run(destination_data, destination_dimensions, destination_stride, ColorFormat::RGBA8, x_output.data(), buf_dimensions, Vector2i(0),
+		ColorFormat::A8);
 }
 }
 
 
 
 

+ 6 - 3
Source/Core/FontEffectGlow.cpp

@@ -136,11 +136,14 @@ void FontEffectGlow::GenerateGlyphTexture(byte* destination_data, const Vector2i
 	DynamicArray<byte, GlobalStackAllocator<byte>> outline_output(buf_size);
 	DynamicArray<byte, GlobalStackAllocator<byte>> outline_output(buf_size);
 	DynamicArray<byte, GlobalStackAllocator<byte>> blur_x_output(buf_size);
 	DynamicArray<byte, GlobalStackAllocator<byte>> blur_x_output(buf_size);
 
 
-	filter_outline.Run(outline_output.data(), buf_dimensions, buf_stride, ColorFormat::A8, glyph.bitmap_data, glyph.bitmap_dimensions, Vector2i(combined_width));
+	filter_outline.Run(outline_output.data(), buf_dimensions, buf_stride, ColorFormat::A8, glyph.bitmap_data, glyph.bitmap_dimensions,
+		Vector2i(combined_width), glyph.color_format);
 	
 	
-	filter_blur_x.Run(blur_x_output.data(), buf_dimensions, buf_stride, ColorFormat::A8, outline_output.data(), buf_dimensions, Vector2i(0));
+	filter_blur_x.Run(blur_x_output.data(), buf_dimensions, buf_stride, ColorFormat::A8, outline_output.data(), buf_dimensions, Vector2i(0),
+		ColorFormat::A8);
 
 
-	filter_blur_y.Run(destination_data, destination_dimensions, destination_stride, ColorFormat::RGBA8, blur_x_output.data(), buf_dimensions, Vector2i(0));
+	filter_blur_y.Run(destination_data, destination_dimensions, destination_stride, ColorFormat::RGBA8, blur_x_output.data(), buf_dimensions,
+		Vector2i(0), ColorFormat::A8);
 }
 }
 
 
 
 

+ 2 - 1
Source/Core/FontEffectOutline.cpp

@@ -94,7 +94,8 @@ bool FontEffectOutline::GetGlyphMetrics(Vector2i& origin, Vector2i& dimensions,
 
 
 void FontEffectOutline::GenerateGlyphTexture(byte* destination_data, const Vector2i destination_dimensions, int destination_stride, const FontGlyph& glyph) const
 void FontEffectOutline::GenerateGlyphTexture(byte* destination_data, const Vector2i destination_dimensions, int destination_stride, const FontGlyph& glyph) const
 {
 {
-	filter.Run(destination_data, destination_dimensions, destination_stride, ColorFormat::RGBA8, glyph.bitmap_data, glyph.bitmap_dimensions, Vector2i(width));
+	filter.Run(destination_data, destination_dimensions, destination_stride, ColorFormat::RGBA8, glyph.bitmap_data, glyph.bitmap_dimensions,
+		Vector2i(width), glyph.color_format);
 }
 }
 
 
 
 

+ 4 - 2
Source/Core/FontEffectShadow.cpp

@@ -51,10 +51,12 @@ bool FontEffectShadow::HasUniqueTexture() const
 	return false;
 	return false;
 }
 }
 
 
-bool FontEffectShadow::GetGlyphMetrics(Vector2i& origin, Vector2i& RMLUI_UNUSED_PARAMETER(dimensions), const FontGlyph& RMLUI_UNUSED_PARAMETER(glyph)) const
+bool FontEffectShadow::GetGlyphMetrics(Vector2i& origin, Vector2i& RMLUI_UNUSED_PARAMETER(dimensions), const FontGlyph& glyph) const
 {
 {
 	RMLUI_UNUSED(dimensions);
 	RMLUI_UNUSED(dimensions);
-	RMLUI_UNUSED(glyph);
+
+	if (glyph.color_format == ColorFormat::RGBA8)
+		return false;
 
 
 	origin += offset;
 	origin += offset;
 	return true;
 	return true;