blob: 752cd78434b9714c730269659d7a0f98aea845a0 [file] [log] [blame]
/* Copyright (C) 2006 TightVNC Team. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*
*
*
*/
// -=- ScaledDIBSectionBuffer.cxx
#include <math.h>
#include <rfb_win32/ScaledDIBSectionBuffer.h>
using namespace rfb;
using namespace win32;
const PixelFormat RGB24(32, 24, 0, 1, 255, 255, 255, 16, 8, 0);
ScaledDIBSectionBuffer::ScaledDIBSectionBuffer(HWND window)
: DIBSectionBuffer(window), src_buffer(0), scaling(false) {
scaled_data = &data;
}
ScaledDIBSectionBuffer::~ScaledDIBSectionBuffer() {
if (src_buffer) delete src_buffer;
}
void ScaledDIBSectionBuffer::setScale(int scale_) {
if (scale == scale_ || scale_ <= 0) return;
if (!(getPixelFormat().trueColour) && scale_ != 100) throw rfb::UnsupportedPixelFormatException();
ScaledPixelBuffer::setScale(scale_);
if (scale == 100) scaling = false;
else scaling = true;
recreateBuffers();
}
void ScaledDIBSectionBuffer::setPF(const PixelFormat &pf_) {
if (memcmp(&(ScaledPixelBuffer::pf), &pf_, sizeof(pf_)) == 0) return;
if (!pf_.trueColour && isScaling()) throw rfb::UnsupportedPixelFormatException();
pf = pf_;
if (scaling) {
if (src_buffer) {
src_buffer->setPF(pf);
} else {
src_buffer = new ManagedPixelBuffer(pf, src_width, src_height);
src_data = &(src_buffer->data);
}
if (memcmp(&(DIBSectionBuffer::getPF()), &RGB24, sizeof(PixelFormat)) != 0) {
DIBSectionBuffer::setPF(RGB24);
}
} else {
DIBSectionBuffer::setPF(pf);
pf = format;
}
}
void ScaledDIBSectionBuffer::setSize(int src_width_, int src_height_) {
if (src_width == src_width_ && src_height == src_height_) return;
src_width = src_width_;
src_height = src_height_;
// FIXME:
// Calculate the scale weight tabs must be in the ScalePixelBuffer class
recreateRowAccum();
freeWeightTabs();
calculateScaledBufferSize();
scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs);
scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs);
recreateBuffers();
}
void ScaledDIBSectionBuffer::setScaleWindowSize(int width, int height) {
if (scaled_width == width && scaled_height == height) return;
freeWeightTabs();
scaled_width = width_ = width;
scaled_height = height_ = height;
if (scaled_width == src_width && scaled_height == src_height) scaling = false;
else scaling = true;
scale_ratio_x = (double)scaled_width / src_width;
scale_ratio_y = (double)scaled_height / src_height;
scale = (int)(scale_ratio_x * 100);
// FIXME:
// Calculate the scale weight tabs must be in the ScalePixelBuffer class
scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs);
scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs);
recreateBuffers();
}
void ScaledDIBSectionBuffer::recreateScaledBuffer() {
if (scaling && memcmp(&(DIBSectionBuffer::getPF()), &RGB24, sizeof(PixelFormat)) != 0) {
DIBSectionBuffer::setPF(RGB24);
} else if (!scaling && (memcmp(&(DIBSectionBuffer::getPF()), &pf, sizeof(PixelFormat)) != 0)){
DIBSectionBuffer::setPF(pf);
} else {
DIBSectionBuffer::recreateBuffer();
}
}
void ScaledDIBSectionBuffer::recreateBuffers() {
// Recreate the source pixel buffer
if (src_width && src_height && pf.depth > 0) {
if (scaling) {
if (src_buffer) {
if (src_buffer->width() != src_width || src_buffer->width() != src_height)
src_buffer->setSize(src_width, src_height);
} else {
src_buffer = new ManagedPixelBuffer(pf, src_width, src_height);
src_data = &(src_buffer->data);
if (data) memcpy(src_buffer->data, data, src_width * src_height * (getPF().bpp/8));
}
}
}
// Recreate the scaled pixel buffer
recreateScaledBuffer();
if (scaling && src_buffer && data) scaleRect(Rect(0, 0, src_width, src_height));
else if (!scaling && src_buffer) {
if (src_buffer->data && data) memcpy(data, src_buffer->data, src_buffer->area() * (getPF().bpp/8));
delete src_buffer;
src_buffer = 0;
src_data = 0;
}
}
void ScaledDIBSectionBuffer::calculateScaledBufferSize() {
ScaledPixelBuffer::calculateScaledBufferSize();
width_ = scaled_width;
height_ = scaled_height;
}
void ScaledDIBSectionBuffer::fillRect(const Rect &dest, Pixel pix) {
if (scaling) {
src_buffer->fillRect(dest, pix);
scaleRect(dest);
} else {
DIBSectionBuffer::fillRect(dest, pix);
}
}
void ScaledDIBSectionBuffer::imageRect(const Rect &dest, const void* pixels, int stride) {
if (scaling) {
src_buffer->imageRect(dest, pixels, stride);
scaleRect(dest);
} else {
DIBSectionBuffer::imageRect(dest, pixels, stride);
}
}
void ScaledDIBSectionBuffer::copyRect(const Rect &dest, const Point &move_by_delta) {
if (scaling) {
src_buffer->copyRect(dest, move_by_delta);
scaleRect(dest);
} else {
DIBSectionBuffer::copyRect(dest, move_by_delta);
}
}
void ScaledDIBSectionBuffer::maskRect(const Rect& r, const void* pixels, const void* mask_) {
if (scaling) {
src_buffer->maskRect(r, pixels, mask_);
scaleRect(r);
} else {
DIBSectionBuffer::maskRect(r, pixels, mask_);
}
}
void ScaledDIBSectionBuffer::maskRect(const Rect& r, Pixel pixel, const void* mask_) {
if (scaling) {
src_buffer->maskRect(r, pixel, mask_);
scaleRect(r);
} else {
DIBSectionBuffer::maskRect(r, pixel, mask_);
}
}