blob: efa27a0b8ab26deb73449b85421b915deffec2d5 [file] [log] [blame]
Constantin Kaplinsky729598c2006-05-25 05:12:25 +00001/* Copyright (C) 2006 TightVNC Team. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 *
18 * TightVNC distribution homepage on the Web: http://www.tightvnc.com/
19 *
20 */
21
22// -=- ScaledDIBSectionBuffer.cxx
23
24#include <math.h>
25
26#include <rfb_win32/ScaledDIBSectionBuffer.h>
27
28using namespace rfb;
29using namespace win32;
30
george82b2f8ae52006-09-16 14:41:12 +000031const PixelFormat RGB24(32, 24, 0, 1, 255, 255, 255, 16, 8, 0);
32
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000033ScaledDIBSectionBuffer::ScaledDIBSectionBuffer(HWND window)
34 : src_buffer(0), scaling(false), DIBSectionBuffer(window) {
george82df9f31c2006-09-16 11:06:07 +000035 scaled_data = &data;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000036}
37
38ScaledDIBSectionBuffer::~ScaledDIBSectionBuffer() {
39 if (src_buffer) delete src_buffer;
40}
41
george822446ed02007-03-10 08:55:35 +000042void ScaledDIBSectionBuffer::setScale(int scale_) {
43 if (scale == scale_ || scale_ <= 0) return;
george82c79c7bb2007-11-05 11:22:14 +000044 ScaledPixelBuffer::setScale(scale_);
george822446ed02007-03-10 08:55:35 +000045 if (scale == 100) scaling = false;
george82b2f8ae52006-09-16 14:41:12 +000046 else scaling = true;
george82e4b3c2c2006-09-05 06:43:28 +000047 recreateBuffers();
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000048}
49
Constantin Kaplinsky1ae2eb02006-05-26 05:24:24 +000050void ScaledDIBSectionBuffer::setPF(const PixelFormat &pf_) {
george82e4b3c2c2006-09-05 06:43:28 +000051 if (memcmp(&(ScaledPixelBuffer::pf), &pf_, sizeof(pf_)) == 0) return;
george82e3341e72006-08-02 15:23:39 +000052
george8243d1fa02006-11-26 11:18:38 +000053 if (!pf_.trueColour) throw rfb::UnsupportedPixelFormatException();
george820ba8cb72006-09-23 07:07:17 +000054
george82b2f8ae52006-09-16 14:41:12 +000055 pf = pf_;
Constantin Kaplinsky1ae2eb02006-05-26 05:24:24 +000056 if (scaling) {
george82b2f8ae52006-09-16 14:41:12 +000057 if (src_buffer) {
58 src_buffer->setPF(pf);
59 } else {
60 src_buffer = new ManagedPixelBuffer(pf, src_width, src_height);
george82e4b3c2c2006-09-05 06:43:28 +000061 src_data = &(src_buffer->data);
62 }
george82b2f8ae52006-09-16 14:41:12 +000063 if (memcmp(&(DIBSectionBuffer::getPF()), &RGB24, sizeof(PixelFormat)) != 0) {
64 DIBSectionBuffer::setPF(RGB24);
65 }
66 } else {
67 DIBSectionBuffer::setPF(pf);
Constantin Kaplinsky1ae2eb02006-05-26 05:24:24 +000068 }
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000069}
70
71void ScaledDIBSectionBuffer::setSize(int src_width_, int src_height_) {
george82e3341e72006-08-02 15:23:39 +000072 if (src_width == src_width_ && src_height == src_height_) return;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000073 src_width = src_width_;
74 src_height = src_height_;
george824ff66752006-11-20 15:55:05 +000075
76 // FIXME:
77 // Calculate the scale weight tabs must be in the ScalePixelBuffer class
george823a1982e2007-11-04 07:35:51 +000078 recreateRowAccum();
george824ff66752006-11-20 15:55:05 +000079 freeWeightTabs();
80 calculateScaledBufferSize();
george822446ed02007-03-10 08:55:35 +000081 scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs);
82 scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs);
george824ff66752006-11-20 15:55:05 +000083
george82e4b3c2c2006-09-05 06:43:28 +000084 recreateBuffers();
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000085}
86
george82770bbbc2007-03-12 10:48:09 +000087void ScaledDIBSectionBuffer::setScaleWindowSize(int width, int height) {
88 if (scaled_width == width && scaled_height == height) return;
89
90 freeWeightTabs();
91
92 scaled_width = width_ = width;
93 scaled_height = height_ = height;
94
95 if (scaled_width == src_width && scaled_height == src_height) scaling = false;
96 else scaling = true;
97 scale_ratio_x = (double)scaled_width / src_width;
98 scale_ratio_y = (double)scaled_height / src_height;
99 scale = (int)(scale_ratio_x * 100);
100
101 // FIXME:
102 // Calculate the scale weight tabs must be in the ScalePixelBuffer class
103 scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs);
104 scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs);
105
106 recreateBuffers();
107}
108
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000109void ScaledDIBSectionBuffer::recreateScaledBuffer() {
george82b2f8ae52006-09-16 14:41:12 +0000110 if (scaling && memcmp(&(DIBSectionBuffer::getPF()), &RGB24, sizeof(PixelFormat)) != 0) {
111 DIBSectionBuffer::setPF(RGB24);
george820ba8cb72006-09-23 07:07:17 +0000112 } else if (!scaling && (memcmp(&(DIBSectionBuffer::getPF()), &pf, sizeof(PixelFormat)) != 0)){
113 DIBSectionBuffer::setPF(pf);
george82b2f8ae52006-09-16 14:41:12 +0000114 } else {
george82e3341e72006-08-02 15:23:39 +0000115 DIBSectionBuffer::recreateBuffer();
george82e3341e72006-08-02 15:23:39 +0000116 }
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000117}
118
george82e4b3c2c2006-09-05 06:43:28 +0000119void ScaledDIBSectionBuffer::recreateBuffers() {
george820ba8cb72006-09-23 07:07:17 +0000120 // Recreate the source pixel buffer
121 if (src_width && src_height && pf.depth > 0) {
george82e4b3c2c2006-09-05 06:43:28 +0000122 if (scaling) {
george82b2f8ae52006-09-16 14:41:12 +0000123 if (src_buffer) {
george82e4b3c2c2006-09-05 06:43:28 +0000124 if (src_buffer->width() != src_width || src_buffer->width() != src_height)
125 src_buffer->setSize(src_width, src_height);
george82e4b3c2c2006-09-05 06:43:28 +0000126 } else {
george820ba8cb72006-09-23 07:07:17 +0000127 src_buffer = new ManagedPixelBuffer(pf, src_width, src_height);
george82e4b3c2c2006-09-05 06:43:28 +0000128 src_data = &(src_buffer->data);
george820ba8cb72006-09-23 07:07:17 +0000129 if (data) memcpy(src_buffer->data, data, src_width * src_height * (getPF().bpp/8));
george82e4b3c2c2006-09-05 06:43:28 +0000130 }
131 }
george820ba8cb72006-09-23 07:07:17 +0000132 }
133 // Recreate the scaled pixel buffer
134 recreateScaledBuffer();
135 if (scaling && src_buffer && data) scaleRect(Rect(0, 0, src_width, src_height));
136 else if (!scaling && src_buffer) {
137 if (src_buffer->data && data) memcpy(data, src_buffer->data, src_buffer->area() * (getPF().bpp/8));
138 delete src_buffer;
139 src_buffer = 0;
140 src_data = 0;
george82e4b3c2c2006-09-05 06:43:28 +0000141 }
142}
143
george8296b17b92006-09-05 15:44:35 +0000144void ScaledDIBSectionBuffer::calculateScaledBufferSize() {
145 ScaledPixelBuffer::calculateScaledBufferSize();
146 width_ = scaled_width;
147 height_ = scaled_height;
148}
149
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000150void ScaledDIBSectionBuffer::fillRect(const Rect &dest, Pixel pix) {
151 if (scaling) {
152 src_buffer->fillRect(dest, pix);
153 scaleRect(dest);
154 } else {
155 DIBSectionBuffer::fillRect(dest, pix);
156 }
157}
158
159void ScaledDIBSectionBuffer::imageRect(const Rect &dest, const void* pixels, int stride) {
160 if (scaling) {
161 src_buffer->imageRect(dest, pixels, stride);
162 scaleRect(dest);
163 } else {
164 DIBSectionBuffer::imageRect(dest, pixels, stride);
165 }
166}
167
168void ScaledDIBSectionBuffer::copyRect(const Rect &dest, const Point &move_by_delta) {
169 if (scaling) {
170 src_buffer->copyRect(dest, move_by_delta);
171 scaleRect(dest);
172 } else {
173 DIBSectionBuffer::copyRect(dest, move_by_delta);
174 }
175}
176
177void ScaledDIBSectionBuffer::maskRect(const Rect& r, const void* pixels, const void* mask_) {
178 if (scaling) {
179 src_buffer->maskRect(r, pixels, mask_);
180 scaleRect(r);
181 } else {
182 DIBSectionBuffer::maskRect(r, pixels, mask_);
183 }
184}
185
186void ScaledDIBSectionBuffer::maskRect(const Rect& r, Pixel pixel, const void* mask_) {
187 if (scaling) {
188 src_buffer->maskRect(r, pixel, mask_);
189 scaleRect(r);
190 } else {
191 DIBSectionBuffer::maskRect(r, pixel, mask_);
192 }
193}