source: mainline/uspace/lib/gfxfont/src/text.c@ d7f82635

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d7f82635 was 17fac946, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Fix gfx_puttext() failing with empty string in text mode

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2020 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libgfxfont
30 * @{
31 */
32/**
33 * @file Text rendering
34 */
35
36#include <errno.h>
37#include <gfx/bitmap.h>
38#include <gfx/color.h>
39#include <gfx/font.h>
40#include <gfx/glyph.h>
41#include <gfx/render.h>
42#include <gfx/text.h>
43#include <io/pixelmap.h>
44#include <mem.h>
45#include <str.h>
46#include "../private/font.h"
47#include "../private/typeface.h"
48
49/** Initialize text formatting structure.
50 *
51 * Text formatting structure must always be initialized using this function
52 * first.
53 *
54 * @param fmt Text formatting structure
55 */
56void gfx_text_fmt_init(gfx_text_fmt_t *fmt)
57{
58 memset(fmt, 0, sizeof(gfx_text_fmt_t));
59}
60
61/** Compute text width.
62 *
63 * @param font Font
64 * @param str String
65 * @return Text width
66 */
67gfx_coord_t gfx_text_width(gfx_font_t *font, const char *str)
68{
69 gfx_glyph_metrics_t gmetrics;
70 size_t stradv;
71 const char *cp;
72 gfx_glyph_t *glyph;
73 gfx_coord_t width;
74 errno_t rc;
75
76 if ((font->finfo->props.flags & gff_text_mode) != 0)
77 return str_width(str);
78
79 width = 0;
80 cp = str;
81 while (*cp != '\0') {
82 rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
83 if (rc != EOK) {
84 ++cp;
85 continue;
86 }
87
88 gfx_glyph_get_metrics(glyph, &gmetrics);
89
90 cp += stradv;
91 width += gmetrics.advance;
92 }
93
94 return width;
95}
96
97/** Print string using text characters in text mode.
98 *
99 * @param font Font
100 * @param pos Position of top-left corner of text
101 * @param color Text color
102 * @param str String
103 * @return EOK on success or an error code
104 */
105static errno_t gfx_puttext_textmode(gfx_font_t *font, gfx_coord2_t *pos,
106 gfx_color_t *color, const char *str)
107{
108 gfx_context_t *gc = font->typeface->gc;
109 gfx_bitmap_params_t params;
110 gfx_bitmap_t *bitmap;
111 gfx_bitmap_alloc_t alloc;
112 uint16_t r, g, b;
113 pixelmap_t pmap;
114 gfx_coord_t x;
115 pixel_t pixel;
116 errno_t rc;
117
118 /*
119 * NOTE: Creating and destroying bitmap each time is not probably
120 * the most efficient way.
121 */
122
123 gfx_color_get_rgb_i16(color, &r, &g, &b);
124
125 /*
126 * We are setting the *background* color, the foreground color
127 * will be set to its complement.
128 */
129 r = 0xff ^ (r >> 8);
130 g = 0xff ^ (g >> 8);
131 b = 0xff ^ (b >> 8);
132
133 gfx_bitmap_params_init(&params);
134 params.rect.p0.x = 0;
135 params.rect.p0.y = 0;
136 params.rect.p1.x = str_width(str);
137 params.rect.p1.y = 1;
138
139 if (params.rect.p1.x == 0) {
140 /* Nothing to do. Avoid creating bitmap of zero width. */
141 return EOK;
142 }
143
144 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
145 if (rc != EOK)
146 return rc;
147
148 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
149 if (rc != EOK) {
150 gfx_bitmap_destroy(bitmap);
151 return rc;
152 }
153
154 pmap.width = params.rect.p1.x;
155 pmap.height = 1;
156 pmap.data = alloc.pixels;
157
158 for (x = 0; x < params.rect.p1.x; x++) {
159 pixel = PIXEL(str[x], r, g, b);
160 pixelmap_put_pixel(&pmap, x, 0, pixel);
161 }
162
163 rc = gfx_bitmap_render(bitmap, NULL, pos);
164
165 gfx_bitmap_destroy(bitmap);
166 return rc;
167}
168
169/** Render text.
170 *
171 * @param font Font
172 * @param pos Anchor position
173 * @param fmt Text formatting
174 * @param str String
175 * @return EOK on success or an error code
176 */
177errno_t gfx_puttext(gfx_font_t *font, gfx_coord2_t *pos,
178 gfx_text_fmt_t *fmt, const char *str)
179{
180 gfx_font_metrics_t fmetrics;
181 gfx_glyph_metrics_t gmetrics;
182 size_t stradv;
183 const char *cp;
184 gfx_glyph_t *glyph;
185 gfx_coord2_t cpos;
186 gfx_coord_t width;
187 errno_t rc;
188
189 cpos = *pos;
190
191 /* Adjust position for horizontal alignment */
192 if (fmt->halign != gfx_halign_left) {
193 width = gfx_text_width(font, str);
194 switch (fmt->halign) {
195 case gfx_halign_center:
196 cpos.x -= width / 2;
197 break;
198 case gfx_halign_right:
199 cpos.x -= width - 1;
200 break;
201 default:
202 break;
203 }
204 }
205
206 /* Adjust position for vertical alignment */
207 gfx_font_get_metrics(font, &fmetrics);
208
209 if (fmt->valign != gfx_valign_baseline) {
210 switch (fmt->valign) {
211 case gfx_valign_top:
212 cpos.y += fmetrics.ascent;
213 break;
214 case gfx_valign_center:
215 cpos.y += fmetrics.ascent / 2;
216 break;
217 case gfx_valign_bottom:
218 cpos.y -= fmetrics.descent;
219 break;
220 default:
221 break;
222 }
223 }
224
225 /* Text mode */
226 if ((font->finfo->props.flags & gff_text_mode) != 0)
227 return gfx_puttext_textmode(font, &cpos, fmt->color, str);
228
229 rc = gfx_set_color(font->typeface->gc, fmt->color);
230 if (rc != EOK)
231 return rc;
232
233 cp = str;
234 while (*cp != '\0') {
235 rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
236 if (rc != EOK) {
237 ++cp;
238 continue;
239 }
240
241 gfx_glyph_get_metrics(glyph, &gmetrics);
242
243 rc = gfx_glyph_render(glyph, &cpos);
244 if (rc != EOK)
245 return rc;
246
247 cp += stradv;
248 cpos.x += gmetrics.advance;
249 }
250
251 return EOK;
252}
253
254/** @}
255 */
Note: See TracBrowser for help on using the repository browser.