<commit_before>#pragma once

#include "configuration_monitor.hpp"
#include "console_user_id_monitor.hpp"
#include "constants.hpp"
#include "frontmost_application_observer.hpp"
#include "grabber_client.hpp"
#include "input_source_observer.hpp"
#include "logger.hpp"
#include "menu_process_manager.hpp"
#include "receiver.hpp"
#include "session.hpp"
#include "system_preferences_monitor.hpp"
#include "version_monitor.hpp"
#include "version_monitor_utility.hpp"
#include <thread>

namespace krbn {
class components_manager final {
public:
  components_manager(const components_manager&) = delete;

  components_manager(void) {
    version_monitor_ = version_monitor_utility::make_version_monitor_stops_main_run_loop_when_version_changed();

    console_user_id_monitor_.console_user_id_changed.connect([this](boost::optional<uid_t> uid) {
      version_monitor_->manual_check();

      filesystem::create_directory_with_intermediate_directories(
          constants::get_user_configuration_directory(),
          0700);

      if (uid != getuid()) {
        stop_grabber_client();
        return;
      }

      receiver_ = std::make_unique<receiver>();

      receiver_->bound.connect([this] {
        stop_grabber_client();
        start_grabber_client();
      });

      receiver_->bind_failed.connect([this](auto&& error_code) {
        stop_grabber_client();
      });

      receiver_->closed.connect([this] {
        stop_grabber_client();
      });

      receiver_->start();
    });
    console_user_id_monitor_.start();
  }

  ~components_manager(void) {
    console_user_id_monitor_.stop();

    receiver_ = nullptr;

    stop_grabber_client();
  }

private:
  void start_grabber_client(void) {
    std::lock_guard<std::mutex> lock(grabber_client_mutex_);

    if (grabber_client_) {
      return;
    }

    grabber_client_ = std::make_shared<grabber_client>();

    grabber_client_->connected.connect([this] {
      version_monitor_->manual_check();

      stop_child_components();
      start_child_components();
    });

    grabber_client_->connect_failed.connect([this](auto&& error_code) {
      version_monitor_->manual_check();

      stop_child_components();
    });

    grabber_client_->closed.connect([this] {
      version_monitor_->manual_check();

      stop_child_components();
    });

    grabber_client_->start();
  }

  void stop_grabber_client(void) {
    std::lock_guard<std::mutex> lock(grabber_client_mutex_);

    grabber_client_ = nullptr;
    stop_child_components();
  }

  void start_child_components(void) {
    std::lock_guard<std::mutex> lock(child_components_mutex_);

    configuration_monitor_ = std::make_shared<configuration_monitor>(
        constants::get_user_core_configuration_file_path());

    start_menu_process_manager();
    start_system_preferences_monitor();
    start_frontmost_application_observer();
    start_input_source_observer();

    configuration_monitor_->start();
  }

  void stop_child_components(void) {
    std::lock_guard<std::mutex> lock(child_components_mutex_);

    stop_menu_process_manager();
    stop_system_preferences_monitor();
    stop_frontmost_application_observer();
    stop_input_source_observer();

    configuration_monitor_ = nullptr;
  }

  void start_menu_process_manager(void) {
    if (menu_process_manager_) {
      return;
    }

    menu_process_manager_ = std::make_unique<menu_process_manager>(configuration_monitor_);
  }

  void stop_menu_process_manager(void) {
    menu_process_manager_ = nullptr;
  }

  void start_system_preferences_monitor(void) {
    if (system_preferences_monitor_) {
      return;
    }

    system_preferences_monitor_ = std::make_unique<system_preferences_monitor>(
        [this](auto&& system_preferences) {
          std::lock_guard<std::mutex> lock(grabber_client_mutex_);

          if (grabber_client_) {
            grabber_client_->system_preferences_updated(system_preferences);
          }
        },
        configuration_monitor_);
  }

  void stop_system_preferences_monitor(void) {
    system_preferences_monitor_ = nullptr;
  }

  void start_frontmost_application_observer(void) {
    if (frontmost_application_observer_) {
      return;
    }

    frontmost_application_observer_ = std::make_unique<frontmost_application_observer>(
        [this](auto&& bundle_identifier, auto&& file_path) {
          if (bundle_identifier == "org.pqrs.Karabiner.EventViewer" ||
              bundle_identifier == "org.pqrs.Karabiner-EventViewer") {
            return;
          }

          {
            std::lock_guard<std::mutex> lock(grabber_client_mutex_);

            if (grabber_client_) {
              grabber_client_->frontmost_application_changed(bundle_identifier, file_path);
            }
          }
        });
  }

  void stop_frontmost_application_observer(void) {
    frontmost_application_observer_ = nullptr;
  }

  void start_input_source_observer(void) {
    if (input_source_observer_) {
      return;
    }

    input_source_observer_ = std::make_unique<input_source_observer>(
        [this](auto&& input_source_identifiers) {
          std::lock_guard<std::mutex> lock(grabber_client_mutex_);

          if (grabber_client_) {
            grabber_client_->input_source_changed(input_source_identifiers);
          }
        });
  }

  void stop_input_source_observer(void) {
    input_source_observer_ = nullptr;
  }

  // Core components

  std::shared_ptr<version_monitor> version_monitor_;

  console_user_id_monitor console_user_id_monitor_;
  std::unique_ptr<receiver> receiver_;

  std::shared_ptr<grabber_client> grabber_client_;
  std::mutex grabber_client_mutex_;

  // Child components

  std::mutex child_components_mutex_;

  std::shared_ptr<configuration_monitor> configuration_monitor_;
  std::unique_ptr<menu_process_manager> menu_process_manager_;
  std::unique_ptr<system_preferences_monitor> system_preferences_monitor_;
  // `frontmost_application_observer` does not work properly in karabiner_grabber after fast user switching.
  // Therefore, we have to use `frontmost_application_observer` in `console_user_server`.
  std::unique_ptr<frontmost_application_observer> frontmost_application_observer_;
  std::unique_ptr<input_source_observer> input_source_observer_;
};
} // namespace krbn
<commit_msg>add make_menu_process_manager, make_system_preferences_monitor<commit_after>#pragma once

#include "configuration_monitor.hpp"
#include "console_user_id_monitor.hpp"
#include "constants.hpp"
#include "frontmost_application_observer.hpp"
#include "grabber_client.hpp"
#include "input_source_observer.hpp"
#include "logger.hpp"
#include "menu_process_manager.hpp"
#include "receiver.hpp"
#include "session.hpp"
#include "system_preferences_monitor.hpp"
#include "version_monitor.hpp"
#include "version_monitor_utility.hpp"
#include <thread>

namespace krbn {
class components_manager final {
public:
  components_manager(const components_manager&) = delete;

  components_manager(void) {
    version_monitor_ = version_monitor_utility::make_version_monitor_stops_main_run_loop_when_version_changed();

    console_user_id_monitor_.console_user_id_changed.connect([this](boost::optional<uid_t> uid) {
      version_monitor_->manual_check();

      filesystem::create_directory_with_intermediate_directories(
          constants::get_user_configuration_directory(),
          0700);

      if (uid != getuid()) {
        stop_grabber_client();
        return;
      }

      receiver_ = std::make_unique<receiver>();

      receiver_->bound.connect([this] {
        stop_grabber_client();
        start_grabber_client();
      });

      receiver_->bind_failed.connect([this](auto&& error_code) {
        stop_grabber_client();
      });

      receiver_->closed.connect([this] {
        stop_grabber_client();
      });

      receiver_->start();
    });
    console_user_id_monitor_.start();
  }

  ~components_manager(void) {
    console_user_id_monitor_.stop();

    receiver_ = nullptr;

    stop_grabber_client();
  }

private:
  void start_grabber_client(void) {
    std::lock_guard<std::mutex> lock(grabber_client_mutex_);

    if (grabber_client_) {
      return;
    }

    grabber_client_ = std::make_shared<grabber_client>();

    grabber_client_->connected.connect([this] {
      version_monitor_->manual_check();

      stop_child_components();
      start_child_components();
    });

    grabber_client_->connect_failed.connect([this](auto&& error_code) {
      version_monitor_->manual_check();

      stop_child_components();
    });

    grabber_client_->closed.connect([this] {
      version_monitor_->manual_check();

      stop_child_components();
    });

    grabber_client_->start();
  }

  void stop_grabber_client(void) {
    std::lock_guard<std::mutex> lock(grabber_client_mutex_);

    grabber_client_ = nullptr;
    stop_child_components();
  }

  void start_child_components(void) {
    std::weak_ptr<grabber_client> grabber_client_weak_ptr;
    {
      std::lock_guard<std::mutex> lock(grabber_client_mutex_);
      grabber_client_weak_ptr = grabber_client_;
    }

    {
      std::lock_guard<std::mutex> lock(child_components_mutex_);

      configuration_monitor_ = std::make_shared<configuration_monitor>(
          constants::get_user_core_configuration_file_path());

      menu_process_manager_ = make_menu_process_manager(configuration_monitor_);
      system_preferences_monitor_ = make_system_preferences_monitor(configuration_monitor_,
                                                                    grabber_client_weak_ptr);
      start_frontmost_application_observer();
      start_input_source_observer();

      configuration_monitor_->start();
    }
  }

  void stop_child_components(void) {
    std::lock_guard<std::mutex> lock(child_components_mutex_);

    menu_process_manager_ = nullptr;
    system_preferences_monitor_ = nullptr;
    stop_frontmost_application_observer();
    stop_input_source_observer();

    configuration_monitor_ = nullptr;
  }

  static std::unique_ptr<menu_process_manager> make_menu_process_manager(std::shared_ptr<configuration_monitor> configuration_monitor) {
    return std::make_unique<menu_process_manager>(configuration_monitor);
  }

  static std::unique_ptr<system_preferences_monitor> make_system_preferences_monitor(std::shared_ptr<configuration_monitor> configuration_monitor,
                                                                                std::weak_ptr<grabber_client> grabber_client) {
    return std::make_unique<system_preferences_monitor>(
        [grabber_client](auto&& system_preferences) {
          if (auto client = grabber_client.lock()) {
            client->system_preferences_updated(system_preferences);
          }
        },
        configuration_monitor);
  }

  void start_frontmost_application_observer(void) {
    if (frontmost_application_observer_) {
      return;
    }

    frontmost_application_observer_ = std::make_unique<frontmost_application_observer>(
        [this](auto&& bundle_identifier, auto&& file_path) {
          if (bundle_identifier == "org.pqrs.Karabiner.EventViewer" ||
              bundle_identifier == "org.pqrs.Karabiner-EventViewer") {
            return;
          }

          {
            std::lock_guard<std::mutex> lock(grabber_client_mutex_);

            if (grabber_client_) {
              grabber_client_->frontmost_application_changed(bundle_identifier, file_path);
            }
          }
        });
  }

  void stop_frontmost_application_observer(void) {
    frontmost_application_observer_ = nullptr;
  }

  void start_input_source_observer(void) {
    if (input_source_observer_) {
      return;
    }

    input_source_observer_ = std::make_unique<input_source_observer>(
        [this](auto&& input_source_identifiers) {
          std::lock_guard<std::mutex> lock(grabber_client_mutex_);

          if (grabber_client_) {
            grabber_client_->input_source_changed(input_source_identifiers);
          }
        });
  }

  void stop_input_source_observer(void) {
    input_source_observer_ = nullptr;
  }

  // Core components

  std::shared_ptr<version_monitor> version_monitor_;

  console_user_id_monitor console_user_id_monitor_;
  std::unique_ptr<receiver> receiver_;

  std::shared_ptr<grabber_client> grabber_client_;
  std::mutex grabber_client_mutex_;

  // Child components

  std::mutex child_components_mutex_;

  std::shared_ptr<configuration_monitor> configuration_monitor_;
  std::unique_ptr<menu_process_manager> menu_process_manager_;
  std::unique_ptr<system_preferences_monitor> system_preferences_monitor_;
  // `frontmost_application_observer` does not work properly in karabiner_grabber after fast user switching.
  // Therefore, we have to use `frontmost_application_observer` in `console_user_server`.
  std::unique_ptr<frontmost_application_observer> frontmost_application_observer_;
  std::unique_ptr<input_source_observer> input_source_observer_;
};
} // namespace krbn
<|endoftext|>


<commit_before>#include "main.hpp"

#include "ParticleRenderer.hpp"
#include "Timeline.hpp"

void ParticleRenderer::reset() {
  graphicsPipeline.destroy();
  uniforms.clear();
}

void ParticleRenderer::setTimeline(std::unique_ptr<Timeline> _timeline) {
  reset();

  timeline = std::move(_timeline);

  state.clock.setPeriod(timeline->getPeriod());

  std::vector<UniformDescription> uniforms;
  ShaderBuilder vertexShader, fragmentShader;

  uniforms.emplace_back("invImageAspectRatio", GLSLType::Float,
                        [](const RenderProps &props) {
                          return UniformValue((float)props.webcam_height / props.webcam_width);
                        });
  uniforms.emplace_back("invScreenAspectRatio", GLSLType::Float,
                        [](const RenderProps &props) {
                          return UniformValue((float)props.screen_height / props.screen_width);
                        });
  uniforms.emplace_back("viewProjectionMatrix", GLSLType::Mat4,
                        [](const RenderProps &props) {
                          const auto aspect = (float)props.screen_width / props.screen_height;
                          const auto underscan = 1 - ((float)props.screen_height / props.screen_width) /
                                                         ((float)props.webcam_height / props.webcam_width);
                          // clang-format off
                          return UniformValue(glm::mat4(
                              2.f / aspect, 0.f, 0.f, 0.f,
                              0.f, 2.f, 0.f, 0.f,
                              0.f, 0.f, 0.f, 0.f,
                              underscan - 1.f, -1.f, 0.f, 1.f
                          ));
                          // clang-format on
                        });
  uniforms.emplace_back("invViewProjectionMatrix", GLSLType::Mat4,
                        [](const RenderProps &props) {
                          const auto aspect = (float)props.screen_width / props.screen_height;
                          const auto underscan = 1 - ((float)props.screen_height / props.screen_width) /
                                                         ((float)props.webcam_height / props.webcam_width);
                          // clang-format off
                          return UniformValue(glm::mat4(
                            .5f * aspect, 0.f, 0.f, 0.f,
                            0.f, .5f, 0.f, 0.f,
                            0.f, 0.f, 0.f, 0.f,
                            (-.5f * (underscan - 1.f)) * aspect, .5f, 0.f, 1.f
                          ));
                          // clang-format on
                        });
  uniforms.emplace_back("particleSize", GLSLType::Float,
                        [](const RenderProps &props) {
                          //TODO: particleScaling config
                          return UniformValue(((float)props.screen_height / props.webcam_height) * 2 /* * particleScaling*/);
                        });
  uniforms.emplace_back("globalTime", GLSLType::Float,
                        [](const RenderProps &props) {
                          return UniformValue(props.state.clock.getTime());
                        });

  vertexShader.appendIn("texcoord", GLSLType::Vec2);
  vertexShader.appendIn("rgb", GLSLType::Vec3);
  vertexShader.appendIn("hsv", GLSLType::Vec3);

  vertexShader.appendOut("color", GLSLType::Vec3);

  vertexShader.appendGlobal("PI", GLSLType::Float, std::to_string(PI));

  vertexShader.appendFunction(R"glsl(
    vec2 getDirectionVector(float angle) {
      return vec2(cos(angle), sin(angle));
    }
  )glsl");

  fragmentShader.appendIn("color", GLSLType::Vec3);

  fragmentShader.appendOut("frag_color", GLSLType::Vec4);

  vertexShader.appendMainBody(R"glsl(
    vec3 initialPosition = vec3(texcoord, 0);
    initialPosition.y *= invImageAspectRatio;
    float pointSize = max(particleSize, 0.);

    vec3 position = initialPosition;
  )glsl");

  fragmentShader.appendMainBody(R"glsl(
    float v = pow(max(1. - 2. * length(gl_PointCoord - vec2(.5)), 0.), 1.5);
  )glsl");

  unsigned instanceId = 0;
  timeline->forEachInstance([&](const IEffect &i) {
    Uniforms instanceUniforms(uniforms, instanceId++);
    vertexShader.appendMainBody(("if(" + std::to_string(i.getTimeBegin()) +
                                 "<= globalTime && globalTime <=" +
                                 std::to_string(i.getTimeEnd()) + ") {")
                                    .c_str());
#if 1
    vertexShader.appendMainBody("\n#line 0\n");
    fragmentShader.appendMainBody("\n#line 0\n");
#endif
    i.registerEffect(instanceUniforms, vertexShader, fragmentShader);
    vertexShader.appendMainBody("}");
  });

  vertexShader.appendMainBody(R"glsl(
    color = rgb;
    gl_PointSize = pointSize;
    gl_Position = viewProjectionMatrix * vec4(position, 1.);
  )glsl");

  // TODO: different overlap modes
  fragmentShader.appendMainBody(R"glsl(
    frag_color = vec4(color * v, 1);
  )glsl");

  for (const auto &u : uniforms) {
    vertexShader.appendUniform(u);
    fragmentShader.appendUniform(u);
  }

  const auto vertexShaderSource = vertexShader.assemble();
  const auto fragmentShaderSource = fragmentShader.assemble();

  graphicsPipeline.create(vertexShaderSource.c_str(),
                          fragmentShaderSource.c_str());

  for (const auto &u : uniforms) {
    UniformElement newElement;
    newElement.location = graphicsPipeline.getUniformLocation(u.name.c_str());
    newElement.value = u.value;
    this->uniforms.push_back(newElement);
  }
}

void ParticleRenderer::update(float dt) {
  state.clock.frame(dt);
}

void ParticleRenderer::render(const RendererParameters &parameters) {
  RenderProps props(parameters, state);

  graphicsPipeline.bind();

  for (const auto &uniform : uniforms) {
    const auto value = uniform.value(props);
    switch (value.type) {
    case GLSLType::Float:
      glUniform1fv(uniform.location, 1, &value.data.f);
      break;
    case GLSLType::Vec2:
      glUniform2fv(uniform.location, 1, &value.data.v2[0]);
      break;
    case GLSLType::Vec3:
      glUniform3fv(uniform.location, 1, &value.data.v3[0]);
      break;
    case GLSLType::Vec4:
      glUniform4fv(uniform.location, 1, &value.data.v4[0]);
      break;
    case GLSLType::Mat4:
      glUniformMatrix4fv(uniform.location, 1, GL_FALSE, &value.data.m4[0][0]);
      break;
    }
  }

  parameters.particle_buffer.draw();
}
<commit_msg>Fix black bars in portrait orientation<commit_after>#include "main.hpp"

#include "ParticleRenderer.hpp"
#include "Timeline.hpp"

void ParticleRenderer::reset() {
  graphicsPipeline.destroy();
  uniforms.clear();
}

void ParticleRenderer::setTimeline(std::unique_ptr<Timeline> _timeline) {
  reset();

  timeline = std::move(_timeline);

  state.clock.setPeriod(timeline->getPeriod());

  std::vector<UniformDescription> uniforms;
  ShaderBuilder vertexShader, fragmentShader;

  uniforms.emplace_back("invImageAspectRatio", GLSLType::Float,
                        [](const RenderProps &props) {
                          return UniformValue((float)props.webcam_height / props.webcam_width);
                        });
  uniforms.emplace_back("invScreenAspectRatio", GLSLType::Float,
                        [](const RenderProps &props) {
                          return UniformValue((float)props.screen_height / props.screen_width);
                        });
  uniforms.emplace_back("viewProjectionMatrix", GLSLType::Mat4,
                        [](const RenderProps &props) {
                          const auto aspect = (float)props.screen_width / props.screen_height;
                          const auto underscan = 1 - ((float)props.screen_height / props.screen_width) /
                                                         ((float)props.webcam_height / props.webcam_width);
                          // clang-format off
                          return UniformValue(glm::mat4(
                              2.f / aspect, 0.f, 0.f, 0.f,
                              0.f, 2.f, 0.f, 0.f,
                              0.f, 0.f, 0.f, 0.f,
                              underscan - 1.f, -1.f, 0.f, 1.f
                          ));
                          // clang-format on
                        });
  uniforms.emplace_back("invViewProjectionMatrix", GLSLType::Mat4,
                        [](const RenderProps &props) {
                          const auto aspect = (float)props.screen_width / props.screen_height;
                          const auto underscan = 1 - ((float)props.screen_height / props.screen_width) /
                                                         ((float)props.webcam_height / props.webcam_width);
                          // clang-format off
                          return UniformValue(glm::mat4(
                            .5f * aspect, 0.f, 0.f, 0.f,
                            0.f, .5f, 0.f, 0.f,
                            0.f, 0.f, 0.f, 0.f,
                            (-.5f * (underscan - 1.f)) * aspect, .5f, 0.f, 1.f
                          ));
                          // clang-format on
                        });
  uniforms.emplace_back("particleSize", GLSLType::Float,
                        [](const RenderProps &props) {
                          //TODO: particleScaling config
                          return UniformValue(((float)props.screen_height / props.webcam_height) * 2 /* * particleScaling*/);
                        });
  uniforms.emplace_back("globalTime", GLSLType::Float,
                        [](const RenderProps &props) {
                          return UniformValue(props.state.clock.getTime());
                        });

  vertexShader.appendIn("texcoord", GLSLType::Vec2);
  vertexShader.appendIn("rgb", GLSLType::Vec3);
  vertexShader.appendIn("hsv", GLSLType::Vec3);

  vertexShader.appendOut("color", GLSLType::Vec3);

  vertexShader.appendGlobal("PI", GLSLType::Float, std::to_string(PI));

  vertexShader.appendFunction(R"glsl(
    vec2 getDirectionVector(float angle) {
      return vec2(cos(angle), sin(angle));
    }
  )glsl");

  fragmentShader.appendIn("color", GLSLType::Vec3);

  fragmentShader.appendOut("frag_color", GLSLType::Vec4);

  vertexShader.appendMainBody(R"glsl(
    vec3 initialPosition = vec3(texcoord, 0);
    initialPosition.x /= invImageAspectRatio;
    float pointSize = max(particleSize, 0.);

    vec3 position = initialPosition;
  )glsl");

  fragmentShader.appendMainBody(R"glsl(
    float v = pow(max(1. - 2. * length(gl_PointCoord - vec2(.5)), 0.), 1.5);
  )glsl");

  unsigned instanceId = 0;
  timeline->forEachInstance([&](const IEffect &i) {
    Uniforms instanceUniforms(uniforms, instanceId++);
    vertexShader.appendMainBody(("if(" + std::to_string(i.getTimeBegin()) +
                                 "<= globalTime && globalTime <=" +
                                 std::to_string(i.getTimeEnd()) + ") {")
                                    .c_str());
#if 1
    vertexShader.appendMainBody("\n#line 0\n");
    fragmentShader.appendMainBody("\n#line 0\n");
#endif
    i.registerEffect(instanceUniforms, vertexShader, fragmentShader);
    vertexShader.appendMainBody("}");
  });

  vertexShader.appendMainBody(R"glsl(
    color = rgb;
    gl_PointSize = pointSize;
    gl_Position = viewProjectionMatrix * vec4(position, 1.);
  )glsl");

  // TODO: different overlap modes
  fragmentShader.appendMainBody(R"glsl(
    frag_color = vec4(color * v, 1);
  )glsl");

  for (const auto &u : uniforms) {
    vertexShader.appendUniform(u);
    fragmentShader.appendUniform(u);
  }

  const auto vertexShaderSource = vertexShader.assemble();
  const auto fragmentShaderSource = fragmentShader.assemble();

  graphicsPipeline.create(vertexShaderSource.c_str(),
                          fragmentShaderSource.c_str());

  for (const auto &u : uniforms) {
    UniformElement newElement;
    newElement.location = graphicsPipeline.getUniformLocation(u.name.c_str());
    newElement.value = u.value;
    this->uniforms.push_back(newElement);
  }
}

void ParticleRenderer::update(float dt) {
  state.clock.frame(dt);
}

void ParticleRenderer::render(const RendererParameters &parameters) {
  RenderProps props(parameters, state);

  graphicsPipeline.bind();

  for (const auto &uniform : uniforms) {
    const auto value = uniform.value(props);
    switch (value.type) {
    case GLSLType::Float:
      glUniform1fv(uniform.location, 1, &value.data.f);
      break;
    case GLSLType::Vec2:
      glUniform2fv(uniform.location, 1, &value.data.v2[0]);
      break;
    case GLSLType::Vec3:
      glUniform3fv(uniform.location, 1, &value.data.v3[0]);
      break;
    case GLSLType::Vec4:
      glUniform4fv(uniform.location, 1, &value.data.v4[0]);
      break;
    case GLSLType::Mat4:
      glUniformMatrix4fv(uniform.location, 1, GL_FALSE, &value.data.m4[0][0]);
      break;
    }
  }

  parameters.particle_buffer.draw();
}
<|endoftext|>


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

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 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 "SpriteRenderPass.h"

DC_BEGIN_DREEMCHEST

namespace Scene {

// ** SpriteRenderPass::SpriteRenderPass
SpriteRenderPass::SpriteRenderPass( Ecs::Entities& entities, const Renderers& renderers ) : RenderPass2D( entities, "SpriteRenderPass", renderers )
{
}

// ** SpriteRenderPass::process
void SpriteRenderPass::process( u32 currentTime, f32 dt, SceneObject& sceneObject, Sprite& sprite, Transform& transform )
{
	// Get the sprite texture
	ImagePtr			 image   = sprite.image();
	AssetTexturePtr		 data    = image->data();
	Renderer::TexturePtr texture = data.valid() ? data->texture : Renderer::TexturePtr();

	// Get the rotation
	f32  angle = radians( transform.rotationZ() );
	f32  s	   = sinf( angle );
	f32  c	   = cosf( angle );

	// Calculate the basis vectors from rotation
	Vec2 up   = Vec2( s, c );
	Vec2 side = Vec2( up.y, -up.x );

	// Render oriented quad
	m_renderers.m_renderer2d->orientedQuad( texture, transform.x(), transform.y(), image->width() * 0.5f, image->height() * 0.5f, up, side, sprite.color() );
}

} // namespace Scene

DC_END_DREEMCHEST<commit_msg>Fixed sprite rendering scale<commit_after>/**************************************************************************

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 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 "SpriteRenderPass.h"

DC_BEGIN_DREEMCHEST

namespace Scene {

// ** SpriteRenderPass::SpriteRenderPass
SpriteRenderPass::SpriteRenderPass( Ecs::Entities& entities, const Renderers& renderers ) : RenderPass2D( entities, "SpriteRenderPass", renderers )
{
}

// ** SpriteRenderPass::process
void SpriteRenderPass::process( u32 currentTime, f32 dt, SceneObject& sceneObject, Sprite& sprite, Transform& transform )
{
	// Get the sprite texture
	ImagePtr			 image   = sprite.image();
	AssetTexturePtr		 data    = image->data();
	Renderer::TexturePtr texture = data.valid() ? data->texture : Renderer::TexturePtr();

	// Get the rotation
	f32  angle = radians( transform.rotationZ() );
	f32  s	   = sinf( angle );
	f32  c	   = cosf( angle );

	// Calculate the basis vectors from rotation
	Vec2 up   = Vec2( s, c );
	Vec2 side = Vec2( up.y, -up.x );

	// Calculate the sprite dimensions
	f32 width  = image->width()  * transform.scaleX() * 0.5f;
	f32 height = image->height() * transform.scaleY() * 0.5f;

	// Render oriented quad
	m_renderers.m_renderer2d->orientedQuad( texture, transform.x(), transform.y(), width,height, up, side, sprite.color() );
}

} // namespace Scene

DC_END_DREEMCHEST<|endoftext|>


<commit_before>//
// PROJECT:         Aspia Remote Desktop
// FILE:            host/host_session.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "host/host_session.h"
#include "host/host_session_launcher.h"
#include "base/version_helpers.h"
#include "base/scoped_privilege.h"

namespace aspia {

static const std::chrono::seconds kAttachTimeout{ 30 };

HostSession::HostSession(
    proto::SessionType session_type,
    std::shared_ptr<NetworkChannelProxy> channel_proxy)
    : session_type_(session_type),
      channel_proxy_(channel_proxy),
      process_connector_(channel_proxy)
{
    ui_thread_.Start(MessageLoop::TYPE_UI, this);
}

HostSession::~HostSession()
{
    ui_thread_.Stop();
}

void HostSession::OnBeforeThreadRunning()
{
    runner_ = ui_thread_.message_loop_proxy();
    DCHECK(runner_);

    OnSessionAttached(WTSGetActiveConsoleSessionId());

    // In Windows XP/2003, the console session always has a ID equal to 0.
    // We do not need to watch the session.
    if (IsWindowsVistaOrGreater())
    {
        bool ret = session_watcher_.StartWatching(this);
        DCHECK(ret);
    }
}

void HostSession::OnAfterThreadRunning()
{
    session_watcher_.StopWatching();
    OnSessionDetached();
    timer_.Stop();
    channel_proxy_->Disconnect();
}

void HostSession::OnSessionAttached(uint32_t session_id)
{
    DCHECK(runner_->BelongsToCurrentThread());
    DCHECK(state_ == State::DETACHED);
    DCHECK(!process_.IsValid());

    state_ = State::STARTING;

    std::wstring channel_id;

    if (process_connector_.StartServer(channel_id))
    {
        bool session_process_launched =
            LaunchSessionProcess(session_type_, session_id, channel_id);

        PipeChannel::DisconnectHandler disconnect_handler =
            std::bind(&HostSession::OnIpcChannelDisconnect, this);

        uint32_t user_data = static_cast<uint32_t>(session_type_);

        if (session_process_launched &&
            process_connector_.Accept(user_data,
                                      std::move(disconnect_handler)))
        {
            OnIpcChannelConnect(user_data);
            return;
        }
    }

    runner_->PostQuit();
}

void HostSession::OnSessionDetached()
{
    DCHECK(runner_->BelongsToCurrentThread());

    if (state_ == State::DETACHED)
        return;

    state_ = State::DETACHED;

    process_connector_.Disconnect();
    process_watcher_.StopWatching();

    if (session_type_ == proto::SESSION_TYPE_DESKTOP_MANAGE ||
        session_type_ == proto::SESSION_TYPE_DESKTOP_VIEW)
    {
        process_.Terminate(0, false);
    }

    process_.Close();

    // If the new session is not connected within the specified time interval,
    // an error occurred.
    timer_.Start(kAttachTimeout,
                 std::bind(&HostSession::OnSessionAttachTimeout, this));
}

void HostSession::OnProcessClose()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&HostSession::OnProcessClose, this));
        return;
    }

    switch (state_)
    {
        case State::ATTACHED:
        case State::STARTING:
            OnSessionDetached();
            break;

        case State::DETACHED:
            break;
    }
}

void HostSession::OnIpcChannelConnect(uint32_t user_data)
{
    DCHECK(runner_->BelongsToCurrentThread());

    // To open a host process and terminate it, additional privileges are
    // required. If the current process is running from the service, then the
    // privilege already exists, if not, then enable it.
    ScopedProcessPrivilege privilege(SE_DEBUG_NAME);

    // The client sends a process ID in user_data.
    process_ = Process::Open(user_data);

    bool ok = process_.IsValid();
    if (!ok)
    {
        LOG(ERROR) << "Unable to open session process: "
                   << GetLastSystemErrorString();
    }

    if (ok)
    {
        ok = process_watcher_.StartWatching(
            process_, std::bind(&HostSession::OnProcessClose, this));

        if (!ok)
        {
            LOG(ERROR) << "Process watcher not started";
            process_.Close();
        }
    }

    timer_.Stop();

    if (!ok)
    {
        state_ = State::DETACHED;
        runner_->PostQuit();
        return;
    }

    state_ = State::ATTACHED;
}

void HostSession::OnIpcChannelDisconnect()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&HostSession::OnIpcChannelDisconnect, this));
        return;
    }

    switch (state_)
    {
        case State::DETACHED:
            break;

        case State::ATTACHED:
        {
            OnSessionDetached();

            if (session_type_ == proto::SESSION_TYPE_FILE_TRANSFER ||
                session_type_ == proto::SESSION_TYPE_POWER_MANAGE)
            {
                state_ = State::DETACHED;

                timer_.Stop();
                runner_->PostQuit();
            }
        }
        break;

        case State::STARTING:
        {
            DCHECK(!process_.IsValid());

            state_ = State::DETACHED;

            timer_.Stop();
            runner_->PostQuit();
        }
        break;
    }
}

void HostSession::OnSessionAttachTimeout()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&HostSession::OnSessionAttachTimeout, this));
        return;
    }

    switch (state_)
    {
        case State::DETACHED:
        case State::STARTING:
            runner_->PostQuit();
            break;

        case State::ATTACHED:
            LOG(FATAL) << "In the attached state, the timer must me stopped";
            break;
    }
}

} // namespace aspia
<commit_msg>- Send quit message for all session types except Desktop Manage and Desktop View.<commit_after>//
// PROJECT:         Aspia Remote Desktop
// FILE:            host/host_session.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "host/host_session.h"
#include "host/host_session_launcher.h"
#include "base/version_helpers.h"
#include "base/scoped_privilege.h"

namespace aspia {

static const std::chrono::seconds kAttachTimeout{ 30 };

HostSession::HostSession(proto::SessionType session_type,
                         std::shared_ptr<NetworkChannelProxy> channel_proxy)
    : session_type_(session_type),
      channel_proxy_(channel_proxy),
      process_connector_(channel_proxy)
{
    ui_thread_.Start(MessageLoop::TYPE_UI, this);
}

HostSession::~HostSession()
{
    ui_thread_.Stop();
}

void HostSession::OnBeforeThreadRunning()
{
    runner_ = ui_thread_.message_loop_proxy();
    DCHECK(runner_);

    OnSessionAttached(WTSGetActiveConsoleSessionId());

    // In Windows XP/2003, the console session always has a ID equal to 0.
    // We do not need to watch the session.
    if (IsWindowsVistaOrGreater())
    {
        bool ret = session_watcher_.StartWatching(this);
        DCHECK(ret);
    }
}

void HostSession::OnAfterThreadRunning()
{
    session_watcher_.StopWatching();
    OnSessionDetached();
    timer_.Stop();
    channel_proxy_->Disconnect();
}

void HostSession::OnSessionAttached(uint32_t session_id)
{
    DCHECK(runner_->BelongsToCurrentThread());
    DCHECK(state_ == State::DETACHED);
    DCHECK(!process_.IsValid());

    state_ = State::STARTING;

    std::wstring channel_id;

    if (process_connector_.StartServer(channel_id))
    {
        bool session_process_launched = LaunchSessionProcess(session_type_, session_id, channel_id);

        PipeChannel::DisconnectHandler disconnect_handler =
            std::bind(&HostSession::OnIpcChannelDisconnect, this);

        uint32_t user_data = static_cast<uint32_t>(session_type_);

        if (session_process_launched &&
            process_connector_.Accept(user_data, std::move(disconnect_handler)))
        {
            OnIpcChannelConnect(user_data);
            return;
        }
    }

    runner_->PostQuit();
}

void HostSession::OnSessionDetached()
{
    DCHECK(runner_->BelongsToCurrentThread());

    if (state_ == State::DETACHED)
        return;

    state_ = State::DETACHED;

    process_connector_.Disconnect();
    process_watcher_.StopWatching();

    if (session_type_ == proto::SESSION_TYPE_DESKTOP_MANAGE ||
        session_type_ == proto::SESSION_TYPE_DESKTOP_VIEW)
    {
        // We close the session process only for desktop manage and desktop view sessions.
        // Processes for other types of sessions are left open so that the user can see the fact
        // of connection to his computer.
        process_.Terminate(0, false);
    }

    process_.Close();

    if (session_type_ == proto::SESSION_TYPE_DESKTOP_MANAGE ||
        session_type_ == proto::SESSION_TYPE_DESKTOP_VIEW)
    {
        // If the new session is not connected within the specified time interval,
        // an error occurred.
        timer_.Start(kAttachTimeout, std::bind(&HostSession::OnSessionAttachTimeout, this));
    }
    else
    {
        // All other types of sessions do not allow reconnection. Closing the session.
        runner_->PostQuit();
    }
}

void HostSession::OnProcessClose()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&HostSession::OnProcessClose, this));
        return;
    }

    switch (state_)
    {
        case State::ATTACHED:
        case State::STARTING:
            OnSessionDetached();
            break;

        case State::DETACHED:
            break;
    }
}

void HostSession::OnIpcChannelConnect(uint32_t user_data)
{
    DCHECK(runner_->BelongsToCurrentThread());

    // To open a host process and terminate it, additional privileges are
    // required. If the current process is running from the service, then the
    // privilege already exists, if not, then enable it.
    ScopedProcessPrivilege privilege(SE_DEBUG_NAME);

    // The client sends a process ID in user_data.
    process_ = Process::Open(user_data);

    bool ok = process_.IsValid();
    if (!ok)
    {
        LOG(ERROR) << "Unable to open session process: " << GetLastSystemErrorString();
    }

    if (ok)
    {
        ok = process_watcher_.StartWatching(process_,
                                            std::bind(&HostSession::OnProcessClose, this));

        if (!ok)
        {
            LOG(ERROR) << "Process watcher not started";
            process_.Close();
        }
    }

    timer_.Stop();

    if (!ok)
    {
        state_ = State::DETACHED;
        runner_->PostQuit();
        return;
    }

    state_ = State::ATTACHED;
}

void HostSession::OnIpcChannelDisconnect()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&HostSession::OnIpcChannelDisconnect, this));
        return;
    }

    switch (state_)
    {
        case State::DETACHED:
            break;

        case State::ATTACHED:
            OnSessionDetached();
            break;

        case State::STARTING:
        {
            DCHECK(!process_.IsValid());

            state_ = State::DETACHED;

            timer_.Stop();
            runner_->PostQuit();
        }
        break;
    }
}

void HostSession::OnSessionAttachTimeout()
{
    if (!runner_->BelongsToCurrentThread())
    {
        runner_->PostTask(std::bind(&HostSession::OnSessionAttachTimeout, this));
        return;
    }

    switch (state_)
    {
        case State::DETACHED:
        case State::STARTING:
            runner_->PostQuit();
            break;

        case State::ATTACHED:
            LOG(FATAL) << "In the attached state, the timer must me stopped";
            break;
    }
}

} // namespace aspia
<|endoftext|>


<commit_before><commit_msg>Planning: bug fix with st-bounds decision.<commit_after><|endoftext|>


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

#include "HTMLDiagnostics.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Rewrite/Rewriter.h"
#include "clang/Rewrite/HTMLRewrite.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Streams.h"
#include "llvm/System/Path.h"
#include <fstream>
#include <sstream>

using namespace clang;

//===----------------------------------------------------------------------===//
// Boilerplate.
//===----------------------------------------------------------------------===//

namespace {

class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
  llvm::sys::Path Directory, FilePrefix;
  bool createdDir, noDir;
  Preprocessor* PP;
  PreprocessorFactory* PPF;
  std::vector<const PathDiagnostic*> BatchedDiags;
public:
  HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
                  PreprocessorFactory* ppf);

  virtual ~HTMLDiagnostics();

  virtual void HandlePathDiagnostic(const PathDiagnostic* D);

  void HandlePiece(Rewriter& R, const PathDiagnosticPiece& P,
                   unsigned num, unsigned max);

  void HighlightRange(Rewriter& R, SourceRange Range);

  void ReportDiag(const PathDiagnostic& D);
};

} // end anonymous namespace

HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
                                 PreprocessorFactory* ppf)
  : Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
    PP(pp), PPF(ppf) {

  // All html files begin with "report"
  FilePrefix.appendComponent("report");
}

PathDiagnosticClient*
clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
                                  PreprocessorFactory* PPF) {

  return new HTMLDiagnostics(prefix, PP, PPF);
}

//===----------------------------------------------------------------------===//
// Report processing.
//===----------------------------------------------------------------------===//

void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
  if (!D)
    return;

  if (D->empty()) {
    delete D;
    return;
  }

  BatchedDiags.push_back(D);
}

HTMLDiagnostics::~HTMLDiagnostics() {

  while (!BatchedDiags.empty()) {
    const PathDiagnostic* D = BatchedDiags.back();
    BatchedDiags.pop_back();
    ReportDiag(*D);
    delete D;
  }
}

void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {

  // Create the HTML directory if it is missing.

  if (!createdDir) {
    createdDir = true;
    std::string ErrorMsg;
    Directory.createDirectoryOnDisk(true, &ErrorMsg);

    if (!Directory.isDirectory()) {
      llvm::cerr << "warning: could not create directory '"
                 << Directory.toString() << "'\n"
                 << "reason: " << ErrorMsg << '\n';

      noDir = true;

      return;
    }
  }

  if (noDir)
    return;

  // Create a new rewriter to generate HTML.
  SourceManager& SMgr = D.begin()->getLocation().getManager();
  Rewriter R(SMgr);

  // Process the path.

  unsigned n = D.size();
  unsigned max = n;

  for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend();
        I!=E; ++I, --n) {

    HandlePiece(R, *I, n, max);
  }

  // Add line numbers, header, footer, etc.

  unsigned FileID = R.getSourceMgr().getMainFileID();
  html::EscapeText(R, FileID);
  html::AddLineNumbers(R, FileID);

  // If we have a preprocessor, relex the file and syntax highlight.
  // We might not have a preprocessor if we come from a deserialized AST file,
  // for example.

  if (PP) html::SyntaxHighlight(R, FileID, *PP);

  // FIXME: We eventually want to use PPF to create a fresh Preprocessor,
  //  once we have worked out the bugs.
  //
  // if (PPF) html::HighlightMacros(R, FileID, *PPF);
  //
  if (PP) html::HighlightMacros(R, FileID, *PP);

  // Get the full directory name of the analyzed file.

  const FileEntry* Entry = SMgr.getFileEntryForID(FileID);

  // This is a cludge; basically we want to append either the full
  // working directory if we have no directory information.  This is
  // a work in progress.

  std::string DirName = "";

  if (!llvm::sys::Path(Entry->getName()).isAbsolute()) {
    llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
    DirName = P.toString() + "/";
  }

  // Add the name of the file as an
 tag.

  {
    std::ostringstream os;

    os << "
Bug Summary
\n
\n"
          "
File:	"
       << html::EscapeText(DirName)
       <getName())
       << "
\n
Location:	"
          "line "
       << (*D.rbegin()).getLocation().getLogicalLineNumber()
       << ", column "
       << (*D.rbegin()).getLocation().getLogicalColumnNumber()
       << "
\n"
          "
Description:	"
       << D.getDescription() << "
\n";

    // Output any other meta data.

    for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end();
         I!=E; ++I) {
      os << "
	" << html::EscapeText(*I) << "
\n";
    }

    os << "
\n
Annotated Source Code
\n";

    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  // Embed meta-data tags.

  const std::string& BugDesc = D.getDescription();

  if (!BugDesc.empty()) {
    std::ostringstream os;
    os << "\n\n";
    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  {
    std::ostringstream os;
    os << "\n\n";
    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  {
    std::ostringstream os;
    os << "\n\n";
    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  {
    std::ostringstream os;
    os << "\n\n";
    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  // Add CSS, header, and footer.

  html::AddHeaderFooterInternalBuiltinCSS(R, FileID);

  // Get the rewrite buffer.
  const RewriteBuffer *Buf = R.getRewriteBufferFor(FileID);

  if (!Buf) {
    llvm::cerr << "warning: no diagnostics generated for main file.\n";
    return;
  }

  // Create the stream to write out the HTML.
  std::ofstream os;

  {
    // Create a path for the target HTML file.
    llvm::sys::Path F(FilePrefix);
    F.makeUnique(false, NULL);

    // Rename the file with an HTML extension.
    llvm::sys::Path H(F);
    H.appendSuffix("html");
    F.renamePathOnDisk(H, NULL);

    os.open(H.toString().c_str());

    if (!os) {
      llvm::cerr << "warning: could not create file '" << F.toString() << "'\n";
      return;
    }
  }

  // Emit the HTML to disk.

  for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
      os << *I;
}

void HTMLDiagnostics::HandlePiece(Rewriter& R,
                                  const PathDiagnosticPiece& P,
                                  unsigned num, unsigned max) {

  // For now, just draw a box above the line in question, and emit the
  // warning.

  FullSourceLoc Pos = P.getLocation();

  if (!Pos.isValid())
    return;

  SourceManager& SM = R.getSourceMgr();
  FullSourceLoc LPos = Pos.getLogicalLoc();
  unsigned FileID = SM.getCanonicalFileID(LPos.getLocation());

  assert (&LPos.getManager() == &SM && "SourceManagers are different!");

  if (!SM.isFromMainFile(LPos.getLocation()))
    return;

  // Compute the column number.  Rewind from the current position to the start
  // of the line.

  unsigned ColNo = LPos.getColumnNumber();
  const char *TokLogicalPtr = LPos.getCharacterData();
  const char *LineStart = TokLogicalPtr-ColNo;

  // Compute the margin offset by counting tabs and non-tabs.

  unsigned PosNo = 0;

  for (const char* c = LineStart; c != TokLogicalPtr; ++c)
    PosNo += *c == '\t' ? 4 : 1;

  // Create the html for the message.

  std::ostringstream os;

  os << "\n
	"
     << "<div id=\"";

  if (num == max)
    os << "EndPath";
  else
    os << "Path" << num;

  os << "\" class=\"msg\" style=\"margin-left:"
     << PosNo << "ex\">";

  if (max > 1)
    os << "[" << num << "] ";

  os << html::EscapeText(P.getString()) << "

";

  // Insert the new html.

  const llvm::MemoryBuffer *Buf = SM.getBuffer(FileID);
  const char* FileStart = Buf->getBufferStart();

  R.InsertStrBefore(SourceLocation::getFileLoc(FileID, LineStart - FileStart),
                    os.str());

  // Now highlight the ranges.

  for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end();
        I != E; ++I)
    HighlightRange(R, *I);
}

void HTMLDiagnostics::HighlightRange(Rewriter& R, SourceRange Range) {

  SourceManager& SM = R.getSourceMgr();

  SourceLocation LogicalStart = SM.getLogicalLoc(Range.getBegin());
  unsigned StartLineNo = SM.getLineNumber(LogicalStart);

  SourceLocation LogicalEnd = SM.getLogicalLoc(Range.getEnd());
  unsigned EndLineNo = SM.getLineNumber(LogicalEnd);

  if (EndLineNo < StartLineNo)
    return;

  if (!SM.isFromMainFile(LogicalStart) ||
      !SM.isFromMainFile(LogicalEnd))
    return;

  // Compute the column number of the end.
  unsigned EndColNo = SM.getColumnNumber(LogicalEnd);
  unsigned OldEndColNo = EndColNo;

  if (EndColNo) {
    // Add in the length of the token, so that we cover multi-char tokens.
    EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM) - 1;
  }

  // Highlight the range.  Make the span tag the outermost tag for the
  // selected range.

  SourceLocation E = LogicalEnd.getFileLocWithOffset(EndColNo - OldEndColNo);

  html::HighlightRange(R, LogicalStart, E,
                       "", "");
}
<commit_msg>Improve HTMLDiagnostics by understanding the "Below" hint.<commit_after>//===--- HTMLDiagnostics.cpp - HTML Diagnostics for Paths ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the HTMLDiagnostics object.
//
//===----------------------------------------------------------------------===//

#include "HTMLDiagnostics.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Rewrite/Rewriter.h"
#include "clang/Rewrite/HTMLRewrite.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Streams.h"
#include "llvm/System/Path.h"
#include <fstream>
#include <sstream>

using namespace clang;

//===----------------------------------------------------------------------===//
// Boilerplate.
//===----------------------------------------------------------------------===//

namespace {

class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
  llvm::sys::Path Directory, FilePrefix;
  bool createdDir, noDir;
  Preprocessor* PP;
  PreprocessorFactory* PPF;
  std::vector<const PathDiagnostic*> BatchedDiags;
public:
  HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
                  PreprocessorFactory* ppf);

  virtual ~HTMLDiagnostics();

  virtual void HandlePathDiagnostic(const PathDiagnostic* D);

  void HandlePiece(Rewriter& R, const PathDiagnosticPiece& P,
                   unsigned num, unsigned max);

  void HighlightRange(Rewriter& R, SourceRange Range);

  void ReportDiag(const PathDiagnostic& D);
};

} // end anonymous namespace

HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
                                 PreprocessorFactory* ppf)
  : Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
    PP(pp), PPF(ppf) {

  // All html files begin with "report"
  FilePrefix.appendComponent("report");
}

PathDiagnosticClient*
clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
                                  PreprocessorFactory* PPF) {

  return new HTMLDiagnostics(prefix, PP, PPF);
}

//===----------------------------------------------------------------------===//
// Report processing.
//===----------------------------------------------------------------------===//

void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
  if (!D)
    return;

  if (D->empty()) {
    delete D;
    return;
  }

  BatchedDiags.push_back(D);
}

HTMLDiagnostics::~HTMLDiagnostics() {

  while (!BatchedDiags.empty()) {
    const PathDiagnostic* D = BatchedDiags.back();
    BatchedDiags.pop_back();
    ReportDiag(*D);
    delete D;
  }
}

void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {

  // Create the HTML directory if it is missing.

  if (!createdDir) {
    createdDir = true;
    std::string ErrorMsg;
    Directory.createDirectoryOnDisk(true, &ErrorMsg);

    if (!Directory.isDirectory()) {
      llvm::cerr << "warning: could not create directory '"
                 << Directory.toString() << "'\n"
                 << "reason: " << ErrorMsg << '\n';

      noDir = true;

      return;
    }
  }

  if (noDir)
    return;

  // Create a new rewriter to generate HTML.
  SourceManager& SMgr = D.begin()->getLocation().getManager();
  Rewriter R(SMgr);

  // Process the path.

  unsigned n = D.size();
  unsigned max = n;

  for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend();
        I!=E; ++I, --n) {

    HandlePiece(R, *I, n, max);
  }

  // Add line numbers, header, footer, etc.

  unsigned FileID = R.getSourceMgr().getMainFileID();
  html::EscapeText(R, FileID);
  html::AddLineNumbers(R, FileID);

  // If we have a preprocessor, relex the file and syntax highlight.
  // We might not have a preprocessor if we come from a deserialized AST file,
  // for example.

  if (PP) html::SyntaxHighlight(R, FileID, *PP);

  // FIXME: We eventually want to use PPF to create a fresh Preprocessor,
  //  once we have worked out the bugs.
  //
  // if (PPF) html::HighlightMacros(R, FileID, *PPF);
  //
  if (PP) html::HighlightMacros(R, FileID, *PP);

  // Get the full directory name of the analyzed file.

  const FileEntry* Entry = SMgr.getFileEntryForID(FileID);

  // This is a cludge; basically we want to append either the full
  // working directory if we have no directory information.  This is
  // a work in progress.

  std::string DirName = "";

  if (!llvm::sys::Path(Entry->getName()).isAbsolute()) {
    llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
    DirName = P.toString() + "/";
  }

  // Add the name of the file as an
 tag.

  {
    std::ostringstream os;

    os << "
Bug Summary
\n
\n"
          "
File:	"
       << html::EscapeText(DirName)
       <getName())
       << "
\n
Location:	"
          "line "
       << (*D.rbegin()).getLocation().getLogicalLineNumber()
       << ", column "
       << (*D.rbegin()).getLocation().getLogicalColumnNumber()
       << "
\n"
          "
Description:	"
       << D.getDescription() << "
\n";

    // Output any other meta data.

    for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end();
         I!=E; ++I) {
      os << "
	" << html::EscapeText(*I) << "
\n";
    }

    os << "
\n
Annotated Source Code
\n";

    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  // Embed meta-data tags.

  const std::string& BugDesc = D.getDescription();

  if (!BugDesc.empty()) {
    std::ostringstream os;
    os << "\n\n";
    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  {
    std::ostringstream os;
    os << "\n\n";
    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  {
    std::ostringstream os;
    os << "\n\n";
    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  {
    std::ostringstream os;
    os << "\n\n";
    R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
  }

  // Add CSS, header, and footer.

  html::AddHeaderFooterInternalBuiltinCSS(R, FileID);

  // Get the rewrite buffer.
  const RewriteBuffer *Buf = R.getRewriteBufferFor(FileID);

  if (!Buf) {
    llvm::cerr << "warning: no diagnostics generated for main file.\n";
    return;
  }

  // Create the stream to write out the HTML.
  std::ofstream os;

  {
    // Create a path for the target HTML file.
    llvm::sys::Path F(FilePrefix);
    F.makeUnique(false, NULL);

    // Rename the file with an HTML extension.
    llvm::sys::Path H(F);
    H.appendSuffix("html");
    F.renamePathOnDisk(H, NULL);

    os.open(H.toString().c_str());

    if (!os) {
      llvm::cerr << "warning: could not create file '" << F.toString() << "'\n";
      return;
    }
  }

  // Emit the HTML to disk.

  for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
      os << *I;
}

void HTMLDiagnostics::HandlePiece(Rewriter& R,
                                  const PathDiagnosticPiece& P,
                                  unsigned num, unsigned max) {

  // For now, just draw a box above the line in question, and emit the
  // warning.

  FullSourceLoc Pos = P.getLocation();

  if (!Pos.isValid())
    return;

  SourceManager& SM = R.getSourceMgr();
  FullSourceLoc LPos = Pos.getLogicalLoc();
  unsigned FileID = SM.getCanonicalFileID(LPos.getLocation());

  assert (&LPos.getManager() == &SM && "SourceManagers are different!");

  if (!SM.isFromMainFile(LPos.getLocation()))
    return;

  const llvm::MemoryBuffer *Buf = SM.getBuffer(FileID);
  const char* FileStart = Buf->getBufferStart();

  // Compute the column number.  Rewind from the current position to the start
  // of the line.

  unsigned ColNo = LPos.getColumnNumber();
  const char *TokLogicalPtr = LPos.getCharacterData();
  const char *LineStart = TokLogicalPtr-ColNo;

  // Only compute LineEnd if we display below a line.
  const char *LineEnd = TokLogicalPtr;

  if (P.getDisplayHint() == PathDiagnosticPiece::Below) {
    const char* FileEnd = Buf->getBufferEnd();

    while (*LineEnd != '\n' && LineEnd != FileEnd)
      ++LineEnd;
  }

  // Compute the margin offset by counting tabs and non-tabs.

  unsigned PosNo = 0;

  for (const char* c = LineStart; c != TokLogicalPtr; ++c)
    PosNo += *c == '\t' ? 8 : 1;

  // Create the html for the message.

  std::ostringstream os;

  os << "\n
	"
     << "<div id=\"";

  if (num == max)
    os << "EndPath";
  else
    os << "Path" << num;

  os << "\" class=\"msg\" style=\"margin-left:"
     << PosNo << "ex\">";

  if (max > 1)
    os << "[" << num << "] ";

  os << html::EscapeText(P.getString()) << "

";

  // Insert the new html.

  unsigned DisplayPos = 0;

  switch (P.getDisplayHint()) {
    case PathDiagnosticPiece::Above:
      DisplayPos = LineStart - FileStart;
      break;
    case PathDiagnosticPiece::Below:
      DisplayPos = LineEnd - FileStart;
      break;
    default:
      assert (false && "Unhandled hint.");
  }

  R.InsertStrBefore(SourceLocation::getFileLoc(FileID, DisplayPos), os.str());

  // Now highlight the ranges.

  for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end();
        I != E; ++I)
    HighlightRange(R, *I);
}

void HTMLDiagnostics::HighlightRange(Rewriter& R, SourceRange Range) {

  SourceManager& SM = R.getSourceMgr();

  SourceLocation LogicalStart = SM.getLogicalLoc(Range.getBegin());
  unsigned StartLineNo = SM.getLineNumber(LogicalStart);

  SourceLocation LogicalEnd = SM.getLogicalLoc(Range.getEnd());
  unsigned EndLineNo = SM.getLineNumber(LogicalEnd);

  if (EndLineNo < StartLineNo)
    return;

  if (!SM.isFromMainFile(LogicalStart) ||
      !SM.isFromMainFile(LogicalEnd))
    return;

  // Compute the column number of the end.
  unsigned EndColNo = SM.getColumnNumber(LogicalEnd);
  unsigned OldEndColNo = EndColNo;

  if (EndColNo) {
    // Add in the length of the token, so that we cover multi-char tokens.
    EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM) - 1;
  }

  // Highlight the range.  Make the span tag the outermost tag for the
  // selected range.

  SourceLocation E = LogicalEnd.getFileLocWithOffset(EndColNo - OldEndColNo);

  html::HighlightRange(R, LogicalStart, E,
                       "", "");
}
<|endoftext|>


<commit_before>#include <opengl/draw_info.hpp>
#include <iostream>

using namespace boomhs;
namespace opengl
{

////////////////////////////////////////////////////////////////////////////////////////////////////
// BufferHandles
BufferHandles::BufferHandles()
{
  glGenBuffers(NUM_BUFFERS, &vbo_);
  glGenBuffers(NUM_BUFFERS, &ebo_);
}

BufferHandles::~BufferHandles()
{
  glDeleteBuffers(NUM_BUFFERS, &ebo_);
  glDeleteBuffers(NUM_BUFFERS, &vbo_);
}

  // move-construction OK.
BufferHandles::BufferHandles(BufferHandles &&other)
    : vbo_(other.vbo_)
    , ebo_(other.ebo_)
{
  other.vbo_ = 0;
  other.ebo_ = 0;
}

BufferHandles&
BufferHandles::operator=(BufferHandles &&other)
{
  vbo_ = MOVE(other.vbo_);
  ebo_ = MOVE(other.ebo_);

  other.vbo_ = 0;
  other.ebo_ = 0;
  return *this;
}

std::ostream&
operator<<(std::ostream &stream, BufferHandles const& buffers)
{
  stream << fmt::format("vbo: {}, ebo: {}", buffers.vbo(), buffers.ebo());;
  return stream;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// DrawInfo
DrawInfo::DrawInfo(GLenum const dm, size_t const num_vertices, GLuint const num_indices,
    std::optional<TextureInfo> const& ti)
  : draw_mode_(dm)
  , num_vertices_(num_vertices)
  , num_indices_(num_indices)
  , texture_info_(ti)
{
}

DrawInfo::DrawInfo(DrawInfo &&other)
  : draw_mode_(other.draw_mode_)
  , num_indices_(other.num_indices_)
  , handles_(MOVE(other.handles_))
  , vao_(MOVE(other.vao_))
  , texture_info_(MOVE(other.texture_info_))
{
}

DrawInfo&
DrawInfo::operator=(DrawInfo &&other)
{
  draw_mode_ = other.draw_mode_;
  num_indices_ = other.num_indices_;
  other.draw_mode_ = -1;
  other.num_indices_ = 0;

  handles_ = MOVE(other.handles_);
  vao_ = MOVE(other.vao_);
  texture_info_ = MOVE(other.texture_info_);
  return *this;
}

void
DrawInfo::print_self(std::ostream &stream, VertexAttribute const& va) const
{
  auto const& dinfo = *this;
  stream << fmt::format("DrawMode: {} NumIndices: {}\n", dinfo.draw_mode(), dinfo.num_indices());
  stream << "VAO:\n" << dinfo.vao_ << "\n";
  stream << "BufferHandles:\n" << dinfo.handles_ << "\n";
  stream << "EBO contents:\n";
  auto const num_indices = dinfo.num_indices();
  {
    auto const target = GL_ELEMENT_ARRAY_BUFFER;
    GLuint const*const pmem = static_cast<GLuint const*const>(glMapBuffer(target, GL_READ_ONLY));
    assert(pmem);
    ON_SCOPE_EXIT([]() { glUnmapBuffer((target)); });

    FOR(i, num_indices) {
      // (void* + GLuint) -> GLuint*
      GLuint const* p_element = pmem + i;
      stream << std::to_string(*p_element) << " ";
    }
    stream << "\n";
  }

  auto const stride = va.stride();
  auto const num_vertices = dinfo.num_vertices();

  auto const target = GL_ARRAY_BUFFER;
  GLfloat *pmem = static_cast<GLfloat *>(glMapBuffer(target, GL_READ_ONLY));
  assert(pmem);
  ON_SCOPE_EXIT([]() { assert(glUnmapBuffer(target)); });

  stream << fmt::format("vbo id: {} VBO contents:\n", dinfo.vbo());
  stream << "VBO stride: '" << stride << "'\n";
  stream << "VBO num_vertices: '" << num_vertices << "'\n";
  stream << "VBO contents:\n";

  auto count{0};
  for(auto i = 0u; i < num_vertices; ++i, ++count) {
    if (count == stride) {
      count = 0;
      stream << "\n";
    } else if (i > 0) {
      stream << " ";
    }
    stream << std::to_string(*(pmem + i));
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EntityDrawinfos
size_t
EntityDrawinfos::add(EntityID const entity, opengl::DrawInfo &&di)
{
  auto const pos = drawinfos_.size();
  drawinfos_.emplace_back(MOVE(di));
  entities_.emplace_back(entity);

  // return the index di was stored in.
  return pos;
}

opengl::DrawInfo const&
EntityDrawinfos::get(EntityID const entity) const
{
  FOR(i, entities_.size()) {
    if (entities_[i] == entity) {
      return drawinfos_[i];
    }
  }
  std::cerr << fmt::format("Error could not find entity drawinfo associated to entity {}'\n", entity);
  std::abort();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EntityDrawHandles
opengl::DrawInfo const&
EntityDrawHandles::lookup(EntityID const eid) const
{
  return infos_.get(eid);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EntityDrawHandles
opengl::DrawInfo const&
TileDrawHandles::lookup(TileType const type) const
{
  assert(type < TileType::UNDEFINED);
  auto const index = static_cast<size_t>(type);
  return drawinfos_[index];
}

} // ns opengl
<commit_msg>Fix move bug in DrawInfo<commit_after>#include <opengl/draw_info.hpp>
#include <iostream>

using namespace boomhs;
namespace opengl
{

////////////////////////////////////////////////////////////////////////////////////////////////////
// BufferHandles
BufferHandles::BufferHandles()
{
  glGenBuffers(NUM_BUFFERS, &vbo_);
  glGenBuffers(NUM_BUFFERS, &ebo_);
}

BufferHandles::~BufferHandles()
{
  glDeleteBuffers(NUM_BUFFERS, &ebo_);
  glDeleteBuffers(NUM_BUFFERS, &vbo_);
}

  // move-construction OK.
BufferHandles::BufferHandles(BufferHandles &&other)
    : vbo_(other.vbo_)
    , ebo_(other.ebo_)
{
  other.vbo_ = 0;
  other.ebo_ = 0;
}

BufferHandles&
BufferHandles::operator=(BufferHandles &&other)
{
  vbo_ = MOVE(other.vbo_);
  ebo_ = MOVE(other.ebo_);

  other.vbo_ = 0;
  other.ebo_ = 0;
  return *this;
}

std::ostream&
operator<<(std::ostream &stream, BufferHandles const& buffers)
{
  stream << fmt::format("vbo: {}, ebo: {}", buffers.vbo(), buffers.ebo());;
  return stream;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// DrawInfo
DrawInfo::DrawInfo(GLenum const dm, size_t const num_vertices, GLuint const num_indices,
    std::optional<TextureInfo> const& ti)
  : draw_mode_(dm)
  , num_vertices_(num_vertices)
  , num_indices_(num_indices)
  , texture_info_(ti)
{
}

DrawInfo::DrawInfo(DrawInfo &&other)
  : draw_mode_(other.draw_mode_)
  , num_vertices_(other.num_vertices_)
  , num_indices_(other.num_indices_)
  , handles_(MOVE(other.handles_))
  , vao_(MOVE(other.vao_))
  , texture_info_(MOVE(other.texture_info_))
{
}

DrawInfo&
DrawInfo::operator=(DrawInfo &&other)
{
  draw_mode_ = other.draw_mode_;
  num_vertices_ = other.num_vertices_;
  num_indices_ = other.num_indices_;
  other.draw_mode_ = -1;
  other.num_vertices_ = 0;
  other.num_indices_ = 0;

  handles_ = MOVE(other.handles_);
  vao_ = MOVE(other.vao_);
  texture_info_ = MOVE(other.texture_info_);
  return *this;
}

void
DrawInfo::print_self(std::ostream &stream, VertexAttribute const& va) const
{
  auto const& dinfo = *this;
  stream << fmt::format("DrawMode: {} NumIndices: {}\n", dinfo.draw_mode(), dinfo.num_indices());
  stream << "VAO:\n" << dinfo.vao_ << "\n";
  stream << "BufferHandles:\n" << dinfo.handles_ << "\n";
  stream << "EBO contents:\n";
  auto const num_indices = dinfo.num_indices();
  {
    auto const target = GL_ELEMENT_ARRAY_BUFFER;
    GLuint const*const pmem = static_cast<GLuint const*const>(glMapBuffer(target, GL_READ_ONLY));
    assert(pmem);
    ON_SCOPE_EXIT([]() { glUnmapBuffer((target)); });

    FOR(i, num_indices) {
      // (void* + GLuint) -> GLuint*
      GLuint const* p_element = pmem + i;
      stream << std::to_string(*p_element) << " ";
    }
    stream << "\n";
  }

  auto const stride = va.stride();
  auto const num_vertices = dinfo.num_vertices();

  auto const target = GL_ARRAY_BUFFER;
  GLfloat *pmem = static_cast<GLfloat *>(glMapBuffer(target, GL_READ_ONLY));
  assert(pmem);
  ON_SCOPE_EXIT([]() { assert(glUnmapBuffer(target)); });

  stream << fmt::format("vbo id: {} VBO contents:\n", dinfo.vbo());
  stream << "VBO stride: '" << stride << "'\n";
  stream << "VBO num_vertices: '" << num_vertices << "'\n";
  stream << "VBO contents:\n";

  auto count{0};
  for(auto i = 0u; i < num_vertices; ++i, ++count) {
    if (count == stride) {
      count = 0;
      stream << "\n";
    } else if (i > 0) {
      stream << " ";
    }
    stream << std::to_string(*(pmem + i));
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EntityDrawinfos
size_t
EntityDrawinfos::add(EntityID const entity, opengl::DrawInfo &&di)
{
  auto const pos = drawinfos_.size();
  drawinfos_.emplace_back(MOVE(di));
  entities_.emplace_back(entity);

  // return the index di was stored in.
  return pos;
}

opengl::DrawInfo const&
EntityDrawinfos::get(EntityID const entity) const
{
  FOR(i, entities_.size()) {
    if (entities_[i] == entity) {
      return drawinfos_[i];
    }
  }
  std::cerr << fmt::format("Error could not find entity drawinfo associated to entity {}'\n", entity);
  std::abort();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EntityDrawHandles
opengl::DrawInfo const&
EntityDrawHandles::lookup(EntityID const eid) const
{
  return infos_.get(eid);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EntityDrawHandles
opengl::DrawInfo const&
TileDrawHandles::lookup(TileType const type) const
{
  assert(type < TileType::UNDEFINED);
  auto const index = static_cast<size_t>(type);
  return drawinfos_[index];
}

} // ns opengl
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "CoarseMeshExtraElementIDGenerator.h"

registerMooseObject("ReactorApp", CoarseMeshExtraElementIDGenerator);

#include "libmesh/enum_point_locator_type.h"
#include "libmesh/elem.h"
#include "libmesh/mesh_serializer.h"

InputParameters
CoarseMeshExtraElementIDGenerator::validParams()
{
  InputParameters params = MeshGenerator::validParams();
  params.addRequiredParam<MeshGeneratorName>(
      "input", "Name of an existing mesh generator to which we assign coarse element IDs");
  params.addRequiredParam<MeshGeneratorName>(
      "coarse_mesh", "Name of an existing mesh generator as the coarse mesh");
  params.addRequiredParam<std::string>(
      "extra_element_id_name", "Name for the extra element ID that is added to the input mesh");
  params.addParam<std::string>(
      "coarse_mesh_extra_element_id",
      "Name for the extra element ID that is copied from the coarse mesh (default to element ID)");
  params.addParam<bool>("enforce_mesh_embedding",
                        false,
                        "True to error out when the input mesh is not embedded in the coarse mesh");

  params.addClassDescription("Assign coarse element IDs for elements on a "
                             "mesh based on a coarse mesh.");
  return params;
}

CoarseMeshExtraElementIDGenerator::CoarseMeshExtraElementIDGenerator(const InputParameters & params)
  : MeshGenerator(params),
    _input(getMesh("input")),
    _coarse_mesh(getMesh("coarse_mesh")),
    _coarse_id_name(getParam<std::string>("extra_element_id_name")),
    _using_coarse_element_id(isParamValid("coarse_mesh_extra_element_id")),
    _embedding_necessary(getParam<bool>("enforce_mesh_embedding"))
{
}

std::unique_ptr<MeshBase>
CoarseMeshExtraElementIDGenerator::generate()
{
  std::unique_ptr<MeshBase> mesh = std::move(_input);

  unsigned int coarse_id;
  if (!mesh->has_elem_integer(_coarse_id_name))
    coarse_id = mesh->add_elem_integer(_coarse_id_name);
  else
    coarse_id = mesh->get_elem_integer_index(_coarse_id_name);

  std::unique_ptr<MeshBase> coarse_mesh = std::move(_coarse_mesh);

  bool using_subdomain_id = false;
  unsigned int id_for_assignment = 0;
  if (_using_coarse_element_id)
  {
    const auto & id_name = getParam<std::string>("coarse_mesh_extra_element_id");
    if (id_name == "subdomain_id")
      using_subdomain_id = true;
    else
    {
      using_subdomain_id = false;
      if (!coarse_mesh->has_elem_integer(id_name))
        paramError("coarse_mesh_extra_element_id",
                   "The extra element ID does not exist on the coarse mesh");
      else
        id_for_assignment = coarse_mesh->get_elem_integer_index(id_name);
    }
  }

  // a relative tolerance on checking if fine mesh is embedded in the coarse mesh
  Real aeps = 0.01;

  // The coarse mesh is serialized for distributed mesh to avoid boundary issues.
  // As it is coarse this should be cheap. This will be a null operation for a replicated mesh.
  MeshSerializer tm(*coarse_mesh);

  // build a point_locator on coarse mesh
  UniquePtr<PointLocatorBase> point_locator = PointLocatorBase::build(TREE_ELEMENTS, *coarse_mesh);
  point_locator->enable_out_of_mesh_mode();

  // loop through fine mesh elements and get element's centroid
  for (auto & elem : mesh->active_element_ptr_range())
  {
    // Get the centroid of the fine elem
    Point centroid = elem->true_centroid();

    // Find coarse elem
    const Elem * coarse_elem = (*point_locator)(centroid);
    if (!coarse_elem)
      mooseError("Could not find a coarse element containing a fine element with centroid ",
                 centroid);

    // get id from the coarse element
    dof_id_type elem_id;
    if (_using_coarse_element_id)
    {
      if (using_subdomain_id)
        elem_id = coarse_elem->subdomain_id();
      else
        elem_id = coarse_elem->get_extra_integer(id_for_assignment);
    }
    else
      elem_id = coarse_elem->id();

    // Check if the fine elem is nested in the coarse element
    for (unsigned int n = 0; n < elem->n_nodes(); n++)
    {
      // Get the node: we need to manually move it towards the centroid to
      // ensure that nothing weird happes due to round-off
      Node current_node = elem->node_ref(n);
      current_node.add_scaled(current_node, -aeps);
      current_node.add_scaled(centroid, aeps);

      // Get the element this node is in and check if it is the same
      // as the coarse elem; however check if node_elem is valid as it
      // might not be in case the sub element it outside the coarse domain
      const Elem * node_elem = (*point_locator)(current_node);
      if (!node_elem)
        mooseError("Could not find a coarse element containing a node of fine element at ",
                   elem->point(n));

      // get another id from the coarse element with this node
      dof_id_type node_elem_id;
      if (_using_coarse_element_id)
      {
        if (using_subdomain_id)
          node_elem_id = node_elem->subdomain_id();
        else
          node_elem_id = node_elem->get_extra_integer(id_for_assignment);
      }
      else
        node_elem_id = node_elem->id();

      if (node_elem_id != elem_id)
        if (_embedding_necessary)
          mooseError(
              "Input mesh is not nested in the coarse mesh in CoarseMeshExtraElementIDGenerator.");
    }

    elem->set_extra_integer(coarse_id, elem_id);
  }

  return mesh;
}
<commit_msg>Replace deprecated UniquePtr shim<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "CoarseMeshExtraElementIDGenerator.h"

registerMooseObject("ReactorApp", CoarseMeshExtraElementIDGenerator);

#include "libmesh/enum_point_locator_type.h"
#include "libmesh/elem.h"
#include "libmesh/mesh_serializer.h"

InputParameters
CoarseMeshExtraElementIDGenerator::validParams()
{
  InputParameters params = MeshGenerator::validParams();
  params.addRequiredParam<MeshGeneratorName>(
      "input", "Name of an existing mesh generator to which we assign coarse element IDs");
  params.addRequiredParam<MeshGeneratorName>(
      "coarse_mesh", "Name of an existing mesh generator as the coarse mesh");
  params.addRequiredParam<std::string>(
      "extra_element_id_name", "Name for the extra element ID that is added to the input mesh");
  params.addParam<std::string>(
      "coarse_mesh_extra_element_id",
      "Name for the extra element ID that is copied from the coarse mesh (default to element ID)");
  params.addParam<bool>("enforce_mesh_embedding",
                        false,
                        "True to error out when the input mesh is not embedded in the coarse mesh");

  params.addClassDescription("Assign coarse element IDs for elements on a "
                             "mesh based on a coarse mesh.");
  return params;
}

CoarseMeshExtraElementIDGenerator::CoarseMeshExtraElementIDGenerator(const InputParameters & params)
  : MeshGenerator(params),
    _input(getMesh("input")),
    _coarse_mesh(getMesh("coarse_mesh")),
    _coarse_id_name(getParam<std::string>("extra_element_id_name")),
    _using_coarse_element_id(isParamValid("coarse_mesh_extra_element_id")),
    _embedding_necessary(getParam<bool>("enforce_mesh_embedding"))
{
}

std::unique_ptr<MeshBase>
CoarseMeshExtraElementIDGenerator::generate()
{
  std::unique_ptr<MeshBase> mesh = std::move(_input);

  unsigned int coarse_id;
  if (!mesh->has_elem_integer(_coarse_id_name))
    coarse_id = mesh->add_elem_integer(_coarse_id_name);
  else
    coarse_id = mesh->get_elem_integer_index(_coarse_id_name);

  std::unique_ptr<MeshBase> coarse_mesh = std::move(_coarse_mesh);

  bool using_subdomain_id = false;
  unsigned int id_for_assignment = 0;
  if (_using_coarse_element_id)
  {
    const auto & id_name = getParam<std::string>("coarse_mesh_extra_element_id");
    if (id_name == "subdomain_id")
      using_subdomain_id = true;
    else
    {
      using_subdomain_id = false;
      if (!coarse_mesh->has_elem_integer(id_name))
        paramError("coarse_mesh_extra_element_id",
                   "The extra element ID does not exist on the coarse mesh");
      else
        id_for_assignment = coarse_mesh->get_elem_integer_index(id_name);
    }
  }

  // a relative tolerance on checking if fine mesh is embedded in the coarse mesh
  Real aeps = 0.01;

  // The coarse mesh is serialized for distributed mesh to avoid boundary issues.
  // As it is coarse this should be cheap. This will be a null operation for a replicated mesh.
  MeshSerializer tm(*coarse_mesh);

  // build a point_locator on coarse mesh
  std::unique_ptr<PointLocatorBase> point_locator = PointLocatorBase::build(TREE_ELEMENTS, *coarse_mesh);
  point_locator->enable_out_of_mesh_mode();

  // loop through fine mesh elements and get element's centroid
  for (auto & elem : mesh->active_element_ptr_range())
  {
    // Get the centroid of the fine elem
    Point centroid = elem->true_centroid();

    // Find coarse elem
    const Elem * coarse_elem = (*point_locator)(centroid);
    if (!coarse_elem)
      mooseError("Could not find a coarse element containing a fine element with centroid ",
                 centroid);

    // get id from the coarse element
    dof_id_type elem_id;
    if (_using_coarse_element_id)
    {
      if (using_subdomain_id)
        elem_id = coarse_elem->subdomain_id();
      else
        elem_id = coarse_elem->get_extra_integer(id_for_assignment);
    }
    else
      elem_id = coarse_elem->id();

    // Check if the fine elem is nested in the coarse element
    for (unsigned int n = 0; n < elem->n_nodes(); n++)
    {
      // Get the node: we need to manually move it towards the centroid to
      // ensure that nothing weird happes due to round-off
      Node current_node = elem->node_ref(n);
      current_node.add_scaled(current_node, -aeps);
      current_node.add_scaled(centroid, aeps);

      // Get the element this node is in and check if it is the same
      // as the coarse elem; however check if node_elem is valid as it
      // might not be in case the sub element it outside the coarse domain
      const Elem * node_elem = (*point_locator)(current_node);
      if (!node_elem)
        mooseError("Could not find a coarse element containing a node of fine element at ",
                   elem->point(n));

      // get another id from the coarse element with this node
      dof_id_type node_elem_id;
      if (_using_coarse_element_id)
      {
        if (using_subdomain_id)
          node_elem_id = node_elem->subdomain_id();
        else
          node_elem_id = node_elem->get_extra_integer(id_for_assignment);
      }
      else
        node_elem_id = node_elem->id();

      if (node_elem_id != elem_id)
        if (_embedding_necessary)
          mooseError(
              "Input mesh is not nested in the coarse mesh in CoarseMeshExtraElementIDGenerator.");
    }

    elem->set_extra_integer(coarse_id, elem_id);
  }

  return mesh;
}
<|endoftext|>