Index: imagecache.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imagecache/imagecache.module,v
retrieving revision 1.19.2.15.2.10
diff -u -p -r1.19.2.15.2.10 imagecache.module
--- imagecache.module	19 Apr 2007 23:03:55 -0000	1.19.2.15.2.10
+++ imagecache.module	19 May 2007 13:40:02 -0000
@@ -161,38 +161,7 @@ function imagecache_cache() {
     file_copy($source, $tmpdestination);
 
     foreach ($actions as $action) {
-      $size = getimagesize($tmpdestination);
-      $new_width = _imagecache_filter('width', $action['data']['width'], $size[0], $size[1]);
-      $new_height = _imagecache_filter('height', $action['data']['height'], $size[0], $size[1]);
-      foreach ($action['data'] as $key => $value) {
-        $action['data'][$key] = _imagecache_filter($key, $value, $size[0], $size[1], $new_width, $new_height);
-      }
-      switch ($action['data']['function']) {
-        case 'resize':
-          if (!image_resize($tmpdestination, $tmpdestination, $action['data']['width'], $action['data']['height'])) {
-            watchdog('imagecache', t('Imagecache resize action ID %id failed.', array('%id' => $action['actionid'])), WATCHDOG_ERROR);
-          }
-          break;
-        case 'scale':
-          if ($action['data']['fit'] == 'outside' && $action['data']['width'] && $action['data']['height']) {
-            $ratio = $size[0]/$size[1];
-            $new_ratio = $action['data']['width']/$action['data']['height'];
-            $action['data']['width'] = $ratio > $new_ratio ? 0 : $action['data']['width'];
-            $action['data']['height'] = $ratio < $new_ratio ? 0 : $action['data']['height'];
-          }
-          // Set impossibly large values if the width and height aren't set.
-          $action['data']['width'] = $action['data']['width'] ? $action['data']['width'] : 9999999;
-          $action['data']['height'] = $action['data']['height'] ? $action['data']['height'] : 9999999;
-          if (!image_scale($tmpdestination, $tmpdestination, $action['data']['width'], $action['data']['height'])) {
-            watchdog('imagecache', t('Imagecache scale action ID %id failed.', array('%id' => $action['actionid'])), WATCHDOG_ERROR);
-          }
-          break;
-        case 'crop':
-          if (!image_crop($tmpdestination, $tmpdestination, $action['data']['xoffset'], $action['data']['yoffset'], $action['data']['width'], $action['data']['height'])) {
-            watchdog('imagecache', t('Imagecache crop action ID %id failed.', array('%id' => $action['actionid'])), WATCHDOG_ERROR);
-          }
-          break;
-      }
+      module_invoke($action['data']['module'], 'imagecache_action', 'process', $tmpdestination, $action['data']['delta'], $action);
     }
     file_move($tmpdestination, $destination);
   }
@@ -253,6 +222,63 @@ function imagecache_field_formatter($fie
   }
 }
 
+/**
+ * Implementation of hook_imagecache_action()
+ */
+function imagecache_imagecache_action($op, $image, $delta = '', $action = array()) {
+  switch ($op) {
+    case 'list':
+      $list = array();
+      $path = drupal_get_path('module', 'imagecache') . '/actions';
+      $files = drupal_system_listing('.*\.inc$', $path, 'name', 0);
+
+      foreach ($files as $file) {
+        $inc = $file->name;
+        $info = _imagecache_call_inc($inc, 'info');
+
+        if (is_array($info)) {
+          $list[$inc] = $info;
+        }
+      }
+
+      return $list;
+      break;
+    case 'form':
+      return _imagecache_call_inc($delta, 'admin', $action);
+      break;
+
+    case 'process':
+      $action['size'] = $size = getimagesize($image);
+      $new_width = _imagecache_filter('width', $action['data']['width'], $size[0], $size[1]);
+      $new_height = _imagecache_filter('height', $action['data']['height'], $size[0], $size[1]);
+      foreach ($action['data'] as $key => $value) {
+        $action['data'][$key] = _imagecache_filter($key, $value, $size[0], $size[1], $new_width, $new_height);
+      }
+      _imagecache_call_inc($delta, 'process', $image, $action);
+      break;
+  }
+}
+
+function _imagecache_call_inc($inc, $op, $a3 = NULL, $a4 = NULL) {
+  static $incs = array();
+  if (!isset($incs[$inc])) {
+    $filename = drupal_get_path('module', 'imagecache'). "/actions/{$inc}.inc";
+    if (file_exists($filename)) {
+      include_once $filename;
+      $incs[$inc] = TRUE;
+    }
+    else {
+      watchdog('imagecache', t('Imagecache was unable to locate include %file', array('%file' => $filename)));
+      return;
+    }
+  }
+
+  $f = 'imagecache_action_'. $inc .'_'. $op;
+  if (function_exists($f)) {
+    return $f($a3, $a4);
+  }
+}
+
 function _imagecache_file_load($fid = NULL) {
   // Don't bother if we weren't passed an fid.
   if (isset($fid) && is_numeric($fid)) {
@@ -448,9 +474,10 @@ function imagecache_admin_submit($form_i
         case t('Update preset'):
           // Add new actions
           $newaction = $form_values['presets'][$presetid]['handlers']['newaction'];
-          if ($newaction) {
+          if ($newaction != NULL) {
             $action = array();
-            $action['data'] = array('function' => $newaction);
+            $action['data'] = $form_values['presets'][$presetid]['handlers']['action_list'][$newaction];
+            unset($action['data']['description']);
             $action['presetid'] = $presetid;
             $action['weight'] = 0;
             _imagecache_action_create($action);
@@ -600,12 +627,21 @@ function _imagecache_actions_form($prese
     //debug_msg($action);
     $form[$actionid] = array(
       '#type' => 'fieldset',
-      '#title' => t($action['data']['function']),
+      '#title' => t($action['data']['title']),
     );
 
-    $form[$actionid]['data']['function'] = array(
-      '#type' => 'hidden',
-      '#value' => $action['data']['function'],
+    $form[$actionid]['data'] = module_invoke($action['data']['module'], 'imagecache_action', 'form', NULL, $action['data']['delta'], $action);
+    $form[$actionid]['data']['module'] = array(
+      '#type' => 'value',
+      '#value' => $action['data']['module'],
+    );
+    $form[$actionid]['data']['delta'] = array(
+      '#type' => 'value',
+      '#value' => $action['data']['delta'],
+    );
+    $form[$actionid]['data']['title'] = array(
+      '#type' => 'value',
+      '#value' => $action['data']['title'],
     );
     $form[$actionid]['weight'] = array(
       '#type' => 'weight',
@@ -613,64 +649,6 @@ function _imagecache_actions_form($prese
       '#default_value' => $action['weight'],
     );
 
-    switch ($action['data']['function']) {
-      case 'scale':
-        $helptext = array();
-        $helptext['inside'] = t('<strong>Inside dimensions</strong>: Final dimensions will be less than or equal to the entered width and height. Useful for ensuring a maximum height and/or width.');
-        $helptext['outside'] = t('<strong>Outside dimensions</strong>: Final dimensions will be greater than or equal to the entered width and height. Ideal for cropping the result to a square.');
-        $description = '<ul><li>'. implode('</li><li>', $helptext) .'</li><ul>';
-
-        $form[$actionid]['data']['fit'] = array(
-          '#type' => 'select',
-          '#title' => t('Scale to fit'),
-          '#options' => array('inside' => t('Inside dimensions'), 'outside' => t('Outside dimensions')),
-          '#default_value' => $action['data']['fit'],
-          '#weight' => 1,
-          '#description' => $description,
-        );
-      case 'resize':
-        $form[$actionid]['data']['width'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Width'),
-          '#default_value' => $action['data']['width'],
-          '#description' => t('Enter a width in pixels or as a percentage. i.e. 500 or 80%.'),
-        );
-        $form[$actionid]['data']['height'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Height'),
-          '#default_value' => $action['data']['height'],
-          '#description' => t('Enter a height in pixels or as a percentage. i.e. 500 or 80%.'),
-        );
-        break;
-      case 'crop':
-        $form[$actionid]['data']['width'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Width'),
-          '#default_value' => $action['data']['width'],
-          '#description' => t('Enter a width in pixels or as a percentage. i.e. 500 or 80%.'),
-        );
-        $form[$actionid]['data']['height'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Height'),
-          '#default_value' => $action['data']['height'],
-          '#description' => t('Enter a height in pixels or as a percentage. i.e. 500 or 80%.'),
-        );
-        $form[$actionid]['data']['xoffset'] = array(
-          '#type' => 'textfield',
-          '#title' => t('X offset'),
-          '#default_value' => $action['data']['xoffset'],
-          '#description' => t('Enter an offset in pixels or use a keyword: <em>left</em>, <em>center</em>, or <em>right</em>.'),
-        );
-        $form[$actionid]['data']['yoffset'] = array(
-          '#type' => 'textfield',
-          '#title' => t('Y offset'),
-          '#default_value' => $action['data']['yoffset'],
-          '#description' => t('Enter an offset in pixels or use a keyword: <em>top</em>, <em>center</em>, or <em>bottom</em>.'),
-        );
-        break;
-      case 'watermark':
-        // Think about this one...        
-    }
     $form[$actionid]['remove'] = array(
       '#type' => 'checkbox',
       '#title' => t('Remove this action'),
@@ -678,14 +656,30 @@ function _imagecache_actions_form($prese
   }
 
   $helptext = array();
-  $helptext['scale']  = t('<strong>Scale</strong>: Resize an image maintaining the original aspect-ratio (only one value necessary).');
-  $helptext['resize'] = t('<strong>Resize</strong>: Resize an image to an exact set of dimensions, ignoring aspect ratio.');
-  $helptext['crop']   = t('<strong>Crop</strong>: Crop an image to the rectangle specified by the given offsets and dimensions.');
+  $options = array();
+  $action_list = array();
+  foreach (module_implements('imagecache_action') as $module) {
+    if ($list = module_invoke($module, 'imagecache_action', 'list', NULL)) {
+      foreach ($list as $delta => $option) {
+        $option['module'] = $module;
+        $option['delta'] = $delta;
+        $action_list[] = $option;
+      }
+    }
+  }
+  $form['action_list'] = array(
+    '#type' => 'value',
+    '#value' => $action_list,
+  );
+  $options[''] = t('select...');
+  foreach ($action_list as $key => $value) {
+    $options[$key] = $value['title'];
+    $helptext[$key] = t('<strong>@action</strong>: @description', array('@action' => $value['title'], '@description' => $value['description']));
+  }
   $description = '<ul><li>'. implode('</li><li>', $helptext) .'</li><ul>';
-
   $form['newaction'] = array(
     '#type' => 'select',
-    '#options' => array('' => t('select...'), 'scale' => t('Scale'), 'resize' => t('Resize'), 'crop' => t('Crop')),
+    '#options' => $options,
     '#title' => t('Add a new action'),
     '#description' => $description,
   );
Index: actions/crop.inc
===================================================================
RCS file: actions/crop.inc
diff -N actions/crop.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ actions/crop.inc	19 May 2007 13:40:02 -0000
@@ -0,0 +1,43 @@
+<?php
+// $Id:$
+
+function imagecache_action_crop_info() {
+  return array(
+    'title' => t('Crop'),
+    'description' => t('Crop an image to the rectangle specified by the given offsets and dimensions.'),
+  );
+}
+
+function imagecache_action_crop_admin($action) {
+  $form['width'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Width'),
+    '#default_value' => $action['data']['width'],
+    '#description' => t('Enter a width in pixels or as a percentage. i.e. 500 or 80%.'),
+  );
+  $form['height'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Height'),
+    '#default_value' => $action['data']['height'],
+    '#description' => t('Enter a height in pixels or as a percentage. i.e. 500 or 80%.'),
+  );
+  $form['xoffset'] = array(
+    '#type' => 'textfield',
+    '#title' => t('X offset'),
+    '#default_value' => $action['data']['xoffset'],
+    '#description' => t('Enter an offset in pixels or use a keyword: <em>left</em>, <em>center</em>, or <em>right</em>.'),
+  );
+  $form['yoffset'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Y offset'),
+    '#default_value' => $action['data']['yoffset'],
+    '#description' => t('Enter an offset in pixels or use a keyword: <em>top</em>, <em>center</em>, or <em>bottom</em>.'),
+  );
+  return $form;
+}
+
+function imagecache_action_crop_process($image, $action) {
+  if (!image_crop($image, $image, $action['data']['xoffset'], $action['data']['yoffset'], $action['data']['width'], $action['data']['height'])) {
+    watchdog('imagecache', t('Imagecache crop action ID %id failed.', array('%id' => $action['actionid'])), WATCHDOG_ERROR);
+  }
+}
Index: actions/resize.inc
===================================================================
RCS file: actions/resize.inc
diff -N actions/resize.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ actions/resize.inc	19 May 2007 13:40:02 -0000
@@ -0,0 +1,31 @@
+<?php
+// $Id:$
+
+function imagecache_action_resize_info() {
+  return array(
+    'title' => t('Resize'),
+    'description' => t('Resize an image to an exact set of dimensions, ignoring aspect ratio.'),
+  );
+}
+
+function imagecache_action_resize_admin($action) {
+  $form['width'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Width'),
+    '#default_value' => $action['data']['width'],
+    '#description' => t('Enter a width in pixels or as a percentage. i.e. 500 or 80%.'),
+  );
+  $form['height'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Height'),
+    '#default_value' => $action['data']['height'],
+    '#description' => t('Enter a height in pixels or as a percentage. i.e. 500 or 80%.'),
+  );
+  return $form;
+}
+
+function imagecache_action_resize_process($image, $action) {
+  if (!image_resize($image, $image, $action['data']['width'], $action['data']['height'])) {
+    watchdog('imagecache', t('Imagecache resize action ID %id failed.', array('%id' => $action['actionid'])), WATCHDOG_ERROR);
+  }
+}
Index: actions/scale.inc
===================================================================
RCS file: actions/scale.inc
diff -N actions/scale.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ actions/scale.inc	19 May 2007 13:40:02 -0000
@@ -0,0 +1,43 @@
+<?php
+// $Id:$
+
+function imagecache_action_scale_info() {
+  return array(
+    'title' => t('Scale'),
+    'description' => t('Resize an image maintaining the original aspect-ratio (only one value necessary)'),
+  );
+}
+
+function imagecache_action_scale_admin($action) {
+  $helptext = array();
+  $helptext['inside'] = t('<strong>Inside dimensions</strong>: Final dimensions will be less than or equal to the entered width and height. Useful for ensuring a maximum height and/or width.');
+  $helptext['outside'] = t('<strong>Outside dimensions</strong>: Final dimensions will be greater than or equal to the entered width and height. Ideal for cropping the result to a square.');
+  $description = '<ul><li>'. implode('</li><li>', $helptext) .'</li><ul>';
+
+  $form['fit'] = array(
+    '#type' => 'select',
+    '#title' => t('Scale to fit'),
+    '#options' => array('inside' => t('Inside dimensions'), 'outside' => t('Outside dimensions')),
+    '#default_value' => $action['data']['fit'],
+    '#weight' => 1,
+    '#description' => $description,
+  );
+
+  return $form;
+}
+
+function imagecache_action_scale_process($image, $action) {
+  if ($action['data']['fit'] == 'outside' && $action['data']['width'] && $action['data']['height']) {
+    $ratio = $action['size'][0]/$action['size'][1];
+    $new_ratio = $action['data']['width']/$action['data']['height'];
+    $action['data']['width'] = $ratio > $new_ratio ? 0 : $action['data']['width'];
+    $action['data']['height'] = $ratio < $new_ratio ? 0 : $action['data']['height'];
+  }
+  // Set impossibly large values if the width and height aren't set.
+  $action['data']['width'] = $action['data']['width'] ? $action['data']['width'] : 9999999;
+  $action['data']['height'] = $action['data']['height'] ? $action['data']['height'] : 9999999;
+  if (!image_scale($image, $image, $action['data']['width'], $action['data']['height'])) {
+    watchdog('imagecache', t('Imagecache scale action ID %id failed.', array('%id' => $action['actionid'])), WATCHDOG_ERROR);
+  }
+}
+
