]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/geometry.c
(no commit message)
[imagemagick] / MagickCore / geometry.c
index 0a6f4dc57efdaa3d31db615e29376b0735c77265..9ae2849a4f43a6217d25e45d0f58594db146870a 100644 (file)
 %                       MagickCore Geometry Methods                           %
 %                                                                             %
 %                             Software Design                                 %
-%                               John Cristy                                   %
+%                                  Cristy                                     %
 %                              January 2003                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
 %  whether the x or y values are negative.  In addition, there are flags to
 %  report any meta characters (%, !, <, or >).
 %
+%  The value must form a proper geometry style specification of WxH+X+Y
+%  of integers only, and values can not be separated by comma, colon, or
+%  slash charcaters.  See ParseGeometry() below.
+%
+%  Offsets may be prefixed by multiple signs to make offset string
+%  substitutions easier to handle from shell scripts.
+%  For example: "-10-10", "-+10-+10", or "+-10+-10" will generate negtive
+%  offsets, while "+10+10", "++10++10", or "--10--10" will generate positive
+%  offsets.
+%
 %  The format of the GetGeometry method is:
 %
 %      MagickStatusType GetGeometry(const char *geometry,ssize_t *x,ssize_t *y,
@@ -160,6 +170,13 @@ MagickExport MagickStatusType GetGeometry(const char *geometry,ssize_t *x,
         (void) CopyMagickString(p,p+1,MaxTextExtent);
         break;
       }
+      case 'x':
+      case 'X':
+      {
+        flags|=SeparatorValue;
+        p++;
+        break;
+      }
       case '-':
       case '.':
       case ',':
@@ -174,9 +191,9 @@ MagickExport MagickStatusType GetGeometry(const char *geometry,ssize_t *x,
       case '7':
       case '8':
       case '9':
-      case 'x':
-      case 'X':
       case 215:
+      case 'e':
+      case 'E':
       {
         p++;
         break;
@@ -196,33 +213,39 @@ MagickExport MagickStatusType GetGeometry(const char *geometry,ssize_t *x,
   (void) value;
   if (LocaleNCompare(p,"0x",2) == 0)
     value=(double) strtol(p,&q,10);
-  c=(int) ((unsigned char) *q);
-  if ((c == 215) || (*q == 'x') || (*q == 'X') || (*q == '\0'))
-    {
-      /*
-        Parse width.
-      */
-      q=p;
-      if (LocaleNCompare(p,"0x",2) == 0)
-        *width=(size_t) strtol(p,&p,10);
-      else
-        *width=(size_t) floor(StringToDouble(p,&p)+0.5);
-      if (p != q)
-        flags|=WidthValue;
-    }
-  c=(int) ((unsigned char) *p);
-  if ((c == 215) || (*p == 'x') || (*p == 'X'))
+  if ((*p != '+') && (*p != '-'))
     {
-      p++;
-      if ((*p != '+') && (*p != '-'))
+      c=(int) ((unsigned char) *q);
+      if ((c == 215) || (*q == 'x') || (*q == 'X') || (*q == '\0'))
         {
           /*
-            Parse height.
+            Parse width.
           */
           q=p;
-          *height=(size_t) floor(StringToDouble(p,&p)+0.5);
+          if (LocaleNCompare(p,"0x",2) == 0)
+            *width=(size_t) strtol(p,&p,10);
+          else
+            *width=(size_t) floor(StringToDouble(p,&p)+0.5);
           if (p != q)
-            flags|=HeightValue;
+            flags|=WidthValue;
+        }
+    }
+  if ((*p != '+') && (*p != '-'))
+    {
+      c=(int) ((unsigned char) *p);
+      if ((c == 215) || (*p == 'x') || (*p == 'X'))
+        {
+          p++;
+          if ((*p != '+') && (*p != '-'))
+            {
+              /*
+                Parse height.
+              */
+              q=p;
+              *height=(size_t) floor(StringToDouble(p,&p)+0.5);
+              if (p != q)
+                flags|=HeightValue;
+            }
         }
     }
   if ((*p == '+') || (*p == '-'))
@@ -230,25 +253,62 @@ MagickExport MagickStatusType GetGeometry(const char *geometry,ssize_t *x,
       /*
         Parse x value.
       */
-      if (*p == '-')
-        flags|=XNegative;
+      while ((*p == '+') || (*p == '-'))
+      {
+        if (*p == '-')
+          flags^=XNegative;  /* negate sign */
+        p++;
+      }
       q=p;
       *x=(ssize_t) ceil(StringToDouble(p,&p)-0.5);
       if (p != q)
-        flags|=XValue;
-      if ((*p == '+') || (*p == '-'))
         {
-          /*
-            Parse y value.
-          */
-          if (*p == '-')
-            flags|=YNegative;
-          q=p;
-          *y=(ssize_t) ceil(StringToDouble(p,&p)-0.5);
-          if (p != q)
-            flags|=YValue;
+          flags|=XValue;
+          if ((flags & XNegative) != 0)
+            *x=(-*x);
         }
     }
+  if ((*p == '+') || (*p == '-'))
+    {
+      /*
+        Parse y value.
+      */
+      while ((*p == '+') || (*p == '-'))
+      {
+        if (*p == '-')
+          flags^=YNegative;  /* negate sign */
+        p++;
+      }
+      q=p;
+      *y=(ssize_t) ceil(StringToDouble(p,&p)-0.5);
+      if (p != q)
+        {
+          flags|=YValue;
+          if ((flags & YNegative) != 0)
+            *y=(-*y);
+        }
+    }
+  if ((flags & PercentValue) != 0)
+    {
+      if (((flags & SeparatorValue) == 0) && ((flags & HeightValue) == 0))
+        {
+          *height=(*width);
+          flags|=HeightValue;
+        }
+      if (((flags & SeparatorValue) != 0) && ((flags & WidthValue) == 0))
+        *width=(*height);
+    }
+#if 0
+  /* Debugging Geometry */
+  (void) fprintf(stderr,"GetGeometry...\n");
+  (void) fprintf(stderr,"Input: %s\n",geometry);
+  (void) fprintf(stderr,"Flags: %c %c %s %s\n",
+    (flags & WidthValue) ? 'W' : ' ',(flags & HeightValue) ? 'H' : ' ',
+    (flags & XValue) ? ((flags & XNegative) ? "-X" : "+X") : "  ",
+    (flags & YValue) ? ((flags & YNegative) ? "-Y" : "+Y") : "  ");
+  (void) fprintf(stderr,"Geometry: %ldx%ld%+ld%+ld\n",(long) *width,(long)
+    *height,(long) *x,(long) *y);
+#endif
   return(flags);
 }
 \f
@@ -297,7 +357,7 @@ MagickExport char *GetPageGeometry(const char *page_geometry)
       { "a2",  "1191x1684" },
       { "a3",  "842x1191" },
       { "a4",  "595x842" },
-      { "a4smaLL", "595x842" },
+      { "a4small", "595x842" },
       { "a5",  "420x595" },
       { "a6",  "297x420" },
       { "a7",  "210x297" },
@@ -353,7 +413,7 @@ MagickExport char *GetPageGeometry(const char *page_geometry)
       { "ledger",  "1224x792" },
       { "legal",  "612x1008" },
       { "letter", "612x792" },
-      { "lettersmaLL",  "612x792" },
+      { "lettersmall",  "612x792" },
       { "quarto",  "610x780" },
       { "statement",  "396x612" },
       { "tabloid",  "792x1224" },
@@ -442,7 +502,6 @@ MagickExport void GravityAdjustGeometry(const size_t width,
     case NorthGravity:
     case SouthGravity:
     case CenterGravity:
-    case StaticGravity:
     {
       region->x+=(ssize_t) (width/2-region->width/2);
       break;
@@ -466,7 +525,6 @@ MagickExport void GravityAdjustGeometry(const size_t width,
     case EastGravity:
     case WestGravity:
     case CenterGravity:
-    case StaticGravity:
     {
       region->y+=(ssize_t) (height/2-region->height/2);
       break;
@@ -700,8 +758,8 @@ MagickExport MagickStatusType ParseAffineGeometry(const char *geometry,
       }
     }
   }
-  determinant=(affine_matrix->sx*affine_matrix->sy
-                 - affine_matrix->rx*affine_matrix->ry);
+  determinant=(affine_matrix->sx*affine_matrix->sy-affine_matrix->rx*
+    affine_matrix->ry);
   if (fabs(determinant) < MagickEpsilon)
     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
       "InvalidArgument","'%s' : 'Indeterminate Matrix'",geometry);
@@ -728,6 +786,13 @@ MagickExport MagickStatusType ParseAffineGeometry(const char *geometry,
 %  and ^) flags present. It does not report the location of the percentage
 %  relative to the values.
 %
+%  Values may also be separated by commas, colons, or slashes, and offsets.
+%  Offsets may be prefixed by multiple signs to make offset string
+%  substitutions easier to handle from shell scripts.
+%  For example: "-10-10", "-+10-+10", or "+-10+-10" will generate negtive
+%  offsets, while "+10+10", "++10++10", or "--10--10" will generate positive
+%  offsets.
+%
 %  The format of the ParseGeometry method is:
 %
 %      MagickStatusType ParseGeometry(const char *geometry,
@@ -819,6 +884,13 @@ MagickExport MagickStatusType ParseGeometry(const char *geometry,
         (void) CopyMagickString(p,p+1,MaxTextExtent);
         break;
       }
+      case 'x':
+      case 'X':
+      {
+        flags|=SeparatorValue;
+        p++;
+        break;
+      }
       case '-':
       case '+':
       case ',':
@@ -832,11 +904,11 @@ MagickExport MagickStatusType ParseGeometry(const char *geometry,
       case '7':
       case '8':
       case '9':
-      case 'x':
-      case 'X':
       case '/':
       case ':':
       case 215:
+      case 'e':
+      case 'E':
       {
         p++;
         break;
@@ -910,15 +982,21 @@ MagickExport MagickStatusType ParseGeometry(const char *geometry,
       /*
         Parse xi value.
       */
-      if ((*p == '+') || (*p == ',') || (*p == '/') || (*p == ':') )
+      if ((*p == ',') || (*p == '/') || (*p == ':') )
+        p++;
+      while ((*p == '+') || (*p == '-'))
+      {
+        if (*p == '-')
+          flags^=XiNegative;  /* negate sign */
         p++;
+      }
       q=p;
       value=StringToDouble(p,&p);
       if (p != q)
         {
           flags|=XiValue;
-          if (*q == '-')
-            flags|=XiNegative;
+          if ((flags & XiNegative) != 0)
+            value=(-value);
           geometry_info->xi=value;
         }
       while (isspace((int) ((unsigned char) *p)) != 0)
@@ -929,18 +1007,24 @@ MagickExport MagickStatusType ParseGeometry(const char *geometry,
           /*
             Parse psi value.
           */
-          if ((*p == '+') || (*p == ',') || (*p == '/') || (*p == ':'))
+          if ((*p == ',') || (*p == '/') || (*p == ':'))
+            p++;
+          while ((*p == '+') || (*p == '-'))
+          {
+            if (*p == '-')
+              flags^=PsiNegative;  /* negate sign */
             p++;
+          }
           q=p;
           value=StringToDouble(p,&p);
           if (p != q)
             {
               flags|=PsiValue;
-              if (*q == '-')
-                flags|=PsiNegative;
+              if ((flags & PsiNegative) != 0)
+                value=(-value);
               geometry_info->psi=value;
             }
-        }
+      }
       while (isspace((int) ((unsigned char) *p)) != 0)
         p++;
       if ((*p == '+') || (*p == '-') || (*p == ',') || (*p == '/') ||
@@ -949,15 +1033,21 @@ MagickExport MagickStatusType ParseGeometry(const char *geometry,
           /*
             Parse chi value.
           */
-          if ((*p == '+') || (*p == ',') || (*p == '/') || (*p == ':'))
+          if ((*p == ',') || (*p == '/') || (*p == ':'))
+            p++;
+          while ((*p == '+') || (*p == '-'))
+          {
+            if (*p == '-')
+              flags^=ChiNegative;  /* negate sign */
             p++;
+          }
           q=p;
           value=StringToDouble(p,&p);
           if (p != q)
             {
               flags|=ChiValue;
-              if (*q == '-')
-                flags|=ChiNegative;
+              if ((flags & ChiNegative) != 0)
+                value=(-value);
               geometry_info->chi=value;
             }
         }
@@ -983,6 +1073,25 @@ MagickExport MagickStatusType ParseGeometry(const char *geometry,
       flags|=SigmaValue;
       flags&=(~XiValue);
     }
+  if ((flags & PercentValue) != 0)
+    {
+      if (((flags & SeparatorValue) == 0) && ((flags & SigmaValue) == 0))
+        geometry_info->sigma=geometry_info->rho;
+      if (((flags & SeparatorValue) != 0) && ((flags & RhoValue) == 0))
+        geometry_info->rho=geometry_info->sigma;
+    }
+#if 0
+  /* Debugging Geometry */
+  (void) fprintf(stderr,"ParseGeometry...\n");
+  (void) fprintf(stderr,"Flags: %c %c %s %s %s\n",
+    (flags & RhoValue) ? 'W' : ' ',(flags & SigmaValue) ? 'H' : ' ',
+    (flags & XiValue) ? ((flags & XiNegative) ? "-X" : "+X") : "  ",
+    (flags & PsiValue) ? ((flags & PsiNegative) ? "-Y" : "+Y") : "  ",
+    (flags & ChiValue) ? ((flags & ChiNegative) ? "-Z" : "+Z") : "  ");
+  (void) fprintf(stderr,"Geometry: %lg,%lg,%lg,%lg,%lg\n",geometry_info->rho,
+    geometry_info->sigma,geometry_info->xi,geometry_info->psi,
+    geometry_info->chi);
+#endif
   return(flags);
 }
 \f
@@ -1042,7 +1151,7 @@ MagickExport MagickStatusType ParseGravityGeometry(const Image *image,
   if (flags == NoValue)
     {
       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-        "InvalidGeometry","'%s'",geometry);
+        "InvalidGeometry","`%s'",geometry);
       return(flags);
     }
   if ((flags & PercentValue) != 0)
@@ -1106,7 +1215,7 @@ MagickExport MagickStatusType ParseGravityGeometry(const Image *image,
 %  image within the specified geometry width and height.
 %
 %  Flags are interpreted...
-%     %   geometry size is given percentage of original image size
+%     %   geometry size is given percentage of original width and height given
 %     !   do not try to preserve aspect ratio
 %     <   only enlarge images smaller that geometry
 %     >   only shrink images larger than geometry
@@ -1186,11 +1295,7 @@ MagickExport MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x,
       if ((flags & SigmaValue) == 0)
         scale.y=scale.x;
       *width=(size_t) floor(scale.x*former_width/100.0+0.5);
-      if (*width == 0)
-        *width=1;
       *height=(size_t) floor(scale.y*former_height/100.0+0.5);
-      if (*height == 0)
-        *height=1;
       former_width=(*width);
       former_height=(*height);
     }
@@ -1272,12 +1377,12 @@ MagickExport MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x,
       (void) ParseGeometry(geometry,&geometry_info);
       area=geometry_info.rho;
       distance=sqrt((double) former_width*former_height);
-      scale.x=(double) former_width/(distance/sqrt((double) area));
-      scale.y=(double) former_height/(distance/sqrt((double) area));
+      scale.x=former_width/(distance/sqrt(area));
+      scale.y=former_height/(distance/sqrt(area));
       if ((scale.x < (double) *width) || (scale.y < (double) *height))
         {
-          *width=(size_t) (former_width/(distance/sqrt(area))+0.5);
-          *height=(size_t) (former_height/(distance/sqrt(area))+0.5);
+          *width=(unsigned long) (former_width/(distance/sqrt(area)));
+          *height=(unsigned long) (former_height/(distance/sqrt(area)));
         }
       former_width=(*width);
       former_height=(*height);
@@ -1333,7 +1438,7 @@ MagickExport MagickStatusType ParsePageGeometry(const Image *image,
   if (flags == NoValue)
     {
       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-        "InvalidGeometry","'%s'",geometry);
+        "InvalidGeometry","`%s'",geometry);
       return(flags);
     }
   if ((flags & PercentValue) != 0)
@@ -1343,6 +1448,14 @@ MagickExport MagickStatusType ParsePageGeometry(const Image *image,
     }
   flags=ParseMetaGeometry(geometry,&region_info->x,&region_info->y,
     &region_info->width,&region_info->height);
+  if ((((flags & WidthValue) != 0) || ((flags & HeightValue) != 0)) &&
+      (((flags & PercentValue) != 0) || ((flags & SeparatorValue) == 0)))
+    {
+      if ((flags & WidthValue) == 0)
+        region_info->width=region_info->height;
+      if ((flags & HeightValue) == 0)
+        region_info->height=region_info->width;
+    }
   return(flags);
 }
 \f
@@ -1390,7 +1503,7 @@ MagickExport MagickStatusType ParseRegionGeometry(const Image *image,
     &region_info->width,&region_info->height);
   if (flags == NoValue)
     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "InvalidGeometry","'%s'",geometry);
+      "InvalidGeometry","`%s'",geometry);
   return(flags);
 }
 \f