Files
scummvm-cursorfix/engines/m4/graphics/gr_line.cpp
2026-02-02 04:50:13 +01:00

139 lines
4.4 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/graphics/gr_line.h"
#include "m4/vars.h"
namespace M4 {
void gr_vline_xor(Buffer *buf, int32 x, int32 y1, int32 y2) {
if (y1 > y2) {
SWAP(y1, y2);
}
if ((x > buf->w) || (y1 > buf->h))
return;
if (y2 > buf->h)
y2 = buf->h; // Don't draw past bottom
byte *start = buf->data + x;
for (int32 i = y1; i < y2; i++, start += buf->stride)
*start ^= 0xff;
}
void gr_hline_xor(Buffer *buf, int32 x1, int32 x2, int32 y) {
if (x1 > x2) {
SWAP(x1, x2);
}
if ((y > buf->h) || (x1 > buf->w))
return;
byte *start = gr_buffer_pointer(buf, x1, y);
for (int32 i = x1; i < x2; i++, start++)
*start ^= 0xff;
}
void gr_vline(Buffer *buf, int32 x, int32 y1, int32 y2) {
if (y1 > y2) {
SWAP(y1, y2);
}
if ((x > buf->w) || (y1 > buf->h))
return;
y2++;
if (y2 > buf->h)
y2 = buf->h; // don't draw past bottom
byte *start = gr_buffer_pointer(buf, x, y1);
for (int32 i = y1; i < y2; i++, start += buf->stride)
*start = _G(color);
}
void gr_hline(Buffer *buf, int32 x1, int32 x2, int32 y) {
if (x1 > x2) {
SWAP(x1, x2);
}
if ((y > buf->h) || (x1 > buf->w))
return;
byte *start = gr_buffer_pointer(buf, x1, y);
x2++;
if (x2 > buf->w)
x2 = buf->w;
for (int32 i = x1; i < x2; i++, start++)
*start = _G(color);
}
void gr_line(int32 x1, int32 y1, int32 x2, int32 y2, int32 color, Buffer *screen) {
byte *myData = (byte *)screen->data;
int32 y_unit, x_unit; // Variables for amount of change in x and y
int32 offset = y1 * screen->stride + x1; // Calculate offset into video RAM
int32 ydiff = y2 - y1; // Calculate difference between y coordinates
if (ydiff < 0) { // If the line moves in the negative direction
ydiff = -ydiff; // ...get absolute value of difference
y_unit = -screen->stride; // ...and set negative unit in y dimension
} else y_unit = screen->stride; // Else set positive unit in y dimension
int32 xdiff = x2 - x1; // Calculate difference between x coordinates
if (xdiff < 0) { // If the line moves in the negative direction
xdiff = -xdiff; // ...get absolute value of difference
x_unit = -1; // ...and set negative unit in x dimension
} else x_unit = 1; // Else set positive unit in y dimension
int32 error_term = 0; // Initialize error term
if (xdiff > ydiff) { // If difference is bigger in x dimension
const int32 length = xdiff + 1; // ...prepare to count off in x direction
for (int32 i = 0; i < length; i++) { // Loop through points in x direction
myData[offset] = (char)color; // Set the next pixel in the line to COLOR
offset += x_unit; // Move offset to next pixel in x direction
error_term += ydiff; // Check to see if move required in y direction
if (error_term > xdiff) { // If so...
error_term -= xdiff; // ...reset error term
offset += y_unit; // ...and move offset to next pixel in y dir.
}
}
} else { // If difference is bigger in y dimension
const int32 length = ydiff + 1; // ...prepare to count off in y direction
for (int32 i = 0; i < length; i++) { // Loop through points in y direction
myData[offset] = (char)color; // Set the next pixel in the line to COLOR
offset += y_unit; // Move offset to next pixel in y direction
error_term += xdiff; // Check to see if move required in x direction
if (error_term > 0) { // If so...
error_term -= ydiff; // ...reset error term
offset += x_unit; // ...and move offset to next pixel in x dir.
}
}
}
}
} // namespace M4