Esempio n. 1
0
/**
 * 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);
}
Esempio n. 2
0
/**
 * 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;
}
Esempio n. 3
0
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 gint
gimp_display_shell_format_title (GimpDisplayShell *shell,
                                 gchar            *title,
                                 gint              title_len,
                                 const gchar      *format)
{
  GimpImage *image;
  gint       num, denom;
  gint       i = 0;

  g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), 0);

  image = gimp_display_get_image (shell->display);

  if (! image)
    {
      title[0] = '\n';
      return 0;
    }

  gimp_zoom_model_get_fraction (shell->zoom, &num, &denom);

  while (i < title_len && *format)
    {
      switch (*format)
        {
        case '%':
          format++;
          switch (*format)
            {
            case 0:
              /* format string ends within %-sequence, print literal '%' */

            case '%':
              title[i++] = '%';
              break;

            case 'f': /* base filename */
              i += print (title, title_len, i, "%s",
                          gimp_image_get_display_name (image));
              break;

            case 'F': /* full filename */
              i += print (title, title_len, i, "%s",
                          gimp_image_get_display_path (image));
              break;

            case 'p': /* PDB id */
              i += print (title, title_len, i, "%d", gimp_image_get_ID (image));
              break;

            case 'i': /* instance */
              i += print (title, title_len, i, "%d",
                          gimp_display_get_instance (shell->display));
              break;

            case 't': /* image type */
              i += print (title, title_len, i, "%s %s",
                          gimp_display_shell_title_image_type (image),
                          gimp_display_shell_title_image_precision (image));
              break;

            case 'T': /* drawable type */
              {
                GimpDrawable *drawable = gimp_image_get_active_drawable (image);
                const Babl   *format   = gimp_drawable_get_format (drawable);

                if (drawable)
                  i += print (title, title_len, i, "%s",
                              gimp_babl_get_description (format));
              }
              break;

            case 's': /* user source zoom factor */
              i += print (title, title_len, i, "%d", denom);
              break;

            case 'd': /* user destination zoom factor */
              i += print (title, title_len, i, "%d", num);
              break;

            case 'z': /* user zoom factor (percentage) */
              {
                gdouble  scale = gimp_zoom_model_get_factor (shell->zoom);

                i += print (title, title_len, i,
                            scale >= 0.15 ? "%.0f" : "%.2f", 100.0 * scale);
              }
              break;

            case 'D': /* dirty flag */
              if (format[1] == 0)
                {
                  /* format string ends within %D-sequence, print literal '%D' */
                  i += print (title, title_len, i, "%%D");
                  break;
                }
              if (gimp_image_is_dirty (image))
                title[i++] = format[1];
              format++;
              break;

            case 'C': /* clean flag */
              if (format[1] == 0)
                {
                  /* format string ends within %C-sequence, print literal '%C' */
                  i += print (title, title_len, i, "%%C");
                  break;
                }
              if (! gimp_image_is_dirty (image))
                title[i++] = format[1];
              format++;
              break;

            case 'B': /* dirty flag (long) */
              if (gimp_image_is_dirty (image))
                i += print (title, title_len, i, "%s", _("(modified)"));
              break;

            case 'A': /* clean flag (long) */
              if (! gimp_image_is_dirty (image))
                i += print (title, title_len, i, "%s", _("(clean)"));
              break;

            case 'm': /* memory used by image */
              {
                GimpObject *object = GIMP_OBJECT (image);
                gchar      *str;

                str = g_format_size (gimp_object_get_memsize (object, NULL));
                i += print (title, title_len, i, "%s", str);
                g_free (str);
              }
              break;

            case 'M': /* image size in megapixels */
              i += print (title, title_len, i, "%.1f",
                          (gdouble) gimp_image_get_width (image) *
                          (gdouble) gimp_image_get_height (image) / 1000000.0);
              break;

            case 'l': /* number of layers */
              i += print (title, title_len, i, "%d",
                          gimp_image_get_n_layers (image));
              break;

            case 'L': /* number of layers (long) */
              {
                gint num = gimp_image_get_n_layers (image);

                i += print (title, title_len, i,
                            ngettext ("%d layer", "%d layers", num), num);
              }
              break;

            case 'n': /* active drawable name */
              {
                GimpDrawable *drawable = gimp_image_get_active_drawable (image);

                if (drawable)
                  {
                    gchar *desc;

                    desc = gimp_viewable_get_description (GIMP_VIEWABLE (drawable),
                                                          NULL);

                    i += print (title, title_len, i, "%s", desc);

                    g_free (desc);
                  }
                else
                  {
                    i += print (title, title_len, i, "%s", _("(none)"));
                  }
              }
              break;

            case 'P': /* active drawable PDB id */
              {
                GimpDrawable *drawable = gimp_image_get_active_drawable (image);

                if (drawable)
                  i += print (title, title_len, i, "%d",
                              gimp_item_get_ID (GIMP_ITEM (drawable)));
                else
                  i += print (title, title_len, i, "%s", _("(none)"));
              }
              break;

            case 'W': /* width in real-world units */
              if (shell->unit != GIMP_UNIT_PIXEL)
                {
                  gdouble xres;
                  gdouble yres;
                  gchar   unit_format[8];

                  gimp_image_get_resolution (image, &xres, &yres);

                  g_snprintf (unit_format, sizeof (unit_format), "%%.%df",
                              gimp_unit_get_digits (shell->unit) + 1);
                  i += print (title, title_len, i, unit_format,
                              gimp_pixels_to_units (gimp_image_get_width (image),
                                                    shell->unit, xres));
                  break;
                }
              /* else fallthru */
            case 'w': /* width in pixels */
              i += print (title, title_len, i, "%d",
                          gimp_image_get_width (image));
              break;

            case 'H': /* height in real-world units */
              if (shell->unit != GIMP_UNIT_PIXEL)
                {
                  gdouble xres;
                  gdouble yres;
                  gchar   unit_format[8];

                  gimp_image_get_resolution (image, &xres, &yres);

                  g_snprintf (unit_format, sizeof (unit_format), "%%.%df",
                              gimp_unit_get_digits (shell->unit) + 1);
                  i += print (title, title_len, i, unit_format,
                              gimp_pixels_to_units (gimp_image_get_height (image),
                                                    shell->unit, yres));
                  break;
                }
              /* else fallthru */
            case 'h': /* height in pixels */
              i += print (title, title_len, i, "%d",
                          gimp_image_get_height (image));
              break;

            case 'u': /* unit symbol */
              i += print (title, title_len, i, "%s",
                          gimp_unit_get_symbol (shell->unit));
              break;

            case 'U': /* unit abbreviation */
              i += print (title, title_len, i, "%s",
                          gimp_unit_get_abbreviation (shell->unit));
              break;

              /* Other cool things to be added:
               * %r = xresolution
               * %R = yresolution
               * %ø = image's fractal dimension
               * %þ = the answer to everything
               */

            default:
              /* format string contains unknown %-sequence, print it literally */
              i += print (title, title_len, i, "%%%c", *format);
              break;
            }
          break;

        default:
          title[i++] = *format;
          break;
        }

      format++;
    }

  title[MIN (i, title_len - 1)] = '\0';

  return i;
}