Bug 665571 - Have DrawCellWithSnapping handles special NSZeroSize value in CellRenderSettings. r=mstange
authorMounir Lamouri <mounir.lamouri@gmail.com>
Fri, 08 Jul 2011 14:56:44 +0200
changeset 73367 0bd82b867cf012b05c1c283341f1ceea2dbe0ebc
parent 73366 364d2debc2a7c95797d1e03db5076ad0b8684183
child 73368 f53268a84b23ca67cb6cc5c8c867f0f2c582e37c
push idunknown
push userunknown
push dateunknown
reviewersmstange
bugs665571
milestone8.0a1
Bug 665571 - Have DrawCellWithSnapping handles special NSZeroSize value in CellRenderSettings. r=mstange
widget/src/cocoa/nsNativeThemeCocoa.mm
--- a/widget/src/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/src/cocoa/nsNativeThemeCocoa.mm
@@ -275,16 +275,25 @@ static int EnumSizeForCocoaSize(NSContro
   if (cocoaControlSize == NSMiniControlSize)
     return miniControlSize;
   else if (cocoaControlSize == NSSmallControlSize)
     return smallControlSize;
   else
     return regularControlSize;
 }
 
+static NSControlSize CocoaSizeForEnum(PRInt32 enumControlSize) {
+  if (enumControlSize == miniControlSize)
+    return NSMiniControlSize;
+  else if (enumControlSize == smallControlSize)
+    return NSSmallControlSize;
+  else
+    return NSRegularControlSize;
+}
+
 static void InflateControlRect(NSRect* rect, NSControlSize cocoaControlSize, const float marginSet[][3][4])
 {
   if (!marginSet)
     return;
 
   static int osIndex = leopardOS;
   int controlSize = EnumSizeForCocoaSize(cocoaControlSize);
   const float* buttonMargins = marginSet[osIndex][controlSize];
@@ -552,16 +561,59 @@ struct CellRenderSettings {
   // A three-dimensional array,
   // with the first dimension being the OS version (only Leopard for the moment),
   // the second being the control size (mini, small, regular), and the third
   // being the 4 margin values (left, top, right, bottom).
   float margins[1][3][4];
 };
 
 /*
+ * This is a helper method that returns the required NSControlSize given a size
+ * and the size of the three controls plus a tolerance.
+ * size - The width or the height of the element to draw.
+ * sizes - An array with the all the width/height of the element for its
+ *         different sizes.
+ * tolerance - The tolerance as passed to DrawCellWithSnapping.
+ * NOTE: returns NSRegularControlSize if all values in 'sizes' are zero.
+ */
+static NSControlSize FindControlSize(CGFloat size, CGFloat* sizes, CGFloat tolerance)
+{
+  for (PRUint32 i = miniControlSize; i <= regularControlSize; ++i) {
+    if (sizes[i] == 0) {
+      continue;
+    }
+
+    CGFloat next = 0;
+    // Find next value.
+    for (PRUint32 j = i+1; j <= regularControlSize; ++j) {
+      if (sizes[j] != 0) {
+        next = sizes[j];
+        break;
+      }
+    }
+
+    // If it's the latest value, we pick it.
+    if (next == 0) {
+      return CocoaSizeForEnum(i);
+    }
+
+    if (size <= sizes[i] + tolerance && size < next) {
+      return CocoaSizeForEnum(i);
+    }
+  }
+
+  // If we are here, that means sizes[] was an array with only empty values
+  // or the algorithm above is wrong.
+  // The former can happen but the later would be wrong.
+  NS_ASSERTION(sizes[0] == 0 && sizes[1] == 0 && sizes[2] == 0,
+               "We found no control! We shouldn't be there!");
+  return CocoaSizeForEnum(regularControlSize);
+}
+
+/*
  * Draw the given NSCell into the given cgContext with a nice control size.
  *
  * This function is similar to DrawCellWithScaling, but it decides what
  * control size to use based on the destRect's size.
  * Scaling is only applied when the difference between the destRect's size
  * and the next smaller natural size is greater than snapTolerance. Otherwise
  * it snaps to the next smaller control size without scaling because unscaled
  * controls look nicer.
@@ -578,28 +630,22 @@ static void DrawCellWithSnapping(NSCell 
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   const float rectWidth = destRect.size.width, rectHeight = destRect.size.height;
   const NSSize *sizes = settings.naturalSizes;
   const NSSize miniSize = sizes[EnumSizeForCocoaSize(NSMiniControlSize)];
   const NSSize smallSize = sizes[EnumSizeForCocoaSize(NSSmallControlSize)];
   const NSSize regularSize = sizes[EnumSizeForCocoaSize(NSRegularControlSize)];
 
-  NSControlSize controlSizeX = NSRegularControlSize, controlSizeY = NSRegularControlSize;
   HIRect drawRect = destRect;
 
-  if (rectWidth <= miniSize.width + snapTolerance && rectWidth < smallSize.width)
-    controlSizeX = NSMiniControlSize;
-  else if(rectWidth <= smallSize.width + snapTolerance && rectWidth < regularSize.width)
-    controlSizeX = NSSmallControlSize;
-
-  if (rectHeight <= miniSize.height + snapTolerance && rectHeight < smallSize.height)
-    controlSizeY = NSMiniControlSize;
-  else if(rectHeight <= smallSize.height + snapTolerance && rectHeight < regularSize.height)
-    controlSizeY = NSSmallControlSize;
+  CGFloat controlWidths[3] = { miniSize.width, smallSize.width, regularSize.width };
+  NSControlSize controlSizeX = FindControlSize(rectWidth, controlWidths, snapTolerance);
+  CGFloat controlHeights[3] = { miniSize.height, smallSize.height, regularSize.height };
+  NSControlSize controlSizeY = FindControlSize(rectHeight, controlHeights, snapTolerance);
 
   NSControlSize controlSize = NSRegularControlSize;
   int sizeIndex = 0;
 
   // At some sizes, don't scale but snap.
   const NSControlSize smallerControlSize =
     EnumSizeForCocoaSize(controlSizeX) < EnumSizeForCocoaSize(controlSizeY) ?
     controlSizeX : controlSizeY;