Beispiel #1
0
void testWeakCache() {
    WeakCache<std::string, CacheTestRef> cache;

    debugAssert(CacheTest::count == 0);
    CacheTestRef x = new CacheTest();
    debugAssert(CacheTest::count == 1);

    cache.set("x", x);
    debugAssert(CacheTest::count == 1);
    CacheTestRef y = new CacheTest();
    CacheTestRef z = new CacheTest();
    debugAssert(CacheTest::count == 3);
    
    cache.set("y", y);
    
    debugAssert(cache["x"] == x);
    debugAssert(cache["y"] == y);
    debugAssert(cache["q"].isNull());
    
    x = NULL;
    debugAssert(CacheTest::count == 2);
    debugAssert(cache["x"].isNull());

    cache.set("y", z);
    y = NULL;
    debugAssert(cache["y"] == z);

    cache.remove("y");
}
Beispiel #2
0
shared_ptr<IconSet> IconSet::fromFile(const std::string& filename) {
    shared_ptr<IconSet> set = cache[filename];
    if (notNull(set)) {
        return set;
    }

    BinaryInput b(filename, G3D_LITTLE_ENDIAN);
    
    const std::string& header = b.readString();
    alwaysAssertM(header == "ICON", "Corrupt icon file");
    
    const float version = b.readFloat32();
    alwaysAssertM(version == 1.0f, "Unsupported icon file version");

    shared_ptr<IconSet> s(new IconSet());

    s->m_icon.resize(b.readInt32());
    for (int i = 0; i < s->m_icon.size(); ++i) {
        Entry& e = s->m_icon[i];
        e.filename = b.readString32();
        float x, y, w, h;
        x = b.readFloat32();
        y = b.readFloat32();
        w = b.readFloat32();
        h = b.readFloat32();
        e.rect = Rect2D::xywh(x, y, w, h);
        s->m_index.set(e.filename, i);
    }

    shared_ptr<Image> image = Image::fromBinaryInput(b);
    Texture::Settings settings;
    settings.wrapMode = WrapMode::CLAMP;
    settings.interpolateMode = Texture::BILINEAR_NO_MIPMAP;
    s->m_texture = Texture::fromPixelTransferBuffer(filename, image->toPixelTransferBuffer(), ImageFormat::AUTO(), Texture::DIM_2D_NPOT, settings);

    cache.set(filename, s);
    return s;
}
Beispiel #3
0
namespace G3D {

static WeakCache<String, shared_ptr<IconSet> > cache;

shared_ptr<IconSet> IconSet::fromFile(const String& filename) {
    shared_ptr<IconSet> set = cache[filename];
    if (notNull(set)) {
        return set;
    }

    BinaryInput b(filename, G3D_LITTLE_ENDIAN);
    
    const String& header = b.readString();
    alwaysAssertM(header == "ICON", "Corrupt icon file");
    
    const float version = b.readFloat32();
    alwaysAssertM(version == 1.0f, "Unsupported icon file version");

    shared_ptr<IconSet> s(new IconSet());

    s->m_icon.resize(b.readInt32());
    for (int i = 0; i < s->m_icon.size(); ++i) {
        Entry& e = s->m_icon[i];
        e.filename = b.readString32();
        float x, y, w, h;
        x = b.readFloat32();
        y = b.readFloat32();
        w = b.readFloat32();
        h = b.readFloat32();
        e.rect = Rect2D::xywh(x, y, w, h);
        s->m_index.set(e.filename, i);
    }

    shared_ptr<Image> image = Image::fromBinaryInput(b);
    bool generateMipMaps = true;
    s->m_texture = Texture::fromPixelTransferBuffer(filename, image->toPixelTransferBuffer(), ImageFormat::AUTO(), Texture::DIM_2D, generateMipMaps);

    cache.set(filename, s);
    return s;
}


void IconSet::findImages(const String& baseDir, const String& sourceDir, Array<Source>& sourceArray) {
    Array<String> filenameArray;
    FileSystem::getFiles(pathConcat(pathConcat(baseDir, sourceDir), "*"), filenameArray);
    for (int i = 0; i < filenameArray.size(); ++i) {
        if (Image::fileSupported(filenameArray[i])) {
            String f = pathConcat(sourceDir, filenameArray[i]);
            shared_ptr<Image> im = Image::fromFile(pathConcat(baseDir, f));
            Source& s = sourceArray.next();
            s.filename = f;
            s.width    = im->width();
            s.height   = im->height();
            // todo (Image upgrade): find replacement calculation for channels
            //s.channels = im.channels;
        }
    }

    Array<String> dirArray;
    FileSystem::getDirectories(pathConcat(pathConcat(baseDir, sourceDir), "*"), dirArray);
    for (int i = 0; i < dirArray.size(); ++i) {
        if (dirArray[i] != ".svn" && dirArray[i] != "CVS") {
            findImages(baseDir, pathConcat(sourceDir, dirArray[i]), sourceArray);
        }
    }
}


void IconSet::makeIconSet(const String& baseDir, const String& outFile) {
    /* todo (Image upgrade): find replacement calculation for channels
    // Find all images
    Array<Source> sourceArray;
    findImages(baseDir, "", sourceArray);
   
    // See if we can fit everything in one row
    int maxWidth = 0;
    int minHeight = 0;
    int maxChannels = 0;
    for (int i = 0; i < sourceArray.size(); ++i) {
        maxWidth += sourceArray[i].width;
        minHeight = max(minHeight, sourceArray[i].height);
        maxChannels = max(maxChannels, sourceArray[i].channels);
    }

    int width = min(maxWidth, 1024);

    // Round to the nearest multiple of 4 pixels; PNG and textures
    // like this sizing.
    width = (width / 4) * 4;
    
    // Given our width, walk through on a pretend allocation to see
    // how much space we need. 

    // Current row width
    int w = 0;

    // Current row height
    int h = 0;

    // Full image height
    int height = 0;
    for (int i = 0; i < sourceArray.size(); ++i) {
        // Walk until we hit the end of the row
        const Source& s = sourceArray[i];
        if (s.width + w > width) {
            // Start the next row
            height += h;
            w = 0;
            h = 0;
        }

        // Add this icon
        w += s.width;
        h = max(h, s.height);
    }
    height += h;

    alwaysAssertM(height < 1024, "Height must be less than 1024");

    BinaryOutput b(outFile, G3D_LITTLE_ENDIAN);

    // Write the header
    b.writeString("ICON");
    b.writeFloat32(1.0f);
    b.writeInt32(sourceArray.size());

    GImage packed(width, height, maxChannels);
    w = 0; h = 0;
    int y = 0;
    for (int i = 0; i < sourceArray.size(); ++i) {
        // Walk until we hit the end of the row
        const Source& s = sourceArray[i];
        if (s.width + w > width) {
            // Start the next row
            y += h;
            w = 0;
            h = 0;
        }

        b.writeString32(s.filename);
        b.writeFloat32(w);
        b.writeFloat32(y);
        b.writeFloat32(s.width);
        b.writeFloat32(s.height);

        GImage src;
        if (s.channels == maxChannels) {
            src.load(pathConcat(baseDir, s.filename));
        } else {
            // Need to expand the number of channels
            GImage tmp(pathConcat(baseDir, s.filename));
            src.resize(tmp.width(), tmp.height(), maxChannels);
            if (maxChannels == 4) {
                if (tmp.channels() == 1) {
                    GImage::LtoRGBA((unorm8*)tmp.byte(), (unorm8*)src.byte(), tmp.width() * tmp.height());
                } else if (tmp.channels() == 3) {
                    GImage::RGBtoRGBA((unorm8*)tmp.byte(), (unorm8*)src.byte(), tmp.width() * tmp.height());
                }
            } else {
                debugAssert(maxChannels == 3 && tmp.channels() == 1);
                GImage::LtoRGB((unorm8*)tmp.byte(), (unorm8*)src.byte(), tmp.width() * tmp.height());
            }
        }
        
        // Paste into the packed image
        GImage::copyRect(packed, src, w, y, 0, 0, src.width(), src.height());

        w += s.width;
        h = max(h, s.height);
    }

    packed.encode(GImage::PNG, b);

    b.commit();
    */
}


int IconSet::getIndex(const String& s) const {
    const int* i = m_index.getPointer(s);
        
    if (notNull(i)) {
        return *i;
    } else {
        debugAssertM(notNull(i), format("Icon \"%s\" not found.", s.c_str()));
        return 0;
    }
}


Icon IconSet::get(int index) const {
    Icon icon(m_texture, m_icon[index].rect);
    icon.m_keepAlive = dynamic_pointer_cast<IconSet>(const_cast<IconSet*>(this)->shared_from_this());
    return icon;
}

}