--- old/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m	2015-03-26 15:26:21.000000000 +0300
+++ new/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m	2015-03-26 15:26:21.000000000 +0300
@@ -48,14 +48,28 @@
  * If the necessary canvas is too large, the shared one will not be used and a
  * temporary one will be provided.
  */
+typedef enum {
+    BLACK_ON_WHITE_STAGE,
+    WHITE_ON_BLACK_STAGE
+} CGGI_GlyphRenderingStage;
+
 @interface CGGI_GlyphCanvas : NSObject {
 @public
     CGContextRef context;
     vImage_Buffer *image;
+    CGGI_GlyphRenderingStage stage;
 }
 @end;
 
 @implementation CGGI_GlyphCanvas
+- (id) init {
+    if (self = [super init]) {
+        context = NULL;
+        image = NULL;
+        stage = BLACK_ON_WHITE_STAGE;
+    }
+    return self;
+}
 @end
 
 
@@ -199,15 +213,9 @@
 static inline void
 CGGI_CopyARGBPixelToRGBPixel(const UInt32 p, UInt8 *dst)
 {
-#if __LITTLE_ENDIAN__
-    *(dst + 2) = 0xFF - (p >> 24 & 0xFF);
-    *(dst + 1) = 0xFF - (p >> 16 & 0xFF);
-    *(dst) = 0xFF - (p >> 8 & 0xFF);
-#else
-    *(dst) = 0xFF - (p >> 16 & 0xFF);
-    *(dst + 1) = 0xFF - (p >> 8 & 0xFF);
-    *(dst + 2) = 0xFF - (p & 0xFF);
-#endif
+    *(dst + 0) = 0xFF - (p >> 16 & 0xFF);  // red
+    *(dst + 1) = 0xFF - (p >>  8 & 0xFF);  // green
+    *(dst + 2) = 0xFF - (p & 0xFF);        // blue
 }
 
 static void
@@ -222,20 +230,41 @@
     size_t height = info->height;
 
     size_t y;
-    for (y = 0; y < height; y++) {
-        size_t destRow = y * destRowWidth * 3;
-        size_t srcRow = y * srcRowWidth;
-
-        size_t x;
-        for (x = 0; x < destRowWidth; x++) {
-            // size_t x3 = x * 3;
-            // UInt32 p = src[srcRow + x];
-            // dest[destRow + x3] = 0xFF - (p >> 16 & 0xFF);
-            // dest[destRow + x3 + 1] = 0xFF - (p >> 8 & 0xFF);
-            // dest[destRow + x3 + 2] = 0xFF - (p & 0xFF);
-            CGGI_CopyARGBPixelToRGBPixel(src[srcRow + x],
-                                         dest + destRow + x * 3);
-        }
+    switch (canvas->stage) {
+        case BLACK_ON_WHITE_STAGE:
+            // fill empty glyph image with black-on-white glyph
+            for (y = 0; y < height; y++) {
+                size_t destRow = y * destRowWidth * 3;
+                size_t srcRow = y * srcRowWidth;
+
+                size_t x;
+                for (x = 0; x < destRowWidth; x++) {
+                    CGGI_CopyARGBPixelToRGBPixel(src[srcRow + x],
+                            dest + destRow + x * 3);
+                }
+            }
+            break;
+        case WHITE_ON_BLACK_STAGE:
+            // merge black-on-white glyph (which is already in the glyph image)
+            // with white-on-black glyph
+            for (y = 0; y < height; y++) {
+                size_t destRow = y * destRowWidth * 3;
+                size_t srcRow = y * srcRowWidth;
+
+                size_t x;
+                for (x = 0; x < destRowWidth; x++) {
+                    UInt8* pDst = dest + destRow + x * 3;
+                    UInt32 srcPixel = src[srcRow + x];
+
+                    UInt16 r = *(pDst + 0) + (0xff & (srcPixel >> 16));
+                    *(pDst + 0) = (UInt8)(r >> 1);
+                    UInt16 g = *(pDst + 1) + (0xff & (srcPixel >>  8));
+                    *(pDst + 1) = (UInt8)(g >> 1);
+                    UInt16 b = *(pDst + 2) + (0xff & (srcPixel      ));
+                    *(pDst + 2) = (UInt8)(b >> 1);
+                }
+            }
+            break;
     }
 }
 
@@ -260,13 +289,14 @@
 //}
 
 static inline UInt8
-CGGI_ConvertPixelToGreyBit(UInt32 p)
+CGGI_ConvertWBPixelToByteGray(UInt32 p) {
+    return ((p >> 16 & 0xFF) + (p >> 8 & 0xFF) + (p & 0xFF)) / 3;
+}
+
+static inline UInt8
+CGGI_ConvertBWPixelToByteGray(UInt32 p)
 {
-#ifdef __LITTLE_ENDIAN__
-    return 0xFF - ((p >> 24 & 0xFF) + (p >> 16 & 0xFF) + (p >> 8 & 0xFF)) / 3;
-#else
-    return 0xFF - ((p >> 16 & 0xFF) + (p >> 8 & 0xFF) + (p & 0xFF)) / 3;
-#endif
+    return 0xFF - CGGI_ConvertWBPixelToByteGray(p);
 }
 
 static void
@@ -281,15 +311,34 @@
     size_t height = info->height;
 
     size_t y;
-    for (y = 0; y < height; y++) {
-        size_t destRow = y * destRowWidth;
-        size_t srcRow = y * srcRowWidth;
-
-        size_t x;
-        for (x = 0; x < destRowWidth; x++) {
-            UInt32 p = src[srcRow + x];
-            dest[destRow + x] = CGGI_ConvertPixelToGreyBit(p);
-        }
+    switch (canvas->stage) {
+        case BLACK_ON_WHITE_STAGE:
+            // fill empty glyph image with black-on-white glyph
+            for (y = 0; y < height; y++) {
+                size_t destRow = y * destRowWidth;
+                size_t srcRow = y * srcRowWidth;
+                size_t x;
+                for (x = 0; x < destRowWidth; x++) {
+                    UInt32 p = src[srcRow + x];
+                    dest[destRow + x] = CGGI_ConvertBWPixelToByteGray(p);
+                }
+            }
+            break;
+        case WHITE_ON_BLACK_STAGE:
+            // merge black-on-white glyph (which is already in the glyph image)
+            // with white-on-black glyph
+            for (y = 0; y < height; y++) {
+                size_t destRow = y * destRowWidth;
+                size_t srcRow = y * srcRowWidth;
+
+                size_t x;
+                for (x = 0; x < destRowWidth; x++) {
+                    UInt32 p = src[srcRow + x];
+                    UInt16 gray = dest[destRow + x] + CGGI_ConvertWBPixelToByteGray(p);
+                    dest[destRow + x] = (UInt8)(gray >> 1);
+                }
+            }
+            break;
     }
 }
 
@@ -316,13 +365,11 @@
 {
     CGGI_RenderingMode mode;
     mode.cgFontMode = strike->fStyle;
+    NSException *e = nil;
 
     switch (strike->fAAStyle) {
-    case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_DEFAULT:
     case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_OFF:
     case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_ON:
-    case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_GASP:
-    default:
         mode.glyphDescriptor = &grey;
         break;
     case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
@@ -331,6 +378,14 @@
     case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_LCD_VBGR:
         mode.glyphDescriptor = &rgb;
         break;
+    case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_GASP:
+    case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_DEFAULT:
+    default:
+        e = [NSException
+                exceptionWithName:@"IllegalArgumentException"
+                reason:@"Invalid hint value"
+                userInfo:nil];
+        @throw e;
     }
 
     return mode;
@@ -345,7 +400,8 @@
  */
 static inline void
 CGGI_InitCanvas(CGGI_GlyphCanvas *canvas,
-                const vImagePixelCount width, const vImagePixelCount height)
+                const vImagePixelCount width, const vImagePixelCount height,
+                const CGGI_RenderingMode* mode)
 {
     // our canvas is *always* 4-byte ARGB
     size_t bytesPerRow = width * sizeof(UInt32);
@@ -356,19 +412,28 @@
     canvas->image->height = height;
     canvas->image->rowBytes = bytesPerRow;
 
-    canvas->image->data = (void *)calloc(byteCount, sizeof(UInt32));
+    canvas->image->data = (void *)calloc(byteCount, sizeof(UInt8));
     if (canvas->image->data == NULL) {
         [[NSException exceptionWithName:NSMallocException
             reason:@"Failed to allocate memory for the buffer which backs the CGContext for glyph strikes." userInfo:nil] raise];
     }
 
+    canvas->stage = BLACK_ON_WHITE_STAGE;
+
+    uint32_t bmpInfo = kCGImageAlphaPremultipliedFirst;
+    if (mode->glyphDescriptor == &rgb) {
+        bmpInfo |= kCGBitmapByteOrder32Host;
+    }
+
     CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
     canvas->context = CGBitmapContextCreate(canvas->image->data,
                                             width, height, 8, bytesPerRow,
                                             colorSpace,
-                                            kCGImageAlphaPremultipliedFirst);
+                                            bmpInfo);
 
+    // set foreground color
     CGContextSetRGBFillColor(canvas->context, 0.0f, 0.0f, 0.0f, 1.0f);
+    
     CGContextSetFontSize(canvas->context, 1);
     CGContextSaveGState(canvas->context);
 
@@ -404,7 +469,9 @@
  * Quick and easy inline to check if this canvas is big enough.
  */
 static inline void
-CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width, const vImagePixelCount height, const JRSFontRenderingStyle style)
+CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width,
+        const vImagePixelCount height,
+        const CGGI_RenderingMode* mode)
 {
     if (canvas->image != NULL &&
         width  < canvas->image->width &&
@@ -418,8 +485,9 @@
     CGGI_FreeCanvas(canvas);
     CGGI_InitCanvas(canvas,
                     width * CGGI_GLYPH_CANVAS_SLACK,
-                    height * CGGI_GLYPH_CANVAS_SLACK);
-    JRSFontSetRenderingStyleOnContext(canvas->context, style);
+                    height * CGGI_GLYPH_CANVAS_SLACK,
+                    mode);
+    JRSFontSetRenderingStyleOnContext(canvas->context, mode->cgFontMode);
 }
 
 /*
@@ -439,11 +507,24 @@
     // clean the canvas
 #ifdef CGGI_DEBUG
     Pixel_8888 opaqueWhite = { 0xE0, 0xE0, 0xE0, 0xE0 };
+    Pixel_8888 opaqueBlack = { 0x10, 0x10, 0x10, 0xF0 };
 #else
     Pixel_8888 opaqueWhite = { 0xFF, 0xFF, 0xFF, 0xFF };
+    Pixel_8888 opaqueBlack = { 0x00, 0x00, 0x00, 0xFF };
 #endif
 
-    vImageBufferFill_ARGB8888(&canvasRectToClear, opaqueWhite, kvImageNoFlags);
+    // clear canvas background and set foreground color
+    switch(canvas->stage) {
+        case BLACK_ON_WHITE_STAGE:
+            vImageBufferFill_ARGB8888(&canvasRectToClear, opaqueWhite, kvImageNoFlags);
+            CGContextSetRGBFillColor(canvas->context, 0.0f, 0.0f, 0.0f, 1.0f);
+            break;
+        case WHITE_ON_BLACK_STAGE:
+            vImageBufferFill_ARGB8888(&canvasRectToClear, opaqueBlack, kvImageNoFlags);
+            CGContextSetRGBFillColor(canvas->context, 1.0f, 1.0f, 1.0f, 1.0f);
+            break;
+    }
+    CGContextSaveGState(canvas->context);
 }
 
 
@@ -577,7 +658,7 @@
     GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode);
 
     // fix the context size, just in case the substituted character is unexpectedly large
-    CGGI_SizeCanvas(canvas, info->width, info->height, mode->cgFontMode);
+    CGGI_SizeCanvas(canvas, info->width, info->height, mode);
 
     // align the transform for the real CoreText strike
     CGContextSetTextMatrix(canvas->context, strike->fAltTx);
@@ -653,8 +734,11 @@
 #endif
 }
 
-static NSString *threadLocalCanvasKey =
-    @"Java CoreGraphics Text Renderer Cached Canvas";
+static NSString *threadLocalAACanvasKey =
+    @"Java CoreGraphics Text Renderer Cached Canvas for AA";
+
+static NSString *threadLocalLCDCanvasKey =
+    @"Java CoreGraphics Text Renderer Cached Canvas for LCD";
 
 /*
  * This is the maximum length and height times the above slack squared
@@ -678,7 +762,14 @@
         CGGI_GLYPH_CANVAS_MAX*CGGI_GLYPH_CANVAS_MAX*CGGI_GLYPH_CANVAS_SLACK*CGGI_GLYPH_CANVAS_SLACK)
     {
         CGGI_GlyphCanvas *tmpCanvas = [[CGGI_GlyphCanvas alloc] init];
-        CGGI_InitCanvas(tmpCanvas, maxWidth, maxHeight);
+        CGGI_InitCanvas(tmpCanvas, maxWidth, maxHeight, mode);
+        // create black-on-white glyph image
+        CGGI_FillImagesForGlyphsWithSizedCanvas(tmpCanvas, strike,
+                mode, glyphInfos, uniChars,
+                glyphs, len);
+
+        // merge glyph image with white-on-black glyph
+        tmpCanvas->stage = WHITE_ON_BLACK_STAGE;
         CGGI_FillImagesForGlyphsWithSizedCanvas(tmpCanvas, strike,
                                                 mode, glyphInfos, uniChars,
                                                 glyphs, len);
@@ -687,18 +778,29 @@
         [tmpCanvas release];
         return;
     }
-
     NSMutableDictionary *threadDict =
         [[NSThread currentThread] threadDictionary];
-    CGGI_GlyphCanvas *canvas = [threadDict objectForKey:threadLocalCanvasKey];
+
+    NSString* theKey = (mode->glyphDescriptor == &rgb) ?
+        threadLocalLCDCanvasKey : threadLocalAACanvasKey;
+    
+    CGGI_GlyphCanvas *canvas = [threadDict objectForKey:theKey];
     if (canvas == nil) {
         canvas = [[CGGI_GlyphCanvas alloc] init];
-        [threadDict setObject:canvas forKey:threadLocalCanvasKey];
+        [threadDict setObject:canvas forKey:theKey];
     }
 
-    CGGI_SizeCanvas(canvas, maxWidth, maxHeight, mode->cgFontMode);
+    CGGI_SizeCanvas(canvas, maxWidth, maxHeight, mode);
+    // create black-on-white glyph image
+    canvas->stage = BLACK_ON_WHITE_STAGE;
     CGGI_FillImagesForGlyphsWithSizedCanvas(canvas, strike, mode,
                                             glyphInfos, uniChars, glyphs, len);
+
+    // merge glyph image with white-on-black glyph
+    canvas->stage = WHITE_ON_BLACK_STAGE;
+    CGGI_FillImagesForGlyphsWithSizedCanvas(canvas, strike, mode,
+                                            glyphInfos, uniChars, glyphs, len);
+
 }
 
 /*