/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: AGG template library types. * Author: John Novak (jnovak@novacell.com) * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ******************************************************************************/ #include "renderers/agg/include/agg_rendering_buffer.h" /* * interface to a shapeObj representing lines, providing the functions * needed by the agg rasterizer. treats shapeObjs with multiple linestrings. */ class line_adaptor { public: line_adaptor(shapeObj *shape):s(shape) { m_line=s->line; /*first line*/ m_point=m_line->point; /*current vertex is first vertex of first line*/ m_lend=&(s->line[s->numlines]); /*pointer to after last line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } /* a class with virtual functions should also provide a virtual destructor */ virtual ~line_adaptor() {} void rewind(unsigned) { m_line=s->line; /*first line*/ m_point=m_line->point; /*current vertex is first vertex of first line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } virtual unsigned vertex(double* x, double* y) { if(m_point < m_pend) { /*here we treat the case where a real vertex is returned*/ bool first = m_point == m_line->point; /*is this the first vertex of a line*/ *x = m_point->x; *y = m_point->y; m_point++; return first ? mapserver::path_cmd_move_to : mapserver::path_cmd_line_to; } /*if here, we're at the end of a line*/ m_line++; *x = *y = 0.0; if(m_line>=m_lend) /*is this the last line of the shapObj. normally, (m_line==m_lend) should be a sufficient test, as the caller should not call this function if a previous call returned path_cmd_stop.*/ return mapserver::path_cmd_stop; /*no more points to process*/ /*if here, there are more lines in the shapeObj, continue with next one*/ m_point=m_line->point; /*pointer to first point of next line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last point of next line*/ return vertex(x,y); /*this will return the first point of the next line*/ } private: shapeObj *s; lineObj *m_line, /*current line pointer*/ *m_lend; /*points to after the last line*/ pointObj *m_point, /*current point*/ *m_pend; /*points to after last point of current line*/ }; class offset_line_adaptor: public line_adaptor { public: offset_line_adaptor(shapeObj *shape, double ox, double oy):line_adaptor(shape),ox(ox),oy(oy) { } unsigned vertex(double* x, double* y) { unsigned ret = line_adaptor::vertex(x,y); *x+=ox; *y+=oy; return ret; } private: double ox,oy; }; class polygon_adaptor { public: polygon_adaptor(shapeObj *shape):s(shape),m_stop(false) { m_line=s->line; /*first lines*/ m_point=m_line->point; /*first vertex of first line*/ m_lend=&(s->line[s->numlines]); /*pointer to after last line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } /* a class with virtual functions should also provide a virtual destructor */ virtual ~polygon_adaptor() {} void rewind(unsigned) { /*reset pointers*/ m_stop=false; m_line=s->line; m_point=m_line->point; m_pend=&(m_line->point[m_line->numpoints]); } virtual unsigned vertex(double* x, double* y) { if(m_point < m_pend) { /*if here, we have a real vertex*/ bool first = m_point == m_line->point; *x = m_point->x; *y = m_point->y; m_point++; return first ? mapserver::path_cmd_move_to : mapserver::path_cmd_line_to; } *x = *y = 0.0; if(!m_stop) { /*if here, we're after the last vertex of the current line * we return the command to close the current polygon*/ m_line++; if(m_line>=m_lend) { /*if here, we've finished all the vertexes of the shape. * we still return the command to close the current polygon, * but set m_stop so the subsequent call to vertex() will return * the stop command*/ m_stop=true; return mapserver::path_cmd_end_poly; } /*if here, there's another line in the shape, so we set the pointers accordingly * and return the command to close the current polygon*/ m_point=m_line->point; /*first vertex of next line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of next line*/ return mapserver::path_cmd_end_poly; } /*if here, a previous call to vertex informed us that we'd consumed all the vertexes * of the shape. return the command to stop processing this shape*/ return mapserver::path_cmd_stop; } private: shapeObj *s; double ox,oy; lineObj *m_line, /*pointer to current line*/ *m_lend; /*pointer to after last line of the shape*/ pointObj *m_point, /*pointer to current vertex*/ *m_pend; /*pointer to after last vertex of current line*/ bool m_stop; /*should next call return stop command*/ }; class offset_polygon_adaptor: public polygon_adaptor { public: offset_polygon_adaptor(shapeObj *shape, double ox, double oy):polygon_adaptor(shape),ox(ox),oy(oy) { } unsigned vertex(double* x, double* y) { unsigned ret = polygon_adaptor::vertex(x,y); *x+=ox; *y+=oy; return ret; } private: double ox,oy; };