static void gimp_foreground_select_tool_stroke (GimpChannel *mask, FgSelectStroke *stroke) { GimpScanConvert *scan_convert = gimp_scan_convert_new (); if (stroke->num_points == 1) { GimpVector2 points[2]; points[0] = points[1] = stroke->points[0]; points[1].x += 0.01; points[1].y += 0.01; gimp_scan_convert_add_polyline (scan_convert, 2, points, FALSE); } else { gimp_scan_convert_add_polyline (scan_convert, stroke->num_points, stroke->points, FALSE); } gimp_scan_convert_stroke (scan_convert, stroke->width, GIMP_JOIN_ROUND, GIMP_CAP_ROUND, 10.0, 0.0, NULL); gimp_scan_convert_compose_value (scan_convert, gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)), 0, 0, stroke->background ? 0 : 255); gimp_scan_convert_free (scan_convert); }
static void gimp_foreground_select_tool_stroke_paint (GimpForegroundSelectTool *fg_select, GimpDisplay *display, GimpForegroundSelectOptions *options) { GimpScanConvert *scan_convert; gint width; gdouble opacity; g_return_if_fail (fg_select->stroke != NULL); scan_convert = gimp_scan_convert_new (); if (fg_select->stroke->len == 1) { GimpVector2 points[2]; points[0] = points[1] = ((GimpVector2 *) fg_select->stroke->data)[0]; points[1].x += 0.01; points[1].y += 0.01; gimp_scan_convert_add_polyline (scan_convert, 2, points, FALSE); } else { gimp_scan_convert_add_polyline (scan_convert, fg_select->stroke->len, (GimpVector2 *) fg_select->stroke->data, FALSE); } width = ROUND ((gdouble) options->stroke_width); gimp_scan_convert_stroke (scan_convert, width, GIMP_JOIN_ROUND, GIMP_CAP_ROUND, 10.0, 0.0, NULL); if (options->draw_mode == GIMP_MATTING_DRAW_MODE_FOREGROUND) opacity = 1.0; else if (options->draw_mode == GIMP_MATTING_DRAW_MODE_BACKGROUND) opacity = 0.0; else opacity = 0.5; gimp_scan_convert_compose_value (scan_convert, fg_select->trimap, 0, 0, opacity); gimp_scan_convert_free (scan_convert); g_array_free (fg_select->stroke, TRUE); fg_select->stroke = NULL; }
void gimp_drawable_stroke_scan_convert (GimpDrawable *drawable, GimpStrokeOptions *options, GimpScanConvert *scan_convert, gboolean push_undo) { gdouble width; GimpUnit unit; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (GIMP_IS_STROKE_OPTIONS (options)); g_return_if_fail (scan_convert != NULL); g_return_if_fail (gimp_fill_options_get_style (GIMP_FILL_OPTIONS (options)) != GIMP_FILL_STYLE_PATTERN || gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL); if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), NULL, NULL, NULL, NULL)) return; width = gimp_stroke_options_get_width (options); unit = gimp_stroke_options_get_unit (options); if (unit != GIMP_UNIT_PIXEL) { GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); gdouble xres; gdouble yres; gimp_image_get_resolution (image, &xres, &yres); gimp_scan_convert_set_pixel_ratio (scan_convert, yres / xres); width = gimp_units_to_pixels (width, unit, yres); } gimp_scan_convert_stroke (scan_convert, width, gimp_stroke_options_get_join_style (options), gimp_stroke_options_get_cap_style (options), gimp_stroke_options_get_miter_limit (options), gimp_stroke_options_get_dash_offset (options), gimp_stroke_options_get_dash_info (options)); gimp_drawable_fill_scan_convert (drawable, GIMP_FILL_OPTIONS (options), scan_convert, push_undo); }
static void gimp_drawable_stroke_scan_convert (GimpDrawable *drawable, GimpStrokeOptions *options, GimpScanConvert *scan_convert) { GimpContext *context = GIMP_CONTEXT (options); GimpImage *image; gdouble width; TileManager *base; TileManager *mask; gint x, y, w, h; gint bytes; gint off_x, off_y; guchar bg[1] = { 0, }; PixelRegion maskPR, basePR; image = gimp_item_get_image (GIMP_ITEM (drawable)); /* must call gimp_channel_is_empty() instead of relying on * gimp_drawable_mask_intersect() because the selection pretends to * be empty while it is being stroked, to prevent masking itself. */ if (gimp_channel_is_empty (gimp_image_get_mask (image))) { x = 0; y = 0; w = gimp_item_width (GIMP_ITEM (drawable)); h = gimp_item_height (GIMP_ITEM (drawable)); } else if (! gimp_drawable_mask_intersect (drawable, &x, &y, &w, &h)) { return; } gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y); width = options->width; if (options->unit != GIMP_UNIT_PIXEL) { gimp_scan_convert_set_pixel_ratio (scan_convert, image->yresolution / image->xresolution); width *= (image->yresolution / _gimp_unit_get_factor (image->gimp, options->unit)); } gimp_scan_convert_stroke (scan_convert, width, options->join_style, options->cap_style, options->miter_limit, options->dash_offset, options->dash_info); /* fill a 1-bpp Tilemanager with black, this will describe the shape * of the stroke. */ mask = tile_manager_new (w, h, 1); pixel_region_init (&maskPR, mask, 0, 0, w, h, TRUE); color_region (&maskPR, bg); /* render the stroke into it */ gimp_scan_convert_render (scan_convert, mask, x + off_x, y + off_y, options->antialias); bytes = gimp_drawable_bytes_with_alpha (drawable); base = tile_manager_new (w, h, bytes); pixel_region_init (&basePR, base, 0, 0, w, h, TRUE); pixel_region_init (&maskPR, mask, 0, 0, w, h, FALSE); switch (options->style) { case GIMP_STROKE_STYLE_SOLID: { guchar tmp_col[MAX_CHANNELS] = { 0, }; guchar col[MAX_CHANNELS] = { 0, }; gimp_rgb_get_uchar (&context->foreground, &tmp_col[RED_PIX], &tmp_col[GREEN_PIX], &tmp_col[BLUE_PIX]); gimp_image_transform_color (image, gimp_drawable_type (drawable), col, GIMP_RGB, tmp_col); col[bytes - 1] = OPAQUE_OPACITY; color_region_mask (&basePR, &maskPR, col); } break; case GIMP_STROKE_STYLE_PATTERN: { GimpPattern *pattern; TempBuf *pat_buf; gboolean new_buf; pattern = gimp_context_get_pattern (context); pat_buf = gimp_image_transform_temp_buf (image, gimp_drawable_type (drawable), pattern->mask, &new_buf); pattern_region (&basePR, &maskPR, pat_buf, x, y); if (new_buf) temp_buf_free (pat_buf); } break; } /* Apply to drawable */ pixel_region_init (&basePR, base, 0, 0, w, h, FALSE); gimp_drawable_apply_region (drawable, &basePR, TRUE, _("Render Stroke"), gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), NULL, x, y); tile_manager_unref (mask); tile_manager_unref (base); gimp_drawable_update (drawable, x, y, w, h); }