static void cairo_truetype_font_update_entry (cairo_truetype_font_t *font, int index, unsigned long tag, unsigned long start, unsigned long end) { uint32_t *entry; entry = _cairo_array_index (&font->output, 12 + 16 * index); entry[0] = cpu_to_be32 ((uint32_t)tag); entry[1] = cpu_to_be32 (cairo_truetype_font_calculate_checksum (font, start, end)); entry[2] = cpu_to_be32 ((uint32_t)start); entry[3] = cpu_to_be32 ((uint32_t)(end - start)); }
/** * _cairo_user_data_array_fini: * @array: a #cairo_user_data_array_t * * Destroys all current keys in the user data array and deallocates * any memory allocated for the array itself. **/ void _cairo_user_data_array_fini (cairo_user_data_array_t *array) { int i, num_slots; cairo_user_data_slot_t *slots; num_slots = array->num_elements; slots = _cairo_array_index (array, 0); for (i = 0; i < num_slots; i++) { if (slots[i].user_data != NULL && slots[i].destroy != NULL) slots[i].destroy (slots[i].user_data); } _cairo_array_fini (array); }
void cairo_tee_surface_remove (cairo_surface_t *abstract_surface, cairo_surface_t *target) { cairo_tee_surface_t *surface; cairo_surface_wrapper_t *slaves; int n, num_slaves; cairo_status_t status; if (unlikely (abstract_surface->status)) return; if (unlikely (abstract_surface->finished)) { status = _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); return; } if (abstract_surface->backend != &cairo_tee_surface_backend) { status = _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); return; } surface = (cairo_tee_surface_t *) abstract_surface; if (target == surface->master.target) { status = _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_INVALID_INDEX)); return; } num_slaves = _cairo_array_num_elements (&surface->slaves); slaves = _cairo_array_index (&surface->slaves, 0); for (n = 0; n < num_slaves; n++) { if (slaves[n].target == target) break; } if (n == num_slaves) { status = _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_INVALID_INDEX)); return; } _cairo_surface_wrapper_fini (&slaves[n]); for (n++; n < num_slaves; n++) slaves[n-1] = slaves[n]; surface->slaves.num_elements--; /* XXX: cairo_array_remove()? */ }
static cairo_int_status_t _cairo_tee_surface_fill (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; cairo_surface_wrapper_t *slaves; int n, num_slaves; cairo_status_t status; const cairo_pattern_t *matched_source; cairo_surface_pattern_t temp; matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp); status = _cairo_surface_wrapper_fill (&surface->master, op, matched_source, path, fill_rule, tolerance, antialias, clip); if (matched_source == &temp.base) { _cairo_pattern_fini (&temp.base); } if (unlikely (status)) return status; num_slaves = _cairo_array_num_elements (&surface->slaves); slaves = _cairo_array_index (&surface->slaves, 0); for (n = 0; n < num_slaves; n++) { matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp); status = _cairo_surface_wrapper_fill (&slaves[n], op, matched_source, path, fill_rule, tolerance, antialias, clip); if (matched_source == &temp.base) { _cairo_pattern_fini (&temp.base); } if (unlikely (status)) return status; } return CAIRO_STATUS_SUCCESS; }
void _cairo_user_data_array_foreach (cairo_user_data_array_t *array, void (*func) (const void *key, void *elt, void *closure), void *closure) { cairo_user_data_slot_t *slots; int i, num_slots; num_slots = array->num_elements; slots = _cairo_array_index (array, 0); for (i = 0; i < num_slots; i++) { if (slots[i].user_data != NULL) func (slots[i].key, slots[i].user_data, closure); } }
cairo_status_t _cairo_user_data_array_copy (cairo_user_data_array_t *dst, cairo_user_data_array_t *src) { /* discard any existing user-data */ if (dst->num_elements != 0) { _cairo_user_data_array_fini (dst); _cairo_user_data_array_init (dst); } if (src->num_elements == 0) return CAIRO_STATUS_SUCCESS; return _cairo_array_append_multiple (dst, _cairo_array_index (src, 0), src->num_elements); }
/** * _cairo_user_data_array_set_data: * @array: a #cairo_user_data_array_t * @key: the address of a #cairo_user_data_key_t to attach the user data to * @user_data: the user data to attach * @destroy: a #cairo_destroy_func_t which will be called when the * user data array is destroyed or when new user data is attached using the * same key. * * Attaches user data to a user data array. To remove user data, * call this function with the key that was used to set it and %NULL * for @data. * * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a * slot could not be allocated for the user data. **/ cairo_status_t _cairo_user_data_array_set_data (cairo_user_data_array_t *array, const cairo_user_data_key_t *key, void *user_data, cairo_destroy_func_t destroy) { cairo_status_t status; int i, num_slots; cairo_user_data_slot_t *slots, *slot, new_slot; if (user_data) { new_slot.key = key; new_slot.user_data = user_data; new_slot.destroy = destroy; } else { new_slot.key = NULL; new_slot.user_data = NULL; new_slot.destroy = NULL; } slot = NULL; num_slots = array->num_elements; slots = _cairo_array_index (array, 0); for (i = 0; i < num_slots; i++) { if (slots[i].key == key) { slot = &slots[i]; if (slot->destroy && slot->user_data) slot->destroy (slot->user_data); break; } if (user_data && slots[i].user_data == NULL) { slot = &slots[i]; /* Have to keep searching for an exact match */ } } if (slot) { *slot = new_slot; return CAIRO_STATUS_SUCCESS; } status = _cairo_array_append (array, &new_slot); if (status) return status; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_tee_surface_finish (void *abstract_surface) { cairo_tee_surface_t *surface = abstract_surface; cairo_surface_wrapper_t *slaves; int n, num_slaves; _cairo_surface_wrapper_fini (&surface->master); num_slaves = _cairo_array_num_elements (&surface->slaves); slaves = _cairo_array_index (&surface->slaves, 0); for (n = 0; n < num_slaves; n++) _cairo_surface_wrapper_fini (&slaves[n]); _cairo_array_fini (&surface->slaves); return CAIRO_STATUS_SUCCESS; }
static uint32_t cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font, unsigned long start, unsigned long end) { uint32_t *padded_end; uint32_t *p; uint32_t checksum; char *data; checksum = 0; data = _cairo_array_index (&font->output, 0); p = (uint32_t *) (data + start); padded_end = (uint32_t *) (data + ((end + 3) & ~3)); while (p < padded_end) checksum += be32_to_cpu(*p++); return checksum; }
/** * _cairo_user_data_array_fini: * @array: a #cairo_user_data_array_t * * Destroys all current keys in the user data array and deallocates * any memory allocated for the array itself. **/ void _cairo_user_data_array_fini (cairo_user_data_array_t *array) { unsigned int num_slots; num_slots = array->num_elements; if (num_slots) { cairo_user_data_slot_t *slots; slots = _cairo_array_index (array, 0); while (num_slots--) { cairo_user_data_slot_t *s = &slots[num_slots]; if (s->user_data != NULL && s->destroy != NULL) s->destroy (s->user_data); } } _cairo_array_fini (array); }
/** * _cairo_user_data_array_fini: * @array: a #cairo_user_data_array_t * * Destroys all current keys in the user data array and deallocates * any memory allocated for the array itself. **/ void _cairo_user_data_array_fini (cairo_user_data_array_t *array) { unsigned int num_slots; num_slots = array->num_elements; if (num_slots) { cairo_user_data_slot_t *slots; slots = _cairo_array_index (array, 0); do { if (slots->user_data != NULL && slots->destroy != NULL) slots->destroy (slots->user_data); slots++; } while (--num_slots); } _cairo_array_fini (array); }
static cairo_surface_t * _cairo_tee_surface_snapshot (void *abstract_surface) { cairo_tee_surface_t *surface = abstract_surface; cairo_surface_wrapper_t *slaves; int num_slaves, n; /* we prefer to use a recording surface for our snapshots */ if (_cairo_surface_is_recording (surface->master.target)) return _cairo_surface_wrapper_snapshot (&surface->master); num_slaves = _cairo_array_num_elements (&surface->slaves); slaves = _cairo_array_index (&surface->slaves, 0); for (n = 0; n < num_slaves; n++) { if (_cairo_surface_is_recording (slaves[n].target)) return _cairo_surface_wrapper_snapshot (&slaves[n]); } return _cairo_surface_wrapper_snapshot (&surface->master); }
/** * _cairo_user_data_array_get_data: * @array: a #cairo_user_data_array_t * @key: the address of the #cairo_user_data_key_t the user data was * attached to * * Returns user data previously attached using the specified * key. If no user data has been attached with the given key this * function returns %NULL. * * Return value: the user data previously attached or %NULL. **/ void * _cairo_user_data_array_get_data (cairo_user_data_array_t *array, const cairo_user_data_key_t *key) { int i, num_slots; cairo_user_data_slot_t *slots; /* We allow this to support degenerate objects such as cairo_surface_nil. */ if (array == NULL) return NULL; num_slots = array->num_elements; slots = _cairo_array_index (array, 0); for (i = 0; i < num_slots; i++) { if (slots[i].key == key) return slots[i].user_data; } return NULL; }
static cairo_int_status_t _cairo_tee_surface_stroke (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_stroke_style_t *style, cairo_matrix_t *ctm, cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; cairo_surface_wrapper_t *slaves; int n, num_slaves; cairo_status_t status; status = _cairo_surface_wrapper_stroke (&surface->master, op, source, path, style, ctm, ctm_inverse, tolerance, antialias, clip); if (unlikely (status)) return status; num_slaves = _cairo_array_num_elements (&surface->slaves); slaves = _cairo_array_index (&surface->slaves, 0); for (n = 0; n < num_slaves; n++) { status = _cairo_surface_wrapper_stroke (&slaves[n], op, source, path, style, ctm, ctm_inverse, tolerance, antialias, clip); if (unlikely (status)) return status; } return CAIRO_STATUS_SUCCESS; }
void _cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info) { cairo_xlib_visual_info_t **visuals; int i; CAIRO_MUTEX_LOCK (info->mutex); for (i = 0; i < ARRAY_LENGTH (info->gc); i++) { if (info->gc[i] != NULL) { XFreeGC (info->display->display, info->gc[i]); info->gc[i] = NULL; } } visuals = _cairo_array_index (&info->visuals, 0); for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++) _cairo_xlib_visual_info_destroy (info->display->display, visuals[i]); _cairo_array_truncate (&info->visuals, 0); CAIRO_MUTEX_UNLOCK (info->mutex); }
static cairo_int_status_t _cairo_tee_surface_paint (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; cairo_surface_wrapper_t *slaves; int n, num_slaves; cairo_int_status_t status; num_slaves = _cairo_array_num_elements (&surface->slaves); slaves = _cairo_array_index (&surface->slaves, 0); for (n = 0; n < num_slaves; n++) { status = _cairo_surface_wrapper_paint (&slaves[n], op, source, clip); if (unlikely (status)) return status; } return _cairo_surface_wrapper_paint (&surface->master, op, source, clip); }
static cairo_surface_t * _cairo_tee_surface_create_similar (void *abstract_surface, cairo_content_t content, int width, int height) { cairo_tee_surface_t *other = abstract_surface; cairo_surface_t *similar; cairo_surface_t *surface; cairo_surface_wrapper_t *slaves; int n, num_slaves; similar = _cairo_surface_wrapper_create_similar (&other->master, content, width, height); surface = cairo_tee_surface_create (similar); cairo_surface_destroy (similar); if (unlikely (surface->status)) return surface; num_slaves = _cairo_array_num_elements (&other->slaves); slaves = _cairo_array_index (&other->slaves, 0); for (n = 0; n < num_slaves; n++) { similar = _cairo_surface_wrapper_create_similar (&slaves[n], content, width, height); cairo_tee_surface_add (surface, similar); cairo_surface_destroy (similar); } if (unlikely (surface->status)) { cairo_status_t status = surface->status; cairo_surface_destroy (surface); surface = _cairo_surface_create_in_error (status); } return surface; }
static cairo_status_t _cairo_tee_surface_flush (void *abstract_surface) { cairo_tee_surface_t *surface = abstract_surface; cairo_surface_wrapper_t *slaves; int n, num_slaves; cairo_status_t status; status = _cairo_surface_wrapper_flush(&surface->master); if (unlikely (status)) return status; num_slaves = _cairo_array_num_elements (&surface->slaves); slaves = _cairo_array_index (&surface->slaves, 0); for (n = 0; n < num_slaves; n++) { status = _cairo_surface_wrapper_flush(&slaves[n]); if (unlikely (status)) return status; } return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_meta_surface_replay_internal (cairo_surface_t *surface, cairo_surface_t *target, cairo_meta_replay_type_t type, cairo_meta_region_type_t region) { cairo_meta_surface_t *meta; cairo_command_t *command, **elements; int i, num_elements; cairo_int_status_t status, status2; cairo_clip_t clip, *old_clip; cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target); cairo_matrix_t *device_transform = &target->device_transform; cairo_path_fixed_t path_copy, *dev_path; if (surface->status) return surface->status; if (target->status) return _cairo_surface_set_error (surface, target->status); meta = (cairo_meta_surface_t *) surface; status = CAIRO_STATUS_SUCCESS; _cairo_clip_init (&clip, target); old_clip = _cairo_surface_get_clip (target); num_elements = meta->commands.num_elements; elements = _cairo_array_index (&meta->commands, 0); for (i = meta->replay_start_idx; i < num_elements; i++) { command = elements[i]; if (type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL) { if (command->header.region != region) continue; } /* For all commands except intersect_clip_path, we have to * ensure the current clip gets set on the surface. */ if (command->header.type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) { status = _cairo_surface_set_clip (target, &clip); if (status) break; } dev_path = _cairo_command_get_path (command); if (dev_path && has_device_transform) { status = _cairo_path_fixed_init_copy (&path_copy, dev_path); if (status) break; _cairo_path_fixed_transform (&path_copy, device_transform); dev_path = &path_copy; } switch (command->header.type) { case CAIRO_COMMAND_PAINT: status = _cairo_surface_paint (target, command->paint.op, &command->paint.source.base); break; case CAIRO_COMMAND_MASK: status = _cairo_surface_mask (target, command->mask.op, &command->mask.source.base, &command->mask.mask.base); break; case CAIRO_COMMAND_STROKE: { cairo_matrix_t dev_ctm = command->stroke.ctm; cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse; if (has_device_transform) { cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform); cairo_matrix_multiply (&dev_ctm_inverse, &target->device_transform_inverse, &dev_ctm_inverse); } status = _cairo_surface_stroke (target, command->stroke.op, &command->stroke.source.base, dev_path, &command->stroke.style, &dev_ctm, &dev_ctm_inverse, command->stroke.tolerance, command->stroke.antialias); break; } case CAIRO_COMMAND_FILL: { cairo_command_t *stroke_command; if (type != CAIRO_META_CREATE_REGIONS) stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL; else stroke_command = NULL; if (stroke_command != NULL && type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL) { if (stroke_command->header.region != region) stroke_command = NULL; } if (stroke_command != NULL && stroke_command->header.type == CAIRO_COMMAND_STROKE && _cairo_path_fixed_is_equal (dev_path, _cairo_command_get_path (stroke_command))) { cairo_matrix_t dev_ctm; cairo_matrix_t dev_ctm_inverse; dev_ctm = stroke_command->stroke.ctm; dev_ctm_inverse = stroke_command->stroke.ctm_inverse; if (has_device_transform) { cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform); cairo_matrix_multiply (&dev_ctm_inverse, &surface->device_transform_inverse, &dev_ctm_inverse); } status = _cairo_surface_fill_stroke (target, command->fill.op, &command->fill.source.base, command->fill.fill_rule, command->fill.tolerance, command->fill.antialias, dev_path, stroke_command->stroke.op, &stroke_command->stroke.source.base, &stroke_command->stroke.style, &dev_ctm, &dev_ctm_inverse, stroke_command->stroke.tolerance, stroke_command->stroke.antialias); i++; } else status = _cairo_surface_fill (target, command->fill.op, &command->fill.source.base, dev_path, command->fill.fill_rule, command->fill.tolerance, command->fill.antialias); break; } case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: { cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs; cairo_glyph_t *dev_glyphs; int i, num_glyphs = command->show_text_glyphs.num_glyphs; /* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed * to modify the glyph array that's passed in. We must always * copy the array before handing it to the backend. */ dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); if (dev_glyphs == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); break; } if (has_device_transform) { for (i = 0; i < num_glyphs; i++) { dev_glyphs[i] = glyphs[i]; cairo_matrix_transform_point (device_transform, &dev_glyphs[i].x, &dev_glyphs[i].y); } } else { memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs); } status = _cairo_surface_show_text_glyphs (target, command->show_text_glyphs.op, &command->show_text_glyphs.source.base, command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len, dev_glyphs, num_glyphs, command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters, command->show_text_glyphs.cluster_flags, command->show_text_glyphs.scaled_font); free (dev_glyphs); break; } case CAIRO_COMMAND_INTERSECT_CLIP_PATH: /* XXX Meta surface clipping is broken and requires some * cairo-gstate.c rewriting. Work around it for now. */ if (dev_path == NULL) _cairo_clip_reset (&clip); else status = _cairo_clip_clip (&clip, dev_path, command->intersect_clip_path.fill_rule, command->intersect_clip_path.tolerance, command->intersect_clip_path.antialias, target); break; default: ASSERT_NOT_REACHED; } if (dev_path == &path_copy) _cairo_path_fixed_fini (&path_copy); if (type == CAIRO_META_CREATE_REGIONS) { if (status == CAIRO_STATUS_SUCCESS) { command->header.region = CAIRO_META_REGION_NATIVE; } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) { command->header.region = CAIRO_META_REGION_IMAGE_FALLBACK; status = CAIRO_STATUS_SUCCESS; } } if (status) break; } _cairo_clip_reset (&clip); status2 = _cairo_surface_set_clip (target, old_clip); if (status == CAIRO_STATUS_SUCCESS) status = status2; return _cairo_surface_set_error (surface, status); }
static cairo_status_t _cairo_recording_surface_replay_internal (cairo_surface_t *surface, const cairo_rectangle_int_t *surface_extents, cairo_surface_t *target, cairo_recording_replay_type_t type, cairo_recording_region_type_t region) { cairo_recording_surface_t *recording_surface; cairo_command_t **elements; int i, num_elements; cairo_int_status_t status; cairo_surface_wrapper_t wrapper; if (unlikely (surface->status)) return surface->status; if (unlikely (target->status)) return target->status; if (unlikely (surface->finished)) return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); if (surface->is_clear) return CAIRO_STATUS_SUCCESS; assert (_cairo_surface_is_recording (surface)); _cairo_surface_wrapper_init (&wrapper, target); _cairo_surface_wrapper_set_extents (&wrapper, surface_extents); recording_surface = (cairo_recording_surface_t *) surface; status = CAIRO_STATUS_SUCCESS; num_elements = recording_surface->commands.num_elements; elements = _cairo_array_index (&recording_surface->commands, 0); for (i = recording_surface->replay_start_idx; i < num_elements; i++) { cairo_command_t *command = elements[i]; if (type == CAIRO_RECORDING_REPLAY && region != CAIRO_RECORDING_REGION_ALL) { if (command->header.region != region) continue; } switch (command->header.type) { case CAIRO_COMMAND_PAINT: status = _cairo_surface_wrapper_paint (&wrapper, command->header.op, &command->paint.source.base, _clip (command)); break; case CAIRO_COMMAND_MASK: status = _cairo_surface_wrapper_mask (&wrapper, command->header.op, &command->mask.source.base, &command->mask.mask.base, _clip (command)); break; case CAIRO_COMMAND_STROKE: { status = _cairo_surface_wrapper_stroke (&wrapper, command->header.op, &command->stroke.source.base, &command->stroke.path, &command->stroke.style, &command->stroke.ctm, &command->stroke.ctm_inverse, command->stroke.tolerance, command->stroke.antialias, _clip (command)); break; } case CAIRO_COMMAND_FILL: { cairo_command_t *stroke_command; stroke_command = NULL; if (type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1) stroke_command = elements[i + 1]; if (stroke_command != NULL && type == CAIRO_RECORDING_REPLAY && region != CAIRO_RECORDING_REGION_ALL) { if (stroke_command->header.region != region) stroke_command = NULL; } if (stroke_command != NULL && stroke_command->header.type == CAIRO_COMMAND_STROKE && _cairo_path_fixed_is_equal (&command->fill.path, &stroke_command->stroke.path)) { status = _cairo_surface_wrapper_fill_stroke (&wrapper, command->header.op, &command->fill.source.base, command->fill.fill_rule, command->fill.tolerance, command->fill.antialias, &command->fill.path, stroke_command->header.op, &stroke_command->stroke.source.base, &stroke_command->stroke.style, &stroke_command->stroke.ctm, &stroke_command->stroke.ctm_inverse, stroke_command->stroke.tolerance, stroke_command->stroke.antialias, _clip (command)); i++; } else { status = _cairo_surface_wrapper_fill (&wrapper, command->header.op, &command->fill.source.base, &command->fill.path, command->fill.fill_rule, command->fill.tolerance, command->fill.antialias, _clip (command)); } break; } case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: { cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs; cairo_glyph_t *glyphs_copy; int num_glyphs = command->show_text_glyphs.num_glyphs; /* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed * to modify the glyph array that's passed in. We must always * copy the array before handing it to the backend. */ glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); if (unlikely (glyphs_copy == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); break; } memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); status = _cairo_surface_wrapper_show_text_glyphs (&wrapper, command->header.op, &command->show_text_glyphs.source.base, command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len, glyphs_copy, num_glyphs, command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters, command->show_text_glyphs.cluster_flags, command->show_text_glyphs.scaled_font, _clip (command)); free (glyphs_copy); break; } default: ASSERT_NOT_REACHED; } if (type == CAIRO_RECORDING_CREATE_REGIONS) { if (status == CAIRO_STATUS_SUCCESS) { command->header.region = CAIRO_RECORDING_REGION_NATIVE; } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) { command->header.region = CAIRO_RECORDING_REGION_IMAGE_FALLBACK; status = CAIRO_STATUS_SUCCESS; } else { assert (_cairo_status_is_error (status)); } } if (unlikely (status)) break; } /* free up any caches */ for (i = recording_surface->replay_start_idx; i < num_elements; i++) { cairo_command_t *command = elements[i]; _cairo_clip_drop_cache (&command->header.clip); } _cairo_surface_wrapper_fini (&wrapper); return _cairo_surface_set_error (surface, status); }
cairo_int_status_t _cairo_recording_surface_get_path (cairo_surface_t *surface, cairo_path_fixed_t *path) { cairo_recording_surface_t *recording_surface; cairo_command_t **elements; int i, num_elements; cairo_int_status_t status; if (surface->status) return surface->status; recording_surface = (cairo_recording_surface_t *) surface; status = CAIRO_STATUS_SUCCESS; num_elements = recording_surface->commands.num_elements; elements = _cairo_array_index (&recording_surface->commands, 0); for (i = recording_surface->replay_start_idx; i < num_elements; i++) { cairo_command_t *command = elements[i]; switch (command->header.type) { case CAIRO_COMMAND_PAINT: case CAIRO_COMMAND_MASK: status = CAIRO_INT_STATUS_UNSUPPORTED; break; case CAIRO_COMMAND_STROKE: { cairo_traps_t traps; _cairo_traps_init (&traps); /* XXX call cairo_stroke_to_path() when that is implemented */ status = _cairo_path_fixed_stroke_to_traps (&command->stroke.path, &command->stroke.style, &command->stroke.ctm, &command->stroke.ctm_inverse, command->stroke.tolerance, &traps); if (status == CAIRO_STATUS_SUCCESS) status = _cairo_traps_path (&traps, path); _cairo_traps_fini (&traps); break; } case CAIRO_COMMAND_FILL: { status = _cairo_path_fixed_append (path, &command->fill.path, CAIRO_DIRECTION_FORWARD, 0, 0); break; } case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: { status = _cairo_scaled_font_glyph_path (command->show_text_glyphs.scaled_font, command->show_text_glyphs.glyphs, command->show_text_glyphs.num_glyphs, path); break; } default: ASSERT_NOT_REACHED; } if (unlikely (status)) break; } return _cairo_surface_set_error (surface, status); }
static cairo_int_status_t _cairo_tee_surface_show_text_glyphs (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const char *utf8, int utf8_len, cairo_glyph_t *glyphs, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font, cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; cairo_surface_wrapper_t *slaves; int n, num_slaves; cairo_status_t status; cairo_glyph_t *glyphs_copy; const cairo_pattern_t *matched_source; cairo_surface_pattern_t temp; /* XXX: This copying is ugly. */ glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); if (unlikely (glyphs_copy == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp); status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, op, matched_source, utf8, utf8_len, glyphs_copy, num_glyphs, clusters, num_clusters, cluster_flags, scaled_font, clip); if (matched_source == &temp.base) { _cairo_pattern_fini (&temp.base); } if (unlikely (status)) goto CLEANUP; num_slaves = _cairo_array_num_elements (&surface->slaves); slaves = _cairo_array_index (&surface->slaves, 0); for (n = 0; n < num_slaves; n++) { memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp); status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op, matched_source, utf8, utf8_len, glyphs_copy, num_glyphs, clusters, num_clusters, cluster_flags, scaled_font, clip); if (matched_source == &temp.base) { _cairo_pattern_fini (&temp.base); } if (unlikely (status)) goto CLEANUP; } CLEANUP: free (glyphs_copy); return status; }
/** * _cairo_array_copy_element: * * Copy a single element out of the array from index @index into the * location pointed to by @dst. **/ void _cairo_array_copy_element (cairo_array_t *array, int index, void *dst) { memcpy (dst, _cairo_array_index (array, index), array->element_size); }
static cairo_status_t _cairo_meta_surface_finish (void *abstract_surface) { cairo_meta_surface_t *meta = abstract_surface; cairo_command_t *command; cairo_command_t **elements; int i, num_elements; if (meta->commands_owner) { cairo_surface_destroy (meta->commands_owner); return CAIRO_STATUS_SUCCESS; } num_elements = meta->commands.num_elements; elements = _cairo_array_index (&meta->commands, 0); for (i = 0; i < num_elements; i++) { command = elements[i]; switch (command->header.type) { /* 5 basic drawing operations */ case CAIRO_COMMAND_PAINT: _cairo_pattern_fini (&command->paint.source.base); free (command); break; case CAIRO_COMMAND_MASK: _cairo_pattern_fini (&command->mask.source.base); _cairo_pattern_fini (&command->mask.mask.base); free (command); break; case CAIRO_COMMAND_STROKE: _cairo_pattern_fini (&command->stroke.source.base); _cairo_path_fixed_fini (&command->stroke.path); _cairo_stroke_style_fini (&command->stroke.style); free (command); break; case CAIRO_COMMAND_FILL: _cairo_pattern_fini (&command->fill.source.base); _cairo_path_fixed_fini (&command->fill.path); free (command); break; case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: _cairo_pattern_fini (&command->show_text_glyphs.source.base); free (command->show_text_glyphs.utf8); free (command->show_text_glyphs.glyphs); free (command->show_text_glyphs.clusters); cairo_scaled_font_destroy (command->show_text_glyphs.scaled_font); free (command); break; /* Other junk. */ case CAIRO_COMMAND_INTERSECT_CLIP_PATH: if (command->intersect_clip_path.path_pointer) _cairo_path_fixed_fini (&command->intersect_clip_path.path); free (command); break; default: ASSERT_NOT_REACHED; } } _cairo_array_fini (&meta->commands); return CAIRO_STATUS_SUCCESS; }