source: mainline/uspace/lib/gfxfont/src/glyph.c@ 20d0098

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

Finish glyph bitmap operations and tests

Setting/getting pixel, opening/saving glyph bitmap.

  • Property mode set to 100644
File size: 7.2 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 Glyph
34 */
35
36#include <assert.h>
37#include <errno.h>
38#include <gfx/bitmap.h>
39#include <gfx/glyph.h>
40#include <io/pixelmap.h>
41#include <mem.h>
42#include <stdlib.h>
43#include <str.h>
44#include "../private/font.h"
45#include "../private/glyph.h"
46
47/** Initialize glyph metrics structure.
48 *
49 * Glyph metrics structure must always be initialized using this function
50 * first.
51 *
52 * @param metrics Glyph metrics structure
53 */
54void gfx_glyph_metrics_init(gfx_glyph_metrics_t *metrics)
55{
56 memset(metrics, 0, sizeof(gfx_glyph_metrics_t));
57}
58
59/** Create glyph.
60 *
61 * @param font Containing font
62 * @param metrics Glyph metrics
63 * @param rglyph Place to store pointer to new glyph
64 *
65 * @return EOK on success, EINVAL if parameters are invald,
66 * ENOMEM if insufficient resources, EIO if graphic device connection
67 * was lost
68 */
69errno_t gfx_glyph_create(gfx_font_t *font, gfx_glyph_metrics_t *metrics,
70 gfx_glyph_t **rglyph)
71{
72 gfx_glyph_t *glyph;
73 errno_t rc;
74
75 glyph = calloc(1, sizeof(gfx_glyph_t));
76 if (glyph == NULL)
77 return ENOMEM;
78
79 glyph->font = font;
80
81 rc = gfx_glyph_set_metrics(glyph, metrics);
82 if (rc != EOK) {
83 assert(rc == EINVAL);
84 free(glyph);
85 return rc;
86 }
87
88 glyph->metrics = *metrics;
89 list_append(&glyph->lglyphs, &glyph->font->glyphs);
90 list_initialize(&glyph->patterns);
91 *rglyph = glyph;
92 return EOK;
93}
94
95/** Destroy glyph.
96 *
97 * @param glyph Glyph
98 */
99void gfx_glyph_destroy(gfx_glyph_t *glyph)
100{
101 list_remove(&glyph->lglyphs);
102 free(glyph);
103}
104
105/** Get glyph metrics.
106 *
107 * @param glyph Glyph
108 * @param metrics Place to store metrics
109 */
110void gfx_glyph_get_metrics(gfx_glyph_t *glyph, gfx_glyph_metrics_t *metrics)
111{
112 *metrics = glyph->metrics;
113}
114
115/** Set glyph metrics.
116 *
117 * @param glyph Glyph
118 * @param metrics Place to store metrics
119 * @return EOK on success, EINVAL if supplied metrics are invalid
120 */
121errno_t gfx_glyph_set_metrics(gfx_glyph_t *glyph, gfx_glyph_metrics_t *metrics)
122{
123 glyph->metrics = *metrics;
124 return EOK;
125}
126
127/** Set a pattern that the glyph will match.
128 *
129 * A glyph can match any number of patterns. Setting the same pattern
130 * again has no effect. The pattern is a simple (sub)string. Matching
131 * is done using maximum munch rule.
132 *
133 * @param glyph Glyph
134 * @param pattern Pattern
135 * @return EOK on success, ENOMEM if out of memory
136 */
137errno_t gfx_glyph_set_pattern(gfx_glyph_t *glyph, const char *pattern)
138{
139 gfx_glyph_pattern_t *pat;
140
141 pat = gfx_glyph_first_pattern(glyph);
142 while (pat != NULL) {
143 if (str_cmp(pat->text, pattern) == 0) {
144 /* Already set */
145 return EOK;
146 }
147
148 pat = gfx_glyph_next_pattern(pat);
149 }
150
151 pat = calloc(1, sizeof(gfx_glyph_pattern_t));
152 if (pat == NULL)
153 return ENOMEM;
154
155 pat->glyph = glyph;
156 pat->text = str_dup(pattern);
157 if (pat->text == NULL) {
158 free(pat);
159 return ENOMEM;
160 }
161
162 list_append(&pat->lpatterns, &glyph->patterns);
163 return EOK;
164}
165
166/** Clear a matching pattern from a glyph.
167 *
168 * Clearing a pattern that is not set has no effect.
169 *
170 * @param Glyph
171 * @param pattern Pattern
172 */
173void gfx_glyph_clear_pattern(gfx_glyph_t *glyph, const char *pattern)
174{
175 gfx_glyph_pattern_t *pat;
176
177 pat = gfx_glyph_first_pattern(glyph);
178 while (pat != NULL) {
179 if (str_cmp(pat->text, pattern) == 0) {
180 list_remove(&pat->lpatterns);
181 free(pat->text);
182 free(pat);
183 return;
184 }
185
186 pat = gfx_glyph_next_pattern(pat);
187 }
188}
189
190/** Determine if glyph maches the beginning of a string.
191 *
192 * @param glyph Glyph
193 * @param str String
194 * @param rsize Place to store number of bytes in the matching pattern
195 * @return @c true iff glyph matches the beginning of the string
196 */
197bool gfx_glyph_matches(gfx_glyph_t *glyph, const char *str, size_t *rsize)
198{
199 gfx_glyph_pattern_t *pat;
200
201 pat = gfx_glyph_first_pattern(glyph);
202 while (pat != NULL) {
203 if (str_test_prefix(str, pat->text)) {
204 *rsize = str_size(pat->text);
205 return true;
206 }
207
208 pat = gfx_glyph_next_pattern(pat);
209 }
210
211 return false;
212}
213
214/** Get first glyph pattern.
215 *
216 * @param glyph Glyph
217 * @return First pattern or @c NULL if there are none
218 */
219gfx_glyph_pattern_t *gfx_glyph_first_pattern(gfx_glyph_t *glyph)
220{
221 link_t *link;
222
223 link = list_first(&glyph->patterns);
224 if (link == NULL)
225 return NULL;
226
227 return list_get_instance(link, gfx_glyph_pattern_t, lpatterns);
228}
229
230/** Get next glyph pattern.
231 *
232 * @param cur Current pattern
233 * @return Next pattern or @c NULL if there are none
234 */
235gfx_glyph_pattern_t *gfx_glyph_next_pattern(gfx_glyph_pattern_t *cur)
236{
237 link_t *link;
238
239 link = list_next(&cur->lpatterns, &cur->glyph->patterns);
240 if (link == NULL)
241 return NULL;
242
243 return list_get_instance(link, gfx_glyph_pattern_t, lpatterns);
244}
245
246/** Return pattern string.
247 *
248 * @param pattern Pattern
249 * @return Pattern string (owned by @a pattern)
250 */
251const char *gfx_glyph_pattern_str(gfx_glyph_pattern_t *pattern)
252{
253 return pattern->text;
254}
255
256/** Transfer glyph to new font bitmap.
257 *
258 * @param glyph Glyph
259 * @param offs Offset in new font bitmap
260 * @param dest New font bitmap
261 * @param drect Bounding rectangle for @a dest
262 *
263 * @return EOK on success or an error code
264 */
265errno_t gfx_glyph_transfer(gfx_glyph_t *glyph, gfx_coord_t offs,
266 gfx_bitmap_t *dest, gfx_rect_t *drect)
267{
268 pixelmap_t smap;
269 pixelmap_t dmap;
270 gfx_bitmap_alloc_t salloc;
271 gfx_bitmap_alloc_t dalloc;
272 gfx_coord_t x, y;
273 pixel_t pixel;
274 errno_t rc;
275
276 rc = gfx_bitmap_get_alloc(glyph->font->bitmap, &salloc);
277 if (rc != EOK)
278 return rc;
279
280 rc = gfx_bitmap_get_alloc(dest, &dalloc);
281 if (rc != EOK)
282 return rc;
283
284 smap.width = glyph->font->rect.p1.x;
285 smap.height = glyph->font->rect.p1.y;
286 smap.data = salloc.pixels;
287
288 dmap.width = drect->p1.x;
289 dmap.height = drect->p1.y;
290 dmap.data = dalloc.pixels;
291
292 for (y = drect->p0.y; y < drect->p1.y; y++) {
293 for (x = drect->p0.x; x < drect->p1.x; x++) {
294 pixel = pixelmap_get_pixel(&smap, x, y);
295 pixelmap_put_pixel(&dmap, x + offs, y, pixel);
296 }
297 }
298
299 return EOK;
300}
301
302/** @}
303 */
Note: See TracBrowser for help on using the repository browser.