src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c

Print this page




  65 }
  66 
  67 /* These macro help to ensure that we only take part of frame that fits into
  68    logical screen. */
  69 
  70 /* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
  71 #define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
  72 /* Ensures that line starting at point p does not exceed boundary pmax.
  73    Returns fixed length (if fix is needed) */
  74 #define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
  75 
  76 int
  77 SplashDecodeGif(Splash * splash, GifFileType * gif)
  78 {
  79     int stride;
  80     int bufferSize;
  81     byte_t *pBitmapBits, *pOldBitmapBits;
  82     int i, j;
  83     int imageIndex;
  84     int cx, cy, cw, ch; /* clamped coordinates */
  85     int numLines;
  86     int numPassLines;
  87 
  88     if (DGifSlurp(gif) == GIF_ERROR) {
  89         return 0;
  90     }
  91 
  92     SplashCleanup(splash);
  93 
  94     if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
  95         return 0;
  96     }
  97     stride = gif->SWidth * splash->imageFormat.depthBytes;
  98     if (splash->byteAlignment > 1)
  99         stride =
 100             (stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
 101 
 102     if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
 103         return 0;
 104     }
 105 
 106     if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {


 196                                 (pExtension[1] | (((int)pExtension[2]) << 8)) - 1;
 197                         }
 198                     }
 199                     break;
 200                 }
 201             default:
 202                 break;
 203             }
 204         }
 205 
 206         if (colorMap) {
 207             for (i = 0; i < colorCount; i++) {
 208                 colorMapBuf[i] = MAKE_QUAD_GIF(colorMap->Colors[i], 0xff);
 209             }
 210         }
 211         {
 212 
 213             byte_t *pSrc = image->RasterBits;
 214             ImageFormat srcFormat;
 215             ImageRect srcRect, dstRect;










 216 
 217             srcFormat.colorMap = colorMapBuf;
 218             srcFormat.depthBytes = 1;
 219             srcFormat.byteOrder = BYTE_ORDER_NATIVE;
 220             srcFormat.transparentColor = transparentColor;
 221             srcFormat.fixedBits = QUAD_ALPHA_MASK;      // fixed 100% alpha
 222             srcFormat.premultiplied = 0;
 223 



 224             /* Number of source lines for current pass */
 225             numPassLines = desc->Height;
 226             /* Number of lines that fits to dest buffer */
 227             numLines = ch;
 228 
 229             initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
 230                 desc->Width, pSrc, &srcFormat);
 231 
 232             if (numLines > 0) {
 233                 initRect(&dstRect, cx, cy, cw,
 234                          numLines , 1, stride, pBitmapBits, &splash->imageFormat);
 235 
 236                 pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
 237             }
 238             // skip extra source data
 239             pSrc += (numPassLines - numLines) * srcRect.stride;
 240         }

 241 
 242         // now dispose of the previous frame correctly
 243 
 244         splash->frames[imageIndex].bitmapBits =
 245             (rgbquad_t *) malloc(bufferSize); // bufferSize is safe (checked above)
 246         if (!splash->frames[imageIndex].bitmapBits) {
 247             free(pBitmapBits);
 248             free(pOldBitmapBits);
 249             /* Assuming that callee will take care of splash frames we have already allocated */
 250             return 0;
 251         }
 252         memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
 253 
 254         SplashInitFrameShape(splash, imageIndex);
 255 
 256         splash->frames[imageIndex].delay = frameDelay * 10;     // 100ths of second to milliseconds
 257         switch (disposeMethod) {
 258         case GIF_DISPOSE_LEAVE:
 259             memcpy(pOldBitmapBits, pBitmapBits, bufferSize);
 260             break;


 279         case GIF_DISPOSE_RESTORE:
 280             {
 281                 int lineSize = cw * splash->imageFormat.depthBytes;
 282                 if (lineSize > 0) {
 283                     int lineOffset = cx * splash->imageFormat.depthBytes;
 284                     int lineIndex = cy * stride + lineOffset;
 285                     for (j=0; j<ch; j++) {
 286                         memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
 287                                lineSize);
 288                         lineIndex += stride;
 289                     }
 290                 }
 291             }
 292             break;
 293         }
 294     }
 295 
 296     free(pBitmapBits);
 297     free(pOldBitmapBits);
 298 
 299     DGifCloseFile(gif, NULL);






 300 
 301     return 1;
 302 }
 303 
 304 int
 305 SplashDecodeGifStream(Splash * splash, SplashStream * stream)
 306 {

 307     GifFileType *gif = DGifOpen((void *) stream, SplashStreamGifInputFunc, NULL);



 308 
 309     if (!gif)
 310         return 0;
 311     return SplashDecodeGif(splash, gif);
 312 }


  65 }
  66 
  67 /* These macro help to ensure that we only take part of frame that fits into
  68    logical screen. */
  69 
  70 /* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
  71 #define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
  72 /* Ensures that line starting at point p does not exceed boundary pmax.
  73    Returns fixed length (if fix is needed) */
  74 #define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
  75 
  76 int
  77 SplashDecodeGif(Splash * splash, GifFileType * gif)
  78 {
  79     int stride;
  80     int bufferSize;
  81     byte_t *pBitmapBits, *pOldBitmapBits;
  82     int i, j;
  83     int imageIndex;
  84     int cx, cy, cw, ch; /* clamped coordinates */
  85     const int interlacedOffset[] = { 0, 4, 2, 1, 0 };   /* The way Interlaced image should. */
  86     const int interlacedJumps[] = { 8, 8, 4, 2, 1 };    /* be read - offsets and jumps... */
  87 
  88     if (DGifSlurp(gif) == GIF_ERROR) {
  89         return 0;
  90     }
  91 
  92     SplashCleanup(splash);
  93 
  94     if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
  95         return 0;
  96     }
  97     stride = gif->SWidth * splash->imageFormat.depthBytes;
  98     if (splash->byteAlignment > 1)
  99         stride =
 100             (stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
 101 
 102     if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
 103         return 0;
 104     }
 105 
 106     if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {


 196                                 (pExtension[1] | (((int)pExtension[2]) << 8)) - 1;
 197                         }
 198                     }
 199                     break;
 200                 }
 201             default:
 202                 break;
 203             }
 204         }
 205 
 206         if (colorMap) {
 207             for (i = 0; i < colorCount; i++) {
 208                 colorMapBuf[i] = MAKE_QUAD_GIF(colorMap->Colors[i], 0xff);
 209             }
 210         }
 211         {
 212 
 213             byte_t *pSrc = image->RasterBits;
 214             ImageFormat srcFormat;
 215             ImageRect srcRect, dstRect;
 216             int pass = 4, npass = 5;
 217 
 218 #if GIFLIB_MAJOR < 5
 219             /* Interlaced gif support is broken in giflib < 5
 220                so we need to work around this */
 221             if (desc->Interlace) {
 222                 pass = 0;
 223                 npass = 4;
 224             }
 225 #endif
 226 
 227             srcFormat.colorMap = colorMapBuf;
 228             srcFormat.depthBytes = 1;
 229             srcFormat.byteOrder = BYTE_ORDER_NATIVE;
 230             srcFormat.transparentColor = transparentColor;
 231             srcFormat.fixedBits = QUAD_ALPHA_MASK;      // fixed 100% alpha
 232             srcFormat.premultiplied = 0;
 233 
 234             for (; pass < npass; ++pass) {
 235                 int jump = interlacedJumps[pass];
 236                 int ofs = interlacedOffset[pass];
 237                 /* Number of source lines for current pass */
 238                 int numPassLines = (desc->Height + jump - ofs - 1) / jump;
 239                 /* Number of lines that fits to dest buffer */
 240                 int numLines = (ch + jump - ofs - 1) / jump;
 241 
 242                 initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
 243                     desc->Width, pSrc, &srcFormat);
 244 
 245                 if (numLines > 0) {
 246                     initRect(&dstRect, cx, cy + ofs, cw,
 247                              numLines , jump, stride, pBitmapBits, &splash->imageFormat);
 248 
 249                     pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
 250                 }
 251                 // skip extra source data
 252                 pSrc += (numPassLines - numLines) * srcRect.stride;
 253             }
 254         }
 255 
 256         // now dispose of the previous frame correctly
 257 
 258         splash->frames[imageIndex].bitmapBits =
 259             (rgbquad_t *) malloc(bufferSize); // bufferSize is safe (checked above)
 260         if (!splash->frames[imageIndex].bitmapBits) {
 261             free(pBitmapBits);
 262             free(pOldBitmapBits);
 263             /* Assuming that callee will take care of splash frames we have already allocated */
 264             return 0;
 265         }
 266         memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
 267 
 268         SplashInitFrameShape(splash, imageIndex);
 269 
 270         splash->frames[imageIndex].delay = frameDelay * 10;     // 100ths of second to milliseconds
 271         switch (disposeMethod) {
 272         case GIF_DISPOSE_LEAVE:
 273             memcpy(pOldBitmapBits, pBitmapBits, bufferSize);
 274             break;


 293         case GIF_DISPOSE_RESTORE:
 294             {
 295                 int lineSize = cw * splash->imageFormat.depthBytes;
 296                 if (lineSize > 0) {
 297                     int lineOffset = cx * splash->imageFormat.depthBytes;
 298                     int lineIndex = cy * stride + lineOffset;
 299                     for (j=0; j<ch; j++) {
 300                         memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
 301                                lineSize);
 302                         lineIndex += stride;
 303                     }
 304                 }
 305             }
 306             break;
 307         }
 308     }
 309 
 310     free(pBitmapBits);
 311     free(pOldBitmapBits);
 312 
 313 #if GIFLIB_MAJOR > 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1)
 314     if (DGifCloseFile(gif, NULL) == GIF_ERROR) {
 315         return 0;
 316     }
 317 #else
 318     DGifCloseFile(gif);
 319 #endif
 320 
 321     return 1;
 322 }
 323 
 324 int
 325 SplashDecodeGifStream(Splash * splash, SplashStream * stream)
 326 {
 327 #if GIFLIB_MAJOR >= 5
 328     GifFileType *gif = DGifOpen((void *) stream, SplashStreamGifInputFunc, NULL);
 329 #else
 330     GifFileType *gif = DGifOpen((void *) stream, SplashStreamGifInputFunc);
 331 #endif
 332 
 333     if (!gif)
 334         return 0;
 335     return SplashDecodeGif(splash, gif);
 336 }