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

Last change on this file was 211fd68, checked in by Jiri Svoboda <jiri@…>, 17 months ago

Add text mode support to Barber

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