<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Mark Guerra
 *
 * 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 <sstream>
#include <stack>
#include <iostream>

#include "bignumber.h"

BigNumber::BigNumber(std::string number) :
    _numberString(number)
{
}

BigNumber BigNumber::add(BigNumber other) {
    if (this->isNegative() || other.isNegative()) {
        if (this->isNegative() && other.isNegative()) {
            return this->negate().add(other.negate()).negate();
        }
        else if (this->isNegative() && !other.isNegative()) {
            return this->negate().subtract(other).negate();
        }
        else {
            return other.negate().subtract(*this).negate();
        }
    }
    std::string results;
    int carry = 0;
    BigNumber num1 = other > *this ? other : *this;
    BigNumber num2 = other > *this ? *this : other;
    int diff = int(num1._numberString.size() - num2._numberString.size());
    for (int i = 0; i < diff; i++) {
        num2._numberString.insert(num2._numberString.begin(), '0');
    }
    for (int i = int(num1._numberString.size() - 1); i >= 0; i--) {
        int sum = (num1._numberString[i] - '0') + (num2._numberString[i] - '0') + carry;
        carry = 0;
        if (sum <= 9 || i == 0) {
            results.insert(0, std::to_string(sum));
        }
        else {
            results.insert(0, std::to_string(sum % 10));
            carry = 1;
        }
    }
    return BigNumber(results);
}

BigNumber BigNumber::subtract(BigNumber other) {
    if (this->isNegative() || other.isNegative()) {
        if (this->isNegative() && other.isNegative()) {
            return this->negate().add(other.negate()).negate();
        }
        else if (this->isNegative() && !other.isNegative()) {
            return this->negate().add(other).negate();
        }
        else {
            return other.negate().add(*this);
        }
    }
    std::string results;
    int n = 0, p = 0;
    bool takeOffOne = false;
    bool shouldBeTen = false;

    if (*this < other) {
        //Negative answer
        std::string t = other.subtract(*this).negate().getString();
        for (unsigned int i = 1; i < t.length(); ++i) {
            if (t[i] != '0') break;
            t.erase(1, 1);
        }
        return BigNumber(t);
    }

    int i = int(this->_numberString.size() - 1);
    for (int j = int(other._numberString.size() - 1); j >= 0; j--) {
        if (((this->_numberString[i] - '0') < (other._numberString[j] - '0')) && i > 0) {
            n = char((this->_numberString[i] - '0') + 10);
            takeOffOne = true;
            if (j > 0 || this->_numberString[i - 1] != '0') {
                p = char((this->_numberString[i - 1] - '0') - 1);
                if (p == -1) {
                    p = 9;
                    shouldBeTen = true;
                }
                takeOffOne = false;
            }
            if (shouldBeTen) {
                int index = i - 1;
                for (int a = i - 1; (this->_numberString[a] - '0') == 0; a--) {
                    this->_numberString[a] = (p + '0');
                    index--;
                }
                int t = (this->_numberString[index] - '0') - 1;
                this->_numberString[index] = (t + '0');
            }
            this->_numberString[i - 1] = (p + '0');
            shouldBeTen = false;
        }
        std::stringstream ss;
        if (((this->_numberString[i] - '0') == (other._numberString[j] - '0'))) {
            ss << "0";
        }
        else {
            if (n <= 0) {
                ss << ((this->_numberString[i] - '0') - (other._numberString[j] - '0'));
            }
            else {
                ss << (n - (other._numberString[j] - '0'));
            }
        }

        results.insert(0, ss.str());
        i--;
        n = 0;
    }
    if (takeOffOne) {
        std::string number = "";
        for (int i = this->_numberString.length() - other._numberString.length() - 1; i >= 0; i--) {
            if (this->_numberString[i] == '0') {
                number += "0";
                continue;
            }
            else {
                number.insert(number.begin(), this->_numberString[i]);
                int n = atoi(number.c_str());
                n--;
                this->_numberString.replace(0, number.size(), std::to_string(n));
                break;
            }
        }
    }
    while (i >= 0) {
        std::stringstream ss;
        if (i == 0) {
            if (this->_numberString[i] - '0' != 0) {
                ss << (this->_numberString[i] - '0');
                results.insert(0, ss.str());
            }
        }
        else {
            ss << (this->_numberString[i] - '0');
            results.insert(0, ss.str());
        }

        i--;
    }
    //In the case of all 0's, we only want to return one of them
    if (results.find_first_not_of('0') == std::string::npos) {
        results = "0";
    }

    return BigNumber(results);
}

BigNumber BigNumber::multiply(BigNumber other) {
    if (this->isNegative() || other.isNegative()) {
        if (this->_numberString[0] == '-' && other._numberString[0] == '-') {
            this->negate();
            other.negate();
            return this->multiply(other);
        }
        else if (this->isNegative() && !other.isNegative()) {
            this->negate();
            BigNumber res = this->multiply(other);
            res.negate();
            return res;
        }
        else {
            other.negate();
            BigNumber res = other.multiply(*this);
            res.negate();
            return res;
        }
    }
    int carry = 0;
    int zeroCounter = 0;
    std::vector<std::string> results;
    BigNumber num1 = other > *this ? other : *this;
    BigNumber num2 = other > *this ? *this : other;
    for (unsigned int i = 0; i < num1._numberString.size() - num2._numberString.size(); i++) {
        num2._numberString.insert(num2._numberString.begin(), '0');
    }
    for (int i = (num2._numberString.size() - 1); i >= 0; i--) {
        std::string rr;
        for (int j = int(num1._numberString.size() - 1); j >= 0; j--) {
            int val = ((num2._numberString[i] - '0') * (num1._numberString[j] - '0')) + carry;
            carry = 0;
            if (val > 9 && j != 0) {
                int dig = val % 10;
                carry = val / 10;
                rr.insert(0, std::to_string(dig));
            }
            else {
                rr.insert(0, std::to_string(val));
            }
        }
        if (zeroCounter > 0) {
            for (int x = 0; x < zeroCounter; x++) {
                rr.append("0");
            }
        }
        zeroCounter++;
        results.push_back(rr);
    }
    std::vector<BigNumber> bigNumbers;
    for (unsigned int i = 0; i < results.size(); i++) {
        bigNumbers.push_back(BigNumber(results[i]));
    }
    BigNumber b("0");
    for (unsigned int i = 0; i < bigNumbers.size(); i++) {
        b = b.add(bigNumbers[i]);
    }
    if (b._numberString.find_first_not_of('0') != std::string::npos) {
        b = BigNumber(b._numberString.erase(0, b._numberString.find_first_not_of('0')));
    }
    else {
        //In the case of all 0's, we only want to return one of them
        b = BigNumber("0");
    }
    return b;

}

BigNumber BigNumber::pow(int exponent) {
    if (exponent < 0) {
        std::cerr << "Powers less than 0 are not supported" << std::endl;
    }
    BigNumber result("1");
    while (exponent > 0) {
        if (exponent & 1) {
            result = result.multiply(*this);
        }
        *this = this->multiply(*this);
        exponent /= 2;
    }
    return result;
}

std::string BigNumber::getString() {
    return this->_numberString;
}

void BigNumber::setString(const std::string &newStr) {
    this->_numberString = newStr;
}

BigNumber BigNumber::negate() {
    if (this->_numberString[0] == '-') {
        this->_numberString.erase(0, 1);
    }
    else {
        this->_numberString.insert(this->_numberString.begin(), '-');
    }
    return *this;
}

bool BigNumber::equals(const BigNumber &other) {
    return this->_numberString == other._numberString;
}

int BigNumber::digits() {
    return this->_numberString.size() - this->isNegative() ? 1 : 0;
}

bool BigNumber::isNegative() const {
    return this->_numberString[0] == '-';
}

bool BigNumber::isPositive() {
    return !this->isNegative();
}

bool BigNumber::isEven() {
    return this->_numberString[this->_numberString.length() - 1] % 2 == 0;
}

bool BigNumber::isOdd() {
    return !this->isEven();
}

std::ostream &operator<<(std::ostream &os, const BigNumber &num) {
    os << num._numberString;
    return os;
}

BigNumber operator+(BigNumber b1, const BigNumber &b2) {
    return b1.add(b2);
}

BigNumber operator-(BigNumber b1, const BigNumber &b2) {
    return b1.subtract(b2);
}

BigNumber operator*(BigNumber b1, const BigNumber &b2) {
    return b1.multiply(b2);
}

BigNumber operator^(BigNumber b1, const int &b2) {
    return b1.pow(b2);
}

bool operator==(BigNumber b1, const BigNumber &b2) {
    return b1.equals(b2);
}

bool operator>(BigNumber b1, const BigNumber &b2) {
    if (b1.isNegative() || b2.isNegative()) {
        if (b1.isNegative() && b2.isNegative()) {
            BigNumber bt = b2;
            b1._numberString.erase(0, 1);
            bt._numberString.erase(0, 1);
            return b1 < bt;
        }
        else {
            return !(b1.isNegative() && !b2.isNegative());
        }
    }
    if (b1 == b2) {
        return false;
    }
    if (b1._numberString.size() > b2._numberString.size()) {
        return true;
    }
    else if (b2._numberString.size() > b1._numberString.size()) {
        return false;
    }
    else {
        for (unsigned int i = 0; i < b1._numberString.size(); i++) {
            if (b1[i] == (b2._numberString[i] - '0')) {
                continue;
            }
            return b1[i] > (b2._numberString[i] - '0');
        }
    }
    return false;
}

bool operator<(BigNumber b1, const BigNumber &b2) {
    return !(b1 == b2) && !(b1 > b2);
}

bool operator>=(BigNumber b1, const BigNumber &b2) {
    return b1 > b2 || b1 == b2;
}

bool operator<=(BigNumber b1, const BigNumber &b2) {
    return b1 < b2 || b1 == b2;
}

int BigNumber::operator[](int index) {
    if (this->_numberString[index] == '-') {
        std::cerr << "You cannot get the negative sign from the number" << std::endl;
    }
    return this->_numberString[index] - '0';
}

BigNumber& BigNumber::operator=(const BigNumber &other) {
    this->_numberString = other._numberString;
    return *this;
}

BigNumber& BigNumber::operator+=(const BigNumber &other) {
    *this = *this + other;
    return *this;
}

BigNumber& BigNumber::operator-=(const BigNumber &other) {
    *this = *this - other;
    return *this;
}

BigNumber& BigNumber::operator*=(const BigNumber &other) {
    *this = *this * other;
    return *this;
}

<commit_msg>refactoring code<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Mark Guerra
 *
 * 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 <sstream>
#include <stack>
#include <iostream>

#include "bignumber.h"

BigNumber::BigNumber(std::string number) :
    _numberString(number)
{
}

BigNumber BigNumber::add(BigNumber other) {
    if (this->isNegative() || other.isNegative()) {
        if (this->isNegative() && other.isNegative()) {
            return this->negate().add(other.negate()).negate();
        }
        else if (this->isNegative() && !other.isNegative()) {
            return this->negate().subtract(other).negate();
        }
        else {
            return other.negate().subtract(*this).negate();
        }
    }
    std::string results;
    int carry = 0;
    BigNumber num1 = other > *this ? other : *this;
    BigNumber num2 = other > *this ? *this : other;
    int diff = int(num1._numberString.size() - num2._numberString.size());
    for (int i = 0; i < diff; i++) {
        num2._numberString.insert(num2._numberString.begin(), '0');
    }
    for (int i = int(num1._numberString.size() - 1); i >= 0; i--) {
        int sum = (num1._numberString[i] - '0') + (num2._numberString[i] - '0') + carry;
        carry = 0;
        if (sum <= 9 || i == 0) {
            results.insert(0, std::to_string(sum));
        }
        else {
            results.insert(0, std::to_string(sum % 10));
            carry = 1;
        }
    }
    return BigNumber(results);
}

BigNumber BigNumber::subtract(BigNumber other) {
    if (this->isNegative() || other.isNegative()) {
        if (this->isNegative() && other.isNegative()) {
            return this->negate().add(other.negate()).negate();
        }
        else if (this->isNegative() && !other.isNegative()) {
            return this->negate().add(other).negate();
        }
        else {
            return other.negate().add(*this);
        }
    }
    std::string results;
    int n = 0, p = 0;
    bool takeOffOne = false;
    bool shouldBeTen = false;

    if (*this < other) {
        //Negative answer
        std::string t = other.subtract(*this).negate().getString();
        for (unsigned int i = 1; i < t.length(); ++i) {
            if (t[i] != '0') break;
            t.erase(1, 1);
        }
        return BigNumber(t);
    }

    int i = int(this->_numberString.size() - 1);
    for (int j = int(other._numberString.size() - 1); j >= 0; j--) {
        if (((this->_numberString[i] - '0') < (other._numberString[j] - '0')) && i > 0) {
            n = char((this->_numberString[i] - '0') + 10);
            takeOffOne = true;
            if (j > 0 || this->_numberString[i - 1] != '0') {
                p = char((this->_numberString[i - 1] - '0') - 1);
                if (p == -1) {
                    p = 9;
                    shouldBeTen = true;
                }
                takeOffOne = false;
            }
            if (shouldBeTen) {
                int index = i - 1;
                for (int a = i - 1; (this->_numberString[a] - '0') == 0; a--) {
                    this->_numberString[a] = (p + '0');
                    index--;
                }
                int t = (this->_numberString[index] - '0') - 1;
                this->_numberString[index] = (t + '0');
            }
            this->_numberString[i - 1] = (p + '0');
            shouldBeTen = false;
        }
        std::stringstream ss;
        if (((this->_numberString[i] - '0') == (other._numberString[j] - '0'))) {
            ss << "0";
        }
        else {
            if (n <= 0) {
                ss << ((this->_numberString[i] - '0') - (other._numberString[j] - '0'));
            }
            else {
                ss << (n - (other._numberString[j] - '0'));
            }
        }

        results.insert(0, ss.str());
        i--;
        n = 0;
    }
    if (takeOffOne) {
        std::string number = "";
        for (int i = this->_numberString.length() - other._numberString.length() - 1; i >= 0; i--) {
            if (this->_numberString[i] == '0') {
                number += "0";
                continue;
            }
            else {
                number.insert(number.begin(), this->_numberString[i]);
                int n = atoi(number.c_str());
                n--;
                this->_numberString.replace(0, number.size(), std::to_string(n));
                break;
            }
        }
    }
    while (i >= 0) {
        std::stringstream ss;
        if (i == 0) {
            if (this->_numberString[i] - '0' != 0) {
                ss << (this->_numberString[i] - '0');
                results.insert(0, ss.str());
            }
        }
        else {
            ss << (this->_numberString[i] - '0');
            results.insert(0, ss.str());
        }

        i--;
    }
    //In the case of all 0's, we only want to return one of them
    if (results.find_first_not_of('0') == std::string::npos) {
        results = "0";
    }

    return BigNumber(results);
}

BigNumber BigNumber::multiply(BigNumber other) {
    if (this->isNegative() || other.isNegative()) {
        if (this->isNegative() && other.isNegative()) {
            return this->negate().multiply(other.negate());
        }
        else if (this->isNegative() && !other.isNegative()) {
            return this->negate().multiply(other).negate();
        }
        else {
            return other.negate().multiply(*this).negate();
        }
    }
    int carry = 0;
    int zeroCounter = 0;
    std::vector<std::string> results;
    BigNumber num1 = other > *this ? other : *this;
    BigNumber num2 = other > *this ? *this : other;
    for (unsigned int i = 0; i < num1._numberString.size() - num2._numberString.size(); i++) {
        num2._numberString.insert(num2._numberString.begin(), '0');
    }
    for (int i = (num2._numberString.size() - 1); i >= 0; i--) {
        std::string rr;
        for (int j = int(num1._numberString.size() - 1); j >= 0; j--) {
            int val = ((num2._numberString[i] - '0') * (num1._numberString[j] - '0')) + carry;
            carry = 0;
            if (val > 9 && j != 0) {
                int dig = val % 10;
                carry = val / 10;
                rr.insert(0, std::to_string(dig));
            }
            else {
                rr.insert(0, std::to_string(val));
            }
        }
        if (zeroCounter > 0) {
            for (int x = 0; x < zeroCounter; x++) {
                rr.append("0");
            }
        }
        zeroCounter++;
        results.push_back(rr);
    }
    std::vector<BigNumber> bigNumbers;
    for (unsigned int i = 0; i < results.size(); i++) {
        bigNumbers.push_back(BigNumber(results[i]));
    }
    BigNumber b("0");
    for (unsigned int i = 0; i < bigNumbers.size(); i++) {
        b = b.add(bigNumbers[i]);
    }
    if (b._numberString.find_first_not_of('0') != std::string::npos) {
        b = BigNumber(b._numberString.erase(0, b._numberString.find_first_not_of('0')));
    }
    else {
        //In the case of all 0's, we only want to return one of them
        b = BigNumber("0");
    }
    return b;

}

BigNumber BigNumber::pow(int exponent) {
    if (exponent < 0) {
        std::cerr << "Powers less than 0 are not supported" << std::endl;
    }
    BigNumber result("1");
    while (exponent > 0) {
        if (exponent & 1) {
            result = result.multiply(*this);
        }
        *this = this->multiply(*this);
        exponent /= 2;
    }
    return result;
}

std::string BigNumber::getString() {
    return this->_numberString;
}

void BigNumber::setString(const std::string &newStr) {
    this->_numberString = newStr;
}

BigNumber BigNumber::negate() {
    if (this->_numberString[0] == '-') {
        this->_numberString.erase(0, 1);
    }
    else {
        this->_numberString.insert(this->_numberString.begin(), '-');
    }
    return *this;
}

bool BigNumber::equals(const BigNumber &other) {
    return this->_numberString == other._numberString;
}

int BigNumber::digits() {
    return this->_numberString.size() - this->isNegative() ? 1 : 0;
}

bool BigNumber::isNegative() const {
    return this->_numberString[0] == '-';
}

bool BigNumber::isPositive() {
    return !this->isNegative();
}

bool BigNumber::isEven() {
    return this->_numberString[this->_numberString.length() - 1] % 2 == 0;
}

bool BigNumber::isOdd() {
    return !this->isEven();
}

std::ostream &operator<<(std::ostream &os, const BigNumber &num) {
    os << num._numberString;
    return os;
}

BigNumber operator+(BigNumber b1, const BigNumber &b2) {
    return b1.add(b2);
}

BigNumber operator-(BigNumber b1, const BigNumber &b2) {
    return b1.subtract(b2);
}

BigNumber operator*(BigNumber b1, const BigNumber &b2) {
    return b1.multiply(b2);
}

BigNumber operator^(BigNumber b1, const int &b2) {
    return b1.pow(b2);
}

bool operator==(BigNumber b1, const BigNumber &b2) {
    return b1.equals(b2);
}

bool operator>(BigNumber b1, const BigNumber &b2) {
    if (b1.isNegative() || b2.isNegative()) {
        if (b1.isNegative() && b2.isNegative()) {
            BigNumber bt = b2;
            b1._numberString.erase(0, 1);
            bt._numberString.erase(0, 1);
            return b1 < bt;
        }
        else {
            return !(b1.isNegative() && !b2.isNegative());
        }
    }
    if (b1 == b2) {
        return false;
    }
    if (b1._numberString.size() > b2._numberString.size()) {
        return true;
    }
    else if (b2._numberString.size() > b1._numberString.size()) {
        return false;
    }
    else {
        for (unsigned int i = 0; i < b1._numberString.size(); i++) {
            if (b1[i] == (b2._numberString[i] - '0')) {
                continue;
            }
            return b1[i] > (b2._numberString[i] - '0');
        }
    }
    return false;
}

bool operator<(BigNumber b1, const BigNumber &b2) {
    return !(b1 == b2) && !(b1 > b2);
}

bool operator>=(BigNumber b1, const BigNumber &b2) {
    return b1 > b2 || b1 == b2;
}

bool operator<=(BigNumber b1, const BigNumber &b2) {
    return b1 < b2 || b1 == b2;
}

int BigNumber::operator[](int index) {
    if (this->_numberString[index] == '-') {
        std::cerr << "You cannot get the negative sign from the number" << std::endl;
    }
    return this->_numberString[index] - '0';
}

BigNumber& BigNumber::operator=(const BigNumber &other) {
    this->_numberString = other._numberString;
    return *this;
}

BigNumber& BigNumber::operator+=(const BigNumber &other) {
    *this = *this + other;
    return *this;
}

BigNumber& BigNumber::operator-=(const BigNumber &other) {
    *this = *this - other;
    return *this;
}

BigNumber& BigNumber::operator*=(const BigNumber &other) {
    *this = *this * other;
    return *this;
}

<|endoftext|>


<commit_before>/**
 * @brief Analyzer for multi-languages
 * @file MultiLanguageAnalyzer.h
 *
 * @date Jan 4, 2010
 * @author vernkin
 */

/**
 * @brief Rewrite MLA using a fast language detction,
 *     String mode is moved to EnglishAnalyzer,
 *      Char mode is moved to CharAnalyzer.
 * @author Wei
 */

#include "la/analyzer/MultiLanguageAnalyzer.h"

#include <iostream>
using namespace std;
using namespace izenelib::util;
using namespace ilplib::langid;

namespace la
{

MultiLanguageAnalyzer::MultiLanguageAnalyzer() : Analyzer() {}

MultiLanguageAnalyzer::~MultiLanguageAnalyzer() {}

void MultiLanguageAnalyzer::setAnalyzer( Language lang, shared_ptr<Analyzer>& analyzer )
{
    if( lang == OTHER )
        return;
    analyzers_[ lang ] = analyzer;
}

shared_ptr<Analyzer> MultiLanguageAnalyzer::getAnalyzer( MultiLanguageAnalyzer::Language lang ) const
{
    if( lang == OTHER )
        return shared_ptr<Analyzer>();
    return analyzers_[ lang ];
}

void MultiLanguageAnalyzer::setDefaultAnalyzer( shared_ptr<Analyzer>& defAnalyzer )
{
    defAnalyzer_ = defAnalyzer;
}

shared_ptr<Analyzer> MultiLanguageAnalyzer::getDefaultAnalyzer() const
{
    return defAnalyzer_;
}

MultiLanguageAnalyzer::Language MultiLanguageAnalyzer::getCharType( UCS2Char ucs2Char )
{
    if(UString::isThisChineseChar( ucs2Char ) )
        return CHINESE;

    if(UString::isThisAlphaChar( ucs2Char ) )
        return ENGLISH;

    if(UString::isThisKoreanChar( ucs2Char ) )
        return KOREAN;

    if(UString::isThisJapaneseChar( ucs2Char ) )
        return JAPANESE;

    return OTHER;
}

MultiLanguageAnalyzer::Language MultiLanguageAnalyzer::detectLanguage( const UString & input )
{
    LanguageID langId;
    std::string utf8_text;

    input.convertString(utf8_text, izenelib::util::UString::UTF_8);

    langIdAnalyzer_->languageFromString(utf8_text.c_str(), langId);
    switch (langId)
    {
    case LANGUAGE_ID_CHINESE_SIMPLIFIED:
    case LANGUAGE_ID_CHINESE_TRADITIONAL:
        return CHINESE;
    case LANGUAGE_ID_JAPANESE:
        return JAPANESE;
    case LANGUAGE_ID_KOREAN:
        return KOREAN;
    case LANGUAGE_ID_ENGLISH:
        return ENGLISH;
    default:
        return OTHER;
    }
}

/// obsolete
void MultiLanguageAnalyzer::analyzeSynonym(TermList& output, size_t n)
{
    if (analyzers_[CHINESE])
        analyzers_[CHINESE]->analyzeSynonym(output, n);
}

int MultiLanguageAnalyzer::analyzeSynonym(const izenelib::util::UString& inputString, TermList& output)
{
    if (analyzers_[CHINESE])
    {
        return analyzers_[CHINESE]->analyzeSynonym(inputString, output);
    }
    else if (defAnalyzer_)
    {
        return defAnalyzer_->analyzeSynonym(inputString, output);
    }
    else
        return 0;
}

ilplib::langid::Analyzer* MultiLanguageAnalyzer::langIdAnalyzer_;

int MultiLanguageAnalyzer::analyze_impl( const Term& input, void* data, HookType func )
{
    if ( !langIdAnalyzer_ )
    {
        if ( defAnalyzer_ )
        {
            return defAnalyzer_->analyze_impl(input, data, func);
        }
        else
        {
            return 0;
        }
    }

    Language lang = detectLanguage(input.text_);
    if ( lang != OTHER && analyzers_[lang] )
    {
        return analyzers_[lang]->analyze_impl(input, data, func);
    }
    else if ( defAnalyzer_ )
    {
        return defAnalyzer_->analyze_impl(input, data, func);
    }
    else
    {
        return 0;
    }
}

int MultiLanguageAnalyzer::analyze_impl( const Term& input, void* data, HookType func, MultilangGranularity multilangGranularity )
{
    if ( !langIdAnalyzer_ || multilangGranularity != SENTENCE_LEVEL )
        return analyze_impl(input, data, func);

    void** parameters = (void**)data;
    TermIdList * output = (TermIdList*) parameters[0];
    std::string utf8_text;

    input.text_.convertString(utf8_text, izenelib::util::UString::UTF_8);
    const char* p = utf8_text.c_str();
    std::size_t lastpos, pos = 0, globalOffset = 0;
    while (int len = langIdAnalyzer_->sentenceLength(p))
    {
        UString sentence;
        sentence.assign(p, len, izenelib::util::UString::UTF_8);
        Language lang = detectLanguage(sentence);
        lastpos = pos;

        if(lang != OTHER && analyzers_[lang])
            analyzers_[lang]->analyze_impl(sentence, data, func);
        else if(defAnalyzer_)
            defAnalyzer_->analyze_impl(sentence, data, func);

        pos = output->size();
        if(lastpos > 0)
        {
            TermIdList& laInput = (*output);
            for(std::size_t i = lastpos; i < pos; ++i)
                laInput[i].wordOffset_ += globalOffset;
        }
        globalOffset = output->back().wordOffset_ + 1;
        p += len;
    }

    return pos;
}
}
<commit_msg>little fix<commit_after>/**
 * @brief Analyzer for multi-languages
 * @file MultiLanguageAnalyzer.h
 *
 * @date Jan 4, 2010
 * @author vernkin
 */

/**
 * @brief Rewrite MLA using a fast language detction,
 *     String mode is moved to EnglishAnalyzer,
 *      Char mode is moved to CharAnalyzer.
 * @author Wei
 */

#include "la/analyzer/MultiLanguageAnalyzer.h"

#include <iostream>
using namespace std;
using namespace izenelib::util;
using namespace ilplib::langid;

namespace la
{

MultiLanguageAnalyzer::MultiLanguageAnalyzer() : Analyzer() {}

MultiLanguageAnalyzer::~MultiLanguageAnalyzer() {}

void MultiLanguageAnalyzer::setAnalyzer( Language lang, shared_ptr<Analyzer>& analyzer )
{
    if( lang == OTHER )
        return;
    analyzers_[ lang ] = analyzer;
}

shared_ptr<Analyzer> MultiLanguageAnalyzer::getAnalyzer( MultiLanguageAnalyzer::Language lang ) const
{
    if( lang == OTHER )
        return shared_ptr<Analyzer>();
    return analyzers_[ lang ];
}

void MultiLanguageAnalyzer::setDefaultAnalyzer( shared_ptr<Analyzer>& defAnalyzer )
{
    defAnalyzer_ = defAnalyzer;
}

shared_ptr<Analyzer> MultiLanguageAnalyzer::getDefaultAnalyzer() const
{
    return defAnalyzer_;
}

MultiLanguageAnalyzer::Language MultiLanguageAnalyzer::getCharType( UCS2Char ucs2Char )
{
    if(UString::isThisChineseChar( ucs2Char ) )
        return CHINESE;

    if(UString::isThisAlphaChar( ucs2Char ) )
        return ENGLISH;

    if(UString::isThisKoreanChar( ucs2Char ) )
        return KOREAN;

    if(UString::isThisJapaneseChar( ucs2Char ) )
        return JAPANESE;

    return OTHER;
}

MultiLanguageAnalyzer::Language MultiLanguageAnalyzer::detectLanguage( const UString & input )
{
    LanguageID langId;
    std::string utf8_text;

    input.convertString(utf8_text, izenelib::util::UString::UTF_8);

    langIdAnalyzer_->languageFromString(utf8_text.c_str(), langId);
    switch (langId)
    {
    case LANGUAGE_ID_CHINESE_SIMPLIFIED:
    case LANGUAGE_ID_CHINESE_TRADITIONAL:
        return CHINESE;
    case LANGUAGE_ID_JAPANESE:
        return JAPANESE;
    case LANGUAGE_ID_KOREAN:
        return KOREAN;
    case LANGUAGE_ID_ENGLISH:
        return ENGLISH;
    default:
        return OTHER;
    }
}

/// obsolete
void MultiLanguageAnalyzer::analyzeSynonym(TermList& output, size_t n)
{
    if (analyzers_[CHINESE])
        analyzers_[CHINESE]->analyzeSynonym(output, n);
}

int MultiLanguageAnalyzer::analyzeSynonym(const izenelib::util::UString& inputString, TermList& output)
{
    if (analyzers_[CHINESE])
    {
        return analyzers_[CHINESE]->analyzeSynonym(inputString, output);
    }
    else if (defAnalyzer_)
    {
        return defAnalyzer_->analyzeSynonym(inputString, output);
    }
    else
        return 0;
}

ilplib::langid::Analyzer* MultiLanguageAnalyzer::langIdAnalyzer_;

int MultiLanguageAnalyzer::analyze_impl( const Term& input, void* data, HookType func )
{
    if ( !langIdAnalyzer_ )
    {
        if ( defAnalyzer_ )
        {
            return defAnalyzer_->analyze_impl(input, data, func);
        }
        else
        {
            return 0;
        }
    }

    Language lang = detectLanguage(input.text_);
    if ( lang != OTHER && analyzers_[lang] )
    {
        return analyzers_[lang]->analyze_impl(input, data, func);
    }
    else if ( defAnalyzer_ )
    {
        return defAnalyzer_->analyze_impl(input, data, func);
    }
    else
    {
        return 0;
    }
}

int MultiLanguageAnalyzer::analyze_impl( const Term& input, void* data, HookType func, MultilangGranularity multilangGranularity )
{
    if ( !langIdAnalyzer_ || multilangGranularity != SENTENCE_LEVEL )
        return analyze_impl(input, data, func);

    void** parameters = (void**)data;
    TermIdList * output = (TermIdList*) parameters[0];
    std::string utf8_text;

    input.text_.convertString(utf8_text, izenelib::util::UString::UTF_8);
    const char* p = utf8_text.c_str();
    std::size_t lastpos, pos = 0, globalOffset = 0;
    while (int len = langIdAnalyzer_->sentenceLength(p))
    {
        UString sentence;
        sentence.assign(p, len, izenelib::util::UString::UTF_8);
        Language lang = detectLanguage(sentence);
        lastpos = pos;

        if(lang != OTHER && analyzers_[lang])
            analyzers_[lang]->analyze_impl(sentence, data, func);
        else if(defAnalyzer_)
            defAnalyzer_->analyze_impl(sentence, data, func);

        pos = output->size();

        if(lastpos > 0)
        {
            TermIdList& laInput = (*output);
            for(std::size_t i = lastpos; i < pos; ++i)
                laInput[i].wordOffset_ += globalOffset;
        }
        if (pos > lastpos)
            globalOffset = output->back().wordOffset_ + 1;

        p += len;
    }

    if (output->size() > 0)
        return output->back().wordOffset_;
    else
        return 0;
}
}
<|endoftext|>


<commit_before>
#include <gmock/gmock.h>

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>

#include <glbinding/Binding.h>
#include <glbinding/Meta.h>

#include <glbinding/gl/functions.h>  // < imagine this was included by a 3rd party library (e.g., globjects.cpp)

#include <glbinding/gl/types.h>
#include <glbinding/gl/functions.h>
#include <glbinding/gl/enum.h>

class Regression_185 : public testing::Test
{
public:
};

TEST(Regression_185, GLbooleanReturnValueCall)  // GL calls fail if function returns GLboolean
{
    ASSERT_TRUE(glfwInit());

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_VISIBLE, false);

#ifdef SYSTEM_DARWIN
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif

    GLFWwindow * window = glfwCreateWindow(320, 240, "", nullptr, nullptr);

    ASSERT_NE(nullptr, window);

    glfwMakeContextCurrent(window);

    glbinding::Binding::initialize();

    ASSERT_EQ(gl::GL_NO_ERROR, gl::glGetError());

    // "Death Test": resolve a basic OpenGL of return type GLboolean (with underlying type char)
    // note: this might work on some OpenGL drivers without expected failure (try NVIDIA for expected failure on windows x64)
    ASSERT_NO_THROW(gl::glIsProgram(0));

    ASSERT_EQ(gl::GL_NO_ERROR, gl::glGetError());

    glfwMakeContextCurrent(nullptr);
    glfwTerminate();

    SUCCEED();
}

TEST(Regression_185, GetString)  // Static initializiation issue ...
{
    ASSERT_EQ(glbinding::Meta::getString(gl::GL_TRUE), "GL_TRUE");
    ASSERT_EQ(glbinding::Meta::getString(gl::GL_FALSE), "GL_FALSE");

    SUCCEED();
}
<commit_msg>adjust regression test to nogl environments<commit_after>
#include <gmock/gmock.h>

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>

#include <glbinding/Binding.h>
#include <glbinding/Meta.h>

#include <glbinding/gl/functions.h>  // < imagine this was included by a 3rd party library (e.g., globjects.cpp)

#include <glbinding/gl/types.h>
#include <glbinding/gl/functions.h>
#include <glbinding/gl/enum.h>

class Regression_185 : public testing::Test
{
public:
};

TEST(Regression_185, GLbooleanReturnValueCall)  // GL calls fail if function returns GLboolean
{
    if (!glfwInit())
    {
        SUCCEED();
        return;
    }

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_VISIBLE, false);

#ifdef SYSTEM_DARWIN
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif

    GLFWwindow * window = glfwCreateWindow(320, 240, "", nullptr, nullptr);

    ASSERT_NE(nullptr, window);

    glfwMakeContextCurrent(window);

    glbinding::Binding::initialize();

    ASSERT_EQ(gl::GL_NO_ERROR, gl::glGetError());

    // "Death Test": resolve a basic OpenGL of return type GLboolean (with underlying type char)
    // note: this might work on some OpenGL drivers without expected failure (try NVIDIA for expected failure on windows x64)
    ASSERT_NO_THROW(gl::glIsProgram(0));

    ASSERT_EQ(gl::GL_NO_ERROR, gl::glGetError());

    glfwMakeContextCurrent(nullptr);
    glfwTerminate();

    SUCCEED();
}

TEST(Regression_185, GetString)  // Static initializiation issue ...
{
    ASSERT_EQ(glbinding::Meta::getString(gl::GL_TRUE), "GL_TRUE");
    ASSERT_EQ(glbinding::Meta::getString(gl::GL_FALSE), "GL_FALSE");

    SUCCEED();
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgallerytrackerthumbnailcolumn_p.h"

#include <QtCore/qcryptographichash.h>
#include <QtCore/qfile.h>
#include <QtCore/qfuturewatcher.h>
#include <QtCore/qtconcurrentmap.h>
#include <QtDBus/qdbuspendingcall.h>
#include <QtDBus/qdbuspendingreply.h>
#include <QtGui/qdesktopservices.h>
#include <QtGui/qimage.h>
#include <QtGui/qpixmap.h>

QTM_BEGIN_NAMESPACE

class QGalleryTrackerThumbnailDBusWatcher : public QDBusPendingCallWatcher
{
public:
    QGalleryTrackerThumbnailDBusWatcher(
            const QDBusPendingCall &call,
            const QVector<uint> &imageIds,
            const QStringList &filePaths,
            const QStringList &mimeTypes)
        : QDBusPendingCallWatcher(call)
        , id(0)
        , imageIds(imageIds)
        , filePaths(filePaths)
        , mimeTypes(mimeTypes)
    {
    }

    uint id;
    QVector<uint> imageIds;
    QStringList filePaths;
    QStringList mimeTypes;
};

class QGalleryTrackerThumbnailLoadWatcher : public QFutureWatcher<QVariant>
{
public:
    QGalleryTrackerThumbnailLoadWatcher(
            const QVector<uint> imageIds, const QStringList &filePaths, const QStringList &mimeTypes)
        : imageIds(imageIds)
        , filePaths(filePaths)
        , mimeTypes(mimeTypes)
    {
    }

    QVector<uint> imageIds;
    QStringList filePaths;
    QStringList mimeTypes;
};

QGalleryTrackerThumbnailColumn::QGalleryTrackerThumbnailColumn(
        const QGalleryDBusInterfacePointer &thumbnailInterface,
        int key,
        int mimeTypeColumn,
        QVariant::Type type,
        const QString &flavor,
        QObject *parent)
    : QGalleryTrackerImageColumn(parent)
    , m_mimeTypeColumn(mimeTypeColumn)
    , m_type(type)
    , m_flavor(flavor)
    , m_thumbnailDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
                 + QLatin1String("/.thumbnails/") + flavor + QLatin1Char('/'))
    , m_failDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
                + QLatin1String("/.thumbnails/fail/"))
    , m_localDir(QLatin1String(".thumblocal/") + flavor + QLatin1Char('/'))
    , m_thumbnailInterface(thumbnailInterface)
    , m_keys(QList<int>() << key)
{
}

QGalleryTrackerThumbnailColumn::~QGalleryTrackerThumbnailColumn()
{
    qDeleteAll(m_dbusWatchers);

    typedef QList<QGalleryTrackerThumbnailLoadWatcher *>::iterator iterator;

    for (iterator it = m_loadWatchers.begin(), end = m_loadWatchers.end(); it != end; ++it)
        (*it)->cancel();

    for (iterator it = m_loadWatchers.begin(), end = m_loadWatchers.end(); it != end; ++it)
        (*it)->waitForFinished();

    qDeleteAll(m_loadWatchers);
}

QGalleryTrackerImageColumn *QGalleryTrackerThumbnailColumn::createImageColumn(
        QGalleryDBusInterfaceFactory *dbus,
        int key,
        const QString &profile,
        const QVector<int> &columns)
{
    return new QGalleryTrackerThumbnailColumn(
            dbus->thumbnailInterface(), key, columns.first(), QVariant::Image, profile);
}

QGalleryTrackerImageColumn *QGalleryTrackerThumbnailColumn::createPixmapColumn(
        QGalleryDBusInterfaceFactory *dbus,
        int key,
        const QString &profile,
        const QVector<int> &columns)
{
    return new QGalleryTrackerThumbnailColumn(
            dbus->thumbnailInterface(), key, columns.first(), QVariant::Pixmap, profile);
}

void QGalleryTrackerThumbnailColumn::insertImages(
        int index, int count, QVector<QVariant>::const_iterator row, int tableWidth)
{
    QStringList filePaths;
    QStringList mimeTypes;

    m_images.insert(index, count, QVariant());
    m_imageIds.insert(index, count, 0);

    for (int i = index; i < count; ++i, row += tableWidth) {
        const QString filePath = row->toString();
        const QString mimeType = (row + m_mimeTypeColumn)->toString();

        const uint imageId = qHash(filePath);

        m_imageIds.replace(i, imageId);

        filePaths.append(filePath);
        mimeTypes.append(mimeType);
    }

    QGalleryTrackerThumbnailLoadWatcher *watcher = new QGalleryTrackerThumbnailLoadWatcher(
            m_imageIds.mid(index, count), filePaths, mimeTypes);

    m_loadWatchers.append(watcher);

    connect(watcher, SIGNAL(finished()), this, SLOT(loadWatcherFinished()));
    connect(watcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(imagesReady(int,int)));

    watcher->setFuture(QtConcurrent::mapped(filePaths, LoadFunc(this)));
}

void QGalleryTrackerThumbnailColumn::removeImages(int index, int count)
{
    count = qMin(m_images.count() - index, count);

    if (count > 0) {
        m_images.remove(index, count);
        m_imageIds.remove(index, count);
    }
}

void QGalleryTrackerThumbnailColumn::loadWatcherFinished()
{
    QGalleryTrackerThumbnailLoadWatcher *loadWatcher
            = static_cast<QGalleryTrackerThumbnailLoadWatcher *>(sender());

    QStringList urls;
    QStringList mimeTypes;
    QStringList filePaths;
    QVector<uint> imageIds;

    for (int i = 0, count = loadWatcher->future().resultCount(); i < count; ++i) {
        if (loadWatcher->resultAt(i).isNull()) {
            urls.append(QLatin1String("file://") + loadWatcher->filePaths.at(i));
            mimeTypes.append(loadWatcher->mimeTypes.at(i));
            filePaths.append(loadWatcher->filePaths.at(i));
            imageIds.append(loadWatcher->imageIds.at(i));
        }
    }

    const uint cancelId = 0;

    if (!imageIds.isEmpty()) {
        QDBusPendingCall call = m_thumbnailInterface->asyncCall(
                QLatin1String("Queue"),
                urls,
                mimeTypes,
#ifndef Q_WS_MAEMO_5
                m_flavor,
                QLatin1String("default"),
#endif
                cancelId);

        QGalleryTrackerThumbnailDBusWatcher *dbusWatcher = new QGalleryTrackerThumbnailDBusWatcher(
                call, imageIds, filePaths, mimeTypes);

        m_dbusWatchers.append(dbusWatcher);

        if (dbusWatcher->isFinished()) {
            dbusWatcherFinished(dbusWatcher);
        } else {
            connect(dbusWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
                    this, SLOT(dbusWatcherFinished(QDBusPendingCallWatcher*)));
        }
    }

    m_loadWatchers.removeAll(loadWatcher);

    loadWatcher->deleteLater();
}

void QGalleryTrackerThumbnailColumn::finalLoadWatcherFinished()
{
    QGalleryTrackerThumbnailLoadWatcher *loadWatcher
            = static_cast<QGalleryTrackerThumbnailLoadWatcher *>(sender());

    m_loadWatchers.removeAll(loadWatcher);

    loadWatcher->deleteLater();
}

void QGalleryTrackerThumbnailColumn::imagesReady(int begin, int end)
{
    QGalleryTrackerThumbnailLoadWatcher *watcher
            = static_cast<QGalleryTrackerThumbnailLoadWatcher *>(sender());

    for (int i = begin, index = 0, count = 0; i < end && index < m_imageIds.count(); ++i) {
        while (index < m_imageIds.count() && m_imageIds.at(index) != watcher->imageIds.at(i))
            ++index;

        while (i < end
               && index + count < m_imageIds.count()
               && m_imageIds.at(index + count) == watcher->imageIds.at(i)) {
            QVariant image = watcher->resultAt(i);

            if (!image.isNull()) {
                image.convert(m_type);

                m_images.replace(index + count, image);

                ++i;
                ++count;
            } else {
                if (count > 0)
                    emit imagesChanged(index + m_offset, count, m_keys);

                index += count;

                break;
            }
        }

        if (count > 0) {
            emit imagesChanged(index + m_offset, count, m_keys);

            index += count;
            count = 0;
        }
    }
}

void QGalleryTrackerThumbnailColumn::dbusWatcherFinished(QDBusPendingCallWatcher *watcher)
{
    if (watcher->isError()) {
        qWarning("DBUS Error %s", qPrintable(watcher->error().message()));

        m_dbusWatchers.removeAll(static_cast<QGalleryTrackerThumbnailDBusWatcher *>(watcher));

        watcher->deleteLater();
    } else {
        QDBusPendingReply<uint> reply(*watcher);

        static_cast<QGalleryTrackerThumbnailDBusWatcher *>(watcher)->id = reply.value();
    }
}

void QGalleryTrackerThumbnailColumn::dbusError(
        uint id, const QStringList &uris, int error, const QString &errorString)
{
    Q_UNUSED(id);
    Q_UNUSED(uris);

    qWarning("Thumbnail Error %d, %s", error, qPrintable(errorString));
}

void QGalleryTrackerThumbnailColumn::dbusFinished(uint id)
{
    for (QList<QGalleryTrackerThumbnailDBusWatcher *>::iterator it = m_dbusWatchers.begin();
            it != m_dbusWatchers.end();
            ++it) {
        if ((*it)->id == id) {
            QGalleryTrackerThumbnailDBusWatcher *dbusWatcher = *it;

            QGalleryTrackerThumbnailLoadWatcher *loadWatcher
                    = new QGalleryTrackerThumbnailLoadWatcher(
                            dbusWatcher->imageIds, dbusWatcher->filePaths, dbusWatcher->mimeTypes);

            m_loadWatchers.append(loadWatcher);

            connect(loadWatcher, SIGNAL(finished()), this, SLOT(finalLoadWatcherFinished()));
            connect(loadWatcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(imagesReady(int,int)));

            loadWatcher->setFuture(QtConcurrent::mapped(dbusWatcher->filePaths, LoadFunc(this)));

            dbusWatcher->deleteLater();

            m_dbusWatchers.erase(it);

            return;
        }
    }
}

QVariant QGalleryTrackerThumbnailColumn::loadThumbnail(const QString &filePath)
{
    const QString hash = QCryptographicHash::hash(
            QUrl::fromLocalFile(filePath).toEncoded(), QCryptographicHash::Md5).toHex();

#ifdef Q_WS_MAEMO_5
    QString imagePath = m_thumbnailDir + hash + QLatin1String(".jpeg");
#else
    QString imagePath = m_thumbnailDir + hash + QLatin1String(".png");
#endif

    if (!QFile::exists(imagePath)) {
        const int index = filePath.lastIndexOf(QLatin1Char('/'));

        if (index != -1 && index != filePath.count() - 1) {
            imagePath = filePath.mid(0, index + 1)
                    + m_localDir
                    + QUrl::toPercentEncoding(filePath.mid(index + 1))
                    + QLatin1String(".jpeg");

            if (!QFile::exists(imagePath)) {
#ifdef Q_WS_MAEMO_5
                imagePath = m_failDir + hash + QLatin1String(".jpeg");
#else
                imagePath = m_failDir + hash + QLatin1String(".png");
#endif
                return QFile::exists(imagePath)
                        ? QImage()
                        : QVariant();
            }
        }
    }

    return QImage(imagePath);
}

#include "moc_qgallerytrackerthumbnailcolumn_p.cpp"

QTM_END_NAMESPACE
<commit_msg>Connect to the thumbnailer ready signal.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgallerytrackerthumbnailcolumn_p.h"

#include <QtCore/qcryptographichash.h>
#include <QtCore/qfile.h>
#include <QtCore/qfuturewatcher.h>
#include <QtCore/qtconcurrentmap.h>
#include <QtDBus/qdbuspendingcall.h>
#include <QtDBus/qdbuspendingreply.h>
#include <QtGui/qdesktopservices.h>
#include <QtGui/qimage.h>
#include <QtGui/qpixmap.h>

QTM_BEGIN_NAMESPACE

class QGalleryTrackerThumbnailDBusWatcher : public QDBusPendingCallWatcher
{
public:
    QGalleryTrackerThumbnailDBusWatcher(
            const QDBusPendingCall &call,
            const QVector<uint> &imageIds,
            const QStringList &filePaths,
            const QStringList &mimeTypes)
        : QDBusPendingCallWatcher(call)
        , id(0)
        , imageIds(imageIds)
        , filePaths(filePaths)
        , mimeTypes(mimeTypes)
    {
    }

    uint id;
    QVector<uint> imageIds;
    QStringList filePaths;
    QStringList mimeTypes;
};

class QGalleryTrackerThumbnailLoadWatcher : public QFutureWatcher<QVariant>
{
public:
    QGalleryTrackerThumbnailLoadWatcher(
            const QVector<uint> imageIds, const QStringList &filePaths, const QStringList &mimeTypes)
        : imageIds(imageIds)
        , filePaths(filePaths)
        , mimeTypes(mimeTypes)
    {
    }

    QVector<uint> imageIds;
    QStringList filePaths;
    QStringList mimeTypes;
};

QGalleryTrackerThumbnailColumn::QGalleryTrackerThumbnailColumn(
        const QGalleryDBusInterfacePointer &thumbnailInterface,
        int key,
        int mimeTypeColumn,
        QVariant::Type type,
        const QString &flavor,
        QObject *parent)
    : QGalleryTrackerImageColumn(parent)
    , m_mimeTypeColumn(mimeTypeColumn)
    , m_type(type)
    , m_flavor(flavor)
    , m_thumbnailDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
                 + QLatin1String("/.thumbnails/") + flavor + QLatin1Char('/'))
    , m_failDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
                + QLatin1String("/.thumbnails/fail/"))
    , m_localDir(QLatin1String(".thumblocal/") + flavor + QLatin1Char('/'))
    , m_thumbnailInterface(thumbnailInterface)
    , m_keys(QList<int>() << key)
{
    connect(m_thumbnailInterface.data(), SIGNAL(Finished(uint)), this, SLOT(dbusFinished(uint)));
}

QGalleryTrackerThumbnailColumn::~QGalleryTrackerThumbnailColumn()
{
    qDeleteAll(m_dbusWatchers);

    typedef QList<QGalleryTrackerThumbnailLoadWatcher *>::iterator iterator;

    for (iterator it = m_loadWatchers.begin(), end = m_loadWatchers.end(); it != end; ++it)
        (*it)->cancel();

    for (iterator it = m_loadWatchers.begin(), end = m_loadWatchers.end(); it != end; ++it)
        (*it)->waitForFinished();

    qDeleteAll(m_loadWatchers);
}

QGalleryTrackerImageColumn *QGalleryTrackerThumbnailColumn::createImageColumn(
        QGalleryDBusInterfaceFactory *dbus,
        int key,
        const QString &profile,
        const QVector<int> &columns)
{
    return new QGalleryTrackerThumbnailColumn(
            dbus->thumbnailInterface(), key, columns.first(), QVariant::Image, profile);
}

QGalleryTrackerImageColumn *QGalleryTrackerThumbnailColumn::createPixmapColumn(
        QGalleryDBusInterfaceFactory *dbus,
        int key,
        const QString &profile,
        const QVector<int> &columns)
{
    return new QGalleryTrackerThumbnailColumn(
            dbus->thumbnailInterface(), key, columns.first(), QVariant::Pixmap, profile);
}

void QGalleryTrackerThumbnailColumn::insertImages(
        int index, int count, QVector<QVariant>::const_iterator row, int tableWidth)
{
    QStringList filePaths;
    QStringList mimeTypes;

    m_images.insert(index, count, QVariant());
    m_imageIds.insert(index, count, 0);

    for (int i = index; i < count; ++i, row += tableWidth) {
        const QString filePath = row->toString();
        const QString mimeType = (row + m_mimeTypeColumn)->toString();

        const uint imageId = qHash(filePath);

        m_imageIds.replace(i, imageId);

        filePaths.append(filePath);
        mimeTypes.append(mimeType);
    }

    QGalleryTrackerThumbnailLoadWatcher *watcher = new QGalleryTrackerThumbnailLoadWatcher(
            m_imageIds.mid(index, count), filePaths, mimeTypes);

    m_loadWatchers.append(watcher);

    connect(watcher, SIGNAL(finished()), this, SLOT(loadWatcherFinished()));
    connect(watcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(imagesReady(int,int)));

    watcher->setFuture(QtConcurrent::mapped(filePaths, LoadFunc(this)));
}

void QGalleryTrackerThumbnailColumn::removeImages(int index, int count)
{
    count = qMin(m_images.count() - index, count);

    if (count > 0) {
        m_images.remove(index, count);
        m_imageIds.remove(index, count);
    }
}

void QGalleryTrackerThumbnailColumn::loadWatcherFinished()
{
    QGalleryTrackerThumbnailLoadWatcher *loadWatcher
            = static_cast<QGalleryTrackerThumbnailLoadWatcher *>(sender());

    QStringList urls;
    QStringList mimeTypes;
    QStringList filePaths;
    QVector<uint> imageIds;

    for (int i = 0, count = loadWatcher->future().resultCount(); i < count; ++i) {
        if (loadWatcher->resultAt(i).isNull()) {
            urls.append(QLatin1String("file://") + loadWatcher->filePaths.at(i));
            mimeTypes.append(loadWatcher->mimeTypes.at(i));
            filePaths.append(loadWatcher->filePaths.at(i));
            imageIds.append(loadWatcher->imageIds.at(i));
        }
    }

    const uint cancelId = 0;

    if (!imageIds.isEmpty()) {
        QDBusPendingCall call = m_thumbnailInterface->asyncCall(
                QLatin1String("Queue"),
                urls,
                mimeTypes,
#ifndef Q_WS_MAEMO_5
                m_flavor,
                QLatin1String("default"),
#endif
                cancelId);

        QGalleryTrackerThumbnailDBusWatcher *dbusWatcher = new QGalleryTrackerThumbnailDBusWatcher(
                call, imageIds, filePaths, mimeTypes);

        m_dbusWatchers.append(dbusWatcher);

        if (dbusWatcher->isFinished()) {
            dbusWatcherFinished(dbusWatcher);
        } else {
            connect(dbusWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
                    this, SLOT(dbusWatcherFinished(QDBusPendingCallWatcher*)));
        }
    }

    m_loadWatchers.removeAll(loadWatcher);

    loadWatcher->deleteLater();
}

void QGalleryTrackerThumbnailColumn::finalLoadWatcherFinished()
{
    QGalleryTrackerThumbnailLoadWatcher *loadWatcher
            = static_cast<QGalleryTrackerThumbnailLoadWatcher *>(sender());

    m_loadWatchers.removeAll(loadWatcher);

    loadWatcher->deleteLater();
}

void QGalleryTrackerThumbnailColumn::imagesReady(int begin, int end)
{
    QGalleryTrackerThumbnailLoadWatcher *watcher
            = static_cast<QGalleryTrackerThumbnailLoadWatcher *>(sender());

    for (int i = begin, index = 0, count = 0; i < end && index < m_imageIds.count(); ++i) {
        while (index < m_imageIds.count() && m_imageIds.at(index) != watcher->imageIds.at(i))
            ++index;

        while (i < end
               && index + count < m_imageIds.count()
               && m_imageIds.at(index + count) == watcher->imageIds.at(i)) {
            QVariant image = watcher->resultAt(i);

            if (!image.isNull()) {
                image.convert(m_type);

                m_images.replace(index + count, image);

                ++i;
                ++count;
            } else {
                if (count > 0)
                    emit imagesChanged(index + m_offset, count, m_keys);

                index += count;

                break;
            }
        }

        if (count > 0) {
            emit imagesChanged(index + m_offset, count, m_keys);

            index += count;
            count = 0;
        }
    }
}

void QGalleryTrackerThumbnailColumn::dbusWatcherFinished(QDBusPendingCallWatcher *watcher)
{
    if (watcher->isError()) {
        qWarning("DBUS Error %s", qPrintable(watcher->error().message()));

        m_dbusWatchers.removeAll(static_cast<QGalleryTrackerThumbnailDBusWatcher *>(watcher));

        watcher->deleteLater();
    } else {
        QDBusPendingReply<uint> reply(*watcher);

        static_cast<QGalleryTrackerThumbnailDBusWatcher *>(watcher)->id = reply.value();
    }
}

void QGalleryTrackerThumbnailColumn::dbusError(
        uint id, const QStringList &uris, int error, const QString &errorString)
{
    Q_UNUSED(id);
    Q_UNUSED(uris);

    qWarning("Thumbnail Error %d, %s", error, qPrintable(errorString));
}

void QGalleryTrackerThumbnailColumn::dbusFinished(uint id)
{
    for (QList<QGalleryTrackerThumbnailDBusWatcher *>::iterator it = m_dbusWatchers.begin();
            it != m_dbusWatchers.end();
            ++it) {
        if ((*it)->id == id) {
            QGalleryTrackerThumbnailDBusWatcher *dbusWatcher = *it;

            QGalleryTrackerThumbnailLoadWatcher *loadWatcher
                    = new QGalleryTrackerThumbnailLoadWatcher(
                            dbusWatcher->imageIds, dbusWatcher->filePaths, dbusWatcher->mimeTypes);

            m_loadWatchers.append(loadWatcher);

            connect(loadWatcher, SIGNAL(finished()), this, SLOT(finalLoadWatcherFinished()));
            connect(loadWatcher, SIGNAL(resultsReadyAt(int,int)), this, SLOT(imagesReady(int,int)));

            loadWatcher->setFuture(QtConcurrent::mapped(dbusWatcher->filePaths, LoadFunc(this)));

            dbusWatcher->deleteLater();

            m_dbusWatchers.erase(it);

            return;
        }
    }
}

QVariant QGalleryTrackerThumbnailColumn::loadThumbnail(const QString &filePath)
{
    const QString hash = QCryptographicHash::hash(
            QUrl::fromLocalFile(filePath).toEncoded(), QCryptographicHash::Md5).toHex();

#ifdef Q_WS_MAEMO_5
    QString imagePath = m_thumbnailDir + hash + QLatin1String(".jpeg");
#else
    QString imagePath = m_thumbnailDir + hash + QLatin1String(".png");
#endif

    if (!QFile::exists(imagePath)) {
        const int index = filePath.lastIndexOf(QLatin1Char('/'));

        if (index != -1 && index != filePath.count() - 1) {
            imagePath = filePath.mid(0, index + 1)
                    + m_localDir
                    + QUrl::toPercentEncoding(filePath.mid(index + 1))
                    + QLatin1String(".jpeg");

            if (!QFile::exists(imagePath)) {
#ifdef Q_WS_MAEMO_5
                imagePath = m_failDir + hash + QLatin1String(".jpeg");
#else
                imagePath = m_failDir + hash + QLatin1String(".png");
#endif
                return QFile::exists(imagePath)
                        ? QImage()
                        : QVariant();
            }
        }
    }

    return QImage(imagePath);
}

#include "moc_qgallerytrackerthumbnailcolumn_p.cpp"

QTM_END_NAMESPACE
<|endoftext|>


<commit_before>//Copyright (c) 2020 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "RedistributeBeadingStrategy.h"

#include <algorithm>
#include <numeric>

namespace cura
{
    BeadingStrategy::Beading RedistributeBeadingStrategy::compute(coord_t thickness, coord_t bead_count) const
    {
        Beading ret = parent->compute(thickness, bead_count);

        // Early out when the only walls are outer, the parent can have been trusted to handle it.
        if (bead_count < 3)
        {
            if (bead_count == 2 && optimal_width_outer < (thickness / 2))
            {
                const coord_t back_pos = bead_count - 1;

                // Compensate for the outer wall lock factor:
                ret.bead_widths[0] = static_cast<coord_t>(outer_wall_lock_factor * optimal_width_outer + outer_wall_lock_inverse * ret.bead_widths[0]);
                ret.bead_widths[back_pos] = static_cast<coord_t>(outer_wall_lock_factor * optimal_width_outer + outer_wall_lock_inverse * ret.bead_widths[back_pos]);
                ret.toolpath_locations[0] = ret.bead_widths[0] / 2;
                ret.toolpath_locations[back_pos] = thickness - ret.bead_widths[back_pos] / 2;

                // Check if a third wall needs to be created, if so, do it, otherwise put the rest-width in leftovers:
                coord_t left_over = std::max(static_cast<coord_t>(0), thickness - (ret.bead_widths.front() + ret.bead_widths.back()));
                if (left_over >= this->getTransitionThickness(0))
                {
                    ret.bead_widths.insert(std::next(ret.bead_widths.begin()), left_over);
                    ret.toolpath_locations.insert(std::next(ret.toolpath_locations.begin()), thickness / 2);
                    ret.left_over = 0;
                }
                else
                {
                    ret.left_over = left_over;
                }
            }
            return ret;
        }

        // Determine outer bead ratio
        const coord_t outer_width = ret.bead_widths.front() + ret.bead_widths.back();
        const coord_t outer_width_optimal = optimal_width_outer * 2;
        const coord_t outer_width_deviation = static_cast<coord_t>(static_cast<double>(outer_width_optimal - outer_width) * outer_wall_lock_factor + 0.5);
        const coord_t outer_width_required = outer_width + outer_width_deviation;
        const Ratio outer_bead_ratio = static_cast<double>(outer_width_required) / static_cast<double>(outer_width);

        if (outer_bead_ratio != 1._r) // Only update if needed
        {
            // Update outer beads
            ret.bead_widths.front() = static_cast<coord_t>(static_cast<double>(ret.bead_widths.front()) * outer_bead_ratio + 0.5);
            ret.bead_widths.back() = static_cast<coord_t>(static_cast<double>(ret.bead_widths.back()) * outer_bead_ratio + 0.5);
            // TODO: validate size

            // Determine inner bead ratio
            auto inner_bead_width_begin = std::next(ret.bead_widths.begin());
            auto inner_bead_width_end = std::prev(ret.bead_widths.end());
            const coord_t total_inner_bead_width = std::accumulate(inner_bead_width_begin, inner_bead_width_end, static_cast<coord_t>(0));
            const coord_t total_required_inner_bead_width = thickness - ret.bead_widths.front() - ret.bead_widths.back();
            const Ratio inner_bead_ratio = static_cast<double>(total_required_inner_bead_width) / static_cast<double>(total_inner_bead_width);

            for (auto bead_width_it = inner_bead_width_begin; bead_width_it < inner_bead_width_end; bead_width_it++)
            {
                *bead_width_it = static_cast<coord_t>(static_cast<double>(*bead_width_it) * inner_bead_ratio + 0.5);
                // TODO: validate Size
            }

            // TODO: insert inner_bead if needed

            // TODO: lock position of outer wall

            // Update the first half of the toolpath-locations with the updated bead-widths (starting from 0, up to half):
            coord_t last_coord = 0;
            coord_t last_width = 0;
            for (coord_t i_location = 0; i_location < bead_count / 2; ++i_location)
            {
                ret.toolpath_locations[i_location] = last_coord + (last_width + ret.bead_widths[i_location]) / 2;
                last_coord = ret.toolpath_locations[i_location];
                last_width = ret.bead_widths[i_location];
            }

            // Handle the position of any middle wall (note that the width will already have been set correctly):
            if (bead_count % 2 == 1)
            {
                ret.toolpath_locations[bead_count / 2] = thickness / 2;
            }

            // Update the last half of the toolpath-locations with the updated bead-widths (starting from thickness, down to half):
            last_coord = thickness;
            last_width = 0;
            for (coord_t i_location = bead_count - 1; i_location >= bead_count - (bead_count / 2); --i_location)
            {
                ret.toolpath_locations[i_location] = last_coord - (last_width + ret.bead_widths[i_location]) / 2;
                last_coord = ret.toolpath_locations[i_location];
                last_width = ret.bead_widths[i_location];
            }

            ret.left_over = thickness - std::accumulate(ret.bead_widths.cbegin(), ret.bead_widths.cend(), static_cast<coord_t>(0));
        }
        return ret;
    }

    } // namespace cura
<commit_msg>Inner beads should also be processed<commit_after>//Copyright (c) 2020 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "RedistributeBeadingStrategy.h"

#include <algorithm>
#include <numeric>

namespace cura
{
    BeadingStrategy::Beading RedistributeBeadingStrategy::compute(coord_t thickness, coord_t bead_count) const
    {
        Beading ret = parent->compute(thickness, bead_count);

        // Early out when the only walls are outer, the parent can have been trusted to handle it. TODO: False! Now we need to lock postition
        if (bead_count < 3)
        {
            if (bead_count == 2 && optimal_width_outer < (thickness / 2))
            {
                const coord_t back_pos = bead_count - 1;

                // Compensate for the outer wall lock factor:
                ret.bead_widths[0] = static_cast<coord_t>(outer_wall_lock_factor * optimal_width_outer + outer_wall_lock_inverse * ret.bead_widths[0]);
                ret.bead_widths[back_pos] = static_cast<coord_t>(outer_wall_lock_factor * optimal_width_outer + outer_wall_lock_inverse * ret.bead_widths[back_pos]);
                ret.toolpath_locations[0] = ret.bead_widths[0] / 2;
                ret.toolpath_locations[back_pos] = thickness - ret.bead_widths[back_pos] / 2;

                // Check if a third wall needs to be created, if so, do it, otherwise put the rest-width in leftovers:
                coord_t left_over = std::max(static_cast<coord_t>(0), thickness - (ret.bead_widths.front() + ret.bead_widths.back()));
                if (left_over >= this->getTransitionThickness(0))
                {
                    ret.bead_widths.insert(std::next(ret.bead_widths.begin()), left_over);
                    ret.toolpath_locations.insert(std::next(ret.toolpath_locations.begin()), thickness / 2);
                    ret.left_over = 0;
                }
                else
                {
                    ret.left_over = left_over;
                }
            }
            return ret;
        }

        // Determine outer bead ratio
        const coord_t outer_width = ret.bead_widths.front() + ret.bead_widths.back();
        const coord_t outer_width_optimal = optimal_width_outer * 2;
        const coord_t outer_width_deviation = static_cast<coord_t>(static_cast<double>(outer_width_optimal - outer_width) * outer_wall_lock_factor + 0.5);
        const coord_t outer_width_required = outer_width + outer_width_deviation;
        const Ratio outer_bead_ratio = static_cast<double>(outer_width_required) / static_cast<double>(outer_width);

        // Update outer beads
        ret.bead_widths.front() = static_cast<coord_t>(static_cast<double>(ret.bead_widths.front()) * outer_bead_ratio + 0.5);
        ret.bead_widths.back() = static_cast<coord_t>(static_cast<double>(ret.bead_widths.back()) * outer_bead_ratio + 0.5);

        // Determine inner bead ratio
        auto inner_bead_width_begin = std::next(ret.bead_widths.begin());
        auto inner_bead_width_end = std::prev(ret.bead_widths.end());
        const coord_t total_inner_bead_width =
            std::accumulate(inner_bead_width_begin, inner_bead_width_end, static_cast<coord_t>(0));
        const coord_t total_required_inner_bead_width =
            thickness - ret.bead_widths.front() - ret.bead_widths.back();
        const Ratio inner_bead_ratio =
            static_cast<double>(total_required_inner_bead_width) / static_cast<double>(total_inner_bead_width);

        for (auto bead_width_it = inner_bead_width_begin; bead_width_it < inner_bead_width_end; bead_width_it++)
        {
            *bead_width_it = static_cast<coord_t>(static_cast<double>(*bead_width_it) * inner_bead_ratio + 0.5);
        }

        // Filter out bead_widths that violate the transition width and recalculate if needed
        ret.bead_widths.erase(std::remove_if(ret.bead_widths.begin(), ret.bead_widths.end(),
                                             [&](const coord_t width)
                                             {
                                                 return width <= parent->getTransitionThickness(0);
                                             }), ret.bead_widths.end());
        if (ret.bead_widths.size() < ret.toolpath_locations.size())
        {
            const coord_t left_over = thickness - std::accumulate(ret.bead_widths.cbegin(), ret.bead_widths.cend(), static_cast<coord_t>(0));
            logWarning("Removed a bead -> leftover %d, no_beads -> %d, you should update!\n", left_over, ret.bead_widths.size());
        }
        bead_count = ret.bead_widths.size();
        ret.toolpath_locations.resize(bead_count);

        // Update the first half of the toolpath-locations with the updated bead-widths (starting from 0, up to half):
        coord_t last_coord = 0;
        coord_t last_width = 0;
        for (coord_t i_location = 0; i_location < bead_count / 2; ++i_location)
        {
            ret.toolpath_locations[i_location] = last_coord + (last_width + ret.bead_widths[i_location]) / 2;
            last_coord = ret.toolpath_locations[i_location];
            last_width = ret.bead_widths[i_location];
        }

        // Handle the position of any middle wall (note that the width will already have been set correctly):
        if (bead_count % 2 == 1)
        {
            ret.toolpath_locations[bead_count / 2] = thickness / 2;
        }

        // Update the last half of the toolpath-locations with the updated bead-widths (starting from thickness, down to half):
        last_coord = thickness;
        last_width = 0;
        for (coord_t i_location = bead_count - 1; i_location >= bead_count - (bead_count / 2); --i_location)
        {
            ret.toolpath_locations[i_location] = last_coord - (last_width + ret.bead_widths[i_location]) / 2;
            last_coord = ret.toolpath_locations[i_location];
            last_width = ret.bead_widths[i_location];
        }

        ret.left_over = thickness - std::accumulate(ret.bead_widths.cbegin(), ret.bead_widths.cend(), static_cast<coord_t>(0));
        return ret;
    }

    } // namespace cura
<|endoftext|>


<commit_before>//
// Copyright (C) 2009 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2009 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

// Author: Sergey Kostanbaev <sergey DOT kostanbaev AT SIPez DOT com>

// SYSTEM INCLUDES
#include <os/OsIntTypes.h>
#include <os/OsSysLog.h>

#include <sched.h>
#include <unistd.h>
#include <sys/types.h>

#ifdef __APPLE__
#include <assert.h>

#warning PosixTimer is not implimented in MacOS X
#define timer_create(x,y,z)      (assert(!"timer_create is not implemented"), -1)
#define timer_settime(x,y,z,u)   (assert(!"timer_settime is not implemented"), -1)
#define clock_getres(x,y)        (assert(!"clock_getres is not implemented"), -1)
#define timer_delete(x)          (assert(!"timer_delete is not implemented"), -1)
#define timer_getoverrun(x)      (assert(!"timer_getoverrun is not implemented"), -1)
#define SIGRTMIN 0
#define SIGRTMAX 0

#define si_ptr    si_addr

struct itv
{
    int tv_sec;
    int tv_nsec;
};

struct itimerspec
{
   struct itv it_value;
   struct itv it_interval;
};

#endif

// APPLICATION INCLUDES
#include "mp/MpMMTimerPosix.h"

#define TIMER_SIGNAL    SIGRTMIN
#ifdef ANDROID // [
#  define TIMER_SIGTERM SIGCONT
#else // ANDROID ][
#  define TIMER_SIGTERM SIGTERM
#endif // ANDROID ]

const char * const MpMMTimerPosix::TYPE = "POSIX Timer";

MpMMTimerPosix::PosixSignalReg gPosixTimerReg(TIMER_SIGNAL, MpMMTimerPosix::signalHandler);

MpMMTimerPosix::MpMMTimerPosix(MpMMTimer::MMTimerType type)
: MpMMTimer(type)
, mbTimerStarted(FALSE)
{
   if (mTimerType == Linear)
   {
      int res = sem_init(&mSyncSemaphore, 0, 0);
      assert( res == 0);
   }

   sem_init(&mIoSem, 0, 0);

   int res = pthread_create(&mThread, NULL, threadIoWrapper, this);
   assert(res == 0);

   sem_wait(&mIoSem);
}

MpMMTimerPosix::~MpMMTimerPosix()
{
   if (mbTimerStarted)
      stop();

   if (mTimerType == Linear)
   {
      sem_destroy(&mSyncSemaphore);
   }

   sem_destroy(&mIoSem);

   pthread_kill(mThread, TIMER_SIGTERM);
#ifndef ANDROID // [
   // Under Android this leads to hans. Not sure why.
   pthread_join(mThread, NULL);
#endif // ANDROID ]
}

OsStatus MpMMTimerPosix::run(unsigned usecPeriodic)
{
  OsStatus status = OS_SUCCESS;
   if(mbTimerStarted)
   {
      return OS_INVALID_STATE;
   }

   struct sigevent evnt;

   evnt.sigev_notify = SIGEV_SIGNAL;
   evnt.sigev_value.sival_ptr = this;
   evnt.sigev_signo = TIMER_SIGNAL;

   int res = timer_create(CLOCK_REALTIME, &evnt, &mTimer);
   if (res != 0)
   {
      OsSysLog::add(FAC_MP, PRI_WARNING,
         "Couldn't create POSIX timer");
      return OS_INVALID_ARGUMENT;
   }

   struct itimerspec ts;
   ts.it_value.tv_sec = usecPeriodic / 1000000;
   ts.it_value.tv_nsec = (usecPeriodic % 1000000) * 1000;
   ts.it_interval.tv_sec = usecPeriodic / 1000000;
   ts.it_interval.tv_nsec = (usecPeriodic % 1000000) * 1000;

//CLOCK_REALTIME //TIMER_ABSTIME
   res = timer_settime(mTimer, CLOCK_REALTIME, &ts, NULL);
   if (res != 0)
   {
      OsSysLog::add(FAC_MP, PRI_WARNING,
         "Couldn't set POSIX timer with %d us period",
         usecPeriodic);

      return OS_INVALID_ARGUMENT;
   }

   mbTimerStarted = TRUE;
   return status;
}

OsStatus MpMMTimerPosix::stop()
{
   if (mbTimerStarted)
   {
      struct itimerspec ts;
      ts.it_value.tv_sec = 0;
      ts.it_value.tv_nsec = 0;
      ts.it_interval.tv_sec = 0;
      ts.it_interval.tv_nsec = 0;
      timer_settime(mTimer, CLOCK_REALTIME, &ts, NULL);

      int res = timer_delete(mTimer);
      assert (res == 0);

      mbTimerStarted = FALSE;

      return OS_SUCCESS;
   }
   else
      return OS_INVALID_STATE;
}

OsStatus MpMMTimerPosix::getPeriodRange(unsigned* pMinUSecs,
                                        unsigned* pMaxUSecs)
{
   if (pMaxUSecs)
      *pMaxUSecs = INT_MAX;

   if (pMinUSecs)
      return getResolution(*pMinUSecs);

   return OS_SUCCESS;
}

OsStatus MpMMTimerPosix::getResolution(unsigned& resolution)
{
   struct timespec ts;
   int res = clock_getres(CLOCK_REALTIME, &ts);
   if (res != 0)
     return OS_FAILED;

   resolution = ts.tv_nsec / 1000;
   if (resolution == 0)
      resolution++;

   return OS_SUCCESS;
}

OsStatus MpMMTimerPosix::waitForNextTick()
{
   if(mTimerType != Linear)
   {
      return OS_INVALID_STATE;
   }

   if(mbTimerStarted == FALSE)
   {
      OsSysLog::add(FAC_MP, PRI_ERR,
                    "MpMMTimerPosix::waitForNextTick "
                    "- Timer not started or timer not initialized!");
      return OS_FAILED;
   }

   int res = sem_wait(&mSyncSemaphore);
   if (res == 0)
      return OS_SUCCESS;

   return OS_FAILED;
}

OsTime MpMMTimerPosix::getAbsFireTime() const
{
   return OsTime::OS_INFINITY;
}

OsStatus MpMMTimerPosix::setNotification(OsNotification* notification)
{
   mpNotification = notification;
   return OS_SUCCESS;
}

void MpMMTimerPosix::callback()
{
   int overruns = timer_getoverrun(mTimer);
   do
   {
      if (mTimerType == Notification)
      {
          if(mpNotification != NULL)
          {
            // Then signal it to indicate a tick.
            mpNotification->signal((intptr_t)this);
          }
      }
      else
      {
          sem_post(&mSyncSemaphore);
      }
   } while (overruns-- > 0);
}

void* MpMMTimerPosix::threadIoWrapper(void* arg)
{
   MpMMTimerPosix* obj = (MpMMTimerPosix*)arg;

   sigset_t mask, fmask;
   sigemptyset(&mask);
   sigaddset (&mask, gPosixTimerReg.getSignalNum());
   sigaddset (&mask, TIMER_SIGTERM);

   sigfillset(&fmask);
   pthread_sigmask (SIG_SETMASK, &fmask, NULL);

   struct sched_param realtime;
   if (geteuid() == 0)
   {
       realtime.sched_priority = sched_get_priority_max(SCHED_FIFO);
       pthread_setschedparam(pthread_self(), SCHED_FIFO, &realtime);
   }

   int signum;

   sem_post(&obj->mIoSem);

   for(;;)
   {
      sigwait(&mask, &signum);
      if (signum == TIMER_SIGTERM)
      {
#ifdef ANDROID // [
         LOGD("threadIoWrapper received signal TIMER_SIGTERM\n");
#endif // ANDROID ]
         return NULL;
      }
      assert(signum == gPosixTimerReg.getSignalNum());
#ifdef ANDROID // [
      if (signum == gPosixTimerReg.getSignalNum())
      {
         //LOGD("threadIoWrapper received signal gPosixTimerReg.getSignalNum()\n");
      }
      else
      {
         LOGD("threadIoWrapper unknown signal: %d\n", signum);
      }
#endif // ANDROID ]

      obj->callback();
   }
}

void MpMMTimerPosix::signalHandler(int signum, siginfo_t *siginfo, void *context)
{
   assert(siginfo->si_signo == TIMER_SIGNAL);

   MpMMTimerPosix* object = (MpMMTimerPosix*)siginfo->si_ptr;
   object->callback();
}

MpMMTimerPosix::PosixSignalReg* MpMMTimerPosix::getSignalDescriptor()
{
   return &gPosixTimerReg;
}

MpMMTimerPosix::PosixSignalReg::PosixSignalReg(int sigNum, void (*sa)(int, siginfo_t *, void *))
: mSigNum(sigNum)
{
   sigset_t mask;
   sigemptyset(&mask);
   sigaddset(&mask, mSigNum);

   sigemptyset (&mBlockSigMask);
   sigaddset (&mBlockSigMask, mSigNum);

   // Block this signal for all the threads by defalut
   // Interested in signal thread should use unblockThreadSig() to allow to catch it
   sigprocmask (SIG_BLOCK, &mBlockSigMask, NULL);
/*
   struct sigaction act;
   act.sa_sigaction = sa;
   act.sa_flags = SA_SIGINFO | SA_RESTART;
   act.sa_mask = mask;

   int res = sigaction(mSigNum, &act, &mOldAction);
   assert (res == 0);
*/
}

int MpMMTimerPosix::PosixSignalReg::getSignalNum() const
{
   return mSigNum;
}

int MpMMTimerPosix::PosixSignalReg::blockThreadSig()
{
   return pthread_sigmask (SIG_BLOCK, &mBlockSigMask, NULL);
}

int MpMMTimerPosix::PosixSignalReg::unblockThreadSig()
{
   return pthread_sigmask (SIG_UNBLOCK, &mBlockSigMask, NULL);
}

MpMMTimerPosix::PosixSignalReg::~PosixSignalReg()
{
   int res = sigaction(mSigNum, &mOldAction, NULL);
   assert (res == 0);

   sigprocmask (SIG_UNBLOCK, &mBlockSigMask, NULL);
}
<commit_msg>sipXmediaLib: Fix compilation of MpMMTimerPosix.cpp under Android.<commit_after>//
// Copyright (C) 2009 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2009 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

// Author: Sergey Kostanbaev <sergey DOT kostanbaev AT SIPez DOT com>

// SYSTEM INCLUDES
#include <os/OsIntTypes.h>
#include <os/OsSysLog.h>

#include <sched.h>
#include <unistd.h>
#include <sys/types.h>

#ifdef __APPLE__
#include <assert.h>

#warning PosixTimer is not implimented in MacOS X
#define timer_create(x,y,z)      (assert(!"timer_create is not implemented"), -1)
#define timer_settime(x,y,z,u)   (assert(!"timer_settime is not implemented"), -1)
#define clock_getres(x,y)        (assert(!"clock_getres is not implemented"), -1)
#define timer_delete(x)          (assert(!"timer_delete is not implemented"), -1)
#define timer_getoverrun(x)      (assert(!"timer_getoverrun is not implemented"), -1)
#define SIGRTMIN 0
#define SIGRTMAX 0

#define si_ptr    si_addr

struct itv
{
    int tv_sec;
    int tv_nsec;
};

struct itimerspec
{
   struct itv it_value;
   struct itv it_interval;
};

#endif

// APPLICATION INCLUDES
#include "mp/MpMMTimerPosix.h"

#define TIMER_SIGNAL    SIGRTMIN
#ifdef ANDROID // [
#  define TIMER_SIGTERM SIGCONT
#else // ANDROID ][
#  define TIMER_SIGTERM SIGTERM
#endif // ANDROID ]

const char * const MpMMTimerPosix::TYPE = "POSIX Timer";

MpMMTimerPosix::PosixSignalReg gPosixTimerReg(TIMER_SIGNAL, MpMMTimerPosix::signalHandler);

MpMMTimerPosix::MpMMTimerPosix(MpMMTimer::MMTimerType type)
: MpMMTimer(type)
, mbTimerStarted(FALSE)
{
   if (mTimerType == Linear)
   {
      int res = sem_init(&mSyncSemaphore, 0, 0);
      assert( res == 0);
   }

   sem_init(&mIoSem, 0, 0);

   int res = pthread_create(&mThread, NULL, threadIoWrapper, this);
   assert(res == 0);

   sem_wait(&mIoSem);
}

MpMMTimerPosix::~MpMMTimerPosix()
{
   if (mbTimerStarted)
      stop();

   if (mTimerType == Linear)
   {
      sem_destroy(&mSyncSemaphore);
   }

   sem_destroy(&mIoSem);

   pthread_kill(mThread, TIMER_SIGTERM);
#ifndef ANDROID // [
   // Under Android this leads to hans. Not sure why.
   pthread_join(mThread, NULL);
#endif // ANDROID ]
}

OsStatus MpMMTimerPosix::run(unsigned usecPeriodic)
{
  OsStatus status = OS_SUCCESS;
   if(mbTimerStarted)
   {
      return OS_INVALID_STATE;
   }

   struct sigevent evnt;

   evnt.sigev_notify = SIGEV_SIGNAL;
   evnt.sigev_value.sival_ptr = this;
   evnt.sigev_signo = TIMER_SIGNAL;

   int res = timer_create(CLOCK_REALTIME, &evnt, &mTimer);
   if (res != 0)
   {
      OsSysLog::add(FAC_MP, PRI_WARNING,
         "Couldn't create POSIX timer");
      return OS_INVALID_ARGUMENT;
   }

   struct itimerspec ts;
   ts.it_value.tv_sec = usecPeriodic / 1000000;
   ts.it_value.tv_nsec = (usecPeriodic % 1000000) * 1000;
   ts.it_interval.tv_sec = usecPeriodic / 1000000;
   ts.it_interval.tv_nsec = (usecPeriodic % 1000000) * 1000;

//CLOCK_REALTIME //TIMER_ABSTIME
   res = timer_settime(mTimer, CLOCK_REALTIME, &ts, NULL);
   if (res != 0)
   {
      OsSysLog::add(FAC_MP, PRI_WARNING,
         "Couldn't set POSIX timer with %d us period",
         usecPeriodic);

      return OS_INVALID_ARGUMENT;
   }

   mbTimerStarted = TRUE;
   return status;
}

OsStatus MpMMTimerPosix::stop()
{
   if (mbTimerStarted)
   {
      struct itimerspec ts;
      ts.it_value.tv_sec = 0;
      ts.it_value.tv_nsec = 0;
      ts.it_interval.tv_sec = 0;
      ts.it_interval.tv_nsec = 0;
      timer_settime(mTimer, CLOCK_REALTIME, &ts, NULL);

      int res = timer_delete(mTimer);
      assert (res == 0);

      mbTimerStarted = FALSE;

      return OS_SUCCESS;
   }
   else
      return OS_INVALID_STATE;
}

OsStatus MpMMTimerPosix::getPeriodRange(unsigned* pMinUSecs,
                                        unsigned* pMaxUSecs)
{
   if (pMaxUSecs)
      *pMaxUSecs = INT_MAX;

   if (pMinUSecs)
      return getResolution(*pMinUSecs);

   return OS_SUCCESS;
}

OsStatus MpMMTimerPosix::getResolution(unsigned& resolution)
{
   struct timespec ts;
   int res = clock_getres(CLOCK_REALTIME, &ts);
   if (res != 0)
     return OS_FAILED;

   resolution = ts.tv_nsec / 1000;
   if (resolution == 0)
      resolution++;

   return OS_SUCCESS;
}

OsStatus MpMMTimerPosix::waitForNextTick()
{
   if(mTimerType != Linear)
   {
      return OS_INVALID_STATE;
   }

   if(mbTimerStarted == FALSE)
   {
      OsSysLog::add(FAC_MP, PRI_ERR,
                    "MpMMTimerPosix::waitForNextTick "
                    "- Timer not started or timer not initialized!");
      return OS_FAILED;
   }

   int res = sem_wait(&mSyncSemaphore);
   if (res == 0)
      return OS_SUCCESS;

   return OS_FAILED;
}

OsTime MpMMTimerPosix::getAbsFireTime() const
{
   return OsTime::OS_INFINITY;
}

OsStatus MpMMTimerPosix::setNotification(OsNotification* notification)
{
   mpNotification = notification;
   return OS_SUCCESS;
}

void MpMMTimerPosix::callback()
{
   int overruns = timer_getoverrun(mTimer);
   do
   {
      if (mTimerType == Notification)
      {
          if(mpNotification != NULL)
          {
            // Then signal it to indicate a tick.
            mpNotification->signal((intptr_t)this);
          }
      }
      else
      {
          sem_post(&mSyncSemaphore);
      }
   } while (overruns-- > 0);
}

void* MpMMTimerPosix::threadIoWrapper(void* arg)
{
   MpMMTimerPosix* obj = (MpMMTimerPosix*)arg;

   sigset_t mask, fmask;
   sigemptyset(&mask);
   sigaddset (&mask, gPosixTimerReg.getSignalNum());
   sigaddset (&mask, TIMER_SIGTERM);

   sigfillset(&fmask);
   pthread_sigmask (SIG_SETMASK, &fmask, NULL);

   struct sched_param realtime;
   if (geteuid() == 0)
   {
       realtime.sched_priority = sched_get_priority_max(SCHED_FIFO);
       pthread_setschedparam(pthread_self(), SCHED_FIFO, &realtime);
   }

   int signum;

   sem_post(&obj->mIoSem);

   for(;;)
   {
      sigwait(&mask, &signum);
      if (signum == TIMER_SIGTERM)
      {
#ifdef ANDROID // [
         OsSysLog::add(FAC_MP, PRI_DEBUG, "threadIoWrapper received signal TIMER_SIGTERM\n");
#endif // ANDROID ]
         return NULL;
      }
      assert(signum == gPosixTimerReg.getSignalNum());
#ifdef ANDROID // [
      if (signum == gPosixTimerReg.getSignalNum())
      {
         //OsSysLog::add(FAC_MP, PRI_DEBUG, "threadIoWrapper received signal gPosixTimerReg.getSignalNum()\n");
      }
      else
      {
         OsSysLog::add(FAC_MP, PRI_WARNING, "threadIoWrapper unknown signal: %d\n", signum);
      }
#endif // ANDROID ]

      obj->callback();
   }
}

void MpMMTimerPosix::signalHandler(int signum, siginfo_t *siginfo, void *context)
{
   assert(siginfo->si_signo == TIMER_SIGNAL);

   MpMMTimerPosix* object = (MpMMTimerPosix*)siginfo->si_ptr;
   object->callback();
}

MpMMTimerPosix::PosixSignalReg* MpMMTimerPosix::getSignalDescriptor()
{
   return &gPosixTimerReg;
}

MpMMTimerPosix::PosixSignalReg::PosixSignalReg(int sigNum, void (*sa)(int, siginfo_t *, void *))
: mSigNum(sigNum)
{
   sigset_t mask;
   sigemptyset(&mask);
   sigaddset(&mask, mSigNum);

   sigemptyset (&mBlockSigMask);
   sigaddset (&mBlockSigMask, mSigNum);

   // Block this signal for all the threads by defalut
   // Interested in signal thread should use unblockThreadSig() to allow to catch it
   sigprocmask (SIG_BLOCK, &mBlockSigMask, NULL);
/*
   struct sigaction act;
   act.sa_sigaction = sa;
   act.sa_flags = SA_SIGINFO | SA_RESTART;
   act.sa_mask = mask;

   int res = sigaction(mSigNum, &act, &mOldAction);
   assert (res == 0);
*/
}

int MpMMTimerPosix::PosixSignalReg::getSignalNum() const
{
   return mSigNum;
}

int MpMMTimerPosix::PosixSignalReg::blockThreadSig()
{
   return pthread_sigmask (SIG_BLOCK, &mBlockSigMask, NULL);
}

int MpMMTimerPosix::PosixSignalReg::unblockThreadSig()
{
   return pthread_sigmask (SIG_UNBLOCK, &mBlockSigMask, NULL);
}

MpMMTimerPosix::PosixSignalReg::~PosixSignalReg()
{
   int res = sigaction(mSigNum, &mOldAction, NULL);
   assert (res == 0);

   sigprocmask (SIG_UNBLOCK, &mBlockSigMask, NULL);
}
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/engine/config.h"
#include "sky/engine/tonic/dart_gc_controller.h"

#include "dart/runtime/include/dart_api.h"
#include "sky/engine/tonic/dart_gc_context.h"
#include "sky/engine/tonic/dart_gc_visitor.h"
#include "sky/engine/tonic/dart_wrappable.h"

namespace blink {
namespace {

DartGCContext* g_gc_context = nullptr;

DartWrappable* GetWrappable(intptr_t* fields) {
  return reinterpret_cast<DartWrappable*>(fields[DartWrappable::kPeerIndex]);
}

void Visit(void* isolate_callback_data,
           Dart_WeakPersistentHandle handle,
           intptr_t native_field_count,
           intptr_t* native_fields) {
  if (!native_field_count)
    return;
  DCHECK(native_field_count == DartWrappable::kNumberOfNativeFields);
  DartGCVisitor visitor(g_gc_context);
  GetWrappable(native_fields)->AcceptDartGCVisitor(visitor);
}

}  // namespace

void DartGCPrologue() {
  Dart_EnterScope();
  DCHECK(!g_gc_context);
  g_gc_context = new DartGCContext();
  Dart_VisitPrologueWeakHandles(Visit);
}

void DartGCEpilogue() {
  delete g_gc_context;
  g_gc_context = nullptr;
  Dart_ExitScope();
}

}  // namespace blink
<commit_msg>Add tracing for major GC in Sky<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/engine/config.h"
#include "sky/engine/tonic/dart_gc_controller.h"

#include "base/trace_event/trace_event.h"
#include "dart/runtime/include/dart_api.h"
#include "sky/engine/tonic/dart_gc_context.h"
#include "sky/engine/tonic/dart_gc_visitor.h"
#include "sky/engine/tonic/dart_wrappable.h"

namespace blink {
namespace {

DartGCContext* g_gc_context = nullptr;

DartWrappable* GetWrappable(intptr_t* fields) {
  return reinterpret_cast<DartWrappable*>(fields[DartWrappable::kPeerIndex]);
}

void Visit(void* isolate_callback_data,
           Dart_WeakPersistentHandle handle,
           intptr_t native_field_count,
           intptr_t* native_fields) {
  if (!native_field_count)
    return;
  DCHECK(native_field_count == DartWrappable::kNumberOfNativeFields);
  DartGCVisitor visitor(g_gc_context);
  GetWrappable(native_fields)->AcceptDartGCVisitor(visitor);
}

}  // namespace

void DartGCPrologue() {
  TRACE_EVENT_ASYNC_BEGIN0("sky", "DartGC", 0);

  Dart_EnterScope();
  DCHECK(!g_gc_context);
  g_gc_context = new DartGCContext();
  Dart_VisitPrologueWeakHandles(Visit);
}

void DartGCEpilogue() {
  delete g_gc_context;
  g_gc_context = nullptr;
  Dart_ExitScope();

  TRACE_EVENT_ASYNC_END0("sky", "DartGC", 0);
}

}  // namespace blink
<|endoftext|>


<commit_before><commit_msg>Fixed bug when using transparent deco and opaque style.<commit_after><|endoftext|>