Index: imagecache.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/imagecache/imagecache.module,v
retrieving revision 1.9.2.14
diff -u -r1.9.2.14 imagecache.module
--- imagecache.module	29 Nov 2006 07:56:33 -0000	1.9.2.14
+++ imagecache.module	29 Nov 2006 15:49:53 -0000
@@ -95,6 +95,12 @@
     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']['width'], $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'])) {
@@ -103,6 +109,12 @@
           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 width and height to impossibly large values if unset. allows scaling by only 
           // specifying a single dimension.
           $action['data']['width'] = $action['data']['width'] ? $action['data']['width'] : 9999999;
@@ -409,16 +421,31 @@
 
       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;
         
@@ -427,21 +454,25 @@
             '#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;
 
@@ -490,6 +521,58 @@
   return true;
 }
 
+/**
+ * Filter key word values such as 'top', 'right', 'center', and also percentages.
+ * All returned values are in pixels relative to the passed in height and width
+ */
+function _imagecache_filter($key, $value, $current_width, $current_height, $new_width = NULL, $new_height = NULL) {
+  switch ($key) {
+    case 'width':
+      $value = _imagecache_percent_filter($value, $current_width);
+      break;
+    case 'height':
+      $value = _imagecache_percent_filter($value, $current_height);
+      break;
+    case 'xoffset':
+      $value = _imagecache_keyword_filter($value, $current_width, $new_width);
+      break;
+    case 'yoffset':
+      $value = _imagecache_keyword_filter($value, $current_height, $new_height);
+      break;
+  }
+  return $value;
+}
+
+/**
+ * Accept a percentage and return it in pixels
+ */
+function _imagecache_percent_filter($value, $current_pixels) {
+  if (strpos($value, '%') !== FALSE) {
+    $value = str_replace('%', '', $value) * 0.01 * $current_pixels;
+  }
+  return $value;
+}
+
+/**
+ * Accept a keyword (center, top, left, etc) and return it as an offset in pixels
+ */
+function _imagecache_keyword_filter($value, $current_pixels, $new_pixels) {
+  switch ($value) {
+    case 'top':
+    case 'left':
+      $value = 0;
+      break;
+    case 'bottom':
+    case 'right':
+      $value = $current_pixels - $new_pixels;
+      break;
+    case 'center':
+      $value = $current_pixels/2 - $new_pixels/2;
+      break;
+  }
+  return $value;
+}
+
 function theme_imagecache_admin($form) {
   $output = '';
   $output .= '<p class="cvs-version">$Id: imagecache.module,v 1.9.2.14 2006/11/29 07:56:33 dopry Exp $</p>';
