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

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

Add text rendering routine and demo

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