xref: /linux/lib/fonts/font_rotate.c (revision bdfd943231347ce57133d1ba2d93ed87f1050e81)
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/export.h>
13 #include <linux/math.h>
14 #include <linux/string.h>
15 
16 #include "font.h"
17 
18 static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat)
19 {
20 	u32 tmp = (y * pitch) + x, index = tmp / 8,  bit = tmp % 8;
21 
22 	pat += index;
23 	return (*pat) & (0x80 >> bit);
24 }
25 
26 static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat)
27 {
28 	u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8;
29 
30 	pat += index;
31 
32 	(*pat) |= 0x80 >> bit;
33 }
34 
35 static inline void rotate_cw(const char *in, char *out, u32 width, u32 height)
36 {
37 	int i, j, h = height, w = width;
38 	int shift = (8 - (height % 8)) & 7;
39 
40 	width = (width + 7) & ~7;
41 	height = (height + 7) & ~7;
42 
43 	for (i = 0; i < h; i++) {
44 		for (j = 0; j < w; j++) {
45 			if (pattern_test_bit(j, i, width, in))
46 				pattern_set_bit(height - 1 - i - shift, j,
47 						height, out);
48 		}
49 	}
50 }
51 
52 /**
53  * font_glyph_rotate_90 - Rotate a glyph pattern by 90° in clockwise direction
54  * @glyph: The glyph to rotate
55  * @width: The glyph width in bits per scanline
56  * @height: The number of scanlines in the glyph
57  * @out: The rotated glyph bitmap
58  *
59  * The parameters @width and @height refer to the input glyph given in @glyph.
60  * The caller has to provide the output buffer @out of sufficient size to hold
61  * the rotated glyph. Rotating by 90° flips the width and height for the output
62  * glyph. Depending on the glyph pitch, the size of the output glyph can be
63  * different than the size of the input. Callers have to take this into account
64  * when allocating the output memory.
65  */
66 void font_glyph_rotate_90(const unsigned char *glyph, unsigned int width, unsigned int height,
67 			  unsigned char *out)
68 {
69 	memset(out, 0, font_glyph_size(height, width)); /* flip width/height */
70 
71 	rotate_cw(glyph, out, width, height);
72 }
73 EXPORT_SYMBOL_GPL(font_glyph_rotate_90);
74 
75 static inline void rotate_ud(const char *in, char *out, u32 width, u32 height)
76 {
77 	int i, j;
78 	int shift = (8 - (width % 8)) & 7;
79 
80 	width = (width + 7) & ~7;
81 
82 	for (i = 0; i < height; i++) {
83 		for (j = 0; j < width - shift; j++) {
84 			if (pattern_test_bit(j, i, width, in))
85 				pattern_set_bit(width - (1 + j + shift),
86 						height - (1 + i),
87 						width, out);
88 		}
89 	}
90 }
91 
92 /**
93  * font_glyph_rotate_180 - Rotate a glyph pattern by 180°
94  * @glyph: The glyph to rotate
95  * @width: The glyph width in bits per scanline
96  * @height: The number of scanlines in the glyph
97  * @out: The rotated glyph bitmap
98  *
99  * The parameters @width and @height refer to the input glyph given in @glyph.
100  * The caller has to provide the output buffer @out of sufficient size to hold
101  * the rotated glyph.
102  */
103 void font_glyph_rotate_180(const unsigned char *glyph, unsigned int width, unsigned int height,
104 			   unsigned char *out)
105 {
106 	memset(out, 0, font_glyph_size(width, height));
107 
108 	rotate_ud(glyph, out, width, height);
109 }
110 EXPORT_SYMBOL_GPL(font_glyph_rotate_180);
111 
112 static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height)
113 {
114 	int i, j, h = height, w = width;
115 	int shift = (8 - (width % 8)) & 7;
116 
117 	width = (width + 7) & ~7;
118 	height = (height + 7) & ~7;
119 
120 	for (i = 0; i < h; i++) {
121 		for (j = 0; j < w; j++) {
122 			if (pattern_test_bit(j, i, width, in))
123 				pattern_set_bit(i, width - 1 - j - shift,
124 						height, out);
125 		}
126 	}
127 }
128 
129 /**
130  * font_glyph_rotate_270 - Rotate a glyph pattern by 270° in clockwise direction
131  * @glyph: The glyph to rotate
132  * @width: The glyph width in bits per scanline
133  * @height: The number of scanlines in the glyph
134  * @out: The rotated glyph bitmap
135  *
136  * The parameters @width and @height refer to the input glyph given in @glyph.
137  * The caller has to provide the output buffer @out of sufficient size to hold
138  * the rotated glyph. Rotating by 270° flips the width and height for the output
139  * glyph. Depending on the glyph pitch, the size of the output glyph can be
140  * different than the size of the input. Callers have to take this into account
141  * when allocating the output memory.
142  */
143 void font_glyph_rotate_270(const unsigned char *glyph, unsigned int width, unsigned int height,
144 			   unsigned char *out)
145 {
146 	memset(out, 0, font_glyph_size(height, width)); /* flip width/height */
147 
148 	rotate_ccw(glyph, out, width, height);
149 }
150 EXPORT_SYMBOL_GPL(font_glyph_rotate_270);
151