<commit_before>// MIT License
//
// Copyright (c) 2017-2018 Artur Wyszyński, aljen at hitomi dot pl
//
// 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.

#include <spaghetti/elements/logic/pid.h>

namespace spaghetti::elements::logic {

PID::PID()
  : Element{}
{
  setMinInputs(7);
  setMaxInputs(7);
  setMinOutputs(1);
  setMaxOutputs(1);

  addInput(ValueType::eFloat, "PV", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "SP", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "KP", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "KI", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "KD", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "CV High", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "CV Low", IOSocket::eCanHoldFloat);

  addOutput(ValueType::eFloat, "CV", IOSocket::eCanHoldFloat);
}

void PID::update(duration_t const &a_delta)
{
  m_delta = static_cast<float>(a_delta.count()) / 1000.f;
}

void PID::calculate()
{
  float const PV{ std::get<float>(m_inputs[0].value) };
  float const SP{ std::get<float>(m_inputs[1].value) };
  float const KP{ std::get<float>(m_inputs[2].value) };
  float const KI{ std::get<float>(m_inputs[3].value) };
  float const KD{ std::get<float>(m_inputs[4].value) };
  float const CV_HIGH{ std::get<float>(m_inputs[5].value) };
  float const CV_LOW{ std::get<float>(m_inputs[6].value) };

  float const ERROR{ SP - PV };

  m_integral += (ERROR * m_delta) / KI;
  m_integral = std::clamp(m_integral, CV_LOW, CV_HIGH);

  float const P{ KP * ERROR };
  float const I{ m_integral };
  float const D{ KD * ((ERROR - m_lastError) / m_delta) };

  float const CV{ std::clamp(P + I + D, CV_LOW, CV_HIGH) };

  m_lastError = ERROR;

  m_outputs[0].value = CV;
}

} // namespace spaghetti::elements::logic
<commit_msg>Fix division by zero in PID<commit_after>// MIT License
//
// Copyright (c) 2017-2018 Artur Wyszyński, aljen at hitomi dot pl
//
// 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.

#include <spaghetti/elements/logic/pid.h>
#include <spaghetti/utils.h>

namespace spaghetti::elements::logic {

PID::PID()
  : Element{}
{
  setMinInputs(7);
  setMaxInputs(7);
  setMinOutputs(1);
  setMaxOutputs(1);

  addInput(ValueType::eFloat, "PV", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "SP", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "KP", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "KI", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "KD", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "CV High", IOSocket::eCanHoldFloat);
  addInput(ValueType::eFloat, "CV Low", IOSocket::eCanHoldFloat);

  addOutput(ValueType::eFloat, "CV", IOSocket::eCanHoldFloat);
}

void PID::update(duration_t const &a_delta)
{
  m_delta = static_cast<float>(a_delta.count()) / 1000.f;
}

void PID::calculate()
{
  float const PV{ std::get<float>(m_inputs[0].value) };
  float const SP{ std::get<float>(m_inputs[1].value) };
  float const KP{ std::get<float>(m_inputs[2].value) };
  float const KI{ std::get<float>(m_inputs[3].value) };
  float const KD{ std::get<float>(m_inputs[4].value) };
  float const CV_HIGH{ std::get<float>(m_inputs[5].value) };
  float const CV_LOW{ std::get<float>(m_inputs[6].value) };

  float const ERROR{ SP - PV };

  if (!nearly_equal(KI, 0.0f)) m_integral += (ERROR * m_delta) / KI;
  m_integral = std::clamp(m_integral, CV_LOW, CV_HIGH);

  float const P{ KP * ERROR };
  float const I{ m_integral };
  float const D{ KD * ((ERROR - m_lastError) / m_delta) };

  float const CV{ std::clamp(P + I + D, CV_LOW, CV_HIGH) };

  m_lastError = ERROR;

  m_outputs[0].value = CV;
}

} // namespace spaghetti::elements::logic
<|endoftext|>


<commit_before>#ifndef _SNARKFRONT_ALG_UINT_HPP_
#define _SNARKFRONT_ALG_UINT_HPP_

#include <algorithm>
#include <cassert>

#include <snarkfront/Alg.hpp>

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// Alg_uint8
// Alg_uint32
// Alg_uint64
//

template <typename ALG>
void evalStackOp_internal(std::stack<ALG>& S, const BitwiseOps op)
{
    typedef typename ALG::ValueType Value;
    typedef typename ALG::FrType Fr;
    typedef typename ALG::R1T R1T;
    auto& RS = TL<R1C<Fr>>::singleton();

    typedef BitwiseINT<Value> BitOps;

    // y is right argument
    const auto R = S.top();
    S.pop();
    const Value yvalue = R.value();
    const Fr ywitness = R.witness();

    // modulo addition
    if (BitwiseOps::ADDMOD == op) {
        // x is left argument
        const auto L = S.top();
        S.pop();
        const Value xvalue = L.value();
        const Fr xwitness = L.witness();

        // left argument
        R1T x;
        Fr x_witness;
        Value xhigh, xlow;
        std::size_t xhighCnt;
        if (L.splitBits().size() < 2 * sizeBits(xvalue)) {
            x_witness = xwitness;
            x = RS->argScalar(L);

            const std::vector<int> xrem = bitsValue(xlow, L.splitBits());
            bitsValue(xhigh, xrem);
            xhighCnt = xrem.size();

#ifdef USE_ASSERT
            assert(xlow == xvalue);
            assert(xhighCnt < sizeBits(xvalue));
#endif

        } else {
            x_witness = ALG::valueToString(xvalue);
            const std::vector<R1T> xbits = RS->argBits(L);
            const std::vector<R1T> xfit = rank1_xword(xbits, sizeBits(xvalue));
            x = RS->bitsToWitness(xfit, x_witness);

            xlow = xvalue;
            xhigh = 0;
            xhighCnt = 0;
        }

        // right argument
        R1T y;
        Fr y_witness;
        Value yhigh, ylow;
        std::size_t yhighCnt;
        if (R.splitBits().size() < 2 * sizeBits(yvalue)) {
            y_witness = ywitness;
            y = RS->argScalar(R);

            const std::vector<int> yrem = bitsValue(ylow, R.splitBits());
            bitsValue(yhigh, yrem);
            yhighCnt = yrem.size();

#ifdef USE_ASSERT
            assert(ylow == yvalue);
            assert(yhighCnt < sizeBits(yvalue));
#endif

        } else {
            y_witness = ALG::valueToString(yvalue);
            const std::vector<R1T> ybits = RS->argBits(R);
            const std::vector<R1T> yfit = rank1_xword(ybits, sizeBits(yvalue));
            y = RS->bitsToWitness(yfit, y_witness);

            ylow = yvalue;
            yhigh = 0;
            yhighCnt = 0;
        }

        // overflow addition
        Value high = xhigh + yhigh, low = xlow;
        addover(high, low, ylow);

        const Value zvalue = BitOps::ADDMOD(xvalue, yvalue);
#ifdef USE_ASSERT
        assert(zvalue == low);
#endif

        std::vector<int> zbits = valueBits(low);
        for (std::size_t i = 0; i < xhighCnt + yhighCnt + 1; ++i) {
            zbits.push_back(high & 0x1);
            high >>= 1;
        }
#ifdef USE_ASSERT
        assert(0 == high);
#endif

        const Fr zwitness = x_witness + y_witness;
        const R1T z = RS->createResult(op, x, y, zwitness);

        S.push(
            ALG(zvalue, zwitness, zbits, {z}));

    } else if (BitwiseOps::CMPLMNT == op) {
        // y is only argument
        const std::vector<R1T> y = RS->argBits(R);
#ifdef USE_ASSERT
        assert(y.size() >= sizeBits(yvalue));
        assert(y.size() == R.splitBits().size());
#endif

        // z is result
        const Value zvalue = BitOps::CMPLMNT(yvalue);

        std::vector<int> zbits;
        std::vector<R1T> z;
        zbits.reserve(sizeBits(zvalue));
        z.reserve(sizeBits(zvalue));
        for (std::size_t i = 0; i < sizeBits(zvalue); ++i) {
            const bool b = ! R.splitBits()[i];
            zbits.push_back(b);
            z.emplace_back(
                RS->createResult(op, y[i], y[i], boolTo<Fr>(b)));
        }
#ifdef USE_ASSERT
        assert(zbits == valueBits(zvalue));
#endif

        S.push(
            ALG(zvalue, ALG::valueToString(zvalue), zbits, z));

    } else {
        // x is left argument
        const auto L = S.top();
        S.pop();
        const Value xvalue = L.value();
        const Fr xwitness = L.witness();

        const std::vector<R1T> x = RS->argBits(L);
#ifdef USE_ASSERT
        assert(x.size() >= sizeBits(xvalue));
#endif

        // z is result
        const Value zvalue = evalOp(op, xvalue, yvalue);

        std::vector<R1T> z;
        z.reserve(sizeBits(zvalue));

        if (isPermute(op)) {
            const std::vector<R1T> xfit = rank1_xword(x, sizeBits(xvalue));
            z = RS->permuteBits(op, xfit, yvalue);

        } else {
            const std::vector<R1T> y = RS->argBits(R);
#ifdef USE_ASSERT
            assert(y.size() >= sizeBits(yvalue));
#endif

            Value mask = 0x1;
            for (std::size_t i = 0; i < sizeBits(zvalue); ++i) {
                z.emplace_back(
                    RS->createResult(op, x[i], y[i], boolTo<Fr>(zvalue & mask)));

                mask <<= 1;
            }
        }

        S.push(
            ALG(zvalue, ALG::valueToString(zvalue), valueBits(zvalue), z));
    }
}

template <typename FR>
void evalStackOp(std::stack<Alg_uint8<FR>>& S, const BitwiseOps op)
{
    evalStackOp_internal<Alg_uint8<FR>>(S, op);
}

template <typename FR>
void evalStackOp(std::stack<Alg_uint32<FR>>& S, const BitwiseOps op)
{
    evalStackOp_internal<Alg_uint32<FR>>(S, op);
}

template <typename FR>
void evalStackOp(std::stack<Alg_uint64<FR>>& S, const BitwiseOps op)
{
    evalStackOp_internal<Alg_uint64<FR>>(S, op);
}

template <typename ALG>
void evalStackCmp_internal(std::stack<ALG>& S, const EqualityCmp op)
{
    typedef typename ALG::ValueType Value;
    typedef typename ALG::FrType Fr;
    typedef typename ALG::R1T R1T;
    auto& RS = TL<R1C<Fr>>::singleton();
    auto& POW2 = TL<PowersOf2<Fr>>::singleton();

    // y is right argument
    const auto R = S.top();
    S.pop();
    const Value yvalue = R.value();
    const std::vector<int> ybits = R.splitBits();
    const std::vector<R1T> y = RS->argBits(R);

#ifdef USE_ASSERT
    assert(y.size() >= sizeBits(yvalue));
#endif

    // x is left argument
    const auto L = S.top();
    S.pop();
    const Value xvalue = L.value();
    const std::vector<int> xbits = L.splitBits();
    const std::vector<R1T> x = RS->argBits(L);

#ifdef USE_ASSERT
    assert(x.size() >= sizeBits(xvalue));
#endif

    // intermediate constraint variables for each bit
    std::vector<R1T> zvec;
    std::vector<int> zwitness;
    zvec.reserve(sizeBits(yvalue));
    zwitness.reserve(sizeBits(yvalue));
    for (std::size_t i = 0; i < sizeBits(yvalue); ++i) {
        const bool b = evalOp(op, xbits[i], ybits[i]);
        zwitness.push_back(b);
        zvec.emplace_back(
            RS->createResult(eqToLogical(op), x[i], y[i], boolTo<Fr>(b)));
    }

    // z is result
    const Value zvalue = evalOp(op, xvalue, yvalue);
    const R1T z = EqualityCmp::EQ == op
        ? RS->declarative_AND(zvec) // all must be same
        : RS->imperative_OR(zvec, zwitness); // one must be different

    S.push(
        ALG(zvalue, boolTo<Fr>(zvalue), valueBits(zvalue), {z}));
}

template <typename FR>
void evalStackCmp(std::stack<Alg_uint8<FR>>& S, const EqualityCmp op)
{
    evalStackCmp_internal(S, op);
}

template <typename FR>
void evalStackCmp(std::stack<Alg_uint32<FR>>& S, const EqualityCmp op)
{
    evalStackCmp_internal(S, op);
}

template <typename FR>
void evalStackCmp(std::stack<Alg_uint64<FR>>& S, const EqualityCmp op)
{
    evalStackCmp_internal(S, op);
}

} // namespace snarkfront

#endif
<commit_msg>use refactored internal<commit_after>#ifndef _SNARKFRONT_ALG_UINT_HPP_
#define _SNARKFRONT_ALG_UINT_HPP_

#include <algorithm>
#include <cassert>

#include <snarkfront/Alg.hpp>
#include <snarkfront/Alg_internal.hpp>

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// Alg_uint8
// Alg_uint32
// Alg_uint64
//

template <typename ALG>
void evalStackOp_Bitwise(std::stack<ALG>& S, const BitwiseOps op)
{
    typedef typename ALG::ValueType Value;
    typedef typename ALG::FrType Fr;
    typedef typename ALG::R1T R1T;
    auto& RS = TL<R1C<Fr>>::singleton();

    typedef BitwiseINT<Value> BitOps;

    // y is right argument
    const auto R = S.top();
    S.pop();
    const Value yvalue = R.value();
    const Fr ywitness = R.witness();

    // modulo addition
    if (BitwiseOps::ADDMOD == op) {
        // x is left argument
        const auto L = S.top();
        S.pop();
        const Value xvalue = L.value();
        const Fr xwitness = L.witness();

        // left argument
        R1T x;
        Fr x_witness;
        Value xhigh, xlow;
        std::size_t xhighCnt;
        if (L.splitBits().size() < 2 * sizeBits(xvalue)) {
            x_witness = xwitness;
            x = RS->argScalar(L);

            const std::vector<int> xrem = bitsValue(xlow, L.splitBits());
            bitsValue(xhigh, xrem);
            xhighCnt = xrem.size();

#ifdef USE_ASSERT
            assert(xlow == xvalue);
            assert(xhighCnt < sizeBits(xvalue));
#endif

        } else {
            x_witness = ALG::valueToString(xvalue);
            const std::vector<R1T> xbits = RS->argBits(L);
            const std::vector<R1T> xfit = rank1_xword(xbits, sizeBits(xvalue));
            x = RS->bitsToWitness(xfit, x_witness);

            xlow = xvalue;
            xhigh = 0;
            xhighCnt = 0;
        }

        // right argument
        R1T y;
        Fr y_witness;
        Value yhigh, ylow;
        std::size_t yhighCnt;
        if (R.splitBits().size() < 2 * sizeBits(yvalue)) {
            y_witness = ywitness;
            y = RS->argScalar(R);

            const std::vector<int> yrem = bitsValue(ylow, R.splitBits());
            bitsValue(yhigh, yrem);
            yhighCnt = yrem.size();

#ifdef USE_ASSERT
            assert(ylow == yvalue);
            assert(yhighCnt < sizeBits(yvalue));
#endif

        } else {
            y_witness = ALG::valueToString(yvalue);
            const std::vector<R1T> ybits = RS->argBits(R);
            const std::vector<R1T> yfit = rank1_xword(ybits, sizeBits(yvalue));
            y = RS->bitsToWitness(yfit, y_witness);

            ylow = yvalue;
            yhigh = 0;
            yhighCnt = 0;
        }

        // overflow addition
        Value high = xhigh + yhigh, low = xlow;
        addover(high, low, ylow);

        const Value zvalue = BitOps::ADDMOD(xvalue, yvalue);
#ifdef USE_ASSERT
        assert(zvalue == low);
#endif

        std::vector<int> zbits = valueBits(low);
        for (std::size_t i = 0; i < xhighCnt + yhighCnt + 1; ++i) {
            zbits.push_back(high & 0x1);
            high >>= 1;
        }
#ifdef USE_ASSERT
        assert(0 == high);
#endif

        const Fr zwitness = x_witness + y_witness;
        const R1T z = RS->createResult(op, x, y, zwitness);

        S.push(
            ALG(zvalue, zwitness, zbits, {z}));

    } else if (BitwiseOps::CMPLMNT == op) {
        // y is only argument
        const std::vector<R1T> y = RS->argBits(R);
#ifdef USE_ASSERT
        assert(y.size() >= sizeBits(yvalue));
        assert(y.size() == R.splitBits().size());
#endif

        // z is result
        const Value zvalue = BitOps::CMPLMNT(yvalue);

        std::vector<int> zbits;
        std::vector<R1T> z;
        zbits.reserve(sizeBits(zvalue));
        z.reserve(sizeBits(zvalue));
        for (std::size_t i = 0; i < sizeBits(zvalue); ++i) {
            const bool b = ! R.splitBits()[i];
            zbits.push_back(b);
            z.emplace_back(
                RS->createResult(op, y[i], y[i], boolTo<Fr>(b)));
        }
#ifdef USE_ASSERT
        assert(zbits == valueBits(zvalue));
#endif

        S.push(
            ALG(zvalue, ALG::valueToString(zvalue), zbits, z));

    } else {
        // x is left argument
        const auto L = S.top();
        S.pop();
        const Value xvalue = L.value();
        const Fr xwitness = L.witness();

        const std::vector<R1T> x = RS->argBits(L);
#ifdef USE_ASSERT
        assert(x.size() >= sizeBits(xvalue));
#endif

        // z is result
        const Value zvalue = evalOp(op, xvalue, yvalue);

        std::vector<R1T> z;
        z.reserve(sizeBits(zvalue));

        if (isPermute(op)) {
            const std::vector<R1T> xfit = rank1_xword(x, sizeBits(xvalue));
            z = RS->permuteBits(op, xfit, yvalue);

        } else {
            const std::vector<R1T> y = RS->argBits(R);
#ifdef USE_ASSERT
            assert(y.size() >= sizeBits(yvalue));
#endif

            Value mask = 0x1;
            for (std::size_t i = 0; i < sizeBits(zvalue); ++i) {
                z.emplace_back(
                    RS->createResult(op, x[i], y[i], boolTo<Fr>(zvalue & mask)));

                mask <<= 1;
            }
        }

        S.push(
            ALG(zvalue, ALG::valueToString(zvalue), valueBits(zvalue), z));
    }
}

template <typename FR>
void evalStackOp(std::stack<Alg_uint8<FR>>& S, const BitwiseOps op) {
    evalStackOp_Bitwise<Alg_uint8<FR>>(S, op);
}

template <typename FR>
void evalStackOp(std::stack<Alg_uint32<FR>>& S, const BitwiseOps op) {
    evalStackOp_Bitwise<Alg_uint32<FR>>(S, op);
}

template <typename FR>
void evalStackOp(std::stack<Alg_uint64<FR>>& S, const BitwiseOps op) {
    evalStackOp_Bitwise<Alg_uint64<FR>>(S, op);
}

template <typename FR>
void evalStackCmp(std::stack<Alg_uint8<FR>>& S, const EqualityCmp op) {
    evalStackCmp_Equality(S, op);
}

template <typename FR>
void evalStackCmp(std::stack<Alg_uint32<FR>>& S, const EqualityCmp op) {
    evalStackCmp_Equality(S, op);
}

template <typename FR>
void evalStackCmp(std::stack<Alg_uint64<FR>>& S, const EqualityCmp op) {
    evalStackCmp_Equality(S, op);
}

} // namespace snarkfront

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Esrille Inc.
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <assert.h>
#include <ctype.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

namespace {

bool isDigit(char16_t c)
{
    return '0' <= c && c <= '9';
}

int isHexDigit(char16_t c)
{
    if ('0' <= c && c <= '9')
        return '0';
    if ('A' <= c && c <= 'F')
        return 'A' - 10;
    if ('a' <= c && c <= 'f')
        return 'a' - 10;
    return 0;
}

bool isSpace(char16_t c)
{
    switch (c) {
    // White Space
    case u'\u0009': // Tab <TAB>
    case u'\u000B': // Vertical Tab <VT>
    case u'\u000C': // Form Feed <FF>
    case u'\u0020': // Space <SP>
    case u'\u00A0': // No-break space <NBSP>
    case u'\uFEFF': // Byte Order Mark <BOM>
    // Other category “Zs” Any other Unicode “space separator” <USP>
    case u'\u1680':
    case u'\u180e':
    case u'\u2000':
    case u'\u2001':
    case u'\u2002':
    case u'\u2003':
    case u'\u2004':
    case u'\u2005':
    case u'\u2006':
    case u'\u2007':
    case u'\u2008':
    case u'\u2009':
    case u'\u200a':
    case u'\u202f':
    case u'\u205f':
    case u'\u3000':
    // Line Terminators
    case u'\u000A':  // Line Feed <LF>
    case u'\u000D':  // Carriage Return <CR>
    case u'\u2028':  // Line separator <LS>
    case u'\u2029':  // Paragraph separator <PS>
        return true;
    default:
        return false;
    }
}

std::u16string toString(const char* format, ...)
{
    va_list ap;
    char buffer[24];
    std::u16string text;

    va_start(ap, format);
    vsnprintf(buffer, sizeof buffer, format, ap);
    va_end(ap);
    for (char* p = buffer; *p; ++p)
        text += static_cast<char16_t>(*p);
    return text;
}

std::u16string toString(double value)
{
    if (isnan(value))
        return u"NaN";
    if (isinf(value))
        return (isinf(value) == 1) ? u"Infinity" : u"-Infinity";
    std::u16string text;
    char buffer[24];
    std::sprintf(buffer, "%g", value);
    for (char* p = buffer; *p; ++p)
        text += static_cast<char16_t>(*p);
    return text;
}

double toNumber(const std::u16string& value)
{
    char16_t c = 0;
    std::u16string::const_iterator i = value.begin();
    while (i != value.end()) {
        c = *i;
        if (!isSpace(c))
            break;
        ++i;
    }
    double number = 0.0;
    if (value.compare(i - value.begin(), 2, u"0x") == 0 || value.compare(i - value.begin(), 2, u"0X") == 0) {
        for (i += 2; i != value.end(); ++i) {
            c = *i;
            int hex = isHexDigit(c);
            if (!hex)
                break;
            number *= 16;
            number += (c - hex);
        }
    } else {
        bool negative = (c == '-');
        if (negative || c == '+')
            ++i;
        int exp = 0;
        if (value.compare(i - value.begin(), 8, u"Infinity") == 0) {
            i += 8;
            number = negative ? -INFINITY : INFINITY;
        } else {
            while (i != value.end()) {
                c = *i;
                if (!isDigit(c))
                    break;
                number *= 10.0;
                number += (c - '0');
                ++i;
            }
            if (c == '.') {
                while (++i != value.end()) {
                    c = *i;
                    if (!isDigit(c))
                        break;
                    number *= 10.0;
                    number += (c - '0');
                    --exp;
                }
            }
            if (negative)
                number = -number;
            if (c == 'e' || c == 'E') {
                negative = false;
                if (++i != value.end()) {
                    c = *i;
                    negative = (c == '-');
                    if (negative || c == '+')
                        ++i;
                }
                int n = 0;
                while (i != value.end()) {
                    c = *i;
                    if (!isDigit(c))
                        break;
                    n *= 10;
                    n += (c - '0');
                    ++i;
                }
                if (negative)
                    exp -= n;
                else
                    exp += n;
            }
            if (DBL_MAX_EXP < exp)
                number = negative ? -INFINITY : INFINITY;
            else if (exp < DBL_MIN_EXP)
                number = negative ? -0.0 : 0.0;
            else {
                double p10 = 10.0;
                int n = exp;
                if (n < 0)
                    n = -n;
                while (n) {
                    if (n & 1) {
                        if (exp < 0)
                            number /= p10;
                        else
                            number *= p10;
                    }
                    n >>= 1;
                    p10 *= p10;
                }
            }
        }
    }
    while (i != value.end()) {
        if (!isSpace(*i))
            return NAN;
        ++i;
    }
    return number;
};

}  // namespace

bool Any::isString() const
{
    return (type == Dynamic) && vtable->getType() == typeid(std::u16string);
}

std::u16string Any::toString() const
{
    switch (type) {
    case Bool:
        return heap.i32 ? u"true" : u"false";
    case Int32:
        return ::toString("%d", heap.i32);
    case Uint32:
        return ::toString("%u", heap.u32);
    case Int64:
        return ::toString("%lld", heap.i64);
    case Uint64:
        return ::toString("%llu", heap.u64);
    case Float32:
        return ::toString(heap.f32);
    case Float64:
        return ::toString(heap.f64);
    case Dynamic:
        if (vtable->getType() == typeid(std::u16string))
            return *reinterpret_cast<const std::u16string*>(&heap);
    default:
        break;
    }
    return std::u16string();
}

// toNumber
// for Object, call valueOf and then apply toNumber
// null returns 0, undefined returns NAN
double Any::toNumber() const
{
    switch (type) {
    case Undefined:
        return NAN;
    case Bool:
    case Int32:
        return heap.i32;
    case Uint32:
        return heap.u32;
    case Int64:
        return heap.i64;
    case Uint64:
        return heap.u64;
    case Float32:
        return heap.f32;
    case Float64:
        return heap.f64;
    case Dynamic:
        if (vtable->getType() == typeid(std::u16string))
            return ::toNumber(*reinterpret_cast<const std::u16string*>(&heap));
        break;
    default:
        break;
    }
    return 0.0;
}

// toBoolean
// Object returns true. Otherwise, false.
// NAN returns false.
// empty string returns false. Otherwise, true.
bool Any::toBoolean() const
{
    switch (type) {
    case Bool:
    case Int32:
        return heap.i32;
    case Uint32:
        return heap.u32;
    case Int64:
        return heap.i64;
    case Uint64:
        return heap.u64;
    case Float32:
        return heap.f32 && !isnan(heap.f32);
    case Float64:
        return heap.f64 && !isnan(heap.f64);
    case Dynamic:
        if (vtable->getType() == typeid(std::u16string))
            return (*reinterpret_cast<const std::u16string*>(&heap)).length();
        return true;
        break;
    default:
        break;
    }
    return false;
}

bool Any::isObject() const
{
    return (type == Dynamic) && vtable->getType() == typeid(Object);
}

Object* Any::toObject() const
{
    if (isObject())
        return reinterpret_cast<const Object*>(&heap)->self();
    return 0;
}<commit_msg>(Any) : Merge changes in esidl/jsapi.<commit_after>/*
 * Copyright 2011 Esrille Inc.
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <assert.h>
#include <ctype.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

namespace {

bool isDigit(char16_t c)
{
    return '0' <= c && c <= '9';
}

int isHexDigit(char16_t c)
{
    if ('0' <= c && c <= '9')
        return '0';
    if ('A' <= c && c <= 'F')
        return 'A' - 10;
    if ('a' <= c && c <= 'f')
        return 'a' - 10;
    return 0;
}

bool isSpace(char16_t c)
{
    switch (c) {
    // White Space
    case u'\u0009': // Tab <TAB>
    case u'\u000B': // Vertical Tab <VT>
    case u'\u000C': // Form Feed <FF>
    case u'\u0020': // Space <SP>
    case u'\u00A0': // No-break space <NBSP>
    case u'\uFEFF': // Byte Order Mark <BOM>
    // Other category “Zs” Any other Unicode “space separator” <USP>
    case u'\u1680':
    case u'\u180e':
    case u'\u2000':
    case u'\u2001':
    case u'\u2002':
    case u'\u2003':
    case u'\u2004':
    case u'\u2005':
    case u'\u2006':
    case u'\u2007':
    case u'\u2008':
    case u'\u2009':
    case u'\u200a':
    case u'\u202f':
    case u'\u205f':
    case u'\u3000':
    // Line Terminators
    case u'\u000A':  // Line Feed <LF>
    case u'\u000D':  // Carriage Return <CR>
    case u'\u2028':  // Line separator <LS>
    case u'\u2029':  // Paragraph separator <PS>
        return true;
    default:
        return false;
    }
}

std::u16string toString(const char* format, ...)
{
    va_list ap;
    char buffer[24];
    std::u16string text;

    va_start(ap, format);
    vsnprintf(buffer, sizeof buffer, format, ap);
    va_end(ap);
    for (char* p = buffer; *p; ++p)
        text += static_cast<char16_t>(*p);
    return text;
}

std::u16string toString(double value)
{
    if (isnan(value))
        return u"NaN";
    if (isinf(value))
        return (isinf(value) == 1) ? u"Infinity" : u"-Infinity";
    std::u16string text;
    char buffer[24];
    std::sprintf(buffer, "%g", value);
    for (char* p = buffer; *p; ++p)
        text += static_cast<char16_t>(*p);
    return text;
}

std::u16string toString(Object* object)
{
    if (!object)
        return u"null";
    Any result = object->message_(0, 0, Object::STRINGIFY_, 0);
    if (result.isString())
        return result.toString();
    return u"";
}

double toNumber(const std::u16string& value)
{
    char16_t c = 0;
    std::u16string::const_iterator i = value.begin();
    while (i != value.end()) {
        c = *i;
        if (!isSpace(c))
            break;
        ++i;
    }
    double number = 0.0;
    if (value.compare(i - value.begin(), 2, u"0x") == 0 || value.compare(i - value.begin(), 2, u"0X") == 0) {
        for (i += 2; i != value.end(); ++i) {
            c = *i;
            int hex = isHexDigit(c);
            if (!hex)
                break;
            number *= 16;
            number += (c - hex);
        }
    } else {
        bool negative = (c == '-');
        if (negative || c == '+')
            ++i;
        int exp = 0;
        if (value.compare(i - value.begin(), 8, u"Infinity") == 0) {
            i += 8;
            number = negative ? -INFINITY : INFINITY;
        } else {
            while (i != value.end()) {
                c = *i;
                if (!isDigit(c))
                    break;
                number *= 10.0;
                number += (c - '0');
                ++i;
            }
            if (c == '.') {
                while (++i != value.end()) {
                    c = *i;
                    if (!isDigit(c))
                        break;
                    number *= 10.0;
                    number += (c - '0');
                    --exp;
                }
            }
            if (negative)
                number = -number;
            if (c == 'e' || c == 'E') {
                negative = false;
                if (++i != value.end()) {
                    c = *i;
                    negative = (c == '-');
                    if (negative || c == '+')
                        ++i;
                }
                int n = 0;
                while (i != value.end()) {
                    c = *i;
                    if (!isDigit(c))
                        break;
                    n *= 10;
                    n += (c - '0');
                    ++i;
                }
                if (negative)
                    exp -= n;
                else
                    exp += n;
            }
            if (DBL_MAX_EXP < exp)
                number = negative ? -INFINITY : INFINITY;
            else if (exp < DBL_MIN_EXP)
                number = negative ? -0.0 : 0.0;
            else {
                double p10 = 10.0;
                int n = exp;
                if (n < 0)
                    n = -n;
                while (n) {
                    if (n & 1) {
                        if (exp < 0)
                            number /= p10;
                        else
                            number *= p10;
                    }
                    n >>= 1;
                    p10 *= p10;
                }
            }
        }
    }
    while (i != value.end()) {
        if (!isSpace(*i))
            return NAN;
        ++i;
    }
    return number;
};

}  // namespace

bool Any::isString() const
{
    return (type == Dynamic) && vtable->getType() == typeid(std::u16string);
}

std::u16string Any::toString() const
{
    switch (type) {
    case Bool:
        return heap.i32 ? u"true" : u"false";
    case Int32:
        return ::toString("%d", heap.i32);
    case Uint32:
        return ::toString("%u", heap.u32);
    case Int64:
        return ::toString("%lld", heap.i64);
    case Uint64:
        return ::toString("%llu", heap.u64);
    case Float32:
        return ::toString(heap.f32);
    case Float64:
        return ::toString(heap.f64);
    case Dynamic:
        if (vtable->getType() == typeid(std::u16string))
            return *reinterpret_cast<const std::u16string*>(&heap);
        if (vtable->getType() == typeid(Object))
            return ::toString(const_cast<Object*>(reinterpret_cast<const Object*>(&heap)->self()));
        break;
    default:
        break;
    }
    return std::u16string();
}

// toNumber
// for Object, call valueOf and then apply toNumber
// null returns 0, undefined returns NAN
double Any::toNumber() const
{
    switch (type) {
    case Undefined:
        return NAN;
    case Bool:
    case Int32:
        return heap.i32;
    case Uint32:
        return heap.u32;
    case Int64:
        return heap.i64;
    case Uint64:
        return heap.u64;
    case Float32:
        return heap.f32;
    case Float64:
        return heap.f64;
    case Dynamic:
        if (vtable->getType() == typeid(std::u16string))
            return ::toNumber(*reinterpret_cast<const std::u16string*>(&heap));
        break;
    default:
        break;
    }
    return 0.0;
}

// toBoolean
// Object returns true. Otherwise, false.
// NAN returns false.
// empty string returns false. Otherwise, true.
bool Any::toBoolean() const
{
    switch (type) {
    case Bool:
    case Int32:
        return heap.i32;
    case Uint32:
        return heap.u32;
    case Int64:
        return heap.i64;
    case Uint64:
        return heap.u64;
    case Float32:
        return heap.f32 && !isnan(heap.f32);
    case Float64:
        return heap.f64 && !isnan(heap.f64);
    case Dynamic:
        if (vtable->getType() == typeid(std::u16string))
            return (*reinterpret_cast<const std::u16string*>(&heap)).length();
        return true;
        break;
    default:
        break;
    }
    return false;
}

bool Any::isObject() const
{
    return (type == Dynamic) && vtable->getType() == typeid(Object);
}

Object* Any::toObject() const
{
    if (isObject())
        return reinterpret_cast<const Object*>(&heap)->self();
    return 0;
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: QueryTabWinUndoAct.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2005-09-23 12:43:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef DBAUI_OQueryTabWinUndoAct_HXX
#include "QueryTabWinUndoAct.hxx"
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef DBAUI_QUERY_TABLEWINDOW_HXX
#include "QTableWindow.hxx"
#endif
#ifndef DBAUI_QUERY_TABLEWINDOWDATA_HXX
#include "QTableWindowData.hxx"
#endif
#ifndef DBAUI_TABLECONNECTION_HXX
#include "TableConnection.hxx"
#endif
#ifndef DBAUI_TABLECONNECTIONDATA_HXX
#include "TableConnectionData.hxx"
#endif
#ifndef DBAUI_QUERYDESIGNFIELDUNDOACT_HXX
#include "QueryDesignFieldUndoAct.hxx"
#endif
#ifndef DBAUI_QUERYTABLEVIEW_HXX
#include "QueryTableView.hxx"
#endif

using namespace dbaui;
DBG_NAME(OQueryDesignFieldUndoAct)
OQueryDesignFieldUndoAct::OQueryDesignFieldUndoAct(OSelectionBrowseBox* pSelBrwBox, USHORT nCommentID)
    : OCommentUndoAction(nCommentID)
    , pOwner(pSelBrwBox)
    , m_nColumnPostion(BROWSER_INVALIDID)
{
    DBG_CTOR(OQueryDesignFieldUndoAct,NULL);
}
// -----------------------------------------------------------------------------
OQueryDesignFieldUndoAct::~OQueryDesignFieldUndoAct()
{
    DBG_DTOR(OQueryDesignFieldUndoAct,NULL);
    pOwner = NULL;
}
// -----------------------------------------------------------------------------

DBG_NAME(OQueryTabWinUndoAct )
// ------------------------------------------------------------------------------------------------
OQueryTabWinUndoAct::OQueryTabWinUndoAct(OQueryTableView* pOwner, USHORT nCommentID)
    :OQueryDesignUndoAction(pOwner, nCommentID)
    ,m_pTabWin(NULL)
{
    DBG_CTOR(OQueryTabWinUndoAct ,NULL);
}
//==============================================================================
OQueryTabWinUndoAct::~OQueryTabWinUndoAct()
{
    DBG_DTOR(OQueryTabWinUndoAct ,NULL);
    if (m_bOwnerOfObjects)
    {   // wenn ich der alleinige Owner des Fenster bin, muss ich dafuer sorgen, dass es geloescht wird
        OSL_ENSURE(m_pTabWin != NULL, "OQueryTabWinUndoAct::~OQueryTabWinUndoAct() : m_pTabWin sollte nicht NULL sein");
        OSL_ENSURE(!m_pTabWin->IsVisible(), "OQueryTabWinUndoAct::~OQueryTabWinUndoAct() : *m_pTabWin sollte nicht sichtbar sein");

        delete m_pTabWin->GetData();
        if ( m_pTabWin )
            m_pTabWin->clearListBox();
        delete m_pTabWin;

        // und natuerlich auch die entsprechenden Connections
        ::std::vector<OTableConnection*>::iterator aIter = m_vTableConnection.begin();
        for(;aIter != m_vTableConnection.end();++aIter)
        {
            m_pOwner->DeselectConn(*aIter);
            delete (*aIter)->GetData();
            delete (*aIter);
        }
        m_vTableConnection.clear();
    }
}
//------------------------------------------------------------------------------
void OTabFieldCellModifiedUndoAct::Undo()
{
    pOwner->EnterUndoMode();
    OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!");
    OSL_ENSURE(m_nColumnPostion < pOwner->GetColumnCount(),"Position outside the column count!");
    if ( m_nColumnPostion != BROWSER_INVALIDID )
    {
        USHORT nColumnId = pOwner->GetColumnId(m_nColumnPostion);
        String strNext = pOwner->GetCellContents(m_nCellIndex, nColumnId);
        pOwner->SetCellContents(m_nCellIndex, nColumnId, m_strNextCellContents);
        m_strNextCellContents = strNext;
    }
    pOwner->LeaveUndoMode();
}

//------------------------------------------------------------------------------
void OTabFieldSizedUndoAct::Undo()
{
    pOwner->EnterUndoMode();
    OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!");
    if ( m_nColumnPostion != BROWSER_INVALIDID )
    {
        USHORT nColumnId = pOwner->GetColumnId(m_nColumnPostion);
        long nNextWidth = pOwner->GetColumnWidth(nColumnId);
        pOwner->SetColWidth(nColumnId, m_nNextWidth);
        m_nNextWidth = nNextWidth;
    }
    pOwner->LeaveUndoMode();
}
// -----------------------------------------------------------------------------
void OTabFieldMovedUndoAct::Undo()
{
    pOwner->EnterUndoMode();
    OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!");
    if ( m_nColumnPostion != BROWSER_INVALIDID )
    {
        sal_uInt16 nId = pDescr->GetColumnId();
        USHORT nOldPos = pOwner->GetColumnPos(nId);
        pOwner->SetColumnPos(nId,m_nColumnPostion);
        pOwner->ColumnMoved(nId,FALSE);
        m_nColumnPostion = nOldPos;
    }
    pOwner->LeaveUndoMode();
}
// -----------------------------------------------------------------------------

<commit_msg>INTEGRATION: CWS pchfix02 (1.10.178); FILE MERGED 2006/09/01 17:24:37 kaib 1.10.178.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: QueryTabWinUndoAct.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 07:23:08 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"
#ifndef DBAUI_OQueryTabWinUndoAct_HXX
#include "QueryTabWinUndoAct.hxx"
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef DBAUI_QUERY_TABLEWINDOW_HXX
#include "QTableWindow.hxx"
#endif
#ifndef DBAUI_QUERY_TABLEWINDOWDATA_HXX
#include "QTableWindowData.hxx"
#endif
#ifndef DBAUI_TABLECONNECTION_HXX
#include "TableConnection.hxx"
#endif
#ifndef DBAUI_TABLECONNECTIONDATA_HXX
#include "TableConnectionData.hxx"
#endif
#ifndef DBAUI_QUERYDESIGNFIELDUNDOACT_HXX
#include "QueryDesignFieldUndoAct.hxx"
#endif
#ifndef DBAUI_QUERYTABLEVIEW_HXX
#include "QueryTableView.hxx"
#endif

using namespace dbaui;
DBG_NAME(OQueryDesignFieldUndoAct)
OQueryDesignFieldUndoAct::OQueryDesignFieldUndoAct(OSelectionBrowseBox* pSelBrwBox, USHORT nCommentID)
    : OCommentUndoAction(nCommentID)
    , pOwner(pSelBrwBox)
    , m_nColumnPostion(BROWSER_INVALIDID)
{
    DBG_CTOR(OQueryDesignFieldUndoAct,NULL);
}
// -----------------------------------------------------------------------------
OQueryDesignFieldUndoAct::~OQueryDesignFieldUndoAct()
{
    DBG_DTOR(OQueryDesignFieldUndoAct,NULL);
    pOwner = NULL;
}
// -----------------------------------------------------------------------------

DBG_NAME(OQueryTabWinUndoAct )
// ------------------------------------------------------------------------------------------------
OQueryTabWinUndoAct::OQueryTabWinUndoAct(OQueryTableView* pOwner, USHORT nCommentID)
    :OQueryDesignUndoAction(pOwner, nCommentID)
    ,m_pTabWin(NULL)
{
    DBG_CTOR(OQueryTabWinUndoAct ,NULL);
}
//==============================================================================
OQueryTabWinUndoAct::~OQueryTabWinUndoAct()
{
    DBG_DTOR(OQueryTabWinUndoAct ,NULL);
    if (m_bOwnerOfObjects)
    {   // wenn ich der alleinige Owner des Fenster bin, muss ich dafuer sorgen, dass es geloescht wird
        OSL_ENSURE(m_pTabWin != NULL, "OQueryTabWinUndoAct::~OQueryTabWinUndoAct() : m_pTabWin sollte nicht NULL sein");
        OSL_ENSURE(!m_pTabWin->IsVisible(), "OQueryTabWinUndoAct::~OQueryTabWinUndoAct() : *m_pTabWin sollte nicht sichtbar sein");

        delete m_pTabWin->GetData();
        if ( m_pTabWin )
            m_pTabWin->clearListBox();
        delete m_pTabWin;

        // und natuerlich auch die entsprechenden Connections
        ::std::vector<OTableConnection*>::iterator aIter = m_vTableConnection.begin();
        for(;aIter != m_vTableConnection.end();++aIter)
        {
            m_pOwner->DeselectConn(*aIter);
            delete (*aIter)->GetData();
            delete (*aIter);
        }
        m_vTableConnection.clear();
    }
}
//------------------------------------------------------------------------------
void OTabFieldCellModifiedUndoAct::Undo()
{
    pOwner->EnterUndoMode();
    OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!");
    OSL_ENSURE(m_nColumnPostion < pOwner->GetColumnCount(),"Position outside the column count!");
    if ( m_nColumnPostion != BROWSER_INVALIDID )
    {
        USHORT nColumnId = pOwner->GetColumnId(m_nColumnPostion);
        String strNext = pOwner->GetCellContents(m_nCellIndex, nColumnId);
        pOwner->SetCellContents(m_nCellIndex, nColumnId, m_strNextCellContents);
        m_strNextCellContents = strNext;
    }
    pOwner->LeaveUndoMode();
}

//------------------------------------------------------------------------------
void OTabFieldSizedUndoAct::Undo()
{
    pOwner->EnterUndoMode();
    OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!");
    if ( m_nColumnPostion != BROWSER_INVALIDID )
    {
        USHORT nColumnId = pOwner->GetColumnId(m_nColumnPostion);
        long nNextWidth = pOwner->GetColumnWidth(nColumnId);
        pOwner->SetColWidth(nColumnId, m_nNextWidth);
        m_nNextWidth = nNextWidth;
    }
    pOwner->LeaveUndoMode();
}
// -----------------------------------------------------------------------------
void OTabFieldMovedUndoAct::Undo()
{
    pOwner->EnterUndoMode();
    OSL_ENSURE(m_nColumnPostion != BROWSER_INVALIDID,"Column position was not set add the undo action!");
    if ( m_nColumnPostion != BROWSER_INVALIDID )
    {
        sal_uInt16 nId = pDescr->GetColumnId();
        USHORT nOldPos = pOwner->GetColumnPos(nId);
        pOwner->SetColumnPos(nId,m_nColumnPostion);
        pOwner->ColumnMoved(nId,FALSE);
        m_nColumnPostion = nOldPos;
    }
    pOwner->LeaveUndoMode();
}
// -----------------------------------------------------------------------------

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Rene Herthel
 *
 * This file is subject to the terms and conditions of the MIT License.
 * See the file LICENSE in the top level directory for more details.
 */

/**
 * @ingroup    error_handler
 * @{
 *
 * @brief      Function declaration of the ErrorHandler.
 *
 * @author     Rene Herthel <rene.herthel@haw-hamburg.de>
 */

#include "ErrorHandler.h"

#include "DistanceObservable.h"
#include "DistanceEnum.h"
#include "Signals.h"
#include "CodeDefinition.h"
#include "SerialProtocoll.h"
#include "Signals.h"

#include <iostream>
using namespace std;
using namespace HAL;

ErrorHandler::ErrorHandler( int chid,
                            ConveyorBeltService *conveyorBeltService,
                            LightSystemService *lightSystemService,
                            SerialService *serialService,
                            PuckManager *puckManager)
    :    m_hasError(false)
    ,    m_resetPressed(false)
    ,    m_conveyorBeltService(conveyorBeltService)
    ,    m_lightSystemService(lightSystemService)
	, 	 m_serialService(serialService)
	, 	 m_puckManager(puckManager)
{
    m_lightSystemService->setWarningLevel(Level::OPERATING);
}

ErrorHandler::~ErrorHandler()
{
    // Nothing todo so far.
}

void ErrorHandler::process(PuckManager::ManagerReturn &manager)
{
	LOG_DEBUG << "[ErrorHandler] Demux Manager return \n";
	LOG_DEBUG << "[ErrorHandler] Actor Flag " << manager.actorFlag << " actorSignal " << (int)manager.actorSignal << "\n";

	//if slide full return a warning
	if (manager.actorFlag && manager.actorSignal == PuckManager::ActorSignal::SEND_SLIDE_FULL){
		 m_lightSystemService->setWarningLevel(Level::WARNING_OCCURED);
		 LOG_DEBUG << "[ErrorHandler] Slide is full \n";
	}
	if (manager.actorFlag && manager.actorSignal == PuckManager::ActorSignal::SEND_SLIDE_EMPTY){
		 m_lightSystemService->setWarningLevel(Level::CLEAR_WARNING);
		 m_lightSystemService->setWarningLevel(Level::OPERATING);
		 LOG_DEBUG << "[ErrorHandler] Slide is empty \n";
	}

	//Only handle when error code
    if (manager.errorFlag) {
		m_hasError = true;

		m_lightSystemService->setWarningLevel(Level::ERROR_OCCURED);

		DistanceObservable &distO = DistanceObservable::getInstance();
		distO.updateSpeed(DistanceSpeed::STOP);

		m_conveyorBeltService->changeState(ConveyorBeltState::STOP);
		m_serialService->sendMsg(Serial_n::ser_proto_msg::STOP_SER);

		switch (manager.errorSignal) {

			case PuckManager::ErrorSignal::PUCK_LOST:
				cout << "[ErrorHandler] PUCK_LOST - Late Timer" << endl;
				LOG_DEBUG << "[ErrorHandler] PUCK_LOST - Late Timer" << endl;
				break;

			case PuckManager::ErrorSignal::PUCK_MOVED:
				cout << "[ErrorHandler] PUCK_MOVED - Puck triggered light barrier before early timer" << endl;
				LOG_DEBUG << "[ErrorHandler] PUCK_MOVED - Puck triggered light barrier before early timer" << endl;
				break;

			case PuckManager::ErrorSignal::UNEXPECTED_SIGNAL:
				cout << "[ErrorHandler] UNEXPECTED_SIGNAL - Signal could not be processed" << endl;
				LOG_DEBUG << "[ErrorHandler] UNEXPECTED_SIGNAL - Signal could not be processed" << endl;
				break;

			case PuckManager::ErrorSignal::MULTIPLE_ACCEPT:
				cout << "[ErrorHandler] MULTIPLE_ACCEPT - Shouldn't happen - multiple pucks were triggered" << endl;
				LOG_DEBUG << "[ErrorHandler] MULTIPLE_ACCEPT - Shouldn't happen - multiple pucks were triggered" << endl;
				break;

			case PuckManager::ErrorSignal::MULTIPLE_WARNING:
				cout << "[ErrorHandler] MULTIPLE_WARNING" << endl;
				LOG_DEBUG << "[ErrorHandler] MULTIPLE_WARNING" << endl;
				break;

			case PuckManager::ErrorSignal::BOTH_SLIDES_FULL:
				 cout << "[ErrorHandler] BOTH_SLIDES_FULL" << endl;
				 LOG_DEBUG << "[ErrorHandler] BOTH_SLIDES_FULL" << endl;
				 break;

			default:
				 LOG_DEBUG << "[ErrorHandler] Unkown Error !!!" << endl;
				break;
		}
    }
}

bool ErrorHandler::hasError()
{
	LOG_DEBUG << "[ErrorHandler] Error: " << m_hasError << "\n";
    return m_hasError;
}

void ErrorHandler::handleEvent(rcv::msg_t event)
{
	LOG_DEBUG << "[ErrorHandler] Trying to demux " << event.code << " " << event.value << "\n";
	switch(event.code){
		case CodeDefinition::SER_IN :
			if( event.value == Serial_n::ser_proto_msg::ESTOP_SER ||
				event.value == Serial_n::ser_proto_msg::ERROR_SER ||
				event.value == Serial_n::ser_proto_msg::NO_CON_SER  ){
				LOG_DEBUG << "[ErrorHandler] Got error from serial \n";
				m_lightSystemService->setWarningLevel(Level::ERROR_OCCURED);
				m_conveyorBeltService->changeState(ConveyorBeltState::STOP);
				m_hasError = true;
				m_resetPressed = false;
			}
			break;
		case CodeDefinition::ISR :
			if(event.value == interrupts::BUTTON_ESTOP_IN){
				LOG_DEBUG << "[ErrorHandler] Got Estop from ISR \n";
				m_lightSystemService->setWarningLevel(Level::ERROR_OCCURED);
				m_serialService->sendMsg(Serial_n::ser_proto_msg::ESTOP_SER);
				m_conveyorBeltService->changeState(ConveyorBeltState::STOP);
				m_hasError = true;
				m_resetPressed = false;
			}
			break;
		default :
			//Nothing to do
			break;
	}

	if(m_hasError){
		 	bool buttonReset = false;
		    bool buttonStart = false;

		    if (event.code == 5) { // 5 is hardcoded in the ISR. TODO Serial signal needs to get through when error is acknowledged on other machine
		    	switch(event.value) {

					case interrupts::BUTTON_RESET:
						buttonReset = true;
						break;

					case interrupts::BUTTON_START:
						buttonStart = true;
						break;

					case interrupts::SLIDE_OUT:
						LOG_DEBUG << "[ErrorHandler] Handling SLIDE_OUT error event " << endl;
						PuckSignal::Signal signal;
						signal.signalType = PuckSignal::SignalType::INTERRUPT_SIGNAL;
						signal.interruptSignal = (interrupts::interruptSignals) event.value;
						m_puckManager->process(signal);
						m_serialService->sendMsg(Serial_n::ser_proto_msg::SLIDE_EMTPY_SER); //huge bawrf
						break;
					default:
						// Nothing todo so far.
						break;
				}
		    } else if(event.code == CodeDefinition::Code::SER_IN) {
		    	if(event.value == Serial_n::ser_proto_msg::SLIDE_EMTPY_SER){
		    		m_puckManager->reset();
		    		PuckSignal::Signal signal;
					signal.signalType = PuckSignal::SignalType::SERIAL_SIGNAL;
					signal.serialSignal = (Serial_n::ser_proto_msg) event.value;
					m_puckManager->process(signal);
		    	}
		    }

		    LOG_DEBUG << "[ErrorHandler] Trying to handle error event " << int(event.value) << endl;

		    if (buttonReset && m_hasError) {
		        m_resetPressed = true;
		        cout << "Error acknowledged" << endl;
		        m_lightSystemService->setWarningLevel(Level::ERROR_ACKNOWLEDGED);
		    } else if (buttonStart && m_resetPressed && m_hasError) { // Only go further when reset was pressed before.
		    	m_puckManager->resetPucks();
				cout << "Clear error" << endl;
				m_lightSystemService->setWarningLevel(Level::OPERATING);
				m_resetPressed = false;
				m_hasError = false;
		    }
	}
}

/** @} */
<commit_msg>moved puck Manager reset<commit_after>/*
 * Copyright (C) 2017 Rene Herthel
 *
 * This file is subject to the terms and conditions of the MIT License.
 * See the file LICENSE in the top level directory for more details.
 */

/**
 * @ingroup    error_handler
 * @{
 *
 * @brief      Function declaration of the ErrorHandler.
 *
 * @author     Rene Herthel <rene.herthel@haw-hamburg.de>
 */

#include "ErrorHandler.h"

#include "DistanceObservable.h"
#include "DistanceEnum.h"
#include "Signals.h"
#include "CodeDefinition.h"
#include "SerialProtocoll.h"
#include "Signals.h"

#include <iostream>
using namespace std;
using namespace HAL;

ErrorHandler::ErrorHandler( int chid,
                            ConveyorBeltService *conveyorBeltService,
                            LightSystemService *lightSystemService,
                            SerialService *serialService,
                            PuckManager *puckManager)
    :    m_hasError(false)
    ,    m_resetPressed(false)
    ,    m_conveyorBeltService(conveyorBeltService)
    ,    m_lightSystemService(lightSystemService)
	, 	 m_serialService(serialService)
	, 	 m_puckManager(puckManager)
{
    m_lightSystemService->setWarningLevel(Level::OPERATING);
}

ErrorHandler::~ErrorHandler()
{
    // Nothing todo so far.
}

void ErrorHandler::process(PuckManager::ManagerReturn &manager)
{
	LOG_DEBUG << "[ErrorHandler] Demux Manager return \n";
	LOG_DEBUG << "[ErrorHandler] Actor Flag " << manager.actorFlag << " actorSignal " << (int)manager.actorSignal << "\n";

	//if slide full return a warning
	if (manager.actorFlag && manager.actorSignal == PuckManager::ActorSignal::SEND_SLIDE_FULL){
		 m_lightSystemService->setWarningLevel(Level::WARNING_OCCURED);
		 LOG_DEBUG << "[ErrorHandler] Slide is full \n";
	}
	if (manager.actorFlag && manager.actorSignal == PuckManager::ActorSignal::SEND_SLIDE_EMPTY){
		 m_lightSystemService->setWarningLevel(Level::CLEAR_WARNING);
		 m_lightSystemService->setWarningLevel(Level::OPERATING);
		 LOG_DEBUG << "[ErrorHandler] Slide is empty \n";
	}

	//Only handle when error code
    if (manager.errorFlag) {
		m_hasError = true;

		m_lightSystemService->setWarningLevel(Level::ERROR_OCCURED);

		DistanceObservable &distO = DistanceObservable::getInstance();
		distO.updateSpeed(DistanceSpeed::STOP);

		m_conveyorBeltService->changeState(ConveyorBeltState::STOP);
		m_serialService->sendMsg(Serial_n::ser_proto_msg::STOP_SER);

		switch (manager.errorSignal) {

			case PuckManager::ErrorSignal::PUCK_LOST:
				cout << "[ErrorHandler] PUCK_LOST - Late Timer" << endl;
				LOG_DEBUG << "[ErrorHandler] PUCK_LOST - Late Timer" << endl;
				break;

			case PuckManager::ErrorSignal::PUCK_MOVED:
				cout << "[ErrorHandler] PUCK_MOVED - Puck triggered light barrier before early timer" << endl;
				LOG_DEBUG << "[ErrorHandler] PUCK_MOVED - Puck triggered light barrier before early timer" << endl;
				break;

			case PuckManager::ErrorSignal::UNEXPECTED_SIGNAL:
				cout << "[ErrorHandler] UNEXPECTED_SIGNAL - Signal could not be processed" << endl;
				LOG_DEBUG << "[ErrorHandler] UNEXPECTED_SIGNAL - Signal could not be processed" << endl;
				break;

			case PuckManager::ErrorSignal::MULTIPLE_ACCEPT:
				cout << "[ErrorHandler] MULTIPLE_ACCEPT - Shouldn't happen - multiple pucks were triggered" << endl;
				LOG_DEBUG << "[ErrorHandler] MULTIPLE_ACCEPT - Shouldn't happen - multiple pucks were triggered" << endl;
				break;

			case PuckManager::ErrorSignal::MULTIPLE_WARNING:
				cout << "[ErrorHandler] MULTIPLE_WARNING" << endl;
				LOG_DEBUG << "[ErrorHandler] MULTIPLE_WARNING" << endl;
				break;

			case PuckManager::ErrorSignal::BOTH_SLIDES_FULL:
				 cout << "[ErrorHandler] BOTH_SLIDES_FULL" << endl;
				 LOG_DEBUG << "[ErrorHandler] BOTH_SLIDES_FULL" << endl;
				 m_puckManager->reset();
				 break;

			default:
				 LOG_DEBUG << "[ErrorHandler] Unkown Error !!!" << endl;
				break;
		}
    }
}

bool ErrorHandler::hasError()
{
	LOG_DEBUG << "[ErrorHandler] Error: " << m_hasError << "\n";
    return m_hasError;
}

void ErrorHandler::handleEvent(rcv::msg_t event)
{
	LOG_DEBUG << "[ErrorHandler] Trying to demux " << event.code << " " << event.value << "\n";
	switch(event.code){
		case CodeDefinition::SER_IN :
			if( event.value == Serial_n::ser_proto_msg::ESTOP_SER ||
				event.value == Serial_n::ser_proto_msg::ERROR_SER ||
				event.value == Serial_n::ser_proto_msg::NO_CON_SER  ){
				LOG_DEBUG << "[ErrorHandler] Got error from serial \n";
				m_lightSystemService->setWarningLevel(Level::ERROR_OCCURED);
				m_conveyorBeltService->changeState(ConveyorBeltState::STOP);
				m_hasError = true;
				m_resetPressed = false;
			}
			break;
		case CodeDefinition::ISR :
			if(event.value == interrupts::BUTTON_ESTOP_IN){
				LOG_DEBUG << "[ErrorHandler] Got Estop from ISR \n";
				m_lightSystemService->setWarningLevel(Level::ERROR_OCCURED);
				m_serialService->sendMsg(Serial_n::ser_proto_msg::ESTOP_SER);
				m_conveyorBeltService->changeState(ConveyorBeltState::STOP);
				m_hasError = true;
				m_resetPressed = false;
			}
			break;
		default :
			//Nothing to do
			break;
	}

	if(m_hasError){
		 	bool buttonReset = false;
		    bool buttonStart = false;

		    if (event.code == 5) { // 5 is hardcoded in the ISR. TODO Serial signal needs to get through when error is acknowledged on other machine
		    	switch(event.value) {

					case interrupts::BUTTON_RESET:
						buttonReset = true;
						break;

					case interrupts::BUTTON_START:
						buttonStart = true;
						break;

					case interrupts::SLIDE_OUT:
						LOG_DEBUG << "[ErrorHandler] Handling SLIDE_OUT error event " << endl;
						PuckSignal::Signal signal;
						signal.signalType = PuckSignal::SignalType::INTERRUPT_SIGNAL;
						signal.interruptSignal = (interrupts::interruptSignals) event.value;
						m_puckManager->process(signal);
						m_serialService->sendMsg(Serial_n::ser_proto_msg::SLIDE_EMTPY_SER); //huge bawrf
						break;
					default:
						// Nothing todo so far.
						break;
				}
		    } else if(event.code == CodeDefinition::Code::SER_IN) {
		    	if(event.value == Serial_n::ser_proto_msg::SLIDE_EMTPY_SER){
		    		PuckSignal::Signal signal;
					signal.signalType = PuckSignal::SignalType::SERIAL_SIGNAL;
					signal.serialSignal = (Serial_n::ser_proto_msg) event.value;
					m_puckManager->process(signal);
		    	}
		    }

		    LOG_DEBUG << "[ErrorHandler] Trying to handle error event " << int(event.value) << endl;

		    if (buttonReset && m_hasError) {
		        m_resetPressed = true;
		        cout << "Error acknowledged" << endl;
		        m_lightSystemService->setWarningLevel(Level::ERROR_ACKNOWLEDGED);
		    } else if (buttonStart && m_resetPressed && m_hasError) { // Only go further when reset was pressed before.
		    	m_puckManager->resetPucks();
				cout << "Clear error" << endl;
				m_lightSystemService->setWarningLevel(Level::OPERATING);
				m_resetPressed = false;
				m_hasError = false;
		    }
	}
}

/** @} */
<|endoftext|>


<commit_before>// MIT License
//
// Copyright(c) 2017 Piotr 'utak3r' Borys
//
// 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.

#include "GLViewWidget.h"
#include <QPainter>
#include <QPaintEngine>
#include <QOpenGLPaintDevice>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QTimer>
#include <QMouseEvent>

GLViewWidget::GLViewWidget(QWidget *aParent, const QColor &aBackground)
	:
	theBackgroundColor(aBackground),
	theShaderVertex(nullptr),
	theShaderFragment(nullptr),
	theShaderFragmentTemplate(""),
	theShaderFragmentFailsafe(""),
	theShaderProgram(nullptr),
	theCanvasBuffer(nullptr),
	theFBO(nullptr),
	theCanvasTexture(nullptr),
	theAnimationTimer(nullptr),
	theGlobalTime(0.f),
	theAspectRatio(16.f/9.f),
	theMousePressPos(0, 0),
	theFPSFrames(0),
	theShowFPS(false),
	theAnimationStep(0.1f),
	theOffscreenRendering(false),
	theOffscreenRenderingWidth(0),
	theOffscreenRenderingHeight(0)
	{
	setParent(aParent);
	setMinimumSize(352, 198);
	theAnimationTimer = new QTimer(this);
	theAnimationTimer->setInterval(1000 / 50);
	connect(theAnimationTimer, SIGNAL(timeout()), this, SLOT(timerUpdate()));
	}

GLViewWidget::~GLViewWidget()
	{
	}

void GLViewWidget::setAspectRatio(const double anAspectRatio)
	{
	if (anAspectRatio > 0)
		{
		theAspectRatio = anAspectRatio;
		resizeGL(size().width(), size().height());
		}
	}

void GLViewWidget::resizeGL(int aWidth, int aHeight)
	{
	if (!theOffscreenRendering)
		{
		int cw = aWidth;
		int ch = aHeight;

		QWidget *container = nullptr;
		if (parent() != nullptr)
			{
			container = qobject_cast<QWidget *>(parent());
			cw = container->size().width();
			ch = container->size().height();
			}

		int w = cw;
		int h = int(cw / theAspectRatio);
		double s = qMin(cw / double(w), ch / double(h));

		if (container != nullptr)
			{
			setGeometry((cw - int(w*s)) / 2, (ch - int(h*s)) / 2, int(w*s), int(h*s));
			}
		else
			resize(int(w*s), int(h*s));
		}
	}

static const GLfloat vertices[4 * 2] =
	{
	-1.f, -1.f,
	1.f, -1.f,
	-1.f, 1.f,
	1.f, 1.f
	};

void GLViewWidget::initializeGL()
	{
	initializeOpenGLFunctions();

	theShaderVertex = new QOpenGLShader(QOpenGLShader::Vertex);
	theShaderVertex->compileSourceCode(QLatin1Literal("#version 130\n" \
														"attribute vec3 position;\n" \
														"void main()\n" \
														"{\n" \
														"gl_Position = vec4(position, 1.0);\n" \
														"}\n")
										);

	theShaderFragmentTemplate = QLatin1Literal("#version 130\n" \
												"uniform vec3 iResolution;				// viewport resolution (in pixels)\n" \
												"uniform float iGlobalTime;				// shader playback time (in seconds)\n" \
												"uniform vec4 iMouse;					// mouse pixel coords\n" \
												"uniform vec4 iDate;					// (year, month, day, time in seconds)\n" \
												"uniform float iSampleRate;				// sound sample rate (i.e., 44100)\n" \
												"uniform sampler2D iChannel0;			// input channel. XX = 2D/Cube\n" \
												"uniform sampler2D iChannel1;			// input channel. XX = 2D/Cube\n" \
												"uniform sampler2D iChannel2;			// input channel. XX = 2D/Cube\n" \
												"uniform sampler2D iChannel3;			// input channel. XX = 2D/Cube\n" \
												"uniform vec3 iChannelResolution[4];	// channel resolution (in pixels)\n" \
												"uniform float iChannelTime[4];			// channel playback time (in sec)\n" \
												"uniform vec2 iOffset;					// pixel offset for tiled rendering\n" \
												"\n" \
												"%1" \
												"\n" \
												"void main()\n" \
												"{\n" \
											    "mainImage(gl_FragColor, gl_FragCoord.xy);\n" \
												"}\n");

	theShaderFragmentFailsafe = QLatin1Literal("void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" \
												"{\n" \
												"vec2 uv = fragCoord.xy / iResolution.xy;\n" \
												"fragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);\n" \
												"}\n"
												);

	theShaderFragment = new QOpenGLShader(QOpenGLShader::Fragment);
	theShaderFragment->compileSourceCode(QString(theShaderFragmentTemplate).arg(theShaderFragmentFailsafe));

	theShaderProgram = new QOpenGLShaderProgram();
	theShaderProgram->addShader(theShaderVertex);
	theShaderProgram->addShader(theShaderFragment);
	theShaderProgram->link();

	int positionLocation = theShaderProgram->attributeLocation("position");
	theShaderProgram->enableAttributeArray(positionLocation);
	theShaderProgram->setAttributeArray(positionLocation, vertices, 2, 0);

	theShaderProgram->setUniformValue("iResolution", QVector3D(size().width(), size().height(), 0));
	theShaderProgram->setUniformValue("iMouse", QVector4D(0.0, 0.0, 0.0, 0.0));
	theShaderProgram->setUniformValue("iSampleRate", GLfloat(44100.0));
	for (int i = 0; i < 4; i++)
		{
		theShaderProgram->setUniformValue(QStringLiteral("iChannelTime[%1]").arg(i).toLatin1().constData(), GLfloat(0.0));
		theShaderProgram->setUniformValue(QStringLiteral("iChannel%1").arg(i).toLatin1().constData(), GLint(0));
		}
	theShaderProgram->setUniformValue("iGlobalTime", GLfloat(1.0));
	theShaderProgram->setUniformValue("iOffset", QVector2D(0.0, 0.0));

	//theCanvasTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
	//theCanvasTexture = new QOpenGLTexture(QImage(800, 450, QImage::Format_ARGB32));
	theCanvasTexture = new QOpenGLTexture(QImage(QLatin1Literal("metal-scratched-brushed-512.jpg")).mirrored());
	theCanvasTexture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
	theCanvasTexture->setMagnificationFilter(QOpenGLTexture::Linear);
	theCanvasTexture->setWrapMode(QOpenGLTexture::Repeat);

	/*theCanvasBuffer = new QOpenGLBuffer();
	theCanvasBuffer->create();
	theCanvasBuffer->bind();
	//...
	theCanvasBuffer->release();*/

	theAnimationTimer->start();
	}

void GLViewWidget::paintGL()
	{
	int renderWidth = theOffscreenRendering ? theOffscreenRenderingWidth : width();
	int renderHeight = theOffscreenRendering ? theOffscreenRenderingHeight : height();

	QOpenGLPaintDevice fboPaintDev(renderWidth, renderHeight);
	QPainter painter(&fboPaintDev);
	//painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
	//painter.begin(this);

	painter.beginNativePainting();

	glClearColor(theBackgroundColor.redF(), theBackgroundColor.greenF(), theBackgroundColor.blueF(), 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glFrontFace(GL_CW);
	glCullFace(GL_FRONT);
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);

	// paint the canvas
	theShaderProgram->bind();
	//theCanvasTexture->bind();
	int positionLocation = theShaderProgram->attributeLocation("position");
	glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices);
	glEnableVertexAttribArray(0);

	theShaderProgram->setUniformValue("iResolution", QVector3D(renderWidth, renderHeight, 0));
	theShaderProgram->setUniformValue("iGlobalTime", GLfloat(theGlobalTime));

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	glDisableVertexAttribArray(0);

	theShaderProgram->release();

	glDisable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);

	painter.endNativePainting();

	if (theShowFPS)
		{
		if (const int elapsed = theFPSTime.elapsed())
			{
			QString framesPerSecond;
			framesPerSecond.setNum(theFPSFrames / (elapsed / 1000.0), 'f', 2);
			painter.setPen(Qt::black);
			painter.setFont(QFont(QLatin1Literal("Arial"), 18));
			painter.drawText(20, 40, framesPerSecond + QLatin1Literal(" FPS"));
			}
		}

	painter.end();

	if (theShowFPS)
		{
		if (!(theFPSFrames % 100))
			{
			theFPSTime.start();
			theFPSFrames = 0;
			}
		++theFPSFrames;
		}

	update();
	}

QImage GLViewWidget::renderOffscreen(int aWidth, int aHeight)
	{
	makeCurrent();
	theOffscreenRendering = true;
	if (!theFBO || theFBO->width() != aWidth || theFBO->height() != aHeight)
		{
		if (theFBO)
			delete theFBO;
		QOpenGLFramebufferObjectFormat format;
		format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
		theFBO = new QOpenGLFramebufferObject(aWidth, aHeight, format);
		resizeGL(aWidth, aHeight);
		}
	theFBO->bind();
	theOffscreenRenderingWidth = aWidth;
	theOffscreenRenderingHeight = aHeight;
	paintGL();
	QImage img = theFBO->toImage();
	theFBO->release();
	theOffscreenRendering = false;
	doneCurrent();
	return img;
	}

QImage GLViewWidget::renderOffscreen(const QSize& aSize)
	{
	return renderOffscreen(aSize.width(), aSize.height());
	}

void GLViewWidget::setFragmentShaderSource(const QString& aFragmentShaderSource)
	{
	theAnimationTimer->stop();
	theShaderFragment->compileSourceCode(QString(theShaderFragmentTemplate).arg(aFragmentShaderSource));

	theShaderProgram->removeAllShaders();
	theShaderProgram->addShader(theShaderVertex);
	theShaderProgram->addShader(theShaderFragment);
	theShaderProgram->link();

	int positionLocation = theShaderProgram->attributeLocation("position");
	theShaderProgram->enableAttributeArray(positionLocation);
	theShaderProgram->setAttributeArray(positionLocation, vertices, 2, 0);
	theShaderProgram->setAttributeValue("iMouse", QVector4D(0.0, 0.0, 0.0, 0.0));
	theShaderProgram->setAttributeValue("iSampleRate", 44100.0);
	for (int i = 0; i < 4; i++)
		theShaderProgram->setAttributeValue(QStringLiteral("iChannelTime[%1]").arg(i).toLatin1().constData(), 0.0);
	theShaderProgram->setAttributeValue("iGlobalTime", 0.0);
	theShaderProgram->setAttributeValue("iOffset", QVector2D(0.0, 0.0));
	theAnimationTimer->start();
	}

void GLViewWidget::setFragmentShaderFile(const QString& aFragmentShaderFilename)
	{
	//
	}

void GLViewWidget::timerUpdate()
	{
	theGlobalTime += theAnimationStep;
	}

bool GLViewWidget::isPlaying()
	{
	return (theAnimationStep != 0);
	}

void GLViewWidget::play()
	{
	theAnimationStep = 0.1f;
	}

void GLViewWidget::pause()
	{
	theAnimationStep = 0.f;
	}

void GLViewWidget::rewind()
	{
	theGlobalTime = 0.f;
	}

void GLViewWidget::jogAnimation(double aStep)
	{
	theGlobalTime += aStep;
	}

void GLViewWidget::mousePressEvent(QMouseEvent *event)
	{
	QPoint pos = event->pos();
	theShaderProgram->bind();
	theShaderProgram->setUniformValue("iMouse", QVector4D(pos.x(), size().height()-pos.y(), 0.0, 0.0));
	theShaderProgram->release();
	theMousePressPos = pos;
	}

void GLViewWidget::mouseMoveEvent(QMouseEvent *event)
	{
	QPoint pos = event->pos();
	if (event->buttons() & Qt::LeftButton)
		{
		theShaderProgram->bind();
		theShaderProgram->setUniformValue("iMouse",
										  QVector4D(pos.x(), size().height() - pos.y(),
													 theMousePressPos.x(), size().height() - theMousePressPos.y()
													));
		theShaderProgram->release();
		}
	}
<commit_msg>Lowered the Shader Language version down to 1.2.<commit_after>// MIT License
//
// Copyright(c) 2017 Piotr 'utak3r' Borys
//
// 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.

#include "GLViewWidget.h"
#include <QPainter>
#include <QPaintEngine>
#include <QOpenGLPaintDevice>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QTimer>
#include <QMouseEvent>

GLViewWidget::GLViewWidget(QWidget *aParent, const QColor &aBackground)
	:
	theBackgroundColor(aBackground),
	theShaderVertex(nullptr),
	theShaderFragment(nullptr),
	theShaderFragmentTemplate(""),
	theShaderFragmentFailsafe(""),
	theShaderProgram(nullptr),
	theCanvasBuffer(nullptr),
	theFBO(nullptr),
	theCanvasTexture(nullptr),
	theAnimationTimer(nullptr),
	theGlobalTime(0.f),
	theAspectRatio(16.f/9.f),
	theMousePressPos(0, 0),
	theFPSFrames(0),
	theShowFPS(false),
	theAnimationStep(0.1f),
	theOffscreenRendering(false),
	theOffscreenRenderingWidth(0),
	theOffscreenRenderingHeight(0)
	{
	setParent(aParent);
	setMinimumSize(352, 198);
	theAnimationTimer = new QTimer(this);
	theAnimationTimer->setInterval(1000 / 50);
	connect(theAnimationTimer, SIGNAL(timeout()), this, SLOT(timerUpdate()));
	}

GLViewWidget::~GLViewWidget()
	{
	}

void GLViewWidget::setAspectRatio(const double anAspectRatio)
	{
	if (anAspectRatio > 0)
		{
		theAspectRatio = anAspectRatio;
		resizeGL(size().width(), size().height());
		}
	}

void GLViewWidget::resizeGL(int aWidth, int aHeight)
	{
	if (!theOffscreenRendering)
		{
		int cw = aWidth;
		int ch = aHeight;

		QWidget *container = nullptr;
		if (parent() != nullptr)
			{
			container = qobject_cast<QWidget *>(parent());
			cw = container->size().width();
			ch = container->size().height();
			}

		int w = cw;
		int h = int(cw / theAspectRatio);
		double s = qMin(cw / double(w), ch / double(h));

		if (container != nullptr)
			{
			setGeometry((cw - int(w*s)) / 2, (ch - int(h*s)) / 2, int(w*s), int(h*s));
			}
		else
			resize(int(w*s), int(h*s));
		}
	}

static const GLfloat vertices[4 * 2] =
	{
	-1.f, -1.f,
	1.f, -1.f,
	-1.f, 1.f,
	1.f, 1.f
	};

void GLViewWidget::initializeGL()
	{
	initializeOpenGLFunctions();

	theShaderVertex = new QOpenGLShader(QOpenGLShader::Vertex);
	theShaderVertex->compileSourceCode(QLatin1Literal("#version 120\n" \
														"attribute vec3 position;\n" \
														"void main()\n" \
														"{\n" \
														"gl_Position = vec4(position, 1.0);\n" \
														"}\n")
										);

	theShaderFragmentTemplate = QLatin1Literal("#version 120\n" \
												"uniform vec3 iResolution;				// viewport resolution (in pixels)\n" \
												"uniform float iGlobalTime;				// shader playback time (in seconds)\n" \
												"uniform vec4 iMouse;					// mouse pixel coords\n" \
												"uniform vec4 iDate;					// (year, month, day, time in seconds)\n" \
												"uniform float iSampleRate;				// sound sample rate (i.e., 44100)\n" \
												"uniform sampler2D iChannel0;			// input channel. XX = 2D/Cube\n" \
												"uniform sampler2D iChannel1;			// input channel. XX = 2D/Cube\n" \
												"uniform sampler2D iChannel2;			// input channel. XX = 2D/Cube\n" \
												"uniform sampler2D iChannel3;			// input channel. XX = 2D/Cube\n" \
												"uniform vec3 iChannelResolution[4];	// channel resolution (in pixels)\n" \
												"uniform float iChannelTime[4];			// channel playback time (in sec)\n" \
												"uniform vec2 iOffset;					// pixel offset for tiled rendering\n" \
												"\n" \
												"%1" \
												"\n" \
												"void main()\n" \
												"{\n" \
											    "mainImage(gl_FragColor, gl_FragCoord.xy);\n" \
												"}\n");

	theShaderFragmentFailsafe = QLatin1Literal("void mainImage( out vec4 fragColor, in vec2 fragCoord )\n" \
												"{\n" \
												"vec2 uv = fragCoord.xy / iResolution.xy;\n" \
												"fragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);\n" \
												"}\n"
												);

	theShaderFragment = new QOpenGLShader(QOpenGLShader::Fragment);
	theShaderFragment->compileSourceCode(QString(theShaderFragmentTemplate).arg(theShaderFragmentFailsafe));

	theShaderProgram = new QOpenGLShaderProgram();
	theShaderProgram->addShader(theShaderVertex);
	theShaderProgram->addShader(theShaderFragment);
	theShaderProgram->link();

	int positionLocation = theShaderProgram->attributeLocation("position");
	theShaderProgram->enableAttributeArray(positionLocation);
	theShaderProgram->setAttributeArray(positionLocation, vertices, 2, 0);

	theShaderProgram->setUniformValue("iResolution", QVector3D(size().width(), size().height(), 0));
	theShaderProgram->setUniformValue("iMouse", QVector4D(0.0, 0.0, 0.0, 0.0));
	theShaderProgram->setUniformValue("iSampleRate", GLfloat(44100.0));
	for (int i = 0; i < 4; i++)
		{
		theShaderProgram->setUniformValue(QStringLiteral("iChannelTime[%1]").arg(i).toLatin1().constData(), GLfloat(0.0));
		theShaderProgram->setUniformValue(QStringLiteral("iChannel%1").arg(i).toLatin1().constData(), GLint(0));
		}
	theShaderProgram->setUniformValue("iGlobalTime", GLfloat(1.0));
	theShaderProgram->setUniformValue("iOffset", QVector2D(0.0, 0.0));

	//theCanvasTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
	//theCanvasTexture = new QOpenGLTexture(QImage(800, 450, QImage::Format_ARGB32));
	theCanvasTexture = new QOpenGLTexture(QImage(QLatin1Literal("metal-scratched-brushed-512.jpg")).mirrored());
	theCanvasTexture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
	theCanvasTexture->setMagnificationFilter(QOpenGLTexture::Linear);
	theCanvasTexture->setWrapMode(QOpenGLTexture::Repeat);

	/*theCanvasBuffer = new QOpenGLBuffer();
	theCanvasBuffer->create();
	theCanvasBuffer->bind();
	//...
	theCanvasBuffer->release();*/

	theAnimationTimer->start();
	}

void GLViewWidget::paintGL()
	{
	int renderWidth = theOffscreenRendering ? theOffscreenRenderingWidth : width();
	int renderHeight = theOffscreenRendering ? theOffscreenRenderingHeight : height();

	QOpenGLPaintDevice fboPaintDev(renderWidth, renderHeight);
	QPainter painter(&fboPaintDev);
	//painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
	//painter.begin(this);

	painter.beginNativePainting();

	glClearColor(theBackgroundColor.redF(), theBackgroundColor.greenF(), theBackgroundColor.blueF(), 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glFrontFace(GL_CW);
	glCullFace(GL_FRONT);
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);

	// paint the canvas
	theShaderProgram->bind();
	//theCanvasTexture->bind();
	int positionLocation = theShaderProgram->attributeLocation("position");
	glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices);
	glEnableVertexAttribArray(0);

	theShaderProgram->setUniformValue("iResolution", QVector3D(renderWidth, renderHeight, 0));
	theShaderProgram->setUniformValue("iGlobalTime", GLfloat(theGlobalTime));

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	glDisableVertexAttribArray(0);

	theShaderProgram->release();

	glDisable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);

	painter.endNativePainting();

	if (theShowFPS)
		{
		if (const int elapsed = theFPSTime.elapsed())
			{
			QString framesPerSecond;
			framesPerSecond.setNum(theFPSFrames / (elapsed / 1000.0), 'f', 2);
			painter.setPen(Qt::black);
			painter.setFont(QFont(QLatin1Literal("Arial"), 18));
			painter.drawText(20, 40, framesPerSecond + QLatin1Literal(" FPS"));
			}
		}

	painter.end();

	if (theShowFPS)
		{
		if (!(theFPSFrames % 100))
			{
			theFPSTime.start();
			theFPSFrames = 0;
			}
		++theFPSFrames;
		}

	update();
	}

QImage GLViewWidget::renderOffscreen(int aWidth, int aHeight)
	{
	makeCurrent();
	theOffscreenRendering = true;
	if (!theFBO || theFBO->width() != aWidth || theFBO->height() != aHeight)
		{
		if (theFBO)
			delete theFBO;
		QOpenGLFramebufferObjectFormat format;
		format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
		theFBO = new QOpenGLFramebufferObject(aWidth, aHeight, format);
		resizeGL(aWidth, aHeight);
		}
	theFBO->bind();
	theOffscreenRenderingWidth = aWidth;
	theOffscreenRenderingHeight = aHeight;
	paintGL();
	QImage img = theFBO->toImage();
	theFBO->release();
	theOffscreenRendering = false;
	doneCurrent();
	return img;
	}

QImage GLViewWidget::renderOffscreen(const QSize& aSize)
	{
	return renderOffscreen(aSize.width(), aSize.height());
	}

void GLViewWidget::setFragmentShaderSource(const QString& aFragmentShaderSource)
	{
	theAnimationTimer->stop();
	theShaderFragment->compileSourceCode(QString(theShaderFragmentTemplate).arg(aFragmentShaderSource));

	theShaderProgram->removeAllShaders();
	theShaderProgram->addShader(theShaderVertex);
	theShaderProgram->addShader(theShaderFragment);
	theShaderProgram->link();

	int positionLocation = theShaderProgram->attributeLocation("position");
	theShaderProgram->enableAttributeArray(positionLocation);
	theShaderProgram->setAttributeArray(positionLocation, vertices, 2, 0);
	theShaderProgram->setAttributeValue("iMouse", QVector4D(0.0, 0.0, 0.0, 0.0));
	theShaderProgram->setAttributeValue("iSampleRate", 44100.0);
	for (int i = 0; i < 4; i++)
		theShaderProgram->setAttributeValue(QStringLiteral("iChannelTime[%1]").arg(i).toLatin1().constData(), 0.0);
	theShaderProgram->setAttributeValue("iGlobalTime", 0.0);
	theShaderProgram->setAttributeValue("iOffset", QVector2D(0.0, 0.0));
	theAnimationTimer->start();
	}

void GLViewWidget::setFragmentShaderFile(const QString& aFragmentShaderFilename)
	{
	//
	}

void GLViewWidget::timerUpdate()
	{
	theGlobalTime += theAnimationStep;
	}

bool GLViewWidget::isPlaying()
	{
	return (theAnimationStep != 0);
	}

void GLViewWidget::play()
	{
	theAnimationStep = 0.1f;
	}

void GLViewWidget::pause()
	{
	theAnimationStep = 0.f;
	}

void GLViewWidget::rewind()
	{
	theGlobalTime = 0.f;
	}

void GLViewWidget::jogAnimation(double aStep)
	{
	theGlobalTime += aStep;
	}

void GLViewWidget::mousePressEvent(QMouseEvent *event)
	{
	QPoint pos = event->pos();
	theShaderProgram->bind();
	theShaderProgram->setUniformValue("iMouse", QVector4D(pos.x(), size().height()-pos.y(), 0.0, 0.0));
	theShaderProgram->release();
	theMousePressPos = pos;
	}

void GLViewWidget::mouseMoveEvent(QMouseEvent *event)
	{
	QPoint pos = event->pos();
	if (event->buttons() & Qt::LeftButton)
		{
		theShaderProgram->bind();
		theShaderProgram->setUniformValue("iMouse",
										  QVector4D(pos.x(), size().height() - pos.y(),
													 theMousePressPos.x(), size().height() - theMousePressPos.y()
													));
		theShaderProgram->release();
		}
	}
<|endoftext|>