Bug 492217 - Make more parts of native theme rendering rtl-aware, for example tree twisties and tree header cells with sort arrows. r=josh
authorMarkus Stange <mstange@themasta.com>
Fri, 13 Nov 2009 23:56:30 +0100
changeset 34852 fe9f7efe466444cd716a98a9a4b491ee906765cf
parent 34851 2ad4391e7d0724d7d543b88c4c11c3c017cdf35a
child 34853 9ce4279f72f0f94206f62c791e563a9a4217b0b2
push idunknown
push userunknown
push dateunknown
reviewersjosh
bugs492217
milestone1.9.3a1pre
Bug 492217 - Make more parts of native theme rendering rtl-aware, for example tree twisties and tree header cells with sort arrows. r=josh
widget/src/cocoa/nsNativeThemeCocoa.mm
--- a/widget/src/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/src/cocoa/nsNativeThemeCocoa.mm
@@ -748,16 +748,93 @@ nsNativeThemeCocoa::DrawPushButton(CGCon
 #if DRAW_IN_FRAME_DEBUG
   CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
   CGContextFillRect(cgContext, inBoxRect);
 #endif
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
+typedef void (*RenderHIThemeControlFunction)(CGContextRef cgContext, const HIRect& aRenderRect, void* aData);
+
+static void
+RenderTransformedHIThemeControl(CGContextRef aCGContext, const HIRect& aRect,
+                                RenderHIThemeControlFunction aFunc, void* aData,
+                                BOOL mirrorHorizontally = NO)
+{
+  CGAffineTransform savedCTM = CGContextGetCTM(aCGContext);
+  CGContextTranslateCTM(aCGContext, aRect.origin.x, aRect.origin.y);
+
+  PRBool drawDirect;
+  HIRect drawRect = aRect;
+  drawRect.origin = CGPointZero;
+
+  if (!mirrorHorizontally && savedCTM.a == 1.0f && savedCTM.b == 0.0f &&
+      savedCTM.c == 0.0f && (savedCTM.d == 1.0f || savedCTM.d == -1.0f)) {
+    drawDirect = TRUE;
+  } else {
+    drawDirect = FALSE;
+  }
+
+  // Fall back to no bitmap buffer if the area of our control (in pixels^2)
+  // is too large.
+  if (drawDirect || (aRect.size.width * aRect.size.height > BITMAP_MAX_AREA)) {
+    aFunc(aCGContext, drawRect, aData);
+  } else {
+    // Inflate the buffer to capture focus rings.
+    int w = ceil(drawRect.size.width) + 2 * MAX_FOCUS_RING_WIDTH;
+    int h = ceil(drawRect.size.height) + 2 * MAX_FOCUS_RING_WIDTH;
+
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+    CGContextRef bitmapctx = CGBitmapContextCreate(NULL, w, h, 8, w * 4,
+                                                   colorSpace,
+                                                   kCGImageAlphaPremultipliedFirst);
+    CGColorSpaceRelease(colorSpace);
+
+    CGContextTranslateCTM(bitmapctx, MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH);
+
+    // HITheme always wants to draw into a flipped context, or things
+    // get confused.
+    CGContextTranslateCTM(bitmapctx, 0.0f, aRect.size.height);
+    CGContextScaleCTM(bitmapctx, 1.0f, -1.0f);
+
+    aFunc(bitmapctx, drawRect, aData);
+
+    CGImageRef bitmap = CGBitmapContextCreateImage(bitmapctx);
+
+    CGAffineTransform ctm = CGContextGetCTM(aCGContext);
+
+    // We need to unflip, so that we can do a DrawImage without getting a flipped image.
+    CGContextTranslateCTM(aCGContext, 0.0f, aRect.size.height);
+    CGContextScaleCTM(aCGContext, 1.0f, -1.0f);
+
+    if (mirrorHorizontally) {
+      CGContextTranslateCTM(aCGContext, aRect.size.width, 0);
+      CGContextScaleCTM(aCGContext, -1.0f, 1.0f);
+    }
+
+    HIRect inflatedDrawRect = CGRectMake(-MAX_FOCUS_RING_WIDTH, -MAX_FOCUS_RING_WIDTH, w, h);
+    CGContextDrawImage(aCGContext, inflatedDrawRect, bitmap);
+
+    CGContextSetCTM(aCGContext, ctm);
+
+    CGImageRelease(bitmap);
+    CGContextRelease(bitmapctx);
+  }
+
+  CGContextSetCTM(aCGContext, savedCTM);
+}
+
+static void
+RenderButton(CGContextRef cgContext, const HIRect& aRenderRect, void* aData)
+{
+  HIThemeButtonDrawInfo* bdi = (HIThemeButtonDrawInfo*)aData;
+  HIThemeDrawButton(&aRenderRect, bdi, cgContext, kHIThemeOrientationNormal, NULL);
+}
+
 void
 nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
                                const HIRect& inBoxRect, PRBool inIsDefault, PRBool inDisabled,
                                ThemeButtonValue inValue, ThemeButtonAdornment inAdornment,
                                PRInt32 inState, nsIFrame* aFrame)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
@@ -816,17 +893,18 @@ nsNativeThemeCocoa::DrawButton(CGContext
     drawFrame.size.width += 1;
     PRBool isLast = IsLastTreeHeaderCell(aFrame);
     if (isLast)
       drawFrame.size.width += 1; // Also remove the other border.
     if (!IsFrameRTL(aFrame) || isLast)
       drawFrame.origin.x -= 1;
   }
 
-  HIThemeDrawButton(&drawFrame, &bdi, cgContext, kHIThemeOrientationNormal, NULL);
+  RenderTransformedHIThemeControl(cgContext, drawFrame, RenderButton, &bdi,
+                                  IsFrameRTL(aFrame));
 
 #if DRAW_IN_FRAME_DEBUG
   CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
   CGContextFillRect(cgContext, inBoxRect);
 #endif
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
@@ -1259,87 +1337,18 @@ nsNativeThemeCocoa::GetScrollbarDrawInfo
                                             ConvertToPressState(buttonStates[2], kThemeTopOutsideArrowPressed) |
                                             ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed);
     }
   }
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
-typedef void (*RenderHIThemeControlFunction)(CGContextRef cgContext, void* aData);
-
 static void
-RenderTransformedHIThemeControl(CGContextRef aCGContext, const HIRect& aRect,
-                                RenderHIThemeControlFunction aFunc, void* aData,
-                                BOOL mirrorHorizontally = NO)
-{
-  CGAffineTransform savedCTM = CGContextGetCTM(aCGContext);
-  CGContextTranslateCTM(aCGContext, aRect.origin.x, aRect.origin.y);
-
-  PRBool drawDirect;
-  HIRect drawRect = aRect;
-  drawRect.origin = CGPointZero;
-
-  if (!mirrorHorizontally && savedCTM.a == 1.0f && savedCTM.b == 0.0f &&
-      savedCTM.c == 0.0f && (savedCTM.d == 1.0f || savedCTM.d == -1.0f)) {
-    drawDirect = TRUE;
-  } else {
-    drawDirect = FALSE;
-  }
-
-  // Fall back to no bitmap buffer if the area of our control (in pixels^2)
-  // is too large.
-  if (drawDirect || (aRect.size.width * aRect.size.height > BITMAP_MAX_AREA)) {
-    aFunc(aCGContext, aData);
-  } else {
-    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-    CGContextRef bitmapctx = CGBitmapContextCreate(NULL,
-                                                   (size_t) ceil(drawRect.size.width),
-                                                   (size_t) ceil(drawRect.size.height),
-                                                   8,
-                                                   (size_t) ceil(drawRect.size.width) * 4,
-                                                   colorSpace,
-                                                   kCGImageAlphaPremultipliedFirst);
-    CGColorSpaceRelease(colorSpace);
-
-    // HITheme always wants to draw into a flipped context, or things
-    // get confused.
-    CGContextTranslateCTM(bitmapctx, 0.0f, aRect.size.height);
-    CGContextScaleCTM(bitmapctx, 1.0f, -1.0f);
-    CGContextSetRGBFillColor(bitmapctx, 1.0f, 0, 0, 1.0f);
-    CGContextFillRect(bitmapctx, drawRect);
-
-    aFunc(bitmapctx, aData);
-
-    CGImageRef bitmap = CGBitmapContextCreateImage(bitmapctx);
-
-    CGAffineTransform ctm = CGContextGetCTM(aCGContext);
-
-    // We need to unflip, so that we can do a DrawImage without getting a flipped image.
-    CGContextTranslateCTM(aCGContext, 0.0f, aRect.size.height);
-    CGContextScaleCTM(aCGContext, 1.0f, -1.0f);
-
-    if (mirrorHorizontally) {
-      CGContextTranslateCTM(aCGContext, aRect.size.width, 0);
-      CGContextScaleCTM(aCGContext, -1.0f, 1.0f);
-    }
-
-    CGContextDrawImage(aCGContext, drawRect, bitmap);
-
-    CGContextSetCTM(aCGContext, ctm);
-
-    CGImageRelease(bitmap);
-    CGContextRelease(bitmapctx);
-  }
-
-  CGContextSetCTM(aCGContext, savedCTM);
-}
-
-static void
-RenderScrollbar(CGContextRef cgContext, void* aData)
+RenderScrollbar(CGContextRef cgContext, const HIRect& aRenderRect, void* aData)
 {
   HIThemeTrackDrawInfo* tdi = (HIThemeTrackDrawInfo*)aData;
   HIThemeDrawTrack(tdi, NULL, cgContext, HITHEME_ORIENTATION);
 }
 
 void
 nsNativeThemeCocoa::DrawScrollbar(CGContextRef aCGContext, const HIRect& aBoxRect, nsIFrame *aFrame)
 {
@@ -1484,17 +1493,17 @@ nsNativeThemeCocoa::DrawStatusBar(CGCont
                                          inBoxRect.size.width, inBoxRect.size.height - 2.0f),
                    NativeGreyColorAsFloat(statusbarGradientStartGrey, isMain),
                    NativeGreyColorAsFloat(statusbarGradientEndGrey, isMain));
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 static void
-RenderResizer(CGContextRef cgContext, void* aData)
+RenderResizer(CGContextRef cgContext, const HIRect& aRenderRect, void* aData)
 {
   HIThemeGrowBoxDrawInfo* drawInfo = (HIThemeGrowBoxDrawInfo*)aData;
   HIThemeDrawGrowBox(&CGPointZero, drawInfo, cgContext, kHIThemeOrientationNormal);
 }
 
 void
 nsNativeThemeCocoa::DrawResizer(CGContextRef cgContext, const HIRect& aRect,
                                 nsIFrame *aFrame)