source: mainline/uspace/app/fontedit/fontedit.c@ b9be9b0

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

Puttext needs to know the color of the text being printed

So far we were using the GC's current drawing color. But unless there
was a way to read it, we could not render text-mode text in the correct
color.

  • Property mode set to 100644
File size: 19.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 fontedit
30 * @{
31 */
32/** @file Font editor
33 */
34
35#include <fibril.h>
36#include <gfx/color.h>
37#include <gfx/font.h>
38#include <gfx/glyph.h>
39#include <gfx/render.h>
40#include <gfx/text.h>
41#include <gfx/typeface.h>
42#include <stdbool.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <str.h>
46#include <ui/ui.h>
47#include <ui/wdecor.h>
48#include <ui/window.h>
49#include "fontedit.h"
50
51enum {
52 glyph_scale = 8,
53 glyph_orig_x = 100,
54 glyph_orig_y = 200
55};
56
57static errno_t font_edit_paint(font_edit_t *);
58
59static void font_edit_close_event(ui_window_t *, void *);
60static void font_edit_kbd_event(ui_window_t *, void *, kbd_event_t *);
61static void font_edit_pos_event(ui_window_t *, void *, pos_event_t *);
62
63static ui_window_cb_t font_edit_window_cb = {
64 .close = font_edit_close_event,
65 .kbd = font_edit_kbd_event,
66 .pos = font_edit_pos_event
67};
68
69/** Clear screen.
70 *
71 * @param gc Graphic context
72 * @param w Screen width
73 * @param h Screen height
74 */
75static errno_t clear_scr(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
76{
77 gfx_color_t *color = NULL;
78 gfx_rect_t rect;
79 errno_t rc;
80
81 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
82 if (rc != EOK)
83 goto error;
84
85 rc = gfx_set_color(gc, color);
86 if (rc != EOK)
87 goto error;
88
89 rect.p0.x = 0;
90 rect.p0.y = 0;
91 rect.p1.x = w;
92 rect.p1.y = h;
93
94 rc = gfx_fill_rect(gc, &rect);
95 if (rc != EOK)
96 goto error;
97
98 gfx_color_delete(color);
99 return EOK;
100error:
101 if (color != NULL)
102 gfx_color_delete(color);
103 return rc;
104}
105
106/** Adjust advance of the current glyph.
107 *
108 * @param fedit Font editor
109 */
110static void font_edit_adjust_advance(font_edit_t *fedit, gfx_coord_t change)
111{
112 gfx_glyph_metrics_t gmetrics;
113
114 gfx_glyph_get_metrics(fedit->glyph, &gmetrics);
115 gmetrics.advance += change;
116 (void) gfx_glyph_set_metrics(fedit->glyph, &gmetrics);
117
118 font_edit_paint(fedit);
119}
120
121/** Adjust font ascent.
122 *
123 * @param fedit Font editor
124 */
125static void font_edit_adjust_ascent(font_edit_t *fedit, gfx_coord_t change)
126{
127 gfx_font_metrics_t fmetrics;
128
129 gfx_font_get_metrics(fedit->font, &fmetrics);
130 fmetrics.ascent += change;
131 (void) gfx_font_set_metrics(fedit->font, &fmetrics);
132
133 printf("New ascent: %d\n", fmetrics.ascent);
134 font_edit_paint(fedit);
135}
136
137/** Adjust font descent.
138 *
139 * @param fedit Font editor
140 */
141static void font_edit_adjust_descent(font_edit_t *fedit, gfx_coord_t change)
142{
143 gfx_font_metrics_t fmetrics;
144
145 gfx_font_get_metrics(fedit->font, &fmetrics);
146 fmetrics.descent += change;
147 (void) gfx_font_set_metrics(fedit->font, &fmetrics);
148
149 printf("New descent: %d\n", fmetrics.descent);
150 font_edit_paint(fedit);
151}
152
153/** Adjust font leading.
154 *
155 * @param fedit Font editor
156 */
157static void font_edit_adjust_leading(font_edit_t *fedit, gfx_coord_t change)
158{
159 gfx_font_metrics_t fmetrics;
160
161 gfx_font_get_metrics(fedit->font, &fmetrics);
162 fmetrics.leading += change;
163 (void) gfx_font_set_metrics(fedit->font, &fmetrics);
164
165 printf("New leading: %d\n", fmetrics.leading);
166 font_edit_paint(fedit);
167}
168
169/** Handle font editor close event.
170 *
171 * @param window Window
172 * @param arg Argument (font_edit_t *)
173 */
174static void font_edit_close_event(ui_window_t *window, void *arg)
175{
176 font_edit_t *fedit = (font_edit_t *) arg;
177
178 ui_quit(fedit->ui);
179}
180
181/** Handle font editor position event.
182 *
183 * @param window Window
184 * @param arg Argument (font_edit_t *)
185 * @param event Position event
186 */
187static void font_edit_pos_event(ui_window_t *window, void *arg,
188 pos_event_t *event)
189{
190 font_edit_t *fedit = (font_edit_t *) arg;
191 gfx_coord2_t pos;
192 gfx_rect_t rect;
193 int x, y;
194
195 ui_window_get_app_rect(window, &rect);
196
197 pos.x = event->hpos;
198 pos.y = event->vpos;
199
200 if (event->type != POS_PRESS)
201 return;
202
203 if (!gfx_pix_inside_rect(&pos, &rect))
204 return;
205
206 x = gfx_coord_div_rneg(pos.x - glyph_orig_x -
207 rect.p0.x, glyph_scale);
208 y = gfx_coord_div_rneg(pos.y - glyph_orig_y -
209 rect.p0.y, glyph_scale);
210
211 printf("x=%d y=%d\n", x, y);
212 gfx_glyph_bmp_setpix(fedit->gbmp, x, y, fedit->pen_color);
213 font_edit_paint(fedit);
214}
215
216/** Duplicate previously selected glyph to the current glyph.
217 *
218 * @param fedit Font editor
219 */
220static void font_edit_copy_paste(font_edit_t *fedit)
221{
222 gfx_glyph_bmp_t *src_bmp;
223 gfx_glyph_metrics_t gmetrics;
224 gfx_rect_t rect;
225 gfx_coord_t x, y;
226 int pix;
227 errno_t rc;
228
229 /* If source and destination are the same, there is nothing to do. */
230 if (fedit->glyph == fedit->src_glyph)
231 return;
232
233 rc = gfx_glyph_bmp_open(fedit->src_glyph, &src_bmp);
234 if (rc != EOK) {
235 printf("Error opening source glyph.\n");
236 return;
237 }
238
239 gfx_glyph_bmp_get_rect(src_bmp, &rect);
240
241 rc = gfx_glyph_bmp_clear(fedit->gbmp);
242 if (rc != EOK) {
243 printf("Error clearing glyph bitmap.\n");
244 return;
245 }
246
247 for (y = rect.p0.y; y < rect.p1.y; y++) {
248 for (x = rect.p0.x; x < rect.p1.x; x++) {
249 pix = gfx_glyph_bmp_getpix(src_bmp, x, y);
250 rc = gfx_glyph_bmp_setpix(fedit->gbmp, x, y, pix);
251 if (rc != EOK) {
252 printf("Error setting pixel.\n");
253 return;
254 }
255 }
256 }
257
258 /* Copy metrics over */
259 gfx_glyph_get_metrics(fedit->src_glyph, &gmetrics);
260 (void) gfx_glyph_set_metrics(fedit->glyph, &gmetrics);
261
262 font_edit_paint(fedit);
263
264}
265
266/** Handle font editor control-key press.
267 *
268 * @param widget Canvas widget
269 * @param data Position event
270 */
271static void font_edit_ctrl_key(font_edit_t *fedit, kbd_event_t *event)
272{
273 errno_t rc;
274
275 switch (event->key) {
276 case KC_S:
277 printf("Save!\n");
278 (void) gfx_glyph_bmp_save(fedit->gbmp);
279 rc = gfx_typeface_save(fedit->typeface, fedit->fname);
280 if (rc != EOK)
281 printf("Error saving typeface.\n");
282 font_edit_paint(fedit);
283 break;
284 case KC_1:
285 printf("Set pixels\n");
286 fedit->pen_color = 1;
287 break;
288 case KC_2:
289 printf("Clear pixels\n");
290 fedit->pen_color = 0;
291 break;
292 case KC_3:
293 font_edit_adjust_advance(fedit, -1);
294 break;
295 case KC_4:
296 font_edit_adjust_advance(fedit, +1);
297 break;
298 case KC_5:
299 font_edit_adjust_ascent(fedit, -1);
300 break;
301 case KC_6:
302 font_edit_adjust_ascent(fedit, +1);
303 break;
304 case KC_7:
305 font_edit_adjust_descent(fedit, -1);
306 break;
307 case KC_8:
308 font_edit_adjust_descent(fedit, +1);
309 break;
310 case KC_9:
311 font_edit_adjust_leading(fedit, -1);
312 break;
313 case KC_0:
314 font_edit_adjust_leading(fedit, +1);
315 break;
316 case KC_X:
317 (void) gfx_glyph_bmp_clear(fedit->gbmp);
318 font_edit_paint(fedit);
319 break;
320 case KC_C:
321 /* Select source glyph for copying */
322 fedit->src_glyph = fedit->glyph;
323 break;
324 case KC_V:
325 /* Duplicate another glyph */
326 font_edit_copy_paste(fedit);
327 break;
328 default:
329 break;
330 }
331}
332
333/** Handle font editor unmodified key press.
334 *
335 * @param widget Canvas widget
336 * @param data Position event
337 */
338static void font_edit_unmod_key(font_edit_t *fedit, kbd_event_t *event)
339{
340 char str[5];
341 gfx_glyph_metrics_t gmetrics;
342 gfx_glyph_t *glyph;
343 gfx_glyph_bmp_t *bmp;
344 size_t stradv;
345 errno_t rc;
346
347 if (event->c == '\0')
348 return;
349
350 printf("Character '%lc'\n", event->c);
351 snprintf(str, sizeof(str), "%lc", event->c);
352
353 rc = gfx_font_search_glyph(fedit->font, str, &glyph, &stradv);
354 if (rc == EOK) {
355 /* Found an existing glyph */
356 rc = gfx_glyph_bmp_open(glyph, &bmp);
357 if (rc != EOK) {
358 printf("Error opening glyph bitmap.\n");
359 return;
360 }
361
362 gfx_glyph_bmp_close(fedit->gbmp);
363 fedit->glyph = glyph;
364 fedit->gbmp = bmp;
365 font_edit_paint(fedit);
366 return;
367 }
368
369 /* Create new glyph */
370
371 gfx_glyph_metrics_init(&gmetrics);
372 rc = gfx_glyph_create(fedit->font, &gmetrics, &glyph);
373 if (rc != EOK) {
374 printf("Error creating glyph.\n");
375 goto error;
376 }
377
378 rc = gfx_glyph_set_pattern(glyph, str);
379 if (rc != EOK) {
380 printf("Error setting glyph pattern.\n");
381 goto error;
382 }
383
384 rc = gfx_glyph_bmp_open(glyph, &bmp);
385 if (rc != EOK) {
386 printf("Error opening glyph bitmap.\n");
387 goto error;
388 }
389
390 gfx_glyph_bmp_close(fedit->gbmp);
391 fedit->glyph = glyph;
392 fedit->gbmp = bmp;
393 font_edit_paint(fedit);
394 return;
395error:
396 if (glyph != NULL)
397 gfx_glyph_destroy(glyph);
398 return;
399}
400
401/** Handle font editor keyboard event.
402 *
403 * @param window Window
404 * @param arg Argument (font_edit_t *)
405 * @param event Keyboard event
406 */
407static void font_edit_kbd_event(ui_window_t *window, void *arg,
408 kbd_event_t *event)
409{
410 font_edit_t *fedit = (font_edit_t *) arg;
411
412 if (event->type != KEY_PRESS)
413 return;
414
415 if ((event->mods & KM_CTRL) != 0 &&
416 (event->mods & (KM_ALT | KM_SHIFT)) == 0) {
417 font_edit_ctrl_key(fedit, event);
418 } else if ((event->mods & (KM_CTRL | KM_ALT)) == 0) {
419 font_edit_unmod_key(fedit, event);
420 }
421}
422
423/** Convert glyph pixel coordinates to displayed rectangle.
424 *
425 * Since we upscale the glyph a pixel in the glyph corresponds to a rectangle
426 * on the screen.
427 *
428 * @param fedit Font editor
429 * @param x X coordinate in glyph
430 * @param y Y coordinate in glyph
431 * @param drect Place to store displayed rectangle coordinates
432 */
433static void font_edit_gpix_to_disp(font_edit_t *fedit, int x, int y,
434 gfx_rect_t *drect)
435{
436 (void) fedit;
437
438 drect->p0.x = glyph_orig_x + x * glyph_scale;
439 drect->p0.y = glyph_orig_y + y * glyph_scale;
440 drect->p1.x = glyph_orig_x + (x + 1) * glyph_scale;
441 drect->p1.y = glyph_orig_y + (y + 1) * glyph_scale;
442}
443
444/** Paint font preview string.
445 *
446 * @param fedit Font editor
447 * @param x Starting X coordinate
448 * @param y Starting Y coordinate
449 * @param color Color
450 * @param str String
451 */
452static errno_t font_edit_paint_preview_str(font_edit_t *fedit,
453 gfx_coord_t x, gfx_coord_t y, gfx_color_t *color, const char *str)
454{
455 gfx_text_fmt_t fmt;
456 gfx_coord2_t pos;
457
458 gfx_text_fmt_init(&fmt);
459 fmt.color = color;
460
461 pos.x = x;
462 pos.y = y;
463
464 return gfx_puttext(fedit->font, &pos, &fmt, str);
465}
466
467/** Paint font preview.
468 *
469 * @param fedit Font editor
470 */
471static errno_t font_edit_paint_preview(font_edit_t *fedit)
472{
473 gfx_color_t *color;
474 errno_t rc;
475
476 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
477 if (rc != EOK)
478 return rc;
479
480 rc = gfx_set_color(fedit->gc, color);
481 if (rc != EOK)
482 goto error;
483
484 rc = font_edit_paint_preview_str(fedit, 20, 20, color,
485 "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
486 if (rc != EOK)
487 goto error;
488
489 rc = font_edit_paint_preview_str(fedit, 20, 40, color,
490 "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG");
491 if (rc != EOK)
492 goto error;
493
494 rc = font_edit_paint_preview_str(fedit, 20, 60, color,
495 "abcdefghijklmnopqrstuvwxyz");
496 if (rc != EOK)
497 goto error;
498
499 rc = font_edit_paint_preview_str(fedit, 20, 80, color,
500 "the quick brown fox jumps over the lazy dog");
501 if (rc != EOK)
502 goto error;
503
504 rc = font_edit_paint_preview_str(fedit, 20, 100, color,
505 "0123456789,./<>?;'\\:\"|[]{}`~!@#$%^&*()-_=+");
506 if (rc != EOK)
507 goto error;
508
509 return EOK;
510error:
511 gfx_color_delete(color);
512 return rc;
513}
514
515/** Paint glyph bitmap.
516 *
517 * @param fedit Font editor
518 */
519static errno_t font_edit_paint_gbmp(font_edit_t *fedit)
520{
521 gfx_color_t *color = NULL;
522 gfx_rect_t rect;
523 gfx_rect_t grect;
524 gfx_font_metrics_t fmetrics;
525 gfx_glyph_metrics_t gmetrics;
526 errno_t rc;
527 int x, y;
528 int pix;
529
530 /* Display font baseline, ascent, descent, leading */
531
532 gfx_font_get_metrics(fedit->font, &fmetrics);
533
534 rc = gfx_color_new_rgb_i16(0, 0x4000, 0x4000, &color);
535 if (rc != EOK)
536 goto error;
537
538 rc = gfx_set_color(fedit->gc, color);
539 if (rc != EOK)
540 goto error;
541
542 font_edit_gpix_to_disp(fedit, 0, 0, &rect);
543 rect.p1.x += 100;
544
545 rc = gfx_fill_rect(fedit->gc, &rect);
546 if (rc != EOK)
547 goto error;
548
549 font_edit_gpix_to_disp(fedit, 0, -fmetrics.ascent, &rect);
550 rect.p1.x += 100;
551
552 rc = gfx_fill_rect(fedit->gc, &rect);
553 if (rc != EOK)
554 goto error;
555
556 font_edit_gpix_to_disp(fedit, 0, fmetrics.descent, &rect);
557 rect.p1.x += 100;
558
559 rc = gfx_fill_rect(fedit->gc, &rect);
560 if (rc != EOK)
561 goto error;
562
563 font_edit_gpix_to_disp(fedit, 0, fmetrics.descent +
564 fmetrics.leading, &rect);
565 rect.p1.x += 100;
566
567 rc = gfx_fill_rect(fedit->gc, &rect);
568 if (rc != EOK)
569 goto error;
570
571 gfx_color_delete(color);
572
573 /* Display glyph */
574
575 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
576 if (rc != EOK)
577 goto error;
578
579 rc = gfx_set_color(fedit->gc, color);
580 if (rc != EOK)
581 goto error;
582
583 gfx_glyph_bmp_get_rect(fedit->gbmp, &grect);
584 printf("grect=%d,%d,%d,%d\n", grect.p0.x, grect.p0.y,
585 grect.p1.x, grect.p1.y);
586
587 for (y = grect.p0.y; y < grect.p1.y; y++) {
588 for (x = grect.p0.x; x < grect.p1.x; x++) {
589 pix = gfx_glyph_bmp_getpix(fedit->gbmp, x, y);
590
591 if (pix != 0) {
592 font_edit_gpix_to_disp(fedit, x, y, &rect);
593
594 rc = gfx_fill_rect(fedit->gc, &rect);
595 if (rc != EOK)
596 goto error;
597 }
598 }
599 }
600
601 gfx_color_delete(color);
602
603 /* Display glyph origin and advance */
604
605 rc = gfx_color_new_rgb_i16(0, 0xffff, 0, &color);
606 if (rc != EOK)
607 goto error;
608
609 rc = gfx_set_color(fedit->gc, color);
610 if (rc != EOK)
611 goto error;
612
613 font_edit_gpix_to_disp(fedit, 0, 0, &rect);
614
615 rc = gfx_fill_rect(fedit->gc, &rect);
616 if (rc != EOK)
617 goto error;
618
619 gfx_glyph_get_metrics(fedit->glyph, &gmetrics);
620
621 font_edit_gpix_to_disp(fedit, gmetrics.advance, 0, &rect);
622
623 rc = gfx_fill_rect(fedit->gc, &rect);
624 if (rc != EOK)
625 goto error;
626
627 gfx_color_delete(color);
628
629 return EOK;
630error:
631 if (color != NULL)
632 gfx_color_delete(color);
633 return rc;
634}
635
636/** Paint font editor.
637 *
638 * @param fedit Font editor
639 */
640static errno_t font_edit_paint(font_edit_t *fedit)
641{
642 int w, h;
643 errno_t rc;
644
645 w = fedit->width;
646 h = fedit->height;
647
648 rc = clear_scr(fedit->gc, w, h);
649 if (rc != EOK)
650 return rc;
651
652 rc = font_edit_paint_gbmp(fedit);
653 if (rc != EOK)
654 return rc;
655
656 rc = font_edit_paint_preview(fedit);
657 if (rc != EOK)
658 return rc;
659
660 return EOK;
661}
662
663/** Create font editor.
664 *
665 * @param display_spec Display specifier
666 * @param fname Font file to open or @c NULL to create new font
667 * @param rfedit Place to store pointer to new font editor
668 * @return EOK on success or an error code
669 */
670static errno_t font_edit_create(const char *display_spec, const char *fname,
671 font_edit_t **rfedit)
672{
673 ui_t *ui = NULL;
674 ui_wnd_params_t params;
675 gfx_rect_t rect;
676 gfx_rect_t wrect;
677 gfx_coord2_t off;
678 ui_window_t *window = NULL;
679 gfx_context_t *gc = NULL;
680 font_edit_t *fedit = NULL;
681 gfx_typeface_t *tface = NULL;
682 gfx_font_t *font = NULL;
683 gfx_font_info_t *finfo;
684 gfx_font_props_t props;
685 gfx_font_metrics_t metrics;
686 gfx_glyph_metrics_t gmetrics;
687 gfx_glyph_t *glyph;
688 gfx_glyph_bmp_t *bmp;
689 gfx_coord_t vw, vh;
690 errno_t rc;
691
692 fedit = calloc(1, sizeof(font_edit_t));
693 if (fedit == NULL) {
694 rc = ENOMEM;
695 goto error;
696 }
697
698 printf("Init UI..\n");
699
700 rc = ui_create(display_spec, &ui);
701 if (rc != EOK) {
702 printf("Error initializing UI (%s)\n", display_spec);
703 goto error;
704 }
705
706 vw = 400;
707 vh = 300;
708
709 rect.p0.x = 0;
710 rect.p0.y = 0;
711 rect.p1.x = vw;
712 rect.p1.y = vh;
713
714 ui_wnd_params_init(&params);
715 params.caption = "Font Editor";
716
717 /*
718 * Compute window rectangle such that application area corresponds
719 * to rect
720 */
721 ui_wdecor_rect_from_app(params.style, &rect, &wrect);
722 off = wrect.p0;
723 gfx_rect_rtranslate(&off, &wrect, &params.rect);
724
725 rc = ui_window_create(ui, &params, &window);
726 if (rc != EOK) {
727 printf("Error creating window.\n");
728 goto error;
729 }
730
731 ui_window_set_cb(window, &font_edit_window_cb, (void *) fedit);
732
733 rc = ui_window_get_app_gc(window, &gc);
734 if (rc != EOK) {
735 printf("Error creating graphic context.\n");
736 goto error;
737 }
738
739 if (fname == NULL) {
740 rc = gfx_typeface_create(gc, &tface);
741 if (rc != EOK) {
742 printf("Error creating typeface.\n");
743 goto error;
744 }
745
746 gfx_font_props_init(&props);
747 gfx_font_metrics_init(&metrics);
748
749 rc = gfx_font_create(tface, &props, &metrics, &font);
750 if (rc != EOK) {
751 printf("Error creating font.\n");
752 goto error;
753 }
754
755 gfx_glyph_metrics_init(&gmetrics);
756
757 rc = gfx_glyph_create(font, &gmetrics, &glyph);
758 if (rc != EOK) {
759 printf("Error creating glyph.\n");
760 goto error;
761 }
762
763 rc = gfx_glyph_set_pattern(glyph, "A");
764 if (rc != EOK) {
765 printf("Error setting glyph pattern.\n");
766 goto error;
767 }
768 } else {
769 rc = gfx_typeface_open(gc, fname, &tface);
770 if (rc != EOK) {
771 printf("Error opening typeface '%s.\n",
772 fname);
773 goto error;
774 }
775
776 finfo = gfx_typeface_first_font(tface);
777 rc = gfx_font_open(finfo, &font);
778 if (rc != EOK) {
779 printf("Error opening font.\n");
780 goto error;
781 }
782
783 glyph = gfx_font_first_glyph(font);
784 }
785
786 rc = gfx_glyph_bmp_open(glyph, &bmp);
787 if (rc != EOK) {
788 printf("Error opening glyph bitmap.\n");
789 goto error;
790 }
791
792 if (fname == NULL)
793 fname = "new.tpf";
794
795 fedit->ui = ui;
796 fedit->window = window;
797 fedit->gc = gc;
798 fedit->width = vw;
799 fedit->height = vh;
800 fedit->pen_color = 1;
801 fedit->fname = fname;
802 fedit->typeface = tface;
803 fedit->font = font;
804 fedit->glyph = glyph;
805 fedit->gbmp = bmp;
806
807 *rfedit = fedit;
808 return EOK;
809error:
810 /*
811 * Once the window is created it would be probably more correct
812 * to leave destruction of these resources to a window destroy
813 * handler (which we have no way of registering)
814 */
815 if (bmp != NULL)
816 gfx_glyph_bmp_close(bmp);
817 if (glyph != NULL)
818 gfx_glyph_destroy(glyph);
819 if (font != NULL)
820 gfx_font_close(font);
821 if (tface != NULL)
822 gfx_typeface_destroy(tface);
823 if (window != NULL)
824 ui_window_destroy(window);
825 if (ui != NULL)
826 ui_destroy(ui);
827 if (fedit != NULL)
828 free(fedit);
829 return rc;
830}
831
832/** Destroy font editor.
833 *
834 * @param fedit Font editor
835 */
836static void font_edit_destroy(font_edit_t *fedit)
837{
838 gfx_glyph_bmp_close(fedit->gbmp);
839 gfx_glyph_destroy(fedit->glyph);
840 gfx_font_close(fedit->font);
841 gfx_typeface_destroy(fedit->typeface);
842 ui_window_destroy(fedit->window);
843 ui_destroy(fedit->ui);
844 free(fedit);
845}
846
847static void print_syntax(void)
848{
849 printf("Syntax: fontedit [-d <display-spec>] [<file.tpf>]\n");
850}
851
852int main(int argc, char *argv[])
853{
854 errno_t rc;
855 const char *display_spec = UI_DISPLAY_DEFAULT;
856 const char *fname = NULL;
857 font_edit_t *fedit;
858 int i;
859
860 i = 1;
861 while (i < argc && argv[i][0] == '-') {
862 if (str_cmp(argv[i], "-d") == 0) {
863 ++i;
864 if (i >= argc) {
865 printf("Argument missing.\n");
866 print_syntax();
867 return 1;
868 }
869
870 display_spec = argv[i++];
871 } else {
872 printf("Invalid option '%s'.\n", argv[i]);
873 print_syntax();
874 return 1;
875 }
876 }
877
878 /* File name argument? */
879 if (i < argc) {
880 fname = argv[i];
881 ++i;
882 }
883
884 /* Extra arguments? */
885 if (i < argc) {
886 printf("Unexpected argument '%s'.\n", argv[i]);
887 print_syntax();
888 return 1;
889 }
890
891 rc = font_edit_create(display_spec, fname, &fedit);
892 if (rc != EOK)
893 return 1;
894
895 (void) font_edit_paint(fedit);
896
897 ui_run(fedit->ui);
898 font_edit_destroy(fedit);
899
900 (void) font_edit_kbd_event;
901 (void) font_edit_pos_event;
902 return 0;
903}
904
905/** @}
906 */
Note: See TracBrowser for help on using the repository browser.