<commit_before>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012, ARIEL MALKA ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE MODIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

#include "chronotext/font/xf/Font.h"
#include "chronotext/font/xf/FontManager.h"

using namespace ci;
using namespace std;

namespace chronotext
{
    namespace xf
    {
        Font::Font(FontManager &fontManager, FontData *data, FontTexture *texture, const Properties &properties)
        :
        texture(texture),
        properties(properties),
        indices(fontManager.getIndices(properties.slotCapacity)),
        began(0),
        hasClip(false),
        sequence(nullptr)
        {
            assert(properties.slotCapacity > 0);
            assert(properties.slotCapacity <= 8192);

            // ---

            glyphCount = data->glyphCount;
            glyphs = data->glyphs;

            baseSize = data->baseSize;
            height = data->height;
            ascent = data->ascent;
            descent = data->descent;
            spaceAdvance = data->spaceAdvance;
            strikethroughFactor = data->strikethroughFactor;
            underlineOffset = data->underlineOffset;
            lineThickness = data->lineThickness;

            w = data->w;
            h = data->h;
            le = data->le;
            te = data->te;
            advance = data->advance;

            u1 = data->u1;
            v1 = data->v1;
            u2 = data->u2;
            v2 = data->v2;

            // ---

            if (gl::isExtensionAvailable("GL_EXT_texture_filter_anisotropic"))
            {
                if (properties.useAnisotropy)
                {
                    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy);
                }
                else
                {
                    anisotropy = 1;
                }
            }
            else
            {
                anisotropy = 0;
            }

            // ---

            setSize(baseSize);
            setDirection(+1);
            setAxis(Vec2f(+1, +1));
            setColor(0, 0, 0, 1);
        }

        bool Font::isSpace(wchar_t c) const
        {
            return (c == 0x20) || (c == 0xa0);
        }

        bool Font::isValid(wchar_t c) const
        {
            return glyphs.count(c);
        }

        int Font::getGlyphIndex(wchar_t c) const
        {
            if (isSpace(c))
            {
                return -2;
            }
            else
            {
                auto it = glyphs.find(c);

                if (it == glyphs.end())
                {
                    return -1; // SHALL WE USE A "MISSING GLYPH" AND RETURN ITS INDEX?
                }
                else
                {
                    return it->second;
                }
            }
        }

        wstring Font::getCharacters() const
        {
            wstring characters;
            characters.reserve(glyphs.size());

            for (auto it : glyphs)
            {
                characters.push_back(it.first);
            }

            return characters;
        }

        void Font::setSize(float size)
        {
            this->size = size;
            sizeRatio = size / baseSize;
        }

        void Font::setDirection(float direction)
        {
            this->direction = direction;
        }

        void Font::setAxis(const Vec2f &axis)
        {
            this->axis = axis;
        }

        void Font::setColor(const ColorA &color)
        {
            this->color = color;
        }

        void Font::setColor(float r, float g, float b, float a)
        {
            color.r = r;
            color.g = g;
            color.b = b;
            color.a = a;
        }

        void Font::setStrikethroughFactor(float factor)
        {
            strikethroughFactor = factor;
        }

        void Font::setClip(const Rectf &clipRect)
        {
            this->clipRect = clipRect;
            hasClip = true;
        }

        void Font::setClip(float x1, float y1, float x2, float y2)
        {
            clipRect.x1 = x1;
            clipRect.y1 = y1;
            clipRect.x2 = x2;
            clipRect.y2 = y2;

            hasClip = true;
        }

        void Font::clearClip()
        {
            hasClip = false;
        }

        float Font::getSize() const
        {
            return size;
        }

        float Font::getDirection() const
        {
            return direction * axis.x;
        }

        const Vec2f& Font::getAxis() const
        {
            return axis;
        }

        float Font::getGlyphAdvance(int glyphIndex) const
        {
            if (glyphIndex == -2)
            {
                return spaceAdvance * sizeRatio;
            }
            else if (glyphIndex == -1)
            {
                return 0;
            }
            else
            {
                return advance[glyphIndex] * sizeRatio;
            }
        }

        float Font::getCharAdvance(wchar_t c) const
        {
            return getGlyphAdvance(getGlyphIndex(c));
        }

        float Font::getStringAdvance(const wstring &s) const
        {
            return getSubStringAdvance(s, 0, s.size());
        }

        float Font::getSubStringAdvance(const wstring &s, int begin, int end) const
        {
            float advance = 0;

            for (int i = begin; i < end; i++)
            {
                advance += getCharAdvance(s.at(i));
            }

            return advance;
        }

        float Font::getHeight() const
        {
            return height * sizeRatio;
        }

        float Font::getAscent() const
        {
            return ascent * sizeRatio;
        }

        float Font::getDescent() const
        {
            return descent * sizeRatio;
        }

        float Font::getStrikethroughOffset() const
        {
            return strikethroughFactor * (ascent - descent) * sizeRatio;
        }

        float Font::getUnderlineOffset() const
        {
            return underlineOffset * sizeRatio;
        }

        float Font::getLineThickness() const
        {
            return lineThickness * sizeRatio;
        }

        float Font::getOffsetX(const wstring &text, Alignment align) const
        {
            switch (align)
            {
                case ALIGN_MIDDLE:
                    return -0.5f * getStringAdvance(text) * direction;

                case ALIGN_LEFT:
                    return (direction > 0) ? 0 : getStringAdvance(text);

                case ALIGN_RIGHT:
                    return (direction > 0) ? -getStringAdvance(text) : 0;

                default:
                    return 0;
            }
        }

        float Font::getOffsetY(Alignment align) const
        {
            switch (align)
            {
                case ALIGN_MIDDLE:
                    return getStrikethroughOffset();

                case ALIGN_TOP:
                    return +getAscent();

                case ALIGN_BOTTOM:
                    return -getDescent();

                default:
                    return 0;
            }
        }

        FontMatrix* Font::getMatrix()
        {
            return &matrix;
        }

        const GLushort* Font::getIndices() const
        {
            return const_cast<GLushort*>(indices.data());
        }

        void Font::begin(bool useColor)
        {
            if (began == 0)
            {
                glEnable(GL_TEXTURE_2D);

                if (useColor)
                {
                    glEnableClientState(GL_COLOR_ARRAY);
                }
                else
                {
                    gl::color(color);
                }

                glEnableClientState(GL_VERTEX_ARRAY);
                glEnableClientState(GL_TEXTURE_COORD_ARRAY);

                // ---

                texture->bind(); // RELOADS TEXTURE, IF NECESSARY

                if (anisotropy)
                {
                    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
                }
            }
        }

        void Font::end(bool useColor)
        {
            if (began == 0)
            {
                glDisable(GL_TEXTURE_2D);

                if (useColor)
                {
                    glDisableClientState(GL_COLOR_ARRAY);
                }

                glDisableClientState(GL_VERTEX_ARRAY);
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            }
        }

        void Font::beginSequence(FontSequence *sequence, bool useColor)
        {
            if (began == 0)
            {
                sequenceUseColor = useColor;

                if (!batch)
                {
                    batch = unique_ptr<GlyphBatch>(new GlyphBatch);
                }
                else
                {
                    batch->clear();
                }

                if (sequence)
                {
                    this->sequence = sequence;
                    sequence->begin(useColor);
                }
                else
                {
                    begin(useColor);
                }

                clearClip();
            }

            began++;
        }

        void Font::endSequence()
        {
            began--;

            if (began == 0)
            {
                if (sequence)
                {
                    batch->pack();
                    sequence->addBatch(move(batch));

                    sequence->end();
                    sequence = nullptr;
                }
                else
                {
                    batch->flush(getIndices(), sequenceUseColor);
                    end(sequenceUseColor);
                }
            }
        }

        void Font::replaySequence(FontSequence *sequence)
        {
            begin(sequence->useColor);
            sequence->replay(getIndices());
            end(sequence->useColor);
        }

        void Font::incrementSequence()
        {
            if (sequenceUseColor)
            {
                batch->addColor(color);
            }

            if (batch->size() == properties.slotCapacity)
            {
                if (sequence)
                {
                    batch->pack();
                    sequence->addBatch(move(batch));
                }
                else
                {
                    batch->flush(getIndices(), sequenceUseColor);
                }

                if (!batch)
                {
                    batch = unique_ptr<GlyphBatch>(new GlyphBatch);
                }
                else
                {
                    batch->clear();
                }
            }
        }

        bool Font::fillQuad(GlyphQuad &quad, int glyphIndex, float x, float y) const
        {
            if (glyphIndex < 0)
            {
                return false;
            }
            else
            {
                if (direction * axis.x > 0)
                {
                    quad.x1 = x + le[glyphIndex] * sizeRatio;
                    quad.x2 = quad.x1 + w[glyphIndex] * sizeRatio;
                }
                else
                {
                    quad.x2 = x - le[glyphIndex] * sizeRatio;
                    quad.x1 = quad.x2 - w[glyphIndex] * sizeRatio;
                }

                if (axis.x > 0)
                {
                    quad.u1 = u1[glyphIndex];
                    quad.u2 = u2[glyphIndex];
                }
                else
                {
                    quad.u1 = u2[glyphIndex];
                    quad.u2 = u1[glyphIndex];
                }

                if (axis.y > 0)
                {
                    quad.y1 = y - te[glyphIndex] * sizeRatio;
                    quad.y2 = quad.y1 + h[glyphIndex] * sizeRatio;

                    quad.v1 = v1[glyphIndex];
                    quad.v2 = v2[glyphIndex];
                }
                else
                {
                    quad.y2 = y + te[glyphIndex] * sizeRatio;
                    quad.y1 = quad.y2 - h[glyphIndex] * sizeRatio;

                    quad.v1 = v2[glyphIndex];
                    quad.v2 = v1[glyphIndex];
                }

                return true;
            }
        }

        bool Font::clipQuad(GlyphQuad &quad) const
        {
            return quad.clip(clipRect, texture->getSize() * sizeRatio / axis);
        }

        void Font::addGlyph(int glyphIndex, float x, float y, float z)
        {
            GlyphQuad quad;

            if (fillQuad(quad, glyphIndex, x, y));
            {
                if (!hasClip || clipQuad(quad))
                {
                    batch->addQuad(quad);
                    incrementSequence();
                }
            }
        }

        void Font::addTransformedGlyph(int glyphIndex, float x, float y)
        {
            GlyphQuad quad;

            if (fillQuad(quad, glyphIndex, x, y));
            {
                if (!hasClip || clipQuad(quad))
                {
                    matrix.addTransformedQuad(quad, batch->vertices);
                    incrementSequence();
                }
            }
        }
    }
}
<commit_msg>XFont: FIXING NASTY REGRESSION<commit_after>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012, ARIEL MALKA ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE MODIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

#include "chronotext/font/xf/Font.h"
#include "chronotext/font/xf/FontManager.h"

using namespace ci;
using namespace std;

namespace chronotext
{
    namespace xf
    {
        Font::Font(FontManager &fontManager, FontData *data, FontTexture *texture, const Properties &properties)
        :
        texture(texture),
        properties(properties),
        indices(fontManager.getIndices(properties.slotCapacity)),
        began(0),
        hasClip(false),
        sequence(nullptr)
        {
            assert(properties.slotCapacity > 0);
            assert(properties.slotCapacity <= 8192);

            // ---

            glyphCount = data->glyphCount;
            glyphs = data->glyphs;

            baseSize = data->baseSize;
            height = data->height;
            ascent = data->ascent;
            descent = data->descent;
            spaceAdvance = data->spaceAdvance;
            strikethroughFactor = data->strikethroughFactor;
            underlineOffset = data->underlineOffset;
            lineThickness = data->lineThickness;

            w = data->w;
            h = data->h;
            le = data->le;
            te = data->te;
            advance = data->advance;

            u1 = data->u1;
            v1 = data->v1;
            u2 = data->u2;
            v2 = data->v2;

            // ---

            if (gl::isExtensionAvailable("GL_EXT_texture_filter_anisotropic"))
            {
                if (properties.useAnisotropy)
                {
                    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy);
                }
                else
                {
                    anisotropy = 1;
                }
            }
            else
            {
                anisotropy = 0;
            }

            // ---

            setSize(baseSize);
            setDirection(+1);
            setAxis(Vec2f(+1, +1));
            setColor(0, 0, 0, 1);
        }

        bool Font::isSpace(wchar_t c) const
        {
            return (c == 0x20) || (c == 0xa0);
        }

        bool Font::isValid(wchar_t c) const
        {
            return glyphs.count(c);
        }

        int Font::getGlyphIndex(wchar_t c) const
        {
            if (isSpace(c))
            {
                return -2;
            }
            else
            {
                auto it = glyphs.find(c);

                if (it == glyphs.end())
                {
                    return -1; // SHALL WE USE A "MISSING GLYPH" AND RETURN ITS INDEX?
                }
                else
                {
                    return it->second;
                }
            }
        }

        wstring Font::getCharacters() const
        {
            wstring characters;
            characters.reserve(glyphs.size());

            for (auto it : glyphs)
            {
                characters.push_back(it.first);
            }

            return characters;
        }

        void Font::setSize(float size)
        {
            this->size = size;
            sizeRatio = size / baseSize;
        }

        void Font::setDirection(float direction)
        {
            this->direction = direction;
        }

        void Font::setAxis(const Vec2f &axis)
        {
            this->axis = axis;
        }

        void Font::setColor(const ColorA &color)
        {
            this->color = color;
        }

        void Font::setColor(float r, float g, float b, float a)
        {
            color.r = r;
            color.g = g;
            color.b = b;
            color.a = a;
        }

        void Font::setStrikethroughFactor(float factor)
        {
            strikethroughFactor = factor;
        }

        void Font::setClip(const Rectf &clipRect)
        {
            this->clipRect = clipRect;
            hasClip = true;
        }

        void Font::setClip(float x1, float y1, float x2, float y2)
        {
            clipRect.x1 = x1;
            clipRect.y1 = y1;
            clipRect.x2 = x2;
            clipRect.y2 = y2;

            hasClip = true;
        }

        void Font::clearClip()
        {
            hasClip = false;
        }

        float Font::getSize() const
        {
            return size;
        }

        float Font::getDirection() const
        {
            return direction * axis.x;
        }

        const Vec2f& Font::getAxis() const
        {
            return axis;
        }

        float Font::getGlyphAdvance(int glyphIndex) const
        {
            if (glyphIndex == -2)
            {
                return spaceAdvance * sizeRatio;
            }
            else if (glyphIndex == -1)
            {
                return 0;
            }
            else
            {
                return advance[glyphIndex] * sizeRatio;
            }
        }

        float Font::getCharAdvance(wchar_t c) const
        {
            return getGlyphAdvance(getGlyphIndex(c));
        }

        float Font::getStringAdvance(const wstring &s) const
        {
            return getSubStringAdvance(s, 0, s.size());
        }

        float Font::getSubStringAdvance(const wstring &s, int begin, int end) const
        {
            float advance = 0;

            for (int i = begin; i < end; i++)
            {
                advance += getCharAdvance(s.at(i));
            }

            return advance;
        }

        float Font::getHeight() const
        {
            return height * sizeRatio;
        }

        float Font::getAscent() const
        {
            return ascent * sizeRatio;
        }

        float Font::getDescent() const
        {
            return descent * sizeRatio;
        }

        float Font::getStrikethroughOffset() const
        {
            return strikethroughFactor * (ascent - descent) * sizeRatio;
        }

        float Font::getUnderlineOffset() const
        {
            return underlineOffset * sizeRatio;
        }

        float Font::getLineThickness() const
        {
            return lineThickness * sizeRatio;
        }

        float Font::getOffsetX(const wstring &text, Alignment align) const
        {
            switch (align)
            {
                case ALIGN_MIDDLE:
                    return -0.5f * getStringAdvance(text) * direction;

                case ALIGN_LEFT:
                    return (direction > 0) ? 0 : getStringAdvance(text);

                case ALIGN_RIGHT:
                    return (direction > 0) ? -getStringAdvance(text) : 0;

                default:
                    return 0;
            }
        }

        float Font::getOffsetY(Alignment align) const
        {
            switch (align)
            {
                case ALIGN_MIDDLE:
                    return getStrikethroughOffset();

                case ALIGN_TOP:
                    return +getAscent();

                case ALIGN_BOTTOM:
                    return -getDescent();

                default:
                    return 0;
            }
        }

        FontMatrix* Font::getMatrix()
        {
            return &matrix;
        }

        const GLushort* Font::getIndices() const
        {
            return const_cast<GLushort*>(indices.data());
        }

        void Font::begin(bool useColor)
        {
            if (began == 0)
            {
                glEnable(GL_TEXTURE_2D);

                if (useColor)
                {
                    glEnableClientState(GL_COLOR_ARRAY);
                }
                else
                {
                    gl::color(color);
                }

                glEnableClientState(GL_VERTEX_ARRAY);
                glEnableClientState(GL_TEXTURE_COORD_ARRAY);

                // ---

                texture->bind(); // RELOADS TEXTURE, IF NECESSARY

                if (anisotropy)
                {
                    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
                }
            }
        }

        void Font::end(bool useColor)
        {
            if (began == 0)
            {
                glDisable(GL_TEXTURE_2D);

                if (useColor)
                {
                    glDisableClientState(GL_COLOR_ARRAY);
                }

                glDisableClientState(GL_VERTEX_ARRAY);
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            }
        }

        void Font::beginSequence(FontSequence *sequence, bool useColor)
        {
            if (began == 0)
            {
                sequenceUseColor = useColor;

                if (!batch)
                {
                    batch = unique_ptr<GlyphBatch>(new GlyphBatch);
                }
                else
                {
                    batch->clear();
                }

                if (sequence)
                {
                    this->sequence = sequence;
                    sequence->begin(useColor);
                }
                else
                {
                    begin(useColor);
                }

                clearClip();
            }

            began++;
        }

        void Font::endSequence()
        {
            began--;

            if (began == 0)
            {
                if (sequence)
                {
                    batch->pack();
                    sequence->addBatch(move(batch));

                    sequence->end();
                    sequence = nullptr;
                }
                else
                {
                    batch->flush(getIndices(), sequenceUseColor);
                    end(sequenceUseColor);
                }
            }
        }

        void Font::replaySequence(FontSequence *sequence)
        {
            begin(sequence->useColor);
            sequence->replay(getIndices());
            end(sequence->useColor);
        }

        void Font::incrementSequence()
        {
            if (sequenceUseColor)
            {
                batch->addColor(color);
            }

            if (batch->size() == properties.slotCapacity)
            {
                if (sequence)
                {
                    batch->pack();
                    sequence->addBatch(move(batch));
                }
                else
                {
                    batch->flush(getIndices(), sequenceUseColor);
                }

                if (!batch)
                {
                    batch = unique_ptr<GlyphBatch>(new GlyphBatch);
                }
                else
                {
                    batch->clear();
                }
            }
        }

        bool Font::fillQuad(GlyphQuad &quad, int glyphIndex, float x, float y) const
        {
            if (glyphIndex < 0)
            {
                return false;
            }
            else
            {
                if (direction * axis.x > 0)
                {
                    quad.x1 = x + le[glyphIndex] * sizeRatio;
                    quad.x2 = quad.x1 + w[glyphIndex] * sizeRatio;
                }
                else
                {
                    quad.x2 = x - le[glyphIndex] * sizeRatio;
                    quad.x1 = quad.x2 - w[glyphIndex] * sizeRatio;
                }

                if (axis.x > 0)
                {
                    quad.u1 = u1[glyphIndex];
                    quad.u2 = u2[glyphIndex];
                }
                else
                {
                    quad.u1 = u2[glyphIndex];
                    quad.u2 = u1[glyphIndex];
                }

                if (axis.y > 0)
                {
                    quad.y1 = y - te[glyphIndex] * sizeRatio;
                    quad.y2 = quad.y1 + h[glyphIndex] * sizeRatio;

                    quad.v1 = v1[glyphIndex];
                    quad.v2 = v2[glyphIndex];
                }
                else
                {
                    quad.y2 = y + te[glyphIndex] * sizeRatio;
                    quad.y1 = quad.y2 - h[glyphIndex] * sizeRatio;

                    quad.v1 = v2[glyphIndex];
                    quad.v2 = v1[glyphIndex];
                }

                return true;
            }
        }

        bool Font::clipQuad(GlyphQuad &quad) const
        {
            return quad.clip(clipRect, texture->getSize() * sizeRatio / axis);
        }

        void Font::addGlyph(int glyphIndex, float x, float y, float z)
        {
            GlyphQuad quad;

            if (fillQuad(quad, glyphIndex, x, y))
            {
                if (!hasClip || clipQuad(quad))
                {
                    batch->addQuad(quad);
                    incrementSequence();
                }
            }
        }

        void Font::addTransformedGlyph(int glyphIndex, float x, float y)
        {
            GlyphQuad quad;

            if (fillQuad(quad, glyphIndex, x, y))
            {
                if (!hasClip || clipQuad(quad))
                {
                    matrix.addTransformedQuad(quad, batch->vertices);
                    incrementSequence();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// 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 or substantial portions of the 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.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <Context.h>
#include <Column.h>
#include <ColDepends.h>
#include <ColDescription.h>
#include <ColDue.h>
#include <ColEnd.h>
#include <ColEntry.h>
#include <ColID.h>
#include <ColIMask.h>
#include <ColMask.h>
#include <ColModified.h>
#include <ColParent.h>
#include <ColProject.h>
#include <ColRecur.h>
#include <ColScheduled.h>
#include <ColStart.h>
#include <ColStatus.h>
#include <ColString.h>
#include <ColTags.h>
#include <ColUntil.h>
#include <ColUrgency.h>
#include <ColUUID.h>
#include <ColUDA.h>
#include <ColWait.h>
#include <text.h>
#include <i18n.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
// Supports the complete column definition:
//
//   <type>[.<format>]
//
Column* Column::factory (const std::string& name, const std::string& report)
{
  // Decompose name into type and style.
  auto dot = name.find ('.');
  std::string column_name;
  std::string column_style;
  if (dot != std::string::npos)
  {
    column_name = name.substr (0, dot);
    column_style = name.substr (dot + 1);
  }
  else
  {
    column_name = name;
    column_style = "default";
  }

  Column* c;
       if (column_name == "depends")     c = new ColumnDepends ();
  else if (column_name == "description") c = new ColumnDescription ();
  else if (column_name == "due")         c = new ColumnDue ();
  else if (column_name == "end")         c = new ColumnEnd ();
  else if (column_name == "entry")       c = new ColumnEntry ();
  else if (column_name == "id")          c = new ColumnID ();
  else if (column_name == "imask")       c = new ColumnIMask ();
  else if (column_name == "mask")        c = new ColumnMask ();
  else if (column_name == "modified")    c = new ColumnModified ();
  else if (column_name == "parent")      c = new ColumnParent ();
  else if (column_name == "project")     c = new ColumnProject ();
  else if (column_name == "recur")       c = new ColumnRecur ();
  else if (column_name == "scheduled")   c = new ColumnScheduled ();
  else if (column_name == "start")       c = new ColumnStart ();
  else if (column_name == "status")      c = new ColumnStatus ();
  else if (column_name == "tags")        c = new ColumnTags ();
  else if (column_name == "until")       c = new ColumnUntil ();
  else if (column_name == "urgency")     c = new ColumnUrgency ();
  else if (column_name == "uuid")        c = new ColumnUUID ();
  else if (column_name == "wait")        c = new ColumnWait ();

  // Special non-task column.
  else if (column_name == "string")      c = new ColumnString ();

  // UDA.
  else if (context.config.get ("uda." + column_name + ".type") != "")
    c = Column::uda (column_name);

  else
    throw format (STRING_COLUMN_BAD_NAME, column_name);

  c->setReport (report);
  c->setStyle (column_style);
  return c;
}

////////////////////////////////////////////////////////////////////////////////
// Bulk column instantiation.
void Column::factory (std::map <std::string, Column*>& all)
{
  Column* c;

  c = new ColumnDepends ();        all[c->_name] = c;
  c = new ColumnDescription ();    all[c->_name] = c;
  c = new ColumnDue ();            all[c->_name] = c;
  c = new ColumnEnd ();            all[c->_name] = c;
  c = new ColumnEntry ();          all[c->_name] = c;
  c = new ColumnID ();             all[c->_name] = c;
  c = new ColumnIMask ();          all[c->_name] = c;
  c = new ColumnMask ();           all[c->_name] = c;
  c = new ColumnModified ();       all[c->_name] = c;
  c = new ColumnParent ();         all[c->_name] = c;
  c = new ColumnProject ();        all[c->_name] = c;
  c = new ColumnRecur ();          all[c->_name] = c;
  c = new ColumnScheduled ();      all[c->_name] = c;
  c = new ColumnStart ();          all[c->_name] = c;
  c = new ColumnStatus ();         all[c->_name] = c;
  c = new ColumnTags ();           all[c->_name] = c;
  c = new ColumnUntil ();          all[c->_name] = c;
  c = new ColumnUrgency ();        all[c->_name] = c;
  c = new ColumnUUID ();           all[c->_name] = c;
  c = new ColumnWait ();           all[c->_name] = c;

  Column::uda (all);
}

////////////////////////////////////////////////////////////////////////////////
void Column::uda (std::map <std::string, Column*>& all)
{
  // For each UDA, instantiate and initialize ColumnUDA().
  std::map <std::string, int> udas;

  for (auto& i : context.config)
  {
    if (i.first.substr (0, 4) == "uda.")
    {
      std::string::size_type period = 4;
      if ((period = i.first.find ('.', period)) != std::string::npos)
        udas[i.first.substr (4, period - 4)] = 0;
    }
  }

  for (auto& uda : udas)
  {
    if (all.find (uda.first) != all.end ())
      throw format (STRING_UDA_COLLISION, uda.first);

    Column* c = Column::uda (uda.first);
    all[c->_name] = c;
  }
}

////////////////////////////////////////////////////////////////////////////////
Column* Column::uda (const std::string& name)
{
  ColumnUDA* c = new ColumnUDA ();
  c->_name = name;

  std::string key = "uda." + name + ".type";
  c->_type = context.config.get (key);
  if (c->_type == "")
    context.error (format  (STRING_UDA_TYPE_MISSING, name));

  if (c->_type != "string"   &&
      c->_type != "date"     &&
      c->_type != "duration" &&
      c->_type != "numeric")
    context.error (STRING_UDA_TYPE);

  key = "uda." + name + ".label";
  if (context.config.get (key) != "")
    c->_label = context.config.get (key);

  key = "uda." + name + ".values";
  if (context.config.get (key) != "")
    split (c->_values, context.config.get (key), ',');

  return c;
}

////////////////////////////////////////////////////////////////////////////////
Column::Column ()
: _name ("")
, _type ("string")
, _style ("default")
, _label ("")
, _report ("")
, _modifiable (true)
, _uda (false)
, _fixed_width (false)
{
}

////////////////////////////////////////////////////////////////////////////////
Column::~Column ()
{
}

////////////////////////////////////////////////////////////////////////////////
void Column::renderHeader (
  std::vector <std::string>& lines,
  int width,
  Color& color)
{
  if (context.verbose ("label") &&
     nontrivial (_label))
  {
    // Create a basic label.
    std::string header;
    header.reserve (width);
    header = _label;

    // Create a fungible copy.
    Color c = color;

    // Now underline the header, or add a dashed line.
    if (context.color () &&
        context.config.getBoolean ("fontunderline"))
    {
      c.blend (Color (Color::nocolor, Color::nocolor, true, false, false));
      lines.push_back (c.colorize (leftJustify (header, width)));
    }
    else
    {
      lines.push_back (c.colorize (leftJustify (header, width)));
      lines.push_back (c.colorize (std::string (width, '-')));
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
void Column::setStyle (const std::string& style)
{
  if (style != "default" &&
      std::find (_styles.begin (), _styles.end (), style) == _styles.end ())
    throw format (STRING_COLUMN_BAD_FORMAT, _name, style);

  _style = style;
}

////////////////////////////////////////////////////////////////////////////////
bool Column::validate (std::string& input)
{
  return input.length () ? true : false;
}

////////////////////////////////////////////////////////////////////////////////
// No L10N.
bool Column::can_modify ()
{
  return false;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Column: Missing include<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// 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 or substantial portions of the 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.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <algorithm>
#include <Context.h>
#include <Column.h>
#include <ColDepends.h>
#include <ColDescription.h>
#include <ColDue.h>
#include <ColEnd.h>
#include <ColEntry.h>
#include <ColID.h>
#include <ColIMask.h>
#include <ColMask.h>
#include <ColModified.h>
#include <ColParent.h>
#include <ColProject.h>
#include <ColRecur.h>
#include <ColScheduled.h>
#include <ColStart.h>
#include <ColStatus.h>
#include <ColString.h>
#include <ColTags.h>
#include <ColUntil.h>
#include <ColUrgency.h>
#include <ColUUID.h>
#include <ColUDA.h>
#include <ColWait.h>
#include <text.h>
#include <i18n.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
// Supports the complete column definition:
//
//   <type>[.<format>]
//
Column* Column::factory (const std::string& name, const std::string& report)
{
  // Decompose name into type and style.
  auto dot = name.find ('.');
  std::string column_name;
  std::string column_style;
  if (dot != std::string::npos)
  {
    column_name = name.substr (0, dot);
    column_style = name.substr (dot + 1);
  }
  else
  {
    column_name = name;
    column_style = "default";
  }

  Column* c;
       if (column_name == "depends")     c = new ColumnDepends ();
  else if (column_name == "description") c = new ColumnDescription ();
  else if (column_name == "due")         c = new ColumnDue ();
  else if (column_name == "end")         c = new ColumnEnd ();
  else if (column_name == "entry")       c = new ColumnEntry ();
  else if (column_name == "id")          c = new ColumnID ();
  else if (column_name == "imask")       c = new ColumnIMask ();
  else if (column_name == "mask")        c = new ColumnMask ();
  else if (column_name == "modified")    c = new ColumnModified ();
  else if (column_name == "parent")      c = new ColumnParent ();
  else if (column_name == "project")     c = new ColumnProject ();
  else if (column_name == "recur")       c = new ColumnRecur ();
  else if (column_name == "scheduled")   c = new ColumnScheduled ();
  else if (column_name == "start")       c = new ColumnStart ();
  else if (column_name == "status")      c = new ColumnStatus ();
  else if (column_name == "tags")        c = new ColumnTags ();
  else if (column_name == "until")       c = new ColumnUntil ();
  else if (column_name == "urgency")     c = new ColumnUrgency ();
  else if (column_name == "uuid")        c = new ColumnUUID ();
  else if (column_name == "wait")        c = new ColumnWait ();

  // Special non-task column.
  else if (column_name == "string")      c = new ColumnString ();

  // UDA.
  else if (context.config.get ("uda." + column_name + ".type") != "")
    c = Column::uda (column_name);

  else
    throw format (STRING_COLUMN_BAD_NAME, column_name);

  c->setReport (report);
  c->setStyle (column_style);
  return c;
}

////////////////////////////////////////////////////////////////////////////////
// Bulk column instantiation.
void Column::factory (std::map <std::string, Column*>& all)
{
  Column* c;

  c = new ColumnDepends ();        all[c->_name] = c;
  c = new ColumnDescription ();    all[c->_name] = c;
  c = new ColumnDue ();            all[c->_name] = c;
  c = new ColumnEnd ();            all[c->_name] = c;
  c = new ColumnEntry ();          all[c->_name] = c;
  c = new ColumnID ();             all[c->_name] = c;
  c = new ColumnIMask ();          all[c->_name] = c;
  c = new ColumnMask ();           all[c->_name] = c;
  c = new ColumnModified ();       all[c->_name] = c;
  c = new ColumnParent ();         all[c->_name] = c;
  c = new ColumnProject ();        all[c->_name] = c;
  c = new ColumnRecur ();          all[c->_name] = c;
  c = new ColumnScheduled ();      all[c->_name] = c;
  c = new ColumnStart ();          all[c->_name] = c;
  c = new ColumnStatus ();         all[c->_name] = c;
  c = new ColumnTags ();           all[c->_name] = c;
  c = new ColumnUntil ();          all[c->_name] = c;
  c = new ColumnUrgency ();        all[c->_name] = c;
  c = new ColumnUUID ();           all[c->_name] = c;
  c = new ColumnWait ();           all[c->_name] = c;

  Column::uda (all);
}

////////////////////////////////////////////////////////////////////////////////
void Column::uda (std::map <std::string, Column*>& all)
{
  // For each UDA, instantiate and initialize ColumnUDA().
  std::map <std::string, int> udas;

  for (auto& i : context.config)
  {
    if (i.first.substr (0, 4) == "uda.")
    {
      std::string::size_type period = 4;
      if ((period = i.first.find ('.', period)) != std::string::npos)
        udas[i.first.substr (4, period - 4)] = 0;
    }
  }

  for (auto& uda : udas)
  {
    if (all.find (uda.first) != all.end ())
      throw format (STRING_UDA_COLLISION, uda.first);

    Column* c = Column::uda (uda.first);
    all[c->_name] = c;
  }
}

////////////////////////////////////////////////////////////////////////////////
Column* Column::uda (const std::string& name)
{
  ColumnUDA* c = new ColumnUDA ();
  c->_name = name;

  std::string key = "uda." + name + ".type";
  c->_type = context.config.get (key);
  if (c->_type == "")
    context.error (format  (STRING_UDA_TYPE_MISSING, name));

  if (c->_type != "string"   &&
      c->_type != "date"     &&
      c->_type != "duration" &&
      c->_type != "numeric")
    context.error (STRING_UDA_TYPE);

  key = "uda." + name + ".label";
  if (context.config.get (key) != "")
    c->_label = context.config.get (key);

  key = "uda." + name + ".values";
  if (context.config.get (key) != "")
    split (c->_values, context.config.get (key), ',');

  return c;
}

////////////////////////////////////////////////////////////////////////////////
Column::Column ()
: _name ("")
, _type ("string")
, _style ("default")
, _label ("")
, _report ("")
, _modifiable (true)
, _uda (false)
, _fixed_width (false)
{
}

////////////////////////////////////////////////////////////////////////////////
Column::~Column ()
{
}

////////////////////////////////////////////////////////////////////////////////
void Column::renderHeader (
  std::vector <std::string>& lines,
  int width,
  Color& color)
{
  if (context.verbose ("label") &&
     nontrivial (_label))
  {
    // Create a basic label.
    std::string header;
    header.reserve (width);
    header = _label;

    // Create a fungible copy.
    Color c = color;

    // Now underline the header, or add a dashed line.
    if (context.color () &&
        context.config.getBoolean ("fontunderline"))
    {
      c.blend (Color (Color::nocolor, Color::nocolor, true, false, false));
      lines.push_back (c.colorize (leftJustify (header, width)));
    }
    else
    {
      lines.push_back (c.colorize (leftJustify (header, width)));
      lines.push_back (c.colorize (std::string (width, '-')));
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
void Column::setStyle (const std::string& style)
{
  if (style != "default" &&
      std::find (_styles.begin (), _styles.end (), style) == _styles.end ())
    throw format (STRING_COLUMN_BAD_FORMAT, _name, style);

  _style = style;
}

////////////////////////////////////////////////////////////////////////////////
bool Column::validate (std::string& input)
{
  return input.length () ? true : false;
}

////////////////////////////////////////////////////////////////////////////////
// No L10N.
bool Column::can_modify ()
{
  return false;
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012-2014, ARIEL MALKA ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE MODIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

#include "chronotext/font/xf/Font.h"
#include "chronotext/font/xf/FontManager.h"

using namespace ci;
using namespace std;

namespace chronotext
{
    namespace xf
    {
        Font::Font(FontManager &fontManager, FontData *data, FontTexture *texture, const Properties &properties)
        :
        texture(texture),
        properties(properties),
        indices(fontManager.getIndices(properties.slotCapacity)),
        began(0),
        hasClip(false),
        sequence(nullptr)
        {
            assert(properties.slotCapacity > 0);

            // ---

            glyphCount = data->glyphCount;
            glyphs = data->glyphs;

            baseSize = data->baseSize;
            height = data->height;
            ascent = data->ascent;
            descent = data->descent;
            spaceAdvance = data->spaceAdvance;
            strikethroughFactor = data->strikethroughFactor;
            underlineOffset = data->underlineOffset;
            lineThickness = data->lineThickness;

            w = data->w;
            h = data->h;
            le = data->le;
            te = data->te;
            advance = data->advance;

            u1 = data->u1;
            v1 = data->v1;
            u2 = data->u2;
            v2 = data->v2;

            // ---

            if (gl::isExtensionAvailable("GL_EXT_texture_filter_anisotropic"))
            {
                if (properties.useAnisotropy)
                {
                    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy);
                }
                else
                {
                    anisotropy = 1;
                }
            }
            else
            {
                anisotropy = 0;
            }

            // ---

            setSize(baseSize);
            setDirection(+1);
            setAxis(+1, +1);
            setColor(0, 0, 0, 1);
        }

        bool Font::isSpace(wchar_t c) const
        {
            return (c == 0x20) || (c == 0xa0);
        }

        bool Font::isValid(wchar_t c) const
        {
            return (glyphs.count(c) > 0);
        }

        int Font::getGlyphIndex(wchar_t c) const
        {
            if (isSpace(c))
            {
                return -2;
            }
            else
            {
                auto it = glyphs.find(c);

                if (it == glyphs.end())
                {
                    return -1; // SHALL WE USE A "MISSING GLYPH" AND RETURN ITS INDEX?
                }
                else
                {
                    return it->second;
                }
            }
        }

        wstring Font::getCharacters() const
        {
            wstring characters;
            characters.reserve(glyphs.size());

            for (auto it : glyphs)
            {
                characters.push_back(it.first);
            }

            return characters;
        }

        void Font::setSize(float size)
        {
            this->size = size;
            sizeRatio = size / baseSize;
        }

        void Font::setDirection(float direction)
        {
            this->direction = direction;
        }

        void Font::setAxis(const Vec2f &axis)
        {
            this->axis = axis;
        }

        void Font::setColor(const ColorA &color)
        {
            this->color = color;
        }

        void Font::setColor(float r, float g, float b, float a)
        {
            color.r = r;
            color.g = g;
            color.b = b;
            color.a = a;
        }

        void Font::setStrikethroughFactor(float factor)
        {
            strikethroughFactor = factor;
        }

        void Font::setClip(const Rectf &clipRect)
        {
            this->clipRect = clipRect;
            hasClip = true;
        }

        void Font::setClip(float x1, float y1, float x2, float y2)
        {
            clipRect.x1 = x1;
            clipRect.y1 = y1;
            clipRect.x2 = x2;
            clipRect.y2 = y2;

            hasClip = true;
        }

        void Font::clearClip()
        {
            hasClip = false;
        }

        float Font::getSize() const
        {
            return size;
        }

        float Font::getDirection() const
        {
            return direction * axis.x;
        }

        const Vec2f& Font::getAxis() const
        {
            return axis;
        }

        float Font::getGlyphAdvance(int glyphIndex) const
        {
            if (glyphIndex == -2)
            {
                return spaceAdvance * sizeRatio;
            }
            else if (glyphIndex == -1)
            {
                return 0;
            }
            else
            {
                return advance[glyphIndex] * sizeRatio;
            }
        }

        float Font::getCharAdvance(wchar_t c) const
        {
            return getGlyphAdvance(getGlyphIndex(c));
        }

        float Font::getStringAdvance(const wstring &s) const
        {
            return getSubStringAdvance(s, 0, s.size());
        }

        float Font::getSubStringAdvance(const wstring &s, int begin, int end) const
        {
            float advance = 0;

            for (int i = begin; i < end; i++)
            {
                advance += getCharAdvance(s.at(i));
            }

            return advance;
        }

        float Font::getHeight() const
        {
            return height * sizeRatio;
        }

        float Font::getAscent() const
        {
            return ascent * sizeRatio;
        }

        float Font::getDescent() const
        {
            return descent * sizeRatio;
        }

        float Font::getStrikethroughOffset() const
        {
            return strikethroughFactor * (ascent - descent) * sizeRatio;
        }

        float Font::getUnderlineOffset() const
        {
            return underlineOffset * sizeRatio;
        }

        float Font::getLineThickness() const
        {
            return lineThickness * sizeRatio;
        }

        float Font::getOffsetX(const wstring &text, Alignment align) const
        {
            switch (align)
            {
                case ALIGN_MIDDLE:
                    return -0.5f * getStringAdvance(text) * direction;

                case ALIGN_LEFT:
                    return (direction > 0) ? 0 : getStringAdvance(text);

                case ALIGN_RIGHT:
                    return (direction > 0) ? -getStringAdvance(text) : 0;

                default:
                    return 0;
            }
        }

        float Font::getOffsetY(Alignment align) const
        {
            switch (align)
            {
                case ALIGN_MIDDLE:
                    return getStrikethroughOffset();

                case ALIGN_TOP:
                    return +getAscent();

                case ALIGN_BOTTOM:
                    return -getDescent();

                default:
                    return 0;
            }
        }

        FontMatrix* Font::getMatrix()
        {
            return &matrix;
        }

        const GLushort* Font::getIndices() const
        {
            return const_cast<GLushort*>(indices.data());
        }

        void Font::begin(bool useColor)
        {
            if (began == 0)
            {
                glEnable(GL_TEXTURE_2D);

                if (useColor)
                {
                    glEnableClientState(GL_COLOR_ARRAY);
                }
                else
                {
                    gl::color(color);
                }

                glEnableClientState(GL_VERTEX_ARRAY);
                glEnableClientState(GL_TEXTURE_COORD_ARRAY);

                // ---

                texture->bind(); // RELOADS TEXTURE, IF NECESSARY

                if (anisotropy)
                {
                    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
                }
            }
        }

        void Font::end(bool useColor)
        {
            if (began == 0)
            {
                glDisable(GL_TEXTURE_2D);

                if (useColor)
                {
                    glDisableClientState(GL_COLOR_ARRAY);
                }

                glDisableClientState(GL_VERTEX_ARRAY);
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            }
        }

        void Font::beginSequence(FontSequence *sequence, bool useColor)
        {
            if (began == 0)
            {
                sequenceUseColor = useColor;

                if (!batch)
                {
                    batch = unique_ptr<GlyphBatch>(new GlyphBatch);
                }
                else
                {
                    batch->clear();
                }

                if (sequence)
                {
                    this->sequence = sequence;
                    sequence->begin(useColor);
                }
                else
                {
                    begin(useColor);
                }

                clearClip();
            }

            began++;
        }

        void Font::endSequence()
        {
            began--;

            if (began == 0)
            {
                if (sequence)
                {
                    batch->pack();
                    sequence->addBatch(move(batch));

                    sequence->end();
                    sequence = nullptr;
                }
                else
                {
                    batch->flush(getIndices(), sequenceUseColor);
                    end(sequenceUseColor);
                }
            }
        }

        void Font::replaySequence(FontSequence *sequence)
        {
            begin(sequence->useColor);
            sequence->replay(getIndices());
            end(sequence->useColor);
        }

        void Font::incrementSequence()
        {
            if (sequenceUseColor)
            {
                batch->addColor(color);
            }

            if (batch->size() == properties.slotCapacity)
            {
                if (sequence)
                {
                    batch->pack();
                    sequence->addBatch(move(batch));
                }
                else
                {
                    batch->flush(getIndices(), sequenceUseColor);
                }

                if (!batch)
                {
                    batch = unique_ptr<GlyphBatch>(new GlyphBatch);
                }
                else
                {
                    batch->clear();
                }
            }
        }

        bool Font::fillQuad(GlyphQuad &quad, int glyphIndex, float x, float y) const
        {
            if (glyphIndex < 0)
            {
                return false;
            }
            else
            {
                if (direction * axis.x > 0)
                {
                    quad.x1 = x + le[glyphIndex] * sizeRatio;
                    quad.x2 = quad.x1 + w[glyphIndex] * sizeRatio;
                }
                else
                {
                    quad.x2 = x - le[glyphIndex] * sizeRatio;
                    quad.x1 = quad.x2 - w[glyphIndex] * sizeRatio;
                }

                if (axis.x > 0)
                {
                    quad.u1 = u1[glyphIndex];
                    quad.u2 = u2[glyphIndex];
                }
                else
                {
                    quad.u1 = u2[glyphIndex];
                    quad.u2 = u1[glyphIndex];
                }

                if (axis.y > 0)
                {
                    quad.y1 = y - te[glyphIndex] * sizeRatio;
                    quad.y2 = quad.y1 + h[glyphIndex] * sizeRatio;

                    quad.v1 = v1[glyphIndex];
                    quad.v2 = v2[glyphIndex];
                }
                else
                {
                    quad.y2 = y + te[glyphIndex] * sizeRatio;
                    quad.y1 = quad.y2 - h[glyphIndex] * sizeRatio;

                    quad.v1 = v2[glyphIndex];
                    quad.v2 = v1[glyphIndex];
                }

                return true;
            }
        }

        bool Font::clipQuad(GlyphQuad &quad) const
        {
            return quad.clip(clipRect, texture->getSize() * sizeRatio / axis);
        }

        void Font::addGlyph(int glyphIndex, float x, float y, float z)
        {
            GlyphQuad quad;

            if (fillQuad(quad, glyphIndex, x, y))
            {
                if (!hasClip || clipQuad(quad))
                {
                    batch->addQuad(quad);
                    incrementSequence();
                }
            }
        }

        void Font::addTransformedGlyph(int glyphIndex, float x, float y)
        {
            GlyphQuad quad;

            if (fillQuad(quad, glyphIndex, x, y))
            {
                if (!hasClip || clipQuad(quad))
                {
                    matrix.addTransformedQuad(quad, batch->vertices);
                    incrementSequence();
                }
            }
        }
    }
}
<commit_msg>XFont: TAKING IN COUNT PREVIOUSLY IGNORED Z COORDINATE<commit_after>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012-2014, ARIEL MALKA ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE MODIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

#include "chronotext/font/xf/Font.h"
#include "chronotext/font/xf/FontManager.h"

using namespace ci;
using namespace std;

namespace chronotext
{
    namespace xf
    {
        Font::Font(FontManager &fontManager, FontData *data, FontTexture *texture, const Properties &properties)
        :
        texture(texture),
        properties(properties),
        indices(fontManager.getIndices(properties.slotCapacity)),
        began(0),
        hasClip(false),
        sequence(nullptr)
        {
            assert(properties.slotCapacity > 0);

            // ---

            glyphCount = data->glyphCount;
            glyphs = data->glyphs;

            baseSize = data->baseSize;
            height = data->height;
            ascent = data->ascent;
            descent = data->descent;
            spaceAdvance = data->spaceAdvance;
            strikethroughFactor = data->strikethroughFactor;
            underlineOffset = data->underlineOffset;
            lineThickness = data->lineThickness;

            w = data->w;
            h = data->h;
            le = data->le;
            te = data->te;
            advance = data->advance;

            u1 = data->u1;
            v1 = data->v1;
            u2 = data->u2;
            v2 = data->v2;

            // ---

            if (gl::isExtensionAvailable("GL_EXT_texture_filter_anisotropic"))
            {
                if (properties.useAnisotropy)
                {
                    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy);
                }
                else
                {
                    anisotropy = 1;
                }
            }
            else
            {
                anisotropy = 0;
            }

            // ---

            setSize(baseSize);
            setDirection(+1);
            setAxis(+1, +1);
            setColor(0, 0, 0, 1);
        }

        bool Font::isSpace(wchar_t c) const
        {
            return (c == 0x20) || (c == 0xa0);
        }

        bool Font::isValid(wchar_t c) const
        {
            return (glyphs.count(c) > 0);
        }

        int Font::getGlyphIndex(wchar_t c) const
        {
            if (isSpace(c))
            {
                return -2;
            }
            else
            {
                auto it = glyphs.find(c);

                if (it == glyphs.end())
                {
                    return -1; // SHALL WE USE A "MISSING GLYPH" AND RETURN ITS INDEX?
                }
                else
                {
                    return it->second;
                }
            }
        }

        wstring Font::getCharacters() const
        {
            wstring characters;
            characters.reserve(glyphs.size());

            for (auto it : glyphs)
            {
                characters.push_back(it.first);
            }

            return characters;
        }

        void Font::setSize(float size)
        {
            this->size = size;
            sizeRatio = size / baseSize;
        }

        void Font::setDirection(float direction)
        {
            this->direction = direction;
        }

        void Font::setAxis(const Vec2f &axis)
        {
            this->axis = axis;
        }

        void Font::setColor(const ColorA &color)
        {
            this->color = color;
        }

        void Font::setColor(float r, float g, float b, float a)
        {
            color.r = r;
            color.g = g;
            color.b = b;
            color.a = a;
        }

        void Font::setStrikethroughFactor(float factor)
        {
            strikethroughFactor = factor;
        }

        void Font::setClip(const Rectf &clipRect)
        {
            this->clipRect = clipRect;
            hasClip = true;
        }

        void Font::setClip(float x1, float y1, float x2, float y2)
        {
            clipRect.x1 = x1;
            clipRect.y1 = y1;
            clipRect.x2 = x2;
            clipRect.y2 = y2;

            hasClip = true;
        }

        void Font::clearClip()
        {
            hasClip = false;
        }

        float Font::getSize() const
        {
            return size;
        }

        float Font::getDirection() const
        {
            return direction * axis.x;
        }

        const Vec2f& Font::getAxis() const
        {
            return axis;
        }

        float Font::getGlyphAdvance(int glyphIndex) const
        {
            if (glyphIndex == -2)
            {
                return spaceAdvance * sizeRatio;
            }
            else if (glyphIndex == -1)
            {
                return 0;
            }
            else
            {
                return advance[glyphIndex] * sizeRatio;
            }
        }

        float Font::getCharAdvance(wchar_t c) const
        {
            return getGlyphAdvance(getGlyphIndex(c));
        }

        float Font::getStringAdvance(const wstring &s) const
        {
            return getSubStringAdvance(s, 0, s.size());
        }

        float Font::getSubStringAdvance(const wstring &s, int begin, int end) const
        {
            float advance = 0;

            for (int i = begin; i < end; i++)
            {
                advance += getCharAdvance(s.at(i));
            }

            return advance;
        }

        float Font::getHeight() const
        {
            return height * sizeRatio;
        }

        float Font::getAscent() const
        {
            return ascent * sizeRatio;
        }

        float Font::getDescent() const
        {
            return descent * sizeRatio;
        }

        float Font::getStrikethroughOffset() const
        {
            return strikethroughFactor * (ascent - descent) * sizeRatio;
        }

        float Font::getUnderlineOffset() const
        {
            return underlineOffset * sizeRatio;
        }

        float Font::getLineThickness() const
        {
            return lineThickness * sizeRatio;
        }

        float Font::getOffsetX(const wstring &text, Alignment align) const
        {
            switch (align)
            {
                case ALIGN_MIDDLE:
                    return -0.5f * getStringAdvance(text) * direction;

                case ALIGN_LEFT:
                    return (direction > 0) ? 0 : getStringAdvance(text);

                case ALIGN_RIGHT:
                    return (direction > 0) ? -getStringAdvance(text) : 0;

                default:
                    return 0;
            }
        }

        float Font::getOffsetY(Alignment align) const
        {
            switch (align)
            {
                case ALIGN_MIDDLE:
                    return getStrikethroughOffset();

                case ALIGN_TOP:
                    return +getAscent();

                case ALIGN_BOTTOM:
                    return -getDescent();

                default:
                    return 0;
            }
        }

        FontMatrix* Font::getMatrix()
        {
            return &matrix;
        }

        const GLushort* Font::getIndices() const
        {
            return const_cast<GLushort*>(indices.data());
        }

        void Font::begin(bool useColor)
        {
            if (began == 0)
            {
                glEnable(GL_TEXTURE_2D);

                if (useColor)
                {
                    glEnableClientState(GL_COLOR_ARRAY);
                }
                else
                {
                    gl::color(color);
                }

                glEnableClientState(GL_VERTEX_ARRAY);
                glEnableClientState(GL_TEXTURE_COORD_ARRAY);

                // ---

                texture->bind(); // RELOADS TEXTURE, IF NECESSARY

                if (anisotropy)
                {
                    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
                }
            }
        }

        void Font::end(bool useColor)
        {
            if (began == 0)
            {
                glDisable(GL_TEXTURE_2D);

                if (useColor)
                {
                    glDisableClientState(GL_COLOR_ARRAY);
                }

                glDisableClientState(GL_VERTEX_ARRAY);
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            }
        }

        void Font::beginSequence(FontSequence *sequence, bool useColor)
        {
            if (began == 0)
            {
                sequenceUseColor = useColor;

                if (!batch)
                {
                    batch = unique_ptr<GlyphBatch>(new GlyphBatch);
                }
                else
                {
                    batch->clear();
                }

                if (sequence)
                {
                    this->sequence = sequence;
                    sequence->begin(useColor);
                }
                else
                {
                    begin(useColor);
                }

                clearClip();
            }

            began++;
        }

        void Font::endSequence()
        {
            began--;

            if (began == 0)
            {
                if (sequence)
                {
                    batch->pack();
                    sequence->addBatch(move(batch));

                    sequence->end();
                    sequence = nullptr;
                }
                else
                {
                    batch->flush(getIndices(), sequenceUseColor);
                    end(sequenceUseColor);
                }
            }
        }

        void Font::replaySequence(FontSequence *sequence)
        {
            begin(sequence->useColor);
            sequence->replay(getIndices());
            end(sequence->useColor);
        }

        void Font::incrementSequence()
        {
            if (sequenceUseColor)
            {
                batch->addColor(color);
            }

            if (batch->size() == properties.slotCapacity)
            {
                if (sequence)
                {
                    batch->pack();
                    sequence->addBatch(move(batch));
                }
                else
                {
                    batch->flush(getIndices(), sequenceUseColor);
                }

                if (!batch)
                {
                    batch = unique_ptr<GlyphBatch>(new GlyphBatch);
                }
                else
                {
                    batch->clear();
                }
            }
        }

        bool Font::fillQuad(GlyphQuad &quad, int glyphIndex, float x, float y) const
        {
            if (glyphIndex < 0)
            {
                return false;
            }
            else
            {
                if (direction * axis.x > 0)
                {
                    quad.x1 = x + le[glyphIndex] * sizeRatio;
                    quad.x2 = quad.x1 + w[glyphIndex] * sizeRatio;
                }
                else
                {
                    quad.x2 = x - le[glyphIndex] * sizeRatio;
                    quad.x1 = quad.x2 - w[glyphIndex] * sizeRatio;
                }

                if (axis.x > 0)
                {
                    quad.u1 = u1[glyphIndex];
                    quad.u2 = u2[glyphIndex];
                }
                else
                {
                    quad.u1 = u2[glyphIndex];
                    quad.u2 = u1[glyphIndex];
                }

                if (axis.y > 0)
                {
                    quad.y1 = y - te[glyphIndex] * sizeRatio;
                    quad.y2 = quad.y1 + h[glyphIndex] * sizeRatio;

                    quad.v1 = v1[glyphIndex];
                    quad.v2 = v2[glyphIndex];
                }
                else
                {
                    quad.y2 = y + te[glyphIndex] * sizeRatio;
                    quad.y1 = quad.y2 - h[glyphIndex] * sizeRatio;

                    quad.v1 = v2[glyphIndex];
                    quad.v2 = v1[glyphIndex];
                }

                return true;
            }
        }

        bool Font::clipQuad(GlyphQuad &quad) const
        {
            return quad.clip(clipRect, texture->getSize() * sizeRatio / axis);
        }

        void Font::addGlyph(int glyphIndex, float x, float y, float z)
        {
            GlyphQuad quad;

            if (fillQuad(quad, glyphIndex, x, y))
            {
                if (!hasClip || clipQuad(quad))
                {
                    batch->addQuad(quad, z);
                    incrementSequence();
                }
            }
        }

        void Font::addTransformedGlyph(int glyphIndex, float x, float y)
        {
            GlyphQuad quad;

            if (fillQuad(quad, glyphIndex, x, y))
            {
                if (!hasClip || clipQuad(quad))
                {
                    matrix.addTransformedQuad(quad, batch->vertices);
                    incrementSequence();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#include <avr/io.h>
#include <avr/sleep.h>

#include <Arduino.h>

#include <DS3232RTC.h>
//#include <USIWire.h>

// Input/output defines
#define LED_BLUE            5
#define LED_GR              3
#define LED_RED             2

#define BLU_STATE           1
#define BLU_RESET           0

#define RTC_INT_SQW        10

// Serial defines
#define SERIAL_BAUD      9600   // For at mode and for data mode (CC41, HM-10 and MLT-BT05)

// I2C defines
#define SDA                 4
#define SCL                 6

#define SLEEP_TIMEOUT   5000L   // Timeout before sleep
#define LENGTH             80   // Command buffer length

// Global variables
USI_TWI bus;                    // TinyWireM instance (I2C bus)
//USIWire bus;                    // USIWire instance (I2C bus)
DS3232RTC RTC(bus);

boolean data = false;
unsigned long prevMillis = 0;
bool rtcInitOk = false;

time_t timeProvider() {
  return RTC.get();
}

// Put the micro to sleep
void system_sleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();

  // sleeping ...
  sleep_disable(); // wake up fully
}

void printDigits(int digits) {
  // Utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(':');
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void digitalClockDisplay(void) {
  time_t now = timeProvider();

  // Digital clock display of the time
  Serial.print(hour(now));
  printDigits(minute(now));
  printDigits(second(now));
  Serial.print(' ');
  Serial.print(day(now));
  Serial.print('/');
  Serial.print(month(now));
  Serial.print('/');
  Serial.println(year(now));
}

// PCINT Interrupt Service Routine (unused)
ISR(PCINT0_vect) {
  // Don't do anything here but we must include this
  // block of code otherwise the interrupt calls an
  // uninitialized interrupt handler.
}

void setup() {
  OSCCAL = 0x86;                    // Calibrated OSSCAL value with TinyTuner

  Serial.begin(SERIAL_BAUD);
  bus.begin();

  // Pinmode set
  pinMode(LED_BLUE, OUTPUT);
  pinMode(LED_GR, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(BLU_STATE, INPUT);
  pinMode(BLU_RESET, OUTPUT);
  pinMode(RTC_INT_SQW, INPUT);

  Serial.println(F("START SERIAL"));
  Serial.print(F("Initial value of OSCCAL is 0x"));
  Serial.println(OSCCAL, HEX);

  //setSyncProvider(RTC.get);     // The function to get the time from the RTC
  // Real time clock
  setSyncProvider(timeProvider);  // Pointer to function to get the time from the RTC

  if (timeStatus() != timeSet) {
    Serial.println(F("Unable to sync with the RTC"));
  }
  else {
    Serial.println(F("RTC has set the system time"));
    rtcInitOk = true;
  }

  if (rtcInitOk) {
    time_t t;
    tmElements_t tm;

    tm.Year = 47;
    tm.Month = 10;
    tm.Day = 18;
    tm.Hour = 21;
    tm.Minute = 45;
    tm.Second = 00;
    t = makeTime(tm);
    RTC.set(t);        //use the time_t value to ensure correct weekday is set
    setTime(t);
    Serial.print(F("RTC set to: "));
    digitalClockDisplay();
  }

  ADCSRA  = 0;                      // Disable ADC to save power
  MCUCR  |= _BV(BODS);              // BOD disabled

  PCMSK0 |= _BV(PCINT0);            // Pin change mask: listen to portA bit 0 (D10)
  PCMSK0 |= _BV(PCINT2);            // Pin change mask: listen to portA bit 2 (D8)
  GIMSK  |= _BV(PCIE0);             // Enable PCINT interrupt on portA
}

void loop() {
  size_t count = 0;
  char buffer[LENGTH];

  // FIXME Wake from sleep with new CORE can't read first serial bytes....

  if (millis() - prevMillis >= SLEEP_TIMEOUT) {
    prevMillis = millis();
    Serial.println(F("Sleeping..."));
    system_sleep();
    Serial.println(F("Waking up..."));
    digitalClockDisplay();

    // Necessary to reset the alarm flag on RTC!
    if (RTC.alarm(ALARM_1)) {
      Serial.println(F("From alarm..."));
    }
  }

  while (Serial.available() && count < LENGTH - 1) {
    delay(2);
    char c = (char) Serial.read();

    prevMillis = millis();      // Update prevMillis to reset sleep timeout

    if (c == '\r' || c == '\n') {
      if (c == '\n') {
        data = true;
        Serial.flush();
        break;
      }
      continue;
    }

    buffer[count] = c;
    count++;
  }

  if (data) {
    buffer[count] = '\0';
    //Serial.print("COUNT = ");
    //Serial.println(count);
    //Serial.println(buffer);

    count = 0;
    data = false;

    if (strcmp(buffer, "ON") == 0) {
      digitalWrite(LED_BLUE, HIGH);

      RTC.setAlarm(ALM1_MATCH_MINUTES, 45, 45, 21, 0);
      RTC.alarmInterrupt(ALARM_1, true);

//      for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
//          analogWrite(LED_BLUE, fadeValue);
//          delay(100);
//        }
//      delay(1000);
//      digitalWrite(LED_BLUE, LOW);
//
//      for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
//        analogWrite(LED_RED, fadeValue);
//        delay(100);
//      }
//      delay(1000);
//      digitalWrite(LED_RED, LOW);
//
//      for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
//        analogWrite(LED_GR, fadeValue);
//        delay(100);
//      }
//      delay(1000);
//      digitalWrite(LED_GR, LOW);
    }

    if (strcmp(buffer, "OFF") == 0) {
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_RED, LOW);
      digitalWrite(LED_GR, LOW);
    }

    digitalClockDisplay();
  }
}
<commit_msg>Added license and version<commit_after>/*
 *  This file is part of SmartLamp application.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/*
 * Built for Attiny84 8Mhz, using AVR USBasp programmer.
 * VERSION 0.1
 */

#include <avr/io.h>
#include <avr/sleep.h>
#include <time.h>

#include <Arduino.h>

#include <DS3232RTC.h>
//#include <USIWire.h>

// Input/output defines
#define LED_BLUE            5
#define LED_GR              3
#define LED_RED             2

#define BLU_STATE           1
#define BLU_RESET           0

#define RTC_INT_SQW        10

// Serial defines
#define SERIAL_BAUD      9600   // For at mode and for data mode (CC41, HM-10 and MLT-BT05)

// I2C defines
#define SDA                 4
#define SCL                 6

#define SLEEP_TIMEOUT   5000L   // Timeout before sleep
#define LENGTH             80   // Command buffer length

// Global variables
USI_TWI bus;                    // TinyWireM instance (I2C bus)
//USIWire bus;                    // USIWire instance (I2C bus)
DS3232RTC RTC(bus);

boolean data = false;
unsigned long prevMillis = 0;
bool rtcInitOk = false;

time_t timeProvider() {
  return RTC.get();
}

// Put the micro to sleep
void system_sleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();

  // sleeping ...
  sleep_disable(); // wake up fully
}

void printDigits(int digits) {
  // Utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(':');
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void digitalClockDisplay(void) {
  time_t now = timeProvider();

  // Digital clock display of the time
  Serial.print(hour(now));
  printDigits(minute(now));
  printDigits(second(now));
  Serial.print(' ');
  Serial.print(day(now));
  Serial.print('/');
  Serial.print(month(now));
  Serial.print('/');
  Serial.println(year(now));
}

// PCINT Interrupt Service Routine (unused)
ISR(PCINT0_vect) {
  // Don't do anything here but we must include this
  // block of code otherwise the interrupt calls an
  // uninitialized interrupt handler.
}

void setup() {
  OSCCAL = 0x86;                    // Calibrated OSSCAL value with TinyTuner

  Serial.begin(SERIAL_BAUD);
  bus.begin();

  // Pinmode set
  pinMode(LED_BLUE, OUTPUT);
  pinMode(LED_GR, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(BLU_STATE, INPUT);
  pinMode(BLU_RESET, OUTPUT);
  pinMode(RTC_INT_SQW, INPUT);

  Serial.println(F("START SERIAL"));
  Serial.print(F("Initial value of OSCCAL is 0x"));
  Serial.println(OSCCAL, HEX);

  //setSyncProvider(RTC.get);     // The function to get the time from the RTC
  // Real time clock
  setSyncProvider(timeProvider);  // Pointer to function to get the time from the RTC

  if (timeStatus() != timeSet) {
    Serial.println(F("Unable to sync with the RTC"));
  }
  else {
    Serial.println(F("RTC has set the system time"));
    rtcInitOk = true;
  }

  if (rtcInitOk) {
    time_t t;
    tmElements_t tm;

    tm.Year = 47;
    tm.Month = 10;
    tm.Day = 18;
    tm.Hour = 21;
    tm.Minute = 45;
    tm.Second = 00;
    t = makeTime(tm);
    RTC.set(t);        //use the time_t value to ensure correct weekday is set
    setTime(t);
    Serial.print(F("RTC set to: "));
    digitalClockDisplay();
  }

  ADCSRA  = 0;                      // Disable ADC to save power
  MCUCR  |= _BV(BODS);              // BOD disabled

  PCMSK0 |= _BV(PCINT0);            // Pin change mask: listen to portA bit 0 (D10)
  PCMSK0 |= _BV(PCINT2);            // Pin change mask: listen to portA bit 2 (D8)
  GIMSK  |= _BV(PCIE0);             // Enable PCINT interrupt on portA
}

void loop() {
  size_t count = 0;
  char buffer[LENGTH];

  // FIXME Wake from sleep with new CORE can't read first serial bytes....

  if (millis() - prevMillis >= SLEEP_TIMEOUT) {
    prevMillis = millis();
    Serial.println(F("Sleeping..."));
    system_sleep();
    Serial.println(F("Waking up..."));
    digitalClockDisplay();

    // Necessary to reset the alarm flag on RTC!
    if (RTC.alarm(ALARM_1)) {
      Serial.println(F("From alarm..."));
    }
  }

  while (Serial.available() && count < LENGTH - 1) {
    delay(2);
    char c = (char) Serial.read();

    prevMillis = millis();      // Update prevMillis to reset sleep timeout

    if (c == '\r' || c == '\n') {
      if (c == '\n') {
        data = true;
        Serial.flush();
        break;
      }
      continue;
    }

    buffer[count] = c;
    count++;
  }

  if (data) {
    buffer[count] = '\0';
    //Serial.print("COUNT = ");
    //Serial.println(count);
    //Serial.println(buffer);

    count = 0;
    data = false;

    if (strcmp(buffer, "ON") == 0) {
      digitalWrite(LED_BLUE, HIGH);

      RTC.setAlarm(ALM1_MATCH_MINUTES, 45, 45, 21, 0);
      RTC.alarmInterrupt(ALARM_1, true);

//      for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
//          analogWrite(LED_BLUE, fadeValue);
//          delay(100);
//        }
//      delay(1000);
//      digitalWrite(LED_BLUE, LOW);
//
//      for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
//        analogWrite(LED_RED, fadeValue);
//        delay(100);
//      }
//      delay(1000);
//      digitalWrite(LED_RED, LOW);
//
//      for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
//        analogWrite(LED_GR, fadeValue);
//        delay(100);
//      }
//      delay(1000);
//      digitalWrite(LED_GR, LOW);
    }

    if (strcmp(buffer, "OFF") == 0) {
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_RED, LOW);
      digitalWrite(LED_GR, LOW);
    }

    digitalClockDisplay();
  }
}
<|endoftext|>


<commit_before>#include <SegmentList.hh>

#include "catch.hpp"

SCENARIO("Kernel heap allocator SegmentList", "[kernelheap]")
{
   GIVEN("A segment list")
   {
      SegmentList list;

      WHEN("The list is empty")
      {
         THEN("The count of the list is zero")
         {
            CHECK(list.count() == 0);
         }

         AND_WHEN("Creating an iterator")
         {
            auto i = list.getIterator();

            THEN("The iterator has no next item")
            {
               CHECK(i.hasNext() == false);
            }
         }
      }
   }
}
<commit_msg>Add more tests for iteration<commit_after>#include <SegmentList.hh>

#include "catch.hpp"

SCENARIO("Kernel heap allocator SegmentList", "[kernelheap]")
{
   GIVEN("A segment list")
   {
      SegmentList list;

      WHEN("The list is empty")
      {
         THEN("The count of the list is zero")
         {
            CHECK(list.count() == 0);
         }

         AND_WHEN("Creating an iterator")
         {
            auto i = list.getIterator();

            THEN("The iterator has no next item")
            {
               CHECK(i.hasNext() == false);
            }
         }
      }

      WHEN("An item is added")
      {
         Segment* s1 = new Segment();
         s1->setSize(1);

         list.add(s1);

         AND_WHEN("Creating an iterator")
         {
            auto i = list.getIterator();

            THEN("Iterator has a next item")
            {
               CHECK(i.hasNext() == true);

               AND_THEN("The next item is the item added")
               {
                  CHECK(&i.getNext() == s1);

                  AND_THEN("The iterator has no next item")
                  {
                     CHECK(i.hasNext() == false);
                  }
               }
            }
         }
      }

      WHEN("Three items are present")
      {
         Segment* s2 = new Segment();
         Segment* s3 = new Segment();

         s2->setSize(2);
         s3->setSize(3);

         list.add(s2);
         list.add(s3);
      }
   }
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\MaterialElement.h"
#include <iostream>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace MatElementTest
{
	TEST_CLASS(MatTest1)
	{
	public:

		TEST_METHOD(settersTest)
		{
			MaterialElement M;
			Point P(1, 2, 3);

			M.setPosition(P);
			M.setMass(2002020202.333);
			M.setCharge(2.3423);

			Assert::AreEqual(M.getMass(), 2002020202.333);
			Assert::AreEqual(M.getCharge(), 2.3423);
			Assert::AreEqual(P.xComponent(), M.pointerToPosition()->xComponent());
			Assert::AreEqual(P.yComponent(), M.pointerToPosition()->yComponent());
			Assert::AreEqual(P.zComponent(), M.pointerToPosition()->zComponent());
		}

		TEST_METHOD(ZeroMassSimulation)
		{
			MaterialElement M;

			Point P(1, 2, 3);
			M.setPosition(P);
			M.update(2345.8778);

			double x = M.getAcceleration().xComponent();
			double y = M.getAcceleration().yComponent();
			double z = M.getAcceleration().zComponent();

			Assert::AreEqual(0.0, x);
			Assert::AreEqual(0.0, y);
			Assert::AreEqual(0.0, z);
		}

		TEST_METHOD(Acceleration_at_unitForce)
		{
			MaterialElement M;
			Point P(0, 0, 0);
			M.setPosition(P);
			M.setMass(1);

			Vect F(1, 1, 1);
			M.setResultant(F);
			M.update(1);

			double x = M.getAcceleration().xComponent();
			double y = M.getAcceleration().yComponent();
			double z = M.getAcceleration().zComponent();

			Assert::AreEqual(1.0, x);
			Assert::AreEqual(1.0, y);
			Assert::AreEqual(1.0, z);
		}

		TEST_METHOD(Position_at_unitForce)
		{
			MaterialElement M;

			Point P(0, 0, 0);
			M.setPosition(P);
			M.setMass(1);

			Vect F(1, 1, 1);
			M.setResultant(F);
			M.update(1);

			double x = M.pointerToPosition()->xComponent();
			double y = M.pointerToPosition()->yComponent();
			double z = M.pointerToPosition()->zComponent();

			Assert::AreEqual(0.5, x);
			Assert::AreEqual(0.5, y);
			Assert::AreEqual(0.5, z);
		}

		TEST_METHOD(Position_at_10kg_10sec_underGravity)
		{
			MaterialElement M;
			double accuracy = 0.000001;
			double expectedZ = 490.5;

			Point P(0, 0, 0);
			M.setPosition(P);
			M.setMass(10); //kg

			Vect F(0, 0, 98.1); // force set to gravity * mass

			M.setResultant(F);
			M.update(10);  //seconds

			double x = M.pointerToPosition()->xComponent();
			double y = M.pointerToPosition()->yComponent();
			double z = M.pointerToPosition()->zComponent();

			Assert::AreEqual(0.0, x);
			Assert::AreEqual(0.0, y);
			Assert::IsTrue(abs(z - expectedZ) < accuracy);
		}

	};
}
<commit_msg>updated to match SimModule changes<commit_after>#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\MaterialElement.h"
#include <iostream>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace MatElementTest
{
	TEST_CLASS(MatTest1)
	{
	public:

		TEST_METHOD(settersTest)
		{
			MaterialElement M;
			Point P(1, 2, 3);

			M.place(P);
			M.setMass(2002020202.333);
			M.setCharge(2.3423);

			Assert::AreEqual(M.getMass(), 2002020202.333);
			Assert::AreEqual(M.getCharge(), 2.3423);
			Assert::AreEqual(P.xComponent(), M.pointerToPosition()->xComponent());
			Assert::AreEqual(P.yComponent(), M.pointerToPosition()->yComponent());
			Assert::AreEqual(P.zComponent(), M.pointerToPosition()->zComponent());
		}

		TEST_METHOD(ZeroMassException)
		{
			auto func = []()
			{
				MaterialElement M;
				Point P(1, 2, 3);
				M.place(P);
				M.update(123);
			};
			Assert::ExpectException<std::invalid_argument>(func);
		}

		TEST_METHOD(Acceleration_at_unitForce)
		{
			MaterialElement M;
			Point P(0, 0, 0);
			M.place(P);
			M.setMass(1);

			Vect F(1, 1, 1);
			M.addExternalAction(F);
			M.update(1);

			double x = M.Acceleration().xComponent();
			double y = M.Acceleration().yComponent();
			double z = M.Acceleration().zComponent();

			Assert::AreEqual(1.0, x);
			Assert::AreEqual(1.0, y);
			Assert::AreEqual(1.0, z);
		}

		TEST_METHOD(Position_at_unitForce)
		{
			MaterialElement M;

			Point P(0, 0, 0);
			M.place(P);
			M.setMass(1);

			Vect F(1, 1, 1);
			M.addExternalAction(F);
			M.update(1);

			double x = M.pointerToPosition()->xComponent();
			double y = M.pointerToPosition()->yComponent();
			double z = M.pointerToPosition()->zComponent();

			Assert::AreEqual(0.5, x);
			Assert::AreEqual(0.5, y);
			Assert::AreEqual(0.5, z);
		}

		TEST_METHOD(Position_at_10kg_10sec_underGravity)
		{
			MaterialElement M;
			double accuracy = 0.000001;
			double expectedZ = 490.5;

			Point P(0, 0, 0);
			M.place(P);
			M.setMass(10); //kg

			Vect F(0, 0, 98.1); // force set to gravity * mass

			M.addExternalAction(F);
			M.update(10);  //seconds

			double x = M.pointerToPosition()->xComponent();
			double y = M.pointerToPosition()->yComponent();
			double z = M.pointerToPosition()->zComponent();

			Assert::AreEqual(0.0, x);
			Assert::AreEqual(0.0, y);
			Assert::IsTrue(abs(z - expectedZ) < accuracy);
		}

	};
}
<|endoftext|>


<commit_before>//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AttributeList class implementation
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/AttributeList.h"
using namespace clang;

AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
                             IdentifierInfo *pName, SourceLocation pLoc,
                             Action::ExprTy **elist, unsigned numargs,
                             AttributeList *n)
  : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
    NumArgs(numargs), Next(n) {
  Args = new Action::ExprTy*[numargs];
  for (unsigned i = 0; i != numargs; ++i)
    Args[i] = elist[i];
}

AttributeList::~AttributeList() {
  if (Args) {
    // FIXME: before we delete the vector, we need to make sure the Expr's
    // have been deleted. Since Action::ExprTy is "void", we are dependent
    // on the actions module for actually freeing the memory. The specific
    // hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType,
    // ParseField, ParseTag. Once these routines have freed the expression,
    // they should zero out the Args slot (to indicate the memory has been
    // freed). If any element of the vector is non-null, we should assert.
    delete [] Args;
  }
  delete Next;
}

AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
  const char *Str = Name->getName();
  unsigned Len = Name->getLength();

  // Normalize the attribute name, __foo__ becomes foo.
  if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
      Str[Len - 2] == '_' && Str[Len - 1] == '_') {
    Str += 2;
    Len -= 4;
  }

  // FIXME: Hand generating this is neither smart nor efficient.
  switch (Len) {
  case 4:
    if (!memcmp(Str, "weak", 4)) return AT_weak;
    if (!memcmp(Str, "pure", 4)) return AT_pure;
    if (!memcmp(Str, "mode", 4)) return AT_mode;
    if (!memcmp(Str, "used", 4)) return AT_used;
    break;
  case 5:
    if (!memcmp(Str, "alias", 5)) return AT_alias;
    if (!memcmp(Str, "const", 5)) return AT_const;
    break;
  case 6:
    if (!memcmp(Str, "packed", 6)) return AT_packed;
    if (!memcmp(Str, "malloc", 6)) return IgnoredAttribute; // FIXME: noalias.
    if (!memcmp(Str, "format", 6)) return AT_format;
    if (!memcmp(Str, "unused", 6)) return AT_unused;
    if (!memcmp(Str, "blocks", 6)) return AT_blocks;
    break;
  case 7:
    if (!memcmp(Str, "aligned", 7)) return AT_aligned;
    if (!memcmp(Str, "cleanup", 7)) return AT_cleanup;
    if (!memcmp(Str, "nodebug", 7)) return AT_nodebug;
    if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
    if (!memcmp(Str, "nothrow", 7)) return AT_nothrow;
    if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
    if (!memcmp(Str, "section", 7)) return AT_section;
    if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
    break;
  case 8:
    if (!memcmp(Str, "annotate", 8)) return AT_annotate;
    if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
    if (!memcmp(Str, "noinline", 8)) return AT_noinline;
    if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
    if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
    if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
    if (!memcmp(Str, "NSObject", 8)) return AT_nsobject;
    break;
  case 9:
    if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
    if (!memcmp(Str, "dllexport", 9)) return AT_dllexport;
    if (!memcmp(Str, "may_alias", 9)) return IgnoredAttribute; // FIXME: TBAA
    break;
  case 10:
    if (!memcmp(Str, "deprecated", 10)) return AT_deprecated;
    if (!memcmp(Str, "visibility", 10)) return AT_visibility;
    if (!memcmp(Str, "destructor", 10)) return AT_destructor;
    if (!memcmp(Str, "format_arg", 10))
      return IgnoredAttribute; // FIXME: printf format string checking.
    break;
  case 11:
    if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
    if (!memcmp(Str, "constructor", 11)) return AT_constructor;
    if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
    break;
  case 12:
    if (!memcmp(Str, "overloadable", 12)) return AT_overloadable;
    break;
  case 13:
    if (!memcmp(Str, "address_space", 13)) return AT_address_space;
    if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
    break;
  case 14:
    if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception;
    break;
  case 15:
    if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
    break;
  case 17:
    if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union;
    break;
  case 18:
    if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result;
    break;
  }
  return UnknownAttribute;
}
<commit_msg>don't new[] an empty array when an AttributeList has  zero expression arguments.  This eliminates 2579 1-byte mallocs when parsing Cocoa.h.<commit_after>//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AttributeList class implementation
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/AttributeList.h"
using namespace clang;

AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
                             IdentifierInfo *pName, SourceLocation pLoc,
                             Action::ExprTy **ExprList, unsigned numArgs,
                             AttributeList *n)
  : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
    NumArgs(numArgs), Next(n) {

  if (numArgs == 0)
    Args = 0;
  else {
    Args = new Action::ExprTy*[numArgs];
    memcpy(Args, ExprList, numArgs*sizeof(Args[0]));
  }
}

AttributeList::~AttributeList() {
  if (Args) {
    // FIXME: before we delete the vector, we need to make sure the Expr's
    // have been deleted. Since Action::ExprTy is "void", we are dependent
    // on the actions module for actually freeing the memory. The specific
    // hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType,
    // ParseField, ParseTag. Once these routines have freed the expression,
    // they should zero out the Args slot (to indicate the memory has been
    // freed). If any element of the vector is non-null, we should assert.
    delete [] Args;
  }
  delete Next;
}

AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
  const char *Str = Name->getName();
  unsigned Len = Name->getLength();

  // Normalize the attribute name, __foo__ becomes foo.
  if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
      Str[Len - 2] == '_' && Str[Len - 1] == '_') {
    Str += 2;
    Len -= 4;
  }

  // FIXME: Hand generating this is neither smart nor efficient.
  switch (Len) {
  case 4:
    if (!memcmp(Str, "weak", 4)) return AT_weak;
    if (!memcmp(Str, "pure", 4)) return AT_pure;
    if (!memcmp(Str, "mode", 4)) return AT_mode;
    if (!memcmp(Str, "used", 4)) return AT_used;
    break;
  case 5:
    if (!memcmp(Str, "alias", 5)) return AT_alias;
    if (!memcmp(Str, "const", 5)) return AT_const;
    break;
  case 6:
    if (!memcmp(Str, "packed", 6)) return AT_packed;
    if (!memcmp(Str, "malloc", 6)) return IgnoredAttribute; // FIXME: noalias.
    if (!memcmp(Str, "format", 6)) return AT_format;
    if (!memcmp(Str, "unused", 6)) return AT_unused;
    if (!memcmp(Str, "blocks", 6)) return AT_blocks;
    break;
  case 7:
    if (!memcmp(Str, "aligned", 7)) return AT_aligned;
    if (!memcmp(Str, "cleanup", 7)) return AT_cleanup;
    if (!memcmp(Str, "nodebug", 7)) return AT_nodebug;
    if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
    if (!memcmp(Str, "nothrow", 7)) return AT_nothrow;
    if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
    if (!memcmp(Str, "section", 7)) return AT_section;
    if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
    break;
  case 8:
    if (!memcmp(Str, "annotate", 8)) return AT_annotate;
    if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
    if (!memcmp(Str, "noinline", 8)) return AT_noinline;
    if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
    if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
    if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
    if (!memcmp(Str, "NSObject", 8)) return AT_nsobject;
    break;
  case 9:
    if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
    if (!memcmp(Str, "dllexport", 9)) return AT_dllexport;
    if (!memcmp(Str, "may_alias", 9)) return IgnoredAttribute; // FIXME: TBAA
    break;
  case 10:
    if (!memcmp(Str, "deprecated", 10)) return AT_deprecated;
    if (!memcmp(Str, "visibility", 10)) return AT_visibility;
    if (!memcmp(Str, "destructor", 10)) return AT_destructor;
    if (!memcmp(Str, "format_arg", 10))
      return IgnoredAttribute; // FIXME: printf format string checking.
    break;
  case 11:
    if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
    if (!memcmp(Str, "constructor", 11)) return AT_constructor;
    if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
    break;
  case 12:
    if (!memcmp(Str, "overloadable", 12)) return AT_overloadable;
    break;
  case 13:
    if (!memcmp(Str, "address_space", 13)) return AT_address_space;
    if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
    break;
  case 14:
    if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception;
    break;
  case 15:
    if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
    break;
  case 17:
    if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union;
    break;
  case 18:
    if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result;
    break;
  }
  return UnknownAttribute;
}
<|endoftext|>