svg_status_t _svg_android_begin_group (void *closure, double opacity) { svg_android_t *svg_android = closure; jobject offscreen_bitmap = NULL; DEBUG_ENTRY("begin_group"); ANDROID_SAVE(svg_android); if (opacity != 1.0) { opacity *= 255; jint opacity_i = opacity; opacity_i = ((opacity_i & 0xff) << 24) & 0xffffffff; offscreen_bitmap = ANDROID_CREATE_BITMAP(svg_android, svg_android->state->viewport_width, svg_android->state->viewport_height); ANDROID_FILL_BITMAP(svg_android, offscreen_bitmap, opacity_i); svg_android->state->offscreen_bitmap = offscreen_bitmap; } else svg_android->state->offscreen_bitmap = NULL; _svg_android_push_state (svg_android, offscreen_bitmap); DEBUG_EXIT("begin_group"); return SVG_ANDROID_STATUS_SUCCESS; }
svg_status_t _svg_android_set_pattern (svg_android_t *svg_android, svg_element_t *pattern_element, svg_android_render_type_t type) { svg_pattern_t *pattern = svg_element_pattern (pattern_element); jobject pattern_bitmap; jobject pattern_shader; double x_px, y_px, width_px, height_px; jobject path; _svg_android_length_to_pixel (svg_android, &pattern->x, &x_px); _svg_android_length_to_pixel (svg_android, &pattern->y, &y_px); _svg_android_length_to_pixel (svg_android, &pattern->width, &width_px); _svg_android_length_to_pixel (svg_android, &pattern->height, &height_px); /* OK. We've got the final path to be filled/stroked inside the * android context right now. But we're also going to re-use that * same context to draw the pattern. And since the path is no * longer in the graphics state, android_save/restore will not help * us here. * * Currently we deal with this by manually saving/restoring the * path. * */ path = svg_android->state->path; svg_android->state->path = ANDROID_PATH_CREATE(svg_android); ANDROID_SAVE(svg_android); pattern_bitmap = ANDROID_CREATE_BITMAP(svg_android, (int) (width_px + 0.5), (int) (height_px + 0.5)); _svg_android_push_state (svg_android, pattern_bitmap, NULL); svg_android->state->matrix = ANDROID_IDENTITY_MATRIX(svg_android); svg_android->state->fill_paint.type = SVG_PAINT_TYPE_NONE; svg_android->state->stroke_paint.type = SVG_PAINT_TYPE_NONE; svg_element_render (pattern->group_element, &SVG_ANDROID_RENDER_ENGINE, svg_android); _svg_android_pop_state (svg_android); ANDROID_RESTORE(svg_android); svg_android->state->path = path ; pattern_shader = ANDROID_CREATE_BITMAP_SHADER(svg_android, pattern_bitmap); ANDROID_PAINT_SET_SHADER(svg_android, pattern_shader); return SVG_STATUS_SUCCESS; }
/* XXX: begin_element could be made more efficient in that no extra group is needed if there is only one element in a group */ svg_status_t _svg_android_begin_element (void *closure) { svg_android_t *svg_android = closure; DEBUG_ENTRY("begin_element"); ANDROID_SAVE(svg_android); _svg_android_push_state (svg_android, NULL); DEBUG_EXIT("begin_element"); return SVG_ANDROID_STATUS_SUCCESS; }
svg_status_t _svg_android_render_image (void *closure, unsigned char *data, unsigned int data_width, unsigned int data_height, svg_length_t *x_len, svg_length_t *y_len, svg_length_t *width_len, svg_length_t *height_len) { svg_android_t *svg_android = closure; double x, y, width, height; jintArray iarr; jobject bitmap; jobject matrix; DEBUG_ENTRY("render_image"); ANDROID_SAVE(svg_android); _svg_android_length_to_pixel (svg_android, x_len, &x); _svg_android_length_to_pixel (svg_android, y_len, &y); _svg_android_length_to_pixel (svg_android, width_len, &width); _svg_android_length_to_pixel (svg_android, height_len, &height); // copy bitmap into an java int array iarr = (*(svg_android->env))->NewIntArray(svg_android->env, data_width * data_height); (*(svg_android->env))->SetIntArrayRegion(svg_android->env, iarr, 0, data_width * data_height , (jint *)data); // create bitmap bitmap = ANDROID_DATA_2_BITMAP(svg_android, iarr, data_width, data_height); // prepare matrix matrix = ANDROID_IDENTITY_MATRIX(svg_android); ANDROID_MATRIX_TRANSLATE(svg_android, matrix, x, y); ANDROID_MATRIX_SCALE(svg_android, matrix, width / data_width, height / data_height); // and draw! ANDROID_DRAW_BITMAP(svg_android, bitmap, matrix); ANDROID_RESTORE(svg_android); DEBUG_EXIT("render_image"); return SVG_ANDROID_STATUS_SUCCESS; }
svg_status_t _svg_android_set_pattern (svg_android_t *svg_android, svg_element_t *pattern_element, svg_android_render_type_t type) { svg_pattern_t *pattern = svg_element_pattern (pattern_element); jobject pattern_bitmap; jobject pattern_shader; double x_px, y_px, width_px, height_px; jobject path; _svg_android_length_to_pixel (svg_android, &pattern->x, &x_px); _svg_android_length_to_pixel (svg_android, &pattern->y, &y_px); _svg_android_length_to_pixel (svg_android, &pattern->width, &width_px); _svg_android_length_to_pixel (svg_android, &pattern->height, &height_px); /* OK. We've got the final path to be filled/stroked inside the * android context right now. But we're also going to re-use that * same context to draw the pattern. And since the path is no * longer in the graphics state, android_save/restore will not help * us here. * * Currently we deal with this by manually saving/restoring the * path. * * It might be simpler to just use a new cairo_t for drawing the * pattern. */ path = svg_android->state->path; //cairo_copy_path (svg_android->cr); svg_android->state->path = ANDROID_PATH_CREATE(svg_android); // cairo_new_path (svg_android->cr); ANDROID_SAVE(svg_android); pattern_bitmap = ANDROID_CREATE_BITMAP(svg_android, (int) (width_px + 0.5), (int) (height_px + 0.5)); #if 0 pattern_surface = cairo_surface_create_similar (cairo_get_target (svg_android->cr), CAIRO_FORMAT_ARGB32, (int) (width_px + 0.5), (int) (height_px + 0.5)); #endif _svg_android_push_state (svg_android, pattern_bitmap); svg_android->state->matrix = ANDROID_IDENTITY_MATRIX(svg_android); //cairo_identity_matrix (svg_android->cr); svg_android->state->fill_paint.type = SVG_PAINT_TYPE_NONE; svg_android->state->stroke_paint.type = SVG_PAINT_TYPE_NONE; svg_element_render (pattern->group_element, &SVG_ANDROID_RENDER_ENGINE, svg_android); _svg_android_pop_state (svg_android); ANDROID_RESTORE(svg_android); svg_android->state->path = path ; #if 0 cairo_new_path (svg_android->cr); cairo_append_path (svg_android->cr, path); cairo_path_destroy (path); #endif pattern_shader = ANDROID_CREATE_BITMAP_SHADER(svg_android, pattern_bitmap); ANDROID_PAINT_SET_SHADER(svg_android, pattern_shader); #if 0 surface_pattern = cairo_pattern_create_for_surface (pattern_surface); cairo_surface_destroy (pattern_surface); cairo_pattern_set_extend (surface_pattern, CAIRO_EXTEND_REPEAT); cairo_set_source (svg_android->cr, surface_pattern); cairo_pattern_destroy (surface_pattern); #endif return SVG_STATUS_SUCCESS; }