annotate src/share/native/sun/awt/splashscreen/splashscreen_gif.c @ 3261:a06412e13bf7

6962318: Update copyright year Reviewed-by: xdono
author ohair
date Tue, 28 Dec 2010 15:53:50 -0800
parents 70a695f74efb
children 9c76ea43d491
rev   line source
duke@0 1 /*
ohair@3261 2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
ohair@2362 7 * published by the Free Software Foundation. Oracle designates this
duke@0 8 * particular file as subject to the "Classpath" exception as provided
ohair@2362 9 * by Oracle in the LICENSE file that accompanied this code.
duke@0 10 *
duke@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 15 * accompanied this code).
duke@0 16 *
duke@0 17 * You should have received a copy of the GNU General Public License version
duke@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 20 *
ohair@2362 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@2362 22 * or visit www.oracle.com if you need additional information or have any
ohair@2362 23 * questions.
duke@0 24 */
duke@0 25
duke@0 26 #include "splashscreen_impl.h"
duke@0 27 #include "splashscreen_gfx.h"
duke@0 28
duke@0 29 #include "../giflib/gif_lib.h"
duke@0 30
duke@0 31 #define GIF_TRANSPARENT 0x01
duke@0 32 #define GIF_USER_INPUT 0x02
duke@0 33 #define GIF_DISPOSE_MASK 0x07
duke@0 34 #define GIF_DISPOSE_SHIFT 2
duke@0 35
duke@0 36 #define GIF_NOT_TRANSPARENT -1
duke@0 37
duke@0 38 #define GIF_DISPOSE_NONE 0 // No disposal specified. The decoder is
duke@0 39 // not required to take any action.
duke@0 40 #define GIF_DISPOSE_LEAVE 1 // Do not dispose. The graphic is to be left
duke@0 41 // in place.
duke@0 42 #define GIF_DISPOSE_BACKGND 2 // Restore to background color. The area used by the
duke@0 43 // graphic must be restored to the background color.
duke@0 44
duke@0 45 #define GIF_DISPOSE_RESTORE 3 // Restore to previous. The decoder is required to
duke@0 46 // restore the area overwritten by the graphic with
duke@0 47 // what was there prior to rendering the graphic.
duke@0 48
duke@0 49 static const char szNetscape20ext[11] = "NETSCAPE2.0";
duke@0 50
duke@0 51 #define NSEXT_LOOP 0x01 // Loop Count field code
duke@0 52
duke@0 53 // convert libungif samples to our ones
art@2859 54 #define MAKE_QUAD_GIF(c,a) MAKE_QUAD((c).Red, (c).Green, (c).Blue, (unsigned)(a))
duke@0 55
duke@0 56 /* stdio FILE* and memory input functions for libungif */
duke@0 57 int
duke@0 58 SplashStreamGifInputFunc(GifFileType * gif, GifByteType * buf, int n)
duke@0 59 {
duke@0 60 SplashStream* io = (SplashStream*)gif->UserData;
duke@0 61 int rc = io->read(io, buf, n);
duke@0 62 return rc;
duke@0 63 }
duke@0 64
bae@1118 65 /* These macro help to ensure that we only take part of frame that fits into
bae@1118 66 logical screen. */
bae@1118 67
bae@1118 68 /* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
bae@1118 69 #define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
bae@1118 70 /* Ensures that line starting at point p does not exceed boundary pmax.
bae@1118 71 Returns fixed length (if fix is needed) */
bae@1118 72 #define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
bae@1118 73
duke@0 74 int
duke@0 75 SplashDecodeGif(Splash * splash, GifFileType * gif)
duke@0 76 {
duke@0 77 int stride;
duke@0 78 int bufferSize;
duke@0 79 byte_t *pBitmapBits, *pOldBitmapBits;
duke@0 80 int i, j;
duke@0 81 int imageIndex;
bae@1118 82 int cx, cy, cw, ch; /* clamped coordinates */
duke@0 83 const int interlacedOffset[] = { 0, 4, 2, 1, 0 }; /* The way Interlaced image should. */
duke@0 84 const int interlacedJumps[] = { 8, 8, 4, 2, 1 }; /* be read - offsets and jumps... */
duke@0 85
duke@0 86 if (DGifSlurp(gif) == GIF_ERROR) {
duke@0 87 return 0;
duke@0 88 }
duke@0 89
duke@0 90 SplashCleanup(splash);
duke@0 91
bae@1118 92 if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
bae@1118 93 return 0;
bae@1118 94 }
duke@0 95 stride = gif->SWidth * splash->imageFormat.depthBytes;
duke@0 96 if (splash->byteAlignment > 1)
duke@0 97 stride =
duke@0 98 (stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
duke@0 99
bae@1118 100 if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
bae@1118 101 return 0;
bae@1118 102 }
bae@1118 103
bae@1118 104 if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {
bae@1118 105 return 0;
bae@1118 106 }
duke@0 107 bufferSize = stride * gif->SHeight;
duke@0 108 pBitmapBits = (byte_t *) malloc(bufferSize);
bae@1118 109 if (!pBitmapBits) {
bae@1118 110 return 0;
bae@1118 111 }
duke@0 112 pOldBitmapBits = (byte_t *) malloc(bufferSize);
bae@1118 113 if (!pOldBitmapBits) {
bae@1118 114 free(pBitmapBits);
bae@1118 115 return 0;
bae@1118 116 }
duke@0 117 memset(pBitmapBits, 0, bufferSize);
duke@0 118
duke@0 119 splash->width = gif->SWidth;
duke@0 120 splash->height = gif->SHeight;
duke@0 121 splash->frameCount = gif->ImageCount;
duke@0 122 splash->frames = (SplashImage *)
duke@0 123 malloc(sizeof(SplashImage) * gif->ImageCount);
bae@1118 124 if (!splash->frames) {
bae@1118 125 free(pBitmapBits);
bae@1118 126 free(pOldBitmapBits);
bae@1118 127 return 0;
bae@1118 128 }
duke@0 129 memset(splash->frames, 0, sizeof(SplashImage) * gif->ImageCount);
duke@0 130 splash->loopCount = 1;
duke@0 131
duke@0 132 for (imageIndex = 0; imageIndex < gif->ImageCount; imageIndex++) {
duke@0 133 SavedImage *image = &(gif->SavedImages[imageIndex]);
duke@0 134 GifImageDesc *desc = &(image->ImageDesc);
duke@0 135 ColorMapObject *colorMap =
duke@0 136 desc->ColorMap ? desc->ColorMap : gif->SColorMap;
duke@0 137
duke@0 138 int transparentColor = -1;
duke@0 139 int frameDelay = 100;
duke@0 140 int disposeMethod = GIF_DISPOSE_RESTORE;
duke@0 141 int colorCount = 0;
duke@0 142 rgbquad_t colorMapBuf[SPLASH_COLOR_MAP_SIZE];
duke@0 143
bae@1118 144 cx = FIX_POINT(desc->Left, 0, gif->SWidth);
bae@1118 145 cy = FIX_POINT(desc->Top, 0, gif->SHeight);
bae@1118 146 cw = FIX_LENGTH(desc->Left, desc->Width, gif->SWidth);
bae@1118 147 ch = FIX_LENGTH(desc->Top, desc->Height, gif->SHeight);
bae@1118 148
duke@0 149 if (colorMap) {
duke@0 150 if (colorMap->ColorCount <= SPLASH_COLOR_MAP_SIZE) {
duke@0 151 colorCount = colorMap->ColorCount;
duke@0 152 } else {
duke@0 153 colorCount = SPLASH_COLOR_MAP_SIZE;
duke@0 154 }
duke@0 155 }
duke@0 156
duke@0 157 /* the code below is loosely based around gif extension processing from win32 libungif sample */
duke@0 158
duke@0 159 for (i = 0; i < image->ExtensionBlockCount; i++) {
duke@0 160 byte_t *pExtension = (byte_t *) image->ExtensionBlocks[i].Bytes;
duke@0 161 unsigned size = image->ExtensionBlocks[i].ByteCount;
duke@0 162
duke@0 163 switch (image->ExtensionBlocks[i].Function) {
duke@0 164 case GRAPHICS_EXT_FUNC_CODE:
duke@0 165 {
duke@0 166 int flag = pExtension[0];
duke@0 167
art@2859 168 frameDelay = (((int)pExtension[2]) << 8) | pExtension[1];
duke@0 169 if (frameDelay < 10)
duke@0 170 frameDelay = 10;
duke@0 171 if (flag & GIF_TRANSPARENT) {
duke@0 172 transparentColor = pExtension[3];
duke@0 173 } else {
duke@0 174 transparentColor = GIF_NOT_TRANSPARENT;
duke@0 175 }
duke@0 176 disposeMethod =
duke@0 177 (flag >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK;
duke@0 178 break;
duke@0 179 }
duke@0 180 case APPLICATION_EXT_FUNC_CODE:
duke@0 181 {
duke@0 182 if (size == sizeof(szNetscape20ext)
duke@0 183 && memcmp(pExtension, szNetscape20ext, size) == 0) {
duke@0 184 int iSubCode;
duke@0 185
duke@0 186 if (++i >= image->ExtensionBlockCount)
duke@0 187 break;
duke@0 188 pExtension = (byte_t *) image->ExtensionBlocks[i].Bytes;
duke@0 189 if (image->ExtensionBlocks[i].ByteCount != 3)
duke@0 190 break;
duke@0 191 iSubCode = pExtension[0] & 0x07;
duke@0 192 if (iSubCode == NSEXT_LOOP) {
duke@0 193 splash->loopCount =
art@2859 194 (pExtension[1] | (((int)pExtension[2]) << 8)) - 1;
duke@0 195 }
duke@0 196 }
duke@0 197 break;
duke@0 198 }
duke@0 199 default:
duke@0 200 break;
duke@0 201 }
duke@0 202 }
duke@0 203
duke@0 204 if (colorMap) {
duke@0 205 for (i = 0; i < colorCount; i++) {
duke@0 206 colorMapBuf[i] = MAKE_QUAD_GIF(colorMap->Colors[i], 0xff);
duke@0 207 }
duke@0 208 }
duke@0 209 {
duke@0 210
duke@0 211 byte_t *pSrc = image->RasterBits;
duke@0 212 ImageFormat srcFormat;
duke@0 213 ImageRect srcRect, dstRect;
duke@0 214 int pass, npass;
duke@0 215
duke@0 216 if (desc->Interlace) {
duke@0 217 pass = 0;
duke@0 218 npass = 4;
duke@0 219 }
duke@0 220 else {
duke@0 221 pass = 4;
duke@0 222 npass = 5;
duke@0 223 }
duke@0 224
duke@0 225 srcFormat.colorMap = colorMapBuf;
duke@0 226 srcFormat.depthBytes = 1;
duke@0 227 srcFormat.byteOrder = BYTE_ORDER_NATIVE;
duke@0 228 srcFormat.transparentColor = transparentColor;
duke@0 229 srcFormat.fixedBits = QUAD_ALPHA_MASK; // fixed 100% alpha
duke@0 230 srcFormat.premultiplied = 0;
duke@0 231
duke@0 232 for (; pass < npass; ++pass) {
duke@0 233 int jump = interlacedJumps[pass];
duke@0 234 int ofs = interlacedOffset[pass];
bae@1118 235 /* Number of source lines for current pass */
bae@1118 236 int numPassLines = (desc->Height + jump - ofs - 1) / jump;
bae@1118 237 /* Number of lines that fits to dest buffer */
bae@1118 238 int numLines = (ch + jump - ofs - 1) / jump;
duke@0 239
duke@0 240 initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
duke@0 241 desc->Width, pSrc, &srcFormat);
bae@1118 242
bae@1118 243 if (numLines > 0) {
bae@1118 244 initRect(&dstRect, cx, cy + ofs, cw,
bae@1118 245 numLines , jump, stride, pBitmapBits, &splash->imageFormat);
bae@1118 246
bae@1118 247 pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
bae@1118 248 }
bae@1118 249 // skip extra source data
bae@1118 250 pSrc += (numPassLines - numLines) * srcRect.stride;
duke@0 251 }
duke@0 252 }
duke@0 253
duke@0 254 // now dispose of the previous frame correctly
duke@0 255
duke@0 256 splash->frames[imageIndex].bitmapBits =
duke@0 257 (rgbquad_t *) malloc(bufferSize);
bae@1118 258 if (!splash->frames[imageIndex].bitmapBits) {
bae@1118 259 free(pBitmapBits);
bae@1118 260 free(pOldBitmapBits);
bae@1118 261 /* Assuming that callee will take care of splash frames we have already allocated */
bae@1118 262 return 0;
bae@1118 263 }
duke@0 264 memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
duke@0 265
duke@0 266 SplashInitFrameShape(splash, imageIndex);
duke@0 267
duke@0 268 splash->frames[imageIndex].delay = frameDelay * 10; // 100ths of second to milliseconds
duke@0 269 switch (disposeMethod) {
duke@0 270 case GIF_DISPOSE_LEAVE:
duke@0 271 memcpy(pOldBitmapBits, pBitmapBits, bufferSize);
duke@0 272 break;
duke@0 273 case GIF_DISPOSE_NONE:
duke@0 274 break;
duke@0 275 case GIF_DISPOSE_BACKGND:
duke@0 276 {
duke@0 277 ImageRect dstRect;
duke@0 278 rgbquad_t fillColor = 0; // 0 is transparent
bae@1118 279
bae@2846 280 if (transparentColor < 0) {
duke@0 281 fillColor= MAKE_QUAD_GIF(
duke@0 282 colorMap->Colors[gif->SBackGroundColor], 0xff);
duke@0 283 }
bae@1118 284 initRect(&dstRect,
bae@1118 285 cx, cy, cw, ch,
bae@1118 286 1, stride,
bae@1118 287 pBitmapBits, &splash->imageFormat);
duke@0 288 fillRect(fillColor, &dstRect);
duke@0 289 }
duke@0 290 break;
duke@0 291 case GIF_DISPOSE_RESTORE:
duke@0 292 {
bae@1118 293 int lineSize = cw * splash->imageFormat.depthBytes;
bae@1118 294 if (lineSize > 0) {
bae@1118 295 int lineOffset = cx * splash->imageFormat.depthBytes;
bae@1118 296 int lineIndex = cy * stride + lineOffset;
bae@1118 297 for (j=0; j<ch; j++) {
bae@1118 298 memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
bae@1118 299 lineSize);
bae@1118 300 lineIndex += stride;
bae@1118 301 }
duke@0 302 }
duke@0 303 }
duke@0 304 break;
duke@0 305 }
duke@0 306 }
duke@0 307
duke@0 308 free(pBitmapBits);
duke@0 309 free(pOldBitmapBits);
duke@0 310
duke@0 311 DGifCloseFile(gif);
duke@0 312
duke@0 313 return 1;
duke@0 314 }
duke@0 315
duke@0 316 int
duke@0 317 SplashDecodeGifStream(Splash * splash, SplashStream * stream)
duke@0 318 {
duke@0 319 GifFileType *gif = DGifOpen((void *) stream, SplashStreamGifInputFunc);
duke@0 320
duke@0 321 if (!gif)
duke@0 322 return 0;
duke@0 323 return SplashDecodeGif(splash, gif);
duke@0 324 }