src/java.desktop/windows/native/common/awt_makecube.cpp
changeset 51679 f7563db3ae1b
parent 51678 2fdfe34f7262
child 51680 d058b410af0a
equal deleted inserted replaced
51678:2fdfe34f7262 51679:f7563db3ae1b
     1 /*
       
     2  * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #include "awt.h"
       
    27 #include "awt_image.h"
       
    28 
       
    29 extern "C" {
       
    30 #include "img_colors.h"
       
    31 } // extern "C"
       
    32 
       
    33 char *programname = "awt_makecube";
       
    34 
       
    35 unsigned char cube[LOOKUPSIZE * LOOKUPSIZE * LOOKUPSIZE];
       
    36 
       
    37 unsigned char reds[256], greens[256], blues[256], indices[256];
       
    38 int num_colors;
       
    39 
       
    40 PALETTEENTRY sysPal[256];
       
    41 
       
    42 int sys2cmap[256];
       
    43 int cmap2sys[256];
       
    44 int error[256];
       
    45 
       
    46 int cmapsize = 0;
       
    47 int virtcubesize = 0;
       
    48 int makecube_verbose = 0;
       
    49 
       
    50 void printPalette(char *label, HPALETTE hPal);
       
    51 
       
    52 void usage(char *errmsg)
       
    53 {
       
    54     fprintf(stderr, "%s\n", errmsg);
       
    55     fprintf(stderr, "usage: %s [-cmapsize N] [-cubesize N]\n", programname);
       
    56     fprintf(stderr, "\t-cmapsize N   set the number of colors to allocate\n");
       
    57     fprintf(stderr, "\t              in the colormap (2 <= N <= 256)\n");
       
    58     fprintf(stderr, "\t-cubesize N   set the size of the cube of colors to\n");
       
    59     fprintf(stderr, "                scan as potential entries in the cmap\n");
       
    60     fprintf(stderr, "                (N must be a power of 2 and <= 32)\n");
       
    61     exit(1);
       
    62 }
       
    63 
       
    64 void setsyscolor(int index, int red, int green, int blue)
       
    65 {
       
    66     if (index >= 0) {
       
    67         if (sysPal[index].peFlags != 0) {
       
    68             usage("Internal error: system palette conflict");
       
    69         }
       
    70     } else {
       
    71         for (int i = 0; i < 256; i++) {
       
    72             if (sysPal[i].peFlags != 0) {
       
    73                 if (sysPal[i].peRed   == red &&
       
    74                     sysPal[i].peGreen == green &&
       
    75                     sysPal[i].peBlue  == blue)
       
    76                 {
       
    77                     // Already there.  Ignore it.
       
    78                     return;
       
    79                 }
       
    80             } else if (index < 0) {
       
    81                 index = i;
       
    82             }
       
    83         }
       
    84         if (index < 0) {
       
    85             usage("Internal error: ran out of system palette entries");
       
    86         }
       
    87     }
       
    88     sysPal[index].peRed   = red;
       
    89     sysPal[index].peGreen = green;
       
    90     sysPal[index].peBlue  = blue;
       
    91     sysPal[index].peFlags = 1;
       
    92 }
       
    93 
       
    94 void addcmapcolor(int red, int green, int blue)
       
    95 {
       
    96     for (int i = 0; i < num_colors; i++) {
       
    97         if (red == reds[i] && green == greens[i] && blue == blues[i]) {
       
    98             return;
       
    99         }
       
   100     }
       
   101     if (num_colors >= cmapsize) {
       
   102         usage("Internal error: more than cmapsize static colors defined");
       
   103     }
       
   104     reds[num_colors]   = red;
       
   105     greens[num_colors] = green;
       
   106     blues[num_colors]  = blue;
       
   107     num_colors++;
       
   108 }
       
   109 
       
   110 int main(int argc, char **argv)
       
   111 {
       
   112     int i;
       
   113 
       
   114     programname = argv[0];
       
   115 
       
   116     for (i = 1; i < argc; i++) {
       
   117         if (strcmp(argv[i], "-cmapsize") == 0) {
       
   118             if (i++ >= argc) {
       
   119                 usage("no argument to -cmapsize");
       
   120             }
       
   121             cmapsize = atoi(argv[i]);
       
   122             if (cmapsize <= 2 || cmapsize > 256) {
       
   123                 usage("colormap size must be between 2 and 256");
       
   124             }
       
   125         } else if (strcmp(argv[1], "-cubesize") == 0) {
       
   126             if (i++ >= argc) {
       
   127                 usage("no argument to -cubesize");
       
   128             }
       
   129             virtcubesize = atoi(argv[i]);
       
   130             if (virtcubesize == 0 ||
       
   131                 (virtcubesize & (virtcubesize - 1)) != 0 ||
       
   132                 virtcubesize > 32)
       
   133             {
       
   134                 usage("cube size must by a power of 2 <= 32");
       
   135             }
       
   136         } else if (strcmp(argv[i], "-verbose") == 0) {
       
   137             makecube_verbose = 1;
       
   138         } else {
       
   139             usage("unknown argument");
       
   140         }
       
   141     }
       
   142 
       
   143     if (cmapsize == 0) {
       
   144         cmapsize = CMAPSIZE;
       
   145     }
       
   146     if (virtcubesize == 0) {
       
   147         virtcubesize = VIRTCUBESIZE;
       
   148     }
       
   149 
       
   150     if (0) {  // For testing
       
   151         HDC hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
       
   152         HPALETTE hPal = CreateHalftonePalette(hDC);
       
   153         printPalette("Halftone palette for current display", hPal);
       
   154         printPalette("Stock DEFAULT_PALETTE", (HPALETTE)GetStockObject(DEFAULT_PALETTE));
       
   155         BITMAPINFOHEADER bmInfo = {
       
   156             sizeof(BITMAPINFOHEADER), 1, 1, 1, 8, BI_RGB, 0, 1000, 1000, 0, 0
       
   157             };
       
   158         HBITMAP hBitmap = CreateDIBitmap(hDC, &bmInfo,
       
   159                                          0, NULL, NULL, DIB_RGB_COLORS);
       
   160         HDC hMemDC = CreateCompatibleDC(hDC);
       
   161         SelectObject(hDC, hBitmap);
       
   162         hPal = CreateHalftonePalette(hMemDC);
       
   163         printPalette("Halftone palette for 8-bit DIBitmap", hPal);
       
   164         exit(0);
       
   165     }
       
   166 
       
   167     // Allocate Windows static system colors.
       
   168     {
       
   169         PALETTEENTRY palEntries[256];
       
   170         HPALETTE hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
       
   171         int n = GetPaletteEntries(hPal, 0, 256, palEntries);
       
   172         for (i = 0; i < n; i++) {
       
   173             addcmapcolor(palEntries[i].peRed,
       
   174                          palEntries[i].peGreen,
       
   175                          palEntries[i].peBlue);
       
   176             setsyscolor((i < n / 2) ? i : i + (256 - n),
       
   177                         palEntries[i].peRed,
       
   178                         palEntries[i].peGreen,
       
   179                         palEntries[i].peBlue);
       
   180         }
       
   181     }
       
   182 
       
   183     // Allocate java.awt.Color constant colors.
       
   184     addcmapcolor(  0,   0,   0);        // black
       
   185     addcmapcolor(255, 255, 255);        // white
       
   186     addcmapcolor(255,   0,   0);        // red
       
   187     addcmapcolor(  0, 255,   0);        // green
       
   188     addcmapcolor(  0,   0, 255);        // blue
       
   189     addcmapcolor(255, 255,   0);        // yellow
       
   190     addcmapcolor(255,   0, 255);        // magenta
       
   191     addcmapcolor(  0, 255, 255);        // cyan
       
   192     addcmapcolor(192, 192, 192);        // lightGray
       
   193     addcmapcolor(128, 128, 128);        // gray
       
   194     addcmapcolor( 64,  64,  64);        // darkGray
       
   195     addcmapcolor(255, 175, 175);        // pink
       
   196     addcmapcolor(255, 200,   0);        // orange
       
   197 
       
   198     img_makePalette(cmapsize, virtcubesize, LOOKUPSIZE,
       
   199                     50.0f, 250.0f,
       
   200                     num_colors, TRUE, reds, greens, blues, cube);
       
   201 
       
   202     if (makecube_verbose) {
       
   203         fprintf(stderr, "Calculated colormap:\n");
       
   204         for (i = 0; i < cmapsize; i++) {
       
   205             fprintf(stderr, "%3d:(%3d,%3d,%3d)   ",
       
   206                     i, reds[i], greens[i], blues[i]);
       
   207         }
       
   208         fprintf(stderr, "\n");
       
   209     }
       
   210 
       
   211     // Now simulate adding the halftone palette to the system
       
   212     // palette to get an idea of palette ordering.
       
   213     {
       
   214         int cubevals[6] = {0, 44, 86, 135, 192, 255};
       
   215         for (int b = 0; b < 6; b++) {
       
   216             for (int g = 0; g < 6; g++) {
       
   217                 for (int r = 0; r < 6; r++) {
       
   218                     setsyscolor(-1, cubevals[r], cubevals[g], cubevals[b]);
       
   219                 }
       
   220             }
       
   221         }
       
   222         int grayvals[26] = {  0,  17,  24,  30,  37,  44,  52,  60,
       
   223                              68,  77,  86,  95, 105, 114, 125, 135,
       
   224                             146, 157, 168, 180, 192, 204, 216, 229,
       
   225                             242, 255 };
       
   226         for (i = 0; i < 26; i++) {
       
   227             setsyscolor(-1, grayvals[i], grayvals[i], grayvals[i]);
       
   228         }
       
   229     }
       
   230 
       
   231     if (makecube_verbose) {
       
   232         fprintf(stderr, "System palette with simulated halftone palette:\n");
       
   233         for (i = 0; i < 256; i++) {
       
   234             fprintf(stderr, "%3d:(%3d,%3d,%3d)   ",
       
   235                     i, sysPal[i].peRed, sysPal[i].peGreen, sysPal[i].peBlue);
       
   236         }
       
   237     }
       
   238 
       
   239     if (makecube_verbose) {
       
   240         HDC hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
       
   241         HPALETTE hPal = CreateHalftonePalette(hDC);
       
   242         SelectPalette(hDC, hPal, FALSE);
       
   243         RealizePalette(hDC);
       
   244         PALETTEENTRY palEntries[256];
       
   245         int n = GetSystemPaletteEntries(hDC, 0, 256, palEntries);
       
   246         fprintf(stderr,
       
   247                 "realized halftone palette reads back %d entries\n", n);
       
   248         int broken = 0;
       
   249         for (i = 0; i < 256; i++) {
       
   250             char *msg1 = "";
       
   251             char *msg2 = "";
       
   252             if (palEntries[i].peRed != sysPal[i].peRed ||
       
   253                 palEntries[i].peGreen != sysPal[i].peGreen ||
       
   254                 palEntries[i].peBlue != sysPal[i].peBlue)
       
   255             {
       
   256                 msg1 = "no sysPal match!";
       
   257                 if (sysPal[i].peFlags == 0) {
       
   258                     msg2 = "(OK)";
       
   259                 } else {
       
   260                     broken++;
       
   261                 }
       
   262             } else if (sysPal[i].peFlags == 0) {
       
   263                 msg1 = "no sysPal entry...";
       
   264             }
       
   265             fprintf(stderr,
       
   266                     "palEntries[%3d] = (%3d, %3d, %3d), flags = %d  %s %s\n",
       
   267                     i,
       
   268                     palEntries[i].peRed,
       
   269                     palEntries[i].peGreen,
       
   270                     palEntries[i].peBlue,
       
   271                     palEntries[i].peFlags, msg1, msg2);
       
   272         }
       
   273         fprintf(stderr, "%d broken entries\n", broken);
       
   274     }
       
   275 
       
   276 #if 0
       
   277 #define BIGERROR (255 * 255 * 255)
       
   278 
       
   279     for (i = 0; i < 256; i++) {
       
   280         sys2cmap[i] = -1;
       
   281         cmap2sys[i] = -1;
       
   282         error[i] = BIGERROR;
       
   283         // error[i] = -1 means cmap[i] is locked to cmap2sys[i]
       
   284         // error[i] >= 0 means cmap[i] may lock to cmap2sys[i] on this run
       
   285     }
       
   286 
       
   287     int nummapped;
       
   288     int totalmapped = 0;
       
   289     do {
       
   290         int maxerror = BIGERROR;
       
   291         for (i = 0; i < 256; i++) {
       
   292             if (sysPal[i].peFlags == 0 || sys2cmap[i] >= 0) {
       
   293                 continue;
       
   294             }
       
   295             int red   = sysPal[i].peRed;
       
   296             int green = sysPal[i].peGreen;
       
   297             int blue  = sysPal[i].peBlue;
       
   298             int e = maxerror;
       
   299             int ix = -1;
       
   300             for (int j = 0; j < 256; j++) {
       
   301                 if (error[j] < 0) {
       
   302                     continue;
       
   303                 }
       
   304                 int t = red - reds[j];
       
   305                 int d = t * t;
       
   306                 t = green - greens[j];
       
   307                 d += t * t;
       
   308                 t = blue - blues[j];
       
   309                 d += t * t;
       
   310                 if (d < e) {
       
   311                     e = d;
       
   312                     ix = j;
       
   313                 }
       
   314             }
       
   315             if (ix >= 0) {
       
   316                 if (e < error[ix]) {
       
   317                     if (cmap2sys[ix] >= 0) {
       
   318                         // To be fair we will not accept any matches
       
   319                         // looser than this former match that we just
       
   320                         // displaced with a better match.
       
   321                         if (maxerror > error[ix]) {
       
   322                             maxerror = error[ix];
       
   323                         }
       
   324                         sys2cmap[cmap2sys[ix]] = -1;
       
   325                     }
       
   326                     error[ix] = e;
       
   327                     sys2cmap[i] = ix;
       
   328                     cmap2sys[ix] = i;
       
   329                 }
       
   330             }
       
   331         }
       
   332         nummapped = 0;
       
   333         for (i = 0; i < 256; i++) {
       
   334             if (error[i] >= 0) {
       
   335                 if (error[i] >= maxerror) {
       
   336                     // Throw this one back to be fair to a displaced entry.
       
   337                     error[i] = BIGERROR;
       
   338                     sys2cmap[cmap2sys[i]] = -1;
       
   339                     cmap2sys[i] = -1;
       
   340                     continue;
       
   341                 }
       
   342                 error[i] = -1;
       
   343                 nummapped++;
       
   344             }
       
   345         }
       
   346         totalmapped += nummapped;
       
   347         if (makecube_verbose) {
       
   348             fprintf(stderr, "%3d colors mapped (%3d total), maxerror = %d\n",
       
   349                     nummapped, totalmapped, maxerror);
       
   350         }
       
   351     } while (nummapped != 0);
       
   352 
       
   353     for (i = 0; i < 256; i++) {
       
   354         if (cmap2sys[i] < 0) {
       
   355             for (int j = 0; j < 256; j++) {
       
   356                 if (sys2cmap[j] < 0) {
       
   357                     cmap2sys[i] = j;
       
   358                     sys2cmap[j] = i;
       
   359                     break;
       
   360                 }
       
   361             }
       
   362             if (j == 256) {
       
   363                 usage("Internal error: no unused system entry for cmap entry!\n");
       
   364             }
       
   365         }
       
   366     }
       
   367 #else
       
   368     for (i = 0; i < 256; i++) {
       
   369         if (i < 10) {
       
   370             sys2cmap[i] = i;
       
   371             cmap2sys[i] = i;
       
   372         } else if (i < 20) {
       
   373             sys2cmap[256 - 20 + i] = i;
       
   374             cmap2sys[i] = 256 - 20 + i;
       
   375         } else {
       
   376             sys2cmap[i - 10] = i;
       
   377             cmap2sys[i] = i - 10;
       
   378         }
       
   379     }
       
   380 #endif
       
   381 
       
   382     if (makecube_verbose) {
       
   383         fprintf(stderr, "cmap2sys mapping: \n");
       
   384         for (i = 0; i < 256; i++) {
       
   385             fprintf(stderr, "%4d", cmap2sys[i]);
       
   386             if (sys2cmap[cmap2sys[i]] != i) {
       
   387                 usage("Internal error: bad system palette back pointer!\n");
       
   388             }
       
   389         }
       
   390         fprintf(stderr, "\n");
       
   391     }
       
   392 
       
   393     printf("unsigned char awt_reds[256] = {");
       
   394     for (i = 0; i < 256; i++) {
       
   395         if ((i & 0xf) == 0) printf("\n\t");
       
   396         printf("%3d,", reds[sys2cmap[i]]);
       
   397     }
       
   398     printf("\n};\n");
       
   399     printf("unsigned char awt_greens[256] = {");
       
   400     for (i = 0; i < 256; i++) {
       
   401         if ((i & 0xf) == 0) printf("\n\t");
       
   402         printf("%3d,", greens[sys2cmap[i]]);
       
   403     }
       
   404     printf("\n};\n");
       
   405     printf("unsigned char awt_blues[256] = {");
       
   406     for (i = 0; i < 256; i++) {
       
   407         if ((i & 0xf) == 0) printf("\n\t");
       
   408         printf("%3d,", blues[sys2cmap[i]]);
       
   409     }
       
   410     printf("\n};\n");
       
   411     fflush(stdout);
       
   412     return 0;
       
   413 }
       
   414 
       
   415 void printPalette(char *label, HPALETTE hPal)
       
   416 {
       
   417     PALETTEENTRY palEntries[256];
       
   418     fprintf(stderr, "%s (0x%08x):\n", label, hPal);
       
   419     int n = GetPaletteEntries(hPal, 0, 256, palEntries);
       
   420     for (int i = 0; i < n; i++) {
       
   421         fprintf(stderr, "palEntries[%3d] = (%3d, %3d, %3d), flags = %d\n",
       
   422                 i,
       
   423                 palEntries[i].peRed,
       
   424                 palEntries[i].peGreen,
       
   425                 palEntries[i].peBlue,
       
   426                 palEntries[i].peFlags);
       
   427     }
       
   428 }
       
   429 
       
   430 /* This helps eliminate any dependence on javai.dll at build time. */
       
   431 int
       
   432 jio_fprintf (FILE *handle, const char *format, ...)
       
   433 {
       
   434     int len;
       
   435 
       
   436     va_list args;
       
   437     va_start(args, format);
       
   438     len = vfprintf(handle, format, args);
       
   439     va_end(args);
       
   440 
       
   441     return len;
       
   442 }