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

#include "src/core/lib/gpr/arena.h"

#include <inttypes.h>
#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>

#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/thd.h"
#include "test/core/util/test_config.h"

static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); }

static void test(const char* name, size_t init_size, const size_t* allocs,
                 size_t nallocs) {
  gpr_strvec v;
  char* s;
  gpr_strvec_init(&v);
  gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size);
  gpr_strvec_add(&v, s);
  for (size_t i = 0; i < nallocs; i++) {
    gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]);
    gpr_strvec_add(&v, s);
  }
  gpr_strvec_add(&v, gpr_strdup("}"));
  s = gpr_strvec_flatten(&v, nullptr);
  gpr_strvec_destroy(&v);
  gpr_log(GPR_INFO, "%s", s);
  gpr_free(s);

  gpr_arena* a = gpr_arena_create(init_size);
  void** ps = static_cast<void**>(gpr_zalloc(sizeof(*ps) * nallocs));
  for (size_t i = 0; i < nallocs; i++) {
    ps[i] = gpr_arena_alloc(a, allocs[i]);
    // ensure the returned address is aligned
    GPR_ASSERT(((intptr_t)ps[i] & 0xf) == 0);
    // ensure no duplicate results
    for (size_t j = 0; j < i; j++) {
      GPR_ASSERT(ps[i] != ps[j]);
    }
    // ensure writable
    memset(ps[i], 1, allocs[i]);
  }
  gpr_arena_destroy(a);
  gpr_free(ps);
}

#define TEST(name, init_size, ...)                     \
  static const size_t allocs_##name[] = {__VA_ARGS__}; \
  test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name))

#define CONCURRENT_TEST_THREADS 100

size_t concurrent_test_iterations() {
  if (sizeof(void*) < 8) return 1000;
  return 100000;
}

typedef struct {
  gpr_event ev_start;
  gpr_arena* arena;
} concurrent_test_args;

static void concurrent_test_body(void* arg) {
  concurrent_test_args* a = static_cast<concurrent_test_args*>(arg);
  gpr_event_wait(&a->ev_start, gpr_inf_future(GPR_CLOCK_REALTIME));
  for (size_t i = 0; i < concurrent_test_iterations(); i++) {
    *static_cast<char*>(gpr_arena_alloc(a->arena, 1)) = static_cast<char>(i);
  }
}

static void concurrent_test(void) {
  gpr_log(GPR_DEBUG, "concurrent_test");

  concurrent_test_args args;
  gpr_event_init(&args.ev_start);
  args.arena = gpr_arena_create(1024);

  grpc_core::Thread thds[CONCURRENT_TEST_THREADS];

  for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
    thds[i] =
        grpc_core::Thread("grpc_concurrent_test", concurrent_test_body, &args);
    thds[i].Start();
  }

  gpr_event_set(&args.ev_start, (void*)1);

  for (auto& th : thds) {
    th.Join();
  }

  gpr_arena_destroy(args.arena);
}

int main(int argc, char* argv[]) {
  grpc_test_init(argc, argv);

  test_noop();
  TEST(0_1, 0, 1);
  TEST(1_1, 1, 1);
  TEST(1_2, 1, 2);
  TEST(1_3, 1, 3);
  TEST(1_inc, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
  TEST(6_123, 6, 1, 2, 3);
  concurrent_test();

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

#include "src/core/lib/gpr/arena.h"

#include <inttypes.h>
#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>

#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/thd.h"
#include "test/core/util/test_config.h"

static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); }

static void test(const char* name, size_t init_size, const size_t* allocs,
                 size_t nallocs) {
  gpr_strvec v;
  char* s;
  gpr_strvec_init(&v);
  gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size);
  gpr_strvec_add(&v, s);
  for (size_t i = 0; i < nallocs; i++) {
    gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]);
    gpr_strvec_add(&v, s);
  }
  gpr_strvec_add(&v, gpr_strdup("}"));
  s = gpr_strvec_flatten(&v, nullptr);
  gpr_strvec_destroy(&v);
  gpr_log(GPR_INFO, "%s", s);
  gpr_free(s);

  gpr_arena* a = gpr_arena_create(init_size);
  void** ps = static_cast<void**>(gpr_zalloc(sizeof(*ps) * nallocs));
  for (size_t i = 0; i < nallocs; i++) {
    ps[i] = gpr_arena_alloc(a, allocs[i]);
    // ensure the returned address is aligned
    GPR_ASSERT(((intptr_t)ps[i] & 0xf) == 0);
    // ensure no duplicate results
    for (size_t j = 0; j < i; j++) {
      GPR_ASSERT(ps[i] != ps[j]);
    }
    // ensure writable
    memset(ps[i], 1, allocs[i]);
  }
  gpr_arena_destroy(a);
  gpr_free(ps);
}

#define TEST(name, init_size, ...)                     \
  static const size_t allocs_##name[] = {__VA_ARGS__}; \
  test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name))

#define CONCURRENT_TEST_THREADS 10

size_t concurrent_test_iterations() {
  if (sizeof(void*) < 8) return 1000;
  return 100000;
}

typedef struct {
  gpr_event ev_start;
  gpr_arena* arena;
} concurrent_test_args;

static void concurrent_test_body(void* arg) {
  concurrent_test_args* a = static_cast<concurrent_test_args*>(arg);
  gpr_event_wait(&a->ev_start, gpr_inf_future(GPR_CLOCK_REALTIME));
  for (size_t i = 0; i < concurrent_test_iterations(); i++) {
    *static_cast<char*>(gpr_arena_alloc(a->arena, 1)) = static_cast<char>(i);
  }
}

static void concurrent_test(void) {
  gpr_log(GPR_DEBUG, "concurrent_test");

  concurrent_test_args args;
  gpr_event_init(&args.ev_start);
  args.arena = gpr_arena_create(1024);

  grpc_core::Thread thds[CONCURRENT_TEST_THREADS];

  for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
    thds[i] =
        grpc_core::Thread("grpc_concurrent_test", concurrent_test_body, &args);
    thds[i].Start();
  }

  gpr_event_set(&args.ev_start, (void*)1);

  for (auto& th : thds) {
    th.Join();
  }

  gpr_arena_destroy(args.arena);
}

int main(int argc, char* argv[]) {
  grpc_test_init(argc, argv);

  test_noop();
  TEST(0_1, 0, 1);
  TEST(1_1, 1, 1);
  TEST(1_2, 1, 2);
  TEST(1_3, 1, 3);
  TEST(1_inc, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
  TEST(6_123, 6, 1, 2, 3);
  concurrent_test();

  return 0;
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "test/cpp/qps/limit_cores.h"

#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>

#ifdef GPR_CPU_LINUX
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <sched.h>

namespace grpc {
namespace testing {

int LimitCores(const int* cores, int cores_size) {
  const int num_cores = gpr_cpu_num_cores();
  int cores_set = 0;

  cpu_set_t* cpup = CPU_ALLOC(num_cores);
  GPR_ASSERT(cpup);
  const size_t size = CPU_ALLOC_SIZE(num_cores);
  CPU_ZERO_S(size, cpup);

  if (cores_size > 0) {
    for (int i = 0; i < cores_size; i++) {
      if (cores[i] < num_cores) {
        CPU_SET_S(cores[i], size, cpup);
        cores_set++;
      }
    }
  } else {
    for (int i = 0; i < num_cores; i++) {
      CPU_SET_S(i, size, cpup);
      cores_set++;
    }
  }
  GPR_ASSERT(sched_setaffinity(0, size, cpup) == 0);
  CPU_FREE(cpup);
  return cores_set;
}
#else

namespace grpc {
namespace testing {

// LimitCores is not currently supported for non-Linux platforms
int LimitCores(const int*, int) { return gpr_cpu_num_cores(); }
#endif
}  // namespace testing
}  // namespace grpc
<commit_msg>Made the code simpler to parse for humans<commit_after>/*
 *
 * Copyright 2016, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "test/cpp/qps/limit_cores.h"

#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>

#ifdef GPR_CPU_LINUX
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <sched.h>

namespace grpc {
namespace testing {

int LimitCores(const int* cores, int cores_size) {
  const int num_cores = gpr_cpu_num_cores();
  int cores_set = 0;

  cpu_set_t* cpup = CPU_ALLOC(num_cores);
  GPR_ASSERT(cpup);
  const size_t size = CPU_ALLOC_SIZE(num_cores);
  CPU_ZERO_S(size, cpup);

  if (cores_size > 0) {
    for (int i = 0; i < cores_size; i++) {
      if (cores[i] < num_cores) {
        CPU_SET_S(cores[i], size, cpup);
        cores_set++;
      }
    }
  } else {
    for (int i = 0; i < num_cores; i++) {
      CPU_SET_S(i, size, cpup);
      cores_set++;
    }
  }
  GPR_ASSERT(sched_setaffinity(0, size, cpup) == 0);
  CPU_FREE(cpup);
  return cores_set;
}

}  // namespace testing
}  // namespace grpc
#else
namespace grpc {
namespace testing {

// LimitCores is not currently supported for non-Linux platforms
int LimitCores(const int*, int) { return gpr_cpu_num_cores(); }

}  // namespace testing
}  // namespace grpc
#endif
<|endoftext|>


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

// CLASS HEADER
#include <dali-toolkit/internal/visuals/npatch-loader.h>

// INTERNAL HEADERS
#include <dali-toolkit/internal/visuals/rendering-addon.h>

// EXTERNAL HEADERS
#include <dali/devel-api/common/hash.h>
#include <dali/integration-api/debug.h>

namespace Dali
{

namespace Toolkit
{

namespace Internal
{

namespace
{

constexpr auto INVALID_CACHE_INDEX = int32_t{-1}; ///< Invalid Cache index
constexpr auto UNINITIALIZED_ID = int32_t{0}; ///< uninitialised id, use to initialize ids

} // Anonymous namespace

NPatchLoader::NPatchLoader()
: mCurrentNPatchDataId(0)
{
}

NPatchLoader::~NPatchLoader()
{
}

NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
{
  return mCurrentNPatchDataId++;
}

std::size_t NPatchLoader::Load( TextureManager& textureManager, TextureUploadObserver* textureObserver, const std::string& url, const Rect< int >& border, bool& preMultiplyOnLoad, bool synchronousLoading )
{
  std::size_t hash = CalculateHash( url );
  OwnerContainer< NPatchData* >::SizeType index = UNINITIALIZED_ID;
  const OwnerContainer< NPatchData* >::SizeType count = mCache.Count();

  for( ; index < count; ++index )
  {
    if( mCache[ index ]->GetHash() == hash )
    {
      // hash match, check url as well in case of hash collision
      if(mCache[ index ]->GetUrl() == url)
      {
        // Use cached data
        if( mCache[ index ]->GetBorder() == border )
        {
          if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOADING )
          {
            mCache[ index ]->AddObserver( textureObserver );
          }
          return mCache[ index ]->GetId(); // valid indices are from 1 onwards
        }
        else
        {
          if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
          {
            // Same url but border is different - use the existing texture
            NPatchData* newData = new NPatchData();
            newData->SetId(GenerateUniqueNPatchDataId());
            newData->SetHash(hash);
            newData->SetUrl(url);
            newData->SetCroppedWidth(mCache[ index ]->GetCroppedWidth());
            newData->SetCroppedHeight(mCache[ index ]->GetCroppedHeight());

            newData->SetTextures(mCache[ index ]->GetTextures());

            NPatchUtility::StretchRanges stretchRangesX;
            stretchRangesX.PushBack( Uint16Pair( border.left, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.right )) ? newData->GetCroppedHeight() - border.right : 0 ) ) );

            NPatchUtility::StretchRanges stretchRangesY;
            stretchRangesY.PushBack( Uint16Pair( border.top, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.bottom )) ? newData->GetCroppedHeight() - border.bottom : 0 ) ) );

            newData->SetStretchPixelsX(stretchRangesX);
            newData->SetStretchPixelsY(stretchRangesY);
            newData->SetBorder(border);

            newData->SetPreMultiplyOnLoad(mCache[ index ]->IsPreMultiplied());

            newData->SetLoadingState(NPatchData::LoadingState::LOAD_COMPLETE);
            newData->AddObserver( textureObserver );

            mCache.PushBack( newData );

            return newData->GetId(); // valid ids start from 1u
          }
        }
      }
    }
  }

  // If this is new image loading, make new cache data
  NPatchData* data;
  data = new NPatchData();
  data->SetId(GenerateUniqueNPatchDataId());
  data->SetHash(hash);
  data->SetUrl(url);
  data->SetBorder(border);
  data->SetPreMultiplyOnLoad(preMultiplyOnLoad);
  data->AddObserver(textureObserver);
  mCache.PushBack(data);

  auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
                                                : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;

  Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer( url, Dali::ImageDimensions(), FittingMode::DEFAULT,
                                                                   SamplingMode::BOX_THEN_LINEAR, synchronousLoading,
                                                                   data, true, preMultiplyOnLoading );

  if( pixelBuffer )
  {
    preMultiplyOnLoad = ( preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ) ? true : false;
    data->SetLoadedNPatchData( pixelBuffer, preMultiplyOnLoad );
  }

  return data->GetId();
}

int32_t NPatchLoader::GetCacheIndexFromId( const NPatchData::NPatchDataId id )
{
  const unsigned int size = mCache.Count();

  for( unsigned int i = 0; i < size; ++i )
  {
    if( mCache[i]->GetId() == id )
    {
      return i;
    }
  }

  DALI_LOG_ERROR("Wrong NPatchDataId is used\n");
  return INVALID_CACHE_INDEX;
}

bool NPatchLoader::GetNPatchData( const NPatchData::NPatchDataId id, const NPatchData*& data )
{
  int32_t cacheIndex = GetCacheIndexFromId(id);
  if( cacheIndex != INVALID_CACHE_INDEX )
  {
    data = mCache[cacheIndex];
    return true;
  }
  data = nullptr;
  return false;
}

void NPatchLoader::Remove( std::size_t id, TextureUploadObserver* textureObserver )
{
  int32_t cacheIndex = GetCacheIndexFromId(id);
  if( cacheIndex == INVALID_CACHE_INDEX )
  {
    return;
  }

  NPatchData* data;
  data = mCache[cacheIndex];

  data->RemoveObserver(textureObserver);

  if(data->GetObserverCount() == 0)
  {
      mCache.Erase( mCache.Begin() + cacheIndex );
  }
}

} // namespace Internal

} // namespace Toolkit

} // namespace Dali
<commit_msg>Remove unnecessary log in the npatch-loader<commit_after> /*
 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// CLASS HEADER
#include <dali-toolkit/internal/visuals/npatch-loader.h>

// INTERNAL HEADERS
#include <dali-toolkit/internal/visuals/rendering-addon.h>

// EXTERNAL HEADERS
#include <dali/devel-api/common/hash.h>
#include <dali/integration-api/debug.h>

namespace Dali
{

namespace Toolkit
{

namespace Internal
{

namespace
{

constexpr auto INVALID_CACHE_INDEX = int32_t{-1}; ///< Invalid Cache index
constexpr auto UNINITIALIZED_ID = int32_t{0}; ///< uninitialised id, use to initialize ids

} // Anonymous namespace

NPatchLoader::NPatchLoader()
: mCurrentNPatchDataId(0)
{
}

NPatchLoader::~NPatchLoader()
{
}

NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
{
  return mCurrentNPatchDataId++;
}

std::size_t NPatchLoader::Load( TextureManager& textureManager, TextureUploadObserver* textureObserver, const std::string& url, const Rect< int >& border, bool& preMultiplyOnLoad, bool synchronousLoading )
{
  std::size_t hash = CalculateHash( url );
  OwnerContainer< NPatchData* >::SizeType index = UNINITIALIZED_ID;
  const OwnerContainer< NPatchData* >::SizeType count = mCache.Count();

  for( ; index < count; ++index )
  {
    if( mCache[ index ]->GetHash() == hash )
    {
      // hash match, check url as well in case of hash collision
      if(mCache[ index ]->GetUrl() == url)
      {
        // Use cached data
        if( mCache[ index ]->GetBorder() == border )
        {
          if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOADING )
          {
            mCache[ index ]->AddObserver( textureObserver );
          }
          return mCache[ index ]->GetId(); // valid indices are from 1 onwards
        }
        else
        {
          if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
          {
            // Same url but border is different - use the existing texture
            NPatchData* newData = new NPatchData();
            newData->SetId(GenerateUniqueNPatchDataId());
            newData->SetHash(hash);
            newData->SetUrl(url);
            newData->SetCroppedWidth(mCache[ index ]->GetCroppedWidth());
            newData->SetCroppedHeight(mCache[ index ]->GetCroppedHeight());

            newData->SetTextures(mCache[ index ]->GetTextures());

            NPatchUtility::StretchRanges stretchRangesX;
            stretchRangesX.PushBack( Uint16Pair( border.left, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.right )) ? newData->GetCroppedHeight() - border.right : 0 ) ) );

            NPatchUtility::StretchRanges stretchRangesY;
            stretchRangesY.PushBack( Uint16Pair( border.top, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.bottom )) ? newData->GetCroppedHeight() - border.bottom : 0 ) ) );

            newData->SetStretchPixelsX(stretchRangesX);
            newData->SetStretchPixelsY(stretchRangesY);
            newData->SetBorder(border);

            newData->SetPreMultiplyOnLoad(mCache[ index ]->IsPreMultiplied());

            newData->SetLoadingState(NPatchData::LoadingState::LOAD_COMPLETE);
            newData->AddObserver( textureObserver );

            mCache.PushBack( newData );

            return newData->GetId(); // valid ids start from 1u
          }
        }
      }
    }
  }

  // If this is new image loading, make new cache data
  NPatchData* data;
  data = new NPatchData();
  data->SetId(GenerateUniqueNPatchDataId());
  data->SetHash(hash);
  data->SetUrl(url);
  data->SetBorder(border);
  data->SetPreMultiplyOnLoad(preMultiplyOnLoad);
  data->AddObserver(textureObserver);
  mCache.PushBack(data);

  auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
                                                : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;

  Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer( url, Dali::ImageDimensions(), FittingMode::DEFAULT,
                                                                   SamplingMode::BOX_THEN_LINEAR, synchronousLoading,
                                                                   data, true, preMultiplyOnLoading );

  if( pixelBuffer )
  {
    preMultiplyOnLoad = ( preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ) ? true : false;
    data->SetLoadedNPatchData( pixelBuffer, preMultiplyOnLoad );
  }

  return data->GetId();
}

int32_t NPatchLoader::GetCacheIndexFromId( const NPatchData::NPatchDataId id )
{
  const unsigned int size = mCache.Count();

  for( unsigned int i = 0; i < size; ++i )
  {
    if( mCache[i]->GetId() == id )
    {
      return i;
    }
  }

  return INVALID_CACHE_INDEX;
}

bool NPatchLoader::GetNPatchData( const NPatchData::NPatchDataId id, const NPatchData*& data )
{
  int32_t cacheIndex = GetCacheIndexFromId(id);
  if( cacheIndex != INVALID_CACHE_INDEX )
  {
    data = mCache[cacheIndex];
    return true;
  }
  data = nullptr;
  return false;
}

void NPatchLoader::Remove( std::size_t id, TextureUploadObserver* textureObserver )
{
  int32_t cacheIndex = GetCacheIndexFromId(id);
  if( cacheIndex == INVALID_CACHE_INDEX )
  {
    return;
  }

  NPatchData* data;
  data = mCache[cacheIndex];

  data->RemoveObserver(textureObserver);

  if(data->GetObserverCount() == 0)
  {
      mCache.Erase( mCache.Begin() + cacheIndex );
  }
}

} // namespace Internal

} // namespace Toolkit

} // namespace Dali
<|endoftext|>


<commit_before><commit_msg>Fix bug in localize, created by recently changes<commit_after><|endoftext|>


<commit_before>#include "ExecutionEngine.h"

#include <chrono>
#include <cstdlib>	// env options

#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#pragma warning(push)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Host.h>

#include "Runtime.h"
#include "Compiler.h"
#include "Cache.h"

namespace dev
{
namespace eth
{
namespace jit
{

namespace
{
typedef ReturnCode(*EntryFuncPtr)(Runtime*);

ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime)
{
	// That function uses long jumps to handle "execeptions".
	// Do not create any non-POD objects here

	ReturnCode returnCode{};
	auto sj = setjmp(_runtime->getJmpBuf());
	if (sj == 0)
		returnCode = _mainFunc(_runtime);
	else
		returnCode = static_cast<ReturnCode>(sj);

	return returnCode;
}

std::string codeHash(bytes const& _code)
{
	uint32_t hash = 0;
	for (auto b : _code)
	{
		hash += b;
		hash += (hash << 10);
		hash ^= (hash >> 6);
	}
	hash += (hash << 3);
	hash ^= (hash >> 11);
	hash += (hash << 15);
	return std::to_string(hash);
}

bool getEnvOption(char const* _name, bool _default)
{
	auto var = std::getenv(_name);
	if (!var)
		return _default;
	return std::strtol(var, nullptr, 10) != 0;
}

}

ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env)
{
	static std::unique_ptr<llvm::ExecutionEngine> ee;  // TODO: Use Managed Objects from LLVM?
	static auto debugDumpModule = getEnvOption("EVMJIT_DUMP", false);
	static auto objectCacheEnabled = getEnvOption("EVMJIT_CACHE", true);

	auto mainFuncName = codeHash(_code);
	EntryFuncPtr entryFuncPtr{};
	Runtime runtime(_data, _env);	// TODO: I don't know why but it must be created before getFunctionAddress() calls

	if (ee && (entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName)))
	{
	}
	else
	{
		auto objectCache = objectCacheEnabled ? Cache::getObjectCache() : nullptr;
		std::unique_ptr<llvm::Module> module;
		if (objectCache)
			module = Cache::getObject(mainFuncName);
		if (!module)
			module = Compiler({}).compile(_code, mainFuncName);
		if (debugDumpModule)
			module->dump();
		if (!ee)
		{
			llvm::InitializeNativeTarget();
			llvm::InitializeNativeTargetAsmPrinter();

			llvm::EngineBuilder builder(module.get());
			builder.setEngineKind(llvm::EngineKind::JIT);
			builder.setUseMCJIT(true);
			std::unique_ptr<llvm::SectionMemoryManager> memoryManager(new llvm::SectionMemoryManager);
			builder.setMCJITMemoryManager(memoryManager.get());
			builder.setOptLevel(llvm::CodeGenOpt::None);

			auto triple = llvm::Triple(llvm::sys::getProcessTriple());
			if (triple.getOS() == llvm::Triple::OSType::Win32)
				triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);  // MCJIT does not support COFF format
			module->setTargetTriple(triple.str());

			ee.reset(builder.create());
			if (!ee)
				return ReturnCode::LLVMConfigError;

			module.release();         // Successfully created llvm::ExecutionEngine takes ownership of the module
			memoryManager.release();  // and memory manager

			if (objectCache)
				ee->setObjectCache(objectCache);
			entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
		}
		else
		{
			if (!entryFuncPtr)
			{
				ee->addModule(module.get());
				module.release();
				entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
			}
		}
	}
	assert(entryFuncPtr);

	auto executionStartTime = std::chrono::high_resolution_clock::now();

	auto returnCode = runEntryFunc(entryFuncPtr, &runtime);
	if (returnCode == ReturnCode::Return)
	{
		returnData = runtime.getReturnData();     // Save reference to return data
		std::swap(m_memory, runtime.getMemory()); // Take ownership of memory
	}

	auto executionEndTime = std::chrono::high_resolution_clock::now();
	clog(JIT) << " + " << std::chrono::duration_cast<std::chrono::milliseconds>(executionEndTime - executionStartTime).count() << " ms\n";

	return returnCode;
}

}
}
}
<commit_msg>change typedef to using according to preferred coding style<commit_after>#include "ExecutionEngine.h"

#include <chrono>
#include <cstdlib>	// env options

#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
#pragma warning(push)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/Host.h>

#include "Runtime.h"
#include "Compiler.h"
#include "Cache.h"

namespace dev
{
namespace eth
{
namespace jit
{

namespace
{
using EntryFuncPtr = ReturnCode(*)(Runtime*);

ReturnCode runEntryFunc(EntryFuncPtr _mainFunc, Runtime* _runtime)
{
	// That function uses long jumps to handle "execeptions".
	// Do not create any non-POD objects here

	ReturnCode returnCode{};
	auto sj = setjmp(_runtime->getJmpBuf());
	if (sj == 0)
		returnCode = _mainFunc(_runtime);
	else
		returnCode = static_cast<ReturnCode>(sj);

	return returnCode;
}

std::string codeHash(bytes const& _code)
{
	uint32_t hash = 0;
	for (auto b : _code)
	{
		hash += b;
		hash += (hash << 10);
		hash ^= (hash >> 6);
	}
	hash += (hash << 3);
	hash ^= (hash >> 11);
	hash += (hash << 15);
	return std::to_string(hash);
}

bool getEnvOption(char const* _name, bool _default)
{
	auto var = std::getenv(_name);
	if (!var)
		return _default;
	return std::strtol(var, nullptr, 10) != 0;
}

}

ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _env)
{
	static std::unique_ptr<llvm::ExecutionEngine> ee;  // TODO: Use Managed Objects from LLVM?
	static auto debugDumpModule = getEnvOption("EVMJIT_DUMP", false);
	static auto objectCacheEnabled = getEnvOption("EVMJIT_CACHE", true);

	auto mainFuncName = codeHash(_code);
	EntryFuncPtr entryFuncPtr{};
	Runtime runtime(_data, _env);	// TODO: I don't know why but it must be created before getFunctionAddress() calls

	if (ee && (entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName)))
	{
	}
	else
	{
		auto objectCache = objectCacheEnabled ? Cache::getObjectCache() : nullptr;
		std::unique_ptr<llvm::Module> module;
		if (objectCache)
			module = Cache::getObject(mainFuncName);
		if (!module)
			module = Compiler({}).compile(_code, mainFuncName);
		if (debugDumpModule)
			module->dump();
		if (!ee)
		{
			llvm::InitializeNativeTarget();
			llvm::InitializeNativeTargetAsmPrinter();

			llvm::EngineBuilder builder(module.get());
			builder.setEngineKind(llvm::EngineKind::JIT);
			builder.setUseMCJIT(true);
			std::unique_ptr<llvm::SectionMemoryManager> memoryManager(new llvm::SectionMemoryManager);
			builder.setMCJITMemoryManager(memoryManager.get());
			builder.setOptLevel(llvm::CodeGenOpt::None);

			auto triple = llvm::Triple(llvm::sys::getProcessTriple());
			if (triple.getOS() == llvm::Triple::OSType::Win32)
				triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);  // MCJIT does not support COFF format
			module->setTargetTriple(triple.str());

			ee.reset(builder.create());
			if (!ee)
				return ReturnCode::LLVMConfigError;

			module.release();         // Successfully created llvm::ExecutionEngine takes ownership of the module
			memoryManager.release();  // and memory manager

			if (objectCache)
				ee->setObjectCache(objectCache);
			entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
		}
		else
		{
			if (!entryFuncPtr)
			{
				ee->addModule(module.get());
				module.release();
				entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
			}
		}
	}
	assert(entryFuncPtr);

	auto executionStartTime = std::chrono::high_resolution_clock::now();

	auto returnCode = runEntryFunc(entryFuncPtr, &runtime);
	if (returnCode == ReturnCode::Return)
	{
		returnData = runtime.getReturnData();     // Save reference to return data
		std::swap(m_memory, runtime.getMemory()); // Take ownership of memory
	}

	auto executionEndTime = std::chrono::high_resolution_clock::now();
	clog(JIT) << " + " << std::chrono::duration_cast<std::chrono::milliseconds>(executionEndTime - executionStartTime).count() << " ms\n";

	return returnCode;
}

}
}
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkOverlay.h"

#include <QBoxLayout>

#include <QGraphicsDropShadowEffect>

QmitkOverlay::QmitkOverlay( const char* id )
:QObject()
, m_Id(id)
, m_Position(top_Left)
, m_Layer(-1)
, m_Widget(NULL)
{
}

QmitkOverlay::~QmitkOverlay()
{
  if (m_Widget)
  {
    m_Widget->deleteLater();
    m_Widget = NULL;
  }
}

QmitkOverlay::DisplayPosition QmitkOverlay::GetPosition()
{
  return m_Position;
}

void QmitkOverlay::SetPosition( DisplayPosition pos )
{
  m_Position = pos;
}

unsigned int QmitkOverlay::GetLayer()
{
  return m_Layer;
}

void QmitkOverlay::SetLayer( unsigned int layer )
{
  m_Layer = layer;
}

QWidget* QmitkOverlay::GetWidget()
{
  return m_Widget;
}

void QmitkOverlay::AddDropShadow( QWidget* widget )
{
  QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect(widget);
  effect->setOffset( QPointF( 1.0, 1.0 ) );
  effect->setBlurRadius( 0 );
  effect->setColor( Qt::black );

  widget->setGraphicsEffect( effect );
}

<commit_msg>check if m_Widget is NULL<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkOverlay.h"

#include <QBoxLayout>

#include <QGraphicsDropShadowEffect>

QmitkOverlay::QmitkOverlay( const char* id )
:QObject()
, m_Id(id)
, m_Position(top_Left)
, m_Layer(-1)
, m_Widget(NULL)
{
}

QmitkOverlay::~QmitkOverlay()
{
  if (m_Widget)
  {
    m_Widget->deleteLater();
    m_Widget = NULL;
  }
}

QmitkOverlay::DisplayPosition QmitkOverlay::GetPosition()
{
  return m_Position;
}

void QmitkOverlay::SetPosition( DisplayPosition pos )
{
  m_Position = pos;
}

unsigned int QmitkOverlay::GetLayer()
{
  return m_Layer;
}

void QmitkOverlay::SetLayer( unsigned int layer )
{
  m_Layer = layer;
}

QWidget* QmitkOverlay::GetWidget()
{
  return m_Widget;
}

void QmitkOverlay::AddDropShadow( QWidget* widget )
{
  if (m_Widget)
  {
    QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect(widget);
    effect->setOffset( QPointF( 1.0, 1.0 ) );
    effect->setBlurRadius( 0 );
    effect->setColor( Qt::black );

    widget->setGraphicsEffect( effect );
  }
}

<|endoftext|>


<commit_before>#include <iostream>

#include "KAI/Console/Console.h"
#include "KAI/Network/Peer.h"

using namespace std;
using namespace kai;
using namespace Bin;

struct Peer : kai::Peer
{
    bool Start()
    {
        //return _peer.Start(ReceivePacket);
		return false;
    }

    bool Connect(String host, int port)
    {
        return _peer.Connect(host.c_str(), port);
    }

    void Send(String text)
    {
        _peer.SendText(text.c_str());
    }

    //void ReceivePacket(RakNet::Pac)
    //{
    //}

    kai::Peer _peer;
};

Console console;

string Kai_VersionString()
{
    stringstream str;
    str << KAI_VERSION_MAJOR << '.' << KAI_VERSION_MINOR << '.' << KAI_VERSION_PATCH;
    return str.str();
}

int main(int argc, char **argv)
{
    KAI_UNUSED_2(argc, argv);

    cout << "KAI v" << Kai_VersionString() << endl << endl;

    console.SetLanguage(Language::Pi);

    // the higher the number, the greater the verbosity of debug output for language systems
    Process::trace = 0;

    // the higher the number, the greater the verbosity of debug output for the Executor
    console.GetExecutor()->SetTraceLevel(0);

    // start the REPL
    return console.Run();
}
<commit_msg>Main doesn't need to reference Bin.<commit_after>#include <iostream>

#include "KAI/Console/Console.h"
#include "KAI/Network/Peer.h"

using namespace std;
using namespace kai;

struct Peer : kai::Peer
{
    bool Start()
    {
        //return _peer.Start(ReceivePacket);
		return false;
    }

    bool Connect(String host, int port)
    {
        return _peer.Connect(host.c_str(), port);
    }

    void Send(String text)
    {
        _peer.SendText(text.c_str());
    }

    //void ReceivePacket(RakNet::Pac)
    //{
    //}

    kai::Peer _peer;
};

Console console;

string Kai_VersionString()
{
    stringstream str;
    str << KAI_VERSION_MAJOR << '.' << KAI_VERSION_MINOR << '.' << KAI_VERSION_PATCH;
    return str.str();
}

int main(int argc, char **argv)
{
    KAI_UNUSED_2(argc, argv);

    cout << "KAI v" << Kai_VersionString() << endl << endl;

    console.SetLanguage(Language::Pi);

    // the higher the number, the greater the verbosity of debug output for language systems
    Process::trace = 0;

    // the higher the number, the greater the verbosity of debug output for the Executor
    console.GetExecutor()->SetTraceLevel(0);

    // start the REPL
    return console.Run();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "core/html/FileInputType.h"

#include "HTMLNames.h"
#include "bindings/v8/ScriptController.h"
#include "core/dom/Event.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/fileapi/File.h"
#include "core/fileapi/FileList.h"
#include "core/html/FormController.h"
#include "core/html/FormDataList.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/InputTypeNames.h"
#include "core/page/Chrome.h"
#include "RuntimeEnabledFeatures.h"
#include "core/platform/DragData.h"
#include "core/platform/FileSystem.h"
#include "core/platform/LocalizedStrings.h"
#include "core/platform/graphics/Icon.h"
#include "core/rendering/RenderFileUploadControl.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

using namespace HTMLNames;

class UploadButtonElement : public HTMLInputElement {
public:
    static PassRefPtr<UploadButtonElement> create(Document*);
    static PassRefPtr<UploadButtonElement> createForMultiple(Document*);

private:
    UploadButtonElement(Document*);

    virtual const AtomicString& shadowPseudoId() const;
};

PassRefPtr<UploadButtonElement> UploadButtonElement::create(Document* document)
{
    RefPtr<UploadButtonElement> button = adoptRef(new UploadButtonElement(document));
    button->setType("button");
    button->setValue(fileButtonChooseFileLabel());
    return button.release();
}

PassRefPtr<UploadButtonElement> UploadButtonElement::createForMultiple(Document* document)
{
    RefPtr<UploadButtonElement> button = adoptRef(new UploadButtonElement(document));
    button->setType("button");
    button->setValue(fileButtonChooseMultipleFilesLabel());
    return button.release();
}

UploadButtonElement::UploadButtonElement(Document* document)
    : HTMLInputElement(inputTag, document, 0, false)
{
}

const AtomicString& UploadButtonElement::shadowPseudoId() const
{
    DEFINE_STATIC_LOCAL(AtomicString, pseudoId, ("-webkit-file-upload-button", AtomicString::ConstructFromLiteral));
    return pseudoId;
}

inline FileInputType::FileInputType(HTMLInputElement* element)
    : BaseClickableWithKeyInputType(element)
    , m_fileList(FileList::create())
{
}

PassOwnPtr<InputType> FileInputType::create(HTMLInputElement* element)
{
    return adoptPtr(new FileInputType(element));
}

Vector<FileChooserFileInfo> FileInputType::filesFromFormControlState(const FormControlState& state)
{
    Vector<FileChooserFileInfo> files;
    for (size_t i = 0; i < state.valueSize(); i += 2) {
        if (!state[i + 1].isEmpty())
            files.append(FileChooserFileInfo(state[i], state[i + 1]));
        else
            files.append(FileChooserFileInfo(state[i]));
    }
    return files;
}

const AtomicString& FileInputType::formControlType() const
{
    return InputTypeNames::file();
}

FormControlState FileInputType::saveFormControlState() const
{
    if (m_fileList->isEmpty())
        return FormControlState();
    FormControlState state;
    unsigned numFiles = m_fileList->length();
    for (unsigned i = 0; i < numFiles; ++i) {
        state.append(m_fileList->item(i)->path());
        state.append(m_fileList->item(i)->name());
    }
    return state;
}

void FileInputType::restoreFormControlState(const FormControlState& state)
{
    if (state.valueSize() % 2)
        return;
    filesChosen(filesFromFormControlState(state));
}

bool FileInputType::appendFormData(FormDataList& encoding, bool multipart) const
{
    FileList* fileList = element()->files();
    unsigned numFiles = fileList->length();
    if (!multipart) {
        // Send only the basenames.
        // 4.10.16.4 and 4.10.16.6 sections in HTML5.

        // Unlike the multipart case, we have no special handling for the empty
        // fileList because Netscape doesn't support for non-multipart
        // submission of file inputs, and Firefox doesn't add "name=" query
        // parameter.
        for (unsigned i = 0; i < numFiles; ++i)
            encoding.appendData(element()->name(), fileList->item(i)->name());
        return true;
    }

    // If no filename at all is entered, return successful but empty.
    // Null would be more logical, but Netscape posts an empty file. Argh.
    if (!numFiles) {
        encoding.appendBlob(element()->name(), File::create(""));
        return true;
    }

    for (unsigned i = 0; i < numFiles; ++i)
        encoding.appendBlob(element()->name(), fileList->item(i));
    return true;
}

bool FileInputType::valueMissing(const String& value) const
{
    return element()->isRequired() && value.isEmpty();
}

String FileInputType::valueMissingText() const
{
    return element()->multiple() ? validationMessageValueMissingForMultipleFileText() : validationMessageValueMissingForFileText();
}

void FileInputType::handleDOMActivateEvent(Event* event)
{
    if (element()->isDisabledFormControl())
        return;

    if (!ScriptController::processingUserGesture())
        return;

    if (Chrome* chrome = this->chrome()) {
        FileChooserSettings settings;
        HTMLInputElement* input = element();
        settings.allowsDirectoryUpload = RuntimeEnabledFeatures::directoryUploadEnabled() && input->fastHasAttribute(webkitdirectoryAttr);
        settings.allowsMultipleFiles = settings.allowsDirectoryUpload || input->fastHasAttribute(multipleAttr);
        settings.acceptMIMETypes = input->acceptMIMETypes();
        settings.acceptFileExtensions = input->acceptFileExtensions();
        settings.selectedFiles = m_fileList->paths();
#if ENABLE(MEDIA_CAPTURE)
        settings.capture = input->capture();
#endif
        chrome->runOpenPanel(input->document()->frame(), newFileChooser(settings));
    }
    event->setDefaultHandled();
}

RenderObject* FileInputType::createRenderer(RenderArena* arena, RenderStyle*) const
{
    return new (arena) RenderFileUploadControl(element());
}

bool FileInputType::canSetStringValue() const
{
    return false;
}

bool FileInputType::canChangeFromAnotherType() const
{
    // Don't allow the type to be changed to file after the first type change.
    // In other engines this might mean a JavaScript programmer could set a text
    // field's value to something like /etc/passwd and then change it to a file input.
    // I don't think this would actually occur in WebKit, but this rule still may be
    // important for compatibility.
    return false;
}

FileList* FileInputType::files()
{
    return m_fileList.get();
}

bool FileInputType::canSetValue(const String& value)
{
    // For security reasons, we don't allow setting the filename, but we do allow clearing it.
    // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't
    // applicable to the file upload control at all, but for now we are keeping this behavior
    // to avoid breaking existing websites that may be relying on this.
    return value.isEmpty();
}

bool FileInputType::getTypeSpecificValue(String& value)
{
    if (m_fileList->isEmpty()) {
        value = String();
        return true;
    }

    // HTML5 tells us that we're supposed to use this goofy value for
    // file input controls. Historically, browsers revealed the real
    // file path, but that's a privacy problem. Code on the web
    // decided to try to parse the value by looking for backslashes
    // (because that's what Windows file paths use). To be compatible
    // with that code, we make up a fake path for the file.
    value = "C:\\fakepath\\" + m_fileList->item(0)->name();
    return true;
}

void FileInputType::setValue(const String&, bool, TextFieldEventBehavior)
{
    m_fileList->clear();
    m_icon.clear();
    element()->setNeedsStyleRecalc();
}

PassRefPtr<FileList> FileInputType::createFileList(const Vector<FileChooserFileInfo>& files) const
{
    RefPtr<FileList> fileList(FileList::create());
    size_t size = files.size();

    // If a directory is being selected, the UI allows a directory to be chosen
    // and the paths provided here share a root directory somewhere up the tree;
    // we want to store only the relative paths from that point.
    if (size && element()->fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabledFeatures::directoryUploadEnabled()) {
        // Find the common root path.
        String rootPath = directoryName(files[0].path);
        for (size_t i = 1; i < size; i++) {
            while (!files[i].path.startsWith(rootPath))
                rootPath = directoryName(rootPath);
        }
        rootPath = directoryName(rootPath);
        ASSERT(rootPath.length());
        int rootLength = rootPath.length();
        if (rootPath[rootLength - 1] != '\\' && rootPath[rootLength - 1] != '/')
            rootLength += 1;
        for (size_t i = 0; i < size; i++) {
            // Normalize backslashes to slashes before exposing the relative path to script.
            String relativePath = files[i].path.substring(rootLength).replace('\\', '/');
            fileList->append(File::createWithRelativePath(files[i].path, relativePath));
        }
        return fileList;
    }

    for (size_t i = 0; i < size; i++)
        fileList->append(File::createWithName(files[i].path, files[i].displayName, File::AllContentTypes));
    return fileList;
}

bool FileInputType::isFileUpload() const
{
    return true;
}

void FileInputType::createShadowSubtree()
{
    ASSERT(element()->shadow());
    element()->userAgentShadowRoot()->appendChild(element()->multiple() ? UploadButtonElement::createForMultiple(element()->document()): UploadButtonElement::create(element()->document()), IGNORE_EXCEPTION);
}

void FileInputType::disabledAttributeChanged()
{
    ASSERT(element()->shadow());
    UploadButtonElement* button = static_cast<UploadButtonElement*>(element()->userAgentShadowRoot()->firstChild());
    if (button)
        button->setBooleanAttribute(disabledAttr, element()->isDisabledFormControl());
}

void FileInputType::multipleAttributeChanged()
{
    ASSERT(element()->shadow());
    UploadButtonElement* button = static_cast<UploadButtonElement*>(element()->userAgentShadowRoot()->firstChild());
    if (button)
        button->setValue(element()->multiple() ? fileButtonChooseMultipleFilesLabel() : fileButtonChooseFileLabel());
}

void FileInputType::requestIcon(const Vector<String>& paths)
{
    if (!paths.size())
        return;

    if (Chrome* chrome = this->chrome())
        chrome->loadIconForFiles(paths, newFileIconLoader());
}

void FileInputType::setFiles(PassRefPtr<FileList> files)
{
    if (!files)
        return;

    RefPtr<HTMLInputElement> input = element();

    bool pathsChanged = false;
    if (files->length() != m_fileList->length())
        pathsChanged = true;
    else {
        for (unsigned i = 0; i < files->length(); ++i) {
            if (files->item(i)->path() != m_fileList->item(i)->path()) {
                pathsChanged = true;
                break;
            }
        }
    }

    m_fileList = files;

    input->setFormControlValueMatchesRenderer(true);
    input->notifyFormStateChanged();
    input->setNeedsValidityCheck();

    Vector<String> paths;
    for (unsigned i = 0; i < m_fileList->length(); ++i)
        paths.append(m_fileList->item(i)->path());
    requestIcon(paths);

    if (input->renderer())
        input->renderer()->repaint();

    if (pathsChanged) {
        // This call may cause destruction of this instance.
        // input instance is safe since it is ref-counted.
        input->HTMLElement::dispatchChangeEvent();
    }
    input->setChangedSinceLastFormControlChangeEvent(false);
}

void FileInputType::filesChosen(const Vector<FileChooserFileInfo>& files)
{
    setFiles(createFileList(files));
}

void FileInputType::receiveDropForDirectoryUpload(const Vector<String>& paths)
{
    if (Chrome* chrome = this->chrome()) {
        FileChooserSettings settings;
        HTMLInputElement* input = element();
        settings.allowsDirectoryUpload = true;
        settings.allowsMultipleFiles = true;
        settings.selectedFiles.append(paths[0]);
        settings.acceptMIMETypes = input->acceptMIMETypes();
        settings.acceptFileExtensions = input->acceptFileExtensions();
        chrome->enumerateChosenDirectory(newFileChooser(settings));
    }
}

void FileInputType::updateRendering(PassRefPtr<Icon> icon)
{
    if (m_icon == icon)
        return;

    m_icon = icon;
    if (element()->renderer())
        element()->renderer()->repaint();
}

bool FileInputType::receiveDroppedFiles(const DragData* dragData)
{
    Vector<String> paths;
    dragData->asFilenames(paths);
    if (paths.isEmpty())
        return false;

    HTMLInputElement* input = element();
    if (input->fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabledFeatures::directoryUploadEnabled()) {
        receiveDropForDirectoryUpload(paths);
        return true;
    }

    m_droppedFileSystemId = dragData->droppedFileSystemId();

    Vector<FileChooserFileInfo> files;
    for (unsigned i = 0; i < paths.size(); ++i)
        files.append(FileChooserFileInfo(paths[i]));

    if (input->fastHasAttribute(multipleAttr))
        filesChosen(files);
    else {
        Vector<FileChooserFileInfo> firstFileOnly;
        firstFileOnly.append(files[0]);
        filesChosen(firstFileOnly);
    }
    return true;
}

String FileInputType::droppedFileSystemId()
{
    return m_droppedFileSystemId;
}

Icon* FileInputType::icon() const
{
    return m_icon.get();
}

String FileInputType::defaultToolTip() const
{
    FileList* fileList = m_fileList.get();
    unsigned listSize = fileList->length();
    if (!listSize) {
        if (element()->multiple())
            return fileButtonNoFilesSelectedLabel();
        return fileButtonNoFileSelectedLabel();
    }

    StringBuilder names;
    for (size_t i = 0; i < listSize; ++i) {
        names.append(fileList->item(i)->name());
        if (i != listSize - 1)
            names.append('\n');
    }
    return names.toString();
}

} // namespace WebCore
<commit_msg>Remove UploadButtonElement.<commit_after>/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "core/html/FileInputType.h"

#include "HTMLNames.h"
#include "bindings/v8/ScriptController.h"
#include "core/dom/Event.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/fileapi/File.h"
#include "core/fileapi/FileList.h"
#include "core/html/FormController.h"
#include "core/html/FormDataList.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/InputTypeNames.h"
#include "core/page/Chrome.h"
#include "RuntimeEnabledFeatures.h"
#include "core/platform/DragData.h"
#include "core/platform/FileSystem.h"
#include "core/platform/LocalizedStrings.h"
#include "core/platform/graphics/Icon.h"
#include "core/rendering/RenderFileUploadControl.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

using namespace HTMLNames;

inline FileInputType::FileInputType(HTMLInputElement* element)
    : BaseClickableWithKeyInputType(element)
    , m_fileList(FileList::create())
{
}

PassOwnPtr<InputType> FileInputType::create(HTMLInputElement* element)
{
    return adoptPtr(new FileInputType(element));
}

Vector<FileChooserFileInfo> FileInputType::filesFromFormControlState(const FormControlState& state)
{
    Vector<FileChooserFileInfo> files;
    for (size_t i = 0; i < state.valueSize(); i += 2) {
        if (!state[i + 1].isEmpty())
            files.append(FileChooserFileInfo(state[i], state[i + 1]));
        else
            files.append(FileChooserFileInfo(state[i]));
    }
    return files;
}

const AtomicString& FileInputType::formControlType() const
{
    return InputTypeNames::file();
}

FormControlState FileInputType::saveFormControlState() const
{
    if (m_fileList->isEmpty())
        return FormControlState();
    FormControlState state;
    unsigned numFiles = m_fileList->length();
    for (unsigned i = 0; i < numFiles; ++i) {
        state.append(m_fileList->item(i)->path());
        state.append(m_fileList->item(i)->name());
    }
    return state;
}

void FileInputType::restoreFormControlState(const FormControlState& state)
{
    if (state.valueSize() % 2)
        return;
    filesChosen(filesFromFormControlState(state));
}

bool FileInputType::appendFormData(FormDataList& encoding, bool multipart) const
{
    FileList* fileList = element()->files();
    unsigned numFiles = fileList->length();
    if (!multipart) {
        // Send only the basenames.
        // 4.10.16.4 and 4.10.16.6 sections in HTML5.

        // Unlike the multipart case, we have no special handling for the empty
        // fileList because Netscape doesn't support for non-multipart
        // submission of file inputs, and Firefox doesn't add "name=" query
        // parameter.
        for (unsigned i = 0; i < numFiles; ++i)
            encoding.appendData(element()->name(), fileList->item(i)->name());
        return true;
    }

    // If no filename at all is entered, return successful but empty.
    // Null would be more logical, but Netscape posts an empty file. Argh.
    if (!numFiles) {
        encoding.appendBlob(element()->name(), File::create(""));
        return true;
    }

    for (unsigned i = 0; i < numFiles; ++i)
        encoding.appendBlob(element()->name(), fileList->item(i));
    return true;
}

bool FileInputType::valueMissing(const String& value) const
{
    return element()->isRequired() && value.isEmpty();
}

String FileInputType::valueMissingText() const
{
    return element()->multiple() ? validationMessageValueMissingForMultipleFileText() : validationMessageValueMissingForFileText();
}

void FileInputType::handleDOMActivateEvent(Event* event)
{
    if (element()->isDisabledFormControl())
        return;

    if (!ScriptController::processingUserGesture())
        return;

    if (Chrome* chrome = this->chrome()) {
        FileChooserSettings settings;
        HTMLInputElement* input = element();
        settings.allowsDirectoryUpload = RuntimeEnabledFeatures::directoryUploadEnabled() && input->fastHasAttribute(webkitdirectoryAttr);
        settings.allowsMultipleFiles = settings.allowsDirectoryUpload || input->fastHasAttribute(multipleAttr);
        settings.acceptMIMETypes = input->acceptMIMETypes();
        settings.acceptFileExtensions = input->acceptFileExtensions();
        settings.selectedFiles = m_fileList->paths();
#if ENABLE(MEDIA_CAPTURE)
        settings.capture = input->capture();
#endif
        chrome->runOpenPanel(input->document()->frame(), newFileChooser(settings));
    }
    event->setDefaultHandled();
}

RenderObject* FileInputType::createRenderer(RenderArena* arena, RenderStyle*) const
{
    return new (arena) RenderFileUploadControl(element());
}

bool FileInputType::canSetStringValue() const
{
    return false;
}

bool FileInputType::canChangeFromAnotherType() const
{
    // Don't allow the type to be changed to file after the first type change.
    // In other engines this might mean a JavaScript programmer could set a text
    // field's value to something like /etc/passwd and then change it to a file input.
    // I don't think this would actually occur in WebKit, but this rule still may be
    // important for compatibility.
    return false;
}

FileList* FileInputType::files()
{
    return m_fileList.get();
}

bool FileInputType::canSetValue(const String& value)
{
    // For security reasons, we don't allow setting the filename, but we do allow clearing it.
    // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't
    // applicable to the file upload control at all, but for now we are keeping this behavior
    // to avoid breaking existing websites that may be relying on this.
    return value.isEmpty();
}

bool FileInputType::getTypeSpecificValue(String& value)
{
    if (m_fileList->isEmpty()) {
        value = String();
        return true;
    }

    // HTML5 tells us that we're supposed to use this goofy value for
    // file input controls. Historically, browsers revealed the real
    // file path, but that's a privacy problem. Code on the web
    // decided to try to parse the value by looking for backslashes
    // (because that's what Windows file paths use). To be compatible
    // with that code, we make up a fake path for the file.
    value = "C:\\fakepath\\" + m_fileList->item(0)->name();
    return true;
}

void FileInputType::setValue(const String&, bool, TextFieldEventBehavior)
{
    m_fileList->clear();
    m_icon.clear();
    element()->setNeedsStyleRecalc();
}

PassRefPtr<FileList> FileInputType::createFileList(const Vector<FileChooserFileInfo>& files) const
{
    RefPtr<FileList> fileList(FileList::create());
    size_t size = files.size();

    // If a directory is being selected, the UI allows a directory to be chosen
    // and the paths provided here share a root directory somewhere up the tree;
    // we want to store only the relative paths from that point.
    if (size && element()->fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabledFeatures::directoryUploadEnabled()) {
        // Find the common root path.
        String rootPath = directoryName(files[0].path);
        for (size_t i = 1; i < size; i++) {
            while (!files[i].path.startsWith(rootPath))
                rootPath = directoryName(rootPath);
        }
        rootPath = directoryName(rootPath);
        ASSERT(rootPath.length());
        int rootLength = rootPath.length();
        if (rootPath[rootLength - 1] != '\\' && rootPath[rootLength - 1] != '/')
            rootLength += 1;
        for (size_t i = 0; i < size; i++) {
            // Normalize backslashes to slashes before exposing the relative path to script.
            String relativePath = files[i].path.substring(rootLength).replace('\\', '/');
            fileList->append(File::createWithRelativePath(files[i].path, relativePath));
        }
        return fileList;
    }

    for (size_t i = 0; i < size; i++)
        fileList->append(File::createWithName(files[i].path, files[i].displayName, File::AllContentTypes));
    return fileList;
}

bool FileInputType::isFileUpload() const
{
    return true;
}

void FileInputType::createShadowSubtree()
{
    ASSERT(element()->shadow());
    RefPtr<HTMLInputElement> button = HTMLInputElement::create(inputTag, element()->document(), 0, false);
    button->setType(InputTypeNames::button());
    button->setAttribute(valueAttr, element()->multiple() ? fileButtonChooseMultipleFilesLabel() : fileButtonChooseFileLabel());
    button->setPseudo(AtomicString("-webkit-file-upload-button", AtomicString::ConstructFromLiteral));
    element()->userAgentShadowRoot()->appendChild(button.release(), IGNORE_EXCEPTION);
}

void FileInputType::disabledAttributeChanged()
{
    ASSERT(element()->shadow());
    if (Element* button = toElement(element()->userAgentShadowRoot()->firstChild()))
        button->setBooleanAttribute(disabledAttr, element()->isDisabledFormControl());
}

void FileInputType::multipleAttributeChanged()
{
    ASSERT(element()->shadow());
    if (Element* button = toElement(element()->userAgentShadowRoot()->firstChild()))
        button->setAttribute(valueAttr, element()->multiple() ? fileButtonChooseMultipleFilesLabel() : fileButtonChooseFileLabel());
}

void FileInputType::requestIcon(const Vector<String>& paths)
{
    if (!paths.size())
        return;

    if (Chrome* chrome = this->chrome())
        chrome->loadIconForFiles(paths, newFileIconLoader());
}

void FileInputType::setFiles(PassRefPtr<FileList> files)
{
    if (!files)
        return;

    RefPtr<HTMLInputElement> input = element();

    bool pathsChanged = false;
    if (files->length() != m_fileList->length())
        pathsChanged = true;
    else {
        for (unsigned i = 0; i < files->length(); ++i) {
            if (files->item(i)->path() != m_fileList->item(i)->path()) {
                pathsChanged = true;
                break;
            }
        }
    }

    m_fileList = files;

    input->setFormControlValueMatchesRenderer(true);
    input->notifyFormStateChanged();
    input->setNeedsValidityCheck();

    Vector<String> paths;
    for (unsigned i = 0; i < m_fileList->length(); ++i)
        paths.append(m_fileList->item(i)->path());
    requestIcon(paths);

    if (input->renderer())
        input->renderer()->repaint();

    if (pathsChanged) {
        // This call may cause destruction of this instance.
        // input instance is safe since it is ref-counted.
        input->HTMLElement::dispatchChangeEvent();
    }
    input->setChangedSinceLastFormControlChangeEvent(false);
}

void FileInputType::filesChosen(const Vector<FileChooserFileInfo>& files)
{
    setFiles(createFileList(files));
}

void FileInputType::receiveDropForDirectoryUpload(const Vector<String>& paths)
{
    if (Chrome* chrome = this->chrome()) {
        FileChooserSettings settings;
        HTMLInputElement* input = element();
        settings.allowsDirectoryUpload = true;
        settings.allowsMultipleFiles = true;
        settings.selectedFiles.append(paths[0]);
        settings.acceptMIMETypes = input->acceptMIMETypes();
        settings.acceptFileExtensions = input->acceptFileExtensions();
        chrome->enumerateChosenDirectory(newFileChooser(settings));
    }
}

void FileInputType::updateRendering(PassRefPtr<Icon> icon)
{
    if (m_icon == icon)
        return;

    m_icon = icon;
    if (element()->renderer())
        element()->renderer()->repaint();
}

bool FileInputType::receiveDroppedFiles(const DragData* dragData)
{
    Vector<String> paths;
    dragData->asFilenames(paths);
    if (paths.isEmpty())
        return false;

    HTMLInputElement* input = element();
    if (input->fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabledFeatures::directoryUploadEnabled()) {
        receiveDropForDirectoryUpload(paths);
        return true;
    }

    m_droppedFileSystemId = dragData->droppedFileSystemId();

    Vector<FileChooserFileInfo> files;
    for (unsigned i = 0; i < paths.size(); ++i)
        files.append(FileChooserFileInfo(paths[i]));

    if (input->fastHasAttribute(multipleAttr))
        filesChosen(files);
    else {
        Vector<FileChooserFileInfo> firstFileOnly;
        firstFileOnly.append(files[0]);
        filesChosen(firstFileOnly);
    }
    return true;
}

String FileInputType::droppedFileSystemId()
{
    return m_droppedFileSystemId;
}

Icon* FileInputType::icon() const
{
    return m_icon.get();
}

String FileInputType::defaultToolTip() const
{
    FileList* fileList = m_fileList.get();
    unsigned listSize = fileList->length();
    if (!listSize) {
        if (element()->multiple())
            return fileButtonNoFilesSelectedLabel();
        return fileButtonNoFileSelectedLabel();
    }

    StringBuilder names;
    for (size_t i = 0; i < listSize; ++i) {
        names.append(fileList->item(i)->name());
        if (i != listSize - 1)
            names.append('\n');
    }
    return names.toString();
}

} // namespace WebCore
<|endoftext|>


<commit_before>/*
 * This source file is part of Pillar, the C++ Cross-platform middleware for game
 *
 * For the latest information, see https://github.com/prophecy/Pillar
 *
 * The MIT License (MIT)
 * Copyright (c) 2015 Adawat Chanchua
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include "EventManager.h"
#include "ITask.h"
#include "TaskManager.h"

void EventManager::BindTask(WonderPtr<ITask> task)
{
	_tasks.push_back(task);
}

void EventManager::Notify(s32 code, std::string message)
{
	std::vector<ITask*>::iterator it;

	for (u32 i = 0; i < _tasks.size(); ++i)
		_tasks[i]->OnEvent(this, code, message);
}

void EventManager::Notify(s8* data)
{
	std::vector<ITask*>::iterator it;

	for (u32 i = 0; i < _tasks.size(); ++i)
		_tasks[i]->OnEvent(this, data);
}<commit_msg>[Pillar] Comment unused event functions<commit_after>/*
 * This source file is part of Pillar, the C++ Cross-platform middleware for game
 *
 * For the latest information, see https://github.com/prophecy/Pillar
 *
 * The MIT License (MIT)
 * Copyright (c) 2015 Adawat Chanchua
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include "EventManager.h"
#include "ITask.h"
#include "TaskManager.h"

void EventManager::BindTask(WonderPtr<ITask> task)
{
//	_tasks.push_back(task);
}

void EventManager::Notify(s32 code, std::string message)
{
//	for (u32 i = 0; i < _tasks.size(); ++i)
//		_tasks[i]->OnEvent(this, code, message);
}

void EventManager::Notify(s8* data)
{
//	for (u32 i = 0; i < _tasks.size(); ++i)
//		_tasks[i]->OnEvent(this, data);
}<|endoftext|>


<commit_before>#include "Proxy.h"

namespace jni
{

jni::Class s_JNIBridgeClass("bitter/jnibridge/JNIBridge");
ProxyTracker ProxyObject::proxyTracker;

JNIEXPORT jobject JNICALL Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_invoke(JNIEnv* env, jobject thiz, jlong ptr, jclass clazz, jobject method, jobjectArray args)
{
	jmethodID methodID = env->FromReflectedMethod(method);
	// Previous code looked like this
	//    ProxyInvoker* proxy = (ProxyInvoker*)ptr;
	// When running tests on Windows proxy->Invoke would call into ProxyObject::Equals
	// I am not sure why, but my guess - it's because of multiple inheritance with virtual functions.
	// Since the only class which implements __Invoke is ProxyObject, I think it's pretty safe
	// to cast to ProxyObject instead of ProxyInvoker
	// Note: there's also this warning on Windows
	//     Proxy.h(104): warning C4250: 'jni::ProxyGenerator<jni::GlobalRefAllocator,java::lang::Runnable>': inherits 'jni::ProxyObject::jni::ProxyObject::__Invoke' via dominance
	// but even after fixing it, the call ProxyInvoker::__Invoke would still be incorrect, so I think the warning is inrelated, though again it points to virtual inheritance madness

	ProxyObject* proxy = (ProxyObject*)ptr;
	return proxy->__Invoke(clazz, methodID, args);
}

JNIEXPORT void JNICALL Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_delete(JNIEnv* env, jobject thiz, jlong ptr)
{
	delete (ProxyInvoker*)ptr;
}

bool ProxyInvoker::__Register()
{
	jni::LocalScope frame;
	jni::Class nativeProxyClass("bitter/jnibridge/JNIBridge");
	char invokeMethodName[] = "invoke";
	char invokeMethodSignature[] = "(JLjava/lang/Class;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";
	char deleteMethodName[] = "delete";
	char deleteMethodSignature[] = "(J)V";

	JNINativeMethod nativeProxyFunction[] = {
		{invokeMethodName, invokeMethodSignature, (void*) Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_invoke},
		{deleteMethodName, deleteMethodSignature, (void*) Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_delete}
	};

	if (nativeProxyClass) jni::GetEnv()->RegisterNatives(nativeProxyClass, nativeProxyFunction, 2); // <-- fix this
	return !jni::CheckError();
}

::jint ProxyObject::HashCode() const
{
	return java::lang::System::IdentityHashCode(java::lang::Object(__ProxyObject()));
}

::jboolean ProxyObject::Equals(const ::jobject arg0) const
{
	return jni::IsSameObject(__ProxyObject(), arg0);
}

java::lang::String ProxyObject::ToString() const
{
	return java::lang::String("<native proxy object>");
}

jobject ProxyObject::__Invoke(jclass clazz, jmethodID mid, jobjectArray args)
{
	jobject result;
	if (!__InvokeInternal(clazz, mid, args, &result))
	{
		java::lang::reflect::Method method(jni::ToReflectedMethod(clazz, mid, false));
		jni::ThrowNew<java::lang::NoSuchMethodError>(method.ToString().c_str());
	}

	return result;
}

void ProxyObject::DeleteAllProxies()
{
	proxyTracker.DeleteAllProxies();
}

bool ProxyObject::__TryInvoke(jclass clazz, jmethodID methodID, jobjectArray args, bool* success, jobject* result)
{
	if (*success)
		return false;

	// in case jmethodIDs are not unique across classes - couldn't find any spec regarding this
	if (!jni::IsSameObject(clazz, java::lang::Object::__CLASS))
		return false;

	static jmethodID methodIDs[] = {
		jni::GetMethodID(java::lang::Object::__CLASS, "hashCode", "()I"),
		jni::GetMethodID(java::lang::Object::__CLASS, "equals", "(Ljava/lang/Object;)Z"),
		jni::GetMethodID(java::lang::Object::__CLASS, "toString", "()Ljava/lang/String;")
	};
	if (methodIDs[0] == methodID) { *result = jni::NewLocalRef(static_cast<java::lang::Integer>(HashCode())); *success = true; return true; }
	if (methodIDs[1] == methodID) { *result = jni::NewLocalRef(static_cast<java::lang::Boolean>(Equals(::java::lang::Object(jni::GetObjectArrayElement(args, 0))))); *success = true; return true; }
	if (methodIDs[2] == methodID) {	*result = jni::NewLocalRef(static_cast<java::lang::String>(ToString())); *success = true;	return true; }

	return false;
}

jobject ProxyObject::NewInstance(void* nativePtr, const jobject* interfaces, jsize interfaces_len)
{
	Array<jobject> interfaceArray(java::lang::Class::__CLASS, interfaces_len, interfaces);

	static jmethodID newProxyMID = jni::GetStaticMethodID(s_JNIBridgeClass, "newInterfaceProxy", "(J[Ljava/lang/Class;)Ljava/lang/Object;");
	return  jni::Op<jobject>::CallStaticMethod(s_JNIBridgeClass, newProxyMID, (jlong) nativePtr, static_cast<jobjectArray>(interfaceArray));
}

jobject ProxyObject::NewInstance(void* nativePtr, const jobject interfacce)
{
	const jobject objects[] = { interfacce };
	return NewInstance(nativePtr, objects, 1);
}

jobject ProxyObject::NewInstance(void* nativePtr, const jobject interfacce1, const jobject interfacce2)
{
	const jobject objects[] = { interfacce1, interfacce2 };
	return NewInstance(nativePtr, objects, 2);
}

void ProxyObject::DisableInstance(jobject proxy)
{
	static jmethodID disableProxyMID = jni::GetStaticMethodID(s_JNIBridgeClass, "disableInterfaceProxy", "(Ljava/lang/Object;)V");
	jni::Op<jvoid>::CallStaticMethod(s_JNIBridgeClass, disableProxyMID, proxy);
}

ProxyTracker::ProxyTracker()
{
	head = NULL;
}

ProxyTracker::~ProxyTracker()
{
}

void ProxyTracker::StartTracking(ProxyObject* obj)
{
	lock.lock();
	head = new LinkedProxy(obj, head);
	lock.unlock();
}

void ProxyTracker::StopTracking(ProxyObject* obj)
{
	lock.lock();
	LinkedProxy* current = head;
	LinkedProxy* previous = NULL;
	while (current != NULL && current->obj != obj)
	{
		previous = current;
		current = current->next;
	}

	if (current != NULL)
	{
		if (previous == NULL)
			head = current->next;
		else
			previous->next = current->next;
		delete current;
	}
	lock.unlock();
}

void ProxyTracker::DeleteAllProxies()
{
	lock.lock();
	LinkedProxy* current = head;
	head = NULL; // Destructor will call StopTracking, this will prevent it from looping through the whole list
	while (current != NULL)
	{
		LinkedProxy* previous = current;
		current = current->next;
		delete previous->obj;
		delete previous;
	}
	lock.unlock();
}

}<commit_msg>use guard<commit_after>#include "Proxy.h"

namespace jni
{

jni::Class s_JNIBridgeClass("bitter/jnibridge/JNIBridge");
ProxyTracker ProxyObject::proxyTracker;

JNIEXPORT jobject JNICALL Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_invoke(JNIEnv* env, jobject thiz, jlong ptr, jclass clazz, jobject method, jobjectArray args)
{
	jmethodID methodID = env->FromReflectedMethod(method);
	// Previous code looked like this
	//    ProxyInvoker* proxy = (ProxyInvoker*)ptr;
	// When running tests on Windows proxy->Invoke would call into ProxyObject::Equals
	// I am not sure why, but my guess - it's because of multiple inheritance with virtual functions.
	// Since the only class which implements __Invoke is ProxyObject, I think it's pretty safe
	// to cast to ProxyObject instead of ProxyInvoker
	// Note: there's also this warning on Windows
	//     Proxy.h(104): warning C4250: 'jni::ProxyGenerator<jni::GlobalRefAllocator,java::lang::Runnable>': inherits 'jni::ProxyObject::jni::ProxyObject::__Invoke' via dominance
	// but even after fixing it, the call ProxyInvoker::__Invoke would still be incorrect, so I think the warning is inrelated, though again it points to virtual inheritance madness

	ProxyObject* proxy = (ProxyObject*)ptr;
	return proxy->__Invoke(clazz, methodID, args);
}

JNIEXPORT void JNICALL Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_delete(JNIEnv* env, jobject thiz, jlong ptr)
{
	delete (ProxyInvoker*)ptr;
}

bool ProxyInvoker::__Register()
{
	jni::LocalScope frame;
	jni::Class nativeProxyClass("bitter/jnibridge/JNIBridge");
	char invokeMethodName[] = "invoke";
	char invokeMethodSignature[] = "(JLjava/lang/Class;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";
	char deleteMethodName[] = "delete";
	char deleteMethodSignature[] = "(J)V";

	JNINativeMethod nativeProxyFunction[] = {
		{invokeMethodName, invokeMethodSignature, (void*) Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_invoke},
		{deleteMethodName, deleteMethodSignature, (void*) Java_bitter_jnibridge_JNIBridge_00024InterfaceProxy_delete}
	};

	if (nativeProxyClass) jni::GetEnv()->RegisterNatives(nativeProxyClass, nativeProxyFunction, 2); // <-- fix this
	return !jni::CheckError();
}

::jint ProxyObject::HashCode() const
{
	return java::lang::System::IdentityHashCode(java::lang::Object(__ProxyObject()));
}

::jboolean ProxyObject::Equals(const ::jobject arg0) const
{
	return jni::IsSameObject(__ProxyObject(), arg0);
}

java::lang::String ProxyObject::ToString() const
{
	return java::lang::String("<native proxy object>");
}

jobject ProxyObject::__Invoke(jclass clazz, jmethodID mid, jobjectArray args)
{
	jobject result;
	if (!__InvokeInternal(clazz, mid, args, &result))
	{
		java::lang::reflect::Method method(jni::ToReflectedMethod(clazz, mid, false));
		jni::ThrowNew<java::lang::NoSuchMethodError>(method.ToString().c_str());
	}

	return result;
}

void ProxyObject::DeleteAllProxies()
{
	proxyTracker.DeleteAllProxies();
}

bool ProxyObject::__TryInvoke(jclass clazz, jmethodID methodID, jobjectArray args, bool* success, jobject* result)
{
	if (*success)
		return false;

	// in case jmethodIDs are not unique across classes - couldn't find any spec regarding this
	if (!jni::IsSameObject(clazz, java::lang::Object::__CLASS))
		return false;

	static jmethodID methodIDs[] = {
		jni::GetMethodID(java::lang::Object::__CLASS, "hashCode", "()I"),
		jni::GetMethodID(java::lang::Object::__CLASS, "equals", "(Ljava/lang/Object;)Z"),
		jni::GetMethodID(java::lang::Object::__CLASS, "toString", "()Ljava/lang/String;")
	};
	if (methodIDs[0] == methodID) { *result = jni::NewLocalRef(static_cast<java::lang::Integer>(HashCode())); *success = true; return true; }
	if (methodIDs[1] == methodID) { *result = jni::NewLocalRef(static_cast<java::lang::Boolean>(Equals(::java::lang::Object(jni::GetObjectArrayElement(args, 0))))); *success = true; return true; }
	if (methodIDs[2] == methodID) {	*result = jni::NewLocalRef(static_cast<java::lang::String>(ToString())); *success = true;	return true; }

	return false;
}

jobject ProxyObject::NewInstance(void* nativePtr, const jobject* interfaces, jsize interfaces_len)
{
	Array<jobject> interfaceArray(java::lang::Class::__CLASS, interfaces_len, interfaces);

	static jmethodID newProxyMID = jni::GetStaticMethodID(s_JNIBridgeClass, "newInterfaceProxy", "(J[Ljava/lang/Class;)Ljava/lang/Object;");
	return  jni::Op<jobject>::CallStaticMethod(s_JNIBridgeClass, newProxyMID, (jlong) nativePtr, static_cast<jobjectArray>(interfaceArray));
}

jobject ProxyObject::NewInstance(void* nativePtr, const jobject interfacce)
{
	const jobject objects[] = { interfacce };
	return NewInstance(nativePtr, objects, 1);
}

jobject ProxyObject::NewInstance(void* nativePtr, const jobject interfacce1, const jobject interfacce2)
{
	const jobject objects[] = { interfacce1, interfacce2 };
	return NewInstance(nativePtr, objects, 2);
}

void ProxyObject::DisableInstance(jobject proxy)
{
	static jmethodID disableProxyMID = jni::GetStaticMethodID(s_JNIBridgeClass, "disableInterfaceProxy", "(Ljava/lang/Object;)V");
	jni::Op<jvoid>::CallStaticMethod(s_JNIBridgeClass, disableProxyMID, proxy);
}

ProxyTracker::ProxyTracker()
{
	head = NULL;
}

ProxyTracker::~ProxyTracker()
{
}

void ProxyTracker::StartTracking(ProxyObject* obj)
{
	std::lock_guard<std::mutex> guard(lock);
	head = new LinkedProxy(obj, head);
}

void ProxyTracker::StopTracking(ProxyObject* obj)
{
	std::lock_guard<std::mutex> guard(lock);
	LinkedProxy* current = head;
	LinkedProxy* previous = NULL;
	while (current != NULL && current->obj != obj)
	{
		previous = current;
		current = current->next;
	}

	if (current != NULL)
	{
		if (previous == NULL)
			head = current->next;
		else
			previous->next = current->next;
		delete current;
	}
}

void ProxyTracker::DeleteAllProxies()
{
	std::lock_guard<std::mutex> guard(lock);
	LinkedProxy* current = head;
	head = NULL; // Destructor will call StopTracking, this will prevent it from looping through the whole list
	while (current != NULL)
	{
		LinkedProxy* previous = current;
		current = current->next;
		delete previous->obj;
		delete previous;
	}
}

}<|endoftext|>


<commit_before>//
// Name:     appfltk.cpp
// Purpose:  Example FLTK/vtlib application
//   (tested only on Linux using FLTK 1.1.5)
//   (tested only on Windows using FLTK 1.1.6)
//
// Copyright (c) 2004 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//
// Provided by Clark Borst (November 12, 2004)

#ifdef __FreeBSD__
#  include <ieeefp.h>
#endif

#include <iostream>

// the required FLTK headers for this example
#include <FL/Fl.h>
#include <FL/Fl_Gl_Window.h>
#include <FL/gl.h>
#include <GL/glu.h>

// the required VTP headers
#include "vtlib/vtlib.h"
#include "vtlib/core/Terrain.h"
#include "vtlib/core/TerrainScene.h"
#include "vtlib/core/NavEngines.h"
#include "vtdata/vtLog.h"

// handy definitions for FLTK mouse buttons
#define FL_LEFT 1
#define FL_MIDDLE 2
#define FL_RIGHT 3

using namespace std;

// prototype of global idle callback function
void IdleCallback(void* pData);

// create a new FLTK window with OpenGL context by making
// a subclass of the Fl_Gl_Window class
class VTPWindow : public Fl_Gl_Window
{
	public:
		VTPWindow(int width, int height, char* title);
		virtual ~VTPWindow();
		void InitializeGL();
		virtual void draw();
		bool CreateScene();
		virtual int handle(int event);
	private:
		int screenwidth, screenheight;
};

// the idle function will continuously update (redraw) the window,
// even when there are no events
void IdleCallback(void* pData)
{
	if (pData != NULL)
	{
		VTPWindow* pWindow = reinterpret_cast<VTPWindow*>(pData);
		// execute the draw() function of the window by invoking
		// method redraw()
		pWindow->redraw();
	}
}

// constructor
VTPWindow::VTPWindow(int width, int height, char* title) : Fl_Gl_Window(width, height, title)
{
	mode(FL_RGB | FL_ALPHA | FL_DEPTH | FL_DOUBLE);
	// add the idle function to this window
	Fl::add_idle(IdleCallback, this);
}

// destructor
VTPWindow::~VTPWindow()
{
	//
}

// init OpenGL
void VTPWindow::InitializeGL()
{
	glClearColor(.1f, .1f, .1f, 1);
	glEnable(GL_DEPTH_TEST);
}

// the draw() function must be overridden by your own
// drawing code. By invoking method redraw(), FLTK will
// call this draw() method
void VTPWindow::draw()
{
	static bool firstTime = true;
	if (firstTime){
		// create the VTerrain scene
		CreateScene();
		// init OpenGL
		InitializeGL();
		// get the window size with Fl::Widget (parent class of Fl_Gl_Window) methods w() and h()
		screenwidth  = w();
		screenheight = h();
		// print the window size to the terminal
		cout << screenwidth << endl << screenheight << endl;
		// adjust the scene's viewport to the FL window size
		vtGetScene()->SetWindowSize(screenwidth, screenheight);
		// prevent this sequence from being executed over and over again
		firstTime = false;
	};

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	// update the terrain scene
	vtGetScene()->DoUpdate();
}

// the event handler of the window, which takes mouse and keyboard events
// and converts them into VTerrain events
int VTPWindow::handle(int event)
{
	vtMouseEvent vtp_event;
	int x, y;
	unsigned char key;

	switch (event)
	{
		case FL_FOCUS:
		case FL_UNFOCUS:
		return 1;

		// process keyboard events for this window
		case FL_KEYBOARD:
			key = Fl::event_key();
			switch (key)
			{
				// ESC means quit the program
				case 27 :
					exit(0);
					return 1;
				// q means quit the program
				case 'q':
					exit(0);
					return 1;

				default:
					vtGetScene()->OnKey(key, 0);
					return 1;
			}
		// process mouse events for this window
		// First: handle a pushed button by checking
		//        which button has been pushed and
		//        convert it into VTerrain mouse buttons.
		case FL_PUSH:
			if(Fl::event_button() == FL_LEFT){
				vtp_event.button = VT_LEFT;
			}
			else if (Fl::event_button() == FL_MIDDLE){
				vtp_event.button = VT_MIDDLE;
			}
			else if (Fl::event_button() == FL_RIGHT){
				vtp_event.button = VT_RIGHT;
			}
			x = Fl::event_x();
			y = Fl::event_y();
			vtp_event.pos.Set(x, y);
			vtp_event.type = VT_DOWN;
			vtp_event.flags = 0;
			vtGetScene()->OnMouse(vtp_event);
			return 1;
		// Second: if a button has been pushed (i.e. FL_PUSH returned 1),
		//         and the mouse position changed while the button is still
		//         pushed, set the VTerrain tupe to MOVE and force a redraw()
		//	   of the window
		case FL_DRAG:
			x = Fl::event_x();
			y = Fl::event_y();
			vtp_event.type = VT_MOVE;
			vtp_event.button = VT_NONE;
			vtp_event.flags = 0;
			vtp_event.pos.Set(x, y);
			vtGetScene()->OnMouse(vtp_event);
			redraw();
			return 1;
		// Third: handle the mouse button being released
		case FL_RELEASE:
			if(Fl::event_button() == FL_LEFT){
				vtp_event.button = VT_LEFT;
			}
			else if (Fl::event_button() == FL_MIDDLE){
				vtp_event.button = VT_MIDDLE;
			}
			else if (Fl::event_button() == FL_RIGHT){
				vtp_event.button = VT_RIGHT;
			}
			vtp_event.type = VT_UP;
			x = Fl::event_x();
			y = Fl::event_y();
			vtp_event.flags = 0;
			vtp_event.pos.Set(x, y);
			vtGetScene()->OnMouse(vtp_event);
			return 1;
	}

	return Fl_Gl_Window::handle(event);
}

//
// Create the 3d terrain scene
//
bool VTPWindow::CreateScene()
{
	// Get a handle to the vtScene - one is already created for you
	vtScene *pScene = vtGetScene();
	pScene->Init();

	// Log messages to make troubleshooting easier
	VTSTARTLOG("debug.txt");
	VTLOG("glutSimple\n");

	// Look up the camera
	vtCamera *pCamera = pScene->GetCamera();
	pCamera->SetHither(10);
	pCamera->SetYon(1000000);

	// The  terrain scene will contain all the terrains that are created.
	vtTerrainScene *ts = new vtTerrainScene;

	// Set the global data path
	vtStringArray paths;
	paths.push_back(vtString("Data/"));
	ts->SetDataPath(paths);

	// Begin creating the scene, including the sun and sky
	vtGroup *pTopGroup = ts->BeginTerrainScene();

	// Tell the scene graph to point to this terrain scene
	pScene->SetRoot(pTopGroup);

	// Create a new vtTerrain, read its parameters from a file
	vtTerrain *pTerr = new vtTerrain;
	pTerr->SetParamFile("Data/Simple.xml");

	// Add the terrain to the scene, and contruct it
	ts->AppendTerrain(pTerr);
	if (!ts->BuildTerrain(pTerr))
	{
		printf("Terrain creation failed: %s\n",
			(const char *)pTerr->GetLastError());
		return false;
	}
	ts->SetCurrentTerrain(pTerr);

	// Create a navigation engine to move around on the terrain
	// Get flight speed from terrain parameters
	float fSpeed = pTerr->GetParams().GetValueFloat(STR_NAVSPEED);

	vtTerrainFlyer *pFlyer = new vtTerrainFlyer(fSpeed);
	pFlyer->SetTarget(pCamera);
	pFlyer->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pFlyer);

	// Minimum height over terrain is 100 m
	vtHeightConstrain *pConstrain = new vtHeightConstrain(100);
	pConstrain->SetTarget(pCamera);
        pConstrain->SetHeightField(pTerr->GetHeightField());
        pScene->AddEngine(pConstrain);

	return true;
}

//
//  The works.
//
int main(int, char ** )
{
#ifdef __FreeBSD__
	/*  FreeBSD is more stringent with FP ops by default, and OSG is doing  */
	/*    silly things sqrt(Inf) (computing lengths of MAXFLOAT and NaN     */
	/*    Vec3's).   This turns off FP bug core dumps, ignoring the error   */
	/*    like most platforms do by default.                                */
	fpsetmask(0);
#endif

	// create an instance of the VTPWindow class
	VTPWindow MyWindow(800,600,"FLTK and VTP example");
	// show it
	MyWindow.show();

	// Note: with FLTK you can create more instances of the same
	// VTPWindow class. SDL and GLUT allow to have only one active
	// window with OpenGL context, while FLTK can have more in which
	// each window will have its own callbacks.

	// go into the FLTK mainloop
	return(Fl::run());
}

<commit_msg>chg to H for FLTK header extension<commit_after>//
// Name:     appfltk.cpp
// Purpose:  Example FLTK/vtlib application
//   (tested only on Linux using FLTK 1.1.5)
//   (tested only on Windows using FLTK 1.1.6)
//
// Copyright (c) 2004 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//
// Provided by Clark Borst (November 12, 2004)

#ifdef __FreeBSD__
#  include <ieeefp.h>
#endif

#include <iostream>

// the required FLTK headers for this example
// note that fltk seems to use capital H for cpp headers!
#include <FL/Fl.H>
#include <FL/Fl_Gl_Window.H>
#include <FL/gl.h>
#include <GL/glu.h>

// the required VTP headers
#include "vtlib/vtlib.h"
#include "vtlib/core/Terrain.h"
#include "vtlib/core/TerrainScene.h"
#include "vtlib/core/NavEngines.h"
#include "vtdata/vtLog.h"

// handy definitions for FLTK mouse buttons
#define FL_LEFT 1
#define FL_MIDDLE 2
#define FL_RIGHT 3

using namespace std;

// prototype of global idle callback function
void IdleCallback(void* pData);

// create a new FLTK window with OpenGL context by making
// a subclass of the Fl_Gl_Window class
class VTPWindow : public Fl_Gl_Window
{
	public:
		VTPWindow(int width, int height, char* title);
		virtual ~VTPWindow();
		void InitializeGL();
		virtual void draw();
		bool CreateScene();
		virtual int handle(int event);
	private:
		int screenwidth, screenheight;
};

// the idle function will continuously update (redraw) the window,
// even when there are no events
void IdleCallback(void* pData)
{
	if (pData != NULL)
	{
		VTPWindow* pWindow = reinterpret_cast<VTPWindow*>(pData);
		// execute the draw() function of the window by invoking
		// method redraw()
		pWindow->redraw();
	}
}

// constructor
VTPWindow::VTPWindow(int width, int height, char* title) : Fl_Gl_Window(width, height, title)
{
	mode(FL_RGB | FL_ALPHA | FL_DEPTH | FL_DOUBLE);
	// add the idle function to this window
	Fl::add_idle(IdleCallback, this);
}

// destructor
VTPWindow::~VTPWindow()
{
	//
}

// init OpenGL
void VTPWindow::InitializeGL()
{
	glClearColor(.1f, .1f, .1f, 1);
	glEnable(GL_DEPTH_TEST);
}

// the draw() function must be overridden by your own
// drawing code. By invoking method redraw(), FLTK will
// call this draw() method
void VTPWindow::draw()
{
	static bool firstTime = true;
	if (firstTime){
		// create the VTerrain scene
		CreateScene();
		// init OpenGL
		InitializeGL();
		// get the window size with Fl::Widget (parent class of Fl_Gl_Window) methods w() and h()
		screenwidth  = w();
		screenheight = h();
		// print the window size to the terminal
		cout << screenwidth << endl << screenheight << endl;
		// adjust the scene's viewport to the FL window size
		vtGetScene()->SetWindowSize(screenwidth, screenheight);
		// prevent this sequence from being executed over and over again
		firstTime = false;
	};

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	// update the terrain scene
	vtGetScene()->DoUpdate();
}

// the event handler of the window, which takes mouse and keyboard events
// and converts them into VTerrain events
int VTPWindow::handle(int event)
{
	vtMouseEvent vtp_event;
	int x, y;
	unsigned char key;

	switch (event)
	{
		case FL_FOCUS:
		case FL_UNFOCUS:
		return 1;

		// process keyboard events for this window
		case FL_KEYBOARD:
			key = Fl::event_key();
			switch (key)
			{
				// ESC means quit the program
				case 27 :
					exit(0);
					return 1;
				// q means quit the program
				case 'q':
					exit(0);
					return 1;

				default:
					vtGetScene()->OnKey(key, 0);
					return 1;
			}
		// process mouse events for this window
		// First: handle a pushed button by checking
		//        which button has been pushed and
		//        convert it into VTerrain mouse buttons.
		case FL_PUSH:
			if(Fl::event_button() == FL_LEFT){
				vtp_event.button = VT_LEFT;
			}
			else if (Fl::event_button() == FL_MIDDLE){
				vtp_event.button = VT_MIDDLE;
			}
			else if (Fl::event_button() == FL_RIGHT){
				vtp_event.button = VT_RIGHT;
			}
			x = Fl::event_x();
			y = Fl::event_y();
			vtp_event.pos.Set(x, y);
			vtp_event.type = VT_DOWN;
			vtp_event.flags = 0;
			vtGetScene()->OnMouse(vtp_event);
			return 1;
		// Second: if a button has been pushed (i.e. FL_PUSH returned 1),
		//         and the mouse position changed while the button is still
		//         pushed, set the VTerrain tupe to MOVE and force a redraw()
		//	   of the window
		case FL_DRAG:
			x = Fl::event_x();
			y = Fl::event_y();
			vtp_event.type = VT_MOVE;
			vtp_event.button = VT_NONE;
			vtp_event.flags = 0;
			vtp_event.pos.Set(x, y);
			vtGetScene()->OnMouse(vtp_event);
			redraw();
			return 1;
		// Third: handle the mouse button being released
		case FL_RELEASE:
			if(Fl::event_button() == FL_LEFT){
				vtp_event.button = VT_LEFT;
			}
			else if (Fl::event_button() == FL_MIDDLE){
				vtp_event.button = VT_MIDDLE;
			}
			else if (Fl::event_button() == FL_RIGHT){
				vtp_event.button = VT_RIGHT;
			}
			vtp_event.type = VT_UP;
			x = Fl::event_x();
			y = Fl::event_y();
			vtp_event.flags = 0;
			vtp_event.pos.Set(x, y);
			vtGetScene()->OnMouse(vtp_event);
			return 1;
	}

	return Fl_Gl_Window::handle(event);
}

//
// Create the 3d terrain scene
//
bool VTPWindow::CreateScene()
{
	// Get a handle to the vtScene - one is already created for you
	vtScene *pScene = vtGetScene();
	pScene->Init();

	// Log messages to make troubleshooting easier
	VTSTARTLOG("debug.txt");
	VTLOG("glutSimple\n");

	// Look up the camera
	vtCamera *pCamera = pScene->GetCamera();
	pCamera->SetHither(10);
	pCamera->SetYon(1000000);

	// The  terrain scene will contain all the terrains that are created.
	vtTerrainScene *ts = new vtTerrainScene;

	// Set the global data path
	vtStringArray paths;
	paths.push_back(vtString("Data/"));
	ts->SetDataPath(paths);

	// Begin creating the scene, including the sun and sky
	vtGroup *pTopGroup = ts->BeginTerrainScene();

	// Tell the scene graph to point to this terrain scene
	pScene->SetRoot(pTopGroup);

	// Create a new vtTerrain, read its parameters from a file
	vtTerrain *pTerr = new vtTerrain;
	pTerr->SetParamFile("Data/Simple.xml");

	// Add the terrain to the scene, and contruct it
	ts->AppendTerrain(pTerr);
	if (!ts->BuildTerrain(pTerr))
	{
		printf("Terrain creation failed: %s\n",
			(const char *)pTerr->GetLastError());
		return false;
	}
	ts->SetCurrentTerrain(pTerr);

	// Create a navigation engine to move around on the terrain
	// Get flight speed from terrain parameters
	float fSpeed = pTerr->GetParams().GetValueFloat(STR_NAVSPEED);

	vtTerrainFlyer *pFlyer = new vtTerrainFlyer(fSpeed);
	pFlyer->SetTarget(pCamera);
	pFlyer->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pFlyer);

	// Minimum height over terrain is 100 m
	vtHeightConstrain *pConstrain = new vtHeightConstrain(100);
	pConstrain->SetTarget(pCamera);
        pConstrain->SetHeightField(pTerr->GetHeightField());
        pScene->AddEngine(pConstrain);

	return true;
}

//
//  The works.
//
int main(int, char ** )
{
#ifdef __FreeBSD__
	/*  FreeBSD is more stringent with FP ops by default, and OSG is doing  */
	/*    silly things sqrt(Inf) (computing lengths of MAXFLOAT and NaN     */
	/*    Vec3's).   This turns off FP bug core dumps, ignoring the error   */
	/*    like most platforms do by default.                                */
	fpsetmask(0);
#endif

	// create an instance of the VTPWindow class
	VTPWindow MyWindow(800,600,"FLTK and VTP example");
	// show it
	MyWindow.show();

	// Note: with FLTK you can create more instances of the same
	// VTPWindow class. SDL and GLUT allow to have only one active
	// window with OpenGL context, while FLTK can have more in which
	// each window will have its own callbacks.

	// go into the FLTK mainloop
	return(Fl::run());
}

<|endoftext|>


<commit_before><commit_msg>Fixes leaks in remote_unittest. This change just replaces pointers used in remote_unittest with scoped_ptr<> to delete the memory used in the test, and replaces scoped_ptr<> in differ.h with scoped_array<> to avoid mismatched deletes.<commit_after><|endoftext|>