ftsdfcommon.c (3485B)
1 /**************************************************************************** 2 * 3 * ftsdfcommon.c 4 * 5 * Auxiliary data for Signed Distance Field support (body). 6 * 7 * Copyright (C) 2020-2025 by 8 * David Turner, Robert Wilhelm, and Werner Lemberg. 9 * 10 * Written by Anuj Verma. 11 * 12 * This file is part of the FreeType project, and may only be used, 13 * modified, and distributed under the terms of the FreeType project 14 * license, LICENSE.TXT. By continuing to use, modify, or distribute 15 * this file you indicate that you have read the license and 16 * understand and accept it fully. 17 * 18 */ 19 20 21 #include "ftsdf.h" 22 #include "ftsdfcommon.h" 23 24 25 /************************************************************************** 26 * 27 * format and sign manipulating functions 28 * 29 */ 30 31 /* 32 * Convert 16.16 fixed-point values to the desired output format. 33 * In this case we reduce 16.16 fixed-point values to normalized 34 * 8-bit values. 35 * 36 * The `max_value` in the parameter is the maximum value in the 37 * distance field map and is equal to the spread. We normalize 38 * the distances using this value instead of computing the maximum 39 * value for the entire bitmap. 40 * 41 * You can use this function to map the 16.16 signed values to any 42 * format required. Do note that the output buffer is 8-bit, so only 43 * use an 8-bit format for `FT_SDFFormat`, or increase the buffer size in 44 * `ftsdfrend.c`. 45 */ 46 FT_LOCAL_DEF( FT_SDFFormat ) 47 map_fixed_to_sdf( FT_16D16 dist, 48 FT_16D16 max_value ) 49 { 50 FT_SDFFormat out; 51 FT_16D16 udist; 52 53 54 /* normalize the distance values */ 55 dist = FT_DivFix( dist, max_value ); 56 57 udist = dist < 0 ? -dist : dist; 58 59 /* Reduce the distance values to 8 bits. */ 60 /* */ 61 /* Since +1/-1 in 16.16 takes the 16th bit, we right-shift */ 62 /* the number by 9 to make it fit into the 7-bit range. */ 63 /* */ 64 /* One bit is reserved for the sign. */ 65 udist >>= 9; 66 67 /* Since `char` can only store a maximum positive value */ 68 /* of 127 we need to make sure it does not wrap around and */ 69 /* give a negative value. */ 70 if ( dist > 0 && udist > 127 ) 71 udist = 127; 72 if ( dist < 0 && udist > 128 ) 73 udist = 128; 74 75 /* Output the data; negative values are from [0, 127] and positive */ 76 /* from [128, 255]. One important thing is that negative values */ 77 /* are inverted here, that means [0, 128] maps to [-128, 0] linearly. */ 78 /* More on that in `freetype.h` near the documentation of */ 79 /* `FT_RENDER_MODE_SDF`. */ 80 out = dist < 0 ? 128 - (FT_SDFFormat)udist 81 : (FT_SDFFormat)udist + 128; 82 83 return out; 84 } 85 86 87 /* 88 * Invert the signed distance packed into the corresponding format. 89 * So if the values are negative they will become positive in the 90 * chosen format. 91 * 92 * [Note]: This function should only be used after converting the 93 * 16.16 signed distance values to `FT_SDFFormat`. If that 94 * conversion has not been done, then simply invert the sign 95 * and use the above function to pack the values. 96 */ 97 FT_LOCAL_DEF( FT_SDFFormat ) 98 invert_sign( FT_SDFFormat dist ) 99 { 100 return 255 - dist; 101 } 102 103 104 /* END */