#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdexcept>
#include "orientation.hh"
namespace uw {
Orientation::Orientation(Screen &screen, Image &image)
: uwScreen{ screen }, uwImage{ image } {
}
Orientation::~Orientation() {}
void Orientation::center() {
Pixmap pm = XCreatePixmap(uwScreen.getDisplay(), uwScreen.getWindow(),
uwScreen.getExtent().width, uwScreen.getExtent().height,
uwImage.getExtent().depth);
XImage *img = XCreateImage(uwScreen.getDisplay(),
uwImage.getVisual(), uwImage.getExtent().depth, ZPixmap, 0, nullptr,
uwImage.getExtent().width, uwImage.getExtent().height, 32, 0);
if (!img) throw std::runtime_error("中央にする為にXImageの作成に失敗。");
std::vector<char>
imgData(uwImage.getExtent().width * uwImage.getExtent().height * 4);
img->data = imgData.data();
for (int y = 0; y < uwImage.getExtent().height; y++) {
for (int x = 0; x < uwImage.getExtent().width; x++) {
int idx = (y * uwImage.getExtent().width + x) * 4;
uchar blue = uwImage.getImageData()[idx + 2];
uchar green = uwImage.getImageData()[idx + 1];
uchar red = uwImage.getImageData()[idx + 0];
uchar alpha = uwImage.getImageData()[idx + 3];
ulong pixel = (alpha << 24) | (red << 16) | (green << 8) | blue;
XPutPixel(img, x, y, pixel);
}
}
XSetForeground(uwScreen.getDisplay(), uwImage.getGC(), 0);
XFillRectangle(uwScreen.getDisplay(), pm, uwImage.getGC(), 0, 0,
uwScreen.getExtent().width, uwScreen.getExtent().height);
int xoff = (uwScreen.getExtent().width - uwImage.getExtent().width) / 2;
int yoff = (uwScreen.getExtent().height - uwImage.getExtent().height) / 2;
if (xoff < 0) xoff = 0;
if (yoff < 0) yoff = 0;
XPutImage(uwScreen.getDisplay(), pm, uwImage.getGC(), img, 0, 0, xoff, yoff,
uwImage.getExtent().width, uwImage.getExtent().height);
XSetWindowBackgroundPixmap(uwScreen.getDisplay(), uwScreen.getWindow(), pm);
XClearWindow(uwScreen.getDisplay(), uwScreen.getWindow());
XFreePixmap(uwScreen.getDisplay(), pm);
img->data = nullptr;
XDestroyImage(img);
}
void Orientation::fill() {
Pixmap pm = XCreatePixmap(uwScreen.getDisplay(), uwScreen.getWindow(),
uwScreen.getExtent().width, uwScreen.getExtent().height,
uwImage.getExtent().depth);
XImage *img = XCreateImage(uwScreen.getDisplay(),
uwImage.getVisual(), uwImage.getExtent().depth, ZPixmap, 0, nullptr,
uwScreen.getExtent().width, uwScreen.getExtent().height, 32, 0);
if (!img) throw std::runtime_error("スケールする為にXImageの作成に失敗。");
std::vector<char> sdata(
uwScreen.getExtent().width * uwScreen.getExtent().height * 4);
img->data = sdata.data();
if (!img->data)
throw std::runtime_error("スケールしたデータにメモリの役割に失敗。");
double xScale = (double)uwScreen.getExtent().width / uwImage.getExtent().width;
double yScale = (double)uwScreen.getExtent().height / uwImage.getExtent().height;
for (int y = 0; y < uwScreen.getExtent().height; y++) {
for(int x = 0; x < uwScreen.getExtent().width; x++) {
int srcx = (x / xScale);
int srcy = (y / yScale);
if (srcx >= uwImage.getExtent().width) srcx = uwImage.getExtent().width - 1;
if (srcy >= uwImage.getExtent().height) srcy = uwImage.getExtent().height - 1;
int sidx = (srcy * uwImage.getExtent().width + srcx) * 4;
if (sidx >= uwImage.getExtent().width * uwImage.getExtent().height * 4)
continue;
uchar blue = uwImage.getImageData()[sidx + 2];
uchar green = uwImage.getImageData()[sidx + 1];
uchar red = uwImage.getImageData()[sidx + 0];
uchar alpha = uwImage.getImageData()[sidx + 3];
ulong pixel = (alpha << 24) | (red << 16) | (green << 8) | blue;
XPutPixel(img, x, y, pixel);
}
}
XClearWindow(uwScreen.getDisplay(), uwScreen.getWindow());
XPutImage(uwScreen.getDisplay(), pm, uwImage.getGC(), img, 0, 0, 0, 0,
uwScreen.getExtent().width, uwScreen.getExtent().height);
XSetWindowBackgroundPixmap(uwScreen.getDisplay(), uwScreen.getWindow(), pm);
XClearWindow(uwScreen.getDisplay(), uwScreen.getWindow());
XFreePixmap(uwScreen.getDisplay(), pm);
img->data = nullptr;
XDestroyImage(img);
}
void Orientation::tile() {
Pixmap pm = XCreatePixmap(uwScreen.getDisplay(), uwScreen.getWindow(),
uwScreen.getExtent().width, uwScreen.getExtent().height,
uwImage.getExtent().depth);
XImage *img = XCreateImage(uwScreen.getDisplay(),
uwImage.getVisual(), uwImage.getExtent().depth, ZPixmap, 0, nullptr,
uwImage.getExtent().width, uwImage.getExtent().height, 32, 0);
if (!img) throw std::runtime_error("タイルする為にXImageの作成に失敗。");
std::vector<char>
imgData(uwImage.getExtent().width * uwImage.getExtent().height * 4);
img->data = imgData.data();
for (int y = 0; y < uwImage.getExtent().height; y++) {
for (int x = 0; x < uwImage.getExtent().width; x++) {
int idx = (y * uwImage.getExtent().width + x) * 4;
uchar blue = uwImage.getImageData()[idx + 2];
uchar green = uwImage.getImageData()[idx + 1];
uchar red = uwImage.getImageData()[idx + 0];
uchar alpha = uwImage.getImageData()[idx + 3];
ulong pixel = (alpha << 24) | (red << 16) | (green << 8) | blue;
XPutPixel(img, x, y, pixel);
}
}
XPutImage(uwScreen.getDisplay(), pm, uwImage.getGC(), img, 0, 0, 0, 0,
uwImage.getExtent().width, uwImage.getExtent().height);
XSetWindowBackgroundPixmap(uwScreen.getDisplay(), uwScreen.getWindow(), pm);
XClearWindow(uwScreen.getDisplay(), uwScreen.getWindow());
for (int y = 0; y < uwScreen.getExtent().height; y += uwImage.getExtent().height) {
for (int x = 0; x < uwScreen.getExtent().width; x += uwImage.getExtent().width) {
XCopyArea(uwScreen.getDisplay(), pm, uwScreen.getWindow(), uwImage.getGC(),
0, 0, uwImage.getExtent().width, uwImage.getExtent().height, x, y);
}
}
XFreePixmap(uwScreen.getDisplay(), pm);
img->data = nullptr;
XDestroyImage(img);
}
}