babl r304 - in trunk: . babl



Author: ok
Date: Tue Apr  8 18:01:23 2008
New Revision: 304
URL: http://svn.gnome.org/viewvc/babl?rev=304&view=rev

Log:
Applied patch from Jan Heller 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. 
* babl/babl-fish.c: (find_fish_path), (find_memcpy_fish),
(babl_fish_get_id), (babl_fish):
* babl/babl-fish-path.c: (babl_fish_path):
* babl/babl-fish-reference.c: (babl_fish_reference):
* babl/babl-fish-simple.c: (babl_fish_simple):
* babl/babl-internal.h:


Modified:
   trunk/ChangeLog
   trunk/babl/babl-fish-path.c
   trunk/babl/babl-fish-reference.c
   trunk/babl/babl-fish-simple.c
   trunk/babl/babl-fish.c
   trunk/babl/babl-internal.h

Modified: trunk/babl/babl-fish-path.c
==============================================================================
--- trunk/babl/babl-fish-path.c	(original)
+++ trunk/babl/babl-fish-path.c	Tue Apr  8 18:01:23 2008
@@ -193,9 +193,10 @@
 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 @@
       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;

Modified: trunk/babl/babl-fish-reference.c
==============================================================================
--- trunk/babl/babl-fish-reference.c	(original)
+++ trunk/babl/babl-fish-reference.c	Tue Apr  8 18:01:23 2008
@@ -69,7 +69,7 @@
   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;

Modified: trunk/babl/babl-fish-simple.c
==============================================================================
--- trunk/babl/babl-fish-simple.c	(original)
+++ trunk/babl/babl-fish-simple.c	Tue Apr  8 18:01:23 2008
@@ -33,7 +33,6 @@
   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 = 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;

Modified: trunk/babl/babl-fish.c
==============================================================================
--- trunk/babl/babl-fish.c	(original)
+++ trunk/babl/babl-fish.c	Tue Apr  8 18:01:23 2008
@@ -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 @@
   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 @@
   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_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 @@
     }
 
   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 *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 @@
                    void *destination,
                    long  n)
 {
-  long       ret               = 0;
+  long ret = 0;
 
   switch (babl->class_type)
     {

Modified: trunk/babl/babl-internal.h
==============================================================================
--- trunk/babl/babl-internal.h	(original)
+++ trunk/babl/babl-internal.h	Tue Apr  8 18:01:23 2008
@@ -88,6 +88,8 @@
                                          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,



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