|
| 1 | +#include "cairo_pango.h" |
| 2 | + |
| 3 | +cairo_pango::cairo_pango() |
| 4 | +{ |
| 5 | + m_temp_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 2, 2); |
| 6 | + m_temp_cr = cairo_create(m_temp_surface); |
| 7 | +} |
| 8 | + |
| 9 | +cairo_pango::~cairo_pango() |
| 10 | +{ |
| 11 | + clear_images(); |
| 12 | + cairo_surface_destroy(m_temp_surface); |
| 13 | + cairo_destroy(m_temp_cr); |
| 14 | +} |
| 15 | + |
| 16 | +litehtml::uint_ptr cairo_pango::create_font(const char *faceName, int size, int weight, litehtml::font_style italic, |
| 17 | + unsigned int decoration, litehtml::font_metrics *fm) |
| 18 | +{ |
| 19 | + PangoFontDescription *desc = pango_font_description_from_string (faceName); |
| 20 | + pango_font_description_set_absolute_size(desc, size * PANGO_SCALE); |
| 21 | + if(italic == litehtml::font_style_italic) |
| 22 | + { |
| 23 | + pango_font_description_set_style(desc, PANGO_STYLE_ITALIC); |
| 24 | + } else |
| 25 | + { |
| 26 | + pango_font_description_set_style(desc, PANGO_STYLE_NORMAL); |
| 27 | + } |
| 28 | + PangoWeight fnt_weight; |
| 29 | + if(weight >= 0 && weight < 150) fnt_weight = PANGO_WEIGHT_THIN; |
| 30 | + else if(weight >= 150 && weight < 250) fnt_weight = PANGO_WEIGHT_ULTRALIGHT; |
| 31 | + else if(weight >= 250 && weight < 350) fnt_weight = PANGO_WEIGHT_LIGHT; |
| 32 | + else if(weight >= 350 && weight < 450) fnt_weight = PANGO_WEIGHT_NORMAL; |
| 33 | + else if(weight >= 450 && weight < 550) fnt_weight = PANGO_WEIGHT_MEDIUM; |
| 34 | + else if(weight >= 550 && weight < 650) fnt_weight = PANGO_WEIGHT_SEMIBOLD; |
| 35 | + else if(weight >= 650 && weight < 750) fnt_weight = PANGO_WEIGHT_BOLD; |
| 36 | + else if(weight >= 750 && weight < 850) fnt_weight = PANGO_WEIGHT_ULTRABOLD; |
| 37 | + else fnt_weight = PANGO_WEIGHT_HEAVY; |
| 38 | + |
| 39 | + pango_font_description_set_weight(desc, fnt_weight); |
| 40 | + |
| 41 | + cairo_font* ret = nullptr; |
| 42 | + |
| 43 | + if(fm) |
| 44 | + { |
| 45 | + cairo_save(m_temp_cr); |
| 46 | + PangoLayout *layout = pango_cairo_create_layout(m_temp_cr); |
| 47 | + PangoContext *context = pango_layout_get_context(layout); |
| 48 | + PangoLanguage *language = pango_language_get_default(); |
| 49 | + pango_layout_set_font_description(layout, desc); |
| 50 | + PangoFontMetrics *metrics = pango_context_get_metrics(context, desc, language); |
| 51 | + |
| 52 | + fm->ascent = PANGO_PIXELS((double)pango_font_metrics_get_ascent(metrics)); |
| 53 | + fm->descent = PANGO_PIXELS((double)pango_font_metrics_get_descent(metrics)); |
| 54 | + fm->height = fm->ascent + fm->descent; |
| 55 | + fm->x_height = fm->height; |
| 56 | + |
| 57 | + pango_layout_set_text(layout, "x", 1); |
| 58 | + |
| 59 | + int x_width, x_height; |
| 60 | + pango_layout_get_pixel_size(layout, &x_width, &x_height); |
| 61 | + |
| 62 | + fm->x_height = x_height; |
| 63 | + |
| 64 | + cairo_restore(m_temp_cr); |
| 65 | + |
| 66 | + g_object_unref(layout); |
| 67 | + pango_font_metrics_unref(metrics); |
| 68 | + |
| 69 | + ret = new cairo_font; |
| 70 | + ret->font = desc; |
| 71 | + ret->size = size; |
| 72 | + ret->strikeout = (decoration & litehtml::font_decoration_linethrough) != 0; |
| 73 | + ret->underline = (decoration & litehtml::font_decoration_underline) != 0; |
| 74 | + ret->ascent = fm->ascent; |
| 75 | + ret->descent = fm->descent; |
| 76 | + |
| 77 | + ret->underline_thickness = pango_font_metrics_get_underline_thickness(metrics); |
| 78 | + ret->underline_position = -pango_font_metrics_get_underline_position(metrics); |
| 79 | + pango_quantize_line_geometry(&ret->underline_thickness, &ret->underline_position); |
| 80 | + ret->underline_thickness = PANGO_PIXELS(ret->underline_thickness); |
| 81 | + ret->underline_position = -1;//PANGO_PIXELS(ret->underline_position); |
| 82 | + |
| 83 | + ret->strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness(metrics); |
| 84 | + ret->strikethrough_position = pango_font_metrics_get_strikethrough_position(metrics); |
| 85 | + pango_quantize_line_geometry(&ret->strikethrough_thickness, &ret->strikethrough_position); |
| 86 | + ret->strikethrough_thickness = PANGO_PIXELS(ret->strikethrough_thickness); |
| 87 | + ret->strikethrough_position = PANGO_PIXELS(ret->strikethrough_position); |
| 88 | + } |
| 89 | + |
| 90 | + return (litehtml::uint_ptr) ret; |
| 91 | +} |
| 92 | + |
| 93 | +void cairo_pango::delete_font(litehtml::uint_ptr hFont) |
| 94 | +{ |
| 95 | + auto* fnt = (cairo_font*) hFont; |
| 96 | + if(fnt) |
| 97 | + { |
| 98 | + pango_font_description_free(fnt->font); |
| 99 | + delete fnt; |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +int cairo_pango::text_width(const char *text, litehtml::uint_ptr hFont) |
| 104 | +{ |
| 105 | + auto* fnt = (cairo_font*) hFont; |
| 106 | + |
| 107 | + cairo_save(m_temp_cr); |
| 108 | + |
| 109 | + PangoLayout *layout = pango_cairo_create_layout(m_temp_cr); |
| 110 | + pango_layout_set_font_description(layout, fnt->font); |
| 111 | + |
| 112 | + pango_layout_set_text(layout, text, -1); |
| 113 | + pango_cairo_update_layout (m_temp_cr, layout); |
| 114 | + |
| 115 | + int x_width, x_height; |
| 116 | + pango_layout_get_pixel_size(layout, &x_width, &x_height); |
| 117 | + |
| 118 | + cairo_restore(m_temp_cr); |
| 119 | + |
| 120 | + g_object_unref(layout); |
| 121 | + |
| 122 | + return (int) x_width; |
| 123 | +} |
| 124 | + |
| 125 | +void cairo_pango::draw_text(litehtml::uint_ptr hdc, const char *text, litehtml::uint_ptr hFont, |
| 126 | + litehtml::web_color color, const litehtml::position &pos) |
| 127 | +{ |
| 128 | + auto* fnt = (cairo_font*) hFont; |
| 129 | + auto* cr = (cairo_t*) hdc; |
| 130 | + cairo_save(cr); |
| 131 | + |
| 132 | + apply_clip(cr); |
| 133 | + |
| 134 | + set_color(cr, color); |
| 135 | + |
| 136 | + PangoLayout *layout = pango_cairo_create_layout(cr); |
| 137 | + pango_layout_set_font_description (layout, fnt->font); |
| 138 | + pango_layout_set_text (layout, text, -1); |
| 139 | + |
| 140 | + int baseline = PANGO_PIXELS(pango_layout_get_baseline(layout)); |
| 141 | + |
| 142 | + PangoRectangle ink_rect, logical_rect; |
| 143 | + pango_layout_get_pixel_extents(layout, &ink_rect, &logical_rect); |
| 144 | + |
| 145 | + int text_baseline = pos.height - fnt->descent; |
| 146 | + |
| 147 | + int x = pos.left() + logical_rect.x; |
| 148 | + int y = pos.top() + logical_rect.y + text_baseline - baseline; |
| 149 | + |
| 150 | + cairo_move_to(cr, x, y); |
| 151 | + pango_cairo_update_layout (cr, layout); |
| 152 | + pango_cairo_show_layout (cr, layout); |
| 153 | + |
| 154 | + int tw = 0; |
| 155 | + |
| 156 | + if(fnt->underline || fnt->strikeout) |
| 157 | + { |
| 158 | + tw = text_width(text, hFont); |
| 159 | + } |
| 160 | + |
| 161 | + if(fnt->underline) |
| 162 | + { |
| 163 | + cairo_set_line_width(cr, fnt->underline_thickness); |
| 164 | + cairo_move_to(cr, x, pos.top() + text_baseline - fnt->underline_position + 0.5); |
| 165 | + cairo_line_to(cr, x + tw, pos.top() + text_baseline - fnt->underline_position + 0.5); |
| 166 | + cairo_stroke(cr); |
| 167 | + } |
| 168 | + if(fnt->strikeout) |
| 169 | + { |
| 170 | + cairo_set_line_width(cr, fnt->strikethrough_thickness); |
| 171 | + cairo_move_to(cr, x, pos.top() + text_baseline - fnt->strikethrough_position - 0.5); |
| 172 | + cairo_line_to(cr, x + tw, pos.top() + text_baseline - fnt->strikethrough_position - 0.5); |
| 173 | + cairo_stroke(cr); |
| 174 | + } |
| 175 | + |
| 176 | + cairo_restore(cr); |
| 177 | + |
| 178 | + g_object_unref(layout); |
| 179 | +} |
| 180 | + |
0 commit comments