PageRenderTime 63ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/src/share/native/sun/awt/splashscreen/splashscreen_gif.c

https://bitbucket.org/adoptopenjdk/jdk8-jdk
C | 326 lines | 237 code | 47 blank | 42 comment | 39 complexity | 20c18f5b30b31bc6f5cf9c2eb4ba173b MD5 | raw file
Possible License(s): LGPL-3.0, GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, BSD-3-Clause
  1. /*
  2. * Copyright (c) 2005, 2013, 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. #include "splashscreen_impl.h"
  26. #include "splashscreen_gfx.h"
  27. #include <gif_lib.h>
  28. #include "sizecalc.h"
  29. #define GIF_TRANSPARENT 0x01
  30. #define GIF_USER_INPUT 0x02
  31. #define GIF_DISPOSE_MASK 0x07
  32. #define GIF_DISPOSE_SHIFT 2
  33. #define GIF_NOT_TRANSPARENT -1
  34. #define GIF_DISPOSE_NONE 0 // No disposal specified. The decoder is
  35. // not required to take any action.
  36. #define GIF_DISPOSE_LEAVE 1 // Do not dispose. The graphic is to be left
  37. // in place.
  38. #define GIF_DISPOSE_BACKGND 2 // Restore to background color. The area used by the
  39. // graphic must be restored to the background color.
  40. #define GIF_DISPOSE_RESTORE 3 // Restore to previous. The decoder is required to
  41. // restore the area overwritten by the graphic with
  42. // what was there prior to rendering the graphic.
  43. static const char szNetscape20ext[11] = "NETSCAPE2.0";
  44. #define NSEXT_LOOP 0x01 // Loop Count field code
  45. // convert libungif samples to our ones
  46. #define MAKE_QUAD_GIF(c,a) MAKE_QUAD((c).Red, (c).Green, (c).Blue, (unsigned)(a))
  47. /* stdio FILE* and memory input functions for libungif */
  48. int
  49. SplashStreamGifInputFunc(GifFileType * gif, GifByteType * buf, int n)
  50. {
  51. SplashStream* io = (SplashStream*)gif->UserData;
  52. int rc = io->read(io, buf, n);
  53. return rc;
  54. }
  55. /* These macro help to ensure that we only take part of frame that fits into
  56. logical screen. */
  57. /* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
  58. #define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
  59. /* Ensures that line starting at point p does not exceed boundary pmax.
  60. Returns fixed length (if fix is needed) */
  61. #define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
  62. int
  63. SplashDecodeGif(Splash * splash, GifFileType * gif)
  64. {
  65. int stride;
  66. int bufferSize;
  67. byte_t *pBitmapBits, *pOldBitmapBits;
  68. int i, j;
  69. int imageIndex;
  70. int cx, cy, cw, ch; /* clamped coordinates */
  71. const int interlacedOffset[] = { 0, 4, 2, 1, 0 }; /* The way Interlaced image should. */
  72. const int interlacedJumps[] = { 8, 8, 4, 2, 1 }; /* be read - offsets and jumps... */
  73. if (DGifSlurp(gif) == GIF_ERROR) {
  74. return 0;
  75. }
  76. SplashCleanup(splash);
  77. if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
  78. return 0;
  79. }
  80. stride = gif->SWidth * splash->imageFormat.depthBytes;
  81. if (splash->byteAlignment > 1)
  82. stride =
  83. (stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
  84. if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
  85. return 0;
  86. }
  87. if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {
  88. return 0;
  89. }
  90. bufferSize = stride * gif->SHeight;
  91. pBitmapBits = (byte_t *) malloc(bufferSize);
  92. if (!pBitmapBits) {
  93. return 0;
  94. }
  95. pOldBitmapBits = (byte_t *) malloc(bufferSize);
  96. if (!pOldBitmapBits) {
  97. free(pBitmapBits);
  98. return 0;
  99. }
  100. memset(pBitmapBits, 0, bufferSize);
  101. splash->width = gif->SWidth;
  102. splash->height = gif->SHeight;
  103. splash->frameCount = gif->ImageCount;
  104. splash->frames = (SplashImage *)
  105. SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(SplashImage), gif->ImageCount);
  106. if (!splash->frames) {
  107. free(pBitmapBits);
  108. free(pOldBitmapBits);
  109. return 0;
  110. }
  111. memset(splash->frames, 0, sizeof(SplashImage) * gif->ImageCount);
  112. splash->loopCount = 1;
  113. for (imageIndex = 0; imageIndex < gif->ImageCount; imageIndex++) {
  114. SavedImage *image = &(gif->SavedImages[imageIndex]);
  115. GifImageDesc *desc = &(image->ImageDesc);
  116. ColorMapObject *colorMap =
  117. desc->ColorMap ? desc->ColorMap : gif->SColorMap;
  118. int transparentColor = -1;
  119. int frameDelay = 100;
  120. int disposeMethod = GIF_DISPOSE_RESTORE;
  121. int colorCount = 0;
  122. rgbquad_t colorMapBuf[SPLASH_COLOR_MAP_SIZE];
  123. cx = FIX_POINT(desc->Left, 0, gif->SWidth);
  124. cy = FIX_POINT(desc->Top, 0, gif->SHeight);
  125. cw = FIX_LENGTH(desc->Left, desc->Width, gif->SWidth);
  126. ch = FIX_LENGTH(desc->Top, desc->Height, gif->SHeight);
  127. if (colorMap) {
  128. if (colorMap->ColorCount <= SPLASH_COLOR_MAP_SIZE) {
  129. colorCount = colorMap->ColorCount;
  130. } else {
  131. colorCount = SPLASH_COLOR_MAP_SIZE;
  132. }
  133. }
  134. /* the code below is loosely based around gif extension processing from win32 libungif sample */
  135. for (i = 0; i < image->ExtensionBlockCount; i++) {
  136. byte_t *pExtension = (byte_t *) image->ExtensionBlocks[i].Bytes;
  137. unsigned size = image->ExtensionBlocks[i].ByteCount;
  138. switch (image->ExtensionBlocks[i].Function) {
  139. case GRAPHICS_EXT_FUNC_CODE:
  140. {
  141. int flag = pExtension[0];
  142. frameDelay = (((int)pExtension[2]) << 8) | pExtension[1];
  143. if (frameDelay < 10)
  144. frameDelay = 10;
  145. if (flag & GIF_TRANSPARENT) {
  146. transparentColor = pExtension[3];
  147. } else {
  148. transparentColor = GIF_NOT_TRANSPARENT;
  149. }
  150. disposeMethod =
  151. (flag >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK;
  152. break;
  153. }
  154. case APPLICATION_EXT_FUNC_CODE:
  155. {
  156. if (size == sizeof(szNetscape20ext)
  157. && memcmp(pExtension, szNetscape20ext, size) == 0) {
  158. int iSubCode;
  159. if (++i >= image->ExtensionBlockCount)
  160. break;
  161. pExtension = (byte_t *) image->ExtensionBlocks[i].Bytes;
  162. if (image->ExtensionBlocks[i].ByteCount != 3)
  163. break;
  164. iSubCode = pExtension[0] & 0x07;
  165. if (iSubCode == NSEXT_LOOP) {
  166. splash->loopCount =
  167. (pExtension[1] | (((int)pExtension[2]) << 8)) - 1;
  168. }
  169. }
  170. break;
  171. }
  172. default:
  173. break;
  174. }
  175. }
  176. if (colorMap) {
  177. for (i = 0; i < colorCount; i++) {
  178. colorMapBuf[i] = MAKE_QUAD_GIF(colorMap->Colors[i], 0xff);
  179. }
  180. }
  181. {
  182. byte_t *pSrc = image->RasterBits;
  183. ImageFormat srcFormat;
  184. ImageRect srcRect, dstRect;
  185. int pass, npass;
  186. if (desc->Interlace) {
  187. pass = 0;
  188. npass = 4;
  189. }
  190. else {
  191. pass = 4;
  192. npass = 5;
  193. }
  194. srcFormat.colorMap = colorMapBuf;
  195. srcFormat.depthBytes = 1;
  196. srcFormat.byteOrder = BYTE_ORDER_NATIVE;
  197. srcFormat.transparentColor = transparentColor;
  198. srcFormat.fixedBits = QUAD_ALPHA_MASK; // fixed 100% alpha
  199. srcFormat.premultiplied = 0;
  200. for (; pass < npass; ++pass) {
  201. int jump = interlacedJumps[pass];
  202. int ofs = interlacedOffset[pass];
  203. /* Number of source lines for current pass */
  204. int numPassLines = (desc->Height + jump - ofs - 1) / jump;
  205. /* Number of lines that fits to dest buffer */
  206. int numLines = (ch + jump - ofs - 1) / jump;
  207. initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
  208. desc->Width, pSrc, &srcFormat);
  209. if (numLines > 0) {
  210. initRect(&dstRect, cx, cy + ofs, cw,
  211. numLines , jump, stride, pBitmapBits, &splash->imageFormat);
  212. pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
  213. }
  214. // skip extra source data
  215. pSrc += (numPassLines - numLines) * srcRect.stride;
  216. }
  217. }
  218. // now dispose of the previous frame correctly
  219. splash->frames[imageIndex].bitmapBits =
  220. (rgbquad_t *) malloc(bufferSize); // bufferSize is safe (checked above)
  221. if (!splash->frames[imageIndex].bitmapBits) {
  222. free(pBitmapBits);
  223. free(pOldBitmapBits);
  224. /* Assuming that callee will take care of splash frames we have already allocated */
  225. return 0;
  226. }
  227. memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
  228. SplashInitFrameShape(splash, imageIndex);
  229. splash->frames[imageIndex].delay = frameDelay * 10; // 100ths of second to milliseconds
  230. switch (disposeMethod) {
  231. case GIF_DISPOSE_LEAVE:
  232. memcpy(pOldBitmapBits, pBitmapBits, bufferSize);
  233. break;
  234. case GIF_DISPOSE_NONE:
  235. break;
  236. case GIF_DISPOSE_BACKGND:
  237. {
  238. ImageRect dstRect;
  239. rgbquad_t fillColor = 0; // 0 is transparent
  240. if (transparentColor < 0) {
  241. fillColor= MAKE_QUAD_GIF(
  242. colorMap->Colors[gif->SBackGroundColor], 0xff);
  243. }
  244. initRect(&dstRect,
  245. cx, cy, cw, ch,
  246. 1, stride,
  247. pBitmapBits, &splash->imageFormat);
  248. fillRect(fillColor, &dstRect);
  249. }
  250. break;
  251. case GIF_DISPOSE_RESTORE:
  252. {
  253. int lineSize = cw * splash->imageFormat.depthBytes;
  254. if (lineSize > 0) {
  255. int lineOffset = cx * splash->imageFormat.depthBytes;
  256. int lineIndex = cy * stride + lineOffset;
  257. for (j=0; j<ch; j++) {
  258. memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
  259. lineSize);
  260. lineIndex += stride;
  261. }
  262. }
  263. }
  264. break;
  265. }
  266. }
  267. free(pBitmapBits);
  268. free(pOldBitmapBits);
  269. DGifCloseFile(gif);
  270. return 1;
  271. }
  272. int
  273. SplashDecodeGifStream(Splash * splash, SplashStream * stream)
  274. {
  275. GifFileType *gif = DGifOpen((void *) stream, SplashStreamGifInputFunc);
  276. if (!gif)
  277. return 0;
  278. return SplashDecodeGif(splash, gif);
  279. }