static void gimp_resolution_entry_update_unit (GimpResolutionEntry *gre, GimpUnit unit) { GimpUnit old_unit; gint digits; gdouble factor; old_unit = gre->unit; gre->unit = unit; digits = (gimp_unit_get_digits (GIMP_UNIT_INCH) - gimp_unit_get_digits (unit)); gtk_spin_button_set_digits (GTK_SPIN_BUTTON (gre->x.spinbutton), MAX (3 + digits, 3)); factor = gimp_unit_get_factor (old_unit) / gimp_unit_get_factor (unit); gre->x.min_value *= factor; gre->x.max_value *= factor; gre->x.value *= factor; gtk_adjustment_set_value (GTK_ADJUSTMENT (gre->x.adjustment), gre->x.value); gimp_resolution_entry_format_label (gre, gre->width.label, gre->width.phy_size); gimp_resolution_entry_format_label (gre, gre->height.label, gre->height.phy_size); g_signal_emit (gre, gimp_resolution_entry_signals[UNIT_CHANGED], 0); }
static void print_size_info_size_changed (GtkWidget *widget) { gdouble width; gdouble height; gdouble xres; gdouble yres; gdouble scale; scale = gimp_unit_get_factor (gimp_size_entry_get_unit (info.size_entry)); width = gimp_size_entry_get_value (info.size_entry, WIDTH); height = gimp_size_entry_get_value (info.size_entry, HEIGHT); xres = scale * info.image_width / MAX (0.0001, width); yres = scale * info.image_height / MAX (0.0001, height); print_size_info_set_resolution (&info, xres, yres); info.data->offset_x = gimp_size_entry_get_refval (info.size_entry, LEFT); info.data->offset_y = gimp_size_entry_get_refval (info.size_entry, TOP); print_preview_set_image_offsets (PRINT_PREVIEW (info.preview), info.data->offset_x, info.data->offset_y); }
/** * gimp_resolution_entry_get_y_in_dpi; * @gre: The #GimpResolutionEntry you want to know the resolution of. * * Returns the Y resolution of the #GimpResolutionEntry in pixels per inch. **/ gdouble gimp_resolution_entry_get_y_in_dpi (GimpResolutionEntry *gre) { g_return_val_if_fail (GIMP_IS_RESOLUTION_ENTRY (gre), 0); return gre->y.value * gimp_unit_get_factor (gre->unit); }
/** * gimp_resolution_entry_get_x_in_dpi; * @gre: The #GimpResolutionEntry you want to know the resolution of. * * Returns the X resolution of the #GimpResolutionEntry in pixels per inch. **/ gdouble gimp_resolution_entry_get_x_in_dpi (GimpResolutionEntry *gre) { g_return_val_if_fail (GIMP_IS_RESOLUTION_ENTRY (gre), 0); /* dots_in_one_unit * units_in_one_inch -> dpi */ return gre->x.value * gimp_unit_get_factor (gre->unit); }
gdouble gimp_paint_options_get_fade (GimpPaintOptions *paint_options, GimpImage *image, gdouble pixel_dist) { GimpFadeOptions *fade_options; g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), GIMP_OPACITY_OPAQUE); g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_OPACITY_OPAQUE); fade_options = paint_options->fade_options; if (fade_options->use_fade) { gdouble fade_out = 0.0; gdouble unit_factor; switch (fade_options->fade_unit) { case GIMP_UNIT_PIXEL: fade_out = fade_options->fade_length; break; case GIMP_UNIT_PERCENT: fade_out = (MAX (gimp_image_get_width (image), gimp_image_get_height (image)) * fade_options->fade_length / 100); break; default: { gdouble xres; gdouble yres; gimp_image_get_resolution (image, &xres, &yres); unit_factor = gimp_unit_get_factor (fade_options->fade_unit); fade_out = (fade_options->fade_length * MAX (xres, yres) / unit_factor); } break; } /* factor in the fade out value */ if (fade_out > 0.0) { gdouble x; /* Model the amount of paint left as a gaussian curve */ x = pixel_dist / fade_out; return exp (- x * x * 5.541); /* ln (1/255) */ } return GIMP_OPACITY_TRANSPARENT; } return GIMP_OPACITY_OPAQUE; }
static void gimp_vectors_export_image_size (const GimpImage *image, GString *str) { GimpUnit unit; const gchar *abbrev; gchar wbuf[G_ASCII_DTOSTR_BUF_SIZE]; gchar hbuf[G_ASCII_DTOSTR_BUF_SIZE]; gdouble xres; gdouble yres; gdouble w, h; gimp_image_get_resolution (image, &xres, &yres); w = (gdouble) gimp_image_get_width (image) / xres; h = (gdouble) gimp_image_get_height (image) / yres; /* FIXME: should probably use the display unit here */ unit = gimp_image_get_unit (image); switch (unit) { case GIMP_UNIT_INCH: abbrev = "in"; break; case GIMP_UNIT_MM: abbrev = "mm"; break; case GIMP_UNIT_POINT: abbrev = "pt"; break; case GIMP_UNIT_PICA: abbrev = "pc"; break; default: abbrev = "cm"; unit = GIMP_UNIT_MM; w /= 10.0; h /= 10.0; break; } g_ascii_formatd (wbuf, sizeof (wbuf), "%g", w * gimp_unit_get_factor (unit)); g_ascii_formatd (hbuf, sizeof (hbuf), "%g", h * gimp_unit_get_factor (unit)); g_string_append_printf (str, "width=\"%s%s\" height=\"%s%s\"", wbuf, abbrev, hbuf, abbrev); }
static void gimp_resolution_entry_update_value (GimpResolutionEntryField *gref, gdouble value) { if (gref->stop_recursion > 0) return; gref->value = value; gref->stop_recursion++; if (gref->size) gimp_resolution_entry_update_value (gref->corresponding, gref->value / gref->phy_size / gimp_unit_get_factor (gref->gre->unit)); else { gdouble factor = gimp_unit_get_factor (gref->gre->unit); gimp_resolution_entry_update_value (&gref->gre->width, gref->value * gref->gre->width.phy_size * factor); gimp_resolution_entry_update_value (&gref->gre->height, gref->value * gref->gre->height.phy_size * factor); } gtk_adjustment_set_value (GTK_ADJUSTMENT (gref->adjustment), value); gref->stop_recursion--; g_signal_emit (gref->gre, gref->changed_signal, 0); }
static void gimp_resolution_entry_format_label (GimpResolutionEntry *gre, GtkWidget *label, gdouble size) { gchar *format = g_strdup_printf ("%%.%df %%s", gimp_unit_get_digits (gre->unit)); gchar *text = g_strdup_printf (format, size * gimp_unit_get_factor (gre->unit), gimp_unit_get_plural (gre->unit)); g_free (format); gtk_label_set_text (GTK_LABEL (label), text); g_free (text); }
gboolean gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options, GimpImage *image, gdouble grad_point, gdouble pixel_dist, GimpRGB *color) { GimpGradientOptions *gradient_options; GimpGradient *gradient; g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), FALSE); g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (color != NULL, FALSE); gradient_options = paint_options->gradient_options; gradient = gimp_context_get_gradient (GIMP_CONTEXT (paint_options)); if (paint_options->pressure_options->color || paint_options->velocity_options->color || paint_options->random_options->color) { gimp_gradient_get_color_at (gradient, GIMP_CONTEXT (paint_options), NULL, grad_point, gradient_options->gradient_reverse, color); return TRUE; } else if (gradient_options->use_gradient) { gdouble gradient_length = 0.0; gdouble unit_factor; gdouble pos; switch (gradient_options->gradient_unit) { case GIMP_UNIT_PIXEL: gradient_length = gradient_options->gradient_length; break; case GIMP_UNIT_PERCENT: gradient_length = (MAX (gimp_image_get_width (image), gimp_image_get_height (image)) * gradient_options->gradient_length / 100); break; default: { gdouble xres; gdouble yres; gimp_image_get_resolution (image, &xres, &yres); unit_factor = gimp_unit_get_factor (gradient_options->gradient_unit); gradient_length = (gradient_options->gradient_length * MAX (xres, yres) / unit_factor); } break; } if (gradient_length > 0.0) pos = pixel_dist / gradient_length; else pos = 1.0; /* for no repeat, set pos close to 1.0 after the first chunk */ if (gradient_options->gradient_repeat == GIMP_REPEAT_NONE && pos >= 1.0) pos = 0.9999999; if (((gint) pos & 1) && gradient_options->gradient_repeat != GIMP_REPEAT_SAWTOOTH) pos = 1.0 - (pos - (gint) pos); else pos = pos - (gint) pos; gimp_gradient_get_color_at (gradient, GIMP_CONTEXT (paint_options), NULL, pos, gradient_options->gradient_reverse, color); return TRUE; } return FALSE; }
static void print_size_info_set_resolution (PrintSizeInfo *info, gdouble xres, gdouble yres) { PrintData *data = info->data; gdouble offset_x; gdouble offset_y; gdouble offset_x_max; gdouble offset_y_max; if (info->chain && gimp_chain_button_get_active (info->chain)) { if (xres != data->xres) yres = xres; else xres = yres; } data->xres = xres; data->yres = yres; g_signal_handlers_block_by_func (info->resolution_entry, print_size_info_resolution_changed, NULL); gimp_size_entry_set_refval (info->resolution_entry, 0, xres); gimp_size_entry_set_refval (info->resolution_entry, 1, yres); g_signal_handlers_unblock_by_func (info->resolution_entry, print_size_info_resolution_changed, NULL); g_signal_handlers_block_by_func (info->size_entry, print_size_info_size_changed, NULL); gimp_size_entry_set_value (info->size_entry, WIDTH, info->image_width * gimp_unit_get_factor (data->unit) / xres); gimp_size_entry_set_value (info->size_entry, HEIGHT, info->image_height * gimp_unit_get_factor (data->unit) / yres); g_signal_handlers_unblock_by_func (info->size_entry, print_size_info_size_changed, NULL); gimp_size_info_get_max_offsets (&offset_x_max, &offset_y_max); offset_x = gimp_size_entry_get_refval (info->size_entry, LEFT); offset_y = gimp_size_entry_get_refval (info->size_entry, TOP); offset_x = CLAMP (offset_x, 0, offset_x_max); offset_y = CLAMP (offset_y, 0, offset_y_max); data->offset_x = offset_x; data->offset_y = offset_y; print_size_info_update_offsets (); print_preview_set_image_dpi (PRINT_PREVIEW (info->preview), data->xres, data->yres); print_preview_set_image_offsets (PRINT_PREVIEW (info->preview), data->offset_x, data->offset_y); print_preview_set_image_offsets_max (PRINT_PREVIEW (info->preview), offset_x_max, offset_y_max); }
gboolean save_image (const gchar *filename, gint32 image_ID, gint32 drawable_ID, gint32 orig_image_ID, gboolean preview, GError **error) { GimpImageType drawable_type; GeglBuffer *buffer = NULL; const Babl *format; GimpParasite *parasite; static struct jpeg_compress_struct cinfo; static struct my_error_mgr jerr; JpegSubsampling subsampling; FILE * volatile outfile; guchar *data; guchar *src; gboolean has_alpha; gint rowstride, yend; drawable_type = gimp_drawable_type (drawable_ID); buffer = gimp_drawable_get_buffer (drawable_ID); if (! preview) gimp_progress_init_printf (_("Saving '%s'"), gimp_filename_to_utf8 (filename)); /* Step 1: allocate and initialize JPEG compression object */ /* We have to set up the error handler first, in case the initialization * step fails. (Unlikely, but it could happen if you are out of memory.) * This routine fills in the contents of struct jerr, and returns jerr's * address which we place into the link field in cinfo. */ cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; outfile = NULL; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_compress (&cinfo); if (outfile) fclose (outfile); if (buffer) g_object_unref (buffer); return FALSE; } /* Now we can initialize the JPEG compression object. */ jpeg_create_compress (&cinfo); /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ /* Here we use the library-supplied code to send compressed data to a * stdio stream. You can also write your own code to do something else. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to write binary files. */ if ((outfile = g_fopen (filename, "wb")) == NULL) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Could not open '%s' for writing: %s"), gimp_filename_to_utf8 (filename), g_strerror (errno)); return FALSE; } jpeg_stdio_dest (&cinfo, outfile); /* Get the input image and a pointer to its data. */ switch (drawable_type) { case GIMP_RGB_IMAGE: /* # of color components per pixel */ cinfo.input_components = 3; has_alpha = FALSE; format = babl_format ("R'G'B' u8"); break; case GIMP_GRAY_IMAGE: /* # of color components per pixel */ cinfo.input_components = 1; has_alpha = FALSE; format = babl_format ("Y' u8"); break; case GIMP_RGBA_IMAGE: /* # of color components per pixel (minus the GIMP alpha channel) */ cinfo.input_components = 4 - 1; has_alpha = TRUE; format = babl_format ("R'G'B' u8"); break; case GIMP_GRAYA_IMAGE: /* # of color components per pixel (minus the GIMP alpha channel) */ cinfo.input_components = 2 - 1; has_alpha = TRUE; format = babl_format ("Y' u8"); break; case GIMP_INDEXED_IMAGE: default: return FALSE; } /* Step 3: set parameters for compression */ /* First we supply a description of the input image. * Four fields of the cinfo struct must be filled in: */ /* image width and height, in pixels */ cinfo.image_width = gegl_buffer_get_width (buffer); cinfo.image_height = gegl_buffer_get_height (buffer); /* colorspace of input image */ cinfo.in_color_space = (drawable_type == GIMP_RGB_IMAGE || drawable_type == GIMP_RGBA_IMAGE) ? JCS_RGB : JCS_GRAYSCALE; /* Now use the library's routine to set default compression parameters. * (You must set at least cinfo.in_color_space before calling this, * since the defaults depend on the source color space.) */ jpeg_set_defaults (&cinfo); jpeg_set_quality (&cinfo, (gint) (jsvals.quality + 0.5), jsvals.baseline); if (jsvals.use_orig_quality && num_quant_tables > 0) { guint **quant_tables; gint t; /* override tables generated by jpeg_set_quality() with custom tables */ quant_tables = jpeg_restore_original_tables (image_ID, num_quant_tables); if (quant_tables) { for (t = 0; t < num_quant_tables; t++) { jpeg_add_quant_table (&cinfo, t, quant_tables[t], 100, jsvals.baseline); g_free (quant_tables[t]); } g_free (quant_tables); } } if (arithc_supported) { cinfo.arith_code = jsvals.arithmetic_coding; if (!jsvals.arithmetic_coding) cinfo.optimize_coding = jsvals.optimize; } else cinfo.optimize_coding = jsvals.optimize; subsampling = (gimp_drawable_is_rgb (drawable_ID) ? jsvals.subsmp : JPEG_SUBSAMPLING_1x1_1x1_1x1); /* smoothing is not supported with nonstandard sampling ratios */ if (subsampling != JPEG_SUBSAMPLING_2x1_1x1_1x1 && subsampling != JPEG_SUBSAMPLING_1x2_1x1_1x1) { cinfo.smoothing_factor = (gint) (jsvals.smoothing * 100); } if (jsvals.progressive) { jpeg_simple_progression (&cinfo); } switch (subsampling) { case JPEG_SUBSAMPLING_2x2_1x1_1x1: default: cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; break; case JPEG_SUBSAMPLING_2x1_1x1_1x1: cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; break; case JPEG_SUBSAMPLING_1x1_1x1_1x1: cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; break; case JPEG_SUBSAMPLING_1x2_1x1_1x1: cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; break; } cinfo.restart_interval = 0; cinfo.restart_in_rows = jsvals.restart; switch (jsvals.dct) { case 0: default: cinfo.dct_method = JDCT_ISLOW; break; case 1: cinfo.dct_method = JDCT_IFAST; break; case 2: cinfo.dct_method = JDCT_FLOAT; break; } { gdouble xresolution; gdouble yresolution; gimp_image_get_resolution (orig_image_ID, &xresolution, &yresolution); if (xresolution > 1e-5 && yresolution > 1e-5) { gdouble factor; factor = gimp_unit_get_factor (gimp_image_get_unit (orig_image_ID)); if (factor == 2.54 /* cm */ || factor == 25.4 /* mm */) { cinfo.density_unit = 2; /* dots per cm */ xresolution /= 2.54; yresolution /= 2.54; } else { cinfo.density_unit = 1; /* dots per inch */ } cinfo.X_density = xresolution; cinfo.Y_density = yresolution; } } /* Step 4: Start compressor */ /* TRUE ensures that we will write a complete interchange-JPEG file. * Pass TRUE unless you are very sure of what you're doing. */ jpeg_start_compress (&cinfo, TRUE); /* Step 4.1: Write the comment out - pw */ if (image_comment && *image_comment) { #ifdef GIMP_UNSTABLE g_print ("jpeg-save: saving image comment (%d bytes)\n", (int) strlen (image_comment)); #endif jpeg_write_marker (&cinfo, JPEG_COM, (guchar *) image_comment, strlen (image_comment)); } /* Step 4.2: store the color profile if there is one */ parasite = gimp_image_get_parasite (orig_image_ID, "icc-profile"); if (parasite) { jpeg_icc_write_profile (&cinfo, gimp_parasite_data (parasite), gimp_parasite_data_size (parasite)); gimp_parasite_free (parasite); } /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ /* Here we use the library's state variable cinfo.next_scanline as the * loop counter, so that we don't have to keep track ourselves. * To keep things simple, we pass one scanline per call; you can pass * more if you wish, though. */ /* JSAMPLEs per row in image_buffer */ rowstride = cinfo.input_components * cinfo.image_width; data = g_new (guchar, rowstride * gimp_tile_height ()); /* fault if cinfo.next_scanline isn't initially a multiple of * gimp_tile_height */ src = NULL; /* * sg - if we preview, we want this to happen in the background -- do * not duplicate code in the future; for now, it's OK */ if (preview) { PreviewPersistent *pp = g_new (PreviewPersistent, 1); /* pass all the information we need */ pp->cinfo = cinfo; pp->tile_height = gimp_tile_height(); pp->data = data; pp->outfile = outfile; pp->has_alpha = has_alpha; pp->rowstride = rowstride; pp->data = data; pp->buffer = buffer; pp->format = format; pp->src = NULL; pp->file_name = filename; pp->abort_me = FALSE; g_warn_if_fail (prev_p == NULL); prev_p = pp; pp->cinfo.err = jpeg_std_error(&(pp->jerr)); pp->jerr.error_exit = background_error_exit; gtk_label_set_text (GTK_LABEL (preview_size), _("Calculating file size...")); pp->source_id = g_idle_add ((GSourceFunc) background_jpeg_save, pp); /* background_jpeg_save() will cleanup as needed */ return TRUE; } while (cinfo.next_scanline < cinfo.image_height) { if ((cinfo.next_scanline % gimp_tile_height ()) == 0) { yend = cinfo.next_scanline + gimp_tile_height (); yend = MIN (yend, cinfo.image_height); gegl_buffer_get (buffer, GEGL_RECTANGLE (0, cinfo.next_scanline, cinfo.image_width, (yend - cinfo.next_scanline)), 1.0, format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); src = data; } jpeg_write_scanlines (&cinfo, (JSAMPARRAY) &src, 1); src += rowstride; if ((cinfo.next_scanline % 32) == 0) gimp_progress_update ((gdouble) cinfo.next_scanline / (gdouble) cinfo.image_height); } /* Step 6: Finish compression */ jpeg_finish_compress (&cinfo); /* After finish_compress, we can close the output file. */ fclose (outfile); /* Step 7: release JPEG compression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_compress (&cinfo); /* free the temporary buffer */ g_free (data); /* And we're done! */ gimp_progress_update (1.0); g_object_unref (buffer); return TRUE; }
static void gimp_paint_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool); GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool); GimpPaintCore *core = paint_tool->core; GimpDisplayShell *shell = gimp_display_get_shell (display); GimpImage *image = gimp_display_get_image (display); GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool))) { GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity, display); return; } gimp_draw_tool_pause (draw_tool); if (gimp_draw_tool_is_active (draw_tool) && draw_tool->display != display) gimp_draw_tool_stop (draw_tool); gimp_tool_pop_status (tool, display); if (tool->display && tool->display != display && gimp_display_get_image (tool->display) == image) { /* if this is a different display, but the same image, HACK around * in tool internals AFTER stopping the current draw_tool, so * straight line drawing works across different views of the * same image. */ tool->display = display; } if (drawable && proximity) { gboolean constrain_mask = gimp_get_constrain_behavior_mask (); gint off_x, off_y; core->cur_coords = *coords; gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); core->cur_coords.x -= off_x; core->cur_coords.y -= off_y; if (display == tool->display && (state & GIMP_PAINT_TOOL_LINE_MASK)) { /* If shift is down and this is not the first paint stroke, * draw a line. */ gchar *status_help; gdouble dx, dy, dist; gimp_paint_core_round_line (core, paint_options, (state & constrain_mask) != 0); dx = core->cur_coords.x - core->last_coords.x; dy = core->cur_coords.y - core->last_coords.y; status_help = gimp_suggest_modifiers (paint_tool->status_line, constrain_mask & ~state, NULL, _("%s for constrained angles"), NULL); /* show distance in statusbar */ if (shell->unit == GIMP_UNIT_PIXEL) { dist = sqrt (SQR (dx) + SQR (dy)); gimp_tool_push_status (tool, display, "%.1f %s. %s", dist, _("pixels"), status_help); } else { gdouble xres; gdouble yres; gchar format_str[64]; gimp_image_get_resolution (image, &xres, &yres); g_snprintf (format_str, sizeof (format_str), "%%.%df %s. %%s", gimp_unit_get_digits (shell->unit), gimp_unit_get_symbol (shell->unit)); dist = (gimp_unit_get_factor (shell->unit) * sqrt (SQR (dx / xres) + SQR (dy / yres))); gimp_tool_push_status (tool, display, format_str, dist, status_help); } g_free (status_help); paint_tool->draw_line = TRUE; } else { gchar *status; GdkModifierType modifiers = 0; /* HACK: A paint tool may set status_ctrl to NULL to indicate that * it ignores the Ctrl modifier (temporarily or permanently), so * it should not be suggested. This is different from how * gimp_suggest_modifiers() would interpret this parameter. */ if (paint_tool->status_ctrl != NULL) modifiers |= constrain_mask; /* suggest drawing lines only after the first point is set */ if (display == tool->display) modifiers |= GIMP_PAINT_TOOL_LINE_MASK; status = gimp_suggest_modifiers (paint_tool->status, modifiers & ~state, _("%s for a straight line"), paint_tool->status_ctrl, NULL); gimp_tool_push_status (tool, display, "%s", status); g_free (status); paint_tool->draw_line = FALSE; } if (! gimp_draw_tool_is_active (draw_tool)) gimp_draw_tool_start (draw_tool, display); } else if (gimp_draw_tool_is_active (draw_tool)) { gimp_draw_tool_stop (draw_tool); } GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity, display); gimp_draw_tool_resume (draw_tool); }
static gint32 load_image (PopplerDocument *doc, const gchar *filename, GimpRunMode run_mode, GimpPageSelectorTarget target, guint32 resolution, PdfSelectedPages *pages) { gint32 image_ID = 0; gint32 *images = NULL; gint i; gdouble scale; gdouble doc_progress = 0; if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) images = g_new0 (gint32, pages->n_pages); gimp_progress_init_printf (_("Opening '%s'"), gimp_filename_to_utf8 (filename)); scale = resolution / gimp_unit_get_factor (GIMP_UNIT_POINT); /* read the file */ for (i = 0; i < pages->n_pages; i++) { PopplerPage *page; gchar *page_label; gdouble page_width; gdouble page_height; GdkPixbuf *buf; gint width; gint height; page = poppler_document_get_page (doc, pages->pages[i]); poppler_page_get_size (page, &page_width, &page_height); width = page_width * scale; height = page_height * scale; g_object_get (G_OBJECT (page), "label", &page_label, NULL); if (! image_ID) { gchar *name; image_ID = gimp_image_new (width, height, GIMP_RGB); gimp_image_undo_disable (image_ID); if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) name = g_strdup_printf (_("%s-%s"), filename, page_label); else name = g_strdup_printf (_("%s-pages"), filename); gimp_image_set_filename (image_ID, name); g_free (name); gimp_image_set_resolution (image_ID, resolution, resolution); } buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); poppler_page_render_to_pixbuf (page, 0, 0, width, height, scale, 0, buf); layer_from_pixbuf (image_ID, page_label, i, buf, doc_progress, 1.0 / pages->n_pages); g_free (page_label); g_object_unref (buf); doc_progress = (double) (i + 1) / pages->n_pages; gimp_progress_update (doc_progress); if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) { images[i] = image_ID; gimp_image_undo_enable (image_ID); gimp_image_clean_all (image_ID); image_ID = 0; } } if (image_ID) { gimp_image_undo_enable (image_ID); gimp_image_clean_all (image_ID); } if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) { if (run_mode != GIMP_RUN_NONINTERACTIVE) { /* Display images in reverse order. The last will be * displayed by GIMP itself */ for (i = pages->n_pages - 1; i > 0; i--) gimp_display_new (images[i]); } image_ID = images[0]; g_free (images); } return image_ID; }
static void run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[6]; GimpRunMode run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; gint32 image_ID = -1; PopplerDocument *doc = NULL; GError *error = NULL; run_mode = param[0].data.d_int32; INIT_I18N (); *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; if (! g_thread_supported ()) g_thread_init (NULL); if (strcmp (name, LOAD_PROC) == 0) { PdfSelectedPages pages = { 0, NULL }; switch (run_mode) { case GIMP_RUN_INTERACTIVE: /* Possibly retrieve last settings */ gimp_get_data (LOAD_PROC, &loadvals); doc = open_document (param[1].data.d_string, &error); if (!doc) { status = GIMP_PDB_EXECUTION_ERROR; break; } if (load_dialog (doc, &pages)) gimp_set_data (LOAD_PROC, &loadvals, sizeof(loadvals)); else status = GIMP_PDB_CANCEL; break; case GIMP_RUN_WITH_LAST_VALS: /* FIXME: implement last vals mode */ status = GIMP_PDB_EXECUTION_ERROR; break; case GIMP_RUN_NONINTERACTIVE: doc = open_document (param[1].data.d_string, &error); if (doc) { PopplerPage *test_page = poppler_document_get_page (doc, 0); if (test_page) { pages.n_pages = 1; pages.pages = g_new (gint, 1); pages.pages[0] = 0; g_object_unref (test_page); } else { status = GIMP_PDB_EXECUTION_ERROR; g_object_unref (doc); } } else { status = GIMP_PDB_EXECUTION_ERROR; } break; } if (status == GIMP_PDB_SUCCESS) { image_ID = load_image (doc, param[1].data.d_string, run_mode, loadvals.target, loadvals.resolution, &pages); if (image_ID != -1) { *nreturn_vals = 2; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image_ID; } else { status = GIMP_PDB_EXECUTION_ERROR; } } if (doc) g_object_unref (doc); g_free (pages.pages); } else if (strcmp (name, LOAD_THUMB_PROC) == 0) { if (nparams < 2) { status = GIMP_PDB_CALLING_ERROR; } else { gdouble width = 0; gdouble height = 0; gdouble scale; gint32 image = -1; gint num_pages = 0; GdkPixbuf *pixbuf = NULL; /* Possibly retrieve last settings */ gimp_get_data (LOAD_PROC, &loadvals); doc = open_document (param[0].data.d_string, &error); if (doc) { PopplerPage *page = poppler_document_get_page (doc, 0); if (page) { poppler_page_get_size (page, &width, &height); g_object_unref (page); } num_pages = poppler_document_get_n_pages (doc); pixbuf = get_thumbnail (doc, 0, param[1].data.d_int32); g_object_unref (doc); } if (pixbuf) { image = gimp_image_new (gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), GIMP_RGB); gimp_image_undo_disable (image); layer_from_pixbuf (image, "thumbnail", 0, pixbuf, 0.0, 1.0); g_object_unref (pixbuf); gimp_image_undo_enable (image); gimp_image_clean_all (image); } scale = loadvals.resolution / gimp_unit_get_factor (GIMP_UNIT_POINT); width *= scale; height *= scale; if (image != -1) { *nreturn_vals = 6; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image; values[2].type = GIMP_PDB_INT32; values[2].data.d_int32 = width; values[3].type = GIMP_PDB_INT32; values[3].data.d_int32 = height; values[4].type = GIMP_PDB_INT32; values[4].data.d_int32 = GIMP_RGB_IMAGE; values[5].type = GIMP_PDB_INT32; values[5].data.d_int32 = num_pages; } else { status = GIMP_PDB_EXECUTION_ERROR; } } } else { status = GIMP_PDB_CALLING_ERROR; } if (status != GIMP_PDB_SUCCESS && error) { *nreturn_vals = 2; values[1].type = GIMP_PDB_STRING; values[1].data.d_string = error->message; } values[0].data.d_status = status; }
static void print_size_info_set_page_setup (PrintSizeInfo *info) { GtkPageSetup *setup; PrintData *data = info->data; gdouble page_width; gdouble page_height; gdouble x; gdouble y; setup = gtk_print_operation_get_default_page_setup (data->operation); print_size_info_get_page_dimensions (info, &page_width, &page_height, GTK_UNIT_INCH); page_width *= gimp_unit_get_factor (data->unit); page_height *= gimp_unit_get_factor (data->unit); if (info->area_label) { gchar *format; gchar *text; format = g_strdup_printf ("%%.%df x %%.%df %s", gimp_unit_get_digits (data->unit), gimp_unit_get_digits (data->unit), gimp_unit_get_plural (data->unit)); text = g_strdup_printf (format, page_width, page_height); g_free (format); gtk_label_set_text (GTK_LABEL (info->area_label), text); g_free (text); } x = page_width; y = page_height; if (info->chain && gimp_chain_button_get_active (info->chain)) { gdouble ratio_x = page_width / (gdouble) info->image_width; gdouble ratio_y = page_height / (gdouble) info->image_height; if (ratio_x < ratio_y) y = (gdouble) info->image_height * ratio_x; else x = (gdouble) info->image_width * ratio_y; } gimp_size_entry_set_value_boundaries (info->size_entry, WIDTH, page_width / 100.0, x); gimp_size_entry_set_value_boundaries (info->size_entry, HEIGHT, page_height / 100.0, y); print_size_info_get_page_dimensions (info, &page_width, &page_height, GTK_UNIT_POINTS); x = (gdouble) info->image_width / page_width * 72.0; y = (gdouble) info->image_height / page_height * 72.0; if (info->chain && gimp_chain_button_get_active (info->chain)) { gdouble max = MAX (x, y); x = y = max; } gimp_size_entry_set_refval_boundaries (info->resolution_entry, 0, x, GIMP_MAX_RESOLUTION); gimp_size_entry_set_refval_boundaries (info->resolution_entry, 1, y, GIMP_MAX_RESOLUTION); }
static void gimp_image_prop_view_update (GimpImagePropView *view) { GimpImage *image = view->image; GimpImageBaseType type; GimpPrecision precision; GimpUnit unit; gdouble unit_factor; gint unit_digits; const gchar *desc; gchar format_buf[32]; gchar buf[256]; gdouble xres; gdouble yres; gimp_image_get_resolution (image, &xres, &yres); /* pixel size */ g_snprintf (buf, sizeof (buf), ngettext ("%d × %d pixel", "%d × %d pixels", gimp_image_get_height (image)), gimp_image_get_width (image), gimp_image_get_height (image)); gtk_label_set_text (GTK_LABEL (view->pixel_size_label), buf); /* print size */ unit = gimp_get_default_unit (); unit_digits = gimp_unit_get_digits (unit); g_snprintf (format_buf, sizeof (format_buf), "%%.%df × %%.%df %s", unit_digits + 1, unit_digits + 1, gimp_unit_get_plural (unit)); g_snprintf (buf, sizeof (buf), format_buf, gimp_pixels_to_units (gimp_image_get_width (image), unit, xres), gimp_pixels_to_units (gimp_image_get_height (image), unit, yres)); gtk_label_set_text (GTK_LABEL (view->print_size_label), buf); /* resolution */ unit = gimp_image_get_unit (image); unit_factor = gimp_unit_get_factor (unit); g_snprintf (format_buf, sizeof (format_buf), _("pixels/%s"), gimp_unit_get_abbreviation (unit)); g_snprintf (buf, sizeof (buf), _("%g × %g %s"), xres / unit_factor, yres / unit_factor, unit == GIMP_UNIT_INCH ? _("ppi") : format_buf); gtk_label_set_text (GTK_LABEL (view->resolution_label), buf); /* color type */ type = gimp_image_get_base_type (image); gimp_enum_get_value (GIMP_TYPE_IMAGE_BASE_TYPE, type, NULL, NULL, &desc, NULL); switch (type) { case GIMP_RGB: case GIMP_GRAY: g_snprintf (buf, sizeof (buf), "%s", desc); break; case GIMP_INDEXED: g_snprintf (buf, sizeof (buf), "%s (%d %s)", desc, gimp_image_get_colormap_size (image), _("colors")); break; } gtk_label_set_text (GTK_LABEL (view->colorspace_label), buf); /* precision */ precision = gimp_image_get_precision (image); gimp_enum_get_value (GIMP_TYPE_PRECISION, precision, NULL, NULL, &desc, NULL); gtk_label_set_text (GTK_LABEL (view->precision_label), desc); /* size in memory */ gimp_image_prop_view_label_set_memsize (view->memsize_label, GIMP_OBJECT (image)); /* undo / redo */ gimp_image_prop_view_label_set_undo (view->undo_label, gimp_image_get_undo_stack (image)); gimp_image_prop_view_label_set_undo (view->redo_label, gimp_image_get_redo_stack (image)); /* number of layers */ g_snprintf (buf, sizeof (buf), "%d", gimp_image_get_width (image) * gimp_image_get_height (image)); gtk_label_set_text (GTK_LABEL (view->pixels_label), buf); /* number of layers */ g_snprintf (buf, sizeof (buf), "%d", gimp_image_get_n_layers (image)); gtk_label_set_text (GTK_LABEL (view->layers_label), buf); /* number of channels */ g_snprintf (buf, sizeof (buf), "%d", gimp_image_get_n_channels (image)); gtk_label_set_text (GTK_LABEL (view->channels_label), buf); /* number of vectors */ g_snprintf (buf, sizeof (buf), "%d", gimp_image_get_n_vectors (image)); gtk_label_set_text (GTK_LABEL (view->vectors_label), buf); }
/** * gimp_unit_format_string: * @format: A printf-like format string which is used to create the unit * string. * @unit: A unit. * * The @format string supports the following percent expansions: * * <informaltable pgwide="1" frame="none" role="enum"> * <tgroup cols="2"><colspec colwidth="1*"/><colspec colwidth="8*"/> * <tbody> * <row> * <entry>% f</entry> * <entry>Factor (how many units make up an inch)</entry> * </row> * <row> * <entry>% y</entry> * <entry>Symbol (e.g. "''" for GIMP_UNIT_INCH)</entry> * </row> * <row> * <entry>% a</entry> * <entry>Abbreviation</entry> * </row> * <row> * <entry>% s</entry> * <entry>Singular</entry> * </row> * <row> * <entry>% p</entry> * <entry>Plural</entry> * </row> * <row> * <entry>%%</entry> * <entry>Literal percent</entry> * </row> * </tbody> * </tgroup> * </informaltable> * * Returns: A newly allocated string with above percent expressions * replaced with the resp. strings for @unit. * * Since: 2.8 **/ gchar * gimp_unit_format_string (const gchar *format, GimpUnit unit) { gchar buffer[1024]; gint i = 0; g_return_val_if_fail (format != NULL, NULL); g_return_val_if_fail (unit == GIMP_UNIT_PERCENT || (unit >= GIMP_UNIT_PIXEL && unit < gimp_unit_get_number_of_units ()), NULL); while (i < (sizeof (buffer) - 1) && *format) { switch (*format) { case '%': format++; switch (*format) { case 0: g_warning ("%s: unit-menu-format string ended within %%-sequence", G_STRFUNC); break; case '%': buffer[i++] = '%'; break; case 'f': /* factor (how many units make up an inch) */ i += print (buffer, sizeof (buffer), i, "%f", gimp_unit_get_factor (unit)); break; case 'y': /* symbol ("''" for inch) */ i += print (buffer, sizeof (buffer), i, "%s", gimp_unit_get_symbol (unit)); break; case 'a': /* abbreviation */ i += print (buffer, sizeof (buffer), i, "%s", gimp_unit_get_abbreviation (unit)); break; case 's': /* singular */ i += print (buffer, sizeof (buffer), i, "%s", gimp_unit_get_singular (unit)); break; case 'p': /* plural */ i += print (buffer, sizeof (buffer), i, "%s", gimp_unit_get_plural (unit)); break; default: g_warning ("%s: unit-menu-format contains unknown format " "sequence '%%%c'", G_STRFUNC, *format); break; } break; default: buffer[i++] = *format; break; } format++; } buffer[MIN (i, sizeof (buffer) - 1)] = 0; return g_strdup (buffer); }
/** * gimp_display_shell_get_line_status: * @status: initial status text. * @separator: separator text between the line information and @status. * @shell: #GimpDisplayShell this status text will be displayed for. * @x1: abscissa of first point. * @y1: ordinate of first point. * @x2: abscissa of second point. * @y2: ordinate of second point. * * Utility function to prepend the status message with a distance and * angle value. Obviously this is only to be used for tools when it * makes sense, and in particular when there is a concept of line. For * instance when shift-clicking a painting tool or in the blend tool, * etc. * This utility prevents code duplication but also ensures a common * display for every tool where such a status is needed. It will take * into account the shell unit settings and will use the ideal digit * precision according to current image resolution. * * Return value: a newly allocated string containing the enhanced status. **/ gchar * gimp_display_shell_get_line_status (GimpDisplayShell *shell, const gchar *status, const gchar *separator, gdouble x1, gdouble y1, gdouble x2, gdouble y2) { GimpImage *image; gchar *enhanced_status; gdouble xres; gdouble yres; gdouble dx, dy, pixel_dist; gdouble angle; image = gimp_display_get_image (shell->display); if (! image) { /* This makes no sense to add line information when no image is * attached to the display. */ return g_strdup (status); } if (shell->unit == GIMP_UNIT_PIXEL) xres = yres = 1.0; else gimp_image_get_resolution (image, &xres, &yres); dx = x2 - x1; dy = y2 - y1; pixel_dist = sqrt (SQR (dx) + SQR (dy)); if (dx) { angle = gimp_rad_to_deg (atan ((dy/yres) / (dx/xres))); if (dx > 0) { if (dy > 0) angle = 360.0 - angle; else if (dy < 0) angle = -angle; } else { angle = 180.0 - angle; } } else if (dy) { angle = dy > 0 ? 270.0 : 90.0; } else { angle = 0.0; } if (shell->unit == GIMP_UNIT_PIXEL) { enhanced_status = g_strdup_printf ("%.1f %s, %.2f\302\260%s%s", pixel_dist, _("pixels"), angle, separator, status); } else { gdouble inch_dist; gdouble unit_dist; gint digits = 0; /* The distance in unit. */ inch_dist = sqrt (SQR (dx / xres) + SQR (dy / yres)); unit_dist = gimp_unit_get_factor (shell->unit) * inch_dist; /* The ideal digit precision for unit in current resolution. */ if (inch_dist) digits = gimp_unit_get_scaled_digits (shell->unit, pixel_dist / inch_dist); enhanced_status = g_strdup_printf ("%.*f %s, %.2f\302\260%s%s", digits, unit_dist, gimp_unit_get_symbol (shell->unit), angle, separator, status); } return enhanced_status; }
static void gimp_resolution_entry_field_init (GimpResolutionEntry *gre, GimpResolutionEntryField *gref, GimpResolutionEntryField *corresponding, guint changed_signal, gdouble initial_val, GimpUnit initial_unit, gboolean size, gint spinbutton_width) { gint digits; g_return_if_fail (GIMP_IS_RESOLUTION_ENTRY (gre)); gref->gre = gre; gref->corresponding = corresponding; gref->changed_signal = gimp_resolution_entry_signals[changed_signal]; if (size) { gref->value = initial_val / gimp_unit_get_factor (initial_unit) * corresponding->value * gimp_unit_get_factor (gre->unit); gref->phy_size = initial_val / gimp_unit_get_factor (initial_unit); } else { gref->value = initial_val; } gref->min_value = GIMP_MIN_RESOLUTION; gref->max_value = GIMP_MAX_RESOLUTION; gref->adjustment = NULL; gref->stop_recursion = 0; gref->size = size; if (size) { gref->label = g_object_new (GTK_TYPE_LABEL, "xalign", 0.0, "yalign", 0.5, NULL); gimp_label_set_attributes (GTK_LABEL (gref->label), PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, -1); gimp_resolution_entry_format_label (gre, gref->label, gref->phy_size); } digits = size ? 0 : MIN (gimp_unit_get_digits (initial_unit), 5) + 1; gref->spinbutton = gimp_spin_button_new (&gref->adjustment, gref->value, gref->min_value, gref->max_value, 1.0, 10.0, 0.0, 1.0, digits); if (spinbutton_width > 0) { if (spinbutton_width < 17) gtk_entry_set_width_chars (GTK_ENTRY (gref->spinbutton), spinbutton_width); else gtk_widget_set_size_request (gref->spinbutton, spinbutton_width, -1); } }
gdouble gimp_paint_options_get_fade (GimpPaintOptions *paint_options, GimpImage *image, gdouble pixel_dist) { GimpFadeOptions *fade_options; gdouble z = -1.0; gdouble fade_out = 0.0; gdouble unit_factor; gdouble pos; g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), DYNAMIC_MAX_VALUE); g_return_val_if_fail (GIMP_IS_IMAGE (image), DYNAMIC_MAX_VALUE); fade_options = paint_options->fade_options; switch (fade_options->fade_unit) { case GIMP_UNIT_PIXEL: fade_out = fade_options->fade_length; break; case GIMP_UNIT_PERCENT: fade_out = (MAX (gimp_image_get_width (image), gimp_image_get_height (image)) * fade_options->fade_length / 100); break; default: { gdouble xres; gdouble yres; gimp_image_get_resolution (image, &xres, &yres); unit_factor = gimp_unit_get_factor (fade_options->fade_unit); fade_out = (fade_options->fade_length * MAX (xres, yres) / unit_factor); } break; } /* factor in the fade out value */ if (fade_out > 0.0) { pos = pixel_dist / fade_out; } else pos = DYNAMIC_MAX_VALUE; /* for no repeat, set pos close to 1.0 after the first chunk */ if (fade_options->fade_repeat == GIMP_REPEAT_NONE && pos >= DYNAMIC_MAX_VALUE) pos = DYNAMIC_MAX_VALUE - 0.0000001; if (((gint) pos & 1) && fade_options->fade_repeat != GIMP_REPEAT_SAWTOOTH) pos = DYNAMIC_MAX_VALUE - (pos - (gint) pos); else pos = pos - (gint) pos; z = pos; if (fade_options->fade_reverse) z = 1.0 - z; return z; /* ln (1/255) */ }
static GtkWidget * print_size_frame (PrintData *data, GtkSizeGroup *label_group, GtkSizeGroup *entry_group) { GtkWidget *entry; GtkWidget *height; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *chain; GtkWidget *frame; GtkWidget *label; GtkObject *adj; gdouble image_width; gdouble image_height; image_width = (info.image_width * gimp_unit_get_factor (data->unit) / data->xres); image_height = (info.image_height * gimp_unit_get_factor (data->unit) / data->yres); frame = gimp_frame_new (_("Size")); vbox = gtk_vbox_new (FALSE, 6); gtk_container_add (GTK_CONTAINER (frame), vbox); gtk_widget_show (vbox); /* the print size entry */ hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); entry = gimp_size_entry_new (1, data->unit, "%p", FALSE, FALSE, FALSE, SB_WIDTH, GIMP_SIZE_ENTRY_UPDATE_SIZE); gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); gtk_widget_show (entry); info.size_entry = GIMP_SIZE_ENTRY (entry); gtk_table_set_row_spacings (GTK_TABLE (entry), 2); gtk_table_set_col_spacing (GTK_TABLE (entry), 0, 6); gtk_table_set_col_spacing (GTK_TABLE (entry), 2, 6); height = gimp_spin_button_new (&adj, 1, 1, 1, 1, 10, 0, 1, 2); gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry), GTK_SPIN_BUTTON (height), NULL); gtk_table_attach_defaults (GTK_TABLE (entry), height, 1, 2, 0, 1); gtk_widget_show (height); gtk_size_group_add_widget (entry_group, height); gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry), _("_Width:"), 0, 0, 0.0); label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry), _("_Height:"), 1, 0, 0.0); gtk_size_group_add_widget (label_group, label); gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 0, data->xres, FALSE); gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 1, data->yres, FALSE); gimp_size_entry_set_value (GIMP_SIZE_ENTRY (entry), 0, image_width); gimp_size_entry_set_value (GIMP_SIZE_ENTRY (entry), 1, image_height); /* the resolution entry */ hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); entry = gimp_size_entry_new (1, data->image_unit, _("pixels/%a"), FALSE, FALSE, FALSE, SB_WIDTH, GIMP_SIZE_ENTRY_UPDATE_RESOLUTION); gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); gtk_widget_show (entry); info.resolution_entry = GIMP_SIZE_ENTRY (entry); gtk_table_set_row_spacings (GTK_TABLE (entry), 2); gtk_table_set_col_spacing (GTK_TABLE (entry), 0, 6); gtk_table_set_col_spacing (GTK_TABLE (entry), 2, 6); height = gimp_spin_button_new (&adj, 1, 1, 1, 1, 10, 0, 1, 2); gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry), GTK_SPIN_BUTTON (height), NULL); gtk_table_attach_defaults (GTK_TABLE (entry), height, 1, 2, 0, 1); gtk_widget_show (height); gtk_size_group_add_widget (entry_group, height); label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry), _("_X resolution:"), 0, 0, 0.0); gtk_size_group_add_widget (label_group, label); label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry), _("_Y resolution:"), 1, 0, 0.0); gtk_size_group_add_widget (label_group, label); gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (entry), 0, GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION); gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (entry), 1, GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION); gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 0, data->xres); gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 1, data->yres); chain = gimp_chain_button_new (GIMP_CHAIN_RIGHT); gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chain), TRUE); gtk_table_attach (GTK_TABLE (entry), chain, 2, 3, 0, 2, GTK_SHRINK | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show (chain); info.chain = GIMP_CHAIN_BUTTON (chain); g_signal_connect (info.resolution_entry, "value-changed", G_CALLBACK (print_size_info_resolution_changed), NULL); g_signal_connect (info.size_entry, "unit-changed", G_CALLBACK (print_size_info_unit_changed), NULL); return frame; }