18 #include "agg_font_win32_tt.h" 19 #include "agg_bitset_iterator.h" 20 #include "agg_renderer_scanline.h" 22 #ifdef AGG_WIN9X_COMPLIANT 23 #define GetGlyphOutlineX GetGlyphOutline 25 #define GetGlyphOutlineX GetGlyphOutlineW 45 static const unsigned crc32tab[256] =
47 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
48 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
49 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
50 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
51 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
52 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
53 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
54 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
55 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
56 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
57 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
58 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
59 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
60 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
61 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
62 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
63 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
64 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
65 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
66 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
67 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
68 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
69 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
70 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
71 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
72 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
73 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
74 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
75 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
76 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
77 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
78 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
79 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
80 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
81 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
82 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
83 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
84 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
85 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
86 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
87 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
88 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
89 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
90 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
91 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
92 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
93 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
94 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
95 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
96 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
97 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
98 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
99 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
100 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
101 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
102 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
103 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
104 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
105 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
106 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
107 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
108 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
109 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
110 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
114 static unsigned calc_crc32(
const unsigned char* buf,
unsigned size)
116 unsigned crc = (unsigned)~0;
117 const unsigned char* p;
121 for (len += nr, p = buf; nr--; ++p)
123 crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff];
129 static inline FIXED dbl_to_fx(
double d)
132 l = int(d * 65536.0);
137 static inline int dbl_to_plain_fx(
double d)
139 return int(d * 65536.0);
143 static inline FIXED negate_fx(
const FIXED& fx)
145 int l = -(*(
int*)(&fx));
150 static inline double fx_to_dbl(
const FIXED& p)
152 return double(p.value) + double(p.fract) * (1.0 / 65536.0);
156 static inline int fx_to_plain_int(
const FIXED& fx)
162 static inline int fx_to_int26p6(
const FIXED& p)
164 return (
int(p.value) << 6) + (int(p.fract) >> 10);
168 static inline int dbl_to_int26p6(
double p)
170 return int(p * 64.0 + 0.5);
174 template<
class Scanline,
class ScanlineStorage>
175 void decompose_win32_glyph_bitmap_mono(
const char* gbuf,
180 ScanlineStorage& storage)
183 int pitch = ((w + 31) >> 5) << 2;
184 const int8u* buf = (
const int8u*)gbuf;
189 buf += pitch * (h - 1);
193 for(i = 0; i < h; i++)
196 bitset_iterator bits(buf, 0);
198 for(j = 0; j < w; j++)
200 if(bits.bit()) sl.add_cell(x + j, cover_full);
206 sl.finalize(y - i - 1);
215 template<
class Rasterizer,
class Scanline,
class ScanlineStorage>
216 void decompose_win32_glyph_bitmap_gray8(
const char* gbuf,
222 ScanlineStorage& storage)
225 int pitch = ((w + 3) >> 2) << 2;
226 const int8u* buf = (
const int8u*)gbuf;
231 buf += pitch * (h - 1);
235 for(i = 0; i < h; i++)
238 const int8u* p = buf;
239 for(j = 0; j < w; j++)
246 sl.add_cell(x + j, ras.apply_gamma(v));
253 sl.finalize(y - i - 1);
262 template<
class PathStorage>
263 bool decompose_win32_glyph_outline(
const char* gbuf,
266 const trans_affine& mtx,
269 const char* cur_glyph = gbuf;
270 const char* end_glyph = gbuf + total_size;
272 typedef typename PathStorage::value_type value_type;
274 while(cur_glyph < end_glyph)
276 const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
278 const char* end_poly = cur_glyph + th->cb;
279 const char* cur_poly = cur_glyph +
sizeof(TTPOLYGONHEADER);
281 x = fx_to_dbl(th->pfxStart.x);
282 y = fx_to_dbl(th->pfxStart.y);
284 mtx.transform(&x, &y);
285 path.move_to(value_type(dbl_to_int26p6(x)),
286 value_type(dbl_to_int26p6(y)));
288 while(cur_poly < end_poly)
290 const TTPOLYCURVE* pc = (
const TTPOLYCURVE*)cur_poly;
292 if (pc->wType == TT_PRIM_LINE)
295 for (i = 0; i < pc->cpfx; i++)
297 x = fx_to_dbl(pc->apfx[i].x);
298 y = fx_to_dbl(pc->apfx[i].y);
300 mtx.transform(&x, &y);
301 path.line_to(value_type(dbl_to_int26p6(x)),
302 value_type(dbl_to_int26p6(y)));
306 if (pc->wType == TT_PRIM_QSPLINE)
309 for (u = 0; u < pc->cpfx - 1; u++)
311 POINTFX pnt_b = pc->apfx[u];
312 POINTFX pnt_c = pc->apfx[u+1];
314 if (u < pc->cpfx - 2)
317 *(
int*)&pnt_c.x = (*(
int*)&pnt_b.x + *(
int*)&pnt_c.x) / 2;
318 *(
int*)&pnt_c.y = (*(
int*)&pnt_b.y + *(
int*)&pnt_c.y) / 2;
322 x = fx_to_dbl(pnt_b.x);
323 y = fx_to_dbl(pnt_b.y);
324 x2 = fx_to_dbl(pnt_c.x);
325 y2 = fx_to_dbl(pnt_c.y);
326 if(flip_y) { y = -y; y2 = -y2; }
327 mtx.transform(&x, &y);
328 mtx.transform(&x2, &y2);
329 path.curve3(value_type(dbl_to_int26p6(x)),
330 value_type(dbl_to_int26p6(y)),
331 value_type(dbl_to_int26p6(x2)),
332 value_type(dbl_to_int26p6(y2)));
335 cur_poly +=
sizeof(WORD) * 2 +
sizeof(POINTFX) * pc->cpfx;
346 font_engine_win32_tt_base::~font_engine_win32_tt_base()
348 delete [] m_kerning_pairs;
350 delete [] m_signature;
351 delete [] m_typeface;
352 if(m_dc && m_old_font) ::SelectObject(m_dc, m_old_font);
354 for(i = 0; i < m_num_fonts; ++i)
356 delete [] m_font_names[i];
357 ::DeleteObject(m_fonts[i]);
359 delete [] m_font_names;
366 font_engine_win32_tt_base::font_engine_win32_tt_base(
bool flag32,
368 unsigned max_fonts) :
371 m_old_font(m_dc ? (HFONT)::GetCurrentObject(m_dc, OBJ_FONT) : 0),
372 m_fonts(new HFONT [max_fonts]),
374 m_max_fonts(max_fonts),
375 m_font_names(new char* [max_fonts]),
379 m_typeface(new char [256-16]),
380 m_typeface_len(256-16-1),
381 m_signature(new char [256+256-16]),
384 m_weight(FW_REGULAR),
386 m_char_set(DEFAULT_CHARSET),
387 m_pitch_and_family(FF_DONTCARE),
390 m_font_created(false),
392 m_glyph_rendering(glyph_ren_native_gray8),
395 m_data_type(glyph_data_invalid),
399 m_gbuf(new char [buf_size]),
401 m_num_kerning_pairs(0),
402 m_max_kerning_pairs(0),
406 m_curves16(m_path16),
407 m_curves32(m_path32),
414 m_curves16.approximation_scale(4.0);
415 m_curves32.approximation_scale(4.0);
416 std::memset(&m_matrix, 0,
sizeof(m_matrix));
417 m_matrix.eM11.value = 1;
418 m_matrix.eM22.value = 1;
424 int font_engine_win32_tt_base::find_font(
const char* name)
const 427 for(i = 0; i < m_num_fonts; ++i)
429 if(std::strcmp(name, m_font_names[i]) == 0)
return i;
435 bool font_engine_win32_tt_base::create_font(
const char* typeface_,
436 glyph_rendering ren_type)
440 unsigned len = strlen(typeface_);
441 if(len > m_typeface_len)
443 delete [] m_signature;
444 delete [] m_typeface;
445 m_typeface =
new char [len + 32];
446 m_signature =
new char [len + 32 + 256];
447 m_typeface_len = len + 32 - 1;
450 strcpy(m_typeface, typeface_);
457 h = ::MulDiv(m_height, m_resolution, 72);
458 w = ::MulDiv(m_width, m_resolution, 72);
461 m_glyph_rendering = ren_type;
463 int idx = find_font(m_signature);
466 m_cur_font = m_fonts[idx];
467 ::SelectObject(m_dc, m_cur_font);
468 m_num_kerning_pairs = 0;
473 m_cur_font = ::CreateFont(-h,
489 if(m_num_fonts >= m_max_fonts)
491 delete [] m_font_names[0];
492 if(m_old_font) ::SelectObject(m_dc, m_old_font);
493 ::DeleteObject(m_fonts[0]);
496 (m_max_fonts - 1) *
sizeof(HFONT));
497 std::memcpy(m_font_names,
499 (m_max_fonts - 1) *
sizeof(
char*));
500 m_num_fonts = m_max_fonts - 1;
504 m_font_names[m_num_fonts] =
new char[std::strlen(m_signature) + 1];
505 std::strcpy(m_font_names[m_num_fonts], m_signature);
506 m_fonts[m_num_fonts] = m_cur_font;
508 ::SelectObject(m_dc, m_cur_font);
509 m_num_kerning_pairs = 0;
522 bool font_engine_win32_tt_base::create_font(
const char* typeface_,
523 glyph_rendering ren_type,
529 DWORD pitch_and_family_)
536 pitch_and_family(pitch_and_family_);
537 return create_font(typeface_, ren_type);
544 void font_engine_win32_tt_base::update_signature()
547 if(m_dc && m_cur_font)
549 unsigned gamma_hash = 0;
550 if(m_glyph_rendering == glyph_ren_native_gray8 ||
551 m_glyph_rendering == glyph_ren_agg_mono ||
552 m_glyph_rendering == glyph_ren_agg_gray8)
554 unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale];
556 for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i)
558 gamma_table[i] = m_rasterizer.apply_gamma(i);
560 gamma_hash = calc_crc32(gamma_table,
sizeof(gamma_table));
564 "%s,%u,%d,%d:%dx%d,%d,%d,%d,%d,%d,%08X",
567 int(m_glyph_rendering),
575 int(m_pitch_and_family),
578 if(m_glyph_rendering == glyph_ren_outline ||
579 m_glyph_rendering == glyph_ren_agg_mono ||
580 m_glyph_rendering == glyph_ren_agg_gray8)
584 m_affine.store_to(mtx);
585 std::sprintf(buf,
",%08X%08X%08X%08X%08X%08X",
586 dbl_to_plain_fx(mtx[0]),
587 dbl_to_plain_fx(mtx[1]),
588 dbl_to_plain_fx(mtx[2]),
589 dbl_to_plain_fx(mtx[3]),
590 dbl_to_plain_fx(mtx[4]),
591 dbl_to_plain_fx(mtx[5]));
592 std::strcat(m_signature, buf);
601 bool font_engine_win32_tt_base::prepare_glyph(
unsigned glyph_code)
603 if(m_dc && m_cur_font)
605 int format = GGO_BITMAP;
607 switch(m_glyph_rendering)
609 case glyph_ren_native_gray8:
610 format = GGO_GRAY8_BITMAP;
613 case glyph_ren_outline:
614 case glyph_ren_agg_mono:
615 case glyph_ren_agg_gray8:
620 #ifndef GGO_UNHINTED // For compatibility with old SDKs. 621 #define GGO_UNHINTED 0x0100 623 if(!m_hinting) format |= GGO_UNHINTED;
626 int total_size = GetGlyphOutlineX(m_dc,
641 int total_size = GetGlyphOutlineX(m_dc,
649 if(total_size < 0)
return false;
650 gm.gmBlackBoxX = gm.gmBlackBoxY = 0;
654 m_glyph_index = glyph_code;
655 m_advance_x = gm.gmCellIncX;
656 m_advance_y = -gm.gmCellIncY;
658 switch(m_glyph_rendering)
660 case glyph_ren_native_mono:
661 decompose_win32_glyph_bitmap_mono(m_gbuf,
664 gm.gmptGlyphOrigin.x,
665 m_flip_y ? -gm.gmptGlyphOrigin.y :
666 gm.gmptGlyphOrigin.y,
670 m_bounds.x1 = m_scanlines_bin.min_x();
671 m_bounds.y1 = m_scanlines_bin.min_y();
672 m_bounds.x2 = m_scanlines_bin.max_x() + 1;
673 m_bounds.y2 = m_scanlines_bin.max_y() + 1;
674 m_data_size = m_scanlines_bin.byte_size();
675 m_data_type = glyph_data_mono;
678 case glyph_ren_native_gray8:
679 decompose_win32_glyph_bitmap_gray8(m_gbuf,
682 gm.gmptGlyphOrigin.x,
683 m_flip_y ? -gm.gmptGlyphOrigin.y :
684 gm.gmptGlyphOrigin.y,
689 m_bounds.x1 = m_scanlines_aa.min_x();
690 m_bounds.y1 = m_scanlines_aa.min_y();
691 m_bounds.x2 = m_scanlines_aa.max_x() + 1;
692 m_bounds.y2 = m_scanlines_aa.max_y() + 1;
693 m_data_size = m_scanlines_aa.byte_size();
694 m_data_type = glyph_data_gray8;
697 case glyph_ren_outline:
698 m_affine.transform(&m_advance_x, &m_advance_y);
701 m_path32.remove_all();
702 if(decompose_win32_glyph_outline(m_gbuf,
708 rect_d bnd = m_path32.bounding_rect();
709 m_data_size = m_path32.byte_size();
710 m_data_type = glyph_data_outline;
711 m_bounds.x1 = int(floor(bnd.x1));
712 m_bounds.y1 = int(floor(bnd.y1));
713 m_bounds.x2 = int(ceil(bnd.x2));
714 m_bounds.y2 = int(ceil(bnd.y2));
720 m_path16.remove_all();
721 if(decompose_win32_glyph_outline(m_gbuf,
727 rect_d bnd = m_path16.bounding_rect();
728 m_data_size = m_path16.byte_size();
729 m_data_type = glyph_data_outline;
730 m_bounds.x1 = int(floor(bnd.x1));
731 m_bounds.y1 = int(floor(bnd.y1));
732 m_bounds.x2 = int(ceil(bnd.x2));
733 m_bounds.y2 = int(ceil(bnd.y2));
739 case glyph_ren_agg_mono:
740 m_rasterizer.reset();
741 m_affine.transform(&m_advance_x, &m_advance_y);
744 m_path32.remove_all();
745 decompose_win32_glyph_outline(m_gbuf,
750 m_rasterizer.add_path(m_curves32);
754 m_path16.remove_all();
755 decompose_win32_glyph_outline(m_gbuf,
760 m_rasterizer.add_path(m_curves16);
762 m_scanlines_bin.prepare();
763 render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin);
764 m_bounds.x1 = m_scanlines_bin.min_x();
765 m_bounds.y1 = m_scanlines_bin.min_y();
766 m_bounds.x2 = m_scanlines_bin.max_x() + 1;
767 m_bounds.y2 = m_scanlines_bin.max_y() + 1;
768 m_data_size = m_scanlines_bin.byte_size();
769 m_data_type = glyph_data_mono;
772 case glyph_ren_agg_gray8:
773 m_rasterizer.reset();
774 m_affine.transform(&m_advance_x, &m_advance_y);
777 m_path32.remove_all();
778 decompose_win32_glyph_outline(m_gbuf,
783 m_rasterizer.add_path(m_curves32);
787 m_path16.remove_all();
788 decompose_win32_glyph_outline(m_gbuf,
793 m_rasterizer.add_path(m_curves16);
795 m_scanlines_aa.prepare();
796 render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa);
797 m_bounds.x1 = m_scanlines_aa.min_x();
798 m_bounds.y1 = m_scanlines_aa.min_y();
799 m_bounds.x2 = m_scanlines_aa.max_x() + 1;
800 m_bounds.y2 = m_scanlines_aa.max_y() + 1;
801 m_data_size = m_scanlines_aa.byte_size();
802 m_data_type = glyph_data_gray8;
812 void font_engine_win32_tt_base::write_glyph_to(int8u* data)
const 814 if(data && m_data_size)
818 case glyph_data_mono: m_scanlines_bin.serialize(data);
break;
819 case glyph_data_gray8: m_scanlines_aa.serialize(data);
break;
820 case glyph_data_outline:
823 m_path32.serialize(data);
827 m_path16.serialize(data);
837 static bool pair_less(
const KERNINGPAIR& v1,
const KERNINGPAIR& v2)
839 if(v1.wFirst != v2.wFirst)
return v1.wFirst < v2.wFirst;
840 return v1.wSecond < v2.wSecond;
845 void font_engine_win32_tt_base::sort_kerning_pairs()
847 pod_array_adaptor<KERNINGPAIR> pairs(m_kerning_pairs, m_num_kerning_pairs);
848 quick_sort(pairs, pair_less);
854 void font_engine_win32_tt_base::load_kerning_pairs()
856 if(m_dc && m_cur_font)
858 if(m_kerning_pairs == 0)
860 m_kerning_pairs =
new KERNINGPAIR [16384-16];
861 m_max_kerning_pairs = 16384-16;
863 m_num_kerning_pairs = ::GetKerningPairs(m_dc,
867 if(m_num_kerning_pairs)
873 for(i = 1; i < m_num_kerning_pairs; ++i)
875 if(!pair_less(m_kerning_pairs[i - 1], m_kerning_pairs[i]))
877 sort_kerning_pairs();
887 bool font_engine_win32_tt_base::add_kerning(
unsigned first,
unsigned second,
888 double* x,
double* y)
890 if(m_dc && m_cur_font)
892 if(m_num_kerning_pairs == 0)
894 load_kerning_pairs();
897 int end = m_num_kerning_pairs - 1;
900 t.wFirst = (WORD)first;
901 t.wSecond = (WORD)second;
904 int mid = (end + beg) / 2;
905 if(m_kerning_pairs[mid].wFirst == t.wFirst &&
906 m_kerning_pairs[mid].wSecond == t.wSecond)
908 double dx = m_kerning_pairs[mid].iKernAmount;
910 if(m_glyph_rendering == glyph_ren_outline ||
911 m_glyph_rendering == glyph_ren_agg_mono ||
912 m_glyph_rendering == glyph_ren_agg_gray8)
914 m_affine.transform_2x2(&dx, &dy);
921 if(pair_less(t, m_kerning_pairs[mid]))