19 #include "agg_font_freetype.h" 20 #include "agg_bitset_iterator.h" 21 #include "agg_renderer_scanline.h" 41 static const unsigned crc32tab[256] =
43 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
44 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
45 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
46 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
47 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
48 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
49 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
50 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
51 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
52 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
53 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
54 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
55 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
56 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
57 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
58 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
59 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
60 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
61 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
62 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
63 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
64 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
65 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
66 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
67 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
68 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
69 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
70 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
71 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
72 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
73 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
74 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
75 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
76 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
77 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
78 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
79 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
80 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
81 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
82 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
83 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
84 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
85 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
86 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
87 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
88 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
89 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
90 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
91 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
92 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
93 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
94 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
95 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
96 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
97 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
98 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
99 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
100 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
101 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
102 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
103 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
104 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
105 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
106 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
112 static unsigned calc_crc32(
const unsigned char* buf,
unsigned size)
114 unsigned crc = (unsigned)~0;
115 const unsigned char* p;
119 for (len += nr, p = buf; nr--; ++p)
121 crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff];
127 static inline int dbl_to_plain_fx(
double d)
129 return int(d * 65536.0);
133 static inline double int26p6_to_dbl(
int p)
135 return double(p) / 64.0;
139 static inline int dbl_to_int26p6(
double p)
141 return int(p * 64.0 + 0.5);
146 template<
class PathStorage>
147 bool decompose_ft_outline(
const FT_Outline& outline,
149 const trans_affine& mtx,
152 typedef typename PathStorage::value_type value_type;
157 double x1, y1, x2, y2, x3, y3;
169 for(n = 0; n < outline.n_contours; n++)
173 last = outline.contours[n];
174 limit = outline.points + last;
176 v_start = outline.points[first];
177 v_last = outline.points[last];
181 point = outline.points + first;
182 tags = outline.tags + first;
183 tag = FT_CURVE_TAG(tags[0]);
186 if(tag == FT_CURVE_TAG_CUBIC)
return false;
189 if( tag == FT_CURVE_TAG_CONIC)
192 if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON)
203 v_start.x = (v_start.x + v_last.x) / 2;
204 v_start.y = (v_start.y + v_last.y) / 2;
212 x1 = int26p6_to_dbl(v_start.x);
213 y1 = int26p6_to_dbl(v_start.y);
215 mtx.transform(&x1, &y1);
216 path.move_to(value_type(dbl_to_int26p6(x1)),
217 value_type(dbl_to_int26p6(y1)));
224 tag = FT_CURVE_TAG(tags[0]);
227 case FT_CURVE_TAG_ON:
229 x1 = int26p6_to_dbl(point->x);
230 y1 = int26p6_to_dbl(point->y);
232 mtx.transform(&x1, &y1);
233 path.line_to(value_type(dbl_to_int26p6(x1)),
234 value_type(dbl_to_int26p6(y1)));
239 case FT_CURVE_TAG_CONIC:
241 v_control.x = point->x;
242 v_control.y = point->y;
252 tag = FT_CURVE_TAG(tags[0]);
257 if(tag == FT_CURVE_TAG_ON)
259 x1 = int26p6_to_dbl(v_control.x);
260 y1 = int26p6_to_dbl(v_control.y);
261 x2 = int26p6_to_dbl(vec.x);
262 y2 = int26p6_to_dbl(vec.y);
263 if(flip_y) { y1 = -y1; y2 = -y2; }
264 mtx.transform(&x1, &y1);
265 mtx.transform(&x2, &y2);
266 path.curve3(value_type(dbl_to_int26p6(x1)),
267 value_type(dbl_to_int26p6(y1)),
268 value_type(dbl_to_int26p6(x2)),
269 value_type(dbl_to_int26p6(y2)));
273 if(tag != FT_CURVE_TAG_CONIC)
return false;
275 v_middle.x = (v_control.x + vec.x) / 2;
276 v_middle.y = (v_control.y + vec.y) / 2;
278 x1 = int26p6_to_dbl(v_control.x);
279 y1 = int26p6_to_dbl(v_control.y);
280 x2 = int26p6_to_dbl(v_middle.x);
281 y2 = int26p6_to_dbl(v_middle.y);
282 if(flip_y) { y1 = -y1; y2 = -y2; }
283 mtx.transform(&x1, &y1);
284 mtx.transform(&x2, &y2);
285 path.curve3(value_type(dbl_to_int26p6(x1)),
286 value_type(dbl_to_int26p6(y1)),
287 value_type(dbl_to_int26p6(x2)),
288 value_type(dbl_to_int26p6(y2)));
299 x1 = int26p6_to_dbl(v_control.x);
300 y1 = int26p6_to_dbl(v_control.y);
301 x2 = int26p6_to_dbl(v_start.x);
302 y2 = int26p6_to_dbl(v_start.y);
303 if(flip_y) { y1 = -y1; y2 = -y2; }
304 mtx.transform(&x1, &y1);
305 mtx.transform(&x2, &y2);
306 path.curve3(value_type(dbl_to_int26p6(x1)),
307 value_type(dbl_to_int26p6(y1)),
308 value_type(dbl_to_int26p6(x2)),
309 value_type(dbl_to_int26p6(y2)));
320 FT_Vector vec1, vec2;
322 if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
342 x1 = int26p6_to_dbl(vec1.x);
343 y1 = int26p6_to_dbl(vec1.y);
344 x2 = int26p6_to_dbl(vec2.x);
345 y2 = int26p6_to_dbl(vec2.y);
346 x3 = int26p6_to_dbl(vec.x);
347 y3 = int26p6_to_dbl(vec.y);
348 if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; }
349 mtx.transform(&x1, &y1);
350 mtx.transform(&x2, &y2);
351 mtx.transform(&x3, &y3);
352 path.curve4(value_type(dbl_to_int26p6(x1)),
353 value_type(dbl_to_int26p6(y1)),
354 value_type(dbl_to_int26p6(x2)),
355 value_type(dbl_to_int26p6(y2)),
356 value_type(dbl_to_int26p6(x3)),
357 value_type(dbl_to_int26p6(y3)));
368 x1 = int26p6_to_dbl(vec1.x);
369 y1 = int26p6_to_dbl(vec1.y);
370 x2 = int26p6_to_dbl(vec2.x);
371 y2 = int26p6_to_dbl(vec2.y);
372 x3 = int26p6_to_dbl(v_start.x);
373 y3 = int26p6_to_dbl(v_start.y);
374 if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; }
375 mtx.transform(&x1, &y1);
376 mtx.transform(&x2, &y2);
377 mtx.transform(&x3, &y3);
378 path.curve4(value_type(dbl_to_int26p6(x1)),
379 value_type(dbl_to_int26p6(y1)),
380 value_type(dbl_to_int26p6(x2)),
381 value_type(dbl_to_int26p6(y2)),
382 value_type(dbl_to_int26p6(x3)),
383 value_type(dbl_to_int26p6(y3)));
396 path.close_polygon();
408 template<
class Scanline,
class ScanlineStorage>
409 void decompose_ft_bitmap_mono(
const FT_Bitmap& bitmap,
413 ScanlineStorage& storage)
416 const int8u* buf = (
const int8u*)bitmap.buffer;
417 int pitch = bitmap.pitch;
418 sl.reset(x, x + bitmap.width);
422 buf += bitmap.pitch * (bitmap.rows - 1);
426 for(i = 0; i < bitmap.rows; i++)
429 bitset_iterator bits(buf, 0);
431 for(j = 0; j < bitmap.width; j++)
433 if(bits.bit()) sl.add_cell(x + j, cover_full);
439 sl.finalize(y - i - 1);
448 template<
class Rasterizer,
class Scanline,
class ScanlineStorage>
449 void decompose_ft_bitmap_gray8(
const FT_Bitmap& bitmap,
454 ScanlineStorage& storage)
457 const int8u* buf = (
const int8u*)bitmap.buffer;
458 int pitch = bitmap.pitch;
459 sl.reset(x, x + bitmap.width);
463 buf += bitmap.pitch * (bitmap.rows - 1);
467 for(i = 0; i < bitmap.rows; i++)
470 const int8u* p = buf;
471 for(j = 0; j < bitmap.width; j++)
473 if(*p) sl.add_cell(x + j, ras.apply_gamma(*p));
479 sl.finalize(y - i - 1);
498 font_engine_freetype_base::~font_engine_freetype_base()
501 for(i = 0; i < m_num_faces; ++i)
503 delete [] m_face_names[i];
504 FT_Done_Face(m_faces[i]);
506 delete [] m_face_names;
508 delete [] m_signature;
509 if(m_library_initialized) FT_Done_FreeType(m_library);
514 font_engine_freetype_base::font_engine_freetype_base(
bool flag32,
515 unsigned max_faces) :
520 m_name_len(256-16-1),
522 m_char_map(FT_ENCODING_NONE),
523 m_signature(new char [256+256-16]),
528 m_library_initialized(false),
530 m_faces(new FT_Face [max_faces]),
531 m_face_names(new char* [max_faces]),
533 m_max_faces(max_faces),
536 m_glyph_rendering(glyph_ren_native_gray8),
539 m_data_type(glyph_data_invalid),
546 m_curves16(m_path16),
547 m_curves32(m_path32),
554 m_curves16.approximation_scale(4.0);
555 m_curves32.approximation_scale(4.0);
556 m_last_error = FT_Init_FreeType(&m_library);
557 if(m_last_error == 0) m_library_initialized =
true;
563 void font_engine_freetype_base::resolution(
unsigned dpi)
571 int font_engine_freetype_base::find_face(
const char* face_name)
const 574 for(i = 0; i < m_num_faces; ++i)
576 if(std::strcmp(face_name, m_face_names[i]) == 0)
return i;
583 double font_engine_freetype_base::ascender()
const 587 return m_cur_face->ascender * height() / m_cur_face->height;
593 double font_engine_freetype_base::descender()
const 597 return m_cur_face->descender * height() / m_cur_face->height;
604 bool font_engine_freetype_base::load_font(
const char* font_name,
606 glyph_rendering ren_type,
607 const char* font_mem,
608 const long font_mem_size)
612 if(m_library_initialized)
616 int idx = find_face(font_name);
619 m_cur_face = m_faces[idx];
620 m_name = m_face_names[idx];
624 if(m_num_faces >= m_max_faces)
626 delete [] m_face_names[0];
627 FT_Done_Face(m_faces[0]);
630 (m_max_faces - 1) *
sizeof(FT_Face));
631 std::memcpy(m_face_names,
633 (m_max_faces - 1) *
sizeof(
char*));
634 m_num_faces = m_max_faces - 1;
637 if (font_mem && font_mem_size)
639 m_last_error = FT_New_Memory_Face(m_library,
640 (
const FT_Byte*)font_mem,
643 &m_faces[m_num_faces]);
647 m_last_error = FT_New_Face(m_library,
650 &m_faces[m_num_faces]);
653 if(m_last_error == 0)
655 m_face_names[m_num_faces] =
new char [std::strlen(font_name) + 1];
656 std::strcpy(m_face_names[m_num_faces], font_name);
657 m_cur_face = m_faces[m_num_faces];
658 m_name = m_face_names[m_num_faces];
663 m_face_names[m_num_faces] = 0;
670 if(m_last_error == 0)
676 case glyph_ren_native_mono:
677 m_glyph_rendering = glyph_ren_native_mono;
680 case glyph_ren_native_gray8:
681 m_glyph_rendering = glyph_ren_native_gray8;
684 case glyph_ren_outline:
685 if(FT_IS_SCALABLE(m_cur_face))
687 m_glyph_rendering = glyph_ren_outline;
691 m_glyph_rendering = glyph_ren_native_gray8;
695 case glyph_ren_agg_mono:
696 if(FT_IS_SCALABLE(m_cur_face))
698 m_glyph_rendering = glyph_ren_agg_mono;
702 m_glyph_rendering = glyph_ren_native_mono;
706 case glyph_ren_agg_gray8:
707 if(FT_IS_SCALABLE(m_cur_face))
709 m_glyph_rendering = glyph_ren_agg_gray8;
713 m_glyph_rendering = glyph_ren_native_gray8;
725 bool font_engine_freetype_base::attach(
const char* file_name)
729 m_last_error = FT_Attach_File(m_cur_face, file_name);
730 return m_last_error == 0;
736 unsigned font_engine_freetype_base::num_faces()
const 740 return m_cur_face->num_faces;
746 bool font_engine_freetype_base::char_map(FT_Encoding map)
750 m_last_error = FT_Select_Charmap(m_cur_face, map);
751 if(m_last_error == 0)
762 bool font_engine_freetype_base::height(
double h)
764 m_height = int(h * 64.0);
774 bool font_engine_freetype_base::width(
double w)
776 m_width = int(w * 64.0);
786 void font_engine_freetype_base::hinting(
bool h)
796 void font_engine_freetype_base::flip_y(
bool f)
806 void font_engine_freetype_base::transform(
const trans_affine& affine)
816 void font_engine_freetype_base::update_signature()
818 if(m_cur_face && m_name)
820 unsigned name_len = std::strlen(m_name);
821 if(name_len > m_name_len)
823 delete [] m_signature;
824 m_signature =
new char [name_len + 32 + 256];
825 m_name_len = name_len + 32 - 1;
828 unsigned gamma_hash = 0;
829 if(m_glyph_rendering == glyph_ren_native_gray8 ||
830 m_glyph_rendering == glyph_ren_agg_mono ||
831 m_glyph_rendering == glyph_ren_agg_gray8)
833 unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale];
835 for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i)
837 gamma_table[i] = m_rasterizer.apply_gamma(i);
839 gamma_hash = calc_crc32(gamma_table,
sizeof(gamma_table));
842 std::sprintf(m_signature,
843 "%s,%u,%d,%d,%d:%dx%d,%d,%d,%08X",
847 int(m_glyph_rendering),
854 if(m_glyph_rendering == glyph_ren_outline ||
855 m_glyph_rendering == glyph_ren_agg_mono ||
856 m_glyph_rendering == glyph_ren_agg_gray8)
860 m_affine.store_to(mtx);
861 std::sprintf(buf,
",%08X%08X%08X%08X%08X%08X",
862 dbl_to_plain_fx(mtx[0]),
863 dbl_to_plain_fx(mtx[1]),
864 dbl_to_plain_fx(mtx[2]),
865 dbl_to_plain_fx(mtx[3]),
866 dbl_to_plain_fx(mtx[4]),
867 dbl_to_plain_fx(mtx[5]));
868 std::strcat(m_signature, buf);
876 void font_engine_freetype_base::update_char_size()
882 FT_Set_Char_Size(m_cur_face,
890 FT_Set_Pixel_Sizes(m_cur_face,
903 bool font_engine_freetype_base::prepare_glyph(
unsigned glyph_code)
905 m_glyph_index = FT_Get_Char_Index(m_cur_face, glyph_code);
906 m_last_error = FT_Load_Glyph(m_cur_face,
908 m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING);
910 if(m_last_error == 0)
912 switch(m_glyph_rendering)
914 case glyph_ren_native_mono:
915 m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_MONO);
916 if(m_last_error == 0)
918 decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap,
919 m_cur_face->glyph->bitmap_left,
920 m_flip_y ? -m_cur_face->glyph->bitmap_top :
921 m_cur_face->glyph->bitmap_top,
925 m_bounds.x1 = m_scanlines_bin.min_x();
926 m_bounds.y1 = m_scanlines_bin.min_y();
927 m_bounds.x2 = m_scanlines_bin.max_x() + 1;
928 m_bounds.y2 = m_scanlines_bin.max_y() + 1;
929 m_data_size = m_scanlines_bin.byte_size();
930 m_data_type = glyph_data_mono;
931 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
932 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
938 case glyph_ren_native_gray8:
939 m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL);
940 if(m_last_error == 0)
942 decompose_ft_bitmap_gray8(m_cur_face->glyph->bitmap,
943 m_cur_face->glyph->bitmap_left,
944 m_flip_y ? -m_cur_face->glyph->bitmap_top :
945 m_cur_face->glyph->bitmap_top,
950 m_bounds.x1 = m_scanlines_aa.min_x();
951 m_bounds.y1 = m_scanlines_aa.min_y();
952 m_bounds.x2 = m_scanlines_aa.max_x() + 1;
953 m_bounds.y2 = m_scanlines_aa.max_y() + 1;
954 m_data_size = m_scanlines_aa.byte_size();
955 m_data_type = glyph_data_gray8;
956 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
957 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
963 case glyph_ren_outline:
964 if(m_last_error == 0)
968 m_path32.remove_all();
969 if(decompose_ft_outline(m_cur_face->glyph->outline,
974 rect_d bnd = m_path32.bounding_rect();
975 m_data_size = m_path32.byte_size();
976 m_data_type = glyph_data_outline;
977 m_bounds.x1 = int(floor(bnd.x1));
978 m_bounds.y1 = int(floor(bnd.y1));
979 m_bounds.x2 = int(ceil(bnd.x2));
980 m_bounds.y2 = int(ceil(bnd.y2));
981 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
982 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
983 m_affine.transform(&m_advance_x, &m_advance_y);
989 m_path16.remove_all();
990 if(decompose_ft_outline(m_cur_face->glyph->outline,
995 rect_d bnd = m_path16.bounding_rect();
996 m_data_size = m_path16.byte_size();
997 m_data_type = glyph_data_outline;
998 m_bounds.x1 = int(floor(bnd.x1));
999 m_bounds.y1 = int(floor(bnd.y1));
1000 m_bounds.x2 = int(ceil(bnd.x2));
1001 m_bounds.y2 = int(ceil(bnd.y2));
1002 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1003 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1004 m_affine.transform(&m_advance_x, &m_advance_y);
1011 case glyph_ren_agg_mono:
1012 if(m_last_error == 0)
1014 m_rasterizer.reset();
1017 m_path32.remove_all();
1018 decompose_ft_outline(m_cur_face->glyph->outline,
1022 m_rasterizer.add_path(m_curves32);
1026 m_path16.remove_all();
1027 decompose_ft_outline(m_cur_face->glyph->outline,
1031 m_rasterizer.add_path(m_curves16);
1033 m_scanlines_bin.prepare();
1034 render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin);
1035 m_bounds.x1 = m_scanlines_bin.min_x();
1036 m_bounds.y1 = m_scanlines_bin.min_y();
1037 m_bounds.x2 = m_scanlines_bin.max_x() + 1;
1038 m_bounds.y2 = m_scanlines_bin.max_y() + 1;
1039 m_data_size = m_scanlines_bin.byte_size();
1040 m_data_type = glyph_data_mono;
1041 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1042 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1043 m_affine.transform(&m_advance_x, &m_advance_y);
1049 case glyph_ren_agg_gray8:
1050 if(m_last_error == 0)
1052 m_rasterizer.reset();
1055 m_path32.remove_all();
1056 decompose_ft_outline(m_cur_face->glyph->outline,
1060 m_rasterizer.add_path(m_curves32);
1064 m_path16.remove_all();
1065 decompose_ft_outline(m_cur_face->glyph->outline,
1069 m_rasterizer.add_path(m_curves16);
1071 m_scanlines_aa.prepare();
1072 render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa);
1073 m_bounds.x1 = m_scanlines_aa.min_x();
1074 m_bounds.y1 = m_scanlines_aa.min_y();
1075 m_bounds.x2 = m_scanlines_aa.max_x() + 1;
1076 m_bounds.y2 = m_scanlines_aa.max_y() + 1;
1077 m_data_size = m_scanlines_aa.byte_size();
1078 m_data_type = glyph_data_gray8;
1079 m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1080 m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1081 m_affine.transform(&m_advance_x, &m_advance_y);
1094 void font_engine_freetype_base::write_glyph_to(int8u* data)
const 1096 if(data && m_data_size)
1101 case glyph_data_mono: m_scanlines_bin.serialize(data);
break;
1102 case glyph_data_gray8: m_scanlines_aa.serialize(data);
break;
1103 case glyph_data_outline:
1106 m_path32.serialize(data);
1110 m_path16.serialize(data);
1113 case glyph_data_invalid:
break;
1121 bool font_engine_freetype_base::add_kerning(
unsigned first,
unsigned second,
1122 double* x,
double* y)
1124 if(m_cur_face && first && second && FT_HAS_KERNING(m_cur_face))
1127 FT_Get_Kerning(m_cur_face, first, second,
1128 FT_KERNING_DEFAULT, &delta);
1129 double dx = int26p6_to_dbl(delta.x);
1130 double dy = int26p6_to_dbl(delta.y);
1131 if(m_glyph_rendering == glyph_ren_outline ||
1132 m_glyph_rendering == glyph_ren_agg_mono ||
1133 m_glyph_rendering == glyph_ren_agg_gray8)
1135 m_affine.transform_2x2(&dx, &dy);