Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/awt/splashscreen/splashscreen_impl.c
38918 views
/*1* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "splashscreen_impl.h"26#include "splashscreen_gfx_impl.h"2728int splashIsVisible = 0;2930Splash *31SplashGetInstance()32{33static Splash splash;34static int preInitialized = 0;35if (!preInitialized) {36memset(&splash, 0, sizeof(Splash));37splash.currentFrame = -1;38preInitialized = 1;39}40return &splash;41}4243SPLASHEXPORT void44SplashSetFileJarName(const char* fileName, const char* jarName) {45Splash *splash = SplashGetInstance();4647free(splash->fileName);48splash->fileName = SplashConvertStringAlloc(fileName, &splash->fileNameLen);4950free(splash->jarName);51splash->jarName = SplashConvertStringAlloc(jarName, &splash->jarNameLen);52}5354SPLASHEXPORT void55SplashInit()56{57Splash *splash = SplashGetInstance();5859memset(splash, 0, sizeof(Splash));60splash->currentFrame = -1;61splash->scaleFactor = 1;62initFormat(&splash->imageFormat, QUAD_RED_MASK, QUAD_GREEN_MASK,63QUAD_BLUE_MASK, QUAD_ALPHA_MASK);64SplashInitPlatform(splash);65}6667SPLASHEXPORT void68SplashClose()69{70Splash *splash = SplashGetInstance();7172if (splash->isVisible > 0) {73SplashLock(splash);74splash->isVisible = -1;75SplashClosePlatform(splash);76SplashUnlock(splash);77}78}7980void81SplashCleanup(Splash * splash)82{83int i;8485splash->currentFrame = -1;86SplashCleanupPlatform(splash);87if (splash->frames) {88for (i = 0; i < splash->frameCount; i++) {89if (splash->frames[i].bitmapBits) {90free(splash->frames[i].bitmapBits);91splash->frames[i].bitmapBits = NULL;92}93}94free(splash->frames);95splash->frames = NULL;96}97if (splash->overlayData) {98free(splash->overlayData);99splash->overlayData = NULL;100}101SplashSetFileJarName(NULL, NULL);102}103104SPLASHEXPORT void105SplashSetScaleFactor(float scaleFactor)106{107Splash *splash = SplashGetInstance();108splash->scaleFactor = scaleFactor;109}110111void112SplashDone(Splash * splash)113{114SplashCleanup(splash);115SplashDonePlatform(splash);116}117118int119SplashIsStillLooping(Splash * splash)120{121if (splash->currentFrame < 0) {122return 0;123}124return splash->loopCount != 1 ||125splash->currentFrame + 1 < splash->frameCount;126}127128void129SplashUpdateScreenData(Splash * splash)130{131ImageRect srcRect, dstRect;132if (splash->currentFrame < 0) {133return;134}135136initRect(&srcRect, 0, 0, splash->width, splash->height, 1,137splash->width * sizeof(rgbquad_t),138splash->frames[splash->currentFrame].bitmapBits, &splash->imageFormat);139if (splash->screenData) {140free(splash->screenData);141}142splash->screenStride = splash->width * splash->screenFormat.depthBytes;143if (splash->byteAlignment > 1) {144splash->screenStride =145(splash->screenStride + splash->byteAlignment - 1) &146~(splash->byteAlignment - 1);147}148splash->screenData = malloc(splash->height * splash->screenStride);149initRect(&dstRect, 0, 0, splash->width, splash->height, 1,150splash->screenStride, splash->screenData, &splash->screenFormat);151if (splash->overlayData) {152convertRect2(&srcRect, &dstRect, CVT_BLEND, &splash->overlayRect);153}154else {155convertRect(&srcRect, &dstRect, CVT_COPY);156}157}158159void160SplashNextFrame(Splash * splash)161{162if (splash->currentFrame < 0) {163return;164}165do {166if (!SplashIsStillLooping(splash)) {167return;168}169splash->time += splash->frames[splash->currentFrame].delay;170if (++splash->currentFrame >= splash->frameCount) {171splash->currentFrame = 0;172if (splash->loopCount > 0) {173splash->loopCount--;174}175}176} while (splash->time + splash->frames[splash->currentFrame].delay -177SplashTime() <= 0);178}179180int181BitmapToYXBandedRectangles(ImageRect * pSrcRect, RECT_T * out)182{183RECT_T *pPrevLine = NULL, *pFirst = out, *pThis = pFirst;184int i, j, i0;185int length;186187for (j = 0; j < pSrcRect->numLines; j++) {188189/* generate data for a scanline */190191byte_t *pSrc = (byte_t *) pSrcRect->pBits + j * pSrcRect->stride;192RECT_T *pLine = pThis;193194i = 0;195196do {197while (i < pSrcRect->numSamples &&198getRGBA(pSrc, pSrcRect->format) < ALPHA_THRESHOLD) {199pSrc += pSrcRect->depthBytes;200++i;201}202if (i >= pSrcRect->numSamples) {203break;204}205i0 = i;206while (i < pSrcRect->numSamples &&207getRGBA(pSrc, pSrcRect->format) >= ALPHA_THRESHOLD) {208pSrc += pSrcRect->depthBytes;209++i;210}211RECT_SET(*pThis, i0, j, i - i0, 1);212++pThis;213} while (i < pSrcRect->numSamples);214215/* check if the previous scanline is exactly the same, merge if so216(this is the only optimization we can use for YXBanded rectangles, and win32 supports217YXBanded only */218219length = pThis - pLine;220if (pPrevLine && pLine - pPrevLine == length) {221for (i = 0; i < length && RECT_EQ_X(pPrevLine[i], pLine[i]); ++i) {222}223if (i == pLine - pPrevLine) {224// do merge225for (i = 0; i < length; i++) {226RECT_INC_HEIGHT(pPrevLine[i]);227}228pThis = pLine;229continue;230}231}232/* or else use the generated scanline */233234pPrevLine = pLine;235}236return pThis - pFirst;237}238239typedef struct FILEFORMAT240{241int sign;242int (*decodeStream) (Splash * splash, SplashStream * stream);243} FILEFORMAT;244245static const FILEFORMAT formats[] = {246{0x47, SplashDecodeGifStream},247{0x89, SplashDecodePngStream},248{0xFF, SplashDecodeJpegStream}249};250251static int252SplashLoadStream(SplashStream * stream)253{254int success = 0;255int c;256size_t i;257258Splash *splash = SplashGetInstance();259if (splash->isVisible < 0) {260return 0;261}262263SplashLock(splash);264265/* the formats we support can be easily distinguished by the first byte */266c = stream->peek(stream);267if (c != -1) {268for (i = 0; i < sizeof(formats) / sizeof(FILEFORMAT); i++) {269if (c == formats[i].sign) {270success = formats[i].decodeStream(splash, stream);271break;272}273}274}275stream->close(stream);276277if (!success) { // failed to decode278if (splash->isVisible == 0) {279SplashCleanup(splash);280}281SplashUnlock(splash); // SplashClose locks282if (splash->isVisible == 0) {283SplashClose();284}285}286else {287splash->currentFrame = 0;288if (splash->isVisible == 0) {289SplashStart(splash);290} else {291SplashReconfigure(splash);292splash->time = SplashTime();293}294SplashUnlock(splash);295}296return success;297}298299SPLASHEXPORT int300SplashLoadFile(const char *filename)301{302SplashStream stream;303return SplashStreamInitFile(&stream, filename) &&304SplashLoadStream(&stream);305}306307SPLASHEXPORT int308SplashLoadMemory(void *data, int size)309{310SplashStream stream;311return SplashStreamInitMemory(&stream, data, size) &&312SplashLoadStream(&stream);313}314315/* SplashStart MUST be called from under the lock */316317void318SplashStart(Splash * splash)319{320if (splash->isVisible == 0) {321SplashCreateThread(splash);322splash->isVisible = 1;323}324}325326/* SplashStream functions */327328static int readFile(void* pStream, void* pData, int nBytes) {329FILE* f = ((SplashStream*)pStream)->arg.stdio.f;330return fread(pData, 1, nBytes, f);331}332static int peekFile(void* pStream) {333FILE* f = ((SplashStream*)pStream)->arg.stdio.f;334int c = fgetc(f);335if (c != EOF) {336ungetc(c, f);337return c;338} else {339return -1;340}341}342343static void closeFile(void* pStream) {344FILE* f = ((SplashStream*)pStream)->arg.stdio.f;345fclose(f);346}347348static int readMem(void* pStream, void* pData, int nBytes) {349unsigned char* pSrc = (unsigned char*)(((SplashStream*)pStream)->arg.mem.pData);350unsigned char* pSrcEnd = (unsigned char*)(((SplashStream*)pStream)->arg.mem.pDataEnd);351if (nBytes > pSrcEnd - pSrc) {352nBytes = pSrcEnd - pSrc;353}354if (nBytes>0) {355memcpy(pData, pSrc, nBytes);356pSrc += nBytes;357((SplashStream*)pStream)->arg.mem.pData = (void*)pSrc;358}359return nBytes;360}361362static int peekMem(void* pStream) {363unsigned char* pSrc = (unsigned char*)(((SplashStream*)pStream)->arg.mem.pData);364unsigned char* pSrcEnd = (unsigned char*)(((SplashStream*)pStream)->arg.mem.pDataEnd);365if (pSrc >= pSrcEnd) {366return -1;367} else {368return (int)*pSrc;369}370}371372static void closeMem(void* pStream) {373}374375int SplashStreamInitFile(SplashStream * pStream, const char* filename) {376pStream->arg.stdio.f = fopen(filename, "rb");377pStream->read = readFile;378pStream->peek = peekFile;379pStream->close = closeFile;380return pStream->arg.stdio.f != 0;381}382383int SplashStreamInitMemory(SplashStream * pStream, void* pData, int size) {384pStream->arg.mem.pData = (unsigned char*)pData;385pStream->arg.mem.pDataEnd = (unsigned char*)pData + size;386pStream->read = readMem;387pStream->peek = peekMem;388pStream->close = closeMem;389return 1;390}391392393