1: /*
     2:  ============================================================================
     3:  xoblite™ -> an advanced "extended shell" for Microsoft® Windows® 11
     4:  Copyright © 2002-2026 Karl Henrik Henriksson [qwilk/@xoblite]
     5:  Copyright © 2001-2004 The Blackbox for Windows Development Team
     6:  http://xoblite.net/ + https://github.com/xoblite/
     7:  ============================================================================
     8: 
     9:   Blackbox for Windows is free software, released under the
    10:   GNU General Public License (GPL version 2 or later), with an extension
    11:   that allows linking of proprietary modules under a controlled interface.
    12:   What this means is that plugins etc. are allowed to be released
    13:   under any license the author wishes. Please note, however, that the
    14:   original Blackbox gradient math code used in Blackbox for Windows
    15:   is available under the BSD license.
    16: 
    17:   http://www.fsf.org/licenses/gpl.html
    18:   http://www.fsf.org/licenses/gpl-faq.html#LinkingOverControlledInterface
    19:   http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
    20: 
    21:   This program is distributed in the hope that it will be useful,
    22:   but WITHOUT ANY WARRANTY; without even the implied warranty of
    23:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    24:   GNU General Public License for more details.
    25: 
    26:   For additional license information, please read the included license.html.
    27: 
    28:  ============================================================================
    29: */
    30: 
    31: #include "BImage.h" 
    32: #include "..\Settings\Settings.h" 
    33: #include <malloc.h> 
    34: 
    35: extern Settings* pSettings;
    36: 
    37: //===========================================================================
    38: // Function: AlphaRect
    39: // Purpose: ...
    40: //===========================================================================
    41: 
    42: void BImage::AlphaRect(HDC hdc, RECT rect, unsigned char alpha)
    43: {
    44:     CreateBuffer(hdc, rect, false);
    45: 
    46:     // Copy pixel data from the destination...
    47:     BitBlt(buf, 0, 0, width, height, hdc, rect.left, rect.top, SRCCOPY);
    48: 
    49:     // Set per pixel alpha values...
    50:     unsigned int x, y, count = 0;
    51:     for (y = 0; y < height ; y++)
    52:     {
    53:         for (x = 0; x < width; x++)
    54:         {
    55:             pixels[count+3] = alpha;
    56:             count += 4;
    57:         }
    58:     }
    59: 
    60:     // Copy the pixel data including alpha values back to the destination...
    61:     BitBlt(hdc, rect.left, rect.top, width, height, buf, 0, 0, SRCCOPY);
    62: 
    63:     DestroyBuffer();
    64: }
    65: 
    66: //===========================================================================
    67: // Function: AlphaBorder
    68: // Purpose: ...
    69: //===========================================================================
    70: 
    71: void BImage::AlphaBorder(HDC hdc, RECT rect, unsigned char alpha, int borderWidth)
    72: {
    73:     // Copy pixel data from the destination...
    74:     CreateBuffer(hdc, rect, false);
    75:     BitBlt(buf, 0, 0, width, height, hdc, rect.left, rect.top, SRCCOPY);
    76: 
    77:     int widthTimesFour = width * 4;
    78:     unsigned int x, y, count1, count2, nextValueOffset;
    79: 
    80:     for (int n = 1; n <= borderWidth; n++)
    81:     {
    82:         // Set per pixel alpha values along the top+bottom borders...
    83:         count1 = 3 + (widthTimesFour*(n-1)); // Top edge
    84:         count2 = 3 + (widthTimesFour*(height-n)); // Bottom edge
    85:         nextValueOffset = 4;
    86:         for (x = 0; x < width; x++)
    87:         {
    88:             pixels[count1] = pixels[count2] = alpha;
    89:             count1 += nextValueOffset;
    90:             count2 += nextValueOffset;
    91:         }
    92: 
    93:         // Set per pixel alpha values along the left+right borders...
    94:         count1 = 3 + ((n-1)*4); // Left edge
    95:         count2 = widthTimesFour - ((n-1)*4) - 1; // Right edge
    96:         nextValueOffset = widthTimesFour;
    97:         for (y = 0; y < height; y++)
    98:         {
    99:             pixels[count1] = pixels[count2] = alpha;
   100:             count1 += nextValueOffset;
   101:             count2 += nextValueOffset;
   102:         }
   103:     }
   104: 
   105:     // Copy the pixel data including alpha values back to the destination...
   106:     BitBlt(hdc, rect.left, rect.top, width, height, buf, 0, 0, SRCCOPY);
   107: 
   108:     DestroyBuffer();
   109: }
   110: 
   111: //===========================================================================
   112: // Function: AlphaCorner
   113: // Purpose: ...
   114: //===========================================================================
   115: 
   116: BYTE cornerAlphaArrayHiDPI2x[64] =
   117: {
   118:     0x00, 0x00, 0x00, 0x10, 0x40, 0x80, 0xc0, 0xe0,
   119:     0x00, 0x00, 0x40, 0xa0, 0xff, 0xff, 0xff, 0xff,
   120:     0x00, 0x40, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,
   121:     0x10, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   122:     0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   123:     0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   124:     0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   125:     0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
   126: };
   127: 
   128: BYTE cornerAlphaArrayLoDPI[25] =
   129: {
   130:     0x00, 0x10, 0x40, 0x90, 0xc0,
   131:     0x10, 0x60, 0xa0, 0xff, 0xff,
   132:     0x40, 0xa0, 0xff, 0xff, 0xff,
   133:     0x90, 0xff, 0xff, 0xff, 0xff,
   134:     0xc0, 0xff, 0xff, 0xff, 0xff,
   135: };
   136: 
   137: void BImage::AlphaCorner(HDC hdc, RECT rect, int corner, int borderWidth, unsigned char outerAlpha, unsigned char innerAlpha)
   138: {
   139:     // Copy pixel data from the destination...
   140:     CreateBuffer(hdc, rect, false);
   141:     BitBlt(buf, 0, 0, width, height, hdc, rect.left, rect.top, SRCCOPY);
   142: 
   143:     BYTE* alphaPtr;
   144:     unsigned int arraySizeXY;
   145:     unsigned int x, y, offset;
   146:     unsigned int bytesPerRow = (width*4);
   147:     unsigned int topleft, topright, bottomleft, bottomright;
   148:     unsigned int topcount, bottomcount;
   149: 
   150:     bool reversed;
   151:     if (outerAlpha > innerAlpha) reversed = true;
   152:     else reversed = false;
   153: 
   154:     //====================
   155: 
   156:     switch (pSettings->scalingFactorHiDPI)
   157:     {
   158:         case 2:
   159:         case 3: // Placeholder pending addition of HiDPI 3x corner alpha array in AlphaCorner() and related PrepareCorner() support
   160:         case 4: // Placeholder pending addition of HiDPI 4x corner alpha array in AlphaCorner() and related PrepareCorner() support
   161:         {
   162:             alphaPtr = cornerAlphaArrayHiDPI2x;
   163:             arraySizeXY = 8;
   164:             break;
   165:         }
   166: 
   167:         case 1:
   168:         default:
   169:         {
   170:             alphaPtr = cornerAlphaArrayLoDPI;
   171:             arraySizeXY = 5;
   172:             break;
   173:         }
   174:     }
   175: 
   176:     //====================
   177: 
   178:     BYTE pixelAlpha;
   179: 
   180:     // Set per pixel alpha values for all four corners of the target rect...
   181:     for (y = 0; y < arraySizeXY; y++)
   182:     {
   183:         // NOTE: We're using a bottom-up DIB
   184:         // -> origin is the lower-left corner!
   185:         bottomcount = y * bytesPerRow;
   186:         topcount = (height-y-1) * bytesPerRow;
   187: 
   188:         for (x = 0; x < arraySizeXY; x++)
   189:         {
   190:             pixelAlpha = *alphaPtr;
   191: 
   192:             if (pixelAlpha == 0xff)
   193:             {
   194:                 alphaPtr++;
   195:                 continue;
   196:             }
   197: 
   198:             if (reversed)
   199:             {
   200:                 pixelAlpha = 255 - pixelAlpha;
   201:                 if (pixelAlpha <= innerAlpha) pixelAlpha = innerAlpha;
   202:                 if (pixelAlpha >= outerAlpha) pixelAlpha = outerAlpha;
   203:             }
   204:             else
   205:             {
   206:                 if (pixelAlpha <= outerAlpha) pixelAlpha = outerAlpha;
   207:                 if (pixelAlpha >= innerAlpha) pixelAlpha = innerAlpha;
   208:             }
   209: 
   210:             offset = x * 4;
   211: 
   212:             if (corner & CORNER_BOTTOMLEFT)
   213:             {
   214:                 bottomleft = bottomcount+offset+3;
   215:                 pixels[bottomleft] = pixelAlpha;
   216:             }
   217:             if (corner & CORNER_BOTTOMRIGHT)
   218:             {
   219:                 bottomright = bottomcount+bytesPerRow-offset-1;
   220:                 pixels[bottomright] = pixelAlpha;
   221:             }
   222:             if (corner & CORNER_TOPLEFT)
   223:             {
   224:                 topleft = topcount+offset+3;
   225:                 pixels[topleft] = pixelAlpha;
   226:             }
   227:             if (corner & CORNER_TOPRIGHT)
   228:             {
   229:                 topright = topcount+bytesPerRow-offset-1;
   230:                 pixels[topright] = pixelAlpha;
   231:             }
   232: 
   233:             alphaPtr++;
   234:         }
   235:     }
   236: 
   237:     // Copy the pixel data including alpha values back to the destination...
   238:     BitBlt(hdc, rect.left, rect.top, width, height, buf, 0, 0, SRCCOPY);
   239: 
   240:     DestroyBuffer();
   241: }
   242: 
   243: //===========================================================================
   244: // Function: AlphaFromRGB
   245: // Purpose: ...
   246: //===========================================================================
   247: 
   248: void BImage::AlphaFromRGB(HDC hdc, RECT rect, unsigned char minAlpha, unsigned char maxAlpha, bool recolor, COLORREF color)
   249: {
   250:     CreateBuffer(hdc, rect, false);
   251: 
   252:     // Copy pixel data from the destination...
   253:     BitBlt(buf, 0, 0, width, height, hdc, rect.left, rect.top, SRCCOPY);
   254: 
   255:     BYTE red, green, blue;
   256:     if (recolor)
   257:     {
   258:         red = GetRValue(color);
   259:         green = GetGValue(color);
   260:         blue = GetBValue(color);
   261:     }
   262: 
   263:     unsigned int alphaRange = maxAlpha - minAlpha;
   264:     unsigned int averageRGB, newAlpha;
   265: 
   266:     unsigned int x, y, count = 0;
   267:     for (y = 0; y < height; y++)
   268:     {
   269:         for (x = 0; x < width; x++)
   270:         {
   271:             // Set the per pixel alpha values as an average of each pixel's RGB values, mapped to the allowed min<->max alpha range...
   272:             // (e.g. assuming the full alpha range 0-255 is allowed, 0xffffff pixels become fully opaque <-> 0x000000 pixels become fully transparent)
   273:             averageRGB = ((pixels[count+0] + pixels[count+1] + pixels[count+2]) / 3);
   274:             newAlpha = minAlpha + ((averageRGB * alphaRange) / 255);
   275:             pixels[count+3] = (BYTE)newAlpha;
   276: 
   277:             // ...and optionally recolor the pixels themselves to the specified color...
   278:             // (nb. this is typically also used to avoid e.g. text anti-aliasing artifacts on otherwise
   279:             // transparent backgrounds by making the pixels all the same colour but with different alpha values)
   280:             if (recolor)
   281:             {
   282:                 // Use case examples:
   283:                 // Set the new pixel colour without alpha applied to fully white 0xffffff -> "Regular/Light mode"
   284:                 // Set the new pixel colour without alpha applied to fully black 0x000000 -> "Dark mode"
   285:                 // Set the new pixel colour without alpha applied to any colour 0xBBGGRR -> "Recolor mode"
   286:                 pixels[count] = blue;
   287:                 pixels[count+1] = green;
   288:                 pixels[count+2] = red;
   289:             }
   290: 
   291:             count += 4;
   292:         }
   293:     }
   294: 
   295:     // Copy the pixel data including alpha values back to the destination...
   296:     BitBlt(hdc, rect.left, rect.top, width, height, buf, 0, 0, SRCCOPY);
   297: 
   298:     DestroyBuffer();
   299: }
   300: 
   301: //===========================================================================
   302: // Function: AlphaMask
   303: // Purpose: ...
   304: //===========================================================================
   305: 
   306: // ########## NOTE: WORK STILL IN PROGRESS! ##########
   307: 
   308: void BImage::AlphaMask(HDC destHdc, RECT destRect, HDC srcHdc, RECT srcRect, bool useSrcRGBAsAlpha)
   309: {
   310:     // Safeguard: Make sure that the source and destination RECTs are of the same *size*...
   311:     // (the actual position of each RECT inside its parent HDC is irrelevant here)
   312:     int srcSize = (srcRect.right - srcRect.left) * (srcRect.bottom - srcRect.top);
   313:     int destSize = (destRect.right - destRect.left) * (destRect.bottom - destRect.top);
   314:     if (srcSize != destSize) return;
   315: 
   316:     //====================
   317: 
   318:     // Copy the requested input values from the source HDC into a buffer...
   319:     CreateBuffer(srcHdc, srcRect, false);
   320:     BitBlt(buf, 0, 0, width, height, srcHdc, srcRect.left, srcRect.top, SRCCOPY);
   321: 
   322:     BYTE* alphaBuffer = (BYTE*)malloc(width*height);
   323:     if (alphaBuffer == NULL)
   324:     {
   325:         DestroyBuffer();
   326:         return;
   327:     }
   328: 
   329:     unsigned int x, y, count;
   330: 
   331:     // Should we use the source per pixel colors as the destination per pixel alpha values...
   332:     // (nb. greyscale source format assumed so we can use any of R/G/B; here using the B value)
   333:     if (useSrcRGBAsAlpha) count = 0; // Per pixel data offset 0 bytes -> B value
   334:     // ...or copy the per pixel alpha values straight over from the source to the destination?
   335:     else count = 3; // Per pixel data offset 3 bytes -> Alpha value
   336: 
   337:     BYTE* alphaPtr = alphaBuffer;
   338:     for (y = 0; y < height; y++)
   339:     {
   340:         for (x = 0; x < width; x++)
   341:         {
   342:             *alphaPtr = pixels[count];
   343:             alphaPtr++;
   344:             count += 4;
   345:         }
   346:     }
   347: 
   348:     BYTE* alphaBufferEnd = alphaPtr;
   349: 
   350:     DestroyBuffer();
   351: 
   352: //  int alphaBufferSize = alphaBufferEnd - alphaBuffer;
   353: //  char msg[255];
   354: //  sprintf_s(msg, sizeofArray(msg), "Number of alpha bytes copied: %d", alphaBufferSize);
   355: //  SendMessage(GetBBWnd(), BB_CONSOLEMESSAGE, (WPARAM)CONSOLE_REGULAR_MESSAGE, (LPARAM)msg);
   356: 
   357:     //====================
   358: 
   359:     // Copy the alpha values from the buffer to the destination HDC...
   360:     CreateBuffer(destHdc, destRect, false);
   361:     BitBlt(buf, 0, 0, width, height, destHdc, destRect.left, destRect.top, SRCCOPY);
   362: 
   363:     alphaPtr = alphaBuffer;
   364:     count = 3; // Per pixel data offset 3 bytes -> Alpha value
   365:     for (y = 0; y < height; y++)
   366:     {
   367:         for (x = 0; x < width; x++)
   368:         {
   369:             pixels[count] = (BYTE)*alphaPtr;
   370:             count += 4;
   371:             alphaPtr++;
   372:             if (alphaPtr == alphaBufferEnd) break; // Safeguard
   373:         }
   374:     }
   375: 
   376:     BitBlt(destHdc, destRect.left, destRect.top, width, height, buf, 0, 0, SRCCOPY);
   377:     DestroyBuffer();
   378: 
   379:     //====================
   380: 
   381:     free(alphaBuffer);
   382:     alphaBuffer = NULL;
   383: }
   384: 
   385: //===========================================================================
   386: // Function: AlphaApply
   387: // Purpose: Pre-applies the per pixel alpha to the RGB values of each pixel
   388: //          (required by related Windows API functions before processing)
   389: //===========================================================================
   390: 
   391: void BImage::AlphaApply(HDC hdc, RECT rect)
   392: {
   393:     CreateBuffer(hdc, rect, false);
   394: 
   395:     // Copy pixel data from the destination...
   396:     BitBlt(buf, 0, 0, width, height, hdc, rect.left, rect.top, SRCCOPY);
   397: 
   398:     // Apply per pixel alpha to the RGB values...
   399:     unsigned int x, y, count = 0, tempPixel;
   400:     BYTE alpha;
   401:     for (y = 0; y < height; y++)
   402:     {
   403:         for (x = 0; x < width; x++)
   404:         {
   405:             alpha = pixels[count + 3];
   406: 
   407:             if (alpha < 255)
   408:             {
   409:                 tempPixel = (pixels[count+2] * alpha) / 255;
   410:                 pixels[count+2] = (BYTE)tempPixel;
   411:                 tempPixel = (pixels[count+1] * alpha) / 255;
   412:                 pixels[count+1] = (BYTE)tempPixel;
   413:                 tempPixel = (pixels[count] * alpha) / 255;
   414:                 pixels[count] = (BYTE)tempPixel;
   415:             }
   416: 
   417:             count += 4;
   418:         }
   419:     }
   420: 
   421:     // Copy the pixel data with newly applied alpha back to the destination...
   422:     BitBlt(hdc, rect.left, rect.top, width, height, buf, 0, 0, SRCCOPY);
   423: 
   424:     DestroyBuffer();
   425: }
   426: 
   427: //===========================================================================
   428: // Function: PrepareCorner
   429: // Purpose: Round off corner pixel data prior to call to AlphaCorner
   430: //===========================================================================
   431: 
   432: void BImage::PrepareCorner(HDC hdc, RECT rect, int corner, int bevelStyle, int bevelPosition, int bevelWidth, int borderWidth)
   433: {
   434:     switch (pSettings->scalingFactorHiDPI)
   435:     {
   436:         case 2:
   437:         case 3: // Placeholder pending addition of HiDPI 3x corner alpha array in AlphaCorner() and related PrepareCorner() support
   438:         case 4: // Placeholder pending addition of HiDPI 4x corner alpha array in AlphaCorner() and related PrepareCorner() support
   439:         {
   440:             if (bevelStyle != BEVEL_FLAT)
   441:             {
   442:                 if (bevelPosition == BEVEL1)
   443:                 {
   444:                     int offsetX, offsetY;
   445: 
   446:                     if (corner & CORNER_TOPLEFT)
   447:                     {
   448:                         // Round off the top left bevel...
   449:                         offsetX = rect.left + borderWidth;
   450:                         offsetY = rect.top + borderWidth;
   451:                         SetPixel(hdc, offsetX+3, offsetY+1, GetPixel(hdc, offsetX+3, offsetY));
   452:                         SetPixel(hdc, offsetX+2, offsetY+1, GetPixel(hdc, offsetX+2, offsetY));
   453:                         SetPixel(hdc, offsetX+1, offsetY+2, GetPixel(hdc, offsetX, offsetY+2));
   454:                         SetPixel(hdc, offsetX+1, offsetY+3, GetPixel(hdc, offsetX, offsetY+3));
   455:                     }
   456: 
   457:                     if (corner & CORNER_BOTTOMLEFT)
   458:                     {
   459:                         // Round off the bottom left bevel...
   460:                         offsetX = rect.left + borderWidth;
   461:                         offsetY = rect.bottom - borderWidth - 1;
   462:                         SetPixel(hdc, offsetX+1, offsetY-3, GetPixel(hdc, offsetX, offsetY-3));
   463:                         SetPixel(hdc, offsetX+1, offsetY-2, GetPixel(hdc, offsetX, offsetY-2));
   464:                         SetPixel(hdc, offsetX+2, offsetY-1, GetPixel(hdc, offsetX+2, offsetY));
   465:                         SetPixel(hdc, offsetX+3, offsetY-1, GetPixel(hdc, offsetX+3, offsetY));
   466:                     }
   467: 
   468:                     if (corner & CORNER_TOPRIGHT)
   469:                     {
   470:                         // Round off the top right bevel...
   471:                         offsetX = rect.right - borderWidth - 1;
   472:                         offsetY = rect.top + borderWidth;
   473:                         SetPixel(hdc, offsetX-3, offsetY+1, GetPixel(hdc, offsetX-3, offsetY));
   474:                         SetPixel(hdc, offsetX-2, offsetY+1, GetPixel(hdc, offsetX-2, offsetY));
   475:                         SetPixel(hdc, offsetX-1, offsetY+2, GetPixel(hdc, offsetX, offsetY+2));
   476:                         SetPixel(hdc, offsetX-1, offsetY+3, GetPixel(hdc, offsetX, offsetY+3));
   477:                     }
   478: 
   479:                     if (corner & CORNER_BOTTOMRIGHT)
   480:                     {
   481:                         // Round off the bottom right bevel...
   482:                         offsetX = rect.right - borderWidth - 1;
   483:                         offsetY = rect.bottom - borderWidth - 1;
   484:                         SetPixel(hdc, offsetX-1, offsetY-3, GetPixel(hdc, offsetX, offsetY-3));
   485:                         SetPixel(hdc, offsetX-1, offsetY-2, GetPixel(hdc, offsetX, offsetY-2));
   486:                         SetPixel(hdc, offsetX-2, offsetY-1, GetPixel(hdc, offsetX-2, offsetY));
   487:                         SetPixel(hdc, offsetX-3, offsetY-1, GetPixel(hdc, offsetX-3, offsetY));
   488:                     }
   489:                 }
   490:                 else if (bevelPosition == BEVEL2)
   491:                 {
   492:                     // No change necessary... [?] (as far as I can tell right now at least)
   493:                 }
   494:             }
   495: 
   496:             if (borderWidth > 0)
   497:             {
   498:                 int offsetX, offsetY;
   499: 
   500:                 if (corner & CORNER_TOPLEFT)
   501:                 {
   502:                     // Round off the top left corner...
   503:                     offsetX = rect.left + borderWidth;
   504:                     offsetY = rect.top + borderWidth;
   505:                     SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-1), GetPixel(hdc, offsetX-1, offsetY)));
   506:                     SetPixel(hdc, offsetX+1, offsetY, GetPixel(hdc, offsetX+1, offsetY-1));
   507:                     SetPixel(hdc, offsetX+2, offsetY, GetPixel(hdc, offsetX+2, offsetY-1));
   508:                     SetPixel(hdc, offsetX, offsetY+1, GetPixel(hdc, offsetX-1, offsetY+1));
   509:                     SetPixel(hdc, offsetX, offsetY+2, GetPixel(hdc, offsetX-1, offsetY+2));
   510:                     SetPixel(hdc, offsetX+1, offsetY+1, pSettings->MixColors(GetPixel(hdc, offsetX+1, offsetY+1), GetPixel(hdc, offsetX, offsetY)));
   511:                     SetPixel(hdc, offsetX+3, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX+3, offsetY), GetPixel(hdc, offsetX+2, offsetY)));
   512:                     SetPixel(hdc, offsetX, offsetY+3, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+3), GetPixel(hdc, offsetX, offsetY+2)));
   513:                 }
   514: 
   515:                 if (corner & CORNER_BOTTOMLEFT)
   516:                 {
   517:                     // Round off the bottom left corner...
   518:                     offsetX = rect.left + borderWidth;
   519:                     offsetY = rect.bottom - borderWidth - 1;
   520:                     SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+1), GetPixel(hdc, offsetX-1, offsetY)));
   521:                     SetPixel(hdc, offsetX+1, offsetY, GetPixel(hdc, offsetX+1, offsetY+1));
   522:                     SetPixel(hdc, offsetX+2, offsetY, GetPixel(hdc, offsetX+2, offsetY+1));
   523:                     SetPixel(hdc, offsetX, offsetY-1, GetPixel(hdc, offsetX-1, offsetY-1));
   524:                     SetPixel(hdc, offsetX, offsetY-2, GetPixel(hdc, offsetX-1, offsetY-2));
   525:                     SetPixel(hdc, offsetX+1, offsetY-1, pSettings->MixColors(GetPixel(hdc, offsetX+1, offsetY-1), GetPixel(hdc, offsetX, offsetY)));
   526:                     SetPixel(hdc, offsetX+3, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX+3, offsetY), GetPixel(hdc, offsetX+2, offsetY)));
   527:                     SetPixel(hdc, offsetX, offsetY-3, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-3), GetPixel(hdc, offsetX, offsetY-2)));
   528:                 }
   529: 
   530:                 if (corner & CORNER_TOPRIGHT)
   531:                 {
   532:                     // Round off the top right corner...
   533:                     offsetX = rect.right - borderWidth - 1;
   534:                     offsetY = rect.top + borderWidth;
   535:                     SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-1), GetPixel(hdc, offsetX+1, offsetY)));
   536:                     SetPixel(hdc, offsetX-1, offsetY, GetPixel(hdc, offsetX-1, offsetY-1));
   537:                     SetPixel(hdc, offsetX-2, offsetY, GetPixel(hdc, offsetX-2, offsetY-1));
   538:                     SetPixel(hdc, offsetX, offsetY+1, GetPixel(hdc, offsetX+1, offsetY+1));
   539:                     SetPixel(hdc, offsetX, offsetY+2, GetPixel(hdc, offsetX+1, offsetY+2));
   540:                     SetPixel(hdc, offsetX-1, offsetY+1, pSettings->MixColors(GetPixel(hdc, offsetX-1, offsetY+1), GetPixel(hdc, offsetX, offsetY)));
   541:                     SetPixel(hdc, offsetX-3, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX-3, offsetY), GetPixel(hdc, offsetX-2, offsetY)));
   542:                     SetPixel(hdc, offsetX, offsetY+3, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+3), GetPixel(hdc, offsetX, offsetY+2)));
   543:                 }
   544: 
   545:                 if (corner & CORNER_BOTTOMRIGHT)
   546:                 {
   547:                     // Round off the bottom right corner...
   548:                     offsetX = rect.right - borderWidth - 1;
   549:                     offsetY = rect.bottom - borderWidth - 1;
   550:                     SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+1), GetPixel(hdc, offsetX+1, offsetY)));
   551:                     SetPixel(hdc, offsetX-1, offsetY, GetPixel(hdc, offsetX-1, offsetY+1));
   552:                     SetPixel(hdc, offsetX-2, offsetY, GetPixel(hdc, offsetX-2, offsetY+1));
   553:                     SetPixel(hdc, offsetX, offsetY-1, GetPixel(hdc, offsetX+1, offsetY-1));
   554:                     SetPixel(hdc, offsetX, offsetY-2, GetPixel(hdc, offsetX+1, offsetY-2));
   555:                     SetPixel(hdc, offsetX-1, offsetY-1, pSettings->MixColors(GetPixel(hdc, offsetX-1, offsetY-1), GetPixel(hdc, offsetX, offsetY)));
   556:                     SetPixel(hdc, offsetX-3, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX-3, offsetY), GetPixel(hdc, offsetX-2, offsetY)));
   557:                     SetPixel(hdc, offsetX, offsetY-3, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-3), GetPixel(hdc, offsetX, offsetY-2)));
   558:                 }
   559:             }
   560: 
   561:             break;
   562:         }
   563: 
   564:         //====================
   565: 
   566:         case 1:
   567:         default:
   568:         {
   569:             if (bevelStyle != BEVEL_FLAT)
   570:             {
   571:                 if (bevelPosition == BEVEL1)
   572:                 {
   573:                     int offsetX, offsetY;
   574: 
   575:                     if (corner & CORNER_TOPLEFT)
   576:                     {
   577:                         // Round off the top left bevel...
   578:                         offsetX = rect.left + borderWidth;
   579:                         offsetY = rect.top + borderWidth;
   580:                         SetPixel(hdc, offsetX+1, offsetY+1, GetPixel(hdc, offsetX, offsetY));
   581:                     }
   582: 
   583:                     if (corner & CORNER_BOTTOMLEFT)
   584:                     {
   585:                         // Round off the bottom left bevel...
   586:                         offsetX = rect.left + borderWidth;
   587:                         offsetY = rect.bottom - borderWidth - 1;
   588:                         SetPixel(hdc, offsetX+1, offsetY-1, GetPixel(hdc, offsetX, offsetY));
   589:                     }
   590: 
   591:                     if (corner & CORNER_TOPRIGHT)
   592:                     {
   593:                         // Round off the top right bevel...
   594:                         offsetX = rect.right - borderWidth - 1;
   595:                         offsetY = rect.top + borderWidth;
   596:                         SetPixel(hdc, offsetX-1, offsetY+1, GetPixel(hdc, offsetX, offsetY));
   597:                     }
   598: 
   599:                     if (corner & CORNER_BOTTOMRIGHT)
   600:                     {
   601:                         // Round off the bottom right bevel...
   602:                         offsetX = rect.right - borderWidth - 1;
   603:                         offsetY = rect.bottom - borderWidth - 1;
   604:                         SetPixel(hdc, offsetX-1, offsetY-1, GetPixel(hdc, offsetX, offsetY));
   605:                     }
   606:                 }
   607:                 else if (bevelPosition == BEVEL2)
   608:                 {
   609:                     // No change necessary... [?] (as far as I can tell right now at least)
   610:                 }
   611:             }
   612: 
   613:             if (borderWidth > 0)
   614:             {
   615:                 int offsetX, offsetY;
   616: 
   617:                 if (corner & CORNER_TOPLEFT)
   618:                 {
   619:                     // Round off the top left corner...
   620:                     offsetX = rect.left;
   621:                     offsetY = rect.top;
   622:                     SetPixel(hdc, offsetX+1, offsetY+1, GetPixel(hdc, offsetX, offsetY));
   623:                     SetPixel(hdc, offsetX+2, offsetY+1, GetPixel(hdc, offsetX+2, offsetY));
   624:                     SetPixel(hdc, offsetX+1, offsetY+2, GetPixel(hdc, offsetX, offsetY+2));
   625:                     offsetX += borderWidth;
   626:                     offsetY += borderWidth;
   627:                     SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-1), GetPixel(hdc, offsetX-1, offsetY)));
   628:                     SetPixel(hdc, offsetX+1, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX+1, offsetY), GetPixel(hdc, offsetX+1, offsetY-1)));
   629:                     SetPixel(hdc, offsetX, offsetY+1, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+1), GetPixel(hdc, offsetX-1, offsetY+1)));
   630: //                  SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX-1, offsetY), GetPixel(hdc, offsetX, offsetY-1)));
   631: //                  SetPixel(hdc, offsetX+1, offsetY, GetPixel(hdc, offsetX+1, offsetY-1));
   632: //                  SetPixel(hdc, offsetX+2, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX+2, offsetY), GetPixel(hdc, offsetX+2, offsetY-1)));
   633: //                  SetPixel(hdc, offsetX, offsetY+1, GetPixel(hdc, offsetX-1, offsetY+1));
   634: //                  SetPixel(hdc, offsetX, offsetY+2, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+2), GetPixel(hdc, offsetX-1, offsetY+2)));
   635:                 }
   636: 
   637:                 if (corner & CORNER_BOTTOMLEFT)
   638:                 {
   639:                     // Round off the bottom left corner...
   640:                     offsetX = rect.left;
   641:                     offsetY = rect.bottom - 1;
   642:                     SetPixel(hdc, offsetX+1, offsetY-1, GetPixel(hdc, offsetX, offsetY));
   643:                     SetPixel(hdc, offsetX+2, offsetY-1, GetPixel(hdc, offsetX+2, offsetY));
   644:                     SetPixel(hdc, offsetX+1, offsetY-2, GetPixel(hdc, offsetX, offsetY-2));
   645:                     offsetX += borderWidth;
   646:                     offsetY -= borderWidth;
   647:                     SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+1), GetPixel(hdc, offsetX-1, offsetY)));
   648:                     SetPixel(hdc, offsetX+1, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX+1, offsetY), GetPixel(hdc, offsetX+1, offsetY+1)));
   649:                     SetPixel(hdc, offsetX, offsetY-1, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-1), GetPixel(hdc, offsetX-1, offsetY-1)));
   650: //                  SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX-1, offsetY), GetPixel(hdc, offsetX, offsetY+1)));
   651: //                  SetPixel(hdc, offsetX+1, offsetY, GetPixel(hdc, offsetX+1, offsetY+1));
   652: //                  SetPixel(hdc, offsetX+2, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX+2, offsetY), GetPixel(hdc, offsetX+2, offsetY+1)));
   653: //                  SetPixel(hdc, offsetX, offsetY-1, GetPixel(hdc, offsetX-1, offsetY-1));
   654: //                  SetPixel(hdc, offsetX, offsetY-2, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-2), GetPixel(hdc, offsetX-1, offsetY-2)));
   655:                 }
   656: 
   657:                 if (corner & CORNER_TOPRIGHT)
   658:                 {
   659:                     // Round off the top right corner...
   660:                     offsetX = rect.right - 1;
   661:                     offsetY = rect.top;
   662:                     SetPixel(hdc, offsetX-1, offsetY+1, GetPixel(hdc, offsetX, offsetY));
   663:                     SetPixel(hdc, offsetX-2, offsetY+1, GetPixel(hdc, offsetX-2, offsetY));
   664:                     SetPixel(hdc, offsetX-1, offsetY+2, GetPixel(hdc, offsetX, offsetY+2));
   665:                     offsetX -= borderWidth;
   666:                     offsetY += borderWidth;
   667:                     SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-1), GetPixel(hdc, offsetX+1, offsetY)));
   668:                     SetPixel(hdc, offsetX-1, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX-1, offsetY), GetPixel(hdc, offsetX-1, offsetY-1)));
   669:                     SetPixel(hdc, offsetX, offsetY+1, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+1), GetPixel(hdc, offsetX+1, offsetY+1)));
   670: //                  SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX+1, offsetY), GetPixel(hdc, offsetX, offsetY-1)));
   671: //                  SetPixel(hdc, offsetX-1, offsetY, GetPixel(hdc, offsetX-1, offsetY-1));
   672: //                  SetPixel(hdc, offsetX-2, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX-2, offsetY), GetPixel(hdc, offsetX-2, offsetY-1)));
   673: //                  SetPixel(hdc, offsetX, offsetY+1, GetPixel(hdc, offsetX+1, offsetY+1));
   674: //                  SetPixel(hdc, offsetX, offsetY+2, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+2), GetPixel(hdc, offsetX+1, offsetY+2)));
   675:                 }
   676: 
   677:                 if (corner & CORNER_BOTTOMRIGHT)
   678:                 {
   679:                     // Round off the bottom right corner...
   680:                     offsetX = rect.right - 1;
   681:                     offsetY = rect.bottom - 1;
   682:                     SetPixel(hdc, offsetX-1, offsetY-1, GetPixel(hdc, offsetX, offsetY));
   683:                     SetPixel(hdc, offsetX-2, offsetY-1, GetPixel(hdc, offsetX-2, offsetY));
   684:                     SetPixel(hdc, offsetX-1, offsetY-2, GetPixel(hdc, offsetX, offsetY-2));
   685:                     offsetX -= borderWidth;
   686:                     offsetY -= borderWidth;
   687:                     SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY+1), GetPixel(hdc, offsetX+1, offsetY)));
   688:                     SetPixel(hdc, offsetX-1, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX-1, offsetY), GetPixel(hdc, offsetX-1, offsetY+1)));
   689:                     SetPixel(hdc, offsetX, offsetY-1, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-1), GetPixel(hdc, offsetX+1, offsetY-1)));
   690: //                  SetPixel(hdc, offsetX, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX+1, offsetY), GetPixel(hdc, offsetX, offsetY+1)));
   691: //                  SetPixel(hdc, offsetX-1, offsetY, GetPixel(hdc, offsetX-1, offsetY+1));
   692: //                  SetPixel(hdc, offsetX-2, offsetY, pSettings->MixColors(GetPixel(hdc, offsetX-2, offsetY), GetPixel(hdc, offsetX-2, offsetY+1)));
   693: //                  SetPixel(hdc, offsetX, offsetY-1, GetPixel(hdc, offsetX+1, offsetY-1));
   694: //                  SetPixel(hdc, offsetX, offsetY-2, pSettings->MixColors(GetPixel(hdc, offsetX, offsetY-2), GetPixel(hdc, offsetX+1, offsetY-2)));
   695:                 }
   696:             }
   697:             break;
   698:         }
   699:     }
   700: }
   701: 
   702: //===========================================================================
   703: