/* KLayout Layout Viewer Copyright (C) 2006-2020 Matthias Koefferlein 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HDR_layD25MemChunks #define HDR_layD25MemChunks #include #include #include "tlObject.h" #include // for memcpy namespace lay { template struct gl_type2enum { GLenum operator() () const; }; template <> struct gl_type2enum { GLenum operator() () const { return GL_FLOAT; } }; /** * @brief Provides a semi-contiguous array of objects * * The objects are kept in chunks of ChunkLen items. * The blocks can be accessed individually. The array can be * cleared and new items can be added. No insert or delete. * * This object is intended to be used for keeping vertex, * color or point data for OpenGL. */ template class mem_chunks : public QDialog { public: struct chunk { public: chunk () : m_len (0), m_next (0) { // .. nothing yet .. } chunk (const chunk &other) : m_len (0), m_next (0) { operator= (other); } chunk &operator= (const chunk &other) { if (this != &other) { memcpy (&m_objects, &other.m_objects, sizeof (m_objects)); m_len = other.m_len; } return *this; } const Obj *front () const { return m_objects; } size_t size () const { return m_len; } const chunk *next () const { return m_next; } private: friend class mem_chunks; Obj m_objects [ChunkLen]; size_t m_len; chunk *m_next; }; class iterator { public: iterator (chunk *ch = 0) : mp_chunk (ch) { // .. nothing yet .. } bool operator== (iterator other) const { return mp_chunk == other.mp_chunk; } bool operator!= (iterator other) const { return mp_chunk != other.mp_chunk; } const chunk &operator* () const { return *mp_chunk; } const chunk *operator-> () const { return mp_chunk; } void operator++ () { mp_chunk = mp_chunk->next (); } private: const chunk *mp_chunk; }; /** * @brief Default constructor * Creates an empty array */ mem_chunks () : mp_chunks (0), mp_last_chunk (0) { // .. nothing yet .. } /** * @brief Destructor */ ~mem_chunks () { clear (); } /** * @brief Copy constructor */ mem_chunks (const mem_chunks &other) : mp_chunks (0), mp_last_chunk (0) { operator= (other); } /** * @brief Assignment */ mem_chunks &operator= (const mem_chunks &other) { if (this != &other) { clear (); const chunk *ch = other.mp_chunks; while (ch) { if (! mp_chunks) { mp_last_chunk = mp_chunks = new chunk (*ch); } else { mp_last_chunk->m_next = new chunk (*ch); mp_last_chunk = mp_last_chunk->m_next; } ch = ch->next (); } } return *this; } /** * @brief Clears the array */ void clear () { chunk *ch = mp_chunks; mp_chunks = 0; mp_last_chunk = 0; while (ch) { chunk *del = ch; ch = ch->m_next; delete del; } } /** * @brief Adds an element to the array */ void add (const Obj &element) { if (! mp_last_chunk) { mp_chunks = mp_last_chunk = new chunk (); } if (mp_last_chunk->m_len >= ChunkLen) { mp_last_chunk->m_next = new chunk (); mp_last_chunk = mp_last_chunk->m_next; } mp_last_chunk->m_objects [mp_last_chunk->m_len++] = element; } /** * @brief Adds two elements */ void add (const Obj &e1, const Obj &e2) { add (e1); add (e2); } /** * @brief Adds three elements */ void add (const Obj &e1, const Obj &e2, const Obj &e3) { add (e1); add (e2); add (e3); } /** * @brief begin iterator */ iterator begin () const { return iterator (mp_chunks); } /** * @brief end iterator */ iterator end () const { return iterator (); } /** * @brief Draw to the given context */ void draw_to (QOpenGLFunctions *ctx, GLuint location, GLenum mode) const { for (iterator c = begin (); c != end (); ++c) { ctx->glVertexAttribPointer (location, 3, gl_type2enum () (), GL_FALSE, 0, c->front ()); ctx->glDrawArrays (mode, 0, c->size () / 3); } } private: chunk *mp_chunks; chunk *mp_last_chunk; }; } #endif