1
2 #include "studiox_includes.h"
3 #include "ft2build.h"
4 #include FT_FREETYPE_H
5 #include "gx_studio_font_util.h"
6
7 #ifdef _DEBUG
8 #define new DEBUG_NEW
9 #endif
10
11 typedef struct {
12 int ascent;
13 int descent;
14 int max_height;
15 } FONT_METRICS;
16
17 typedef struct {
18 int glyph;
19 int value;
20 } KERNING_INFO;
21
22 ///////////////////////////////////////////////////////////////////////////////
gx_studio_font_util_open(const char * font_file,GXS_FONT_LIBRARY_HANDLE ** handle)23 int gx_studio_font_util_open(const char *font_file, GXS_FONT_LIBRARY_HANDLE **handle)
24 {
25 FT_Error error;
26 GXS_FONT_LIBRARY_HANDLE *font_handle;
27
28 if(font_file == NULL)
29 return(GXS_FONT_UTIL_INVALID_FILENAME_PTR);
30
31 font_handle = (GXS_FONT_LIBRARY_HANDLE*)malloc(sizeof(GXS_FONT_LIBRARY_HANDLE));
32 if(font_handle == 0)
33 return(GXS_FONT_UTIL_MALLOC_FAILURE);
34
35 memset(font_handle, 0, sizeof(GXS_FONT_LIBRARY_HANDLE));
36
37 error = FT_Init_FreeType(&(font_handle -> library)); /* initialize library */
38 if(error)
39 {
40 free(font_handle);
41 return(GXS_FONT_UTIL_FT_INIT_FREETYPE_ERROR);
42 }
43
44 error = FT_New_Face(font_handle -> library, font_file, 0, &(font_handle -> face) );/* create face object */
45 if(error)
46 {
47 FT_Done_FreeType( font_handle -> library );
48 free(font_handle);
49 return(GXS_FONT_UTIL_CANNOT_OPEN_FONT_FILE);
50 }
51
52 font_handle -> size = 0;
53 font_handle -> initialized = 1;
54
55 *handle = font_handle;
56
57 return(GXS_FONT_UTIL_SUCCESS);
58 }
59
60 ///////////////////////////////////////////////////////////////////////////////
gx_studio_font_util_get_glyph(GXS_FONT_LIBRARY_HANDLE * font_handle,int font_index,int pt,int aa,GXS_FONT_DATA * font_data)61 int gx_studio_font_util_get_glyph(GXS_FONT_LIBRARY_HANDLE *font_handle, int font_index, int pt, int aa, GXS_FONT_DATA *font_data)
62 {
63 FT_Glyph_Metrics *metrics;
64 FT_GlyphSlot slot;
65 FT_Error error;
66 int glyph_index;
67
68 if(font_handle -> initialized != 1)
69 return(GXS_FONT_UTIL_LIBRARY_UNINITIAZLIED);
70
71 /* set character size */
72 if(font_handle -> size != pt)
73 {
74 error = FT_Set_Char_Size(font_handle -> face, pt * 64, 0, 72, 0);
75 if(error)
76 {
77 return(GXS_FONT_UTIL_SET_CHAR_SIZE_ERROR);
78 }
79 font_handle -> size = pt;
80 }
81
82 slot = font_handle -> face -> glyph;
83
84 glyph_index = FT_Get_Char_Index(font_handle -> face, font_index);
85 error = FT_Load_Glyph(font_handle -> face, glyph_index, 0);
86
87 if(font_handle -> face -> glyph -> format != FT_GLYPH_FORMAT_BITMAP)
88 {
89 if(aa)
90 error = FT_Render_Glyph(font_handle -> face -> glyph, FT_RENDER_MODE_NORMAL);
91 else
92 error = FT_Render_Glyph(font_handle -> face -> glyph, FT_RENDER_MODE_MONO);
93 }
94
95 if (aa && slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
96 {
97 error = FT_Load_Glyph(font_handle->face, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_RENDER);
98 }
99
100 metrics = &(font_handle -> face -> glyph -> metrics);
101 font_data -> width = slot -> bitmap.width;
102 font_data -> height = slot -> bitmap.rows;
103 font_data -> pitch = slot -> bitmap.pitch;
104
105 font_data -> gx_glyph_ascent = (short) ((metrics -> horiBearingY) >> 6);
106 font_data -> gx_glyph_descent = (short)((metrics->height - metrics->horiBearingY) >> 6);
107 font_data -> gx_glyph_advance = (unsigned char) ((metrics -> horiAdvance) >> 6);
108 font_data -> gx_glyph_leading = (char) ((metrics -> horiBearingX) >> 6);
109 font_data -> gx_glyph_data = slot -> bitmap.buffer;
110 return(GXS_FONT_UTIL_SUCCESS);
111 }
112
113 ///////////////////////////////////////////////////////////////////////////////
gx_studio_font_util_get_kerning_info(GXS_FONT_LIBRARY_HANDLE * font_handle,int font_index,int first_glyph_index,int last_glyph_index,GX_KERNING_GLYPH * kerning_glyph,FontCharMap * map)114 int gx_studio_font_util_get_kerning_info(GXS_FONT_LIBRARY_HANDLE *font_handle, int font_index,
115 int first_glyph_index, int last_glyph_index, GX_KERNING_GLYPH *kerning_glyph, FontCharMap *map)
116 {
117 FT_Error error;
118 FT_Vector kerning_vector;
119 GX_UBYTE left_glyph_index;
120 GX_UBYTE right_glyph_index;
121 INT index;
122 CArray<KERNING_INFO> kerning_pairs;
123 KERNING_INFO kerning_info;
124 INT table_size;
125 GX_UBYTE *left_glyph_ptr;
126 INT first_glyph = first_glyph_index;
127 INT last_glyph = last_glyph_index;
128
129 if (font_handle->initialized != 1)
130 return(GXS_FONT_UTIL_LIBRARY_UNINITIAZLIED);
131
132 if (FT_HAS_KERNING(font_handle->face) == 0)
133 {
134 // The face object does not contain kerning data.
135 return(GXS_FONT_UTIL_SUCCESS);
136 }
137
138 if (!map)
139 {
140 return(GXS_FONT_UTIL_SUCCESS);
141 }
142
143 kerning_pairs.SetSize(0, 1);
144 if (first_glyph > 0xff)
145 {
146 return 0;
147 }
148 if (last_glyph > 0xff)
149 {
150 last_glyph = 0xff;
151 }
152
153 right_glyph_index = FT_Get_Char_Index(font_handle->face, font_index);
154
155 if (!right_glyph_index)
156 {
157 // Undefined character code.
158 return(GXS_FONT_UTIL_SUCCESS);
159 }
160
161 // Get kerning vector between two glyphs in the same face
162 for (index = first_glyph; index <= last_glyph; index++)
163 {
164 if (!map->Test(index))
165 {
166 continue;
167 }
168
169 left_glyph_index = FT_Get_Char_Index(font_handle->face, index);
170
171 if (!left_glyph_index)
172 {
173 continue;
174 }
175
176 memset(&kerning_vector, 0, sizeof(FT_Vector));
177 error = FT_Get_Kerning(font_handle->face, left_glyph_index, right_glyph_index, FT_KERNING_DEFAULT, &kerning_vector);
178 if ((error == 0) && (kerning_vector.x))
179 {
180 kerning_info.glyph = index;
181 kerning_info.value = (kerning_vector.x >> 6);
182 kerning_pairs.Add(kerning_info);
183 }
184 }
185
186 if (kerning_pairs.GetCount())
187 {
188 // Calculate size of needed buffer. 1 byte size + 2 bytes for each kerning pair.
189 table_size = 1 + kerning_pairs.GetCount() * (sizeof(GX_UBYTE) + sizeof(GX_CHAR));
190
191 // Allocate memory to load kerning table.
192 kerning_glyph->gx_kerning_table = new GX_UBYTE[table_size];
193 memset(const_cast<GX_UBYTE *>(kerning_glyph->gx_kerning_table), 0, table_size);
194 left_glyph_ptr = (GX_UBYTE *)(kerning_glyph->gx_kerning_table + 1);
195
196 if (kerning_glyph->gx_kerning_table)
197 {
198 *(const_cast<GX_UBYTE *>(kerning_glyph->gx_kerning_table)) = kerning_pairs.GetCount();
199
200 for (index = 0; index < kerning_pairs.GetCount(); index++)
201 {
202 kerning_info = kerning_pairs.GetAt(index);
203 *left_glyph_ptr++ = (GX_UBYTE)kerning_info.glyph;
204 *left_glyph_ptr++ = (GX_UBYTE)kerning_info.value;
205 }
206
207 }
208 }
209
210 return(GXS_FONT_UTIL_SUCCESS);
211 }
212
213 ///////////////////////////////////////////////////////////////////////////////
gx_studio_font_util_close(GXS_FONT_LIBRARY_HANDLE * font_handle)214 void gx_studio_font_util_close(GXS_FONT_LIBRARY_HANDLE *font_handle)
215 {
216 if(!font_handle)
217 return;
218
219 if(font_handle -> initialized == 1)
220 {
221
222 if(font_handle -> face)
223 FT_Done_Face(font_handle -> face);
224 if(font_handle -> library)
225 FT_Done_FreeType(font_handle -> library);
226 }
227
228 free(font_handle);
229 return;
230 }
231
232 ///////////////////////////////////////////////////////////////////////////////
GetRowPitch(INT width,INT bits_per_pix)233 INT GetRowPitch(INT width, INT bits_per_pix)
234 {
235 // Calcualte data size of glyph map
236 INT pitch = width;
237
238 switch (bits_per_pix)
239 {
240 case 1:
241 pitch += 7;
242 pitch /= 8;
243 break;
244 case 4:
245 pitch ++;
246 pitch /= 2;
247 break;
248 case 8:
249 break;
250 }
251
252 return pitch;
253 }
254
255 ///////////////////////////////////////////////////////////////////////////////
GetFontBits(INT font_format)256 INT GetFontBits(INT font_format)
257 {
258 int font_bits = 8;
259
260 switch (font_format & GX_FONT_FORMAT_BPP_MASK)
261 {
262 case GX_FONT_FORMAT_1BPP:
263 font_bits = 1;
264 break;
265
266 case GX_FONT_FORMAT_2BPP:
267 font_bits = 2;
268 break;
269
270 case GX_FONT_FORMAT_4BPP:
271 font_bits = 4;
272 break;
273
274 case GX_FONT_FORMAT_8BPP:
275 font_bits = 8;
276 break;
277 }
278
279 return font_bits;
280 }
281
282 ///////////////////////////////////////////////////////////////////////////////
IsFontBitsSupported(INT font_bits)283 BOOL IsFontBitsSupported(INT font_bits)
284 {
285 switch (font_bits)
286 {
287 case 1:
288 case 4:
289 case 8:
290 return TRUE;
291 }
292
293 return FALSE;
294 }
295
296 ///////////////////////////////////////////////////////////////////////////////
DuplicatesCount(GX_UBYTE * data,int width,int index)297 int DuplicatesCount(GX_UBYTE *data, int width, int index)
298 {
299 int count = 1;
300 GX_UBYTE pre;
301
302 pre = data[index++];
303
304 while (index < width)
305 {
306 if (pre == data[index])
307 {
308 pre = data[index];
309 count++;
310 }
311 else
312 {
313 break;
314 }
315
316 index++;
317 }
318
319 return count;
320 }
321
322 ///////////////////////////////////////////////////////////////////////////////
RleEncode(GX_UBYTE * put_data,GX_UBYTE * get_data,int width,int height)323 int RleEncode(GX_UBYTE *put_data, GX_UBYTE *get_data, int width, int height)
324 {
325 int count = 0;
326 int raw_count = 0;
327 int put_index = 0;
328 int row;
329 int compressed_size = 0;
330
331 for (row = 0; row < height; row++)
332 {
333 int index = 0;
334
335 while (index < width)
336 {
337
338 count = DuplicatesCount(get_data, width, index);
339
340 if (count >= 3)
341 {
342 if (raw_count)
343 {
344 compressed_size += raw_count + 1;
345
346 if (put_data)
347 {
348 *put_data++ = (raw_count - 1) & 0x7f;
349
350 while (raw_count)
351 {
352 *put_data++ = get_data[index - raw_count];
353 raw_count--;
354 }
355 }
356 else
357 {
358 raw_count = 0;
359 }
360 }
361
362 if (count > 128)
363 {
364 count = 128;
365 }
366
367 if (put_data)
368 {
369 *put_data++ = (count - 1) | 0x80;
370 *put_data++ = get_data[index];
371 }
372 compressed_size += 2;
373 index += count;
374 }
375 else
376 {
377 raw_count++;
378 index++;
379
380 if ((raw_count == 128) || (index == width))
381 {
382 compressed_size += raw_count + 1;
383
384 if (put_data)
385 {
386 *put_data++ = (raw_count - 1) & 0x7f;
387
388 while (raw_count)
389 {
390 *put_data++ = get_data[index - raw_count];
391 raw_count--;
392 }
393 }
394 else
395 {
396 raw_count = 0;
397 }
398 }
399 }
400 }
401
402 get_data += width;
403 }
404
405 return compressed_size;
406 }
407
408 ///////////////////////////////////////////////////////////////////////////////
RleEncodeGlyphData(GX_COMPRESSED_GLYPH * glyph,int bits_per_pix)409 void RleEncodeGlyphData(GX_COMPRESSED_GLYPH *glyph, int bits_per_pix)
410 {
411 GX_UBYTE *pGet = (GX_UBYTE *)glyph->gx_glyph_map;
412
413 int pitch = GetRowPitch(glyph->gx_glyph_width, bits_per_pix);
414 int data_size = pitch * glyph->gx_glyph_height;
415
416 int compressed_size = RleEncode(NULL, pGet, pitch, glyph->gx_glyph_height);
417
418 if (compressed_size < data_size)
419 {
420 glyph->gx_glyph_map_size = compressed_size | 0x8000;
421 UCHAR *pPut = new UCHAR[compressed_size];
422 pGet = (GX_UBYTE *)glyph->gx_glyph_map;
423 RleEncode((GX_UBYTE *)pPut, pGet, pitch, glyph->gx_glyph_height);
424
425 delete glyph->gx_glyph_map;
426 glyph->gx_glyph_map = pPut;
427 }
428 else
429 {
430 glyph->gx_glyph_map_size = data_size;
431 }
432 }
433
434 ///////////////////////////////////////////////////////////////////////////////
RleDecodeGlyphData(GX_COMPRESSED_GLYPH * glyph,int bits_per_pix)435 GX_UBYTE* RleDecodeGlyphData(GX_COMPRESSED_GLYPH* glyph, int bits_per_pix)
436 {
437 int pitch = GetRowPitch(glyph->gx_glyph_width, bits_per_pix);
438 int data_size = pitch * glyph->gx_glyph_height;
439
440 if (!data_size)
441 {
442 return GX_NULL;
443 }
444
445 GX_UBYTE* put_data = new GX_UBYTE[data_size];
446 GX_UBYTE* put_row = put_data;
447 GX_UBYTE* put;
448 GX_CONST GX_UBYTE* glyph_data = glyph->gx_glyph_map;
449
450 int row, col;
451 GX_UBYTE count;
452 GX_UBYTE alpha;
453
454 for (row = 0; row < glyph->gx_glyph_height; row++)
455 {
456 col = 0;
457 put = put_row;
458
459 while (col < pitch)
460 {
461 count = *glyph_data++;
462
463 if (count & 0x80)
464 {
465 count = (count & 0x7f) + 1;
466 alpha = *glyph_data++;
467
468 while (count--)
469 {
470 *put = alpha;
471
472 put++;
473 col++;
474 }
475 }
476 else
477 {
478 count++;
479
480 while (count--)
481 {
482 alpha = *glyph_data++;
483 *put = alpha;
484 put++;
485 col++;
486 }
487 }
488 }
489 put_row += pitch;
490 }
491
492 return put_data;
493 }
494
495 ///////////////////////////////////////////////////////////////////////////////
CopyGlyphData(GX_GLYPH * put_glyph,GXS_FONT_DATA & glyph,int bits_per_pix,BOOL reversed_order)496 void CopyGlyphData(GX_GLYPH *put_glyph, GXS_FONT_DATA &glyph, int bits_per_pix, BOOL reversed_order)
497 {
498 int bitmap_size;
499 int row;
500 int col;
501 int num_bits;
502 UCHAR *read_data;
503 UCHAR *write_data;
504 UCHAR val;
505 UCHAR in_byte;
506 UCHAR in_mask;
507 UCHAR out_mask;
508
509 put_glyph->gx_glyph_advance = glyph.gx_glyph_advance;
510 put_glyph->gx_glyph_ascent = glyph.gx_glyph_ascent;
511 put_glyph->gx_glyph_descent = glyph.gx_glyph_descent;
512 put_glyph->gx_glyph_height = ToUByte(glyph.height);
513 put_glyph->gx_glyph_width = ToUByte(glyph.width);
514 put_glyph->gx_glyph_leading = glyph.gx_glyph_leading;
515
516 bitmap_size = GetRowPitch(glyph.width, bits_per_pix) * glyph.height;
517
518 if(bitmap_size == 0)
519 {
520 return;
521 }
522
523 put_glyph->gx_glyph_map = new UCHAR[bitmap_size];
524
525 switch(bits_per_pix)
526 {
527 case 1:
528 write_data = (UCHAR *) put_glyph->gx_glyph_map;
529
530 for (row = 0; row < glyph.height; row++)
531 {
532 num_bits = glyph.width;
533 read_data = glyph.gx_glyph_data + (row * glyph.pitch);
534
535 while(num_bits)
536 {
537 val = *read_data;
538
539 if (reversed_order)
540 {
541 // swap the bit order:
542 in_byte = val;
543 val = 0;
544 in_mask = 0x80;
545 out_mask = 0x01;
546
547 while(in_mask)
548 {
549 if (in_byte & in_mask)
550 {
551 val |= out_mask;
552 }
553 in_mask >>= 1;
554 out_mask <<= 1;
555 }
556 }
557 if (num_bits > 8)
558 {
559 *write_data++ = val;
560 num_bits -= 8;
561 read_data++;
562 }
563 else
564 {
565 *write_data++ = val;
566 num_bits = 0;
567 }
568 }
569 }
570 break;
571
572 case 4:
573 // convert 8 bit incoming data to 4 bit outgoing data
574
575 read_data = glyph.gx_glyph_data;
576 write_data = (UCHAR *) put_glyph->gx_glyph_map;
577
578 for (row = 0; row < glyph.height; row++)
579 {
580 val = 0;
581 for (col = 0; col < glyph.width; col++)
582 {
583 in_byte = *read_data++;
584
585 if (col & 1)
586 {
587 if (reversed_order)
588 {
589 val |= (in_byte & 0xf0); // keep high nibble
590 }
591 else
592 {
593 val |= (in_byte >> 4);
594 }
595 *write_data++ = val;
596 }
597 else
598 {
599 if (reversed_order)
600 {
601 val = in_byte >> 4;
602 }
603 else
604 {
605 val = in_byte & 0xf0;
606 }
607 }
608 }
609
610 // check for odd width, if so write out last pixel
611 if (glyph.width & 1)
612 {
613 *write_data++ = val;
614 }
615 }
616 break;
617
618 default:
619 memcpy_s((UCHAR *) put_glyph->gx_glyph_map, bitmap_size, glyph.gx_glyph_data, bitmap_size);
620 break;
621 }
622 }
623
624
625 ///////////////////////////////////////////////////////////////////////////////
GetFontMetrics(GXS_FONT_LIBRARY_HANDLE * handle,int height,FONT_METRICS & metrics,int firstchar,int lastchar,int bits_per_pix,FontCharMap & map)626 void GetFontMetrics(GXS_FONT_LIBRARY_HANDLE *handle,
627 int height, FONT_METRICS &metrics, int firstchar, int lastchar, int bits_per_pix, FontCharMap &map)
628 {
629 int use_char;
630
631 GXS_FONT_DATA glyph;
632 GX_BOOL anti_alias = GX_TRUE;
633
634 if (bits_per_pix == 1)
635 {
636 anti_alias = GX_FALSE;
637 }
638
639 for (use_char = firstchar; use_char <= lastchar; use_char++ )
640 {
641 if (!map.Test(use_char))
642 {
643 continue;
644 }
645
646 gx_studio_font_util_get_glyph(handle, use_char,
647 height, anti_alias, &glyph);
648
649 if(glyph.height > metrics.max_height)
650 {
651 metrics.max_height = glyph.height;
652 }
653 if(glyph.gx_glyph_ascent > metrics.ascent)
654 {
655 metrics.ascent = glyph.gx_glyph_ascent;
656 }
657 if(glyph.gx_glyph_descent > metrics.descent)
658 {
659 metrics.descent = glyph.gx_glyph_descent;
660 }
661 }
662
663 if (metrics.max_height < (metrics.ascent + metrics.descent))
664 {
665 metrics.max_height = (metrics.ascent + metrics.descent);
666 }
667 }
668
669
670 ///////////////////////////////////////////////////////////////////////////////
MakeFontPage(GXS_FONT_LIBRARY_HANDLE * handle,int height,FONT_METRICS & metrics,int firstchar,int lastchar,FontCharMap & map,res_info * info,int display)671 GX_FONT *MakeFontPage(GXS_FONT_LIBRARY_HANDLE *handle,
672 int height, FONT_METRICS &metrics, int firstchar, int lastchar, FontCharMap &map, res_info *info, int display)
673 {
674 int use_char;
675 int char_count;
676
677 GXS_FONT_DATA glyph;
678 GX_FONT *new_font;
679 GX_GLYPH *glyph_array;
680 GX_GLYPH *put_glyph;
681 GX_COMPRESSED_GLYPH *compressed_glyph_array;
682 GX_COMPRESSED_GLYPH *put_compressed_glyph;
683 GX_BOOL anti_alias = GX_TRUE;
684 INT bits_per_pix = info->font_bits;
685 /* Kerning glyph */
686 GX_BOOL reversed_order = GX_FALSE;
687 GX_KERNING_GLYPH *kerning_glyph_array;
688 GX_KERNING_GLYPH *put_kerning_glyph;
689
690 studiox_project *project = GetOpenProject();
691
692 if (!project)
693 {
694 return NULL;
695 }
696
697 char_count = lastchar - firstchar + 1;
698
699 new_font = new GX_FONT;
700 new_font->gx_font_first_glyph = firstchar;
701 new_font->gx_font_last_glyph = lastchar;
702 new_font->gx_font_next_page = NULL;
703
704 if (!IsRenesasDave2D(GetOpenProject()))
705 {
706 /* Compressed mode is only supported by Renesas dave2d. */
707 info->compress = FALSE;
708 }
709
710 if (info->compress)
711 {
712 compressed_glyph_array = new GX_COMPRESSED_GLYPH[char_count];
713 memset(compressed_glyph_array, 0, char_count * sizeof(GX_COMPRESSED_GLYPH));
714 new_font->gx_font_glyphs.gx_font_compressed_glyphs = compressed_glyph_array;
715 }
716 else
717 {
718 if (info->font_kerning)
719 {
720 if (FT_HAS_KERNING(handle->face))
721 {
722 /* allocate memory for kerning glyph */
723 kerning_glyph_array = new GX_KERNING_GLYPH[char_count];
724 memset(kerning_glyph_array, 0, char_count * sizeof(GX_KERNING_GLYPH));
725 new_font->gx_font_glyphs.gx_font_kerning_glyphs = kerning_glyph_array;
726
727 }
728 else
729 {
730 /* Set kerning flag to false as the font does not contain kerning information. */
731 info->font_kerning = FALSE;
732 glyph_array = new GX_GLYPH[char_count];
733 memset(glyph_array, 0, char_count * sizeof(GX_GLYPH));
734 new_font->gx_font_glyphs.gx_font_normal_glyphs = glyph_array;
735 }
736 }
737 else
738 {
739 glyph_array = new GX_GLYPH[char_count];
740 memset(glyph_array, 0, char_count * sizeof(GX_GLYPH));
741 new_font->gx_font_glyphs.gx_font_normal_glyphs = glyph_array;
742 }
743 }
744
745 switch(bits_per_pix)
746 {
747 case 1:
748 new_font->gx_font_format = GX_FONT_FORMAT_1BPP;
749 anti_alias = GX_FALSE;
750
751 if (IsDave2dFontFormat(project, display))
752 {
753 reversed_order = TRUE;
754 }
755 break;
756
757 case 4:
758 new_font->gx_font_format = GX_FONT_FORMAT_4BPP;
759
760 if (IsDave2dFontFormat(project, display))
761 {
762 reversed_order = TRUE;
763 }
764 break;
765
766 case 8:
767 new_font->gx_font_format = GX_FONT_FORMAT_8BPP;
768 break;
769 }
770
771 if (reversed_order)
772 {
773 new_font->gx_font_format |= GX_FONT_FORMAT_REVERSED_ORDER;
774 }
775
776 if (info->compress)
777 {
778 new_font->gx_font_format |= GX_FONT_FORMAT_COMPRESSED;
779 }
780
781 if (info->font_kerning)
782 {
783 new_font->gx_font_format |= GX_FONT_FORMAT_KERNING;
784 }
785
786 for (use_char = firstchar; use_char <= lastchar; use_char++)
787 {
788 if (!map.Test(use_char))
789 {
790 continue;
791 }
792
793 gx_studio_font_util_get_glyph(handle, use_char,
794 height, anti_alias, &glyph);
795 if (info->compress)
796 {
797 put_compressed_glyph = &(compressed_glyph_array)[use_char - firstchar];
798 CopyGlyphData((GX_GLYPH *)put_compressed_glyph, glyph, bits_per_pix, reversed_order);
799
800 //Compress glyph data
801 RleEncodeGlyphData(put_compressed_glyph, bits_per_pix);
802 }
803 else
804 {
805 if (info->font_kerning)
806 {
807 put_kerning_glyph = &kerning_glyph_array[use_char - firstchar];
808 CopyGlyphData((GX_GLYPH *)put_kerning_glyph, glyph, bits_per_pix, reversed_order);
809 if (use_char <= 0xff)
810 {
811 gx_studio_font_util_get_kerning_info(handle, use_char, firstchar, lastchar, put_kerning_glyph, &map);
812 }
813 }
814 else
815 {
816 put_glyph = &glyph_array[use_char - firstchar];
817 CopyGlyphData(put_glyph, glyph, bits_per_pix, reversed_order);
818 }
819 }
820 }
821
822 new_font->gx_font_prespace = 0; /* Line spacing above, pixels */
823 new_font->gx_font_postspace = 0;
824 new_font->gx_font_line_height = metrics.max_height;
825 new_font->gx_font_baseline = metrics.ascent;
826
827 return new_font;
828 }
829
830 ///////////////////////////////////////////////////////////////////////////////
MakeFont(res_info * info,int display,BOOL warn_on_error)831 GX_FONT *MakeFont(res_info *info, int display, BOOL warn_on_error)
832 {
833 font_page_info *pages = info->font_pages;
834 int page_count;
835 int max_char_count;
836 int max_char;
837 int height = info->font_height;
838 int bits_per_pix = info->font_bits;
839 FontCharMap char_map;
840 FONT_METRICS metrics;
841
842 int page;
843 GXS_FONT_LIBRARY_HANDLE *handle;
844 GX_FONT *head_page = NULL;
845 GX_FONT *last_page = NULL;
846
847 studiox_project* project = GetOpenProject();
848
849 if(!project)
850 {
851 return NULL;
852 }
853
854 // GotoProjectDirectory();
855 CString abspath = MakeAbsolutePathname(info->pathinfo);
856 if (gx_studio_font_util_open(CT2A(abspath.GetString()), &handle) != 0)
857 {
858 if (warn_on_error)
859 {
860 CString msg;
861 msg.Format(_T("Font Name = %s\nFailed to open TrueType font file: %s"), info->name, abspath);
862 ErrorMsg(msg);
863 }
864 return NULL;
865 }
866
867 if (info->font_support_extended_unicode)
868 {
869 // Use 21-bit character map
870 char_map.SetMapSize(262144);
871 page_count = NUM_FONT_CHAR_RANGES + NUM_FONT_EXTENDED_CHAR_RANGES;
872
873 // extended unicode range is between [0x10000, 0x10ffff],
874 // the total supported character count is 0x110000
875 max_char_count = GX_MAX_GLYPH_CODE + 1;
876 max_char = 0x10ffff;
877 }
878 else
879 {
880 page_count = NUM_FONT_CHAR_RANGES;
881 max_char_count = 0xffff;
882 max_char = 0xffff;
883 }
884
885 if (info->font_pages_count)
886 {
887 page_count = info->font_pages_count;
888 }
889
890 for (page = 0; page < page_count; page++)
891 {
892 // map character ranges the user has turned on
893 if (pages[page].enabled && pages[page].first_char <= pages[page].last_char)
894 {
895 char_map.Set(pages[page].first_char, pages[page].last_char);
896 }
897 }
898
899 if (info->font_charset_include_string_table)
900 {
901 // add characters used in string table
902 FontCharMap *tmap = GetActiveCharacterMap(FALSE);
903 if (tmap)
904 {
905 char_map.Overlay(tmap);
906 }
907 }
908
909 if (char_map.Test(0xe00, 0xe7f))
910 {
911 // Detected thai glyph code
912 if (char_map.Test(0x0e33))
913 {
914 // The vowel sara am will be split into the character nikhahit and sara aa if it is
915 // appended to a consonant.
916 char_map.Set(0x0e4d, 0x0e4d);
917 char_map.Set(0x0e32, 0x0e32);
918 }
919
920 // add private user area for thai glyph shaping
921 char_map.Set(0xf700, 0xf71a);
922 }
923
924 if (char_map.Test(0x600, 0x6ff))
925 {
926 // add arabic presentation forms-b for arabic shaping
927 char_map.Set(0xfe70, 0xfeff);
928
929 // add arabic presentation forms-a for persion shaping
930 char_map.Set(0xfb50, 0xfbff);
931 }
932
933 if (char_map.IsEmpty())
934 {
935 gx_studio_font_util_close(handle);
936 return NULL;
937 }
938
939 int first_char, last_char;
940
941 metrics.ascent = metrics.descent = metrics.max_height = 0;
942
943 // first get the font metrics
944 for (first_char = 0; first_char <= max_char; first_char++)
945 {
946 if (char_map.Test(first_char, first_char))
947 {
948 GetFontMetrics(handle, height, metrics, first_char, first_char, bits_per_pix, char_map);
949 }
950 }
951
952 // now render actual font data pages
953 GX_FONT *newpage;
954
955 for (first_char = 0; first_char <= max_char;)
956 {
957 last_char = first_char + 127;
958
959 if (last_char > max_char)
960 {
961 last_char = max_char;
962 }
963
964 if (char_map.Test(first_char, last_char))
965 {
966 // Make font for characters that defined in character map but not in character ranges.
967 newpage = MakeFontPage(handle, height, metrics, first_char, last_char, char_map, info, display);
968
969 if (newpage)
970 {
971 if (!head_page)
972 {
973 head_page = newpage;
974 }
975 if (last_page)
976 {
977 last_page->gx_font_next_page = newpage;
978 }
979 last_page = newpage;
980 }
981 }
982
983 first_char = last_char + 1;
984 }
985
986 gx_studio_font_util_close(handle);
987 return head_page;
988 }
989
990 ///////////////////////////////////////////////////////////////////////////////
InsertStringTableGlyphs(FontCharMap * char_map,res_info * info,int display)991 BOOL InsertStringTableGlyphs(FontCharMap *char_map, res_info *info, int display)
992 {
993 BOOL status = TRUE;
994 BOOL found_page;
995 BOOL anti_alias = FALSE;
996 int height = info->font_height;
997 int bits_per_pix = info->font_bits;
998 DWORD char_val;
999 DWORD maxval = char_map->GetMapSize() << 3;
1000 GXS_FONT_LIBRARY_HANDLE *handle;
1001 GXS_FONT_DATA glyph;
1002 GX_FONT *head_page = NULL;
1003 GX_FONT *last_page = NULL;
1004
1005 if (!char_map)
1006 {
1007 return FALSE;
1008 }
1009
1010 CString abspath = MakeAbsolutePathname(info->pathinfo);
1011 if (gx_studio_font_util_open(CT2A(abspath.GetString()), &handle) != 0)
1012 {
1013 return FALSE;
1014 }
1015
1016 if (bits_per_pix > 1)
1017 {
1018 anti_alias = TRUE;
1019 }
1020
1021 BOOL reversed_order = FALSE;
1022
1023 switch (bits_per_pix)
1024 {
1025 case 1:
1026 case 4:
1027 if (IsDave2dFontFormat(GetOpenProject(), display))
1028 {
1029 reversed_order = TRUE;
1030 }
1031 break;
1032 }
1033
1034 for (char_val = 0; char_val < maxval; char_val++)
1035 {
1036 if (char_map->Test(char_val))
1037 {
1038 GX_FONT *page = info->font;
1039 found_page = FALSE;
1040
1041 while(page)
1042 {
1043 if (page->gx_font_first_glyph <= char_val &&
1044 page->gx_font_last_glyph >= char_val)
1045 {
1046 found_page = TRUE;
1047
1048 if (info->font_kerning)
1049 {
1050 GX_KERNING_GLYPH *put_glyph = (GX_KERNING_GLYPH *) &page->gx_font_glyphs.gx_font_kerning_glyphs[char_val - page->gx_font_first_glyph];
1051
1052 if ((!put_glyph->gx_glyph_map) && (put_glyph->gx_glyph_advance == 0))
1053 {
1054 // get the glyph data, insert into font
1055
1056 if (gx_studio_font_util_get_glyph(handle, char_val, height, anti_alias, &glyph) != GXS_FONT_UTIL_SUCCESS)
1057 {
1058 status = FALSE;
1059 break;
1060 }
1061 CopyGlyphData((GX_GLYPH *)put_glyph, glyph, bits_per_pix, reversed_order);
1062
1063 if (put_glyph->gx_kerning_table)
1064 {
1065 delete[] put_glyph->gx_kerning_table;
1066 put_glyph->gx_kerning_table = NULL;
1067 if (char_val <= 0xff)
1068 {
1069 gx_studio_font_util_get_kerning_info(handle, char_val, page->gx_font_first_glyph, page->gx_font_last_glyph, put_glyph, char_map);
1070 }
1071 }
1072 }
1073 }
1074 else if (page->gx_font_format & GX_FONT_FORMAT_COMPRESSED)
1075 {
1076 GX_COMPRESSED_GLYPH *put_glyph = (GX_COMPRESSED_GLYPH *) &page->gx_font_glyphs.gx_font_compressed_glyphs[char_val - page->gx_font_first_glyph];
1077
1078 if ((!put_glyph->gx_glyph_map) && (put_glyph->gx_glyph_advance == 0))
1079 {
1080 // get the glyph data, insert into font
1081
1082 if (gx_studio_font_util_get_glyph(handle, char_val, height, anti_alias, &glyph) != GXS_FONT_UTIL_SUCCESS)
1083 {
1084 status = FALSE;
1085 break;
1086 }
1087 CopyGlyphData((GX_GLYPH *)put_glyph, glyph, bits_per_pix, reversed_order);
1088
1089 //Compress glyph data
1090 RleEncodeGlyphData(put_glyph, bits_per_pix);
1091 }
1092 }
1093 else
1094 {
1095 GX_GLYPH *put_glyph = (GX_GLYPH *)&page->gx_font_glyphs.gx_font_normal_glyphs[char_val - page->gx_font_first_glyph];
1096
1097 if ((!put_glyph->gx_glyph_map) && (put_glyph->gx_glyph_advance == 0))
1098 {
1099 // get the glyph data, insert into font
1100
1101 if (gx_studio_font_util_get_glyph(handle, char_val, height, anti_alias, &glyph) != GXS_FONT_UTIL_SUCCESS)
1102 {
1103 status = FALSE;
1104 break;
1105 }
1106 CopyGlyphData(put_glyph, glyph, bits_per_pix, reversed_order);
1107 }
1108 }
1109
1110 break;
1111 }
1112 page = (GX_FONT *) page->gx_font_next_page;
1113 }
1114
1115 if ((!found_page) || (status != TRUE))
1116 {
1117 status = FALSE;
1118 break;
1119 }
1120 }
1121 }
1122
1123 gx_studio_font_util_close(handle);
1124 return status;
1125 }
1126
1127
1128 ///////////////////////////////////////////////////////////////////////////////
DestroyFont(GX_FONT * font)1129 void DestroyFont(GX_FONT *font)
1130 {
1131 GX_GLYPH *glyph;
1132 GX_COMPRESSED_GLYPH *compressed_glyph;
1133 GX_KERNING_GLYPH *kering_glyph;
1134 const GX_FONT *next_page = NULL;
1135
1136 while (font)
1137 {
1138 next_page = font->gx_font_next_page;
1139
1140 int num_chars = font->gx_font_last_glyph - font->gx_font_first_glyph + 1;
1141
1142 if (font->gx_font_glyphs.gx_font_normal_glyphs)
1143 {
1144 glyph = (GX_GLYPH *) font->gx_font_glyphs.gx_font_normal_glyphs;
1145
1146 for (int index = 0; index < num_chars; index++)
1147 {
1148 if (glyph->gx_glyph_map)
1149 {
1150 delete [] glyph->gx_glyph_map;
1151 glyph->gx_glyph_map = NULL;
1152 }
1153
1154 if (font->gx_font_format & GX_FONT_FORMAT_COMPRESSED)
1155 {
1156 compressed_glyph = (GX_COMPRESSED_GLYPH *)glyph;
1157 compressed_glyph++;
1158 glyph = (GX_GLYPH *)compressed_glyph;
1159 }
1160 else if (font->gx_font_format & GX_FONT_FORMAT_KERNING)
1161 {
1162 kering_glyph = (GX_KERNING_GLYPH *)glyph;
1163 if (kering_glyph->gx_kerning_table)
1164 {
1165 delete[] kering_glyph->gx_kerning_table;
1166 kering_glyph->gx_kerning_table = NULL;
1167 }
1168 kering_glyph++;
1169 glyph = (GX_GLYPH *)kering_glyph;
1170 }
1171 else
1172 {
1173 glyph++;
1174 }
1175 }
1176 delete [] font->gx_font_glyphs.gx_font_normal_glyphs;
1177 font->gx_font_glyphs.gx_font_normal_glyphs = NULL;
1178 }
1179 delete font;
1180 font = (GX_FONT *) next_page;
1181 }
1182 }
1183
1184 ///////////////////////////////////////////////////////////////////////////////
FindFirstValidGlyph(const GX_FONT * page,GX_CHAR_CODE glyph_start)1185 GX_CHAR_CODE FindFirstValidGlyph(const GX_FONT *page, GX_CHAR_CODE glyph_start)
1186 {
1187 GX_CHAR_CODE index;
1188 GX_COMPRESSED_GLYPH *compressed_glyph;
1189 GX_KERNING_GLYPH *kerning_glyph;
1190 while(1)
1191 {
1192 if (glyph_start > page->gx_font_last_glyph)
1193 {
1194 break;
1195 }
1196 index = glyph_start - page->gx_font_first_glyph;
1197
1198 if (page->gx_font_format & GX_FONT_FORMAT_COMPRESSED)
1199 {
1200 compressed_glyph = (GX_COMPRESSED_GLYPH *)page->gx_font_glyphs.gx_font_compressed_glyphs;
1201 if (compressed_glyph[index].gx_glyph_map != NULL ||
1202 compressed_glyph[index].gx_glyph_advance != 0)
1203 {
1204 break;
1205 }
1206 }
1207 else if (page->gx_font_format & GX_FONT_FORMAT_KERNING)
1208 {
1209 kerning_glyph = (GX_KERNING_GLYPH *)page->gx_font_glyphs.gx_font_kerning_glyphs;
1210 if (kerning_glyph[index].gx_glyph_map != NULL ||
1211 kerning_glyph[index].gx_glyph_advance != 0)
1212 {
1213 break;
1214 }
1215 }
1216 else
1217 {
1218 if (page->gx_font_glyphs.gx_font_normal_glyphs[index].gx_glyph_map != NULL ||
1219 page->gx_font_glyphs.gx_font_normal_glyphs[index].gx_glyph_advance != 0)
1220 {
1221 break;
1222 }
1223 }
1224 glyph_start++;
1225 }
1226 return glyph_start;
1227 }
1228
1229 #define MAX_FONT_DEAD_BLOCK 64
1230
1231 ///////////////////////////////////////////////////////////////////////////////
FindDeadGlyphBlock(const GX_FONT * page,GX_CHAR_CODE glyph_end)1232 GX_CHAR_CODE FindDeadGlyphBlock(const GX_FONT *page, GX_CHAR_CODE glyph_end)
1233 {
1234 GX_CHAR_CODE dead_count = 0;
1235 GX_CHAR_CODE stop_point = glyph_end;
1236 GX_CHAR_CODE index;
1237 GX_CONST GX_COMPRESSED_GLYPH *compressed_glyph;
1238 GX_CONST GX_KERNING_GLYPH *kerning_glyph;
1239
1240 index = stop_point;
1241
1242 if (page->gx_font_format & GX_FONT_FORMAT_COMPRESSED)
1243 {
1244 compressed_glyph = page->gx_font_glyphs.gx_font_compressed_glyphs;
1245
1246 while (index <= page->gx_font_last_glyph)
1247 {
1248 if (compressed_glyph[index - page->gx_font_first_glyph].gx_glyph_map == NULL &&
1249 compressed_glyph[index - page->gx_font_first_glyph].gx_glyph_advance == 0)
1250 {
1251 dead_count++;
1252
1253 if (dead_count > MAX_FONT_DEAD_BLOCK)
1254 {
1255 break;
1256 }
1257 }
1258 else
1259 {
1260 stop_point = index;
1261 dead_count = 0;
1262 }
1263 index++;
1264 }
1265 }
1266 else if (page->gx_font_format & GX_FONT_FORMAT_KERNING)
1267 {
1268 kerning_glyph = page->gx_font_glyphs.gx_font_kerning_glyphs;
1269
1270 while (index <= page->gx_font_last_glyph)
1271 {
1272 if (kerning_glyph[index - page->gx_font_first_glyph].gx_glyph_map == NULL &&
1273 kerning_glyph[index - page->gx_font_first_glyph].gx_glyph_advance == 0)
1274 {
1275 dead_count++;
1276
1277 if (dead_count > MAX_FONT_DEAD_BLOCK)
1278 {
1279 break;
1280 }
1281 }
1282 else
1283 {
1284 stop_point = index;
1285 dead_count = 0;
1286 }
1287 index++;
1288 }
1289 }
1290 else
1291 {
1292
1293 while (index <= page->gx_font_last_glyph)
1294 {
1295 if (page->gx_font_glyphs.gx_font_normal_glyphs[index - page->gx_font_first_glyph].gx_glyph_map == NULL &&
1296 page->gx_font_glyphs.gx_font_normal_glyphs[index - page->gx_font_first_glyph].gx_glyph_advance == 0)
1297 {
1298 dead_count++;
1299
1300 if (dead_count > MAX_FONT_DEAD_BLOCK)
1301 {
1302 break;
1303 }
1304 }
1305 else
1306 {
1307 stop_point = index;
1308 dead_count = 0;
1309 }
1310 index++;
1311 }
1312 }
1313 return stop_point;
1314 }
1315
1316 ///////////////////////////////////////////////////////////////////////////////
CopyGlyphs(GX_FONT * dest,const GX_FONT * src)1317 void CopyGlyphs(GX_FONT *dest, const GX_FONT *src)
1318 {
1319 int char_count = dest->gx_font_last_glyph - dest->gx_font_first_glyph + 1;
1320
1321 GX_GLYPH *glyph_array = new GX_GLYPH[char_count];
1322 memset(glyph_array, 0, char_count * sizeof(GX_GLYPH));
1323 dest->gx_font_glyphs.gx_font_normal_glyphs = glyph_array;
1324
1325 GX_GLYPH *put = glyph_array;
1326 const GX_GLYPH *get = &src->gx_font_glyphs.gx_font_normal_glyphs[dest->gx_font_first_glyph - src->gx_font_first_glyph];
1327
1328 int bitmap_size = 0;
1329
1330 while(char_count--)
1331 {
1332 *put = *get;
1333 put->gx_glyph_map = NULL;
1334 bitmap_size = GetRowPitch(put->gx_glyph_width, GetFontBits(dest->gx_font_format));
1335 bitmap_size *= put->gx_glyph_height;
1336
1337 if(bitmap_size != 0)
1338 {
1339 put->gx_glyph_map = new UCHAR[bitmap_size];
1340 memcpy_s((GX_UBYTE *) put->gx_glyph_map, bitmap_size, get->gx_glyph_map, bitmap_size);
1341 }
1342 else
1343 {
1344 put->gx_glyph_map = GX_NULL;
1345 }
1346
1347 put++;
1348 get++;
1349 }
1350 }
1351
1352 ///////////////////////////////////////////////////////////////////////////////
CopyKerningGlyphs(GX_FONT * dest,const GX_FONT * src)1353 void CopyKerningGlyphs(GX_FONT *dest, const GX_FONT *src)
1354 {
1355 int char_count = dest->gx_font_last_glyph - dest->gx_font_first_glyph + 1;
1356 GX_KERNING_GLYPH *glyph_array = new GX_KERNING_GLYPH[char_count];
1357 memset(glyph_array, 0, char_count * sizeof(GX_KERNING_GLYPH));
1358 dest->gx_font_glyphs.gx_font_kerning_glyphs = glyph_array;
1359
1360 GX_KERNING_GLYPH *put = glyph_array;
1361 const GX_KERNING_GLYPH *get = &src->gx_font_glyphs.gx_font_kerning_glyphs[dest->gx_font_first_glyph - src->gx_font_first_glyph];
1362
1363 int bitmap_size = 0;
1364 while (char_count--)
1365 {
1366 *put = *get;
1367 bitmap_size = GetRowPitch(put->gx_glyph_width, GetFontBits(dest->gx_font_format));
1368 bitmap_size *= put->gx_glyph_height;
1369
1370 if (bitmap_size != 0)
1371 {
1372 put->gx_glyph_map = new UCHAR[bitmap_size];
1373 memcpy_s((GX_UBYTE *)put->gx_glyph_map, bitmap_size, get->gx_glyph_map, bitmap_size);
1374 }
1375 else
1376 {
1377 put->gx_glyph_map = GX_NULL;
1378 }
1379 put -> gx_kerning_table = GX_NULL;
1380
1381 if (get -> gx_kerning_table)
1382 {
1383 /* Copy kerning table if there's one */
1384 INT table_size = *(get->gx_kerning_table);
1385 table_size = 1 + (table_size * (sizeof(GX_UBYTE) + sizeof(GX_CHAR)));
1386 put->gx_kerning_table = new GX_UBYTE[table_size];
1387 memcpy_s((GX_UBYTE *)put->gx_kerning_table, table_size, get->gx_kerning_table, table_size);
1388 }
1389 put++;
1390 get++;
1391 }
1392 }
1393
1394 ///////////////////////////////////////////////////////////////////////////////
CopyCompressedGlyphs(GX_FONT * dest,const GX_FONT * src)1395 void CopyCompressedGlyphs(GX_FONT *dest, const GX_FONT *src)
1396 {
1397 int char_count = dest->gx_font_last_glyph - dest->gx_font_first_glyph + 1;
1398
1399 GX_COMPRESSED_GLYPH *glyph_array = new GX_COMPRESSED_GLYPH[char_count];
1400 memset(glyph_array, 0, char_count * sizeof(GX_COMPRESSED_GLYPH));
1401 dest->gx_font_glyphs.gx_font_compressed_glyphs = glyph_array;
1402
1403 GX_COMPRESSED_GLYPH *put = glyph_array;
1404 const GX_COMPRESSED_GLYPH *get = &src->gx_font_glyphs.gx_font_compressed_glyphs[dest->gx_font_first_glyph - src->gx_font_first_glyph];
1405
1406 int bitmap_size = 0;
1407
1408 while (char_count--)
1409 {
1410 *put = *get;
1411 bitmap_size = put->gx_glyph_map_size & 0x7fff;
1412
1413 if (bitmap_size != 0)
1414 {
1415 put->gx_glyph_map = new UCHAR[bitmap_size];
1416 memcpy_s((GX_UBYTE *)put->gx_glyph_map, bitmap_size, get->gx_glyph_map, bitmap_size);
1417 }
1418 else
1419 {
1420 put->gx_glyph_map = GX_NULL;
1421 }
1422
1423 put++;
1424 get++;
1425 }
1426 }
1427
1428 ///////////////////////////////////////////////////////////////////////////////
optimize_font(GX_FONT * src_font)1429 GX_FONT *optimize_font(GX_FONT *src_font)
1430 {
1431 GX_FONT *head_page = NULL;
1432 GX_FONT *last_page = NULL;
1433 GX_FONT *current_page = NULL;
1434 const GX_FONT *src_page = src_font;
1435
1436 while (src_page)
1437 {
1438 GX_CHAR_CODE first_glyph = src_page->gx_font_first_glyph;
1439 GX_CHAR_CODE last_glyph = src_page->gx_font_last_glyph;
1440
1441 while(first_glyph <= src_page->gx_font_last_glyph)
1442 {
1443 // skip leading NULL glyphs
1444 first_glyph = FindFirstValidGlyph(src_page, first_glyph);
1445
1446 if (first_glyph <= src_page->gx_font_last_glyph)
1447 {
1448 // stop if there is a large dead section
1449 last_glyph = FindDeadGlyphBlock(src_page, first_glyph);
1450
1451 // make a font page for first to last:
1452 current_page = new GX_FONT;
1453 memset(current_page, 0, sizeof(GX_FONT));
1454 current_page->gx_font_baseline = src_page->gx_font_baseline;
1455 current_page->gx_font_first_glyph = first_glyph;
1456 current_page->gx_font_last_glyph = last_glyph;
1457 current_page->gx_font_format = src_page->gx_font_format;
1458 current_page->gx_font_line_height = src_page->gx_font_line_height;
1459 current_page->gx_font_postspace = src_page->gx_font_postspace;
1460 current_page->gx_font_prespace = src_page->gx_font_prespace;
1461
1462 if (src_page->gx_font_format & GX_FONT_FORMAT_COMPRESSED)
1463 {
1464 CopyCompressedGlyphs(current_page, src_page);
1465 }
1466 else if(src_page->gx_font_format & GX_FONT_FORMAT_KERNING)
1467 {
1468 CopyKerningGlyphs(current_page, src_page);
1469 }
1470 else
1471 {
1472 CopyGlyphs(current_page, src_page);
1473 }
1474
1475 if (last_page)
1476 {
1477 last_page->gx_font_next_page = current_page;
1478 }
1479 else
1480 {
1481 head_page = current_page;
1482 }
1483 last_page = current_page;
1484 first_glyph = last_glyph + 1;
1485 }
1486 }
1487 src_page = src_page->gx_font_next_page;
1488 }
1489 return head_page;
1490 }
1491
1492 ///////////////////////////////////////////////////////////////////////////////
MakeOptimizedFont(res_info * info,int display,BOOL warn_on_error)1493 GX_FONT *MakeOptimizedFont(res_info *info, int display, BOOL warn_on_error)
1494 {
1495 GX_FONT *optimized = GX_NULL;
1496 GX_FONT *new_font = MakeFont(info, display, warn_on_error);
1497
1498 if (new_font)
1499 {
1500 optimized = optimize_font(new_font);
1501 DestroyFont(new_font);
1502 }
1503 return optimized;
1504 }
1505
1506 ///////////////////////////////////////////////////////////////////////////////
GetFontStorage(res_info * info,studiox_project * project,int display)1507 INT GetFontStorage(res_info *info, studiox_project *project, int display)
1508 {
1509 // return the size (in byte) of output font
1510
1511 const GX_FONT *font_page;
1512 const GX_FONT *head_page;
1513 long datasize = 0;
1514 long kerning_datasize = 0;
1515 GX_CHAR_CODE charval;
1516 GX_CHAR_CODE index;
1517 const GX_GLYPH *glyph;
1518 const GX_COMPRESSED_GLYPH *compressed_glyph;
1519 const GX_KERNING_GLYPH *kerning_glyph;
1520 GX_UBYTE Kerning_pairs_count;
1521 int pitch;
1522
1523 /* Make the font again, with optimization */
1524 head_page = MakeOptimizedFont(info, display);
1525
1526 if (!head_page)
1527 {
1528 return datasize;
1529 }
1530
1531 font_page = head_page;
1532
1533 /* Calculate font size. */
1534 while (font_page)
1535 {
1536 for (charval = font_page->gx_font_first_glyph; charval <= font_page->gx_font_last_glyph; charval++)
1537 {
1538 index = charval - font_page->gx_font_first_glyph;
1539
1540 if (font_page->gx_font_format & GX_FONT_FORMAT_COMPRESSED)
1541 {
1542 compressed_glyph = &font_page->gx_font_glyphs.gx_font_compressed_glyphs[index];
1543 datasize += (compressed_glyph->gx_glyph_map_size & 0x7fff);
1544 }
1545 else if (font_page->gx_font_format & GX_FONT_FORMAT_KERNING)
1546 {
1547 kerning_glyph = &font_page->gx_font_glyphs.gx_font_kerning_glyphs[index];
1548 pitch = GetRowPitch(kerning_glyph->gx_glyph_width, info->font_bits);
1549 datasize += pitch * kerning_glyph->gx_glyph_height;
1550 if (kerning_glyph->gx_kerning_table)
1551 {
1552 Kerning_pairs_count = *(kerning_glyph->gx_kerning_table);
1553 /* Add the kerning table size. */
1554 kerning_datasize += 1 + Kerning_pairs_count * (sizeof(GX_CHAR) + sizeof(GX_UBYTE));
1555 }
1556 }
1557 else
1558 {
1559 glyph = &font_page->gx_font_glyphs.gx_font_normal_glyphs[index];
1560 pitch = GetRowPitch(glyph->gx_glyph_width, info->font_bits);
1561 datasize += pitch * glyph->gx_glyph_height;
1562 }
1563 }
1564
1565 font_page = font_page->gx_font_next_page;
1566 }
1567 DestroyFont((GX_FONT *)head_page);
1568
1569 /* if kerning info size is bigger than 5 kB*/
1570 if (kerning_datasize > 5120)
1571 {
1572 if (kerning_datasize > datasize)
1573 {
1574 /* kerning info data size is bigger than the glyph size.
1575 Show notification dialog that the font size is so large. */
1576 CString message ("Generate kerning info of font ");
1577 message += info->name;
1578 message += " is selected and it will take lots of memory. Make sure it is wanted.";
1579 Notify(CW2A(message));
1580 }
1581 }
1582
1583 return (datasize + kerning_datasize);
1584 }
1585
1586
1587 ////////////////////////////////////////////////////////////////////////////////
GetPixelmapStorage(res_info * info)1588 INT GetPixelmapStorage(res_info *info)
1589 {
1590 int storage = 0;
1591
1592 if (info->raw)
1593 {
1594 CString path = MakeAbsolutePathname(info->pathinfo);
1595 FILE *file = _tfopen(path.GetBuffer(), _T("rb"));
1596
1597 if (!file)
1598 {
1599 return 0;
1600 }
1601
1602 fseek(file, 0, SEEK_END);
1603 storage = ftell(file);
1604 fclose(file);
1605 }
1606 else
1607 {
1608 GX_PIXELMAP *map;
1609
1610 for (int index = 0; index < info->GetPixelmapFrameCount(); index++)
1611 {
1612 map = info->GetPixelmap(index);
1613
1614 if (map)
1615 {
1616 storage += map->gx_pixelmap_data_size;
1617
1618 if (map->gx_pixelmap_aux_data_size)
1619 {
1620 if (info->output_color_format != GX_COLOR_FORMAT_8BIT_PALETTE ||
1621 (info->palette_type == PALETTE_TYPE_PRIVATE && index == 0))
1622 {
1623 storage += map->gx_pixelmap_aux_data_size;
1624 }
1625 }
1626 }
1627 }
1628 }
1629
1630 return storage;
1631 }