1 /*
2  * Kuklomenos
3  * Copyright (C) 2008-2009 Martin Bays <mbays@sdf.lonestar.org>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see http://www.gnu.org/licenses/.
17  */
18 
19 #include <algorithm>
20 #include <SDL/SDL.h>
21 #include <SDL_gfxPrimitivesDirty.h>
22 
23 #include "coords.h"
24 #include "gfx.h"
25 #include "geom.h"
26 #include "settings.h"
27 
View(CartCoord icentre,float izoom,float iangle)28 View::View(CartCoord icentre, float izoom, float iangle) :
29     centre(icentre), zoom(izoom), angle(iangle) {}
30 
coord(const CartCoord & c) const31 ScreenCoord View::coord(const CartCoord &c) const
32 {
33     RelCartCoord d( (c-centre).rotated(angle) );
34     return ScreenCoord(
35 	    screenGeom.centre.x+(int)(d.dx*zoom),
36 	    screenGeom.centre.y-(int)(d.dy*zoom));
37 }
38 
inView(const CartCoord & c,float in) const39 bool View::inView(const CartCoord &c, float in) const
40 {
41     RelCartCoord d = c-centre;
42     return ( (zoom*zoom)*(d.dx*d.dx+d.dy*d.dy) <= (screenGeom.rad-in)*(screenGeom.rad-in) );
43 }
44 
draw(SDL_Surface * surface,const View & view,View * boundView,bool noAA)45 int Line::draw(SDL_Surface* surface, const View& view, View* boundView, bool noAA)
46 {
47     ScreenCoord s = view.coord(start);
48     ScreenCoord e = view.coord(end);
49     const bool useAA = ( (settings.useAA==AA_YES && !noAA) ||
50 	    settings.useAA==AA_FORCE );
51 
52     Uint32 drawColour = colour;
53 
54     if (!boundView || (boundView->inView(start) && boundView->inView(end)))
55 	return ( useAA ? aalineColor : lineColor )
56 	    (surface, s.x, s.y, e.x, e.y, drawColour);
57     else
58 	return 0;
59 }
60 
draw(SDL_Surface * surface,const View & view,View * boundView,bool noAA)61 int Circle::draw(SDL_Surface* surface, const View& view, View* boundView, bool noAA)
62 {
63     bool useAA = ( (settings.useAA==AA_YES && !noAA) ||
64 	    settings.useAA==AA_FORCE );
65     ScreenCoord c = view.coord(centre);
66     float screenRad = r*view.zoom;
67 
68     if (screenRad > 2*screenGeom.rad)
69 	// our AA circle algorithm doesn't handle huge circles well
70 	useAA = false;
71 
72     if (!boundView || boundView->inView(centre, r*boundView->zoom))
73 	return (filled ? filledCircleColor :
74 		useAA ? aacircleColor : circleColor)
75 	    (surface, c.x, c.y, int(screenRad), colour);
76     else
77 	return 0;
78 }
79 
draw(SDL_Surface * surface,const View & view,View * boundView,bool noAA)80 int Polygon::draw(SDL_Surface* surface, const View& view, View* boundView, bool noAA)
81 {
82     const bool useAA = ( (settings.useAA==AA_YES && !noAA) ||
83 	    settings.useAA==AA_FORCE );
84 
85     for (int i=0; i<n; i++)
86     {
87 	if (boundView && !boundView->inView(points[i]))
88 	    return 0;
89     }
90 
91     Sint16 *sx = new Sint16[n];
92     Sint16 *sy = new Sint16[n];
93     int ret;
94 
95     for (int i=0; i<n; i++)
96     {
97 	ScreenCoord s = view.coord(points[i]);
98 	sx[i] = s.x;
99 	sy[i] = s.y;
100     }
101 
102     ret = ( filled ? filledPolygonColor :
103 	    useAA ? aapolygonColor : polygonColor )(
104 		surface, sx, sy, n, colour);
105 
106     delete[] sx;
107     delete[] sy;
108     return ret;
109 }
110 
draw(SDL_Surface * surface,const View & view,View * boundView,bool noAA)111 int Pixel::draw(SDL_Surface* surface, const View& view, View* boundView, bool noAA)
112 {
113     if (boundView && !boundView->inView(point))
114 	return 0;
115     else
116     {
117 	ScreenCoord c = view.coord(point);
118 	return pixelColor(surface, c.x, c.y, colour);
119     }
120 }
121