imagecache.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 577 行 · 第 1/2 页
C
577 行
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include <string.h>#include <kni.h>#include <midpError.h>#include <midpMalloc.h>#include <midpServices.h>#include <midpStorage.h>#include <midpJar.h>#include <suitestore_task_manager.h>#include <midp_constants_data.h>#include <img_image.h>#include <midpUtilKni.h>/** * @file * * Implements a cache for native images. * <p> * All images are loaded from the Jar file, converted to the native platform * representation, and stored as files. When an ImmutableImage is created then * loadCachedImage() is called to check if that particular image has been * cached, and if yes the native representation is loaded from the file. This * significantly reduce the time spent instantiating an ImmutableImage. * <p> * Each cached image is stored with the following naming conventions: * <blockquote> * <suite Id><image resource name>".tmp" * </blockquote> * All cache files are deleted when a suite is updated or removed. * <p> * This implementation contains a simple method for preventing cached images * to grab too much storage space: If the remaining space is below * IMAGE_CACHE_THRESHOLD or the last cached image couldn't be saved due * to lack of space, then the creating of the cache for this suite is * aborted and all already created files are deleted. This is not an * ideal approach, but should be sufficient for now. * <p> * Note: Currently, only images ending with ".png" or ".PNG" are supported. *//** * Holds the suite ID. It is initialized during createImageCache() call * and used in png_cache_action() to avoid passing an additional parameter to it * because this function is called for each image entry in the suite's jar file. */static SuiteIdType globalSuiteId;/** * Holds the storage ID where the cached images will be saved. It is initialized * during createImageCache() call and used in png_cache_action() to avoid * passing an additional parameter to it. */static StorageIdType globalStorageId;/** * Handle to the opened jar file with the midlet suite. It is used to * passing an additional parameter to png_cache_action(). */static void *handle;/** * Holds the amount of free space in the storage. It is initialized during * createImageCache() call and used in png_cache_action() to avoid passing * an additional parameter to it. */static jlong remainingSpace;/** * Holds the amount of cached data placed into the storage. It is initialized * during createImageCache() call and used in png_cache_action() to avoid * passing an additional parameter to it. */static long cachedDataSize;PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_START(PNG_EXT1) {'.', 'p', 'n', 'g', '\0'}PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_END(PNG_EXT1);PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_START(PNG_EXT2) {'.', 'P', 'N', 'G', '\0'}PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_END(PNG_EXT2);/* Forward declaration */static int storeImageToCache(SuiteIdType suiteId, StorageIdType storageId, const pcsl_string * resName, unsigned char *bufPtr, int len);/** * Tests if JAR entry is a PNG image, by name extension */static jboolean png_filter(const pcsl_string * entry) { if (pcsl_string_ends_with(entry, &PNG_EXT1) || pcsl_string_ends_with(entry, &PNG_EXT2)) { return KNI_TRUE; } return KNI_FALSE;}/** * Loads PNG image from JAR, decodes it and writes as native */static jboolean png_cache_action(const pcsl_string * entry) { unsigned char *pngBufPtr = NULL; unsigned int pngBufLen = 0; unsigned char *nativeBufPtr = NULL; unsigned int nativeBufLen = 0; jboolean status = KNI_FALSE; do { pngBufLen = midpGetJarEntry(handle, entry, &pngBufPtr); if (img_decode_data2cache(pngBufPtr, pngBufLen, &nativeBufPtr, &nativeBufLen) != MIDP_ERROR_NONE) { break; } /* Check if we can store this file in the remaining storage space */ if (remainingSpace - IMAGE_CACHE_THRESHOLD < (long)nativeBufLen) { break; } /* write native buffer to persistent store */ status = storeImageToCache(globalSuiteId, globalStorageId, entry, nativeBufPtr, nativeBufLen); } while (0); if (status == 1) { remainingSpace -= nativeBufLen; cachedDataSize += nativeBufLen; } if (nativeBufPtr != NULL) { midpFree(nativeBufPtr); } if (pngBufPtr != NULL) { midpFree(pngBufPtr); } return status;}/** * Iterates over all images in a jar, and tries to load and cached them. * * @param jarFileName The name of the jar file * @param filter Pointer to filter function * @param action Pointer to action function * @return 1 if all was successful, <= 0 if some error */static int loadAndCacheJarFileEntries(const pcsl_string * jarFileName, jboolean (*filter)(const pcsl_string *), jboolean (*action)(const pcsl_string *)) { int error = 0; int status = 0; handle = midpOpenJar(&error, jarFileName); if (error) { REPORT_WARN1(LC_LOWUI, "Warning: could not open image cached; Error: %d\n", error); handle = NULL; return status; } status = midpIterateJarEntries(handle, filter, action); midpCloseJar(handle); handle = NULL; return status;}/** * Remove all the cached images associated with a suite. * * @param suiteId Suite ID * @param storageId ID of the storage where to create the cache*/static void deleteImageCache(SuiteIdType suiteId, StorageIdType storageId) { pcsl_string root; pcsl_string filename; char* pszError; void* handle = NULL; jint errorCode; if (suiteId == UNUSED_SUITE_ID) { return; } errorCode = midp_suite_get_cached_resource_filename(suiteId, storageId, &PCSL_STRING_EMPTY, &root); if (errorCode != MIDP_ERROR_NONE) { return; } handle = storage_open_file_iterator(&root); if (handle == NULL) { pcsl_string_free(&root); return; } /* Delete all files that start with suite Id and end with TMP_EXT */ for (;;) { if (0 != storage_get_next_file_in_iterator(&root, handle, &filename)) { break; } if (pcsl_string_ends_with(&filename, &TMP_EXT)) { storage_delete_file(&pszError, &filename); if (pszError != NULL) { storageFreeError(pszError); } } pcsl_string_free(&filename); } storageCloseFileIterator(handle); pcsl_string_free(&root);}/** * Creates a cache of natives images by iterating over all png images in the jar * file, loading each one, decoding it into native, and caching it persistent * store. * * @param suiteId The suite ID * @param storageId ID of the storage where to create the cache * @param pOutDataSize [out] points to a place where the size of the * written data is saved; can be NULL */void createImageCache(SuiteIdType suiteId, StorageIdType storageId, jint* pOutDataSize) { pcsl_string jarFileName; int result; jint errorCode; if (suiteId == UNUSED_SUITE_ID) { return; } /* * This makes the code non-reentrant and unsafe for threads, * but that is ok */ globalSuiteId = suiteId; globalStorageId = storageId; cachedDataSize = 0; /* * First, blow away any existing cache. Note: when a suite is * removed, midp_remove_suite() removes all files associated with * a suite, including the cache, so we don't have to do it * explicitly. */ deleteImageCache(suiteId, storageId);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?