BABL fishing patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

 attached is a patch that improves logic of go_fishing code
 in babl-fish.c. The current code searches list of all
 fishes while looking for suitable preexistent
 BABL_FISH_PATH instance. The new code only searches
 relevant part of database's hash table. Further, the
 current code searches for fish path every time such a babl
 fish is requested, even though the same fish path has been
 requested before and not found. The new code creates dummy
 BABL_FISH instance with appropriate source/destination
 formats and inserts it into the fish database to indicate
 that fish path has been searched for and not found. See
 comments in the patch for details.

 Regards,
  Jan
Index: babl/babl-internal.h
===================================================================
--- babl/babl-internal.h	(revision 302)
+++ babl/babl-internal.h	(working copy)
@@ -88,6 +88,8 @@ long     babl_fish_path_process         
                                          void           *source,
                                          void           *destination,
                                          long            n);
+int      babl_fish_get_id               (const Babl     *source,
+                                         const Babl     *destination);
 
 double   babl_format_loss               (Babl           *babl);
 Babl   * babl_image_from_linear         (char           *buffer,
Index: babl/babl-fish-path.c
===================================================================
--- babl/babl-fish-path.c	(revision 302)
+++ babl/babl-fish-path.c	(working copy)
@@ -193,9 +193,10 @@ Babl *
 babl_fish_path (const Babl *source,
                 const Babl *destination)
 {
-  Babl           *babl = NULL;
-  char           *name = create_name (source, destination, 1);
+  Babl *babl = NULL;
+  char *name;
 
+  name = create_name (source, destination, 1);
   babl = babl_db_exist_by_name (babl_fish_db (), name);
   if (babl) 
     {
@@ -205,17 +206,11 @@ babl_fish_path (const Babl *source,
       return babl;
     }
 
-  babl_assert (BABL_IS_BABL (source));
-  babl_assert (BABL_IS_BABL (destination));
-
-  babl_assert (source->class_type == BABL_FORMAT);
-  babl_assert (destination->class_type == BABL_FORMAT);
-
   babl = babl_calloc (1, sizeof (BablFishPath) +
                       strlen (name) + 1);
 
   babl->class_type                = BABL_FISH_PATH;
-  babl->instance.id               = 0;
+  babl->instance.id               = babl_fish_get_id (source, destination);
   babl->instance.name             = ((char *) babl) + sizeof (BablFishPath);
   strcpy (babl->instance.name, name);
   babl->fish.source               = source;
Index: babl/babl-fish-simple.c
===================================================================
--- babl/babl-fish-simple.c	(revision 302)
+++ babl/babl-fish-simple.c	(working copy)
@@ -33,7 +33,6 @@ babl_fish_simple (BablConversion *conver
   babl_assert (BABL_IS_BABL (conversion));
 
   name = create_name (conversion);
-
   babl = babl_db_exist_by_name (babl_fish_db (), name);
   if (babl) 
     {
@@ -46,7 +45,7 @@ babl_fish_simple (BablConversion *conver
   babl = babl_malloc (sizeof (BablFishSimple) +
                       strlen (name) + 1);
   babl->class_type    = BABL_FISH_SIMPLE;
-  babl->instance.id   = 0;
+  babl->instance.id   = babl_fish_get_id (conversion->source, conversion->destination);
   babl->instance.name = ((char *) babl) + sizeof (BablFishSimple);
   strcpy (babl->instance.name, name);
   babl->fish.source      = conversion->source;
Index: babl/babl-fish-reference.c
===================================================================
--- babl/babl-fish-reference.c	(revision 302)
+++ babl/babl-fish-reference.c	(working copy)
@@ -69,7 +69,7 @@ babl_fish_reference (const Babl *source,
   babl = babl_malloc (sizeof (BablFishReference) +
                       strlen (name) + 1);
   babl->class_type    = BABL_FISH_REFERENCE;
-  babl->instance.id   = 0;
+  babl->instance.id   = babl_fish_get_id (source, destination);
   babl->instance.name = ((char *) babl) + sizeof (BablFishReference);
   strcpy (babl->instance.name, name);
   babl->fish.source      = source;
Index: babl/babl-fish.c
===================================================================
--- babl/babl-fish.c	(revision 302)
+++ babl/babl-fish.c	(working copy)
@@ -20,6 +20,87 @@
 #include <string.h>
 #include <stdarg.h>
 
+typedef struct _BablFindFish BablFindFish;
+
+typedef struct _BablFindFish
+{
+  Babl       *fish_path;
+  Babl       *fish_ref;
+  Babl       *fish_fish;
+  int        fishes;
+  const Babl *source;
+  const Babl *destination;
+} _BablFishFish;
+
+
+static int
+match_conversion (Babl *conversion,
+                  void *inout);
+
+static int
+find_fish_path (Babl *item, 
+                void *data);
+
+static int
+find_memcpy_fish (Babl *item, 
+                  void *data);
+
+static int
+each_babl_fish_destroy (Babl *babl,
+                        void *data);
+
+
+/* ====================================== */
+
+
+static int
+find_fish_path (Babl *item, 
+                void *data)
+{
+  BablFindFish *ffish = (BablFindFish *) data;
+  if ((item->fish.source == ffish->source) &&
+      (item->fish.destination == ffish->destination))
+    {
+      if (item->instance.class_type == BABL_FISH_REFERENCE)
+        {
+          ffish->fish_ref = item;
+          ffish->fishes++;
+        }  
+      else if (item->instance.class_type == BABL_FISH_PATH)
+        {
+          ffish->fish_path = item;
+          ffish->fishes++;
+        }
+      else if (item->instance.class_type == BABL_FISH)
+        {
+          ffish->fish_fish = item;
+          ffish->fishes++;
+        }
+      if (ffish->fishes == 3)
+        return 1;
+    }
+
+  return 0;
+}
+
+static int
+find_memcpy_fish (Babl *item, 
+                  void *data)
+{
+  BablFindFish *ffish = (BablFindFish *) data;
+  if ((item->fish.source == ffish->source) &&
+      (item->fish.destination == ffish->destination))
+    {
+      if ((item->fish.source == item->fish.destination) &&
+          (item->instance.class_type == BABL_FISH_REFERENCE))
+        {
+          ffish->fish_ref = item;
+          return 1;
+        }  
+    }
+
+  return 0;
+}
 
 static int
 match_conversion (Babl *conversion,
@@ -47,6 +128,20 @@ babl_conversion_find (const void *source
   return data;
 }
 
+int
+babl_fish_get_id (const Babl *source,
+                  const Babl *destination)
+{
+  /* value of 'id' will be used as argument for hash function,
+   * substraction serves as simple combination of 
+   * source/destination values. */
+  int id = (int) source - (int) destination;
+  /* instances with id 0 won't be inserted into database */
+  if (id == 0)
+    id = 1;
+  return id;
+}
+
 BablDb *
 babl_fish_db (void)
 {
@@ -55,28 +150,6 @@ babl_fish_db (void)
   return db;
 }
 
-static inline Babl *
-go_fishing (const Babl *source,
-            const Babl *destination)
-{
-  BablDb *db = babl_fish_db ();
-  int i;
-
-  for (i = 0; i < db->babl_list->count; i++)
-    {
-      Babl *item = db->babl_list->items[i];
-      if ((void *) source == (void *) item->fish.source &&
-          (void *) destination == (void *) item->fish.destination &&
-          (item->class_type == BABL_FISH_PATH || /* accept only paths */
-           source == destination)                /* or memcpy */
-          )
-        {
-          return item;
-        }
-    }
-  return NULL;
-}
-
 Babl *
 babl_fish (const void *source,
            const void *destination,
@@ -89,14 +162,10 @@ babl_fish (const void *source,
   babl_assert (destination);
 
   if (BABL_IS_BABL (source))
-    {
-      source_format = source;
-    }
+    source_format = source;
 
   if (!source_format)
-    {
-      source_format = babl_format ((char *) source);
-    }
+    source_format = babl_format ((char *) source);
 
   if (!source_format)
     {
@@ -105,14 +174,10 @@ babl_fish (const void *source,
     }
 
   if (BABL_IS_BABL (destination))
-    {
-      destination_format = destination;
-    }
+    destination_format = destination;
 
   if (!destination_format)
-    {
-      destination_format = babl_format ((char *) destination);
-    }
+    destination_format = babl_format ((char *) destination);
 
   if (!destination_format)
     {
@@ -121,41 +186,90 @@ babl_fish (const void *source,
     }
 
   {
-    Babl *lucky;
-    lucky = go_fishing (source_format, destination_format);
-    if (lucky)
-      return lucky;
-  }
-
-  if (0) /* do not accept shortcut conversions, since there might be
-            a faster path, besides the shortcut conversion might
-            have a too large error, let's rely on the paths for
-            error checking.
-          */
-    {
-      Babl *shortcut_conversion;
+    int            hashval;
+    BablHashTable *id_htable;
+    BablFindFish   ffish = {(Babl *) NULL, 
+                            (Babl *) NULL, 
+                            (Babl *) NULL, 
+                            0,
+                            source_format, 
+                            destination_format};
 
-      shortcut_conversion = babl_conversion_find (
-        source_format, destination_format);
+    id_htable = (babl_fish_db ())->id_hash;
+    hashval = babl_hash_by_int (id_htable, babl_fish_get_id (source_format, destination_format));
 
-      if (shortcut_conversion)
-        {
-          return babl_fish_simple (&(shortcut_conversion->conversion));
-        }
-    }
+    if (source_format == destination_format)
+      {
+        /* In the case of equal source and destination formats
+         * we will search through the fish database for reference fish 
+         * to handle the memcpy */
+        id_htable->find_func = find_memcpy_fish;
+        babl_hash_table_find (id_htable, hashval, (void *) &ffish);
+      }
+    else 
+      {
+        /* In the case of different source and destination formats
+         * we will search through the fish database for appropriate fish path
+         * to handle the conversion. In the case that preexistent
+         * fish path is found, we'll return it. In the case BABL_FISH
+         * instance with the same source/destination is found, we'll
+         * return reference fish. 
+         * In the case neither fish path nor BABL_FISH path are found, 
+         * we'll try to construct new fish path for requested 
+         * source/destination. In the case new fish path is found, we'll
+         * return it, otherwise we'll create dummy BABL_FISH instance and
+         * insert it into the fish database to indicate non-existent fish
+         * path.
+         */
+        id_htable->find_func = find_fish_path;
+        babl_hash_table_find (id_htable, hashval, (void *) &ffish);
 
-  {
-    Babl *fish_path;
+        if (ffish.fish_path)
+          {
+            /* we have found suitable fish path in the database */
+            return ffish.fish_path;
+          }  
+        if (!ffish.fish_fish)
+          {
+            /* we haven't tried to search for suitable path yet */
+            Babl *fish_path = babl_fish_path (source_format, destination_format);
 
-    fish_path = babl_fish_path (source_format, destination_format);
+            if (fish_path)
+              {
+                return fish_path;
+              }
+            else 
+              {
+                /* there isn't a suitable path for requested formats,
+                 * let's create a dummy BABL_FISH instance and insert
+                 * it into the fish database to indicate that such path
+                 * does not exist.
+                 */
+                char *name = "X"; /* name does not matter */
+                Babl *fish = babl_calloc (1, sizeof (BablFish) + strlen (name) + 1);
+                
+                fish->class_type                = BABL_FISH;
+                fish->instance.id               = babl_fish_get_id (source_format, destination_format);
+                fish->instance.name             = ((char *) fish) + sizeof (BablFish);
+                strcpy (fish->instance.name, name);
+                fish->fish.source               = source_format;
+                fish->fish.destination          = destination_format;
+                babl_db_insert (babl_fish_db (), fish);
+              }
+          }
+      }
 
-    if (fish_path)
+    if (ffish.fish_ref)
+      {
+        /* we have already found suitable reference fish */
+        return ffish.fish_ref;
+      }
+    else 
       {
-        return fish_path;
+        /* we have to create new reference fish */
+        return babl_fish_reference (source_format, destination_format);
       }
   }
-
-  return babl_fish_reference (source_format, destination_format);
 }
 
 long
@@ -164,7 +278,7 @@ babl_fish_process (Babl *babl,
                    void *destination,
                    long  n)
 {
-  long       ret               = 0;
+  long ret = 0;
 
   switch (babl->class_type)
     {
_______________________________________________
Gegl-developer mailing list
Gegl-developer@xxxxxxxxxxxxxxxxxxxxxx
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer

[Index of Archives]     [Yosemite News]     [Yosemite Photos]     [gtk]     [GIMP Users]     [KDE]     [Gimp's Home]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux