mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 06:02:44 +00:00 
			
		
		
		
	LibWeb: Add propper rounding to PixelUnits::operator*
Also moves related constants into the class to make them accessible for tests.
This commit is contained in:
		
							parent
							
								
									4896ba11dc
								
							
						
					
					
						commit
						f9fc0505fb
					
				
					 3 changed files with 36 additions and 6 deletions
				
			
		|  | @ -39,6 +39,17 @@ TEST_CASE(multiplication1) | |||
|     CSSPixels b(4); | ||||
|     CSSPixels c = a * b; | ||||
|     EXPECT_EQ(c, CSSPixels(12)); | ||||
| 
 | ||||
|     // Temporary overflow
 | ||||
|     a = CSSPixels::from_raw(0xFFFF'FFFF >> (CSSPixels::fractional_bits + 1)); | ||||
|     b = 1; | ||||
|     EXPECT_EQ((a * b), a); | ||||
| 
 | ||||
|     // Rounding
 | ||||
|     a = CSSPixels::from_raw(0b01'000001); | ||||
|     b = CSSPixels::from_raw(0b01'100000); | ||||
|     EXPECT_EQ(a * b, CSSPixels(a.to_double() * b.to_double())); | ||||
|     EXPECT_EQ(a * -b, CSSPixels(a.to_double() * -b.to_double())); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE(addition2) | ||||
|  |  | |||
|  | @ -9,9 +9,6 @@ | |||
| 
 | ||||
| namespace Web { | ||||
| 
 | ||||
| static i32 const fractional_bits = 6; | ||||
| static constexpr i32 fixed_point_denominator = 1 << fractional_bits; | ||||
| 
 | ||||
| CSSPixels::CSSPixels(int value) | ||||
| { | ||||
|     m_value = value * fixed_point_denominator; | ||||
|  | @ -103,9 +100,26 @@ CSSPixels CSSPixels::operator-(CSSPixels const& other) const | |||
| 
 | ||||
| CSSPixels CSSPixels::operator*(CSSPixels const& other) const | ||||
| { | ||||
|     CSSPixels result; | ||||
|     result.set_raw_value((static_cast<i64>(raw_value()) * other.raw_value()) >> fractional_bits); | ||||
|     return result; | ||||
|     i64 value = raw_value(); | ||||
|     value *= other.raw_value(); | ||||
| 
 | ||||
|     int int_value = AK::clamp_to_int(value >> fractional_bits); | ||||
| 
 | ||||
|     // Rounding:
 | ||||
|     // If last bit cut off was 1:
 | ||||
|     if (value & (1u << (fractional_bits - 1))) { | ||||
|         // If the bit after was 1 as well
 | ||||
|         if (value & (radix_mask >> 2u)) { | ||||
|             // We need to round away from 0
 | ||||
|             int_value = Checked<int>::saturating_add(int_value, 1); | ||||
|         } else { | ||||
|             // Otherwise we round to the next even value
 | ||||
|             // Which means we add the least significant bit of the raw integer value
 | ||||
|             int_value = Checked<int>::saturating_add(int_value, int_value & 1); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return from_raw(int_value); | ||||
| } | ||||
| 
 | ||||
| CSSPixels CSSPixels::operator/(CSSPixels const& other) const | ||||
|  |  | |||
|  | @ -52,6 +52,11 @@ constexpr DevicePixels operator%(DevicePixels left, T right) { return left.value | |||
| /// See https://www.w3.org/TR/css-values-3/#reference-pixel
 | ||||
| class CSSPixels { | ||||
| public: | ||||
|     static constexpr i32 fractional_bits = 6; | ||||
|     static constexpr i32 fixed_point_denominator = 1 << fractional_bits; | ||||
| 
 | ||||
|     static constexpr i32 radix_mask = fixed_point_denominator - 1; | ||||
| 
 | ||||
|     CSSPixels() = default; | ||||
|     CSSPixels(int value); | ||||
|     CSSPixels(unsigned int value); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Hendiadyoin1
						Hendiadyoin1