This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
neofx-zoomedit/draw.c

238 lines
5.9 KiB
C
Raw Normal View History

2007-06-21 19:52:03 +00:00
#include "draw.h"
#include "edit.h"
2007-06-21 19:52:03 +00:00
#include "level.h"
#include "geometry.h"
2007-06-24 00:35:04 +00:00
#include <math.h>
2007-06-21 19:52:03 +00:00
#include <gtk/gtk.h>
2007-06-24 17:33:00 +00:00
#include <glib/gprintf.h>
2007-06-21 19:52:03 +00:00
#include <cairo/cairo.h>
static double scale = 100.0;
static double xTranslate = 0.0, yTranslate = 0.0;
static gboolean repaint = FALSE;
2007-06-21 19:52:03 +00:00
2007-06-24 00:35:04 +00:00
static void drawGrid(cairo_t *cr, const RECTANGLE *rect) {
double depth = log10(scale)-0.75;
double depth2 = floor(depth);
double step = pow(0.1, depth2);
2007-06-24 17:33:00 +00:00
double d;
2007-06-24 00:35:04 +00:00
int i;
gchar buffer[20];
2007-06-24 00:35:04 +00:00
2007-06-24 17:33:00 +00:00
cairo_set_font_size(cr, 10.0/scale);
for(i = 0; 0.4*(depth-depth2+i-1) < 0.5; i++) {
d = MIN(0.4*(depth-depth2+i), 0.5);
2007-06-24 17:33:00 +00:00
cairo_set_source_rgb(cr, d, d, d);
for(d = rect->x - fmod(rect->x, step) - step; d <= rect->x+rect->width; d+=step) {
cairo_move_to(cr, d, rect->y);
cairo_line_to(cr, d, rect->y+rect->height);
2007-06-24 00:35:04 +00:00
cairo_stroke(cr);
2007-06-24 17:33:00 +00:00
if(step > 0.2)
g_snprintf(buffer, sizeof(buffer), "%i", (int)rint(d));
else
g_snprintf(buffer, sizeof(buffer), "%.*f", -(int)floor(log10(step*1.1)), d+step/10);
buffer[sizeof(buffer)-1] = '\0';
cairo_move_to(cr, d+1/scale, rect->y+11/scale);
cairo_show_text(cr, buffer);
2007-06-24 00:35:04 +00:00
}
2007-06-24 17:33:00 +00:00
for(d = rect->y - fmod(rect->y, step) - step; d <= rect->y+rect->height; d+=step) {
cairo_move_to(cr, rect->x, d);
cairo_line_to(cr, rect->x+rect->width, d);
2007-06-24 00:35:04 +00:00
cairo_stroke(cr);
2007-06-24 17:33:00 +00:00
if(step > 0.5)
g_snprintf(buffer, sizeof(buffer), "%i", (int)rint(d));
else
g_snprintf(buffer, sizeof(buffer), "%.*f", -(int)floor(log10(step*1.1)), d+step/10);
buffer[sizeof(buffer)-1] = '\0';
cairo_move_to(cr, rect->x+3/scale, d+11/scale);
cairo_show_text(cr, buffer);
2007-06-24 00:35:04 +00:00
}
step *= 10;
}
}
static void room2path(cairo_t *cr, const ROOM *room, const RECTANGLE *rect) {
2007-06-21 19:52:03 +00:00
int i;
ROOM room2 = {0, NULL};
2007-06-21 19:52:03 +00:00
// no vertices
2007-06-21 19:52:03 +00:00
if(room->nVertices == 0) return;
if(rect)
simplifyPolygon(room, rect, &room2);
else
room2 = *room;
if(room2.nVertices == 0) return;
2007-06-21 19:52:03 +00:00
cairo_new_sub_path(cr);
for(i = 0; i < room2.nVertices; i++) {
cairo_line_to(cr, room2.vertices[i].x, room2.vertices[i].y);
}
2007-06-21 19:52:03 +00:00
cairo_close_path(cr);
if(rect && room2.vertices)
free(room2.vertices);
2007-06-21 19:52:03 +00:00
}
gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
cairo_t *cr;
2007-06-24 17:33:00 +00:00
RECTANGLE rect = {-1, -1, widget->allocation.width+2, widget->allocation.height+2};
static GdkPixmap *pixmap = NULL;
static double lastImageWidth = 0.0, lastImageHeight = 0.0;
static gint lastWidth = 0.0, lastHeight = 0.0;
2007-06-21 19:52:03 +00:00
int i;
if(getLevel() == NULL) return;
2007-06-21 19:52:03 +00:00
if(pixmap == NULL || lastImageWidth != getImageWidth() || lastImageHeight != getImageHeight() ||
lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || repaint)
{
if(pixmap != NULL)
g_object_unref(G_OBJECT(pixmap));
pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1);
lastImageWidth = getImageWidth();
lastImageHeight = getImageHeight();
lastWidth = widget->allocation.width;
lastHeight = widget->allocation.height;
repaint = FALSE;
cr = gdk_cairo_create(GDK_DRAWABLE(pixmap));
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_rectangle(cr, 0, 0, widget->allocation.width, widget->allocation.height);
cairo_fill(cr);
cairo_translate(cr, getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate);
cairo_scale(cr, scale, scale);
cairo_device_to_user(cr, &rect.x, &rect.y);
cairo_device_to_user_distance(cr, &rect.width, &rect.height);
cairo_set_line_width(cr, 1.0/scale);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
drawGrid(cr, &rect);
for(i = 0; i < getLevel()->nRooms; i++) {
if(&getLevel()->rooms[i] != getActiveRoom())
room2path(cr, &getLevel()->rooms[i], &rect);
}
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.3);
cairo_fill_preserve(cr);
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7);
cairo_stroke(cr);
if(getEditMode() == EDIT_MODE_SELECTED) {
room2path(cr, getActiveRoom(), &rect);
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.2);
cairo_fill_preserve(cr);
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.9);
cairo_set_line_width(cr, 1.5/scale);
cairo_stroke(cr);
}
cairo_destroy (cr);
}
2007-06-21 19:52:03 +00:00
gdk_draw_drawable(GDK_DRAWABLE(widget->window), widget->style->fg_gc[GTK_WIDGET_STATE(widget)], GDK_DRAWABLE(pixmap), 0, 0, 0, 0, -1, -1);
2007-06-21 19:52:03 +00:00
return FALSE;
}
2007-06-21 19:52:03 +00:00
double getScale() {
return scale;
}
void setScale(double s) {
scale = s;
repaint = TRUE;
}
void imageToView(VERTEX *v) {
v->x = v->x*scale+getImageWidth()/2-xTranslate;
v->y = v->y*scale+getImageHeight()/2-yTranslate;
}
void viewToImage(VERTEX *v) {
v->x = (v->x-getImageWidth()/2+xTranslate)/scale;
v->y = (v->y-getImageHeight()/2+yTranslate)/scale;
2007-06-21 19:52:03 +00:00
}
double getImageWidth() {
const LEVEL *level = getLevel();
double min = 0.0, max = 0.0;
int i, j;
if(level) {
for(i = 0; i < level->nRooms; i++) {
for(j = 0; j < level->rooms[i].nVertices; j++) {
min = MIN(min, level->rooms[i].vertices[j].x);
max = MAX(max, level->rooms[i].vertices[j].x);
}
}
}
return (max-min+10)*scale;
2007-06-21 19:52:03 +00:00
}
double getImageHeight() {
const LEVEL *level = getLevel();
double min = 0.0, max = 0.0;
int i, j;
if(level) {
for(i = 0; i < level->nRooms; i++) {
for(j = 0; j < level->rooms[i].nVertices; j++) {
min = MIN(min, level->rooms[i].vertices[j].y);
max = MAX(max, level->rooms[i].vertices[j].y);
}
}
}
return (max-min+10)*scale;
2007-06-21 19:52:03 +00:00
}
double getXTranslate() {
return xTranslate;
}
void setXTranslate(double x) {
xTranslate = x;
repaint = TRUE;
2007-06-21 19:52:03 +00:00
}
double getYTranslate() {
return yTranslate;
}
void setYTranslate(double y) {
yTranslate = y;
repaint = TRUE;
}
void redraw() {
repaint = TRUE;
2007-06-21 19:52:03 +00:00
}