<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      app/rdo_console/controller_console_options.cpp
  \author    Пройдаков Евгений (lord.tiran@gmail.com)
  \date      26.10.2011
  \brief     Консольная версия RDO
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
#include <boost/format.hpp>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/src/common/rdomacros.h"
#include "utils/src/locale/rdolocale.h"
#include "app/rdo_console/terminate_codes.h"
#include "app/rdo_console/controller_console_options.h"
#include "app/rdo_console/controller_console_options_config.h"
// --------------------------------------------------------------------------------

using namespace rdo;

ControllerConsoleOptions::ControllerConsoleOptions(int argc, char *argv[]) :
	m_help(false),
	m_convert(false)
{
	po::options_description options_header(boost::str(boost::format("%1%\n\n%2%")
		% rdo::version::g_versionName
		% rdo::version::g_site
	));

	po::options_description options_general("General options");
	createGeneralOptions(options_general);

	po::options_description options_convertor("Convertor options");
	createConvertorOptions(options_convertor);

	po::options_description options_additional("Compatibility options (skipped in console version)");
	createAdditionalOptions(options_additional);

	m_options.add(options_header);
	m_options.add(options_general);
	m_options.add(options_convertor);
	m_options.add(options_additional);

	try
	{
		po::store(po::parse_command_line(argc, argv, m_options), m_variables);
		po::notify(m_variables);
	}
	catch (CREF(std::exception) e)
	{
		std::wcout << rdo::locale::convertToWStr(boost::str(
			boost::format("command line error: %1%") % e.what())) << std::endl;
	}
}

ControllerConsoleOptions::~ControllerConsoleOptions()
{
}

void ControllerConsoleOptions::parseOptions()
{
	if ((m_variables.empty() || m_variables.count(HELP_COMMAND)) &&
		    !m_variables.count(LANGUAGE_COMMAND) &&
		    !m_variables.count(VERSION_COMMAND))
	{
		std::stringstream stream;
		stream << m_options;
		std::wcout << rdo::locale::convertToWStr(stream.str()) << std::endl;
		m_help = true;
	}
	else if (m_variables.count(LANGUAGE_COMMAND))
	{
		std::wcout << rdo::locale::convertToWStr("rdo language v" + RDO_LANGUAGE_VERSION + " ( supported rdox )") << std::endl;
		m_help = true;
	}
	else if (m_variables.count(VERSION_COMMAND))
	{
		std::wcout << rdo::locale::convertToWStr(rdo::version::g_versionName) << std::endl;
		m_help = true;
	}
	else if(m_variables.count(CONVERTOR_COMMAND))
	{
		m_convert = true;
	}
}

boost::filesystem::path ControllerConsoleOptions::getModelFileName() const
{
	boost::filesystem::path result;
	if (m_variables.count(MODEL_COMMAND))
	{
		tstring modelFileName = m_variables[MODEL_COMMAND].as<tstring>();
#if defined(OST_WINDOWS)
		modelFileName = rdo::locale::convertFromCLocale(modelFileName);
#elif defined(OST_LINUX)
		modelFileName = rdo::locale::convert(modelFileName, rdo::locale::get().utf8(), rdo::locale::get().system());
#endif
		result = rdo::locale::convertToWStr(modelFileName);
	}
	return result;
}

boost::filesystem::path ControllerConsoleOptions::getScriptFileName() const
{
	boost::filesystem::path result;
	if (m_variables.count(SCRIPT_COMMAND))
	{
		tstring eventsFileName = m_variables[SCRIPT_COMMAND].as<tstring>();
#if defined(OST_WINDOWS)
		eventsFileName = rdo::locale::convertFromCLocale(eventsFileName);
#elif defined(OST_LINUX)
		eventsFileName = rdo::locale::convert(eventsFileName, rdo::locale::get().utf8(), rdo::locale::get().system());
#endif
		result = rdo::locale::convertToWStr(eventsFileName);
	}
	return result;
}

rbool ControllerConsoleOptions::helpQuery()
{
	return m_help;
}

rbool ControllerConsoleOptions::convertQuery()
{
	return m_convert;
}

void ControllerConsoleOptions::createGeneralOptions(REF(po::options_description) options)
{
	options.add_options()
			((MODEL_COMMAND + COMMA_STRING + MODEL_COMMAND_SHORT).c_str(), po::value<tstring>(), MODEL_COMMENT.c_str())
			((SCRIPT_COMMAND + COMMA_STRING + SCRIPT_COMMAND_SHORT).c_str(), po::value<tstring>(), SCRIPT_COMMENT.c_str())
			((LANGUAGE_COMMAND + COMMA_STRING + LANGUAGE_COMMAND_SHORT).c_str(), LANGUAGE_COMMENT.c_str())
			((VERSION_COMMAND + COMMA_STRING + VERSION_COMMAND_SHORT).c_str(), VERSION_COMMENT.c_str())
			((HELP_COMMAND + COMMA_STRING + HELP_COMMAND_SHORT).c_str(), HELP_COMMENT.c_str());
}

void ControllerConsoleOptions::createConvertorOptions(REF(po::options_description) options)
{
	options.add_options()
		((CONVERTOR_COMMAND + COMMA_STRING + CONVERTOR_COMMAND_SHORT).c_str(), CONVERTOR_COMMENT.c_str());
}

void ControllerConsoleOptions::createAdditionalOptions(REF(po::options_description) options)
{
	options.add_options()
			(AUTO_RUN_COMMAND.c_str(), AUTO_RUN_COMMENT.c_str())
			(AUTO_EXIT_COMMAND.c_str(), AUTO_EXIT_COMMENT.c_str())
			(DONT_CLOSE_IF_ERROR_COMMAND.c_str(), DONT_CLOSE_IF_ERROR_COMMENT.c_str())
			(PLUGIN_START_COMMAND.c_str(), PLUGIN_START_COMMENT.c_str())
			(PLUGIN_AUTO_EXIT_COMMAND.c_str(), PLUGIN_AUTO_EXIT_COMMENT.c_str());
}
<commit_msg> - удалены неиспользуемые инклюды<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      app/rdo_console/controller_console_options.cpp
  \author    Пройдаков Евгений (lord.tiran@gmail.com)
  \date      26.10.2011
  \brief     Консольная версия RDO
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
#include <boost/format.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/src/common/rdomacros.h"
#include "utils/src/locale/rdolocale.h"
#include "app/rdo_console/terminate_codes.h"
#include "app/rdo_console/controller_console_options.h"
#include "app/rdo_console/controller_console_options_config.h"
// --------------------------------------------------------------------------------

using namespace rdo;

ControllerConsoleOptions::ControllerConsoleOptions(int argc, char *argv[]) :
	m_help(false),
	m_convert(false)
{
	po::options_description options_header(boost::str(boost::format("%1%\n\n%2%")
		% rdo::version::g_versionName
		% rdo::version::g_site
	));

	po::options_description options_general("General options");
	createGeneralOptions(options_general);

	po::options_description options_convertor("Convertor options");
	createConvertorOptions(options_convertor);

	po::options_description options_additional("Compatibility options (skipped in console version)");
	createAdditionalOptions(options_additional);

	m_options.add(options_header);
	m_options.add(options_general);
	m_options.add(options_convertor);
	m_options.add(options_additional);

	try
	{
		po::store(po::parse_command_line(argc, argv, m_options), m_variables);
		po::notify(m_variables);
	}
	catch (CREF(std::exception) e)
	{
		std::wcout << rdo::locale::convertToWStr(boost::str(
			boost::format("command line error: %1%") % e.what())) << std::endl;
	}
}

ControllerConsoleOptions::~ControllerConsoleOptions()
{
}

void ControllerConsoleOptions::parseOptions()
{
	if ((m_variables.empty() || m_variables.count(HELP_COMMAND)) &&
		    !m_variables.count(LANGUAGE_COMMAND) &&
		    !m_variables.count(VERSION_COMMAND))
	{
		std::stringstream stream;
		stream << m_options;
		std::wcout << rdo::locale::convertToWStr(stream.str()) << std::endl;
		m_help = true;
	}
	else if (m_variables.count(LANGUAGE_COMMAND))
	{
		std::wcout << rdo::locale::convertToWStr("rdo language v" + RDO_LANGUAGE_VERSION + " ( supported rdox )") << std::endl;
		m_help = true;
	}
	else if (m_variables.count(VERSION_COMMAND))
	{
		std::wcout << rdo::locale::convertToWStr(rdo::version::g_versionName) << std::endl;
		m_help = true;
	}
	else if(m_variables.count(CONVERTOR_COMMAND))
	{
		m_convert = true;
	}
}

boost::filesystem::path ControllerConsoleOptions::getModelFileName() const
{
	boost::filesystem::path result;
	if (m_variables.count(MODEL_COMMAND))
	{
		tstring modelFileName = m_variables[MODEL_COMMAND].as<tstring>();
#if defined(OST_WINDOWS)
		modelFileName = rdo::locale::convertFromCLocale(modelFileName);
#elif defined(OST_LINUX)
		modelFileName = rdo::locale::convert(modelFileName, rdo::locale::get().utf8(), rdo::locale::get().system());
#endif
		result = rdo::locale::convertToWStr(modelFileName);
	}
	return result;
}

boost::filesystem::path ControllerConsoleOptions::getScriptFileName() const
{
	boost::filesystem::path result;
	if (m_variables.count(SCRIPT_COMMAND))
	{
		tstring eventsFileName = m_variables[SCRIPT_COMMAND].as<tstring>();
#if defined(OST_WINDOWS)
		eventsFileName = rdo::locale::convertFromCLocale(eventsFileName);
#elif defined(OST_LINUX)
		eventsFileName = rdo::locale::convert(eventsFileName, rdo::locale::get().utf8(), rdo::locale::get().system());
#endif
		result = rdo::locale::convertToWStr(eventsFileName);
	}
	return result;
}

rbool ControllerConsoleOptions::helpQuery()
{
	return m_help;
}

rbool ControllerConsoleOptions::convertQuery()
{
	return m_convert;
}

void ControllerConsoleOptions::createGeneralOptions(REF(po::options_description) options)
{
	options.add_options()
			((MODEL_COMMAND + COMMA_STRING + MODEL_COMMAND_SHORT).c_str(), po::value<tstring>(), MODEL_COMMENT.c_str())
			((SCRIPT_COMMAND + COMMA_STRING + SCRIPT_COMMAND_SHORT).c_str(), po::value<tstring>(), SCRIPT_COMMENT.c_str())
			((LANGUAGE_COMMAND + COMMA_STRING + LANGUAGE_COMMAND_SHORT).c_str(), LANGUAGE_COMMENT.c_str())
			((VERSION_COMMAND + COMMA_STRING + VERSION_COMMAND_SHORT).c_str(), VERSION_COMMENT.c_str())
			((HELP_COMMAND + COMMA_STRING + HELP_COMMAND_SHORT).c_str(), HELP_COMMENT.c_str());
}

void ControllerConsoleOptions::createConvertorOptions(REF(po::options_description) options)
{
	options.add_options()
		((CONVERTOR_COMMAND + COMMA_STRING + CONVERTOR_COMMAND_SHORT).c_str(), CONVERTOR_COMMENT.c_str());
}

void ControllerConsoleOptions::createAdditionalOptions(REF(po::options_description) options)
{
	options.add_options()
			(AUTO_RUN_COMMAND.c_str(), AUTO_RUN_COMMENT.c_str())
			(AUTO_EXIT_COMMAND.c_str(), AUTO_EXIT_COMMENT.c_str())
			(DONT_CLOSE_IF_ERROR_COMMAND.c_str(), DONT_CLOSE_IF_ERROR_COMMENT.c_str())
			(PLUGIN_START_COMMAND.c_str(), PLUGIN_START_COMMENT.c_str())
			(PLUGIN_AUTO_EXIT_COMMAND.c_str(), PLUGIN_AUTO_EXIT_COMMENT.c_str());
}
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2016 ScyllaDB, Ltd.
 */

#pragma once

#include "core/future-util.hh"

/// \addtogroup fiber-module
/// @{

/// Exception thrown when a condition variable is broken by
/// \ref condition_variable::broken().
class broken_condition_variable : public std::exception {
public:
    /// Reports the exception reason.
    virtual const char* what() const noexcept {
        return "Conditional variable is broken";
    }
};

/// \brief Conditional variable.
///
/// This is a standard computer science condition variable sans locking,
/// since in seastar access to variables is atomic anyway, adapted
/// for futures.  You can wait for variable to be notified.
///
/// To support exceptional conditions, a \ref broken() method
/// is provided, which causes all current waiters to stop waiting,
/// with an exceptional future returned.  This allows causing all
/// fibers that are blocked on a condition variable to continue.
/// This issimilar to POSIX's `pthread_cancel()`, with \ref wait()
/// acting as a cancellation point.

/// FIXME: Support multiple waiters
class condition_variable {
    promise<> _p;
    bool _signaled = false;
    bool _broken = false;
public:
    /// Waits until condition variable is signaled, may wake up without condition been met
    ///
    /// \return a future that becomes ready when \ref signal() is called
    ///         If the condition variable was \ref broken(), may contain an exception.
    future<> wait() {
        if (_broken) {
            return make_exception_future<>(broken_condition_variable());
        }
        if (_signaled) {
            _p = promise<>();
            _signaled = false;
            return make_ready_future<>();
        }
        return _p.get_future().then([this] {
            return wait();
        });
    }
    /// Waits until condition variable is notified and pred() == true, otherwise
    /// wait again.
    ///
    /// \return a future that becomes ready when \ref signal() is called
    ///         If the condition variable was \ref broken(), may contain an exception.
    template<typename Pred>
    future<> wait(Pred&& pred) {
        return do_until(std::forward<Pred>(pred), [this] {
            return wait();
        });
    }
    /// Notify variable and wake up a waiter if there is one
    void signal() {
        if (!_signaled) {
            _p.set_value();
            _signaled = true;
        }
    }
    /// Signal to waiters that an error occurred.  \ref wait() will see
    /// an exceptional future<> containing the provided exception parameter.
    /// The future is made available immediately.
    void broken() {
        _broken = true;
        signal();
    }
};

/// @}
<commit_msg>condition_variable: add multiple waiters and wait with timeout<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2016 ScyllaDB, Ltd.
 */

#pragma once

#include "core/future-util.hh"
#include "core/semaphore.hh"

/// \addtogroup fiber-module
/// @{

/// Exception thrown when a condition variable is broken by
/// \ref condition_variable::broken().
class broken_condition_variable : public std::exception {
public:
    /// Reports the exception reason.
    virtual const char* what() const noexcept {
        return "Condition variable is broken";
    }
};

/// Exception thrown when wait() operation times out
/// \ref condition_variable::wait(time_point timeout).
class condition_variable_timed_out : public std::exception {
public:
    /// Reports the exception reason.
    virtual const char* what() const noexcept {
        return "Condition variable timed out";
    }
};

/// \brief Conditional variable.
///
/// This is a standard computer science condition variable sans locking,
/// since in seastar access to variables is atomic anyway, adapted
/// for futures.  You can wait for variable to be notified.
///
/// To support exceptional conditions, a \ref broken() method
/// is provided, which causes all current waiters to stop waiting,
/// with an exceptional future returned.  This allows causing all
/// fibers that are blocked on a condition variable to continue.
/// This issimilar to POSIX's `pthread_cancel()`, with \ref wait()
/// acting as a cancellation point.

class condition_variable {
    using duration = semaphore::duration;
    using clock = semaphore::clock;
    using time_point = semaphore::time_point;
    struct condition_variable_exception_factory {
        static condition_variable_timed_out timeout() {
            return condition_variable_timed_out();
        }
        static broken_condition_variable broken() {
            return broken_condition_variable();
        }
    };
    basic_semaphore<condition_variable_exception_factory> _sem;
public:
    /// Waits until condition variable is signaled, may wake up without condition been met
    ///
    /// \return a future that becomes ready when \ref signal() is called
    ///         If the condition variable was \ref broken() will return \ref broken_condition_variable
    ///         exception.
    future<> wait() {
        return _sem.wait();
    }

    /// Waits until condition variable is signaled or timeout is reached
    ///
    /// \param timeout time point at which wait will exit with a timeout
    ///
    /// \return a future that becomes ready when \ref signal() is called
    ///         If the condition variable was \ref broken() will return \ref broken_condition_variable
    ///         exception. If timepoint is reached will return \ref condition_variable_timed_out exception.
    future<> wait(time_point timeout) {
        return _sem.wait(timeout);
    }

    /// Waits until condition variable is signaled or timeout is reached
    ///
    /// \param timeout duration after which wait will exit with a timeout
    ///
    /// \return a future that becomes ready when \ref signal() is called
    ///         If the condition variable was \ref broken() will return \ref broken_condition_variable
    ///         exception. If timepoint is passed will return \ref condition_variable_timed_out exception.
    future<> wait(duration timeout) {
        return _sem.wait(timeout);
    }

    /// Waits until condition variable is notified and pred() == true, otherwise
    /// wait again.
    ///
    /// \param pred predicate that checks that awaited condition is true
    ///
    /// \return a future that becomes ready when \ref signal() is called
    ///         If the condition variable was \ref broken(), may contain an exception.
    template<typename Pred>
    future<> wait(Pred&& pred) {
        return do_until(std::forward<Pred>(pred), [this] {
            return wait();
        });
    }

    /// Waits until condition variable is notified and pred() == true or timeout is reached, otherwise
    /// wait again.
    ///
    /// \param timeout time point at which wait will exit with a timeout
    /// \param pred predicate that checks that awaited condition is true
    ///
    /// \return a future that becomes ready when \ref signal() is called
    ///         If the condition variable was \ref broken() will return \ref broken_condition_variable
    ///         exception. If timepoint is reached will return \ref condition_variable_timed_out exception.
    /// \param
    template<typename Pred>
    future<> wait(time_point timeout, Pred&& pred) {
        return do_until(std::forward<Pred>(pred), [this, timeout] () mutable {
            return wait(timeout);
        });
    }

    /// Waits until condition variable is notified and pred() == true or timeout is reached, otherwise
    /// wait again.
    ///
    /// \param timeout duration after which wait will exit with a timeout
    /// \param pred predicate that checks that awaited condition is true
    ///
    /// \return a future that becomes ready when \ref signal() is called
    ///         If the condition variable was \ref broken() will return \ref broken_condition_variable
    ///         exception. If timepoint is passed will return \ref condition_variable_timed_out exception.
    template<typename Pred>
    future<> wait(duration timeout, Pred&& pred) {
        return wait(clock::now() + timeout, std::forward<Pred>(pred));
    }
    /// Notify variable and wake up a waiter if there is one
    void signal() {
        if (_sem.waiters()) {
            _sem.signal();
        }
    }
    /// Notify variable and wake up all waiter
    void broadcast() {
        _sem.signal(_sem.waiters());
    }

    /// Signal to waiters that an error occurred.  \ref wait() will see
    /// an exceptional future<> containing the provided exception parameter.
    /// The future is made available immediately.
    void broken() {
        _sem.broken();
    }
};

/// @}
<|endoftext|>


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

#include "chrome/browser/gtk/nine_box.h"

#include "app/resource_bundle.h"
#include "base/gfx/gtk_util.h"
#include "base/gfx/point.h"
#include "base/logging.h"

namespace {

// Draw pixbuf |src| into |dst| at position (x, y).
void DrawPixbuf(cairo_t* cr, GdkPixbuf* src, int x, int y) {
  gdk_cairo_set_source_pixbuf(cr, src, x, y);
  cairo_paint(cr);
}

// Tile pixbuf |src| across |cr| at |x|, |y| for |width| and |height|.
void TileImage(cairo_t* cr, GdkPixbuf* src,
               int x, int y, int width, int height) {
  gdk_cairo_set_source_pixbuf(cr, src, x, y);
  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
  cairo_rectangle(cr, x, y, width, height);
  cairo_fill(cr);
}

}  // namespace

NineBox::NineBox(int top_left, int top, int top_right, int left, int center,
                 int right, int bottom_left, int bottom, int bottom_right) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  images_[0] = top_left ? rb.GetPixbufNamed(top_left) : NULL;
  images_[1] = top ? rb.GetPixbufNamed(top) : NULL;
  images_[2] = top_right ? rb.GetPixbufNamed(top_right) : NULL;
  images_[3] = left ? rb.GetPixbufNamed(left) : NULL;
  images_[4] = center ? rb.GetPixbufNamed(center) : NULL;
  images_[5] = right ? rb.GetPixbufNamed(right) : NULL;
  images_[6] = bottom_left ? rb.GetPixbufNamed(bottom_left) : NULL;
  images_[7] = bottom ? rb.GetPixbufNamed(bottom) : NULL;
  images_[8] = bottom_right ? rb.GetPixbufNamed(bottom_right) : NULL;
}

NineBox::~NineBox() {
}

void NineBox::RenderToWidget(GtkWidget* dst) const {
  int dst_width = dst->allocation.width;
  int dst_height = dst->allocation.height;

  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(dst->window));
  // Transform our cairo from window to widget coordinates.
  cairo_translate(cr, dst->allocation.x, dst->allocation.y);

  // The upper-left and lower-right corners of the center square in the
  // rendering of the ninebox.
  int x1 = gdk_pixbuf_get_width(images_[0]);
  int y1 = gdk_pixbuf_get_height(images_[0]);
  int x2 = images_[2] ? dst_width - gdk_pixbuf_get_width(images_[2]) : x1;
  int y2 = images_[6] ? dst_height - gdk_pixbuf_get_height(images_[6]) : y1;
  DCHECK_GE(x2, x1);
  DCHECK_GE(y2, y1);

  // Top row, center image is horizontally tiled.
  if (images_[0])
    DrawPixbuf(cr, images_[0], 0, 0);
  if (images_[1])
    RenderTopCenterStrip(cr, x1, 0, x2 - x1);
  if (images_[2])
    DrawPixbuf(cr, images_[2], x2, 0);

  // Center row, all images are vertically tiled, center is horizontally tiled.
  if (images_[3])
    TileImage(cr, images_[3], 0, y1, x1, y2 - y1);
  if (images_[4])
    TileImage(cr, images_[4], x1, y1, x2 - x1, y2 - y1);
  if (images_[5])
    TileImage(cr, images_[5], x2, y1, dst_width - x2, y2 - y1);

  // Bottom row, center image is horizontally tiled.
  if (images_[6])
    DrawPixbuf(cr, images_[6], 0, y2);
  if (images_[7])
    TileImage(cr, images_[7], x1, y2, x2 - x1, dst_height - y2);
  if (images_[8])
    DrawPixbuf(cr, images_[8], x2, y2);

  cairo_destroy(cr);
}

void NineBox::RenderTopCenterStrip(cairo_t* cr,
                                   int x, int y, int width) const {
  const int height = gdk_pixbuf_get_height(images_[1]);
  TileImage(cr, images_[1], x, y, width, height);
}

void NineBox::ChangeWhiteToTransparent() {
  for (int image_idx = 0; image_idx < 9; ++image_idx) {
    GdkPixbuf* pixbuf = images_[image_idx];
    if (!pixbuf)
      continue;

    guchar* pixels = gdk_pixbuf_get_pixels(pixbuf);
    int rowstride = gdk_pixbuf_get_rowstride(pixbuf);

    for (int i = 0; i < gdk_pixbuf_get_height(pixbuf); ++i) {
      for (int j = 0; j < gdk_pixbuf_get_width(pixbuf); ++j) {
         guchar* pixel = &pixels[i * rowstride + j * 4];
         if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) {
           pixel[3] = 0;
         }
      }
    }
  }
}

void NineBox::ContourWidget(GtkWidget* widget) const {
  int x1 = gdk_pixbuf_get_width(images_[0]);
  int x2 = widget->allocation.width - gdk_pixbuf_get_width(images_[2]);

  // Paint the left and right sides.
  GdkBitmap* mask = gdk_pixmap_new(NULL, widget->allocation.width,
                                   widget->allocation.height, 1);
  gdk_pixbuf_render_threshold_alpha(images_[0], mask,
                                    0, 0,
                                    0, 0, -1, -1,
                                    1);
  gdk_pixbuf_render_threshold_alpha(images_[2], mask,
                                    0, 0,
                                    x2, 0, -1, -1,
                                    1);

  // Assume no transparency in the middle rectangle.
  cairo_t* cr = gdk_cairo_create(mask);
  cairo_rectangle(cr, x1, 0, x2 - x1, widget->allocation.height);
  cairo_fill(cr);

  // Mask the widget's window's shape.
  gtk_widget_shape_combine_mask(widget, mask, 0, 0);

  g_object_unref(mask);
  cairo_destroy(cr);
}
<commit_msg>Gtk: fix find bar rendering following NineBox improvements.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/gtk/nine_box.h"

#include "app/resource_bundle.h"
#include "base/gfx/gtk_util.h"
#include "base/gfx/point.h"
#include "base/logging.h"

namespace {

// Draw pixbuf |src| into |dst| at position (x, y).
void DrawPixbuf(cairo_t* cr, GdkPixbuf* src, int x, int y) {
  gdk_cairo_set_source_pixbuf(cr, src, x, y);
  cairo_paint(cr);
}

// Tile pixbuf |src| across |cr| at |x|, |y| for |width| and |height|.
void TileImage(cairo_t* cr, GdkPixbuf* src,
               int x, int y, int width, int height) {
  gdk_cairo_set_source_pixbuf(cr, src, x, y);
  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
  cairo_rectangle(cr, x, y, width, height);
  cairo_fill(cr);
}

}  // namespace

NineBox::NineBox(int top_left, int top, int top_right, int left, int center,
                 int right, int bottom_left, int bottom, int bottom_right) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  images_[0] = top_left ? rb.GetPixbufNamed(top_left) : NULL;
  images_[1] = top ? rb.GetPixbufNamed(top) : NULL;
  images_[2] = top_right ? rb.GetPixbufNamed(top_right) : NULL;
  images_[3] = left ? rb.GetPixbufNamed(left) : NULL;
  images_[4] = center ? rb.GetPixbufNamed(center) : NULL;
  images_[5] = right ? rb.GetPixbufNamed(right) : NULL;
  images_[6] = bottom_left ? rb.GetPixbufNamed(bottom_left) : NULL;
  images_[7] = bottom ? rb.GetPixbufNamed(bottom) : NULL;
  images_[8] = bottom_right ? rb.GetPixbufNamed(bottom_right) : NULL;
}

NineBox::~NineBox() {
}

void NineBox::RenderToWidget(GtkWidget* dst) const {
  int dst_width = dst->allocation.width;
  int dst_height = dst->allocation.height;

  cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(dst->window));
  // For widgets that have their own window, the allocation (x,y) coordinates
  // are GdkWindow relative. For other widgets, the coordinates are relative
  // to their container.
  if (GTK_WIDGET_NO_WINDOW(dst)) {
    // Transform our cairo from window to widget coordinates.
    cairo_translate(cr, dst->allocation.x, dst->allocation.y);
  }

  // The upper-left and lower-right corners of the center square in the
  // rendering of the ninebox.
  int x1 = gdk_pixbuf_get_width(images_[0]);
  int y1 = gdk_pixbuf_get_height(images_[0]);
  int x2 = images_[2] ? dst_width - gdk_pixbuf_get_width(images_[2]) : x1;
  int y2 = images_[6] ? dst_height - gdk_pixbuf_get_height(images_[6]) : y1;
  DCHECK_GE(x2, x1);
  DCHECK_GE(y2, y1);

  // Top row, center image is horizontally tiled.
  if (images_[0])
    DrawPixbuf(cr, images_[0], 0, 0);
  if (images_[1])
    RenderTopCenterStrip(cr, x1, 0, x2 - x1);
  if (images_[2])
    DrawPixbuf(cr, images_[2], x2, 0);

  // Center row, all images are vertically tiled, center is horizontally tiled.
  if (images_[3])
    TileImage(cr, images_[3], 0, y1, x1, y2 - y1);
  if (images_[4])
    TileImage(cr, images_[4], x1, y1, x2 - x1, y2 - y1);
  if (images_[5])
    TileImage(cr, images_[5], x2, y1, dst_width - x2, y2 - y1);

  // Bottom row, center image is horizontally tiled.
  if (images_[6])
    DrawPixbuf(cr, images_[6], 0, y2);
  if (images_[7])
    TileImage(cr, images_[7], x1, y2, x2 - x1, dst_height - y2);
  if (images_[8])
    DrawPixbuf(cr, images_[8], x2, y2);

  cairo_destroy(cr);
}

void NineBox::RenderTopCenterStrip(cairo_t* cr,
                                   int x, int y, int width) const {
  const int height = gdk_pixbuf_get_height(images_[1]);
  TileImage(cr, images_[1], x, y, width, height);
}

void NineBox::ChangeWhiteToTransparent() {
  for (int image_idx = 0; image_idx < 9; ++image_idx) {
    GdkPixbuf* pixbuf = images_[image_idx];
    if (!pixbuf)
      continue;

    guchar* pixels = gdk_pixbuf_get_pixels(pixbuf);
    int rowstride = gdk_pixbuf_get_rowstride(pixbuf);

    for (int i = 0; i < gdk_pixbuf_get_height(pixbuf); ++i) {
      for (int j = 0; j < gdk_pixbuf_get_width(pixbuf); ++j) {
         guchar* pixel = &pixels[i * rowstride + j * 4];
         if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) {
           pixel[3] = 0;
         }
      }
    }
  }
}

void NineBox::ContourWidget(GtkWidget* widget) const {
  int x1 = gdk_pixbuf_get_width(images_[0]);
  int x2 = widget->allocation.width - gdk_pixbuf_get_width(images_[2]);

  // Paint the left and right sides.
  GdkBitmap* mask = gdk_pixmap_new(NULL, widget->allocation.width,
                                   widget->allocation.height, 1);
  gdk_pixbuf_render_threshold_alpha(images_[0], mask,
                                    0, 0,
                                    0, 0, -1, -1,
                                    1);
  gdk_pixbuf_render_threshold_alpha(images_[2], mask,
                                    0, 0,
                                    x2, 0, -1, -1,
                                    1);

  // Assume no transparency in the middle rectangle.
  cairo_t* cr = gdk_cairo_create(mask);
  cairo_rectangle(cr, x1, 0, x2 - x1, widget->allocation.height);
  cairo_fill(cr);

  // Mask the widget's window's shape.
  gtk_widget_shape_combine_mask(widget, mask, 0, 0);

  g_object_unref(mask);
  cairo_destroy(cr);
}
<|endoftext|>


<commit_before>/*
* Copyright 2016 Nu-book Inc.
* Copyright 2016 ZXing authors
* Copyright 2020 Axel Waggershauser
*
* 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 "ODReader.h"

#include "BinaryBitmap.h"
#include "DecodeHints.h"
#include "ODCodabarReader.h"
#include "ODCode128Reader.h"
#include "ODCode39Reader.h"
#include "ODCode93Reader.h"
#include "ODDataBarExpandedReader.h"
#include "ODDataBarReader.h"
#include "ODITFReader.h"
#include "ODMultiUPCEANReader.h"
#include "Result.h"

#include <algorithm>
#include <utility>

namespace ZXing::OneD {

Reader::Reader(const DecodeHints& hints) :
	_tryHarder(hints.tryHarder()),
	_tryRotate(hints.tryRotate()),
	_isPure(hints.isPure()),
	_minLineCount(hints.minLineCount())
{
	_readers.reserve(8);

	auto formats = hints.formats().empty() ? BarcodeFormat::Any : hints.formats();

	if (formats.testFlags(BarcodeFormat::EAN13 | BarcodeFormat::UPCA | BarcodeFormat::EAN8 | BarcodeFormat::UPCE))
		_readers.emplace_back(new MultiUPCEANReader(hints));

	if (formats.testFlag(BarcodeFormat::Code39))
		_readers.emplace_back(new Code39Reader(hints));
	if (formats.testFlag(BarcodeFormat::Code93))
		_readers.emplace_back(new Code93Reader());
	if (formats.testFlag(BarcodeFormat::Code128))
		_readers.emplace_back(new Code128Reader());
	if (formats.testFlag(BarcodeFormat::ITF))
		_readers.emplace_back(new ITFReader(hints));
	if (formats.testFlag(BarcodeFormat::Codabar))
		_readers.emplace_back(new CodabarReader(hints));
	if (formats.testFlags(BarcodeFormat::DataBar))
		_readers.emplace_back(new DataBarReader(hints));
	if (formats.testFlags(BarcodeFormat::DataBarExpanded))
		_readers.emplace_back(new DataBarExpandedReader(hints));
}

Reader::~Reader() = default;

static bool IsIntersecting(QuadrilateralI a, QuadrilateralI b)
{
	bool x = b.topRight().x < a.topLeft().x || b.topLeft().x > a.topRight().x;
	bool y = b.bottomLeft().y < a.topLeft().y || b.topLeft().y > a.bottomLeft().y;
	return !(x || y);
}

/**
* We're going to examine rows from the middle outward, searching alternately above and below the
* middle, and farther out each time. rowStep is the number of rows between each successive
* attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then
* middle + rowStep, then middle - (2 * rowStep), etc.
* rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily
* decided that moving up and down by about 1/16 of the image is pretty good; we try more of the
* image if "trying harder".
*/
static Results DoDecode(const std::vector<std::unique_ptr<RowReader>>& readers, const BinaryBitmap& image,
						bool tryHarder, bool rotate, bool isPure, int maxSymbols, int minLineCount)
{
	Results res;

	std::vector<std::unique_ptr<RowReader::DecodingState>> decodingState(readers.size());

	int width = image.width();
	int height = image.height();

	if (rotate)
		std::swap(width, height);

	int middle = height / 2;
	// TODO: find a better heuristic/parameterization if maxSymbols != 1
	int rowStep = std::max(1, height / ((tryHarder && !isPure) ? (maxSymbols == 1 ? 256 : 512) : 32));
	int maxLines = tryHarder ?
		height :	// Look at the whole image, not just the center
		15;			// 15 rows spaced 1/32 apart is roughly the middle half of the image

	if (isPure)
		minLineCount = 1;
	std::vector<int> checkRows;

	PatternRow bars;
	bars.reserve(128); // e.g. EAN-13 has 59 bars/spaces

	for (int i = 0; i < maxLines; i++) {

		// Scanning from the middle out. Determine which row we're looking at next:
		int rowStepsAboveOrBelow = (i + 1) / 2;
		bool isAbove = (i & 0x01) == 0; // i.e. is x even?
		int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
		if (rowNumber < 0 || rowNumber >= height) {
			// Oops, if we run off the top or bottom, stop
			break;
		}

		// See if we have additional check rows (see below) to process
		if (checkRows.size()) {
			--i;
			rowNumber = checkRows.back();
			checkRows.pop_back();
			if (rowNumber < 0 || rowNumber >= height)
				continue;
		}

		if (!image.getPatternRow(rowNumber, rotate ? 270 : 0, bars))
			continue;

		// While we have the image data in a PatternRow, it's fairly cheap to reverse it in place to
		// handle decoding upside down barcodes.
		// Note: the DataBarExpanded decoder depends on seeing each line from both directions. This
		// 'surprising' and inconsistent. It also requires the decoderState to be shared between
		// normal and reversed scans, which makes no sense in general because it would mix partial
		// detection data from two codes of the same type next to each other. TODO..
		// See also https://github.com/nu-book/zxing-cpp/issues/87
		for (bool upsideDown : {false, true}) {
			// trying again?
			if (upsideDown) {
				// reverse the row and continue
				std::reverse(bars.begin(), bars.end());
			}
			// Look for a barcode
			for (size_t r = 0; r < readers.size(); ++r) {
				// If this is a pure symbol, then checking a single non-empty line is sufficient for all but the stacked
				// DataBar codes. They are the only ones using the decodingState, which we can use as a flag here.
				if (isPure && i && !decodingState[r])
					continue;

				PatternView next(bars);
				do {
					Result result = readers[r]->decodePattern(rowNumber, next, decodingState[r]);
					if (result.isValid()) {
						result.incrementLineCount();
						if (upsideDown) {
							// update position (flip horizontally).
							auto points = result.position();
							for (auto& p : points) {
								p = {width - p.x - 1, p.y};
							}
							result.setPosition(std::move(points));
						}
						if (rotate) {
							auto points = result.position();
							for (auto& p : points) {
								p = {height - p.y - 1, p.x};
							}
							result.setPosition(std::move(points));
						}

						// check if we know this code already
						for (auto& other : res) {
							if (other == result) {
								auto dTop = maxAbsComponent(other.position().topLeft() - result.position().topLeft());
								auto dBot = maxAbsComponent(other.position().bottomLeft() - result.position().topLeft());
								auto length = maxAbsComponent(other.position().topLeft() - other.position().bottomRight());
								// if the new line is less than half the length of the existing result away from the
								// latter, we consider it to belong to the same symbol
								if (std::min(dTop, dBot) < length / 2) {
									// if so, merge the position information
									auto points = other.position();
									if (dTop < dBot ||
										(dTop == dBot && rotate ^ (sumAbsComponent(points[0]) >
																   sumAbsComponent(result.position()[0])))) {
										points[0] = result.position()[0];
										points[1] = result.position()[1];
									} else {
										points[2] = result.position()[2];
										points[3] = result.position()[3];
									}
									other.setPosition(points);
									other.incrementLineCount();
									// clear the result, so we don't insert it again below
									result = Result(DecodeStatus::NotFound);
									break;
								}
							}
						}

						if (result.isValid())
							res.push_back(std::move(result));

						if (maxSymbols && Reduce(res, 0, [&](int s, const Result& r) {
											  return s + (r.lineCount() >= minLineCount);
										  }) == maxSymbols) {
							goto out;
						}

						// if we found a valid code but have a minLineCount > 1, add additional check rows above and
						// below the current one
						if (checkRows.empty() && minLineCount > 1 && rowStep > 1) {
							checkRows = {rowNumber - 1, rowNumber + 1};
							if (rowStep > 2)
								checkRows.insert(checkRows.end(), {rowNumber - 2, rowNumber + 2});
						}
					}
					// make sure we make progress and we start the next try on a bar
					next.shift(2 - (next.index() % 2));
					next.extend();
				} while (tryHarder && next.isValid());
			}
		}
	}

out:
	// remove all symbols with insufficient line count
	auto it = std::remove_if(res.begin(), res.end(), [&](auto&& r) { return r.lineCount() < minLineCount; });
	res.erase(it, res.end());

	// if symbols overlap, remove the one with a lower line count
	for (auto a = res.begin(); a != res.end(); ++a)
		for (auto b = std::next(a); b != res.end(); ++b)
			if (IsIntersecting(a->position(), b->position()))
				*(a->lineCount() < b->lineCount() ? a : b) = Result(DecodeStatus::NotFound);

	//TODO: C++20 res.erase_if()
	it = std::remove_if(res.begin(), res.end(), [](auto&& r) { return r.status() == DecodeStatus::NotFound; });
	res.erase(it, res.end());

	return res;
}

Result
Reader::decode(const BinaryBitmap& image) const
{
	auto result = DoDecode(_readers, image, _tryHarder, false, _isPure, 1, _minLineCount);

	if (result.empty() && _tryRotate)
		result = DoDecode(_readers, image, _tryHarder, true, _isPure, 1, _minLineCount);

	return result.empty() ? Result(DecodeStatus::NotFound) : result.front();
}

Results Reader::decode(const BinaryBitmap& image, int maxSymbols) const
{
	auto resH = DoDecode(_readers, image, _tryHarder, false, _isPure, maxSymbols, _minLineCount);
	if ((!maxSymbols || Size(resH) < maxSymbols) && _tryRotate) {
		auto resV = DoDecode(_readers, image, _tryHarder, true, _isPure, maxSymbols - Size(resH), _minLineCount);
		resH.insert(resH.end(), resV.begin(), resV.end());
	}
	return resH;
}

} // namespace ZXing::OneD
<commit_msg>ODReader: check for next.size() instead of isValid() (performance fix)<commit_after>/*
* Copyright 2016 Nu-book Inc.
* Copyright 2016 ZXing authors
* Copyright 2020 Axel Waggershauser
*
* 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 "ODReader.h"

#include "BinaryBitmap.h"
#include "DecodeHints.h"
#include "ODCodabarReader.h"
#include "ODCode128Reader.h"
#include "ODCode39Reader.h"
#include "ODCode93Reader.h"
#include "ODDataBarExpandedReader.h"
#include "ODDataBarReader.h"
#include "ODITFReader.h"
#include "ODMultiUPCEANReader.h"
#include "Result.h"

#include <algorithm>
#include <utility>

namespace ZXing::OneD {

Reader::Reader(const DecodeHints& hints) :
	_tryHarder(hints.tryHarder()),
	_tryRotate(hints.tryRotate()),
	_isPure(hints.isPure()),
	_minLineCount(hints.minLineCount())
{
	_readers.reserve(8);

	auto formats = hints.formats().empty() ? BarcodeFormat::Any : hints.formats();

	if (formats.testFlags(BarcodeFormat::EAN13 | BarcodeFormat::UPCA | BarcodeFormat::EAN8 | BarcodeFormat::UPCE))
		_readers.emplace_back(new MultiUPCEANReader(hints));

	if (formats.testFlag(BarcodeFormat::Code39))
		_readers.emplace_back(new Code39Reader(hints));
	if (formats.testFlag(BarcodeFormat::Code93))
		_readers.emplace_back(new Code93Reader());
	if (formats.testFlag(BarcodeFormat::Code128))
		_readers.emplace_back(new Code128Reader());
	if (formats.testFlag(BarcodeFormat::ITF))
		_readers.emplace_back(new ITFReader(hints));
	if (formats.testFlag(BarcodeFormat::Codabar))
		_readers.emplace_back(new CodabarReader(hints));
	if (formats.testFlags(BarcodeFormat::DataBar))
		_readers.emplace_back(new DataBarReader(hints));
	if (formats.testFlags(BarcodeFormat::DataBarExpanded))
		_readers.emplace_back(new DataBarExpandedReader(hints));
}

Reader::~Reader() = default;

static bool IsIntersecting(QuadrilateralI a, QuadrilateralI b)
{
	bool x = b.topRight().x < a.topLeft().x || b.topLeft().x > a.topRight().x;
	bool y = b.bottomLeft().y < a.topLeft().y || b.topLeft().y > a.bottomLeft().y;
	return !(x || y);
}

/**
* We're going to examine rows from the middle outward, searching alternately above and below the
* middle, and farther out each time. rowStep is the number of rows between each successive
* attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then
* middle + rowStep, then middle - (2 * rowStep), etc.
* rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily
* decided that moving up and down by about 1/16 of the image is pretty good; we try more of the
* image if "trying harder".
*/
static Results DoDecode(const std::vector<std::unique_ptr<RowReader>>& readers, const BinaryBitmap& image,
						bool tryHarder, bool rotate, bool isPure, int maxSymbols, int minLineCount)
{
	Results res;

	std::vector<std::unique_ptr<RowReader::DecodingState>> decodingState(readers.size());

	int width = image.width();
	int height = image.height();

	if (rotate)
		std::swap(width, height);

	int middle = height / 2;
	// TODO: find a better heuristic/parameterization if maxSymbols != 1
	int rowStep = std::max(1, height / ((tryHarder && !isPure) ? (maxSymbols == 1 ? 256 : 512) : 32));
	int maxLines = tryHarder ?
		height :	// Look at the whole image, not just the center
		15;			// 15 rows spaced 1/32 apart is roughly the middle half of the image

	if (isPure)
		minLineCount = 1;
	std::vector<int> checkRows;

	PatternRow bars;
	bars.reserve(128); // e.g. EAN-13 has 59 bars/spaces

	for (int i = 0; i < maxLines; i++) {

		// Scanning from the middle out. Determine which row we're looking at next:
		int rowStepsAboveOrBelow = (i + 1) / 2;
		bool isAbove = (i & 0x01) == 0; // i.e. is x even?
		int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
		if (rowNumber < 0 || rowNumber >= height) {
			// Oops, if we run off the top or bottom, stop
			break;
		}

		// See if we have additional check rows (see below) to process
		if (checkRows.size()) {
			--i;
			rowNumber = checkRows.back();
			checkRows.pop_back();
			if (rowNumber < 0 || rowNumber >= height)
				continue;
		}

		if (!image.getPatternRow(rowNumber, rotate ? 270 : 0, bars))
			continue;

		// While we have the image data in a PatternRow, it's fairly cheap to reverse it in place to
		// handle decoding upside down barcodes.
		// Note: the DataBarExpanded decoder depends on seeing each line from both directions. This
		// 'surprising' and inconsistent. It also requires the decoderState to be shared between
		// normal and reversed scans, which makes no sense in general because it would mix partial
		// detection data from two codes of the same type next to each other. TODO..
		// See also https://github.com/nu-book/zxing-cpp/issues/87
		for (bool upsideDown : {false, true}) {
			// trying again?
			if (upsideDown) {
				// reverse the row and continue
				std::reverse(bars.begin(), bars.end());
			}
			// Look for a barcode
			for (size_t r = 0; r < readers.size(); ++r) {
				// If this is a pure symbol, then checking a single non-empty line is sufficient for all but the stacked
				// DataBar codes. They are the only ones using the decodingState, which we can use as a flag here.
				if (isPure && i && !decodingState[r])
					continue;

				PatternView next(bars);
				do {
					Result result = readers[r]->decodePattern(rowNumber, next, decodingState[r]);
					if (result.isValid()) {
						result.incrementLineCount();
						if (upsideDown) {
							// update position (flip horizontally).
							auto points = result.position();
							for (auto& p : points) {
								p = {width - p.x - 1, p.y};
							}
							result.setPosition(std::move(points));
						}
						if (rotate) {
							auto points = result.position();
							for (auto& p : points) {
								p = {height - p.y - 1, p.x};
							}
							result.setPosition(std::move(points));
						}

						// check if we know this code already
						for (auto& other : res) {
							if (other == result) {
								auto dTop = maxAbsComponent(other.position().topLeft() - result.position().topLeft());
								auto dBot = maxAbsComponent(other.position().bottomLeft() - result.position().topLeft());
								auto length = maxAbsComponent(other.position().topLeft() - other.position().bottomRight());
								// if the new line is less than half the length of the existing result away from the
								// latter, we consider it to belong to the same symbol
								if (std::min(dTop, dBot) < length / 2) {
									// if so, merge the position information
									auto points = other.position();
									if (dTop < dBot ||
										(dTop == dBot && rotate ^ (sumAbsComponent(points[0]) >
																   sumAbsComponent(result.position()[0])))) {
										points[0] = result.position()[0];
										points[1] = result.position()[1];
									} else {
										points[2] = result.position()[2];
										points[3] = result.position()[3];
									}
									other.setPosition(points);
									other.incrementLineCount();
									// clear the result, so we don't insert it again below
									result = Result(DecodeStatus::NotFound);
									break;
								}
							}
						}

						if (result.isValid())
							res.push_back(std::move(result));

						if (maxSymbols && Reduce(res, 0, [&](int s, const Result& r) {
											  return s + (r.lineCount() >= minLineCount);
										  }) == maxSymbols) {
							goto out;
						}

						// if we found a valid code but have a minLineCount > 1, add additional check rows above and
						// below the current one
						if (checkRows.empty() && minLineCount > 1 && rowStep > 1) {
							checkRows = {rowNumber - 1, rowNumber + 1};
							if (rowStep > 2)
								checkRows.insert(checkRows.end(), {rowNumber - 2, rowNumber + 2});
						}
					}
					// make sure we make progress and we start the next try on a bar
					next.shift(2 - (next.index() % 2));
					next.extend();
				} while (tryHarder && next.size());
			}
		}
	}

out:
	// remove all symbols with insufficient line count
	auto it = std::remove_if(res.begin(), res.end(), [&](auto&& r) { return r.lineCount() < minLineCount; });
	res.erase(it, res.end());

	// if symbols overlap, remove the one with a lower line count
	for (auto a = res.begin(); a != res.end(); ++a)
		for (auto b = std::next(a); b != res.end(); ++b)
			if (IsIntersecting(a->position(), b->position()))
				*(a->lineCount() < b->lineCount() ? a : b) = Result(DecodeStatus::NotFound);

	//TODO: C++20 res.erase_if()
	it = std::remove_if(res.begin(), res.end(), [](auto&& r) { return r.status() == DecodeStatus::NotFound; });
	res.erase(it, res.end());

	return res;
}

Result
Reader::decode(const BinaryBitmap& image) const
{
	auto result = DoDecode(_readers, image, _tryHarder, false, _isPure, 1, _minLineCount);

	if (result.empty() && _tryRotate)
		result = DoDecode(_readers, image, _tryHarder, true, _isPure, 1, _minLineCount);

	return result.empty() ? Result(DecodeStatus::NotFound) : result.front();
}

Results Reader::decode(const BinaryBitmap& image, int maxSymbols) const
{
	auto resH = DoDecode(_readers, image, _tryHarder, false, _isPure, maxSymbols, _minLineCount);
	if ((!maxSymbols || Size(resH) < maxSymbols) && _tryRotate) {
		auto resV = DoDecode(_readers, image, _tryHarder, true, _isPure, maxSymbols - Size(resH), _minLineCount);
		resH.insert(resH.end(), resV.begin(), resV.end());
	}
	return resH;
}

} // namespace ZXing::OneD
<|endoftext|>


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

#include "chrome/browser/login_prompt.h"

#include "app/l10n_util.h"
#include "base/command_line.h"
#include "base/lock.h"
#include "base/message_loop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/password_manager/password_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/browser/tab_contents/constrained_window.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
#include "grit/generated_resources.h"
#include "net/base/auth.h"
#include "net/url_request/url_request.h"

using webkit_glue::PasswordForm;

class LoginHandlerImpl;

// Helper to remove the ref from an URLRequest to the LoginHandler.
// Should only be called from the IO thread, since it accesses an URLRequest.
void ResetLoginHandlerForRequest(URLRequest* request) {
  ResourceDispatcherHostRequestInfo* info =
      ResourceDispatcherHost::InfoForRequest(request);
  if (!info)
    return;

  info->set_login_handler(NULL);
}

// Get the signon_realm under which this auth info should be stored.
//
// The format of the signon_realm for proxy auth is:
//     proxy-host/auth-realm
// The format of the signon_realm for server auth is:
//     url-scheme://url-host[:url-port]/auth-realm
//
// Be careful when changing this function, since you could make existing
// saved logins un-retrievable.
std::string GetSignonRealm(const GURL& url,
                           const net::AuthChallengeInfo& auth_info) {
  std::string signon_realm;
  if (auth_info.is_proxy) {
    signon_realm = WideToASCII(auth_info.host_and_port);
    signon_realm.append("/");
  } else {
    // Take scheme, host, and port from the url.
    signon_realm = url.GetOrigin().spec();
    // This ends with a "/".
  }
  signon_realm.append(WideToUTF8(auth_info.realm));
  return signon_realm;
}

// ----------------------------------------------------------------------------
// LoginDialogTask

// This task is run on the UI thread and creates a constrained window with
// a LoginView to prompt the user.  The response will be sent to LoginHandler,
// which then routes it to the URLRequest on the I/O thread.
class LoginDialogTask : public Task {
 public:
  LoginDialogTask(net::AuthChallengeInfo* auth_info, LoginHandler* handler)
      : auth_info_(auth_info), handler_(handler) {
  }
  virtual ~LoginDialogTask() {
  }

  void Run() {
    TabContents* parent_contents = handler_->GetTabContentsForLogin();
    if (!parent_contents) {
      // The request was probably cancelled.
      return;
    }

    // Tell the password manager to look for saved passwords.
    PasswordManager* password_manager =
        parent_contents->GetPasswordManager();
    std::vector<PasswordForm> v;
    MakeInputForPasswordManager(parent_contents->GetURL(), &v);
    password_manager->PasswordFormsSeen(v);
    handler_->SetPasswordManager(password_manager);

    std::wstring explanation = auth_info_->realm.empty() ?
        l10n_util::GetStringF(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM,
                              auth_info_->host_and_port) :
        l10n_util::GetStringF(IDS_LOGIN_DIALOG_DESCRIPTION,
                              auth_info_->host_and_port,
                              auth_info_->realm);
    handler_->BuildViewForPasswordManager(password_manager,
                                          explanation);
  }

 private:
  // Helper to create a PasswordForm and stuff it into a vector as input
  // for PasswordManager::PasswordFormsSeen, the hook into PasswordManager.
  void MakeInputForPasswordManager(
      const GURL& origin_url,
      std::vector<PasswordForm>* password_manager_input) {
    PasswordForm dialog_form;
    if (LowerCaseEqualsASCII(auth_info_->scheme, "basic")) {
      dialog_form.scheme = PasswordForm::SCHEME_BASIC;
    } else if (LowerCaseEqualsASCII(auth_info_->scheme, "digest")) {
      dialog_form.scheme = PasswordForm::SCHEME_DIGEST;
    } else {
      dialog_form.scheme = PasswordForm::SCHEME_OTHER;
    }
    if (auth_info_->is_proxy) {
      dialog_form.origin = GURL(WideToASCII(auth_info_->host_and_port));
    } else {
      dialog_form.origin = origin_url;
    }
    dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info_);
    password_manager_input->push_back(dialog_form);
    // Set the password form for the handler (by copy).
    handler_->SetPasswordForm(dialog_form);
  }

  // Info about who/where/what is asking for authentication.
  scoped_refptr<net::AuthChallengeInfo> auth_info_;

  // Where to send the authentication when obtained.
  // This is owned by the ResourceDispatcherHost that invoked us.
  LoginHandler* handler_;

  DISALLOW_EVIL_CONSTRUCTORS(LoginDialogTask);
};

// ----------------------------------------------------------------------------
// Public API

LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info,
                                URLRequest* request,
                                MessageLoop* ui_loop) {
  LoginHandler* handler = LoginHandler::Create(request, ui_loop);
  ui_loop->PostTask(FROM_HERE, new LoginDialogTask(auth_info, handler));
  return handler;
}
<commit_msg>Fix the proxy host and port string to start with http:// if it does not already. BUG=21218 TEST=none<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/login_prompt.h"

#include "app/l10n_util.h"
#include "base/command_line.h"
#include "base/lock.h"
#include "base/message_loop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/password_manager/password_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/browser/tab_contents/constrained_window.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
#include "grit/generated_resources.h"
#include "net/base/auth.h"
#include "net/url_request/url_request.h"

using webkit_glue::PasswordForm;

class LoginHandlerImpl;

// Helper to remove the ref from an URLRequest to the LoginHandler.
// Should only be called from the IO thread, since it accesses an URLRequest.
void ResetLoginHandlerForRequest(URLRequest* request) {
  ResourceDispatcherHostRequestInfo* info =
      ResourceDispatcherHost::InfoForRequest(request);
  if (!info)
    return;

  info->set_login_handler(NULL);
}

// Get the signon_realm under which this auth info should be stored.
//
// The format of the signon_realm for proxy auth is:
//     proxy-host/auth-realm
// The format of the signon_realm for server auth is:
//     url-scheme://url-host[:url-port]/auth-realm
//
// Be careful when changing this function, since you could make existing
// saved logins un-retrievable.
std::string GetSignonRealm(const GURL& url,
                           const net::AuthChallengeInfo& auth_info) {
  std::string signon_realm;
  if (auth_info.is_proxy) {
    signon_realm = WideToASCII(auth_info.host_and_port);
    signon_realm.append("/");
  } else {
    // Take scheme, host, and port from the url.
    signon_realm = url.GetOrigin().spec();
    // This ends with a "/".
  }
  signon_realm.append(WideToUTF8(auth_info.realm));
  return signon_realm;
}

// ----------------------------------------------------------------------------
// LoginDialogTask

// This task is run on the UI thread and creates a constrained window with
// a LoginView to prompt the user.  The response will be sent to LoginHandler,
// which then routes it to the URLRequest on the I/O thread.
class LoginDialogTask : public Task {
 public:
  LoginDialogTask(net::AuthChallengeInfo* auth_info, LoginHandler* handler)
      : auth_info_(auth_info), handler_(handler) {
  }
  virtual ~LoginDialogTask() {
  }

  void Run() {
    TabContents* parent_contents = handler_->GetTabContentsForLogin();
    if (!parent_contents) {
      // The request was probably cancelled.
      return;
    }

    // Tell the password manager to look for saved passwords.
    PasswordManager* password_manager =
        parent_contents->GetPasswordManager();
    std::vector<PasswordForm> v;
    MakeInputForPasswordManager(parent_contents->GetURL(), &v);
    password_manager->PasswordFormsSeen(v);
    handler_->SetPasswordManager(password_manager);

    std::wstring explanation = auth_info_->realm.empty() ?
        l10n_util::GetStringF(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM,
                              auth_info_->host_and_port) :
        l10n_util::GetStringF(IDS_LOGIN_DIALOG_DESCRIPTION,
                              auth_info_->host_and_port,
                              auth_info_->realm);
    handler_->BuildViewForPasswordManager(password_manager,
                                          explanation);
  }

 private:
  // Helper to create a PasswordForm and stuff it into a vector as input
  // for PasswordManager::PasswordFormsSeen, the hook into PasswordManager.
  void MakeInputForPasswordManager(
      const GURL& origin_url,
      std::vector<PasswordForm>* password_manager_input) {
    PasswordForm dialog_form;
    if (LowerCaseEqualsASCII(auth_info_->scheme, "basic")) {
      dialog_form.scheme = PasswordForm::SCHEME_BASIC;
    } else if (LowerCaseEqualsASCII(auth_info_->scheme, "digest")) {
      dialog_form.scheme = PasswordForm::SCHEME_DIGEST;
    } else {
      dialog_form.scheme = PasswordForm::SCHEME_OTHER;
    }
    if (auth_info_->is_proxy) {
      std::string origin = WideToASCII(auth_info_->host_and_port);
      // We don't expect this to already start with http:// or https://.
      DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0);
      origin = std::string("http://") + origin;
      dialog_form.origin = GURL(origin);
    } else {
      dialog_form.origin = origin_url;
    }
    dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info_);
    password_manager_input->push_back(dialog_form);
    // Set the password form for the handler (by copy).
    handler_->SetPasswordForm(dialog_form);
  }

  // Info about who/where/what is asking for authentication.
  scoped_refptr<net::AuthChallengeInfo> auth_info_;

  // Where to send the authentication when obtained.
  // This is owned by the ResourceDispatcherHost that invoked us.
  LoginHandler* handler_;

  DISALLOW_EVIL_CONSTRUCTORS(LoginDialogTask);
};

// ----------------------------------------------------------------------------
// Public API

LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info,
                                URLRequest* request,
                                MessageLoop* ui_loop) {
  LoginHandler* handler = LoginHandler::Create(request, ui_loop);
  ui_loop->PostTask(FROM_HERE, new LoginDialogTask(auth_info, handler));
  return handler;
}
<|endoftext|>


<commit_before>/**
 * @file Cosa/IOEvent.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2014, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_IOEVENT_HH
#define COSA_IOEVENT_HH

#include "Cosa/Types.h"
#include "Cosa/Event.hh"
#include "Cosa/IOStream.hh"

/**
 * IOEvent is an IOStream filter class that may push events when
 * data has been received and send completed. Extends a given
 * IOStream::Device class. Can be used to map an interrupt driven
 * device such as UART to event driven on completed input lines.
 * @param[in] T IOStream::Device class to filter.
 */
template <typename T>
class IOEvent : public T {
public:
  /**
   * Constuct IOEvent object for filtered stream operations.
   */
  IOEvent(Event::Handler* handler) : T(), m_handler(handler) {}

  /**
   * @override IOStream::Device<T>
   * Write character to device.
   * @param[in] c character to write.
   * @return character written or EOF(-1).
   */
  virtual int putchar(char c)
  {
    int res = T::putchar(c);
    if (c == '\n' || T::room() == 0)
      Event::push(Event::RECEIVE_COMPLETED_TYPE, m_handler, this);
    return (res);
  }

  /**
   * @override IOStream::Device<T>
   * Read character from device.
   * @return character or EOF(-1).
   */
  virtual int getchar()
  {
    int res = T::getchar();
    if (res == IOStream::EOF)
      Event::push(Event::SEND_COMPLETED_TYPE, m_handler, this);
    return (res);
  }

protected:
  Event::Handler* m_handler;
};

#endif
<commit_msg>Clean up template parameter naming.<commit_after>/**
 * @file Cosa/IOEvent.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2014, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_IOEVENT_HH
#define COSA_IOEVENT_HH

#include "Cosa/Types.h"
#include "Cosa/Event.hh"
#include "Cosa/IOStream.hh"

/**
 * IOEvent is an IOStream filter class that may push events when
 * data has been received and send completed. Extends a given
 * IOStream::Device class. Can be used to map an interrupt driven
 * device such as UART to event driven on completed input lines.
 * @param[in] DEVICE class to filter.
 */
template <typename DEVICE>
class IOEvent : public DEVICE {
public:
  /**
   * Constuct IOEvent object for filtered stream operations.
   */
  IOEvent(Event::Handler* handler) : DEVICE(), m_handler(handler) {}

  /**
   * @override IOStream::Device
   * Write character to device.
   * @param[in] c character to write.
   * @return character written or EOF(-1).
   */
  virtual int putchar(char c)
  {
    int res = DEVICE::putchar(c);
    if (c == '\n' || DEVICE::room() == 0)
      Event::push(Event::RECEIVE_COMPLETED_TYPE, m_handler, this);
    return (res);
  }

  /**
   * @override IOStream::Device
   * Read character from device.
   * @return character or EOF(-1).
   */
  virtual int getchar()
  {
    int res = DEVICE::getchar();
    if (res == IOStream::EOF)
      Event::push(Event::SEND_COMPLETED_TYPE, m_handler, this);
    return (res);
  }

protected:
  Event::Handler* m_handler;
};

#endif
<|endoftext|>


<commit_before>#include "Clock.hpp"

#include <iostream>
#include <ctime>

Clock::Clock()
{

}

Clock::~Clock()
{
}

void Clock::start()
{
    m_window.create(sf::VideoMode(200, 200), "SFML Analog Clock", sf::Style::Close);
    m_window.setFramerateLimit(30);

    if(!m_textureSFML.loadFromFile("SFML.png")) {
        std::cerr << "Cannot load SFML.png" << std::endl;
    }

    sf::Event event;
    while(m_window.isOpen()) {
        while(m_window.pollEvent(event)) {
            if(event.type == sf::Event::Closed) {
                m_window.close();
            }
        }

        m_window.clear(sf::Color(0, 0, 50, 255));
        drawClockFrame();
        drawTimeIndicator();

        m_window.display();
    }
}

void Clock::drawClockFrame()
{
    sf::CircleShape circle(100);
    circle.setFillColor(sf::Color(200, 200, 212));
    circle.setOutlineColor(sf::Color(180, 180, 200));
    circle.setOutlineThickness(-12.0f);

    m_window.draw(circle);

    sf::RectangleShape rectangle(sf::Vector2f(4, 6));
    rectangle.setFillColor(sf::Color(128, 128, 168));
    rectangle.setOrigin(2, 0);

    circle.setPointCount(3);
    circle.setOutlineThickness(0);

    for(size_t i=0; i<12; i++) {
        if(i % 3) {
            rectangle.setPosition(100.0f + sin(i * 30.0f / 180.0f * 3.14159f) * 74.0f, 100.0f - cos(i * 30.0f / 180.0f * 3.14159f) * 74.0f);
            rectangle.setRotation(30.0f * i);
            m_window.draw(rectangle);
        }
        else {
            circle.setRadius(10.0f);
            circle.setOrigin(8.66f, 8.66f);
            circle.setFillColor(sf::Color(80, 88, 120));
            circle.setRotation(180.0f + 30.0f * i);
            circle.setPosition(100.0f + sin(i*30.0f/180.0f*3.14159f) * 74.0f, 100.0f - cos(i*30.0f/180.0f*3.14159f) * 74.0f);
            m_window.draw(circle);
        }

    }

    if(m_textureSFML.getSize().x != 0) {
        sf::Sprite sprite;
        sprite.setTexture(m_textureSFML);
        sprite.scale(0.3f, 0.3f);
        sf::FloatRect rect = sprite.getGlobalBounds();
        float width = rect.width;
        float height = rect.height;
        sprite.setPosition(100.0f-width/2.0f, 160.0f-height);

        m_window.draw(sprite);
    }

}

void Clock::drawTimeIndicator()
{
    std::time_t time_now;
    std::time(&time_now);
    std::tm* timemark = std::localtime(&time_now);

    int hour = timemark->tm_hour;
    if(hour >= 12) {
        hour -= 12;
    }

    int minute = timemark->tm_min;
    int second = timemark->tm_sec;

    sf::RectangleShape rectangle;
    rectangle.setSize(sf::Vector2f(10, 60));
    rectangle.setFillColor(sf::Color(166, 166, 180));
    rectangle.setOrigin(5, 60);
    rectangle.setRotation(hour * 30.0f + minute * 0.5f);
    rectangle.setPosition(100, 100);
    m_window.draw(rectangle);

    rectangle.setSize(sf::Vector2f(6, 75));
    rectangle.setFillColor(sf::Color(120, 120, 160));
    rectangle.setOrigin(3, 75);
    rectangle.setRotation(minute * 6.0f);
    m_window.draw(rectangle);

    rectangle.setSize(sf::Vector2f(2, 80));
    rectangle.setFillColor(sf::Color(36, 36, 36));
    rectangle.setOrigin(1, 80);
    rectangle.setRotation(second * 6.0f);
    m_window.draw(rectangle);

    sf::CircleShape circle(8);
    circle.setFillColor(sf::Color(33, 33, 57));
    circle.setOrigin(4.0f, 4.0f);
    circle.setPosition(96, 96);
    m_window.draw(circle);

    if(m_textureSFML.getSize().x != 0) {
        sf::Sprite sprite;
        sprite.setTexture(m_textureSFML);
        sf::FloatRect localRect = sprite.getLocalBounds();
        float localWidth = localRect.width;
        float localHeight = localRect.height;
        sprite.setOrigin(localHeight/2.0f, localHeight/2.0f);

        sprite.scale(0.2f, 0.2f);
        sf::FloatRect rect = sprite.getGlobalBounds();
        float width = rect.width;
        float height = rect.height;

        sprite.setRotation(second * 6.0f);
        sprite.setPosition(100.0f, 100.0f);
        m_window.draw(sprite);
    }

}
<commit_msg>Revise to remove unused variables for preventing warnings.<commit_after>#include "Clock.hpp"

#include <iostream>
#include <ctime>

Clock::Clock()
{

}

Clock::~Clock()
{
}

void Clock::start()
{
    m_window.create(sf::VideoMode(200, 200), "SFML Analog Clock", sf::Style::Close);
    m_window.setFramerateLimit(30);

    if(!m_textureSFML.loadFromFile("SFML.png")) {
        std::cerr << "Cannot load SFML.png" << std::endl;
    }

    sf::Event event;
    while(m_window.isOpen()) {
        while(m_window.pollEvent(event)) {
            if(event.type == sf::Event::Closed) {
                m_window.close();
            }
        }

        m_window.clear(sf::Color(0, 0, 50, 255));
        drawClockFrame();
        drawTimeIndicator();

        m_window.display();
    }
}

void Clock::drawClockFrame()
{
    sf::CircleShape circle(100);
    circle.setFillColor(sf::Color(200, 200, 212));
    circle.setOutlineColor(sf::Color(180, 180, 200));
    circle.setOutlineThickness(-12.0f);

    m_window.draw(circle);

    sf::RectangleShape rectangle(sf::Vector2f(4, 6));
    rectangle.setFillColor(sf::Color(128, 128, 168));
    rectangle.setOrigin(2, 0);

    circle.setPointCount(3);
    circle.setOutlineThickness(0);

    for(size_t i=0; i<12; i++) {
        if(i % 3) {
            rectangle.setPosition(100.0f + sin(i * 30.0f / 180.0f * 3.14159f) * 74.0f, 100.0f - cos(i * 30.0f / 180.0f * 3.14159f) * 74.0f);
            rectangle.setRotation(30.0f * i);
            m_window.draw(rectangle);
        }
        else {
            circle.setRadius(10.0f);
            circle.setOrigin(8.66f, 8.66f);
            circle.setFillColor(sf::Color(80, 88, 120));
            circle.setRotation(180.0f + 30.0f * i);
            circle.setPosition(100.0f + sin(i*30.0f/180.0f*3.14159f) * 74.0f, 100.0f - cos(i*30.0f/180.0f*3.14159f) * 74.0f);
            m_window.draw(circle);
        }

    }

    if(m_textureSFML.getSize().x != 0) {
        sf::Sprite sprite;
        sprite.setTexture(m_textureSFML);
        sprite.scale(0.3f, 0.3f);
        sf::FloatRect rect = sprite.getGlobalBounds();
        float width = rect.width;
        float height = rect.height;
        sprite.setPosition(100.0f-width/2.0f, 160.0f-height);

        m_window.draw(sprite);
    }

}

void Clock::drawTimeIndicator()
{
    std::time_t time_now;
    std::time(&time_now);
    std::tm* timemark = std::localtime(&time_now);

    int hour = timemark->tm_hour;
    if(hour >= 12) {
        hour -= 12;
    }

    int minute = timemark->tm_min;
    int second = timemark->tm_sec;

    sf::RectangleShape rectangle;
    rectangle.setSize(sf::Vector2f(10, 60));
    rectangle.setFillColor(sf::Color(166, 166, 180));
    rectangle.setOrigin(5, 60);
    rectangle.setRotation(hour * 30.0f + minute * 0.5f);
    rectangle.setPosition(100, 100);
    m_window.draw(rectangle);

    rectangle.setSize(sf::Vector2f(6, 75));
    rectangle.setFillColor(sf::Color(120, 120, 160));
    rectangle.setOrigin(3, 75);
    rectangle.setRotation(minute * 6.0f);
    m_window.draw(rectangle);

    rectangle.setSize(sf::Vector2f(2, 80));
    rectangle.setFillColor(sf::Color(36, 36, 36));
    rectangle.setOrigin(1, 80);
    rectangle.setRotation(second * 6.0f);
    m_window.draw(rectangle);

    sf::CircleShape circle(8);
    circle.setFillColor(sf::Color(33, 33, 57));
    circle.setOrigin(4.0f, 4.0f);
    circle.setPosition(96, 96);
    m_window.draw(circle);

    if(m_textureSFML.getSize().x != 0) {
        sf::Sprite sprite;
        sprite.setTexture(m_textureSFML);
        sf::FloatRect localRect = sprite.getLocalBounds();
        float localWidth = localRect.width;
        float localHeight = localRect.height;
        sprite.setOrigin(localWidth/2.0f, localHeight/2.0f);

        sprite.scale(0.2f, 0.2f);

        sprite.setRotation(second * 6.0f);
        sprite.setPosition(100.0f, 100.0f);
        m_window.draw(sprite);
    }

}
<|endoftext|>


<commit_before>/*********************************************************/
/* class TEXTE_PCB : texts on copper or technical layers */
/*********************************************************/

#include "fctsys.h"
#include "wxstruct.h"
#include "gr_basic.h"
#include "common.h"
#include "kicad_string.h"

#include "pcbnew.h"

/*******************/
/* class TEXTE_PCB */
/*******************/

TEXTE_PCB::TEXTE_PCB( BOARD_ITEM* parent ) :
    BOARD_ITEM( parent, TYPE_TEXTE ),
    EDA_TextStruct()
{
    m_MultilineAllowed = true;
}

/* Destructeur */
TEXTE_PCB:: ~TEXTE_PCB()
{
}

/* copie de stucture */
void TEXTE_PCB::Copy( TEXTE_PCB* source )
{
    m_Parent    = source->m_Parent;
    Pback       = Pnext = NULL;
    m_Mirror    = source->m_Mirror;
    m_Size      = source->m_Size;
    m_Orient    = source->m_Orient;
    m_Pos       = source->m_Pos;
    m_Layer     = source->m_Layer;
    m_Width     = source->m_Width;
    m_Attributs = source->m_Attributs;
    m_Italic    = source->m_Italic;
    m_HJustify  = source->m_HJustify;
    m_VJustify  = source->m_VJustify;
    m_MultilineAllowed = m_MultilineAllowed;

    m_Text = source->m_Text;
}

/****************************************************************/
int TEXTE_PCB::ReadTextePcbDescr( FILE* File, int* LineNum )
/****************************************************************/

/** Function ReadTextePcbDescr
 *  Read a pcb text description
 *  The format is like:
 *  $TEXTPCB
 *  Te "Text example"
 *  Po 66750 53450 600 800 150 0
 *  De 24 1 0 Italic
 *  $EndTEXTPCB
 *  for a single line text
 *
 *  or
 *
 *  $TEXTPCB
 *  Te "Text example"
 *  nl "ligne 2"
 *  Po 66750 53450 600 800 150 0
 *  De 24 1 0 Italic
 *  $EndTEXTPCB
 *  for a multi line text
 *  nl "ligne nn"   is a line added to the current text
 */
{
    char text[1024], Line[1024];
    char style[256];

    while( GetLine( File, Line, LineNum ) != NULL )
    {
        if( strnicmp( Line, "$EndTEXTPCB", 11 ) == 0 )
            return 0;
        if( strncmp( Line, "Te", 2 ) == 0 ) /* Text line (first line for multi line texts */
        {
            ReadDelimitedText( text, Line + 2, sizeof(text) );
            m_Text = CONV_FROM_UTF8( text );
            continue;
        }
        if( strncmp( Line, "nl", 2 ) == 0 ) /* next line of the current text */
        {
            ReadDelimitedText( text, Line + 2, sizeof(text) );
            m_Text.Append( '\n' );
            m_Text += CONV_FROM_UTF8( text );
            continue;
        }
        if( strncmp( Line, "Po", 2 ) == 0 )
        {
            sscanf( Line + 2, " %d %d %d %d %d %d",
                    &m_Pos.x, &m_Pos.y, &m_Size.x, &m_Size.y,
                    &m_Width, &m_Orient );

            // Ensure the text has minimal size to see this text on screen:
            if( m_Size.x < 5 )
                m_Size.x = 5;
            if( m_Size.y < 5 )
                m_Size.y = 5;
            continue;
        }
        if( strncmp( Line, "De", 2 ) == 0 )
        {
            style[0] = 0;
            int normal_display = 1;
            sscanf( Line + 2, " %d %d %lX %s\n", &m_Layer, &normal_display,
                    &m_TimeStamp, style );

            m_Mirror = normal_display ? false : true;

            if( m_Layer < FIRST_COPPER_LAYER )
                m_Layer = FIRST_COPPER_LAYER;
            if( m_Layer > LAST_NO_COPPER_LAYER )
                m_Layer = LAST_NO_COPPER_LAYER;

            if( strnicmp( style, "Italic", 6 ) == 0 )
                m_Italic = 1;
            else
                m_Italic = 0;
            continue;
        }
    }

    return 1;
}

/*****************************************/
bool TEXTE_PCB::Save( FILE* aFile ) const
/*****************************************/
{
    if( GetState( DELETED ) )
        return true;

    if( m_Text.IsEmpty() )
        return true;

    if( fprintf( aFile, "$TEXTPCB\n" ) != sizeof("$TEXTPCB\n") - 1 )
        return false;

    const char* style = m_Italic ? "Italic" : "Normal";

    wxArrayString* list = wxStringSplit( m_Text, '\n' );
    for( unsigned ii = 0; ii < list->Count(); ii++ )
    {
        wxString txt  = list->Item( ii );
        if ( ii == 0 )
            fprintf( aFile, "Te \"%s\"\n", CONV_TO_UTF8( txt ) );
        else
            fprintf( aFile, "nl \"%s\"\n", CONV_TO_UTF8( txt ) );
    }
    delete (list);

    fprintf( aFile, "Po %d %d %d %d %d %d\n",
             m_Pos.x, m_Pos.y, m_Size.x, m_Size.y, m_Width, m_Orient );
    fprintf( aFile, "De %d %d %lX %s\n", m_Layer,
             m_Mirror ? 0 : 1,
             m_TimeStamp, style );

    if( fprintf( aFile, "$EndTEXTPCB\n" ) != sizeof("$EndTEXTPCB\n") - 1 )
        return false;

    return true;
}

/**********************************************************************/
void TEXTE_PCB::Draw( WinEDA_DrawPanel* panel, wxDC* DC,
                      int DrawMode, const wxPoint& offset )
/**********************************************************************/

/*
 *  DrawMode = GR_OR, GR_XOR.., -1 si mode courant.
 */
{
    int color = g_DesignSettings.m_LayerColor[m_Layer];

    if( color & ITEM_NOT_SHOW )
        return;

    EDA_TextStruct::Draw(
        panel,
        DC,
        offset,
        (EDA_Colors) color,
        DrawMode,
        (GRFillMode) DisplayOpt.DisplayDrawItems,
        (g_AnchorColor &
         ITEM_NOT_SHOW) ? UNSPECIFIED_COLOR : (EDA_Colors) g_AnchorColor );
}

// see class_pcb_text.h
void TEXTE_PCB::DisplayInfo( WinEDA_DrawFrame* frame )
{
    wxString    msg;

    BOARD*      board;
    BOARD_ITEM* parent = (BOARD_ITEM*) m_Parent;

    wxASSERT( parent );

    if( parent->Type() == TYPE_COTATION )
        board = (BOARD*) parent->GetParent();
    else
        board = (BOARD*) parent;
    wxASSERT( board );

    frame->MsgPanel->EraseMsgBox();

    if( m_Parent && m_Parent->Type() == TYPE_COTATION )
        Affiche_1_Parametre( frame, 1, _( "COTATION" ), m_Text, DARKGREEN );
    else
        Affiche_1_Parametre( frame, 1, _( "PCB Text" ), m_Text, DARKGREEN );

    Affiche_1_Parametre( frame, 28, _( "Layer" ),
                         board->GetLayerName( m_Layer ),
                         g_DesignSettings.m_LayerColor[m_Layer] & MASKCOLOR );

    Affiche_1_Parametre( frame, 36, _( "Mirror" ), wxEmptyString, GREEN );
    if( !m_Mirror )
        Affiche_1_Parametre( frame, -1, wxEmptyString, _( "No" ), DARKGREEN );
    else
        Affiche_1_Parametre( frame, -1, wxEmptyString, _( "Yes" ), DARKGREEN );

    msg.Printf( wxT( "%.1f" ), (float) m_Orient / 10 );
    Affiche_1_Parametre( frame, 43, _( "Orient" ), msg, DARKGREEN );

    valeur_param( m_Width, msg );
    Affiche_1_Parametre( frame, 50, _( "Width" ), msg, MAGENTA );

    valeur_param( m_Size.x, msg );
    Affiche_1_Parametre( frame, 60, _( "H Size" ), msg, RED );

    valeur_param( m_Size.y, msg );
    Affiche_1_Parametre( frame, 70, _( "V Size" ), msg, RED );
}

#if defined(DEBUG)

/**
 * Function Show
 * is used to output the object tree, currently for debugging only.
 * @param nestLevel An aid to prettier tree indenting, and is the level
 *          of nesting of this object within the overall tree.
 * @param os The ostream& to output to.
 */
void TEXTE_PCB::Show( int nestLevel, std::ostream& os )
{
    // for now, make it look like XML:
    NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
    " string=\"" << m_Text.mb_str() << "\"/>\n";

//    NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
}

#endif
<commit_msg>Rework on TEXTE_PCB, SCH_TEXT and EDA_TextStruct classes. Code seriously cleaned, obscure and duplicated code removed, and some oddities removed. Better support of multiline texts.<commit_after>/*********************************************************/
/* class TEXTE_PCB : texts on copper or technical layers */
/*********************************************************/

#include "fctsys.h"
#include "wxstruct.h"
#include "gr_basic.h"
#include "common.h"
#include "kicad_string.h"

#include "pcbnew.h"

/*******************/
/* class TEXTE_PCB */
/*******************/

TEXTE_PCB::TEXTE_PCB( BOARD_ITEM* parent ) :
    BOARD_ITEM( parent, TYPE_TEXTE ),
    EDA_TextStruct()
{
    m_MultilineAllowed = true;
}

/* Destructeur */
TEXTE_PCB:: ~TEXTE_PCB()
{
}

/* copie de stucture */
void TEXTE_PCB::Copy( TEXTE_PCB* source )
{
    m_Parent    = source->m_Parent;
    Pback       = Pnext = NULL;
    m_Mirror    = source->m_Mirror;
    m_Size      = source->m_Size;
    m_Orient    = source->m_Orient;
    m_Pos       = source->m_Pos;
    m_Layer     = source->m_Layer;
    m_Width     = source->m_Width;
    m_Attributs = source->m_Attributs;
    m_Italic    = source->m_Italic;
    m_HJustify  = source->m_HJustify;
    m_VJustify  = source->m_VJustify;
    m_MultilineAllowed = m_MultilineAllowed;

    m_Text = source->m_Text;
}

/****************************************************************/
int TEXTE_PCB::ReadTextePcbDescr( FILE* File, int* LineNum )
/****************************************************************/

/** Function ReadTextePcbDescr
 *  Read a pcb text description
 *  The format is like:
 *  $TEXTPCB
 *  Te "Text example"
 *  Po 66750 53450 600 800 150 0
 *  De 24 1 0 Italic
 *  $EndTEXTPCB
 *  for a single line text
 *
 *  or
 *
 *  $TEXTPCB
 *  Te "Text example"
 *  nl "ligne 2"
 *  Po 66750 53450 600 800 150 0
 *  De 24 1 0 Italic
 *  $EndTEXTPCB
 *  for a multi line text
 *  nl "ligne nn"   is a line added to the current text
 */
{
    char text[1024], Line[1024];
    char style[256];

    while( GetLine( File, Line, LineNum ) != NULL )
    {
        if( strnicmp( Line, "$EndTEXTPCB", 11 ) == 0 )
            return 0;
        if( strncmp( Line, "Te", 2 ) == 0 ) /* Text line (first line for multi line texts */
        {
            ReadDelimitedText( text, Line + 2, sizeof(text) );
            m_Text = CONV_FROM_UTF8( text );
            continue;
        }
        if( strncmp( Line, "nl", 2 ) == 0 ) /* next line of the current text */
        {
            ReadDelimitedText( text, Line + 2, sizeof(text) );
            m_Text.Append( '\n' );
            m_Text += CONV_FROM_UTF8( text );
            continue;
        }
        if( strncmp( Line, "Po", 2 ) == 0 )
        {
            sscanf( Line + 2, " %d %d %d %d %d %d",
                    &m_Pos.x, &m_Pos.y, &m_Size.x, &m_Size.y,
                    &m_Width, &m_Orient );

            // Ensure the text has minimal size to see this text on screen:
            if( m_Size.x < 5 )
                m_Size.x = 5;
            if( m_Size.y < 5 )
                m_Size.y = 5;
            continue;
        }
        if( strncmp( Line, "De", 2 ) == 0 )
        {
            style[0] = 0;
            int normal_display = 1;
            sscanf( Line + 2, " %d %d %lX %s\n", &m_Layer, &normal_display,
                    &m_TimeStamp, style );

            m_Mirror = normal_display ? false : true;

            if( m_Layer < FIRST_COPPER_LAYER )
                m_Layer = FIRST_COPPER_LAYER;
            if( m_Layer > LAST_NO_COPPER_LAYER )
                m_Layer = LAST_NO_COPPER_LAYER;

            if( strnicmp( style, "Italic", 6 ) == 0 )
                m_Italic = 1;
            else
                m_Italic = 0;
            continue;
        }
    }

    return 1;
}

/*****************************************/
bool TEXTE_PCB::Save( FILE* aFile ) const
/*****************************************/
{
    if( GetState( DELETED ) )
        return true;

    if( m_Text.IsEmpty() )
        return true;

    if( fprintf( aFile, "$TEXTPCB\n" ) != sizeof("$TEXTPCB\n") - 1 )
        return false;

    const char* style = m_Italic ? "Italic" : "Normal";

    wxArrayString* list = wxStringSplit( m_Text, '\n' );
    for( unsigned ii = 0; ii < list->Count(); ii++ )
    {
        wxString txt  = list->Item( ii );
        if ( ii == 0 )
            fprintf( aFile, "Te \"%s\"\n", CONV_TO_UTF8( txt ) );
        else
            fprintf( aFile, "nl \"%s\"\n", CONV_TO_UTF8( txt ) );
    }
    delete (list);

    fprintf( aFile, "Po %d %d %d %d %d %d\n",
             m_Pos.x, m_Pos.y, m_Size.x, m_Size.y, m_Width, m_Orient );
    fprintf( aFile, "De %d %d %lX %s\n", m_Layer,
             m_Mirror ? 0 : 1,
             m_TimeStamp, style );

    if( fprintf( aFile, "$EndTEXTPCB\n" ) != sizeof("$EndTEXTPCB\n") - 1 )
        return false;

    return true;
}

/**********************************************************************/
void TEXTE_PCB::Draw( WinEDA_DrawPanel* panel, wxDC* DC,
                      int DrawMode, const wxPoint& offset )
/**********************************************************************/

/** Function Draw
 *  DrawMode = GR_OR, GR_XOR ..
 * Like tracks, texts are drawn in filled or sketch mode, never in line mode
 * because the line mode does not keep the actual size of the text
 * and the actual size is very important, especially for copper texts
 */
{
    int color = g_DesignSettings.m_LayerColor[m_Layer];

    if( color & ITEM_NOT_SHOW )
        return;

    GRFillMode fillmode = FILLED;
    if ( DisplayOpt.DisplayDrawItems == SKETCH)
        GRFillMode fillmode = SKETCH;

    EDA_TextStruct::Draw(
        panel, DC,
        offset,
        (EDA_Colors) color,
        DrawMode, fillmode,
        (g_AnchorColor & ITEM_NOT_SHOW) ? UNSPECIFIED_COLOR : (EDA_Colors) g_AnchorColor );
}

// see class_pcb_text.h
void TEXTE_PCB::DisplayInfo( WinEDA_DrawFrame* frame )
{
    wxString    msg;

    BOARD*      board;
    BOARD_ITEM* parent = (BOARD_ITEM*) m_Parent;

    wxASSERT( parent );

    if( parent->Type() == TYPE_COTATION )
        board = (BOARD*) parent->GetParent();
    else
        board = (BOARD*) parent;
    wxASSERT( board );

    frame->MsgPanel->EraseMsgBox();

    if( m_Parent && m_Parent->Type() == TYPE_COTATION )
        Affiche_1_Parametre( frame, 1, _( "COTATION" ), m_Text, DARKGREEN );
    else
        Affiche_1_Parametre( frame, 1, _( "PCB Text" ), m_Text, DARKGREEN );

    Affiche_1_Parametre( frame, 28, _( "Layer" ),
                         board->GetLayerName( m_Layer ),
                         g_DesignSettings.m_LayerColor[m_Layer] & MASKCOLOR );

    Affiche_1_Parametre( frame, 36, _( "Mirror" ), wxEmptyString, GREEN );
    if( !m_Mirror )
        Affiche_1_Parametre( frame, -1, wxEmptyString, _( "No" ), DARKGREEN );
    else
        Affiche_1_Parametre( frame, -1, wxEmptyString, _( "Yes" ), DARKGREEN );

    msg.Printf( wxT( "%.1f" ), (float) m_Orient / 10 );
    Affiche_1_Parametre( frame, 43, _( "Orient" ), msg, DARKGREEN );

    valeur_param( m_Width, msg );
    Affiche_1_Parametre( frame, 50, _( "Width" ), msg, MAGENTA );

    valeur_param( m_Size.x, msg );
    Affiche_1_Parametre( frame, 60, _( "H Size" ), msg, RED );

    valeur_param( m_Size.y, msg );
    Affiche_1_Parametre( frame, 70, _( "V Size" ), msg, RED );
}

#if defined(DEBUG)

/**
 * Function Show
 * is used to output the object tree, currently for debugging only.
 * @param nestLevel An aid to prettier tree indenting, and is the level
 *          of nesting of this object within the overall tree.
 * @param os The ostream& to output to.
 */
void TEXTE_PCB::Show( int nestLevel, std::ostream& os )
{
    // for now, make it look like XML:
    NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
    " string=\"" << m_Text.mb_str() << "\"/>\n";

//    NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
}

#endif
<|endoftext|>