blob: 12f9c78a298c363a8d2ac6eee13d7f2dbb3f7ca5 [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
george82bf0adb32006-07-29 10:29:41 +000042void ScaledDIBSectionBuffer::setScaleRatio(double scale_ratio_) {
43 if (scale_ratio == scale_ratio_) return;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000044
george82e4b3c2c2006-09-05 06:43:28 +000045 if (format.depth != 24 && format.depth != 0) throw rfb::UnsupportedPixelFormatException();
george822ac935e2006-05-29 13:57:39 +000046
george82b2f8ae52006-09-16 14:41:12 +000047 scale_ratio = scale_ratio_;
48 if (scale_ratio == 1) scaling = false;
49 else scaling = true;
george82e4b3c2c2006-09-05 06:43:28 +000050 recreateBuffers();
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000051}
52
Constantin Kaplinsky1ae2eb02006-05-26 05:24:24 +000053void ScaledDIBSectionBuffer::setPF(const PixelFormat &pf_) {
george82e4b3c2c2006-09-05 06:43:28 +000054 if (memcmp(&(ScaledPixelBuffer::pf), &pf_, sizeof(pf_)) == 0) return;
george82e3341e72006-08-02 15:23:39 +000055
george82b2f8ae52006-09-16 14:41:12 +000056 pf = pf_;
Constantin Kaplinsky1ae2eb02006-05-26 05:24:24 +000057 if (scaling) {
george82b2f8ae52006-09-16 14:41:12 +000058 if (src_buffer) {
59 src_buffer->setPF(pf);
60 } else {
61 src_buffer = new ManagedPixelBuffer(pf, src_width, src_height);
george82e4b3c2c2006-09-05 06:43:28 +000062 src_data = &(src_buffer->data);
63 }
george82b2f8ae52006-09-16 14:41:12 +000064 if (memcmp(&(DIBSectionBuffer::getPF()), &RGB24, sizeof(PixelFormat)) != 0) {
65 DIBSectionBuffer::setPF(RGB24);
66 }
67 } else {
68 DIBSectionBuffer::setPF(pf);
Constantin Kaplinsky1ae2eb02006-05-26 05:24:24 +000069 }
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000070}
71
72void ScaledDIBSectionBuffer::setSize(int src_width_, int src_height_) {
george82e3341e72006-08-02 15:23:39 +000073 if (src_width == src_width_ && src_height == src_height_) return;
74
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000075 src_width = src_width_;
76 src_height = src_height_;
george82e4b3c2c2006-09-05 06:43:28 +000077 recreateBuffers();
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000078}
79
80void ScaledDIBSectionBuffer::recreateScaledBuffer() {
george82b2f8ae52006-09-16 14:41:12 +000081 calculateScaledBufferSize();
82 if (scaling && memcmp(&(DIBSectionBuffer::getPF()), &RGB24, sizeof(PixelFormat)) != 0) {
83 DIBSectionBuffer::setPF(RGB24);
84 } else {
george82e3341e72006-08-02 15:23:39 +000085 DIBSectionBuffer::recreateBuffer();
george82e3341e72006-08-02 15:23:39 +000086 }
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000087}
88
george82e4b3c2c2006-09-05 06:43:28 +000089void ScaledDIBSectionBuffer::recreateBuffers() {
george82b2f8ae52006-09-16 14:41:12 +000090 if (src_width && src_height && pf.depth != 0 && scale_ratio != 0) {
george82e4b3c2c2006-09-05 06:43:28 +000091 if (scaling) {
george82b2f8ae52006-09-16 14:41:12 +000092 if (src_buffer) {
george82e4b3c2c2006-09-05 06:43:28 +000093 if (src_buffer->width() != src_width || src_buffer->width() != src_height)
94 src_buffer->setSize(src_width, src_height);
george82e4b3c2c2006-09-05 06:43:28 +000095 } else {
96 src_buffer = new ManagedPixelBuffer(format, src_width, src_height);
97 src_data = &(src_buffer->data);
98 memcpy(src_buffer->data, data, src_width * src_height * (getPF().bpp/8));
99 }
100 }
101 recreateScaledBuffer();
102 if (scaling) {
103 scaleRect(Rect(0, 0, src_width, src_height));
george82b2f8ae52006-09-16 14:41:12 +0000104 } else if (src_buffer) {
george82e4b3c2c2006-09-05 06:43:28 +0000105 memcpy(data, src_buffer->data, src_buffer->area() * (src_buffer->getPF().bpp/8));
george82b2f8ae52006-09-16 14:41:12 +0000106 delete src_buffer;
107 src_buffer = 0;
108 src_data = 0;
george82e4b3c2c2006-09-05 06:43:28 +0000109 }
110 }
111}
112
george8296b17b92006-09-05 15:44:35 +0000113void ScaledDIBSectionBuffer::calculateScaledBufferSize() {
114 ScaledPixelBuffer::calculateScaledBufferSize();
115 width_ = scaled_width;
116 height_ = scaled_height;
117}
118
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000119void ScaledDIBSectionBuffer::fillRect(const Rect &dest, Pixel pix) {
120 if (scaling) {
121 src_buffer->fillRect(dest, pix);
122 scaleRect(dest);
123 } else {
124 DIBSectionBuffer::fillRect(dest, pix);
125 }
126}
127
128void ScaledDIBSectionBuffer::imageRect(const Rect &dest, const void* pixels, int stride) {
129 if (scaling) {
130 src_buffer->imageRect(dest, pixels, stride);
131 scaleRect(dest);
132 } else {
133 DIBSectionBuffer::imageRect(dest, pixels, stride);
134 }
135}
136
137void ScaledDIBSectionBuffer::copyRect(const Rect &dest, const Point &move_by_delta) {
138 if (scaling) {
139 src_buffer->copyRect(dest, move_by_delta);
140 scaleRect(dest);
141 } else {
142 DIBSectionBuffer::copyRect(dest, move_by_delta);
143 }
144}
145
146void ScaledDIBSectionBuffer::maskRect(const Rect& r, const void* pixels, const void* mask_) {
147 if (scaling) {
148 src_buffer->maskRect(r, pixels, mask_);
149 scaleRect(r);
150 } else {
151 DIBSectionBuffer::maskRect(r, pixels, mask_);
152 }
153}
154
155void ScaledDIBSectionBuffer::maskRect(const Rect& r, Pixel pixel, const void* mask_) {
156 if (scaling) {
157 src_buffer->maskRect(r, pixel, mask_);
158 scaleRect(r);
159 } else {
160 DIBSectionBuffer::maskRect(r, pixel, mask_);
161 }
162}