static cairo_int_status_t _cairo_xcb_surface_stroke (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip) { cairo_surface_t *surface = abstract_surface; const cairo_compositor_t *compositor = get_compositor (&surface); return _cairo_compositor_stroke (compositor, surface, op, source, path, style, ctm, ctm_inverse, tolerance, antialias, clip); }
static cairo_int_status_t _cairo_gl_surface_paint (void *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip) { /* simplify the common case of clearing the surface */ if (clip == NULL) { if (op == CAIRO_OPERATOR_CLEAR) return _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); else if (source->type == CAIRO_PATTERN_TYPE_SOLID && (op == CAIRO_OPERATOR_SOURCE || (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) { return _cairo_gl_surface_clear (surface, &((cairo_solid_pattern_t *) source)->color); } } return _cairo_compositor_paint (get_compositor (surface), surface, op, source, clip); }
void Label::create_cache_entry(size_t& index, size_t& last_start, Point& origin_offset) { Renderer* renderer = get_compositor()->get_renderer(); if ((index - last_start) > 1) { font_cache_entry cs; cs.start = last_start; cs.length = (index - last_start); cs.origin = origin_offset; last_start = index; Rect text_bounds; renderer->font_measure_string(font_handle, &text[cs.start], cs.length, text_bounds); size_t best_height = glm::max(font_height, text_bounds.height()); cs.height = font_height + best_height; font_cache.push_back(cs); origin_offset.x = LABEL_LEFT_MARGIN; origin_offset.y += font_height + best_height; content_bounds.size.height += font_height + best_height; } } // create_cache_entry
void Label::update_text_cache() { // try and render with a font cache if (cache_is_dirty) { Renderer* renderer = get_compositor()->get_renderer(); size_t height; int ascender, descender; renderer->font_metrics(font_handle, height, ascender, descender); content_bounds.origin = origin + scroll_offset; cache_is_dirty = 0; font_cache.clear(false); size_t last_start = 0; glm::vec2 origin_offset = glm::vec2(LABEL_LEFT_MARGIN, LABEL_TOP_MARGIN); origin_offset.y += font_height; content_bounds.size.width = size.width; content_bounds.size.height = -font_height; const bool enable_word_wrap = true; // keep track of the last segment in text to handle word wraps. size_t last_word_break = 0; const size_t character_count = text.size(); for (size_t index = 0; index < character_count+1; ++index) { const bool is_last_character = (index == character_count); Rect text_bounds; if (text[index] == '\n' || is_last_character) { create_cache_entry(index, last_start, origin_offset); if (is_last_character) { break; } } else if (enable_word_wrap && (text[index] == ' ')) { renderer->font_measure_string(font_handle, &text[last_start], (index - last_start), text_bounds); float test_width = content_bounds.width(); if (has_vertical_scrollbar()) { test_width -= vertical_bar->get_size().width; } if (text_bounds.width() > test_width) { // we need to wrap text starting from last index; create_cache_entry(last_word_break, last_start, origin_offset); // reset index, last_start. Advance it past the space. index = (last_word_break + 1); last_start = (index + 1); } last_word_break = index; } } } } // update_text_cache