After reading this post about screen rotation I wanted to play a bit further with that idea. I have a ThinkPad X1 that I like to use in tent mode (upside down), so an option to rotate the screen would be welcome.
I added a setting to the Screen preferences to set screen rotation:
I also updated HWInterface::_CopyToFront
to handle all four rotations (Landscape, Landscape (flipped), Portrait and Portrait (flipped)).
At this point I’m stuck trying to connect the two pieces together. How can I update the currently hard coded screenRotation
value in HWInterface::_CopyToFront
with whatever setting is used in Screen preferences?
void
HWInterface::_CopyToFront(uint8* src, uint32 srcBPR, int32 x, int32 y,
int32 right, int32 bottom) const
{
RenderingBuffer* frontBuffer = FrontBuffer();
uint8* dst = (uint8*)frontBuffer->Bits();
uint32 dstBPR = frontBuffer->BytesPerRow();
// Todo: Get this value from Screen preferences
int32 screenRotation = 3; // 0 - none, 1 - 90 degrees, 2 - 180 degrees, 3 - 270 degrees
// transfer, handle colorspace conversion
switch (frontBuffer->ColorSpace()) {
case B_RGB32:
case B_RGBA32:
{
int32 src_width = right - x + 1;
int32 src_height = bottom - y + 1;
int32 dst_width = frontBuffer->Width();
int32 dst_height = frontBuffer->Height();
if (screenRotation == 0) {
int32 bytes = (right - x + 1) * 4;
if (bytes > 0) {
// offset to left top pixel in dest buffer
dst += y * dstBPR + x * 4;
// copy
for (; y <= bottom; y++) {
// bytes is guaranteed to be multiple of 4
memcpy(dst, src, bytes);
dst += dstBPR;
src += srcBPR;
}
}
} else if (screenRotation == 1 || screenRotation == 3) {
for (int32 ysrc = 0; ysrc < src_height; ysrc++) {
for (int32 xsrc = 0; xsrc < src_width; xsrc++) {
int32 ydst = (screenRotation == 1) ? x + xsrc : dst_height - (x + xsrc); // 90 or -90 degrees rotation
int32 xdst = (screenRotation == 1) ? dst_width - (y + ysrc) : y + ysrc; // 90 or -90 degrees rotation
if (ydst < 0 || xdst < 0 || ydst >= dst_height || xdst >= dst_width) continue;
uint8* psrc = src + ysrc * srcBPR + xsrc * 4;
uint8* pdst = dst + ydst * dstBPR + xdst * 4;
memcpy(pdst, psrc, 4);
}
}
} else if (screenRotation == 2) {
for (int32 ysrc = 0; ysrc < src_height; ysrc++) {
for (int32 xsrc = 0; xsrc < src_width; xsrc++) {
int32 ydst = dst_height - (ysrc + y);
int32 xdst = dst_width - (xsrc + x);
if (ydst < 0 || xdst < 0 || ydst >= dst_height || xdst >= dst_width) continue;
uint8* psrc = src + ysrc * srcBPR + xsrc * 4;
uint8* pdst = dst + ydst * dstBPR + xdst * 4;
memcpy(pdst, psrc, 4);
}
}
}
break;
}