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