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 + -
显示快捷键?