Speech bubbles can point down right.
[scummvm-innocent.git] / graphics / surface.cpp
blob263a4fd23b4deaa331fc5c7e26c5a11e7c9b557e
1 /* ScummVM - Graphic Adventure Engine
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * $URL$
22 * $Id$
25 #include "common/algorithm.h"
26 #include "common/util.h"
27 #include "graphics/primitives.h"
28 #include "graphics/surface.h"
30 namespace Graphics {
32 template<typename T>
33 static void plotPoint(int x, int y, int color, void *data) {
34 Surface *s = (Surface *)data;
35 if (x >= 0 && x < s->w && y >= 0 && y < s->h) {
36 T *ptr = (T *)s->getBasePtr(x, y);
37 *ptr = (T)color;
41 void Surface::drawLine(int x0, int y0, int x1, int y1, uint32 color) {
42 if (bytesPerPixel == 1)
43 Graphics::drawLine(x0, y0, x1, y1, color, plotPoint<byte>, this);
44 else if (bytesPerPixel == 2)
45 Graphics::drawLine(x0, y0, x1, y1, color, plotPoint<uint16>, this);
46 else
47 error("Surface::drawLine: bytesPerPixel must be 1 or 2");
50 void Surface::create(uint16 width, uint16 height, uint8 bytesPP) {
51 free();
53 w = width;
54 h = height;
55 bytesPerPixel = bytesPP;
56 pitch = w * bytesPP;
58 pixels = calloc(width * height, bytesPP);
59 assert(pixels);
62 void Surface::free() {
63 ::free(pixels);
64 pixels = 0;
65 w = h = pitch = 0;
66 bytesPerPixel = 0;
69 void Surface::copyFrom(const Surface &surf) {
70 create(surf.w, surf.h, surf.bytesPerPixel);
71 memcpy(pixels, surf.pixels, h * pitch);
74 void Surface::hLine(int x, int y, int x2, uint32 color) {
75 // Clipping
76 if (y < 0 || y >= h)
77 return;
79 if (x2 < x)
80 SWAP(x2, x);
82 if (x < 0)
83 x = 0;
84 if (x2 >= w)
85 x2 = w - 1;
87 if (x2 < x)
88 return;
90 if (bytesPerPixel == 1) {
91 byte *ptr = (byte *)getBasePtr(x, y);
92 memset(ptr, (byte)color, x2-x+1);
93 } else if (bytesPerPixel == 2) {
94 uint16 *ptr = (uint16 *)getBasePtr(x, y);
95 Common::set_to(ptr, ptr + (x2-x+1), (uint16)color);
96 } else {
97 error("Surface::hLine: bytesPerPixel must be 1 or 2");
101 void Surface::vLine(int x, int y, int y2, uint32 color) {
102 // Clipping
103 if (x < 0 || x >= w)
104 return;
106 if (y2 < y)
107 SWAP(y2, y);
109 if (y < 0)
110 y = 0;
111 if (y2 >= h)
112 y2 = h - 1;
114 if (bytesPerPixel == 1) {
115 byte *ptr = (byte *)getBasePtr(x, y);
116 while (y++ <= y2) {
117 *ptr = (byte)color;
118 ptr += pitch;
120 } else if (bytesPerPixel == 2) {
121 uint16 *ptr = (uint16 *)getBasePtr(x, y);
122 while (y++ <= y2) {
123 *ptr = (uint16)color;
124 ptr += pitch/2;
126 } else {
127 error("Surface::vLine: bytesPerPixel must be 1 or 2");
131 void Surface::fillRect(Common::Rect r, uint32 color) {
132 r.clip(w, h);
134 if (!r.isValidRect())
135 return;
137 int width = r.width();
138 int height = r.height();
139 // int i;
141 if (bytesPerPixel == 1) {
142 byte *ptr = (byte *)getBasePtr(r.left, r.top);
143 while (height--) {
144 memset(ptr, (byte)color, width);
145 ptr += pitch;
147 } else if (bytesPerPixel == 2) {
148 uint16 *ptr = (uint16 *)getBasePtr(r.left, r.top);
149 while (height--) {
150 Common::set_to(ptr, ptr + width, (uint16)color);
151 ptr += pitch/2;
153 } else {
154 error("Surface::fillRect: bytesPerPixel must be 1 or 2");
158 void Surface::frameRect(const Common::Rect &r, uint32 color) {
159 hLine(r.left, r.top, r.right-1, color);
160 hLine(r.left, r.bottom-1, r.right-1, color);
161 vLine(r.left, r.top, r.bottom-1, color);
162 vLine(r.right-1, r.top, r.bottom-1, color);
165 // FIXME: LordHoto asks why is this in Surface, since this
166 // just supports 8bpp surfaces. Looks like someone wants
167 // to subclass Surface to add this or it should be extended
168 // to support 16bpp (or marked as just working for 8bpp
169 // surfaces).
170 void Surface::move(int dx, int dy, int height) {
171 // This function currently just works with 8bpp surfaces
172 assert(bytesPerPixel == 1);
174 // Short circuit check - do we have to do anything anyway?
175 if ((dx == 0 && dy == 0) || height <= 0)
176 return;
178 byte *src, *dst;
179 int x, y;
181 // vertical movement
182 if (dy > 0) {
183 // move down - copy from bottom to top
184 dst = (byte *)pixels + (height - 1) * w;
185 src = dst - dy * w;
186 for (y = dy; y < height; y++) {
187 memcpy(dst, src, w);
188 src -= w;
189 dst -= w;
191 } else if (dy < 0) {
192 // move up - copy from top to bottom
193 dst = (byte *)pixels;
194 src = dst - dy * w;
195 for (y = -dy; y < height; y++) {
196 memcpy(dst, src, w);
197 src += w;
198 dst += w;
202 // horizontal movement
203 if (dx > 0) {
204 // move right - copy from right to left
205 dst = (byte *)pixels + (w - 1);
206 src = dst - dx;
207 for (y = 0; y < height; y++) {
208 for (x = dx; x < w; x++) {
209 *dst-- = *src--;
211 src += w + (w - dx);
212 dst += w + (w - dx);
214 } else if (dx < 0) {
215 // move left - copy from left to right
216 dst = (byte *)pixels;
217 src = dst - dx;
218 for (y = 0; y < height; y++) {
219 for (x = -dx; x < w; x++) {
220 *dst++ = *src++;
222 src += w - (w + dx);
223 dst += w - (w + dx);
228 } // End of namespace Graphics