/* expand invalidated regions to be align with coordinates divisible by 8 in both
 * directions. This improves improves the performance of GeglProcessor when it
 * iterates the resulting dirtied rectangles in the GeglRegion.
 */
static GeglRectangle gegl_rectangle_expand (const GeglRectangle *rectangle)
{
    gint align = 8;
    GeglRectangle expanded = *rectangle;
    gint xdiff;
    gint ydiff;

    if (gegl_rectangle_is_infinite_plane (rectangle))
        return *rectangle;

    xdiff = expanded.x % align;
    if (xdiff < 0)
        xdiff = align + xdiff;
    expanded.width += xdiff;
    expanded.x -= xdiff;
    xdiff = align -(expanded.width % align);
    expanded.width += xdiff;

    ydiff = expanded.y % align;
    if (ydiff < 0)
        ydiff = align + ydiff;
    expanded.height += ydiff;
    expanded.y -= ydiff;
    ydiff = align -(expanded.height % align);
    expanded.height += ydiff;

    return expanded;
}
Exemple #2
0
static gboolean
operation_process (GeglOperation        *operation,
                   GeglOperationContext *context,
                   const gchar          *output_prop,
                   const GeglRectangle  *result,
                   gint                  level)
{
  GeglOperationClass  *operation_class;

  const GeglRectangle *in_rect =
    gegl_operation_source_get_bounding_box (operation, "input");

  operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);

  if (in_rect && gegl_rectangle_is_infinite_plane (in_rect))
    {
      gpointer in = gegl_operation_context_get_object (context, "input");
      gegl_operation_context_take_object (context, "output",
                                          g_object_ref (G_OBJECT (in)));
      return TRUE;
    }

  return operation_class->process (operation, context, output_prop, result,
                                   gegl_operation_context_get_level (context));
}
Exemple #3
0
/* Pass-through when trying to perform IIR on an infinite plane
 */
static gboolean
operation_process (GeglOperation        *operation,
                   GeglOperationContext *context,
                   const gchar          *output_prop,
                   const GeglRectangle  *result,
                   gint                  level)
{
  GeglOperationClass  *operation_class;
  GeglProperties          *o = GEGL_PROPERTIES (operation);
  GeglGblur1dFilter    filter  = filter_disambiguation (o->filter, o->std_dev);

  operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);

  if (filter == GEGL_GBLUR_1D_IIR)
    {
      const GeglRectangle *in_rect =
        gegl_operation_source_get_bounding_box (operation, "input");

      if (in_rect && gegl_rectangle_is_infinite_plane (in_rect))
        {
          gpointer in = gegl_operation_context_get_object (context, "input");
          gegl_operation_context_take_object (context, "output",
                                              g_object_ref (G_OBJECT (in)));
          return TRUE;
        }
    }
  /* chain up, which will create the needed buffers for our actual
   * process function
   */
  return operation_class->process (operation, context, output_prop, result,
                                   gegl_operation_context_get_level (context));
}
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
  GeglOperationAreaFilter *area = GEGL_OPERATION_AREA_FILTER (operation);
  GeglRectangle            result = { 0, };
  GeglRectangle           *in_rect;

  in_rect = gegl_operation_source_get_bounding_box (operation,"input");

  if (!in_rect)
    return result;

  if (gegl_rectangle_is_infinite_plane (in_rect))
    return *in_rect;

  result = *in_rect;
  if (result.width != 0 &&
      result.height != 0)
    {
      result.x-= area->left;
      result.y-= area->top;
      result.width += area->left + area->right;
      result.height += area->top + area->bottom;
    }

  return result;
}
Exemple #5
0
static GeglRectangle
get_required_for_output (GeglOperation       *operation,
                         const gchar         *input_pad,
                         const GeglRectangle *roi)
{
  GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
  if (gegl_rectangle_is_infinite_plane (&result))
    return *roi;
  return result;
}
static GeglRectangle
get_cached_region (GeglOperation       *operation,
                   const GeglRectangle *roi)
{
  GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");

  if (gegl_rectangle_is_infinite_plane (&result))
    return *roi;

  return result;
}
Exemple #7
0
static GeglRectangle
gegl_gblur_1d_get_required_for_output (GeglOperation       *operation,
                                       const gchar         *input_pad,
                                       const GeglRectangle *output_roi)
{
  GeglRectangle        required_for_output = { 0, };
  GeglProperties          *o       = GEGL_PROPERTIES (operation);
  GeglGblur1dFilter    filter  = filter_disambiguation (o->filter, o->std_dev);

  if (filter == GEGL_GBLUR_1D_IIR)
    {
      const GeglRectangle *in_rect =
        gegl_operation_source_get_bounding_box (operation, input_pad);

      if (in_rect)
        {
          if (!gegl_rectangle_is_infinite_plane (in_rect))
            {
              required_for_output = *output_roi;

              if (o->orientation == GEGL_ORIENTATION_HORIZONTAL)
                {
                  required_for_output.x     = in_rect->x;
                  required_for_output.width = in_rect->width;
                }
              else
                {
                  required_for_output.y      = in_rect->y;
                  required_for_output.height = in_rect->height;
                }

              if (!o->clip_extent)
                required_for_output =
                  gegl_gblur_1d_enlarge_extent (o, &required_for_output);
            }
          /* pass-through case */
          else
            return *output_roi;
        }
    }
  else
    {
      required_for_output = gegl_gblur_1d_enlarge_extent (o, output_roi);
    }

  return required_for_output;
}
Exemple #8
0
static GeglRectangle
gegl_gblur_1d_get_bounding_box (GeglOperation *operation)
{
  GeglProperties          *o       = GEGL_PROPERTIES (operation);
  const GeglRectangle *in_rect =
    gegl_operation_source_get_bounding_box (operation, "input");

  if (! in_rect)
    return *GEGL_RECTANGLE (0, 0, 0, 0);

  if (gegl_rectangle_is_infinite_plane (in_rect))
    return *in_rect;

  if (o->clip_extent)
    {
      return *in_rect;
    }
  else
    {
      /* We use the FIR convolution length for both the FIR and the IIR case */
      return gegl_gblur_1d_enlarge_extent (o, in_rect);
    }
}
Exemple #9
0
static GeglRectangle
gegl_gblur_1d_get_cached_region (GeglOperation       *operation,
                                 const GeglRectangle *output_roi)
{
  GeglRectangle      cached_region;
  GeglProperties        *o       = GEGL_PROPERTIES (operation);
  GeglGblur1dFilter  filter  = filter_disambiguation (o->filter, o->std_dev);

  cached_region = *output_roi;

  if (filter == GEGL_GBLUR_1D_IIR)
    {
      const GeglRectangle in_rect =
        gegl_gblur_1d_get_bounding_box (operation);

      if (! gegl_rectangle_is_empty (&in_rect) &&
          ! gegl_rectangle_is_infinite_plane (&in_rect))
        {
          GeglProperties *o = GEGL_PROPERTIES (operation);

          cached_region = *output_roi;

          if (o->orientation == GEGL_ORIENTATION_HORIZONTAL)
            {
              cached_region.x     = in_rect.x;
              cached_region.width = in_rect.width;
            }
          else
            {
              cached_region.y      = in_rect.y;
              cached_region.height = in_rect.height;
            }
        }
    }

  return cached_region;
}
Exemple #10
0
GeglBuffer *
gegl_operation_context_dup_input_maybe_copy (GeglOperationContext *context,
                                             const gchar          *padname,
                                             const GeglRectangle  *roi)
{
  GeglBuffer    *input;
  GeglBuffer    *output;
  GeglBuffer    *result;
  GeglRectangle  required;
  GeglRectangle  temp;
  gint           shift_x;
  gint           shift_y;
  gint           tile_width;
  gint           tile_height;

  input = GEGL_BUFFER (gegl_operation_context_get_object (context, padname));

  if (! input)
    return NULL;

  /* return input directly when processing a level greater than 0, since
   * gegl_buffer_copy() only copies level-0 tiles
   */
  if (context->level > 0)
    return g_object_ref (input);

  output = GEGL_BUFFER (gegl_operation_context_get_object (context, "output"));

  /* return input directly when processing in-place, otherwise, the copied
   * input buffer will occupy space in the cache after the original is modified
   */
  if (input == output)
    return g_object_ref (input);

  /* get required region to copy */
  required = gegl_operation_get_required_for_output (context->operation,
                                                     padname, roi);

  /* return input directly if the required rectangle is infinite, so that we
   * don't attempt to copy an infinite region
   */
  if (gegl_rectangle_is_infinite_plane (&required))
    return g_object_ref (input);

  /* align required region to the tile grid */
  shift_x     = input->shift_x;
  shift_y     = input->shift_y;
  tile_width  = input->tile_width;
  tile_height = input->tile_height;

  temp.x      = (gint) floor ((gdouble) (required.x                   + shift_x) / tile_width)  * tile_width;
  temp.y      = (gint) floor ((gdouble) (required.y                   + shift_y) / tile_height) * tile_height;
  temp.width  = (gint) ceil  ((gdouble) (required.x + required.width  + shift_x) / tile_width)  * tile_width  - temp.x;
  temp.height = (gint) ceil  ((gdouble) (required.y + required.height + shift_y) / tile_height) * tile_height - temp.y;

  temp.x -= shift_x;
  temp.y -= shift_y;

  required = temp;

  /* intersect required region with input abyss */
  gegl_rectangle_intersect (&required, &required, &input->abyss);

  /* create new buffer with similar characteristics to the input buffer */
  result = g_object_new (GEGL_TYPE_BUFFER,
                         "format",       input->soft_format,
                         "x",            input->extent.x,
                         "y",            input->extent.y,
                         "width",        input->extent.width,
                         "height",       input->extent.height,
                         "abyss-x",      input->abyss.x,
                         "abyss-y",      input->abyss.y,
                         "abyss-width",  input->abyss.width,
                         "abyss-height", input->abyss.height,
                         "shift-x",      shift_x,
                         "shift-y",      shift_y,
                         "tile-width",   tile_width,
                         "tile-height",  tile_height,
                         NULL);

  /* if the tile size doesn't match, bail */
  if (result->tile_width != tile_width || result->tile_height != tile_height)
    {
      g_object_unref (result);

      return g_object_ref (input);
    }

  /* copy required region from input to result -- tiles will generally be COWed */
  gegl_buffer_copy (input,  &required, GEGL_ABYSS_NONE,
                    result, &required);

  return result;
}
gint layer_node_selected (gpointer host, GeglEditor* editor, gint node_id)
{
  GeglEditorLayer*	self = (GeglEditorLayer*)host;
  GeglNode*		node = NULL;
  GSList*		pair = self->pairs;
  for(;pair != NULL; pair = pair->next)
    {
      node_id_pair*	data = pair->data;
      if(data->id == node_id)
	{
	  node = data->node;
	  break;
	}
    }

  g_assert(node != NULL);

  GeglNode** nodes;
  const gchar** pads;
  gint num = gegl_node_get_consumers(node, "output", &nodes, &pads);

  int i;
  g_print("%s: %d consumer(s)\n", gegl_node_get_operation(node), num);
  for(i = 0; i < num; i++)
    {
      g_print("Connection: (%s to %s)\n", gegl_node_get_operation(node), gegl_node_get_operation(nodes[0]), pads[0]);
    }
  g_print("Input from: %s\n", gegl_node_get_operation(gegl_node_get_producer(node, "input", NULL)));

  //  g_print("selected: %s\n", gegl_node_get_operation(node));

  guint		n_props;
  GParamSpec**	properties = gegl_operation_list_properties(gegl_node_get_operation(node), &n_props);

  //TODO: only create enough columns for the properties which will actually be included (i.e. ignoring GeglBuffer props)
  GtkTable	*prop_table = GTK_TABLE(gtk_table_new(2, n_props, FALSE));

  int d;
  for(d = 0, i = 0; i < n_props; i++, d++)
    {
      GParamSpec*	prop = properties[i];
      GType		type = prop->value_type;
      const gchar*		name = prop->name;

      GtkWidget*	name_label = gtk_label_new(name);
      gtk_misc_set_alignment(GTK_MISC(name_label), 0, 0.5);


      GtkWidget*	value_entry = gtk_entry_new();

      gchar buf[256] = "*";	//can probably be smaller; In fact, can probably do this without sprintf and a buffer. TODO: look at g_string

      gint	i_value;
      gdouble	d_value;
      gchar*	str_value;
      gboolean skip = FALSE;

      switch(type)
	{
	case G_TYPE_INT:
	  gegl_node_get(node, name, &i_value, NULL);
	  sprintf(buf, "%d", i_value);
	  break;
	case G_TYPE_DOUBLE:
	  gegl_node_get(node, name, &d_value, NULL);
	  sprintf(buf, "%.3f", d_value);
	  break;
	case G_TYPE_STRING:
	  gegl_node_get(node, name, &str_value, NULL);
	  sprintf(buf, "%s", str_value);
	  break;
	}

      if(type == GEGL_TYPE_BUFFER) {
	skip = TRUE;
	d--;
      } else if( type == GEGL_TYPE_COLOR) {
	skip = TRUE;
	GtkWidget *color_button = gtk_button_new_with_label("Select");

	select_color_info* info = malloc(sizeof(select_color_info));
	info->node = node;
	info->property = name;
	info->layer = self;

	g_signal_connect(color_button, "clicked", (GCallback)select_color, info);

	gtk_table_attach(prop_table, name_label, 0, 1, d, d+1, GTK_FILL, GTK_FILL, 1, 1);
	gtk_table_attach(prop_table, color_button, 1, 2, d, d+1, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 1, 1);
      }

      if(!skip)
	{
	  gtk_entry_set_text(GTK_ENTRY(value_entry), buf);

	  gtk_entry_set_width_chars(GTK_ENTRY(value_entry), 2);
	  struct text_prop_data	*data = malloc(sizeof(struct text_prop_data));	//TODO store this in a list and free it when the node is deselected
	  data->node		      = node;
	  data->property		      = name;
	  data->prop_type		      = type;
	  data->layer		      = self;
	  g_signal_connect(value_entry, "activate", G_CALLBACK(text_property_changed), data);

	  gtk_table_attach(prop_table, name_label, 0, 1, d, d+1, GTK_FILL, GTK_FILL, 1, 1);
	  gtk_table_attach(prop_table, value_entry, 1, 2, d, d+1, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 1, 1);
	}
    }

  //  gegl_node_process(node);
  GeglGtkView *gtk_view = gegl_gtk_view_new_for_node(node);

  GeglRectangle rect = gegl_node_get_bounding_box(node);

  if(gegl_rectangle_is_infinite_plane(&rect))
    {
      gegl_gtk_view_set_autoscale_policy(gtk_view, GEGL_GTK_VIEW_AUTOSCALE_DISABLED);
      gegl_gtk_view_set_scale(gtk_view, 1.0);
      g_print("Disable autoscale: scale=%f, x=%f, y=%f\n", gegl_gtk_view_get_scale(gtk_view),
      gegl_gtk_view_get_x(gtk_view), gegl_gtk_view_get_y(gtk_view));
    }

  gtk_widget_show(GTK_WIDGET(gtk_view));

  //TODO: draw checkerboard under preview to indicate transparency

  gtk_box_pack_start(GTK_BOX(self->prop_box), GTK_WIDGET(prop_table), FALSE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(self->prop_box), GTK_WIDGET(gtk_view), TRUE, TRUE, 10);

  GtkWidget* label = gtk_label_new("Click the image\nto open in a\nnew window");
  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
  gtk_box_pack_start(GTK_BOX(self->prop_box), label, FALSE, TRUE, 10);

  gtk_widget_show_all(self->prop_box);
}