<commit_before>/**
 * @file    Special Purpose Strings Library: hash
 * @author  Daniel Evers
 * @brief   Hashing implementation to enable std::hash specialization
 * @license MIT
 *
 * The hashing function is MurmurHash3, taken thankfully from https://github.com/aappleby/smhasher.
 * It provides a 32 bit hash and a 128 bit hash, but no 64 bit version. This is handled by using
 * the 128 bit hash and cutting it to 64 bit.
 *
 * The implementation was slightly modified to meat current C++ standards, fix type safety issues
 * and meat this library's guidelines.
 */

#ifndef SPSL_HASH_HPP_
#define SPSL_HASH_HPP_

#include <cstdint>
#include <cstring>

namespace spsl
{
namespace hash
{
namespace murmurhash3
{
// Copied from https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp with
// small adaptations for C++. Thanks!

//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain.

// Note - The x86 and x64 versions do _not_ produce the same results, as the
// algorithms are optimized for their respective platforms. You can still
// compile and run any of them on any platform, but your performance with the
// non-native version will be less than optimal.

//-----------------------------------------------------------------------------
// Platform-specific functions and macros

// Microsoft Visual Studio

#if defined(_MSC_VER)

#define SPSL_FORCE_INLINE __forceinline

#include <cstdlib>

#define SPSL_ROTL32(x, y) _rotl(x, y)
#define SPSL_ROTL64(x, y) _rotl64(x, y)

#define SPSL_BIG_CONSTANT(x) (x)

// Other compilers

#else // defined(_MSC_VER)

#define SPSL_FORCE_INLINE inline __attribute__((always_inline))

inline uint32_t rotl32(uint32_t x, int8_t r)
{
    return (x << r) | (x >> (32 - r));
}

inline uint64_t rotl64(uint64_t x, int8_t r)
{
    return (x << r) | (x >> (64 - r));
}

#define SPSL_ROTL32(x, y) rotl32(x, y)
#define SPSL_ROTL64(x, y) rotl64(x, y)

#define SPSL_BIG_CONSTANT(x) (x##LLU)

#endif // !defined(_MSC_VER)

//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here

/*
 * For SPSL/C++, we need aligned memory access - otherwise we run into undefined
 * behavior (due to the reinterpret_cast's below, and it's unclear if C-style
 * casts are better).
 * Benchmarks show that the memcpy version is slightly faster for 64 bit and has
 * no difference on 32 bit. So why not...?
 */

SPSL_FORCE_INLINE uint32_t getblock32(const uint8_t* p, uint32_t i)
{
    uint32_t result;
    memcpy(&result, p + i * sizeof(result), sizeof(result));
    return result;
}

SPSL_FORCE_INLINE uint64_t getblock64(const uint8_t* p, std::size_t i)
{
    uint64_t result;
    memcpy(&result, p + i * sizeof(result), sizeof(result));
    return result;
}

//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche

SPSL_FORCE_INLINE uint32_t fmix32(uint32_t h)
{
    h ^= h >> 16;
    h *= 0x85ebca6b;
    h ^= h >> 13;
    h *= 0xc2b2ae35;
    h ^= h >> 16;

    return h;
}

//----------

SPSL_FORCE_INLINE uint64_t fmix64(uint64_t k)
{
    k ^= k >> 33;
    k *= SPSL_BIG_CONSTANT(0xff51afd7ed558ccd);
    k ^= k >> 33;
    k *= SPSL_BIG_CONSTANT(0xc4ceb9fe1a85ec53);
    k ^= k >> 33;

    return k;
}

//-----------------------------------------------------------------------------

inline void MurmurHash3_x86_32(const uint8_t* data, const uint32_t len, uint32_t seed,
                               uint32_t& out)
{
    const uint32_t nblocks = len / 4;

    uint32_t h1 = seed;

    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;

    //----------
    // body

    for (uint32_t i = 0; i < nblocks; ++i)
    {
        uint32_t k1 = getblock32(data, i);

        k1 *= c1;
        k1 = SPSL_ROTL32(k1, 15);
        k1 *= c2;

        h1 ^= k1;
        h1 = SPSL_ROTL32(h1, 13);
        h1 = h1 * 5 + 0xe6546b64;
    }

    //----------
    // tail

    const uint8_t* tail = (data + nblocks * 4);

    uint32_t k1 = 0;

    switch (len & 3)
    {
    case 3:
        k1 ^= static_cast<uint32_t>(tail[2] << 16);
    /* no break */
    case 2:
        k1 ^= static_cast<uint32_t>(tail[1] << 8);
    /* no break */
    case 1:
        k1 ^= tail[0];
        k1 *= c1;
        k1 = SPSL_ROTL32(k1, 15);
        k1 *= c2;
        h1 ^= k1;
    };

    //----------
    // finalization

    h1 ^= len;

    h1 = fmix32(h1);

    out = h1;
}

//-----------------------------------------------------------------------------

inline void MurmurHash3_x64_128(const uint8_t* data, const std::size_t len, const uint32_t seed,
                                uint64_t& out1, uint64_t& out2)
{
    const std::size_t nblocks = len / 16;

    uint64_t h1 = seed;
    uint64_t h2 = seed;

    const uint64_t c1 = SPSL_BIG_CONSTANT(0x87c37b91114253d5);
    const uint64_t c2 = SPSL_BIG_CONSTANT(0x4cf5ad432745937f);

    //----------
    // body

    for (std::size_t i = 0; i < nblocks; i++)
    {
        uint64_t k1 = getblock64(data, i * 2 + 0);
        uint64_t k2 = getblock64(data, i * 2 + 1);

        k1 *= c1;
        k1 = SPSL_ROTL64(k1, 31);
        k1 *= c2;
        h1 ^= k1;

        h1 = SPSL_ROTL64(h1, 27);
        h1 += h2;
        h1 = h1 * 5 + 0x52dce729;

        k2 *= c2;
        k2 = SPSL_ROTL64(k2, 33);
        k2 *= c1;
        h2 ^= k2;

        h2 = SPSL_ROTL64(h2, 31);
        h2 += h1;
        h2 = h2 * 5 + 0x38495ab5;
    }

    //----------
    // tail

    const uint8_t* tail = (data + nblocks * 16);

    uint64_t k1 = 0;
    uint64_t k2 = 0;

    switch (len & 15)
    {
    case 15:
        k2 ^= (static_cast<uint64_t>(tail[14])) << 48;
    /* no break */
    case 14:
        k2 ^= (static_cast<uint64_t>(tail[13])) << 40;
    /* no break */
    case 13:
        k2 ^= (static_cast<uint64_t>(tail[12])) << 32;
    /* no break */
    case 12:
        k2 ^= (static_cast<uint64_t>(tail[11])) << 24;
    /* no break */
    case 11:
        k2 ^= (static_cast<uint64_t>(tail[10])) << 16;
    /* no break */
    case 10:
        k2 ^= (static_cast<uint64_t>(tail[9])) << 8;
    /* no break */
    case 9:
        k2 ^= (static_cast<uint64_t>(tail[8])) << 0;
        k2 *= c2;
        k2 = SPSL_ROTL64(k2, 33);
        k2 *= c1;
        h2 ^= k2;
    /* no break */

    case 8:
        k1 ^= (static_cast<uint64_t>(tail[7])) << 56;
    /* no break */
    case 7:
        k1 ^= (static_cast<uint64_t>(tail[6])) << 48;
    /* no break */
    case 6:
        k1 ^= (static_cast<uint64_t>(tail[5])) << 40;
    /* no break */
    case 5:
        k1 ^= (static_cast<uint64_t>(tail[4])) << 32;
    /* no break */
    case 4:
        k1 ^= (static_cast<uint64_t>(tail[3])) << 24;
    /* no break */
    case 3:
        k1 ^= (static_cast<uint64_t>(tail[2])) << 16;
    /* no break */
    case 2:
        k1 ^= (static_cast<uint64_t>(tail[1])) << 8;
    /* no break */
    case 1:
        k1 ^= (static_cast<uint64_t>(tail[0])) << 0;
        k1 *= c1;
        k1 = SPSL_ROTL64(k1, 31);
        k1 *= c2;
        h1 ^= k1;
    };

    //----------
    // finalization

    h1 ^= len;
    h2 ^= len;

    h1 += h2;
    h2 += h1;

    h1 = fmix64(h1);
    h2 = fmix64(h2);

    h1 += h2;
    h2 += h1;

    out1 = h1;
    out2 = h2;
}

//-----------------------------------------------------------------------------
}

using std::size_t;

template <size_t HashLength>
size_t hash_impl(const void* buffer, size_t len, uint32_t seed = 0);

/**
 * 32 bit hash function: This function shall be called on 32 bit x86.
 * @param[in] buffer        the data to hash
 * @param[in] len           the number of bytes in the buffer
 * @param[in] seed          optional hash seed (warning: changing it alters the hash!)
 * @return 32 bit hash value
 */
template <>
inline size_t hash_impl<32>(const void* buffer, size_t len, uint32_t seed)
{
    uint32_t result = 0;
    murmurhash3::MurmurHash3_x86_32(reinterpret_cast<const uint8_t*>(buffer),
                                    static_cast<uint32_t>(len), seed, result);
    return result;
}

/**
 * 64 bit hash function: This function shall be called on 64 bit x86_64.
 * @param[in] buffer        the data to hash
 * @param[in] len           the number of bytes in the buffer
 * @param[in] seed          optional hash seed (warning: changing it alters the hash!)
 * @return 64 bit hash value
 */
template <>
inline size_t hash_impl<64>(const void* buffer, size_t len, uint32_t seed)
{
    uint64_t result[2];
    murmurhash3::MurmurHash3_x64_128(reinterpret_cast<const uint8_t*>(buffer), len, seed, result[0],
                                     result[1]);

    // ignore what we don't need...
    return result[0];
}

/**
 * System-independent hash function: Call this function to hash something. Based on the current
 * platform, the matching hash function is called.
 * @param[in] buffer        the data to hash
 * @param[in] len           the number of bytes in the buffer
 * @param[in] seed          optional hash seed (warning: changing it alters the hash!)
 * @return the calculated hash
 */
inline std::size_t hash_impl(const void* buffer, size_t len, uint32_t seed = 0)
{
    return hash_impl<sizeof(size_t) * 8>(buffer, len, seed);
}
}
}

#endif /* SPSL_HASH_HPP_ */
<commit_msg>Fix missing size_t cast for Windows.<commit_after>/**
 * @file    Special Purpose Strings Library: hash
 * @author  Daniel Evers
 * @brief   Hashing implementation to enable std::hash specialization
 * @license MIT
 *
 * The hashing function is MurmurHash3, taken thankfully from https://github.com/aappleby/smhasher.
 * It provides a 32 bit hash and a 128 bit hash, but no 64 bit version. This is handled by using
 * the 128 bit hash and cutting it to 64 bit.
 *
 * The implementation was slightly modified to meat current C++ standards, fix type safety issues
 * and meat this library's guidelines.
 */

#ifndef SPSL_HASH_HPP_
#define SPSL_HASH_HPP_

#include <cstdint>
#include <cstring>

namespace spsl
{
namespace hash
{
namespace murmurhash3
{
// Copied from https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp with
// small adaptations for C++. Thanks!

//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain.

// Note - The x86 and x64 versions do _not_ produce the same results, as the
// algorithms are optimized for their respective platforms. You can still
// compile and run any of them on any platform, but your performance with the
// non-native version will be less than optimal.

//-----------------------------------------------------------------------------
// Platform-specific functions and macros

// Microsoft Visual Studio

#if defined(_MSC_VER)

#define SPSL_FORCE_INLINE __forceinline

#include <cstdlib>

#define SPSL_ROTL32(x, y) _rotl(x, y)
#define SPSL_ROTL64(x, y) _rotl64(x, y)

#define SPSL_BIG_CONSTANT(x) (x)

// Other compilers

#else // defined(_MSC_VER)

#define SPSL_FORCE_INLINE inline __attribute__((always_inline))

inline uint32_t rotl32(uint32_t x, int8_t r)
{
    return (x << r) | (x >> (32 - r));
}

inline uint64_t rotl64(uint64_t x, int8_t r)
{
    return (x << r) | (x >> (64 - r));
}

#define SPSL_ROTL32(x, y) rotl32(x, y)
#define SPSL_ROTL64(x, y) rotl64(x, y)

#define SPSL_BIG_CONSTANT(x) (x##LLU)

#endif // !defined(_MSC_VER)

//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here

/*
 * For SPSL/C++, we need aligned memory access - otherwise we run into undefined
 * behavior (due to the reinterpret_cast's below, and it's unclear if C-style
 * casts are better).
 * Benchmarks show that the memcpy version is slightly faster for 64 bit and has
 * no difference on 32 bit. So why not...?
 */

SPSL_FORCE_INLINE uint32_t getblock32(const uint8_t* p, uint32_t i)
{
    uint32_t result;
    memcpy(&result, p + i * sizeof(result), sizeof(result));
    return result;
}

SPSL_FORCE_INLINE uint64_t getblock64(const uint8_t* p, std::size_t i)
{
    uint64_t result;
    memcpy(&result, p + i * sizeof(result), sizeof(result));
    return result;
}

//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche

SPSL_FORCE_INLINE uint32_t fmix32(uint32_t h)
{
    h ^= h >> 16;
    h *= 0x85ebca6b;
    h ^= h >> 13;
    h *= 0xc2b2ae35;
    h ^= h >> 16;

    return h;
}

//----------

SPSL_FORCE_INLINE uint64_t fmix64(uint64_t k)
{
    k ^= k >> 33;
    k *= SPSL_BIG_CONSTANT(0xff51afd7ed558ccd);
    k ^= k >> 33;
    k *= SPSL_BIG_CONSTANT(0xc4ceb9fe1a85ec53);
    k ^= k >> 33;

    return k;
}

//-----------------------------------------------------------------------------

inline void MurmurHash3_x86_32(const uint8_t* data, const uint32_t len, uint32_t seed,
                               uint32_t& out)
{
    const uint32_t nblocks = len / 4;

    uint32_t h1 = seed;

    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;

    //----------
    // body

    for (uint32_t i = 0; i < nblocks; ++i)
    {
        uint32_t k1 = getblock32(data, i);

        k1 *= c1;
        k1 = SPSL_ROTL32(k1, 15);
        k1 *= c2;

        h1 ^= k1;
        h1 = SPSL_ROTL32(h1, 13);
        h1 = h1 * 5 + 0xe6546b64;
    }

    //----------
    // tail

    const uint8_t* tail = (data + nblocks * 4);

    uint32_t k1 = 0;

    switch (len & 3)
    {
    case 3:
        k1 ^= static_cast<uint32_t>(tail[2] << 16);
    /* no break */
    case 2:
        k1 ^= static_cast<uint32_t>(tail[1] << 8);
    /* no break */
    case 1:
        k1 ^= tail[0];
        k1 *= c1;
        k1 = SPSL_ROTL32(k1, 15);
        k1 *= c2;
        h1 ^= k1;
    };

    //----------
    // finalization

    h1 ^= len;

    h1 = fmix32(h1);

    out = h1;
}

//-----------------------------------------------------------------------------

inline void MurmurHash3_x64_128(const uint8_t* data, const std::size_t len, const uint32_t seed,
                                uint64_t& out1, uint64_t& out2)
{
    const std::size_t nblocks = len / 16;

    uint64_t h1 = seed;
    uint64_t h2 = seed;

    const uint64_t c1 = SPSL_BIG_CONSTANT(0x87c37b91114253d5);
    const uint64_t c2 = SPSL_BIG_CONSTANT(0x4cf5ad432745937f);

    //----------
    // body

    for (std::size_t i = 0; i < nblocks; i++)
    {
        uint64_t k1 = getblock64(data, i * 2 + 0);
        uint64_t k2 = getblock64(data, i * 2 + 1);

        k1 *= c1;
        k1 = SPSL_ROTL64(k1, 31);
        k1 *= c2;
        h1 ^= k1;

        h1 = SPSL_ROTL64(h1, 27);
        h1 += h2;
        h1 = h1 * 5 + 0x52dce729;

        k2 *= c2;
        k2 = SPSL_ROTL64(k2, 33);
        k2 *= c1;
        h2 ^= k2;

        h2 = SPSL_ROTL64(h2, 31);
        h2 += h1;
        h2 = h2 * 5 + 0x38495ab5;
    }

    //----------
    // tail

    const uint8_t* tail = (data + nblocks * 16);

    uint64_t k1 = 0;
    uint64_t k2 = 0;

    switch (len & 15)
    {
    case 15:
        k2 ^= (static_cast<uint64_t>(tail[14])) << 48;
    /* no break */
    case 14:
        k2 ^= (static_cast<uint64_t>(tail[13])) << 40;
    /* no break */
    case 13:
        k2 ^= (static_cast<uint64_t>(tail[12])) << 32;
    /* no break */
    case 12:
        k2 ^= (static_cast<uint64_t>(tail[11])) << 24;
    /* no break */
    case 11:
        k2 ^= (static_cast<uint64_t>(tail[10])) << 16;
    /* no break */
    case 10:
        k2 ^= (static_cast<uint64_t>(tail[9])) << 8;
    /* no break */
    case 9:
        k2 ^= (static_cast<uint64_t>(tail[8])) << 0;
        k2 *= c2;
        k2 = SPSL_ROTL64(k2, 33);
        k2 *= c1;
        h2 ^= k2;
    /* no break */

    case 8:
        k1 ^= (static_cast<uint64_t>(tail[7])) << 56;
    /* no break */
    case 7:
        k1 ^= (static_cast<uint64_t>(tail[6])) << 48;
    /* no break */
    case 6:
        k1 ^= (static_cast<uint64_t>(tail[5])) << 40;
    /* no break */
    case 5:
        k1 ^= (static_cast<uint64_t>(tail[4])) << 32;
    /* no break */
    case 4:
        k1 ^= (static_cast<uint64_t>(tail[3])) << 24;
    /* no break */
    case 3:
        k1 ^= (static_cast<uint64_t>(tail[2])) << 16;
    /* no break */
    case 2:
        k1 ^= (static_cast<uint64_t>(tail[1])) << 8;
    /* no break */
    case 1:
        k1 ^= (static_cast<uint64_t>(tail[0])) << 0;
        k1 *= c1;
        k1 = SPSL_ROTL64(k1, 31);
        k1 *= c2;
        h1 ^= k1;
    };

    //----------
    // finalization

    h1 ^= len;
    h2 ^= len;

    h1 += h2;
    h2 += h1;

    h1 = fmix64(h1);
    h2 = fmix64(h2);

    h1 += h2;
    h2 += h1;

    out1 = h1;
    out2 = h2;
}

//-----------------------------------------------------------------------------
}

using std::size_t;

template <size_t HashLength>
size_t hash_impl(const void* buffer, size_t len, uint32_t seed = 0);

/**
 * 32 bit hash function: This function shall be called on 32 bit x86.
 * @param[in] buffer        the data to hash
 * @param[in] len           the number of bytes in the buffer
 * @param[in] seed          optional hash seed (warning: changing it alters the hash!)
 * @return 32 bit hash value
 */
template <>
inline size_t hash_impl<32>(const void* buffer, size_t len, uint32_t seed)
{
    uint32_t result = 0;
    murmurhash3::MurmurHash3_x86_32(reinterpret_cast<const uint8_t*>(buffer),
                                    static_cast<uint32_t>(len), seed, result);
    return result;
}

/**
 * 64 bit hash function: This function shall be called on 64 bit x86_64.
 * @param[in] buffer        the data to hash
 * @param[in] len           the number of bytes in the buffer
 * @param[in] seed          optional hash seed (warning: changing it alters the hash!)
 * @return 64 bit hash value
 */
template <>
inline size_t hash_impl<64>(const void* buffer, size_t len, uint32_t seed)
{
    uint64_t result[2];
    murmurhash3::MurmurHash3_x64_128(reinterpret_cast<const uint8_t*>(buffer), len, seed, result[0],
                                     result[1]);

    // ignore what we don't need...
    return static_cast<size_t>(result[0]);
}

/**
 * System-independent hash function: Call this function to hash something. Based on the current
 * platform, the matching hash function is called.
 * @param[in] buffer        the data to hash
 * @param[in] len           the number of bytes in the buffer
 * @param[in] seed          optional hash seed (warning: changing it alters the hash!)
 * @return the calculated hash
 */
inline std::size_t hash_impl(const void* buffer, size_t len, uint32_t seed = 0)
{
    return hash_impl<sizeof(size_t) * 8>(buffer, len, seed);
}
}
}

#endif /* SPSL_HASH_HPP_ */
<|endoftext|>


<commit_before><commit_msg>Revert "remove unused SvRefBase constructor"<commit_after><|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file   meta.hpp
/// \author Serge Aleynikov
//----------------------------------------------------------------------------
/// \brief This file contains some generic metaprogramming functions.
//----------------------------------------------------------------------------
// Copyright (c) 2010 Serge Aleynikov <saleyn@gmail.com>
// Created: 2010-09-31
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#pragma once

#include <cstddef>

#include <type_traits>
#include <tuple>
#include <utility>

namespace utxx {

template <size_t N, size_t Base>
struct log {
    static const size_t value = 1 + log<N / Base, Base>::value;
};

template <size_t Base> struct log<1, Base> { static const size_t value = 0; };
template <size_t Base> struct log<0, Base>;

template <size_t N, size_t Power>
struct pow {
    static const size_t value = N * pow<N, Power - 1>::value;
};

template <size_t N>     struct pow<N, 0>        { static const size_t value = 1; };
template <size_t Power> struct pow<0, Power>    { static const size_t value = 0; };

/// Computes the smallest power of \a base equal or greater than number \a n.
template <size_t N, size_t Base>
class upper_power {
    static const size_t s_log = log<N,Base>::value;
    static const size_t s_pow = pow<Base,s_log>::value;
public:
    static const size_t value = s_pow == N ? N : s_pow*Base;
};

// We need specialisation of "upper_power" for N=0, because the log cannot be
// computed in that case (as required in the generic case above).  The result
// is 0 in this case (the corresp exponent of Base is "-oo")    (XXX: even if
// Base==0):
template<size_t Base>
class upper_power<0, Base> {
public:
     static const size_t value  = 0;
};

template <size_t N>
using upper_power2 = upper_power<N, 2>;

/// Given the size N and alignment size get the number of padding and aligned
/// space needed to hold the structure of N bytes.
template<int N, int Size>
class align {
    static const int multiplier = Size / N;
    static const int remainder  = Size % N;
public:
    static const int size       = remainder > 0 ? (multiplier+1) * N : Size;
    static const int padding    = size - Size;
};

/// Check if \a T and \a U are the same types by stripping T's ref and cv-qualifiers
/// \code
/// // All following expressions return true:
/// std::cout << std::boolalpha
///           << is_same_decayed<int,        int>::value  << '\n'
///           << is_same_decayed<int&,       int>::value  << '\n'
///           << is_same_decayed<int&&,      int>::value  << '\n'
///           << is_same_decayed<const int&, int>::value  << '\n'
///           << is_same_decayed<int[2],     int*>::value << '\n'
///           << is_same_decayed<int(int),   int(*)(int)>::value << '\n';
/// \endcode
template <typename T, typename U>
struct is_same_decayed : std::is_same<typename std::decay<T>::type, U>::type
{};

/// Convert strongly typed enum to underlying type
/// \code
/// enum class B { B1 = 1, B2 = 2 };
/// std::cout << utxx::to_underlying(B::B2) << std::endl;
/// \endcode
template <typename E>
constexpr typename std::underlying_type<E>::type to_underlying(E e) {
    return static_cast<typename std::underlying_type<E>::type>(e);
}

/// Syntactic sugar that evaluates to type \a T if \a T is derived from \a BaseT
template <typename BaseT, typename T, typename R = T>
using if_base_of = typename std::enable_if<std::is_base_of<BaseT, T>::value, R>::type;

/// Syntactic sugar that evaluates to type \a T if \a T is not derived from \a BaseT
template <typename BaseT, typename T, typename R = T>
using if_not_base_of = typename std::enable_if<!std::is_base_of<BaseT, T>::value, R>::type;

namespace {
    template<int N, char... Chars>
    struct to_int_helper;

    template<int N, char C>
    struct to_int_helper<N, C> {
        static const size_t value = ((size_t)C) << (8*N);
    };

    template <int N, char C, char... Tail>
    struct to_int_helper<N, C, Tail...> {
        static const size_t value =
            ((size_t)C) << (8*N) | to_int_helper<N-1, Tail...>::value;
    };
}

/// Convert list of chars to integer (up to 8 bytes).
/// I.e. to_int<'A','B','C','Z'>::value() is a compile-time equivalent of
/// size_t("ABCZ\0\0\0\0").  This type of value can be quickly used in switch
/// statements instead of doing string comparisons.
template <char... Chars>
struct to_int {
    static constexpr size_t value() {
        static_assert(sizeof...(Chars) <= 8, "Invalid size!");
        return to_int_helper<(sizeof...(Chars))-1, Chars...>::value;
    }
};

// For generic types, directly use the result of the signature of its 'operator()'
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};

// Specialization for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
    /// Arity is the number of arguments
    enum { arity = sizeof...(Args) };

    typedef ReturnType          result_type;
    typedef std::tuple<Args...> args_tuple;

    template <size_t i>
    struct arg
    {
        // the i-th argument is equivalent to the i-th tuple element of a tuple
        // composed of those arguments.
        typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
    };
};

//------------------------------------------------------------------------------
/// Extract the last type in a parameter pack
//------------------------------------------------------------------------------
/// Usage example:
/// \code
/// struct S
/// {
///   // Accept variadic arguments so long as the last argument type is an int
///   template <
///     typename... T,
///     typename = typename std::enable_if<
///                    std::is_same<int, typename last_type<T...>::type>>::type>
///   S(T...);
/// };
/// \endcode
//------------------------------------------------------------------------------
// 0, the empty pack has no last type (only called if 1 and 2+ don't match)
template<typename... Ts>
struct last_type {};

// 2+ in pack, recurse:
template<typename T0, typename T1, typename... Ts>
struct last_type<T0, T1, Ts...> : last_type<T1, Ts...> {};

// Length 1, last type is only type:
template<typename T0>
struct last_type<T0> { using type = T0; };

//-----------------------------------------------------------------------------
/// Evaluation of anything
//-----------------------------------------------------------------------------
// functions, functors, lambdas, etc.
template<
    class F, class... Args,
    class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type,
    class = typename std::enable_if<!std::is_member_object_pointer<F>::value>::type
    >
auto eval(F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...))
{
    return f(std::forward<Args>(args)...);
}

// const member function
template<class R, class C, class... Args>
auto eval(R(C::*f)() const, const C& c, Args&&... args) -> R
{
    return (c.*f)(std::forward<Args>(args)...);
}

template<class R, class C, class... Args>
auto eval(R(C::*f)() const, C& c, Args&&... args) -> R
{
    return (c.*f)(std::forward<Args>(args)...);
}

// non-const member function
template<class R, class C, class... Args>
auto eval(R(C::*f)(), C& c, Args&&... args) -> R
{
    return (c.*f)(std::forward<Args>(args)...);
}

// member object
template<class R, class C>
auto eval(R(C::*m), const C& c) -> const R&
{
    return c.*m;
}

template<class R, class C>
auto eval(R(C::*m), C& c) -> R&
{
    return c.*m;
}

//-----------------------------------------------------------------------------
/// Check that a tuple has a given type
/// Example:
/// ```
/// if (has_type<SomeT, std::tuple<int, uint, bool>>::value) return;
/// ```
//-----------------------------------------------------------------------------
template <typename T, typename Tuple>
struct has_type;

template <typename T>
struct has_type<T, std::tuple<>> : std::false_type {};

template <typename T, typename U, typename... Ts>
struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};

template <typename T, typename... Ts>
struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};

//-----------------------------------------------------------------------------
/// Same as has_type but ignores const/volatile/reference decorators.
/// Example:
/// ```
/// if (has_type_nocvref<SomeT, std::tuple<int, uint, bool>>::value) return;
/// ```
//-----------------------------------------------------------------------------
template <typename T, typename... Ts>
struct has_type_nocvref
     : has_type<
        typename std::remove_cv<typename std::remove_reference<T>::type>::type,
        Ts...
       >
{};

//-----------------------------------------------------------------------------
// Remove "const", "volatile", and reference ("&") operators from a type
//-----------------------------------------------------------------------------
template <typename T>
struct remove_cvref {
    using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
};

//-----------------------------------------------------------------------------
// Check if two types are the same, ignore const, volatile, and ref modifiers
//-----------------------------------------------------------------------------
template <typename T, typename U>
static constexpr const bool is_same() {
  return std::is_same<typename remove_cvref<T>::type, typename remove_cvref<U>::type>::value;
};

} // namespace utxx
<commit_msg>Add remove_cvr_t<commit_after>//----------------------------------------------------------------------------
/// \file   meta.hpp
/// \author Serge Aleynikov
//----------------------------------------------------------------------------
/// \brief This file contains some generic metaprogramming functions.
//----------------------------------------------------------------------------
// Copyright (c) 2010 Serge Aleynikov <saleyn@gmail.com>
// Created: 2010-09-31
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#pragma once

#include <cstddef>

#include <type_traits>
#include <tuple>
#include <utility>

namespace utxx {

template <size_t N, size_t Base>
struct log {
    static const size_t value = 1 + log<N / Base, Base>::value;
};

template <size_t Base> struct log<1, Base> { static const size_t value = 0; };
template <size_t Base> struct log<0, Base>;

template <size_t N, size_t Power>
struct pow {
    static const size_t value = N * pow<N, Power - 1>::value;
};

template <size_t N>     struct pow<N, 0>        { static const size_t value = 1; };
template <size_t Power> struct pow<0, Power>    { static const size_t value = 0; };

/// Computes the smallest power of \a base equal or greater than number \a n.
template <size_t N, size_t Base>
class upper_power {
    static const size_t s_log = log<N,Base>::value;
    static const size_t s_pow = pow<Base,s_log>::value;
public:
    static const size_t value = s_pow == N ? N : s_pow*Base;
};

// We need specialisation of "upper_power" for N=0, because the log cannot be
// computed in that case (as required in the generic case above).  The result
// is 0 in this case (the corresp exponent of Base is "-oo")    (XXX: even if
// Base==0):
template<size_t Base>
class upper_power<0, Base> {
public:
     static const size_t value  = 0;
};

template <size_t N>
using upper_power2 = upper_power<N, 2>;

/// Given the size N and alignment size get the number of padding and aligned
/// space needed to hold the structure of N bytes.
template<int N, int Size>
class align {
    static const int multiplier = Size / N;
    static const int remainder  = Size % N;
public:
    static const int size       = remainder > 0 ? (multiplier+1) * N : Size;
    static const int padding    = size - Size;
};

/// Check if \a T and \a U are the same types by stripping T's ref and cv-qualifiers
/// \code
/// // All following expressions return true:
/// std::cout << std::boolalpha
///           << is_same_decayed<int,        int>::value  << '\n'
///           << is_same_decayed<int&,       int>::value  << '\n'
///           << is_same_decayed<int&&,      int>::value  << '\n'
///           << is_same_decayed<const int&, int>::value  << '\n'
///           << is_same_decayed<int[2],     int*>::value << '\n'
///           << is_same_decayed<int(int),   int(*)(int)>::value << '\n';
/// \endcode
template <typename T, typename U>
struct is_same_decayed : std::is_same<typename std::decay<T>::type, U>::type
{};

/// Convert strongly typed enum to underlying type
/// \code
/// enum class B { B1 = 1, B2 = 2 };
/// std::cout << utxx::to_underlying(B::B2) << std::endl;
/// \endcode
template <typename E>
constexpr typename std::underlying_type<E>::type to_underlying(E e) {
    return static_cast<typename std::underlying_type<E>::type>(e);
}

/// Syntactic sugar that evaluates to type \a T if \a T is derived from \a BaseT
template <typename BaseT, typename T, typename R = T>
using if_base_of = typename std::enable_if<std::is_base_of<BaseT, T>::value, R>::type;

/// Syntactic sugar that evaluates to type \a T if \a T is not derived from \a BaseT
template <typename BaseT, typename T, typename R = T>
using if_not_base_of = typename std::enable_if<!std::is_base_of<BaseT, T>::value, R>::type;

namespace {
    template<int N, char... Chars>
    struct to_int_helper;

    template<int N, char C>
    struct to_int_helper<N, C> {
        static const size_t value = ((size_t)C) << (8*N);
    };

    template <int N, char C, char... Tail>
    struct to_int_helper<N, C, Tail...> {
        static const size_t value =
            ((size_t)C) << (8*N) | to_int_helper<N-1, Tail...>::value;
    };
}

/// Convert list of chars to integer (up to 8 bytes).
/// I.e. to_int<'A','B','C','Z'>::value() is a compile-time equivalent of
/// size_t("ABCZ\0\0\0\0").  This type of value can be quickly used in switch
/// statements instead of doing string comparisons.
template <char... Chars>
struct to_int {
    static constexpr size_t value() {
        static_assert(sizeof...(Chars) <= 8, "Invalid size!");
        return to_int_helper<(sizeof...(Chars))-1, Chars...>::value;
    }
};

// For generic types, directly use the result of the signature of its 'operator()'
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};

// Specialization for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
    /// Arity is the number of arguments
    enum { arity = sizeof...(Args) };

    typedef ReturnType          result_type;
    typedef std::tuple<Args...> args_tuple;

    template <size_t i>
    struct arg
    {
        // the i-th argument is equivalent to the i-th tuple element of a tuple
        // composed of those arguments.
        typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
    };
};

//------------------------------------------------------------------------------
/// Extract the last type in a parameter pack
//------------------------------------------------------------------------------
/// Usage example:
/// \code
/// struct S
/// {
///   // Accept variadic arguments so long as the last argument type is an int
///   template <
///     typename... T,
///     typename = typename std::enable_if<
///                    std::is_same<int, typename last_type<T...>::type>>::type>
///   S(T...);
/// };
/// \endcode
//------------------------------------------------------------------------------
// 0, the empty pack has no last type (only called if 1 and 2+ don't match)
template<typename... Ts>
struct last_type {};

// 2+ in pack, recurse:
template<typename T0, typename T1, typename... Ts>
struct last_type<T0, T1, Ts...> : last_type<T1, Ts...> {};

// Length 1, last type is only type:
template<typename T0>
struct last_type<T0> { using type = T0; };

//-----------------------------------------------------------------------------
/// Evaluation of anything
//-----------------------------------------------------------------------------
// functions, functors, lambdas, etc.
template<
    class F, class... Args,
    class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type,
    class = typename std::enable_if<!std::is_member_object_pointer<F>::value>::type
    >
auto eval(F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...))
{
    return f(std::forward<Args>(args)...);
}

// const member function
template<class R, class C, class... Args>
auto eval(R(C::*f)() const, const C& c, Args&&... args) -> R
{
    return (c.*f)(std::forward<Args>(args)...);
}

template<class R, class C, class... Args>
auto eval(R(C::*f)() const, C& c, Args&&... args) -> R
{
    return (c.*f)(std::forward<Args>(args)...);
}

// non-const member function
template<class R, class C, class... Args>
auto eval(R(C::*f)(), C& c, Args&&... args) -> R
{
    return (c.*f)(std::forward<Args>(args)...);
}

// member object
template<class R, class C>
auto eval(R(C::*m), const C& c) -> const R&
{
    return c.*m;
}

template<class R, class C>
auto eval(R(C::*m), C& c) -> R&
{
    return c.*m;
}

//-----------------------------------------------------------------------------
/// Check that a tuple has a given type
/// Example:
/// ```
/// if (has_type<SomeT, std::tuple<int, uint, bool>>::value) return;
/// ```
//-----------------------------------------------------------------------------
template <typename T, typename Tuple>
struct has_type;

template <typename T>
struct has_type<T, std::tuple<>> : std::false_type {};

template <typename T, typename U, typename... Ts>
struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};

template <typename T, typename... Ts>
struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};

//-----------------------------------------------------------------------------
/// Same as has_type but ignores const/volatile/reference decorators.
/// Example:
/// ```
/// if (has_type_nocvref<SomeT, std::tuple<int, uint, bool>>::value) return;
/// ```
//-----------------------------------------------------------------------------
template <typename T, typename... Ts>
struct has_type_nocvref
     : has_type<
        typename std::remove_cv<typename std::remove_reference<T>::type>::type,
        Ts...
       >
{};

//-----------------------------------------------------------------------------
/// Remove "const", "volatile", and reference ("&") operators from a type
//-----------------------------------------------------------------------------
template <typename T>
struct remove_cvref {
    using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
};

//-----------------------------------------------------------------------------
/// Remove "const", "volatile", and reference ("&") operators from a type
//-----------------------------------------------------------------------------
template< class T>
using remove_cvr_t = typename remove_cvref<T>::type;

//-----------------------------------------------------------------------------
// Check if two types are the same, ignore const, volatile, and ref modifiers
//-----------------------------------------------------------------------------
template <typename T, typename U>
static constexpr const bool is_same() {
  return std::is_same<typename remove_cvref<T>::type, typename remove_cvref<U>::type>::value;
};

} // namespace utxx
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUITooltip.cpp
    created:    21/2/2005
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/widgets/Tooltip.h"
#include "CEGUI/Logger.h"
#include "CEGUI/Font.h"
#include "CEGUI/Image.h"

// Start of CEGUI namespace section
namespace CEGUI
{
    const String Tooltip::WidgetTypeName("CEGUI/Tooltip");

    //////////////////////////////////////////////////////////////////////////
    // Event name constants
    const String Tooltip::EventNamespace("Tooltip");
    const String Tooltip::EventHoverTimeChanged("HoverTimeChanged");
    const String Tooltip::EventDisplayTimeChanged("DisplayTimeChanged");
    const String Tooltip::EventFadeTimeChanged("FadeTimeChanged");
    const String Tooltip::EventTooltipActive("TooltipActive");
    const String Tooltip::EventTooltipInactive("TooltipInactive");
    const String Tooltip::EventTooltipTransition("TooltipTransition");
    //////////////////////////////////////////////////////////////////////////

    /*************************************************************************
        TooltipWindowRenderer
    *************************************************************************/
    TooltipWindowRenderer::TooltipWindowRenderer(const String& name) :
        WindowRenderer(name, Tooltip::EventNamespace)
    {
    }

    //////////////////////////////////////////////////////////////////////////
    Tooltip::Tooltip(const String& type, const String& name) :
        Window(type, name),

        d_hoverTime(0.4f),
        d_displayTime(7.5f),
        d_inPositionSelf(false)
    {
        addTooltipProperties();

        setClippedByParent(false);
        setDestroyedByParent(false);
        setAlwaysOnTop(true);

        // we need updates even when not visible
        setUpdateMode(WUM_ALWAYS);

        switchToInactiveState();
    }

    Tooltip::~Tooltip(void)
    {}

    void Tooltip::positionSelf(void)
    {
        // no recusion allowed for this function!
        if (d_inPositionSelf)
            return;

        d_inPositionSelf = true;

        MouseCursor& cursor = getGUIContext().getMouseCursor();
        Rectf screen(Vector2f(0, 0), getRootContainerSize());
        Rectf tipRect(getUnclippedOuterRect().get());
        const Image* mouseImage = cursor.getImage();

        Vector2f mousePos(cursor.getPosition());
        Sizef mouseSz(0,0);

        if (mouseImage)
        {
            mouseSz = mouseImage->getRenderedSize();
        }

        Vector2f tmpPos(mousePos.d_x + mouseSz.d_width, mousePos.d_y + mouseSz.d_height);
        tipRect.setPosition(tmpPos);

        // if tooltip would be off the right of the screen,
        // reposition to the other side of the mouse cursor.
        if (screen.right() < tipRect.right())
        {
            tmpPos.d_x = mousePos.d_x - tipRect.getWidth() - 5;
        }

        // if tooltip would be off the bottom of the screen,
        // reposition to the other side of the mouse cursor.
        if (screen.bottom() < tipRect.bottom())
        {
            tmpPos.d_y = mousePos.d_y - tipRect.getHeight() - 5;
        }

        // set final position of tooltip window.
        setPosition(
            UVector2(cegui_absdim(tmpPos.d_x),
                     cegui_absdim(tmpPos.d_y)));

        d_inPositionSelf = false;
    }

    void Tooltip::sizeSelf(void)
    {
        Sizef textSize(getTextSize());

        setSize(USize(cegui_absdim(textSize.d_width),
                      cegui_absdim(textSize.d_height)));
    }

    void Tooltip::setTargetWindow(Window* wnd)
    {
        if (!wnd)
        {
            d_target = wnd;
        }
        else if (wnd != this)
        {
            if (d_target != wnd)
            {
                getGUIContext().getRootWindow()->addChild(this);
                d_target = wnd;
            }

            // set text to that of the tooltip text of the target
            setText(wnd->getTooltipText());

            // set size and position of the tooltip window.
            sizeSelf();
            positionSelf();
        }

        resetTimer();

        if (d_active)
        {
            WindowEventArgs args(this);
            onTooltipTransition(args);
        }
    }

    const Window* Tooltip::getTargetWindow()
    {
        return d_target;
    }

    Sizef Tooltip::getTextSize() const
    {
        if (d_windowRenderer != 0)
        {
            TooltipWindowRenderer* wr = (TooltipWindowRenderer*)d_windowRenderer;
            return wr->getTextSize();
        }
        else
        {
            return getTextSize_impl();
        }
    }

    Sizef Tooltip::getTextSize_impl() const
    {
        const RenderedString& rs(getRenderedString());
        Sizef sz(0.0f, 0.0f);

        for (size_t i = 0; i < rs.getLineCount(); ++i)
        {
            const Sizef line_sz(rs.getPixelSize(i));
            sz.d_height += line_sz.d_height;

            if (line_sz.d_width > sz.d_width)
                sz.d_width = line_sz.d_width;
        }

        return sz;
    }

    void Tooltip::resetTimer(void)
    {
        d_elapsed = 0;
    }

    float Tooltip::getHoverTime(void) const
    {
        return d_hoverTime;
    }

    void Tooltip::setHoverTime(float seconds)
    {
        if (d_hoverTime != seconds)
        {
            d_hoverTime = seconds;

            WindowEventArgs args(this);
            onHoverTimeChanged(args);
        }
    }

    float Tooltip::getDisplayTime(void) const
    {
        return d_displayTime;
    }

    void Tooltip::setDisplayTime(float seconds)
    {
        if (d_displayTime != seconds)
        {
            d_displayTime = seconds;

            WindowEventArgs args(this);
            onDisplayTimeChanged(args);
        }
    }

    void Tooltip::doActiveState(float elapsed)
    {
        // if no target, switch immediately to inactive state.
        if (!d_target || d_target->getTooltipText().empty())
        {
            // hide immediately since the text is empty
            hide();

            switchToInactiveState();
        }
        // else see if display timeout has been reached
        else if ((d_displayTime > 0) && ((d_elapsed += elapsed) >= d_displayTime))
        {
            // display time is up, switch states
            switchToInactiveState();
        }
    }

    void Tooltip::doInactiveState(float elapsed)
    {
        if (d_target && !d_target->getTooltipText().empty() && ((d_elapsed += elapsed) >= d_hoverTime))
        {
            switchToActiveState();
        }
    }

    void Tooltip::switchToInactiveState(void)
    {
        d_active = false;
        d_elapsed = 0;

        // fire event before target gets reset in case that information is required in handler.
        WindowEventArgs args(this);
        onTooltipInactive(args);

        d_target = 0;
    }

    void Tooltip::switchToActiveState(void)
    {
        positionSelf();
        show();

        d_active = true;
        d_elapsed = 0;

        WindowEventArgs args(this);
        onTooltipActive(args);
    }

    bool Tooltip::validateWindowRenderer(const WindowRenderer* renderer) const
	{
		return dynamic_cast<const TooltipWindowRenderer*>(renderer) != 0;
	}

    void Tooltip::updateSelf(float elapsed)
    {
        // base class processing.
        Window::updateSelf(elapsed);

        // do something based upon current Tooltip state.
        if (d_active)
        {
            doActiveState(elapsed);
        }
        else
        {
            doInactiveState(elapsed);
        }
    }

    void Tooltip::addTooltipProperties(void)
    {
        const String& propertyOrigin = WidgetTypeName;

        CEGUI_DEFINE_PROPERTY(Tooltip, float,
            "HoverTime", "Property to get/set the hover timeout value in seconds.  Value is a float.",
            &Tooltip::setHoverTime, &Tooltip::getHoverTime, 0.4f
        );

        CEGUI_DEFINE_PROPERTY(Tooltip, float,
            "DisplayTime", "Property to get/set the display timeout value in seconds.  Value is a float.",
            &Tooltip::setDisplayTime, &Tooltip::getDisplayTime, 7.5f
        );
    }

    void Tooltip::onHidden(WindowEventArgs& e)
    {
        Window::onHidden(e);

        // The animation will take care of fade out or whatnot,
        // at the end it will hide the tooltip to let us know the transition
        // is done. At this point we will remove the tooltip from the
        // previous parent.

        // NOTE: There has to be a fadeout animation! Even if it's a 0 second
        //       immediate hide animation.

        if (getParent())
        {
            getParent()->removeChild(this);
        }
    }

    void Tooltip::onMouseEnters(MouseEventArgs& e)
    {
        positionSelf();

        Window::onMouseEnters(e);
    }

    void Tooltip::onTextChanged(WindowEventArgs& e)
    {
        // base class processing
        Window::onTextChanged(e);

        // set size and position of the tooltip window to consider new text
        sizeSelf();
        positionSelf();

        // we do not signal we handled it, in case user wants to hear
        // about text changes too.
    }

    void Tooltip::onHoverTimeChanged(WindowEventArgs& e)
    {
        fireEvent(EventHoverTimeChanged, e, EventNamespace);
    }

    void Tooltip::onDisplayTimeChanged(WindowEventArgs& e)
    {
        fireEvent(EventDisplayTimeChanged, e, EventNamespace);
    }

    void Tooltip::onTooltipActive(WindowEventArgs& e)
    {
        fireEvent(EventTooltipActive, e, EventNamespace);
    }

    void Tooltip::onTooltipInactive(WindowEventArgs& e)
    {
        fireEvent(EventTooltipInactive, e, EventNamespace);
    }

    void Tooltip::onTooltipTransition(WindowEventArgs& e)
    {
        fireEvent(EventTooltipTransition, e, EventNamespace);
    }
} // End of  CEGUI namespace section
<commit_msg>FIX: Be sure to add ourselves to the right GUIContext root.<commit_after>/***********************************************************************
    filename:   CEGUITooltip.cpp
    created:    21/2/2005
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/widgets/Tooltip.h"
#include "CEGUI/Logger.h"
#include "CEGUI/Font.h"
#include "CEGUI/Image.h"

// Start of CEGUI namespace section
namespace CEGUI
{
    const String Tooltip::WidgetTypeName("CEGUI/Tooltip");

    //////////////////////////////////////////////////////////////////////////
    // Event name constants
    const String Tooltip::EventNamespace("Tooltip");
    const String Tooltip::EventHoverTimeChanged("HoverTimeChanged");
    const String Tooltip::EventDisplayTimeChanged("DisplayTimeChanged");
    const String Tooltip::EventFadeTimeChanged("FadeTimeChanged");
    const String Tooltip::EventTooltipActive("TooltipActive");
    const String Tooltip::EventTooltipInactive("TooltipInactive");
    const String Tooltip::EventTooltipTransition("TooltipTransition");
    //////////////////////////////////////////////////////////////////////////

    /*************************************************************************
        TooltipWindowRenderer
    *************************************************************************/
    TooltipWindowRenderer::TooltipWindowRenderer(const String& name) :
        WindowRenderer(name, Tooltip::EventNamespace)
    {
    }

    //////////////////////////////////////////////////////////////////////////
    Tooltip::Tooltip(const String& type, const String& name) :
        Window(type, name),

        d_hoverTime(0.4f),
        d_displayTime(7.5f),
        d_inPositionSelf(false)
    {
        addTooltipProperties();

        setClippedByParent(false);
        setDestroyedByParent(false);
        setAlwaysOnTop(true);

        // we need updates even when not visible
        setUpdateMode(WUM_ALWAYS);

        switchToInactiveState();
    }

    Tooltip::~Tooltip(void)
    {}

    void Tooltip::positionSelf(void)
    {
        // no recusion allowed for this function!
        if (d_inPositionSelf)
            return;

        d_inPositionSelf = true;

        MouseCursor& cursor = getGUIContext().getMouseCursor();
        Rectf screen(Vector2f(0, 0), getRootContainerSize());
        Rectf tipRect(getUnclippedOuterRect().get());
        const Image* mouseImage = cursor.getImage();

        Vector2f mousePos(cursor.getPosition());
        Sizef mouseSz(0,0);

        if (mouseImage)
        {
            mouseSz = mouseImage->getRenderedSize();
        }

        Vector2f tmpPos(mousePos.d_x + mouseSz.d_width, mousePos.d_y + mouseSz.d_height);
        tipRect.setPosition(tmpPos);

        // if tooltip would be off the right of the screen,
        // reposition to the other side of the mouse cursor.
        if (screen.right() < tipRect.right())
        {
            tmpPos.d_x = mousePos.d_x - tipRect.getWidth() - 5;
        }

        // if tooltip would be off the bottom of the screen,
        // reposition to the other side of the mouse cursor.
        if (screen.bottom() < tipRect.bottom())
        {
            tmpPos.d_y = mousePos.d_y - tipRect.getHeight() - 5;
        }

        // set final position of tooltip window.
        setPosition(
            UVector2(cegui_absdim(tmpPos.d_x),
                     cegui_absdim(tmpPos.d_y)));

        d_inPositionSelf = false;
    }

    void Tooltip::sizeSelf(void)
    {
        Sizef textSize(getTextSize());

        setSize(USize(cegui_absdim(textSize.d_width),
                      cegui_absdim(textSize.d_height)));
    }

    void Tooltip::setTargetWindow(Window* wnd)
    {
        if (!wnd)
        {
            d_target = wnd;
        }
        else if (wnd != this)
        {
            if (d_target != wnd)
            {
                wnd->getGUIContext().getRootWindow()->addChild(this);
                d_target = wnd;
            }

            // set text to that of the tooltip text of the target
            setText(wnd->getTooltipText());

            // set size and position of the tooltip window.
            sizeSelf();
            positionSelf();
        }

        resetTimer();

        if (d_active)
        {
            WindowEventArgs args(this);
            onTooltipTransition(args);
        }
    }

    const Window* Tooltip::getTargetWindow()
    {
        return d_target;
    }

    Sizef Tooltip::getTextSize() const
    {
        if (d_windowRenderer != 0)
        {
            TooltipWindowRenderer* wr = (TooltipWindowRenderer*)d_windowRenderer;
            return wr->getTextSize();
        }
        else
        {
            return getTextSize_impl();
        }
    }

    Sizef Tooltip::getTextSize_impl() const
    {
        const RenderedString& rs(getRenderedString());
        Sizef sz(0.0f, 0.0f);

        for (size_t i = 0; i < rs.getLineCount(); ++i)
        {
            const Sizef line_sz(rs.getPixelSize(i));
            sz.d_height += line_sz.d_height;

            if (line_sz.d_width > sz.d_width)
                sz.d_width = line_sz.d_width;
        }

        return sz;
    }

    void Tooltip::resetTimer(void)
    {
        d_elapsed = 0;
    }

    float Tooltip::getHoverTime(void) const
    {
        return d_hoverTime;
    }

    void Tooltip::setHoverTime(float seconds)
    {
        if (d_hoverTime != seconds)
        {
            d_hoverTime = seconds;

            WindowEventArgs args(this);
            onHoverTimeChanged(args);
        }
    }

    float Tooltip::getDisplayTime(void) const
    {
        return d_displayTime;
    }

    void Tooltip::setDisplayTime(float seconds)
    {
        if (d_displayTime != seconds)
        {
            d_displayTime = seconds;

            WindowEventArgs args(this);
            onDisplayTimeChanged(args);
        }
    }

    void Tooltip::doActiveState(float elapsed)
    {
        // if no target, switch immediately to inactive state.
        if (!d_target || d_target->getTooltipText().empty())
        {
            // hide immediately since the text is empty
            hide();

            switchToInactiveState();
        }
        // else see if display timeout has been reached
        else if ((d_displayTime > 0) && ((d_elapsed += elapsed) >= d_displayTime))
        {
            // display time is up, switch states
            switchToInactiveState();
        }
    }

    void Tooltip::doInactiveState(float elapsed)
    {
        if (d_target && !d_target->getTooltipText().empty() && ((d_elapsed += elapsed) >= d_hoverTime))
        {
            switchToActiveState();
        }
    }

    void Tooltip::switchToInactiveState(void)
    {
        d_active = false;
        d_elapsed = 0;

        // fire event before target gets reset in case that information is required in handler.
        WindowEventArgs args(this);
        onTooltipInactive(args);

        d_target = 0;
    }

    void Tooltip::switchToActiveState(void)
    {
        positionSelf();
        show();

        d_active = true;
        d_elapsed = 0;

        WindowEventArgs args(this);
        onTooltipActive(args);
    }

    bool Tooltip::validateWindowRenderer(const WindowRenderer* renderer) const
	{
		return dynamic_cast<const TooltipWindowRenderer*>(renderer) != 0;
	}

    void Tooltip::updateSelf(float elapsed)
    {
        // base class processing.
        Window::updateSelf(elapsed);

        // do something based upon current Tooltip state.
        if (d_active)
        {
            doActiveState(elapsed);
        }
        else
        {
            doInactiveState(elapsed);
        }
    }

    void Tooltip::addTooltipProperties(void)
    {
        const String& propertyOrigin = WidgetTypeName;

        CEGUI_DEFINE_PROPERTY(Tooltip, float,
            "HoverTime", "Property to get/set the hover timeout value in seconds.  Value is a float.",
            &Tooltip::setHoverTime, &Tooltip::getHoverTime, 0.4f
        );

        CEGUI_DEFINE_PROPERTY(Tooltip, float,
            "DisplayTime", "Property to get/set the display timeout value in seconds.  Value is a float.",
            &Tooltip::setDisplayTime, &Tooltip::getDisplayTime, 7.5f
        );
    }

    void Tooltip::onHidden(WindowEventArgs& e)
    {
        Window::onHidden(e);

        // The animation will take care of fade out or whatnot,
        // at the end it will hide the tooltip to let us know the transition
        // is done. At this point we will remove the tooltip from the
        // previous parent.

        // NOTE: There has to be a fadeout animation! Even if it's a 0 second
        //       immediate hide animation.

        if (getParent())
        {
            getParent()->removeChild(this);
        }
    }

    void Tooltip::onMouseEnters(MouseEventArgs& e)
    {
        positionSelf();

        Window::onMouseEnters(e);
    }

    void Tooltip::onTextChanged(WindowEventArgs& e)
    {
        // base class processing
        Window::onTextChanged(e);

        // set size and position of the tooltip window to consider new text
        sizeSelf();
        positionSelf();

        // we do not signal we handled it, in case user wants to hear
        // about text changes too.
    }

    void Tooltip::onHoverTimeChanged(WindowEventArgs& e)
    {
        fireEvent(EventHoverTimeChanged, e, EventNamespace);
    }

    void Tooltip::onDisplayTimeChanged(WindowEventArgs& e)
    {
        fireEvent(EventDisplayTimeChanged, e, EventNamespace);
    }

    void Tooltip::onTooltipActive(WindowEventArgs& e)
    {
        fireEvent(EventTooltipActive, e, EventNamespace);
    }

    void Tooltip::onTooltipInactive(WindowEventArgs& e)
    {
        fireEvent(EventTooltipInactive, e, EventNamespace);
    }

    void Tooltip::onTooltipTransition(WindowEventArgs& e)
    {
        fireEvent(EventTooltipTransition, e, EventNamespace);
    }
} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>#include <cassert>

#include "Mesh.h"

using namespace eyesore;

using std::vector;

eyesore::Mesh::Mesh(vector<Vertex> vertices, vector<GLuint> indices):
	vertices(vertices), indices(indices)
{
	glGenVertexArrays(1, &vao);
	glGenBuffers(1, &vbo);
	glGenBuffers(1, &ebo);

	glBindVertexArray(vao);

	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0],
			GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, ebo);
	glBufferData(GL_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0],
			GL_STATIC_DRAW);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(GLvoid *) 0);

	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(GLvoid *) offsetof(Vertex, normal));

	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(GLvoid *) offsetof(Vertex, uv));

	glBindVertexArray(0);
}

eyesore::Mesh::~Mesh()
{
	glDeleteBuffers(1, &vbo);
	glDeleteBuffers(1, &ebo);
	glDeleteVertexArrays(1, &vao);
}

void eyesore::Mesh::render(ShaderProgram &shader, Camera &camera) const
{
	shader.use();
	camera.use();
	glBindVertexArray(vao);
	glDrawElements(GL_TRIANGLES, indices.size() / 3, GL_UNSIGNED_INT, &indices[0]);
}

<commit_msg>Fix Mesh drawing<commit_after>#include <cassert>

#include "Mesh.h"

using namespace eyesore;

using std::vector;

eyesore::Mesh::Mesh(vector<Vertex> vertices, vector<GLuint> indices):
	vertices(vertices), indices(indices)
{
	glGenVertexArrays(1, &vao);
	glGenBuffers(1, &vbo);
	glGenBuffers(1, &ebo);

	glBindVertexArray(vao);

	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0],
			GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0],
			GL_STATIC_DRAW);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(GLvoid *) 0);

	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(GLvoid *) offsetof(Vertex, normal));

	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(GLvoid *) offsetof(Vertex, uv));

	glBindVertexArray(0);
}

eyesore::Mesh::~Mesh()
{
	glDeleteBuffers(1, &vbo);
	glDeleteBuffers(1, &ebo);
	glDeleteVertexArrays(1, &vao);
}

void eyesore::Mesh::render(ShaderProgram &shader, Camera &camera) const
{
	shader.use();
	camera.use();

	glBindVertexArray(vao);
	glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
	glBindVertexArray(0);
}

<|endoftext|>


<commit_before>#include <algorithm>
#include <cassert>
#include "system.h"
#include "errors.h"
#include "utils.h"

int System::installMemory(MemoryModule &mod, SizeType offset, SizeType size) {
    int status = ERR_SUCCESS;

    // NB: if(size <= 0 || /* overflow */offset + size < offset) {
    if(offset + size <= offset) {
        status = ERR_BADRANGE;
    } else {
        MemoryInstance overlap = resolveAtMost(offset + size - 1);
        if(overlap) {
            SizeType overlapEnd = overlap.offset + overlap.length - 1;
            if(overlapEnd >= offset) {
                status = ERR_CONFLICT;
            }
        }
    }

    if(status == ERR_SUCCESS) {
        mem.emplace(offset,  MemoryInstance(&mod, offset, size));
    }
    return status;
}

int System::removeMemory(SizeType offset) {
    MemMap::size_type erased = mem.erase(offset);
    assert(erased <= 1);
    int status = erased ? ERR_SUCCESS : ERR_BADRANGE;
    return status;
}

int System::bindPort(PortSocket &sock, PortType port) {
    throw "Not Implemented";
}

int System::releasePort(PortType port) {
    throw "Not Implemented";
}

int System::readMemory(SizeType offset, SizeType len, void *data) const {
    return memoryLoop(offset, len, data, false);
}

int System::writeMemory(SizeType offset, SizeType len, const void *data) const {
    return memoryLoop(offset, len, data, true);
}

int System::readPort(PortType port, SizeType len, void *data) const {
    throw "Not Implemented";
}

int System::writePort(PortType port, SizeType len, const void *data) const {
    throw "Not Implemented";
}

System::MemoryInstance System::resolveAtMost(SizeType address) const {
    auto iterator = mem.lower_bound(address);
    if(iterator->second.offset != address) {
        if (iterator == mem.cbegin()) {
            iterator = mem.cend();
        } else if(iterator != mem.cend()) {
            iterator--;
        }
    }
    return iterator->second;
}

int System::memoryLoop(SizeType offset, SizeType len, const void *data, bool write) const {
    int status = ERR_SUCCESS;
    while(len > 0) {
        MemoryInstance src = resolveAtMost(offset);
        if(!src) {
            status = ERR_BADRANGE;
        } else {
            SizeType srcOff = offset - src.offset;
            SizeType srcLen = std::min(src.length - srcOff, len);
            if(write) {
                status = src.mod->writeMemory(srcOff, srcLen, data);
            } else {
                status = src.mod->readMemory(srcOff, srcLen, /* HACK */(void*)(data));
            }
            if(status == ERR_SUCCESS)
            {
                len -= srcLen;
                offset += srcLen;
                data = advancePtr(data, srcLen);
            } else {
                break;
            }
        }
    }
    return status;
}<commit_msg>Correct implementation of resolveAtMost<commit_after>#include <algorithm>
#include <cassert>
#include "system.h"
#include "errors.h"
#include "utils.h"

int System::installMemory(MemoryModule &mod, SizeType offset, SizeType size) {
    int status = ERR_SUCCESS;

    // NB: if(size <= 0 || /* overflow */offset + size < offset) {
    if(offset + size <= offset) {
        status = ERR_BADRANGE;
    } else {
        MemoryInstance overlap = resolveAtMost(offset + size - 1);
        if(overlap) {
            SizeType overlapEnd = overlap.offset + overlap.length - 1;
            if(overlapEnd >= offset) {
                status = ERR_CONFLICT;
            }
        }
    }

    if(status == ERR_SUCCESS) {
        mem.emplace(offset,  MemoryInstance(&mod, offset, size));
    }
    return status;
}

int System::removeMemory(SizeType offset) {
    MemMap::size_type erased = mem.erase(offset);
    assert(erased <= 1);
    int status = erased ? ERR_SUCCESS : ERR_BADRANGE;
    return status;
}

int System::bindPort(PortSocket &sock, PortType port) {
    throw "Not Implemented";
}

int System::releasePort(PortType port) {
    throw "Not Implemented";
}

int System::readMemory(SizeType offset, SizeType len, void *data) const {
    return memoryLoop(offset, len, data, false);
}

int System::writeMemory(SizeType offset, SizeType len, const void *data) const {
    return memoryLoop(offset, len, data, true);
}

int System::readPort(PortType port, SizeType len, void *data) const {
    throw "Not Implemented";
}

int System::writePort(PortType port, SizeType len, const void *data) const {
    throw "Not Implemented";
}

System::MemoryInstance System::resolveAtMost(SizeType address) const {
    MemoryInstance ret = MemoryInstance::null;
    auto iterator = mem.lower_bound(address);
    if(iterator != mem.cend()) {
        if(iterator->second.offset == address) {
            ret = iterator->second;
        } else {
            if(iterator != mem.cbegin() && iterator != mem.cend()) {
                iterator--;
                ret = iterator->second;
            }
        }
    }
    return ret;
}

int System::memoryLoop(SizeType offset, SizeType len, const void *data, bool write) const {
    int status = ERR_SUCCESS;
    while(len > 0) {
        MemoryInstance src = resolveAtMost(offset);
        if(!src) {
            status = ERR_BADRANGE;
        } else {
            SizeType srcOff = offset - src.offset;
            SizeType srcLen = std::min(src.length - srcOff, len);
            if(write) {
                status = src.mod->writeMemory(srcOff, srcLen, data);
            } else {
                status = src.mod->readMemory(srcOff, srcLen, /* HACK */(void*)(data));
            }
            if(status == ERR_SUCCESS)
            {
                len -= srcLen;
                offset += srcLen;
                data = advancePtr(data, srcLen);
            } else {
                break;
            }
        }
    }
    return status;
}<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "webkit/plugins/ppapi/webkit_forwarding_impl.h"

#include <string>

#include "base/debug/trace_event.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/utf_string_conversions.h"
#include "ppapi/c/dev/ppb_font_dev.h"
#include "ppapi/c/pp_point.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCanvas.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFont.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFontDescription.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFloatPoint.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFloatRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextRun.h"
#include "webkit/glue/webkit_glue.h"

using ::ppapi::WebKitForwarding;
using WebKit::WebCanvas;
using WebKit::WebFloatPoint;
using WebKit::WebFloatRect;
using WebKit::WebFont;
using WebKit::WebFontDescription;
using WebKit::WebRect;
using WebKit::WebTextRun;

namespace webkit {
namespace ppapi {

namespace {

// The PP_* version lacks "None", so is just one value shifted from the
// WebFontDescription version. These values are checked in
// PPFontDescToWebFontDesc to make sure the conversion is correct. This is a
// macro so it can also be used in the COMPILE_ASSERTS.
#define PP_FONTFAMILY_TO_WEB_FONTFAMILY(f) \
  static_cast<WebFontDescription::GenericFamily>(f + 1)

// Assumes the given PP_FontDescription has been validated.
WebFontDescription PPFontDescToWebFontDesc(const PP_FontDescription_Dev& font,
                                           const std::string& face,
                                           const ::ppapi::Preferences& prefs) {
  // Verify that the enums match so we can just static cast.
  COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight100) ==
                 static_cast<int>(PP_FONTWEIGHT_100),
                 FontWeight100);
  COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight900) ==
                 static_cast<int>(PP_FONTWEIGHT_900),
                 FontWeight900);
  COMPILE_ASSERT(WebFontDescription::GenericFamilyStandard ==
                 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_DEFAULT),
                 StandardFamily);
  COMPILE_ASSERT(WebFontDescription::GenericFamilySerif ==
                 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SERIF),
                 SerifFamily);
  COMPILE_ASSERT(WebFontDescription::GenericFamilySansSerif ==
                 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SANSSERIF),
                 SansSerifFamily);
  COMPILE_ASSERT(WebFontDescription::GenericFamilyMonospace ==
                 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_MONOSPACE),
                 MonospaceFamily);

  WebFontDescription result;
  string16 resolved_family;
  if (face.empty()) {
    // Resolve the generic family.
    switch (font.family) {
      case PP_FONTFAMILY_SERIF:
        resolved_family = prefs.serif_font_family;
        break;
      case PP_FONTFAMILY_SANSSERIF:
        resolved_family = prefs.sans_serif_font_family;
        break;
      case PP_FONTFAMILY_MONOSPACE:
        resolved_family = prefs.fixed_font_family;
        break;
      case PP_FONTFAMILY_DEFAULT:
      default:
        resolved_family = prefs.standard_font_family;
        break;
    }
  } else {
    // Use the exact font.
    resolved_family = UTF8ToUTF16(face);
  }
  result.family = resolved_family;

  result.genericFamily = PP_FONTFAMILY_TO_WEB_FONTFAMILY(font.family);

  if (font.size == 0) {
    // Resolve the default font size, using the resolved family to see if
    // we should use the fixed or regular font size. It's difficult at this
    // level to detect if the requested font is fixed width, so we only apply
    // the alternate font size to the default fixed font family.
    if (StringToLowerASCII(resolved_family) ==
        StringToLowerASCII(prefs.fixed_font_family))
      result.size = static_cast<float>(prefs.default_fixed_font_size);
    else
      result.size = static_cast<float>(prefs.default_font_size);
  } else {
    // Use the exact size.
    result.size = static_cast<float>(font.size);
  }

  result.italic = font.italic != PP_FALSE;
  result.smallCaps = font.small_caps != PP_FALSE;
  result.weight = static_cast<WebFontDescription::Weight>(font.weight);
  result.letterSpacing = static_cast<short>(font.letter_spacing);
  result.wordSpacing = static_cast<short>(font.word_spacing);
  return result;
}

WebTextRun TextRunToWebTextRun(const WebKitForwarding::Font::TextRun& run) {
  return WebTextRun(UTF8ToUTF16(run.text),
                    run.rtl != PP_FALSE,
                    run.override_direction != PP_FALSE);
}

// FontImpl --------------------------------------------------------------------

class FontImpl : public WebKitForwarding::Font {
 public:
  FontImpl(const PP_FontDescription_Dev& desc,
           const std::string& desc_face,
           const ::ppapi::Preferences& prefs);
  virtual ~FontImpl();

  virtual void Describe(base::WaitableEvent* event,
                        PP_FontDescription_Dev* description,
                        std::string* face,
                        PP_FontMetrics_Dev* metrics,
                        PP_Bool* result) OVERRIDE;
  virtual void DrawTextAt(base::WaitableEvent* event,
                          const DrawTextParams& params) OVERRIDE;
  virtual void MeasureText(base::WaitableEvent* event,
                           const TextRun& text,
                           int32_t* result) OVERRIDE;
  virtual void CharacterOffsetForPixel(base::WaitableEvent* event,
                                       const TextRun& text,
                                       int32_t pixel_position,
                                       uint32_t* result) OVERRIDE;
  virtual void PixelOffsetForCharacter(base::WaitableEvent* event,
                                       const TextRun& text,
                                       uint32_t char_offset,
                                       int32_t* result) OVERRIDE;

 private:
  scoped_ptr<WebFont> font_;

  DISALLOW_COPY_AND_ASSIGN(FontImpl);
};

FontImpl::FontImpl(const PP_FontDescription_Dev& desc,
                   const std::string& desc_face,
                   const ::ppapi::Preferences& prefs) {
  WebFontDescription web_font_desc = PPFontDescToWebFontDesc(desc, desc_face,
                                                             prefs);
  font_.reset(WebFont::create(web_font_desc));
}

FontImpl::~FontImpl() {
}

void FontImpl::Describe(base::WaitableEvent* event,
                        PP_FontDescription_Dev* description,
                        std::string* face,
                        PP_FontMetrics_Dev* metrics,
                        PP_Bool* result) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::Describe");
  if (description->face.type != PP_VARTYPE_UNDEFINED) {
    *result = PP_FALSE;
  } else {
    WebFontDescription web_desc = font_->fontDescription();

    // While converting the other way in PPFontDescToWebFontDesc we validated
    // that the enums can be casted.
    description->face = PP_MakeUndefined();
    description->family =
        static_cast<PP_FontFamily_Dev>(web_desc.genericFamily);
    description->size = static_cast<uint32_t>(web_desc.size);
    description->weight = static_cast<PP_FontWeight_Dev>(web_desc.weight);
    description->italic = web_desc.italic ? PP_TRUE : PP_FALSE;
    description->small_caps = web_desc.smallCaps ? PP_TRUE : PP_FALSE;

    *face = UTF16ToUTF8(web_desc.family);

    metrics->height = font_->height();
    metrics->ascent = font_->ascent();
    metrics->descent = font_->descent();
    metrics->line_spacing = font_->lineSpacing();
    metrics->x_height = static_cast<int32_t>(font_->xHeight());

    *result = PP_TRUE;
  }
  if (event)
    event->Signal();
}

void FontImpl::DrawTextAt(base::WaitableEvent* event,
                          const DrawTextParams& params) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::DrawTextAt");
  WebTextRun run = TextRunToWebTextRun(params.text);

  // Convert position and clip.
  WebFloatPoint web_position(static_cast<float>(params.position->x),
                             static_cast<float>(params.position->y));
  WebRect web_clip;
  if (!params.clip) {
    // Use entire canvas. SkCanvas doesn't have a size on it, so we just use
    // the current clip bounds.
    SkRect skclip;
    params.destination->getClipBounds(&skclip);
    web_clip = WebRect(skclip.fLeft, skclip.fTop, skclip.fRight - skclip.fLeft,
                       skclip.fBottom - skclip.fTop);
  } else {
    web_clip = WebRect(params.clip->point.x, params.clip->point.y,
                       params.clip->size.width, params.clip->size.height);
  }

  font_->drawText(webkit_glue::ToWebCanvas(params.destination), run,
                  web_position, params.color, web_clip,
                  params.image_data_is_opaque == PP_TRUE);
  if (event)
    event->Signal();
}

void FontImpl::MeasureText(base::WaitableEvent* event,
                           const TextRun& text, int32_t* result) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::MeasureText");
  *result = font_->calculateWidth(TextRunToWebTextRun(text));
  if (event)
    event->Signal();
}

void FontImpl::CharacterOffsetForPixel(base::WaitableEvent* event,
                                       const TextRun& text,
                                       int32_t pixel_position,
                                       uint32_t* result) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::CharacterOffsetForPixel");
  *result = static_cast<uint32_t>(font_->offsetForPosition(
      TextRunToWebTextRun(text), static_cast<float>(pixel_position)));
  if (event)
    event->Signal();
}

void FontImpl::PixelOffsetForCharacter(base::WaitableEvent* event,
                                       const TextRun& text,
                                       uint32_t char_offset,
                                       int32_t* result) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::PixelOffsetForCharacter");
  WebTextRun run = TextRunToWebTextRun(text);
  if (char_offset >= run.text.length()) {
    *result = -1;
  } else {
    WebFloatRect rect = font_->selectionRectForText(
        run, WebFloatPoint(0.0f, 0.0f), font_->height(), 0, char_offset);
    *result = static_cast<int>(rect.width);
  }
  if (event)
    event->Signal();
}

}  // namespace

// WebKitForwardingImpl --------------------------------------------------------

WebKitForwardingImpl::WebKitForwardingImpl() {
}

WebKitForwardingImpl::~WebKitForwardingImpl() {
}

void WebKitForwardingImpl::CreateFontForwarding(
    base::WaitableEvent* event,
    const PP_FontDescription_Dev& desc,
    const std::string& desc_face,
    const ::ppapi::Preferences& prefs,
    Font** result) {
  TRACE_EVENT0("ppapi WebKit thread",
               "WebKitForwardingImpl::CreateFontForwarding");
  *result = new FontImpl(desc, desc_face, prefs);
  if (event)
    event->Signal();
}

}  // namespace ppapi
}  // namespace webkit
<commit_msg>Copy 2 missing fields of PP_FontDescription_Dev.<commit_after>// Copyright (c) 2011 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 "webkit/plugins/ppapi/webkit_forwarding_impl.h"

#include <string>

#include "base/debug/trace_event.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/utf_string_conversions.h"
#include "ppapi/c/dev/ppb_font_dev.h"
#include "ppapi/c/pp_point.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCanvas.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFont.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFontDescription.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFloatPoint.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFloatRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextRun.h"
#include "webkit/glue/webkit_glue.h"

using ::ppapi::WebKitForwarding;
using WebKit::WebCanvas;
using WebKit::WebFloatPoint;
using WebKit::WebFloatRect;
using WebKit::WebFont;
using WebKit::WebFontDescription;
using WebKit::WebRect;
using WebKit::WebTextRun;

namespace webkit {
namespace ppapi {

namespace {

// The PP_* version lacks "None", so is just one value shifted from the
// WebFontDescription version. These values are checked in
// PPFontDescToWebFontDesc to make sure the conversion is correct. This is a
// macro so it can also be used in the COMPILE_ASSERTS.
#define PP_FONTFAMILY_TO_WEB_FONTFAMILY(f) \
  static_cast<WebFontDescription::GenericFamily>(f + 1)

// Assumes the given PP_FontDescription has been validated.
WebFontDescription PPFontDescToWebFontDesc(const PP_FontDescription_Dev& font,
                                           const std::string& face,
                                           const ::ppapi::Preferences& prefs) {
  // Verify that the enums match so we can just static cast.
  COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight100) ==
                 static_cast<int>(PP_FONTWEIGHT_100),
                 FontWeight100);
  COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight900) ==
                 static_cast<int>(PP_FONTWEIGHT_900),
                 FontWeight900);
  COMPILE_ASSERT(WebFontDescription::GenericFamilyStandard ==
                 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_DEFAULT),
                 StandardFamily);
  COMPILE_ASSERT(WebFontDescription::GenericFamilySerif ==
                 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SERIF),
                 SerifFamily);
  COMPILE_ASSERT(WebFontDescription::GenericFamilySansSerif ==
                 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SANSSERIF),
                 SansSerifFamily);
  COMPILE_ASSERT(WebFontDescription::GenericFamilyMonospace ==
                 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_MONOSPACE),
                 MonospaceFamily);

  WebFontDescription result;
  string16 resolved_family;
  if (face.empty()) {
    // Resolve the generic family.
    switch (font.family) {
      case PP_FONTFAMILY_SERIF:
        resolved_family = prefs.serif_font_family;
        break;
      case PP_FONTFAMILY_SANSSERIF:
        resolved_family = prefs.sans_serif_font_family;
        break;
      case PP_FONTFAMILY_MONOSPACE:
        resolved_family = prefs.fixed_font_family;
        break;
      case PP_FONTFAMILY_DEFAULT:
      default:
        resolved_family = prefs.standard_font_family;
        break;
    }
  } else {
    // Use the exact font.
    resolved_family = UTF8ToUTF16(face);
  }
  result.family = resolved_family;

  result.genericFamily = PP_FONTFAMILY_TO_WEB_FONTFAMILY(font.family);

  if (font.size == 0) {
    // Resolve the default font size, using the resolved family to see if
    // we should use the fixed or regular font size. It's difficult at this
    // level to detect if the requested font is fixed width, so we only apply
    // the alternate font size to the default fixed font family.
    if (StringToLowerASCII(resolved_family) ==
        StringToLowerASCII(prefs.fixed_font_family))
      result.size = static_cast<float>(prefs.default_fixed_font_size);
    else
      result.size = static_cast<float>(prefs.default_font_size);
  } else {
    // Use the exact size.
    result.size = static_cast<float>(font.size);
  }

  result.italic = font.italic != PP_FALSE;
  result.smallCaps = font.small_caps != PP_FALSE;
  result.weight = static_cast<WebFontDescription::Weight>(font.weight);
  result.letterSpacing = static_cast<short>(font.letter_spacing);
  result.wordSpacing = static_cast<short>(font.word_spacing);
  return result;
}

WebTextRun TextRunToWebTextRun(const WebKitForwarding::Font::TextRun& run) {
  return WebTextRun(UTF8ToUTF16(run.text),
                    run.rtl != PP_FALSE,
                    run.override_direction != PP_FALSE);
}

// FontImpl --------------------------------------------------------------------

class FontImpl : public WebKitForwarding::Font {
 public:
  FontImpl(const PP_FontDescription_Dev& desc,
           const std::string& desc_face,
           const ::ppapi::Preferences& prefs);
  virtual ~FontImpl();

  virtual void Describe(base::WaitableEvent* event,
                        PP_FontDescription_Dev* description,
                        std::string* face,
                        PP_FontMetrics_Dev* metrics,
                        PP_Bool* result) OVERRIDE;
  virtual void DrawTextAt(base::WaitableEvent* event,
                          const DrawTextParams& params) OVERRIDE;
  virtual void MeasureText(base::WaitableEvent* event,
                           const TextRun& text,
                           int32_t* result) OVERRIDE;
  virtual void CharacterOffsetForPixel(base::WaitableEvent* event,
                                       const TextRun& text,
                                       int32_t pixel_position,
                                       uint32_t* result) OVERRIDE;
  virtual void PixelOffsetForCharacter(base::WaitableEvent* event,
                                       const TextRun& text,
                                       uint32_t char_offset,
                                       int32_t* result) OVERRIDE;

 private:
  scoped_ptr<WebFont> font_;

  DISALLOW_COPY_AND_ASSIGN(FontImpl);
};

FontImpl::FontImpl(const PP_FontDescription_Dev& desc,
                   const std::string& desc_face,
                   const ::ppapi::Preferences& prefs) {
  WebFontDescription web_font_desc = PPFontDescToWebFontDesc(desc, desc_face,
                                                             prefs);
  font_.reset(WebFont::create(web_font_desc));
}

FontImpl::~FontImpl() {
}

void FontImpl::Describe(base::WaitableEvent* event,
                        PP_FontDescription_Dev* description,
                        std::string* face,
                        PP_FontMetrics_Dev* metrics,
                        PP_Bool* result) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::Describe");
  if (description->face.type != PP_VARTYPE_UNDEFINED) {
    *result = PP_FALSE;
  } else {
    WebFontDescription web_desc = font_->fontDescription();

    // While converting the other way in PPFontDescToWebFontDesc we validated
    // that the enums can be casted.
    description->face = PP_MakeUndefined();
    description->family =
        static_cast<PP_FontFamily_Dev>(web_desc.genericFamily);
    description->size = static_cast<uint32_t>(web_desc.size);
    description->weight = static_cast<PP_FontWeight_Dev>(web_desc.weight);
    description->italic = web_desc.italic ? PP_TRUE : PP_FALSE;
    description->small_caps = web_desc.smallCaps ? PP_TRUE : PP_FALSE;
    description->letter_spacing = static_cast<int32_t>(web_desc.letterSpacing);
    description->word_spacing = static_cast<int32_t>(web_desc.wordSpacing);

    *face = UTF16ToUTF8(web_desc.family);

    metrics->height = font_->height();
    metrics->ascent = font_->ascent();
    metrics->descent = font_->descent();
    metrics->line_spacing = font_->lineSpacing();
    metrics->x_height = static_cast<int32_t>(font_->xHeight());

    *result = PP_TRUE;
  }
  if (event)
    event->Signal();
}

void FontImpl::DrawTextAt(base::WaitableEvent* event,
                          const DrawTextParams& params) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::DrawTextAt");
  WebTextRun run = TextRunToWebTextRun(params.text);

  // Convert position and clip.
  WebFloatPoint web_position(static_cast<float>(params.position->x),
                             static_cast<float>(params.position->y));
  WebRect web_clip;
  if (!params.clip) {
    // Use entire canvas. SkCanvas doesn't have a size on it, so we just use
    // the current clip bounds.
    SkRect skclip;
    params.destination->getClipBounds(&skclip);
    web_clip = WebRect(skclip.fLeft, skclip.fTop, skclip.fRight - skclip.fLeft,
                       skclip.fBottom - skclip.fTop);
  } else {
    web_clip = WebRect(params.clip->point.x, params.clip->point.y,
                       params.clip->size.width, params.clip->size.height);
  }

  font_->drawText(webkit_glue::ToWebCanvas(params.destination), run,
                  web_position, params.color, web_clip,
                  params.image_data_is_opaque == PP_TRUE);
  if (event)
    event->Signal();
}

void FontImpl::MeasureText(base::WaitableEvent* event,
                           const TextRun& text, int32_t* result) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::MeasureText");
  *result = font_->calculateWidth(TextRunToWebTextRun(text));
  if (event)
    event->Signal();
}

void FontImpl::CharacterOffsetForPixel(base::WaitableEvent* event,
                                       const TextRun& text,
                                       int32_t pixel_position,
                                       uint32_t* result) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::CharacterOffsetForPixel");
  *result = static_cast<uint32_t>(font_->offsetForPosition(
      TextRunToWebTextRun(text), static_cast<float>(pixel_position)));
  if (event)
    event->Signal();
}

void FontImpl::PixelOffsetForCharacter(base::WaitableEvent* event,
                                       const TextRun& text,
                                       uint32_t char_offset,
                                       int32_t* result) {
  TRACE_EVENT0("ppapi WebKit thread", "FontImpl::PixelOffsetForCharacter");
  WebTextRun run = TextRunToWebTextRun(text);
  if (char_offset >= run.text.length()) {
    *result = -1;
  } else {
    WebFloatRect rect = font_->selectionRectForText(
        run, WebFloatPoint(0.0f, 0.0f), font_->height(), 0, char_offset);
    *result = static_cast<int>(rect.width);
  }
  if (event)
    event->Signal();
}

}  // namespace

// WebKitForwardingImpl --------------------------------------------------------

WebKitForwardingImpl::WebKitForwardingImpl() {
}

WebKitForwardingImpl::~WebKitForwardingImpl() {
}

void WebKitForwardingImpl::CreateFontForwarding(
    base::WaitableEvent* event,
    const PP_FontDescription_Dev& desc,
    const std::string& desc_face,
    const ::ppapi::Preferences& prefs,
    Font** result) {
  TRACE_EVENT0("ppapi WebKit thread",
               "WebKitForwardingImpl::CreateFontForwarding");
  *result = new FontImpl(desc, desc_face, prefs);
  if (event)
    event->Signal();
}

}  // namespace ppapi
}  // namespace webkit
<|endoftext|>