TexturePtr TextureManager::loadTexture(std::stringstream& file) { TexturePtr texture; apng_data apng; if(load_apng(file, &apng) == 0) { Size imageSize(apng.width, apng.height); if(apng.num_frames > 1) { // animated texture std::vector<ImagePtr> frames; std::vector<int> framesDelay; for(uint i=0;i<apng.num_frames;++i) { uchar *frameData = apng.pdata + ((apng.first_frame+i) * imageSize.area() * apng.bpp); int frameDelay = apng.frames_delay[i]; framesDelay.push_back(frameDelay); frames.push_back(ImagePtr(new Image(imageSize, apng.bpp, frameData))); } AnimatedTexturePtr animatedTexture = new AnimatedTexture(imageSize, frames, framesDelay); m_animatedTextures.push_back(animatedTexture); texture = animatedTexture; } else { ImagePtr image = ImagePtr(new Image(imageSize, apng.bpp, apng.pdata)); texture = TexturePtr(new Texture(image)); } free_apng(&apng); } return texture; }
void X11Window::setMouseCursor(const std::string& file, const Point& hotSpot) { std::stringstream fin; g_resources.loadFile(file, fin); apng_data apng; if(load_apng(fin, &apng) != 0) { g_logger.traceError(stdext::format("unable to load png file %s", file)); return; } if(apng.bpp != 4) { g_logger.error("the cursor png must have 4 channels"); free_apng(&apng); return; } if(apng.width != 32|| apng.height != 32) { g_logger.error("the cursor png must have 32x32 dimension"); free_apng(&apng); return; } if(m_cursor != None) restoreMouseCursor(); int width = apng.width; int height = apng.height; int numbits = width * height; int numbytes = (width * height)/8; XColor bg, fg; bg.red = 255 << 8; bg.green = 255 << 8; bg.blue = 255 << 8; fg.red = 0; fg.green = 0; fg.blue = 0; std::vector<uchar> mapBits(numbytes, 0); std::vector<uchar> maskBits(numbytes, 0); for(int i=0;i<numbits;++i) { uint32 rgba = stdext::readLE32(apng.pdata + i*4); if(rgba == 0xffffffff) { //white, background LSB_BIT_SET(maskBits, i); } else if(rgba == 0xff000000) { //black, foreground LSB_BIT_SET(mapBits, i); LSB_BIT_SET(maskBits, i); } //otherwise 0x00000000 => alpha } free_apng(&apng); Pixmap cp = XCreateBitmapFromData(m_display, m_window, (char*)&mapBits[0], width, height); Pixmap mp = XCreateBitmapFromData(m_display, m_window, (char*)&maskBits[0], width, height); m_cursor = XCreatePixmapCursor(m_display, cp, mp, &fg, &bg, hotSpot.x, hotSpot.y); XDefineCursor(m_display, m_window, m_cursor); XFreePixmap(m_display, cp); XFreePixmap(m_display, mp); }
void X11Window::setIcon(const std::string& iconFile) { std::stringstream fin; g_resources.loadFile(iconFile, fin); apng_data apng; if(load_apng(fin, &apng) != 0) { g_logger.error("Unable to load window icon"); return; } if(apng.bpp != 4) { g_logger.error("Could not set window icon, icon image must have 4 channels"); free_apng(&apng); return; } int n = apng.width * apng.height; std::vector<unsigned long int> iconData(n + 2); iconData[0] = apng.width; iconData[1] = apng.height; for(int i=0; i < n;++i) { uint8 *pixel = (uint8*)&iconData[2 + i]; pixel[2] = *(apng.pdata + (i * 4) + 0); pixel[1] = *(apng.pdata + (i * 4) + 1); pixel[0] = *(apng.pdata + (i * 4) + 2); pixel[3] = *(apng.pdata + (i * 4) + 3); } Atom property = XInternAtom(m_display, "_NET_WM_ICON", 0); if(!XChangeProperty(m_display, m_window, property, XA_CARDINAL, 32, PropModeReplace, (const unsigned char*)&iconData[0], iconData.size())) g_logger.error("Couldn't set app icon"); free_apng(&apng); }
ImagePtr Image::loadPNG(const std::string& file) { std::stringstream fin; g_resources.readFileStream(file, fin); ImagePtr image; apng_data apng; if(load_apng(fin, &apng) == 0) { image = ImagePtr(new Image(Size(apng.width, apng.height), apng.bpp, apng.pdata)); free_apng(&apng); } return image; }