src/AggDevice.h
changed.
src/agg/src/agg_font_freetype.cpp
changed.
src/text_renderer.h
changed.
src/ragg.h
changed.
src/AggDevice16.h
changed.
98 | 98 | unsigned data_size() const { return m_data_size; } |
|
99 | 99 | glyph_data_type data_type() const { return m_data_type; } |
|
100 | 100 | const rect_i& bounds() const { return m_bounds; } |
|
101 | + | double ascent() const { return double(m_cur_face->size->metrics.ascender) / 64;} |
|
102 | + | double descent() const { return double(m_cur_face->size->metrics.descender) / 64;} |
|
103 | + | double max_advance() const { return double(m_cur_face->size->metrics.max_advance) / 64;} |
|
101 | 104 | double advance_x() const { return m_advance_x; } |
|
102 | 105 | double advance_y() const { return m_advance_y; } |
|
103 | 106 | void write_glyph_to(int8u* data) const; |
30 | 30 | * regardless. The base class outputs images in ppm format which is not realy |
|
31 | 31 | * a usable format. See png and tiff versions for actual usable classes. |
|
32 | 32 | */ |
|
33 | - | template<class PIXFMT, class R_COLOR = agg::rgba8> |
|
33 | + | template<class PIXFMT, class R_COLOR = agg::rgba8, typename BLNDFMT = pixfmt_type_32> |
|
34 | 34 | class AggDevice { |
|
35 | 35 | public: |
|
36 | 36 | typedef PIXFMT pixfmt_type; |
63 | 63 | double res_mod; |
|
64 | 64 | double lwd_mod; |
|
65 | 65 | ||
66 | - | TextRenderer t_ren; |
|
66 | + | TextRenderer<BLNDFMT> t_ren; |
|
67 | 67 | ||
68 | 68 | // Lifecycle methods |
|
69 | 69 | AggDevice(const char* fp, int w, int h, double ps, int bg, double res, |
156 | 156 | /* The initialiser takes care of setting up the buffer, and caching a pixel |
|
157 | 157 | * formatter and renderer. |
|
158 | 158 | */ |
|
159 | - | template<class PIXFMT, class R_COLOR> |
|
160 | - | AggDevice<PIXFMT, R_COLOR>::AggDevice(const char* fp, int w, int h, double ps, |
|
161 | - | int bg, double res, double scaling) : |
|
159 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
160 | + | AggDevice<PIXFMT, R_COLOR, BLNDFMT>::AggDevice(const char* fp, int w, int h, double ps, |
|
161 | + | int bg, double res, double scaling) : |
|
162 | 162 | width(w), |
|
163 | 163 | height(h), |
|
164 | 164 | clip_left(0), |
181 | 181 | background = convertColour(background_int); |
|
182 | 182 | renderer.clear(background); |
|
183 | 183 | } |
|
184 | - | template<class PIXFMT, class R_COLOR> |
|
185 | - | AggDevice<PIXFMT, R_COLOR>::~AggDevice() { |
|
184 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
185 | + | AggDevice<PIXFMT, R_COLOR, BLNDFMT>::~AggDevice() { |
|
186 | 186 | delete pixf; |
|
187 | 187 | delete [] buffer; |
|
188 | 188 | } |
191 | 191 | * appropriate savePage() method. For screen devices it may make sense to change |
|
192 | 192 | * it for performance |
|
193 | 193 | */ |
|
194 | - | template<class PIXFMT, class R_COLOR> |
|
195 | - | void AggDevice<PIXFMT, R_COLOR>::newPage(unsigned int bg) { |
|
194 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
195 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::newPage(unsigned int bg) { |
|
196 | 196 | if (pageno != 0) { |
|
197 | 197 | if (!savePage()) { |
|
198 | 198 | Rf_warning("agg could not write to the given file"); |
206 | 206 | } |
|
207 | 207 | pageno++; |
|
208 | 208 | } |
|
209 | - | template<class PIXFMT, class R_COLOR> |
|
210 | - | void AggDevice<PIXFMT, R_COLOR>::close() { |
|
209 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
210 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::close() { |
|
211 | 211 | if (pageno == 0) pageno++; |
|
212 | 212 | if (!savePage()) { |
|
213 | 213 | Rf_warning("agg could not write to the given file"); |
|
214 | 214 | } |
|
215 | 215 | } |
|
216 | 216 | ||
217 | - | template<class PIXFMT, class R_COLOR> |
|
218 | - | SEXP AggDevice<PIXFMT, R_COLOR>::capture() { |
|
217 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
218 | + | SEXP AggDevice<PIXFMT, R_COLOR, BLNDFMT>::capture() { |
|
219 | 219 | return Rf_allocVector(INTSXP, 0); |
|
220 | 220 | } |
|
221 | 221 |
223 | 223 | * may be specified as a printf string with room for a page counter, so the |
|
224 | 224 | * method should take care of resolving that together with the pageno field. |
|
225 | 225 | */ |
|
226 | - | template<class PIXFMT, class R_COLOR> |
|
227 | - | bool AggDevice<PIXFMT, R_COLOR>::savePage() { |
|
226 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
227 | + | bool AggDevice<PIXFMT, R_COLOR, BLNDFMT>::savePage() { |
|
228 | 228 | return true; |
|
229 | 229 | } |
|
230 | 230 |
235 | 235 | * gain the different drawing methods should set it on the rasterizer as well |
|
236 | 236 | * to avoid unneccesary allocation and looping |
|
237 | 237 | */ |
|
238 | - | template<class PIXFMT, class R_COLOR> |
|
239 | - | void AggDevice<PIXFMT, R_COLOR>::clipRect(double x0, double y0, double x1, |
|
238 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
239 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::clipRect(double x0, double y0, double x1, |
|
240 | 240 | double y1) { |
|
241 | 241 | clip_left = x0; |
|
242 | 242 | clip_right = x1; |
251 | 251 | * They work on gray8 bitmap to speed it up as all metrixs are assumed to be in |
|
252 | 252 | * horizontal mode only |
|
253 | 253 | */ |
|
254 | - | template<class PIXFMT, class R_COLOR> |
|
255 | - | double AggDevice<PIXFMT, R_COLOR>::stringWidth(const char *str, |
|
254 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
255 | + | double AggDevice<PIXFMT, R_COLOR, BLNDFMT>::stringWidth(const char *str, |
|
256 | 256 | const char *family, int face, |
|
257 | 257 | double size) { |
|
258 | 258 | size *= res_mod; |
263 | 263 | ||
264 | 264 | return t_ren.get_text_width(str); |
|
265 | 265 | } |
|
266 | - | template<class PIXFMT, class R_COLOR> |
|
267 | - | void AggDevice<PIXFMT, R_COLOR>::charMetric(int c, const char *family, int face, |
|
266 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
267 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::charMetric(int c, const char *family, int face, |
|
268 | 268 | double size, double *ascent, double *descent, |
|
269 | 269 | double *width) { |
|
270 | 270 | if (c < 0) { |
296 | 296 | * number of points around the circle is precalculated below a radius of 64 |
|
297 | 297 | * pixels in order to speed up point rendering |
|
298 | 298 | */ |
|
299 | - | template<class PIXFMT, class R_COLOR> |
|
300 | - | void AggDevice<PIXFMT, R_COLOR>::drawCircle(double x, double y, double r, |
|
299 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
300 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::drawCircle(double x, double y, double r, |
|
301 | 301 | int fill, int col, double lwd, |
|
302 | 302 | int lty, R_GE_lineend lend) { |
|
303 | 303 | bool draw_fill = visibleColour(fill); |
349 | 349 | } |
|
350 | 350 | } |
|
351 | 351 | ||
352 | - | template<class PIXFMT, class R_COLOR> |
|
353 | - | void AggDevice<PIXFMT, R_COLOR>::drawRect(double x0, double y0, double x1, |
|
352 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
353 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::drawRect(double x0, double y0, double x1, |
|
354 | 354 | double y1, int fill, int col, |
|
355 | 355 | double lwd, int lty, |
|
356 | 356 | R_GE_lineend lend) { |
395 | 395 | } |
|
396 | 396 | } |
|
397 | 397 | ||
398 | - | template<class PIXFMT, class R_COLOR> |
|
399 | - | void AggDevice<PIXFMT, R_COLOR>::drawPolygon(int n, double *x, double *y, |
|
398 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
399 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::drawPolygon(int n, double *x, double *y, |
|
400 | 400 | int fill, int col, double lwd, |
|
401 | 401 | int lty, R_GE_lineend lend, |
|
402 | 402 | R_GE_linejoin ljoin, |
447 | 447 | } |
|
448 | 448 | } |
|
449 | 449 | ||
450 | - | template<class PIXFMT, class R_COLOR> |
|
451 | - | void AggDevice<PIXFMT, R_COLOR>::drawLine(double x1, double y1, double x2, |
|
450 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
451 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::drawLine(double x1, double y1, double x2, |
|
452 | 452 | double y2, int col, double lwd, |
|
453 | 453 | int lty, R_GE_lineend lend) { |
|
454 | 454 | if (!visibleColour(col) || lwd == 0.0 || lty == LTY_BLANK) return; |
480 | 480 | } |
|
481 | 481 | } |
|
482 | 482 | ||
483 | - | template<class PIXFMT, class R_COLOR> |
|
484 | - | void AggDevice<PIXFMT, R_COLOR>::drawPolyline(int n, double* x, double* y, |
|
483 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
484 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::drawPolyline(int n, double* x, double* y, |
|
485 | 485 | int col, double lwd, int lty, |
|
486 | 486 | R_GE_lineend lend, |
|
487 | 487 | R_GE_linejoin ljoin, |
521 | 521 | } |
|
522 | 522 | } |
|
523 | 523 | ||
524 | - | template<class PIXFMT, class R_COLOR> |
|
525 | - | void AggDevice<PIXFMT, R_COLOR>::drawPath(int npoly, int* nper, double* x, |
|
524 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
525 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::drawPath(int npoly, int* nper, double* x, |
|
526 | 526 | double* y, int col, int fill, |
|
527 | 527 | double lwd, int lty, |
|
528 | 528 | R_GE_lineend lend, |
586 | 586 | } |
|
587 | 587 | } |
|
588 | 588 | ||
589 | - | template<class PIXFMT, class R_COLOR> |
|
590 | - | void AggDevice<PIXFMT, R_COLOR>::drawRaster(unsigned int *raster, int w, int h, |
|
589 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
590 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::drawRaster(unsigned int *raster, int w, int h, |
|
591 | 591 | double x, double y, |
|
592 | 592 | double final_width, |
|
593 | 593 | double final_height, double rot, |
595 | 595 | agg::rendering_buffer rbuf(reinterpret_cast<unsigned char*>(raster), w, h, |
|
596 | 596 | w * 4); |
|
597 | 597 | ||
598 | - | unsigned char * buffer8 = new unsigned char[w * h * pixfmt_type_32::pix_width]; |
|
599 | - | agg::rendering_buffer rbuf8(buffer8, w, h, w * pixfmt_type_32::pix_width); |
|
600 | - | agg::convert<pixfmt_type_32, pixfmt_r_raster>(&rbuf8, &rbuf); |
|
598 | + | unsigned char * buffer8 = new unsigned char[w * h * BLNDFMT::pix_width]; |
|
599 | + | agg::rendering_buffer rbuf8(buffer8, w, h, w * BLNDFMT::pix_width); |
|
600 | + | agg::convert<BLNDFMT, pixfmt_r_raster>(&rbuf8, &rbuf); |
|
601 | 601 | ||
602 | 602 | agg::trans_affine img_mtx; |
|
603 | 603 | img_mtx *= agg::trans_affine_reflection(0); |
612 | 612 | typedef agg::span_interpolator_linear<> interpolator_type; |
|
613 | 613 | interpolator_type interpolator(img_mtx); |
|
614 | 614 | ||
615 | - | typedef agg::image_accessor_clone<pixfmt_type_32> img_source_type; |
|
615 | + | typedef agg::image_accessor_clone<BLNDFMT> img_source_type; |
|
616 | 616 | ||
617 | - | pixfmt_type_32 img_pixf(rbuf8); |
|
617 | + | BLNDFMT img_pixf(rbuf8); |
|
618 | 618 | img_source_type img_src(img_pixf); |
|
619 | - | agg::span_allocator<agg::rgba8> sa; |
|
619 | + | agg::span_allocator<R_COLOR> sa; |
|
620 | 620 | agg::rasterizer_scanline_aa<> ras; |
|
621 | 621 | ras.clip_box(clip_left, clip_top, clip_right, clip_bottom); |
|
622 | 622 | agg::scanline_u8 sl; |
646 | 646 | delete [] buffer8; |
|
647 | 647 | } |
|
648 | 648 | ||
649 | - | template<class PIXFMT, class R_COLOR> |
|
650 | - | void AggDevice<PIXFMT, R_COLOR>::drawText(double x, double y, const char *str, |
|
649 | + | template<class PIXFMT, class R_COLOR, typename BLNDFMT> |
|
650 | + | void AggDevice<PIXFMT, R_COLOR, BLNDFMT>::drawText(double x, double y, const char *str, |
|
651 | 651 | const char *family, int face, |
|
652 | 652 | double size, double rot, double hadj, |
|
653 | 653 | int col) { |
662 | 662 | renderer_solid ren_solid(renderer); |
|
663 | 663 | ren_solid.color(convertColour(col)); |
|
664 | 664 | ||
665 | - | t_ren.plot_text(x, y, str, rot, hadj, ren_solid); |
|
665 | + | t_ren.plot_text(x, y, str, rot, hadj, ren_solid, renderer); |
|
666 | 666 | } |
|
667 | 667 | ||
668 | 668 |
483 | 483 | } |
|
484 | 484 | ||
485 | 485 | ||
486 | - | ||
487 | - | ||
486 | + | //------------------------------------------------------------------------ |
|
487 | + | template<class Rasterizer, class Scanline, class ScanlineStorage> |
|
488 | + | void decompose_ft_bitmap_color(const FT_Bitmap& bitmap, |
|
489 | + | int x, int y, |
|
490 | + | bool flip_y, |
|
491 | + | Rasterizer& ras, |
|
492 | + | Scanline& sl, |
|
493 | + | ScanlineStorage& storage) |
|
494 | + | { |
|
495 | + | unsigned int i, j; |
|
496 | + | const int8u* buf = (const int8u*)bitmap.buffer; |
|
497 | + | int pitch = bitmap.pitch; |
|
498 | + | sl.reset(x, x + bitmap.width*4); |
|
499 | + | storage.prepare(); |
|
500 | + | if(flip_y) |
|
501 | + | { |
|
502 | + | buf += bitmap.pitch * (bitmap.rows - 1); |
|
503 | + | y += bitmap.rows; |
|
504 | + | pitch = -pitch; |
|
505 | + | } |
|
506 | + | for(i = 0; i < bitmap.rows; i++) |
|
507 | + | { |
|
508 | + | sl.reset_spans(); |
|
509 | + | const int8u* p = buf; |
|
510 | + | for(j = 0; j < bitmap.width*4; j++) |
|
511 | + | { |
|
512 | + | if(*p) sl.add_cell(x + j, *p); |
|
513 | + | ++p; |
|
514 | + | } |
|
515 | + | buf += pitch; |
|
516 | + | if(sl.num_spans()) |
|
517 | + | { |
|
518 | + | sl.finalize(y - i - 1); |
|
519 | + | storage.render(sl); |
|
520 | + | } |
|
521 | + | } |
|
522 | + | } |
|
488 | 523 | ||
489 | 524 | ||
490 | 525 |
680 | 715 | if(m_last_error == 0) |
|
681 | 716 | { |
|
682 | 717 | ret = true; |
|
683 | - | ||
684 | - | switch(ren_type) |
|
718 | + | if (FT_HAS_COLOR(m_cur_face)) |
|
685 | 719 | { |
|
686 | - | case glyph_ren_native_mono: |
|
687 | - | m_glyph_rendering = glyph_ren_native_mono; |
|
688 | - | break; |
|
689 | - | ||
690 | - | case glyph_ren_native_gray8: |
|
691 | - | m_glyph_rendering = glyph_ren_native_gray8; |
|
692 | - | break; |
|
693 | - | ||
694 | - | case glyph_ren_outline: |
|
695 | - | if(FT_IS_SCALABLE(m_cur_face)) |
|
696 | - | { |
|
697 | - | m_glyph_rendering = glyph_ren_outline; |
|
698 | - | } |
|
699 | - | else |
|
700 | - | { |
|
701 | - | m_glyph_rendering = glyph_ren_native_gray8; |
|
702 | - | } |
|
703 | - | break; |
|
704 | - | ||
705 | - | case glyph_ren_agg_mono: |
|
706 | - | if(FT_IS_SCALABLE(m_cur_face)) |
|
707 | - | { |
|
708 | - | m_glyph_rendering = glyph_ren_agg_mono; |
|
709 | - | } |
|
710 | - | else |
|
720 | + | m_glyph_rendering = glyph_ren_native_color; |
|
721 | + | } |
|
722 | + | else |
|
723 | + | { |
|
724 | + | switch(ren_type) |
|
711 | 725 | { |
|
726 | + | case glyph_ren_native_mono: |
|
712 | 727 | m_glyph_rendering = glyph_ren_native_mono; |
|
713 | - | } |
|
714 | - | break; |
|
715 | - | ||
716 | - | case glyph_ren_agg_gray8: |
|
717 | - | if(FT_IS_SCALABLE(m_cur_face)) |
|
718 | - | { |
|
719 | - | m_glyph_rendering = glyph_ren_agg_gray8; |
|
720 | - | } |
|
721 | - | else |
|
722 | - | { |
|
728 | + | break; |
|
729 | + | ||
730 | + | case glyph_ren_native_gray8: |
|
723 | 731 | m_glyph_rendering = glyph_ren_native_gray8; |
|
724 | - | } |
|
725 | - | break; |
|
732 | + | break; |
|
733 | + | ||
734 | + | case glyph_ren_native_color: // Not a color font so use gray8 |
|
735 | + | m_glyph_rendering = glyph_ren_native_gray8; |
|
736 | + | break; |
|
737 | + | ||
738 | + | case glyph_ren_outline: |
|
739 | + | if(FT_IS_SCALABLE(m_cur_face)) |
|
740 | + | { |
|
741 | + | m_glyph_rendering = glyph_ren_outline; |
|
742 | + | } |
|
743 | + | else |
|
744 | + | { |
|
745 | + | m_glyph_rendering = glyph_ren_native_gray8; |
|
746 | + | } |
|
747 | + | break; |
|
748 | + | ||
749 | + | case glyph_ren_agg_mono: |
|
750 | + | if(FT_IS_SCALABLE(m_cur_face)) |
|
751 | + | { |
|
752 | + | m_glyph_rendering = glyph_ren_agg_mono; |
|
753 | + | } |
|
754 | + | else |
|
755 | + | { |
|
756 | + | m_glyph_rendering = glyph_ren_native_mono; |
|
757 | + | } |
|
758 | + | break; |
|
759 | + | ||
760 | + | case glyph_ren_agg_gray8: |
|
761 | + | if(FT_IS_SCALABLE(m_cur_face)) |
|
762 | + | { |
|
763 | + | m_glyph_rendering = glyph_ren_agg_gray8; |
|
764 | + | } |
|
765 | + | else |
|
766 | + | { |
|
767 | + | m_glyph_rendering = glyph_ren_native_gray8; |
|
768 | + | } |
|
769 | + | break; |
|
770 | + | } |
|
726 | 771 | } |
|
727 | 772 | update_signature(); |
|
728 | 773 | } |
836 | 881 | } |
|
837 | 882 | ||
838 | 883 | unsigned gamma_hash = 0; |
|
839 | - | if(m_glyph_rendering == glyph_ren_native_gray8 || |
|
884 | + | if(m_glyph_rendering == glyph_ren_native_gray8 || m_glyph_rendering == glyph_ren_native_color || |
|
840 | 885 | m_glyph_rendering == glyph_ren_agg_mono || |
|
841 | 886 | m_glyph_rendering == glyph_ren_agg_gray8) |
|
842 | 887 | { |
892 | 937 | int diff = 1e6; |
|
893 | 938 | for (int i = 0; i < m_cur_face->num_fixed_sizes; ++i) |
|
894 | 939 | { |
|
895 | - | int ndiff = m_cur_face->available_sizes[i].height - (m_height >> 6); |
|
940 | + | int ndiff = m_cur_face->available_sizes[i].size - m_height; |
|
896 | 941 | if(ndiff >= 0 && ndiff < diff) |
|
897 | 942 | { |
|
898 | 943 | best_match = i; |
933 | 978 | m_glyph_index = glyph_index; |
|
934 | 979 | m_last_error = FT_Load_Glyph(m_cur_face, |
|
935 | 980 | m_glyph_index, |
|
936 | - | m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING); |
|
937 | - | // m_hinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING); |
|
981 | + | m_glyph_rendering == glyph_ren_native_color ? FT_LOAD_COLOR : (m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING)); |
|
938 | 982 | if(m_last_error == 0) |
|
939 | 983 | { |
|
940 | 984 | switch(m_glyph_rendering) |
963 | 1007 | break; |
|
964 | 1008 | ||
965 | 1009 | ||
1010 | + | ||
1011 | + | case glyph_ren_native_color: |
|
1012 | + | m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL); |
|
1013 | + | if(m_last_error == 0) |
|
1014 | + | { |
|
1015 | + | m_bounds.x1 = m_cur_face->glyph->bitmap_left; |
|
1016 | + | m_bounds.y1 = m_cur_face->glyph->bitmap_top; |
|
1017 | + | m_bounds.x2 = m_bounds.x1 + m_cur_face->glyph->bitmap.width; |
|
1018 | + | m_bounds.y2 = m_bounds.y1 - m_cur_face->glyph->bitmap.rows; |
|
1019 | + | m_data_size = m_cur_face->glyph->bitmap.rows * m_cur_face->glyph->bitmap.pitch; |
|
1020 | + | m_data_type = glyph_data_color; |
|
1021 | + | m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); |
|
1022 | + | m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); |
|
1023 | + | return true; |
|
1024 | + | } |
|
1025 | + | break; |
|
1026 | + | ||
966 | 1027 | case glyph_ren_native_gray8: |
|
967 | 1028 | m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL); |
|
968 | 1029 | if(m_last_error == 0) |
1127 | 1188 | { |
|
1128 | 1189 | default: return; |
|
1129 | 1190 | case glyph_data_mono: m_scanlines_bin.serialize(data); break; |
|
1191 | + | case glyph_data_color: memcpy(data, m_cur_face->glyph->bitmap.buffer, m_data_size); break; |
|
1130 | 1192 | case glyph_data_gray8: m_scanlines_aa.serialize(data); break; |
|
1131 | 1193 | case glyph_data_outline: |
|
1132 | 1194 | if(m_flag32) |
10 | 10 | #include "ragg.h" |
|
11 | 11 | ||
12 | 12 | #include "agg_font_freetype.h" |
|
13 | + | #include "agg_span_interpolator_linear.h" |
|
14 | + | #include "agg_image_accessors.h" |
|
15 | + | #include "agg_span_image_filter_rgba.h" |
|
16 | + | #include "agg_span_allocator.h" |
|
17 | + | #include "agg_path_storage.h" |
|
18 | + | ||
19 | + | #include "util/agg_color_conv.h" |
|
13 | 20 | ||
14 | 21 | typedef agg::font_engine_freetype_int32 font_engine_type; |
|
15 | 22 | typedef agg::font_cache_manager<font_engine_type> font_manager_type; |
121 | 128 | } |
|
122 | 129 | }; |
|
123 | 130 | ||
131 | + | template<typename PIXFMT> |
|
124 | 132 | class TextRenderer { |
|
125 | 133 | UTF_UCS converter; |
|
126 | 134 | FontSettings last_font; |
188 | 196 | ||
189 | 197 | *width = glyph->advance_x; |
|
190 | 198 | } else if (c == 77) { // GE uses M (77) to figure out size |
|
191 | - | // Use height as a proxy - this fallback is mostly relevant for emoji |
|
192 | - | *ascent = get_engine().height(); |
|
193 | - | *descent = get_engine().height(); |
|
199 | + | // Use global font metrics |
|
200 | + | *ascent = get_engine().ascent(); |
|
201 | + | *descent = get_engine().descent(); |
|
194 | 202 | ||
195 | - | *width = get_engine().height(); |
|
203 | + | *width = get_engine().max_advance(); |
|
196 | 204 | } |
|
197 | 205 | } |
|
198 | 206 | ||
199 | - | template<typename renderer_solid> |
|
207 | + | template<typename renderer_solid, typename renderer> |
|
200 | 208 | void plot_text(double x, double y, const char *string, double rot, double hadj, |
|
201 | - | renderer_solid &ren_solid) { |
|
209 | + | renderer_solid &ren_solid, renderer &ren) { |
|
202 | 210 | agg::scanline_u8 sl; |
|
203 | 211 | agg::rasterizer_scanline_aa<> ras; |
|
204 | 212 | agg::conv_curve<font_manager_type::path_adaptor_type> curves(get_manager().path_adaptor()); |
274 | 282 | ren_solid); |
|
275 | 283 | break; |
|
276 | 284 | ||
285 | + | case agg::glyph_data_color: |
|
286 | + | renderColourGlyph(glyph, x + x_offset, y + y_offset, rot, ren); |
|
287 | + | break; |
|
288 | + | ||
277 | 289 | case agg::glyph_data_outline: |
|
278 | 290 | ras.reset(); |
|
279 | 291 | ras.add_path(curves); |
326 | 338 | } |
|
327 | 339 | return locate_font_with_features(fontfamily, italic, bold); |
|
328 | 340 | } |
|
341 | + | ||
342 | + | template<typename ren> |
|
343 | + | void renderColourGlyph(const agg::glyph_cache* glyph, double x, double y, double rot, ren &renderer) { |
|
344 | + | int w = glyph->bounds.x2 - glyph->bounds.x1; |
|
345 | + | int h = glyph->bounds.y1 - glyph->bounds.y2; |
|
346 | + | x += glyph->bounds.x1; |
|
347 | + | y -= glyph->bounds.y1; |
|
348 | + | agg::rendering_buffer rbuf(glyph->data, w, h, w * 4); |
|
349 | + | ||
350 | + | unsigned char * buffer = new unsigned char[w * h * PIXFMT::pix_width]; |
|
351 | + | agg::rendering_buffer rbuf_conv(buffer, w, h, w * PIXFMT::pix_width); |
|
352 | + | agg::convert<PIXFMT, pixfmt_col_glyph>(&rbuf_conv, &rbuf); |
|
353 | + | ||
354 | + | agg::trans_affine img_mtx; |
|
355 | + | img_mtx *= agg::trans_affine_rotation(rot); |
|
356 | + | img_mtx *= agg::trans_affine_translation(x, y); |
|
357 | + | agg::trans_affine src_mtx = img_mtx; |
|
358 | + | img_mtx.invert(); |
|
359 | + | ||
360 | + | typedef agg::span_interpolator_linear<> interpolator_type; |
|
361 | + | interpolator_type interpolator(img_mtx); |
|
362 | + | ||
363 | + | typedef agg::image_accessor_clone<PIXFMT> img_source_type; |
|
364 | + | ||
365 | + | PIXFMT img_pixf(rbuf_conv); |
|
366 | + | img_source_type img_src(img_pixf); |
|
367 | + | agg::span_allocator<typename PIXFMT::blender_type::color_type> sa; |
|
368 | + | agg::rasterizer_scanline_aa<> ras; |
|
369 | + | agg::scanline_u8 sl; |
|
370 | + | ||
371 | + | agg::path_storage rect; |
|
372 | + | rect.remove_all(); |
|
373 | + | rect.move_to(0, 0); |
|
374 | + | rect.line_to(0, h); |
|
375 | + | rect.line_to(w, h); |
|
376 | + | rect.line_to(w, 0); |
|
377 | + | rect.close_polygon(); |
|
378 | + | agg::conv_transform<agg::path_storage> tr(rect, src_mtx); |
|
379 | + | ras.add_path(tr); |
|
380 | + | ||
381 | + | typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type> span_gen_type; |
|
382 | + | span_gen_type sg(img_src, interpolator); |
|
383 | + | agg::render_scanlines_aa(ras, sl, renderer, sa, sg); |
|
384 | + | ||
385 | + | delete [] buffer; |
|
386 | + | } |
|
329 | 387 | }; |
|
330 | 388 | ||
331 | 389 | #endif |
33 | 33 | typedef agg::pixfmt_rgba32_pre pixfmt_type_32; |
|
34 | 34 | typedef agg::pixfmt_rgb48_pre pixfmt_type_48; |
|
35 | 35 | typedef agg::pixfmt_rgba64_pre pixfmt_type_64; |
|
36 | + | typedef agg::pixfmt_bgra32_pre pixfmt_col_glyph; |
|
36 | 37 | ||
37 | 38 | #ifdef WORDS_BIGENDIAN |
|
38 | 39 | typedef agg::pixfmt_abgr32_plain pixfmt_r_raster; |
28 | 28 | glyph_data_invalid = 0, |
|
29 | 29 | glyph_data_mono = 1, |
|
30 | 30 | glyph_data_gray8 = 2, |
|
31 | - | glyph_data_outline = 3 |
|
31 | + | glyph_data_outline = 3, |
|
32 | + | glyph_data_color = 4 |
|
32 | 33 | }; |
|
33 | 34 | ||
34 | 35 |
248 | 249 | glyph_ren_native_gray8, |
|
249 | 250 | glyph_ren_outline, |
|
250 | 251 | glyph_ren_agg_mono, |
|
251 | - | glyph_ren_agg_gray8 |
|
252 | + | glyph_ren_agg_gray8, |
|
253 | + | glyph_ren_native_color |
|
252 | 254 | }; |
|
253 | 255 | ||
254 | 256 |
323 | 325 | case glyph_data_mono: |
|
324 | 326 | m_mono_adaptor.init(gl->data, gl->data_size, x, y); |
|
325 | 327 | break; |
|
326 | - | ||
327 | 328 | case glyph_data_gray8: |
|
328 | 329 | m_gray8_adaptor.init(gl->data, gl->data_size, x, y); |
|
329 | 330 | break; |
25 | 25 | }; |
|
26 | 26 | ||
27 | 27 | template<class PIXFMT> |
|
28 | - | class AggDevice16 : public AggDevice<PIXFMT, agg::rgba16> { |
|
28 | + | class AggDevice16 : public AggDevice<PIXFMT, agg::rgba16, pixfmt_type_64> { |
|
29 | 29 | public: |
|
30 | 30 | double alpha_mod; |
|
31 | 31 | ||
32 | 32 | AggDevice16(const char* fp, int w, int h, double ps, int bg, double res, |
|
33 | 33 | double scaling, double alpha_mod = 1.0) : |
|
34 | - | AggDevice<PIXFMT, agg::rgba16>(fp, w, h, ps, bg, res, scaling), |
|
34 | + | AggDevice<PIXFMT, agg::rgba16, pixfmt_type_64>(fp, w, h, ps, bg, res, scaling), |
|
35 | 35 | alpha_mod(alpha_mod) |
|
36 | 36 | { |
|
37 | 37 | this->background = convertColour(this->background_int); |
|
38 | 38 | this->renderer.clear(this->background); |
|
39 | 39 | } |
|
40 | - | ||
41 | - | void drawRaster(unsigned int *raster, int w, int h, double x, double y, |
|
42 | - | double final_width, double final_height, double rot, |
|
43 | - | bool interpolate) { |
|
44 | - | agg::rendering_buffer rbuf(reinterpret_cast<unsigned char*>(raster), w, h, |
|
45 | - | w * 4); |
|
46 | - | ||
47 | - | unsigned char * buffer16 = new unsigned char[w * h * pixfmt_type_64::pix_width]; |
|
48 | - | agg::rendering_buffer rbuf16(buffer16, w, h, w * pixfmt_type_64::pix_width); |
|
49 | - | ||
50 | - | agg::convert<pixfmt_type_64, pixfmt_r_raster>(&rbuf16, &rbuf); |
|
51 | - | ||
52 | - | agg::trans_affine img_mtx; |
|
53 | - | img_mtx *= agg::trans_affine_reflection(0); |
|
54 | - | img_mtx *= agg::trans_affine_translation(0, h); |
|
55 | - | img_mtx *= agg::trans_affine_scaling(final_width / double(w), |
|
56 | - | final_height / double (h)); |
|
57 | - | img_mtx *= agg::trans_affine_rotation(-rot * agg::pi / 180.0); |
|
58 | - | img_mtx *= agg::trans_affine_translation(x, y); |
|
59 | - | agg::trans_affine src_mtx = img_mtx; |
|
60 | - | img_mtx.invert(); |
|
61 | - | ||
62 | - | typedef agg::span_interpolator_linear<> interpolator_type; |
|
63 | - | interpolator_type interpolator(img_mtx); |
|
64 | - | ||
65 | - | typedef agg::image_accessor_clone<pixfmt_type_64> img_source_type; |
|
66 | 40 | ||
67 | - | pixfmt_type_64 img_pixf(rbuf16); |
|
68 | - | img_source_type img_src(img_pixf); |
|
69 | - | agg::span_allocator<agg::rgba16> sa; |
|
70 | - | agg::rasterizer_scanline_aa<> ras; |
|
71 | - | ras.clip_box(this->clip_left, this->clip_top, this->clip_right, |
|
72 | - | this->clip_bottom); |
|
73 | - | agg::scanline_u8 sl; |
|
74 | - | ||
75 | - | agg::path_storage rect; |
|
76 | - | rect.remove_all(); |
|
77 | - | rect.move_to(0, 0); |
|
78 | - | rect.line_to(0, h); |
|
79 | - | rect.line_to(w, h); |
|
80 | - | rect.line_to(w, 0); |
|
81 | - | rect.close_polygon(); |
|
82 | - | agg::conv_transform<agg::path_storage> tr(rect, src_mtx); |
|
83 | - | ras.add_path(tr); |
|
84 | - | ||
85 | - | if (interpolate) { |
|
86 | - | typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type> span_gen_type; |
|
87 | - | span_gen_type sg(img_src, interpolator); |
|
88 | - | ||
89 | - | agg::render_scanlines_aa(ras, sl, this->renderer, sa, sg); |
|
90 | - | } else { |
|
91 | - | typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type> span_gen_type; |
|
92 | - | span_gen_type sg(img_src, interpolator); |
|
93 | - | ||
94 | - | agg::render_scanlines_aa(ras, sl, this->renderer, sa, sg); |
|
95 | - | } |
|
96 | - | ||
97 | - | delete [] buffer16; |
|
98 | - | } |
|
99 | 41 | void to_bigend() { |
|
100 | 42 | uint16_t * buf = reinterpret_cast<uint16_t *>(this->buffer); |
|
101 | 43 | for (int i = 0; i < this->width * this->height * PIXFMT::num_components; i++) { |