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

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

First attempt at printing text in text-mode via GFX

  • Property mode set to 100644
File size: 5.3 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/font.h>
39#include <gfx/glyph.h>
40#include <gfx/text.h>
41#include <io/pixelmap.h>
42#include <mem.h>
43#include <str.h>
44#include "../private/font.h"
45#include "../private/typeface.h"
46
47/** Initialize text formatting structure.
48 *
49 * Text formatting structure must always be initialized using this function
50 * first.
51 *
52 * @param fmt Text formatting structure
53 */
54void gfx_text_fmt_init(gfx_text_fmt_t *fmt)
55{
56 memset(fmt, 0, sizeof(gfx_text_fmt_t));
57}
58
59/** Compute text width.
60 *
61 * @param font Font
62 * @param str String
63 * @return Text width
64 */
65gfx_coord_t gfx_text_width(gfx_font_t *font, const char *str)
66{
67 gfx_glyph_metrics_t gmetrics;
68 size_t stradv;
69 const char *cp;
70 gfx_glyph_t *glyph;
71 gfx_coord_t width;
72 errno_t rc;
73
74 if ((font->finfo->props.flags & gff_text_mode) != 0)
75 return str_width(str);
76
77 width = 0;
78 cp = str;
79 while (*cp != '\0') {
80 rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
81 if (rc != EOK) {
82 ++cp;
83 continue;
84 }
85
86 gfx_glyph_get_metrics(glyph, &gmetrics);
87
88 cp += stradv;
89 width += gmetrics.advance;
90 }
91
92 return width;
93}
94
95/** Print string using text characters in text mode.
96 *
97 * @param font Font
98 * @param pos Position of top-left corner of text
99 * @param str String
100 * @return EOK on success or an error code
101 */
102static errno_t gfx_puttext_textmode(gfx_font_t *font, gfx_coord2_t *pos,
103 const char *str)
104{
105 gfx_context_t *gc = font->typeface->gc;
106 gfx_bitmap_params_t params;
107 gfx_bitmap_t *bitmap;
108 gfx_bitmap_alloc_t alloc;
109 pixelmap_t pmap;
110 gfx_coord_t x;
111 pixel_t pixel;
112 errno_t rc;
113
114 /*
115 * NOTE: Creating and destroying bitmap each time is not probably
116 * the most efficient way.
117 */
118
119 gfx_bitmap_params_init(&params);
120 params.rect.p0.x = 0;
121 params.rect.p0.y = 0;
122 params.rect.p1.x = str_width(str);
123 params.rect.p1.y = 1;
124
125 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
126 if (rc != EOK)
127 return rc;
128
129 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
130 if (rc != EOK) {
131 gfx_bitmap_destroy(bitmap);
132 return rc;
133 }
134
135 pmap.width = params.rect.p1.x;
136 pmap.height = 1;
137 pmap.data = alloc.pixels;
138
139 for (x = 0; x < params.rect.p1.x; x++) {
140 pixel = PIXEL(str[x], 0xff, 0xff, 0xff);
141 pixelmap_put_pixel(&pmap, x, 0, pixel);
142 }
143
144 rc = gfx_bitmap_render(bitmap, NULL, pos);
145
146 gfx_bitmap_destroy(bitmap);
147 return rc;
148}
149
150/** Render text.
151 *
152 * @param font Font
153 * @param pos Anchor position
154 * @param fmt Text formatting
155 * @param str String
156 * @return EOK on success or an error code
157 */
158errno_t gfx_puttext(gfx_font_t *font, gfx_coord2_t *pos,
159 gfx_text_fmt_t *fmt, const char *str)
160{
161 gfx_font_metrics_t fmetrics;
162 gfx_glyph_metrics_t gmetrics;
163 size_t stradv;
164 const char *cp;
165 gfx_glyph_t *glyph;
166 gfx_coord2_t cpos;
167 gfx_coord_t width;
168 errno_t rc;
169
170 cpos = *pos;
171
172 /* Adjust position for horizontal alignment */
173 if (fmt->halign != gfx_halign_left) {
174 width = gfx_text_width(font, str);
175 switch (fmt->halign) {
176 case gfx_halign_center:
177 cpos.x -= width / 2;
178 break;
179 case gfx_halign_right:
180 cpos.x -= width;
181 break;
182 default:
183 break;
184 }
185 }
186
187 /* Adjust position for vertical alignment */
188 gfx_font_get_metrics(font, &fmetrics);
189
190 if (fmt->valign != gfx_valign_baseline) {
191 switch (fmt->valign) {
192 case gfx_valign_top:
193 cpos.y += fmetrics.ascent;
194 break;
195 case gfx_valign_center:
196 cpos.y += fmetrics.ascent / 2;
197 break;
198 case gfx_valign_bottom:
199 cpos.y -= fmetrics.descent;
200 break;
201 default:
202 break;
203 }
204 }
205
206 /* Text mode */
207 if ((font->finfo->props.flags & gff_text_mode) != 0)
208 return gfx_puttext_textmode(font, &cpos, str);
209
210 cp = str;
211 while (*cp != '\0') {
212 rc = gfx_font_search_glyph(font, cp, &glyph, &stradv);
213 if (rc != EOK) {
214 ++cp;
215 continue;
216 }
217
218 gfx_glyph_get_metrics(glyph, &gmetrics);
219
220 rc = gfx_glyph_render(glyph, &cpos);
221 if (rc != EOK)
222 return rc;
223
224 cp += stradv;
225 cpos.x += gmetrics.advance;
226 }
227
228 return EOK;
229}
230
231/** @}
232 */
Note: See TracBrowser for help on using the repository browser.