1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Font rotation 4 * 5 * Copyright (C) 2005 Antonino Daplas <adaplas @pol.net> 6 * 7 * This file is subject to the terms and conditions of the GNU General Public 8 * License. See the file COPYING in the main directory of this archive for 9 * more details. 10 */ 11 12 #include <linux/errno.h> 13 #include <linux/export.h> 14 #include <linux/math.h> 15 #include <linux/overflow.h> 16 #include <linux/slab.h> 17 #include <linux/string.h> 18 19 #include "font.h" 20 21 /* number of bits per line */ 22 static unsigned int font_glyph_bit_pitch(unsigned int width) 23 { 24 return round_up(width, 8); 25 } 26 27 static unsigned int __font_glyph_pos(unsigned int x, unsigned int y, unsigned int bit_pitch, 28 unsigned int *bit) 29 { 30 unsigned int off = y * bit_pitch + x; 31 unsigned int bit_shift = off % 8; 32 33 *bit = 0x80 >> bit_shift; /* MSB has position 0, LSB has position 7 */ 34 35 return off / 8; 36 } 37 38 static bool font_glyph_test_bit(const unsigned char *glyph, unsigned int x, unsigned int y, 39 unsigned int bit_pitch) 40 { 41 unsigned int bit; 42 unsigned int i = __font_glyph_pos(x, y, bit_pitch, &bit); 43 44 return glyph[i] & bit; 45 } 46 47 static void font_glyph_set_bit(unsigned char *glyph, unsigned int x, unsigned int y, 48 unsigned int bit_pitch) 49 { 50 unsigned int bit; 51 unsigned int i = __font_glyph_pos(x, y, bit_pitch, &bit); 52 53 glyph[i] |= bit; 54 } 55 56 static void __font_glyph_rotate_90(const unsigned char *glyph, 57 unsigned int width, unsigned int height, 58 unsigned char *out) 59 { 60 unsigned int x, y; 61 unsigned int shift = (8 - (height % 8)) & 7; 62 unsigned int bit_pitch = font_glyph_bit_pitch(width); 63 unsigned int out_bit_pitch = font_glyph_bit_pitch(height); 64 65 for (y = 0; y < height; y++) { 66 for (x = 0; x < width; x++) { 67 if (font_glyph_test_bit(glyph, x, y, bit_pitch)) { 68 font_glyph_set_bit(out, out_bit_pitch - 1 - y - shift, x, 69 out_bit_pitch); 70 } 71 } 72 } 73 } 74 75 /** 76 * font_glyph_rotate_90 - Rotate a glyph pattern by 90° in clockwise direction 77 * @glyph: The glyph to rotate 78 * @width: The glyph width in bits per scanline 79 * @height: The number of scanlines in the glyph 80 * @out: The rotated glyph bitmap 81 * 82 * The parameters @width and @height refer to the input glyph given in @glyph. 83 * The caller has to provide the output buffer @out of sufficient size to hold 84 * the rotated glyph. Rotating by 90° flips the width and height for the output 85 * glyph. Depending on the glyph pitch, the size of the output glyph can be 86 * different than the size of the input. Callers have to take this into account 87 * when allocating the output memory. 88 */ 89 void font_glyph_rotate_90(const unsigned char *glyph, unsigned int width, unsigned int height, 90 unsigned char *out) 91 { 92 memset(out, 0, font_glyph_size(height, width)); /* flip width/height */ 93 94 __font_glyph_rotate_90(glyph, width, height, out); 95 } 96 EXPORT_SYMBOL_GPL(font_glyph_rotate_90); 97 98 static void __font_glyph_rotate_180(const unsigned char *glyph, 99 unsigned int width, unsigned int height, 100 unsigned char *out) 101 { 102 unsigned int x, y; 103 unsigned int shift = (8 - (width % 8)) & 7; 104 unsigned int bit_pitch = font_glyph_bit_pitch(width); 105 106 for (y = 0; y < height; y++) { 107 for (x = 0; x < width; x++) { 108 if (font_glyph_test_bit(glyph, x, y, bit_pitch)) { 109 font_glyph_set_bit(out, width - (1 + x + shift), height - (1 + y), 110 bit_pitch); 111 } 112 } 113 } 114 } 115 116 /** 117 * font_glyph_rotate_180 - Rotate a glyph pattern by 180° 118 * @glyph: The glyph to rotate 119 * @width: The glyph width in bits per scanline 120 * @height: The number of scanlines in the glyph 121 * @out: The rotated glyph bitmap 122 * 123 * The parameters @width and @height refer to the input glyph given in @glyph. 124 * The caller has to provide the output buffer @out of sufficient size to hold 125 * the rotated glyph. 126 */ 127 void font_glyph_rotate_180(const unsigned char *glyph, unsigned int width, unsigned int height, 128 unsigned char *out) 129 { 130 memset(out, 0, font_glyph_size(width, height)); 131 132 __font_glyph_rotate_180(glyph, width, height, out); 133 } 134 EXPORT_SYMBOL_GPL(font_glyph_rotate_180); 135 136 static void __font_glyph_rotate_270(const unsigned char *glyph, 137 unsigned int width, unsigned int height, 138 unsigned char *out) 139 { 140 unsigned int x, y; 141 unsigned int shift = (8 - (width % 8)) & 7; 142 unsigned int bit_pitch = font_glyph_bit_pitch(width); 143 unsigned int out_bit_pitch = font_glyph_bit_pitch(height); 144 145 for (y = 0; y < height; y++) { 146 for (x = 0; x < width; x++) { 147 if (font_glyph_test_bit(glyph, x, y, bit_pitch)) 148 font_glyph_set_bit(out, y, bit_pitch - 1 - x - shift, 149 out_bit_pitch); 150 } 151 } 152 } 153 154 /** 155 * font_glyph_rotate_270 - Rotate a glyph pattern by 270° in clockwise direction 156 * @glyph: The glyph to rotate 157 * @width: The glyph width in bits per scanline 158 * @height: The number of scanlines in the glyph 159 * @out: The rotated glyph bitmap 160 * 161 * The parameters @width and @height refer to the input glyph given in @glyph. 162 * The caller has to provide the output buffer @out of sufficient size to hold 163 * the rotated glyph. Rotating by 270° flips the width and height for the output 164 * glyph. Depending on the glyph pitch, the size of the output glyph can be 165 * different than the size of the input. Callers have to take this into account 166 * when allocating the output memory. 167 */ 168 void font_glyph_rotate_270(const unsigned char *glyph, unsigned int width, unsigned int height, 169 unsigned char *out) 170 { 171 memset(out, 0, font_glyph_size(height, width)); /* flip width/height */ 172 173 __font_glyph_rotate_270(glyph, width, height, out); 174 } 175 EXPORT_SYMBOL_GPL(font_glyph_rotate_270); 176 177 /** 178 * font_data_rotate - Rotate font data by multiples of 90° 179 * @fd: The font data to rotate 180 * @width: The glyph width in bits per scanline 181 * @height: The number of scanlines in the glyph 182 * @charcount: The number of glyphs in the font 183 * @steps: Number of rotation steps of 90° 184 * @buf: Preallocated output buffer; can be NULL 185 * @bufsize: The size of @buf in bytes; can be NULL 186 * 187 * The parameters @width and @height refer to the visible number of pixels 188 * and scanlines in a single glyph. The number of glyphs is given in @charcount. 189 * Rotation happens in steps of 90°. The @steps parameter can have any value, 190 * but only 0 to 3 produce distinct results. With 4 or higher, a full rotation 191 * has been performed. You can pass any value for @steps and the helper will 192 * perform the appropriate rotation. Note that the returned buffer is not 193 * compatible with font_data_t. It only contains glyph data in the same format 194 * as returned by font_data_buf(). Callers are responsible to free the returned 195 * buffer with kfree(). Font rotation typically happens when displays get 196 * re-oriented. To avoid unnecessary re-allocation of the memory buffer, the 197 * caller can pass in an earlier result buffer in @buf for reuse. The old and 198 * new buffer sizes are given and retrieved by the caller in @bufsize. The 199 * allocation semantics are compatible with krealloc(). 200 * 201 * Returns: 202 * A buffer with rotated glyphs on success, or an error pointer otherwise 203 */ 204 unsigned char *font_data_rotate(font_data_t *fd, unsigned int width, unsigned int height, 205 unsigned int charcount, unsigned int steps, 206 unsigned char *buf, size_t *bufsize) 207 { 208 const unsigned char *src = font_data_buf(fd); 209 unsigned int s_cellsize = font_glyph_size(width, height); 210 unsigned int d_cellsize, i; 211 unsigned char *dst; 212 size_t size; 213 214 steps %= 4; 215 216 switch (steps) { 217 case 0: 218 case 2: 219 d_cellsize = s_cellsize; 220 break; 221 case 1: 222 case 3: 223 d_cellsize = font_glyph_size(height, width); /* flip width/height */ 224 break; 225 } 226 227 if (check_mul_overflow(charcount, d_cellsize, &size)) 228 return ERR_PTR(-EINVAL); 229 230 if (!buf || !bufsize || size > *bufsize) { 231 dst = kmalloc_array(charcount, d_cellsize, GFP_KERNEL); 232 if (!dst) 233 return ERR_PTR(-ENOMEM); 234 235 kfree(buf); 236 buf = dst; 237 if (bufsize) 238 *bufsize = size; 239 } else { 240 dst = buf; 241 } 242 243 switch (steps) { 244 case 0: 245 memcpy(dst, src, size); 246 break; 247 case 1: 248 memset(dst, 0, size); 249 for (i = 0; i < charcount; ++i) { 250 __font_glyph_rotate_90(src, width, height, dst); 251 src += s_cellsize; 252 dst += d_cellsize; 253 } 254 break; 255 case 2: 256 memset(dst, 0, size); 257 for (i = 0; i < charcount; ++i) { 258 __font_glyph_rotate_180(src, width, height, dst); 259 src += s_cellsize; 260 dst += d_cellsize; 261 } 262 break; 263 case 3: 264 memset(dst, 0, size); 265 for (i = 0; i < charcount; ++i) { 266 __font_glyph_rotate_270(src, width, height, dst); 267 src += s_cellsize; 268 dst += d_cellsize; 269 } 270 break; 271 } 272 273 return buf; 274 } 275 EXPORT_SYMBOL_GPL(font_data_rotate); 276