<commit_before>/*

Copyright 2015-2021 Igor Petrovic

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 <cstddef>
#include <stdio.h>
#include <stdlib.h>
#include <avr/power.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include "board/Board.h"
#include "board/Internal.h"
#include "board/common/io/Helpers.h"
#include "core/src/general/ADC.h"
#include "core/src/arch/avr/Misc.h"
#include "core/src/general/IO.h"
#include "core/src/general/Interrupt.h"
#include "core/src/general/Timing.h"
#include "Pins.h"

extern "C" void __cxa_pure_virtual()
{
    Board::detail::errorHandler();
}

void* operator new(std::size_t size)
{
    return malloc(size);
}

void operator delete(void* ptr)
{
}

namespace std
{
    void __throw_bad_function_call()
    {
        Board::detail::errorHandler();
    }

    void __throw_bad_alloc()
    {
        Board::detail::errorHandler();
    }
}    // namespace std

namespace Board
{
    namespace detail
    {
        namespace setup
        {
            void bootloader()
            {
                DISABLE_INTERRUPTS();

                //clear reset source
                MCUSR &= ~(1 << EXTRF);

                //disable watchdog
                MCUSR &= ~(1 << WDRF);
                wdt_disable();

                //disable clock division
                clock_prescale_set(clock_div_1);

                detail::setup::io();

                //relocate the interrupt vector table to the bootloader section
                MCUCR = (1 << IVCE);
                MCUCR = (1 << IVSEL);

                ENABLE_INTERRUPTS();

#if defined(USB_LINK_MCU) || !defined(USB_MIDI_SUPPORTED)
                Board::UART::init(UART_CHANNEL_USB_LINK, UART_BAUDRATE_MIDI_OD);
#endif
            }

            void application()
            {
                DISABLE_INTERRUPTS();

                //relocate the interrupt vector table to the application section
                MCUCR = (1 << IVCE);
                MCUCR = (0 << IVSEL);

                //clear reset source
                MCUSR &= ~(1 << EXTRF);

                //disable watchdog
                MCUSR &= ~(1 << WDRF);
                wdt_disable();

                //disable clock division
                clock_prescale_set(clock_div_1);

                detail::setup::io();
                detail::setup::adc();

#if defined(USB_LINK_MCU) || !defined(USB_MIDI_SUPPORTED)
                Board::UART::init(UART_CHANNEL_USB_LINK, UART_BAUDRATE_MIDI_OD);
#endif

                detail::setup::usb();
                detail::setup::timers();

                ENABLE_INTERRUPTS();

#ifndef USB_LINK_MCU
                //add some delay and remove initial readout of digital inputs
                core::timing::waitMs(10);
                detail::io::flushInputReadings();
#endif
            }

#ifdef ANALOG_SUPPORTED
            void adc()
            {
                core::adc::conf_t adcConfiguration;

                adcConfiguration.prescaler = core::adc::prescaler_t::p128;

#ifdef ADC_EXT_REF
                adcConfiguration.vref = core::adc::vRef_t::aref;
#else
                adcConfiguration.vref = core::adc::vRef_t::avcc;
#endif

                for (int i = 0; i < MAX_ADC_CHANNELS; i++)
                    core::adc::disconnectDigitalIn(Board::detail::map::adcChannel(i));

                core::adc::setup(adcConfiguration);
                core::adc::setChannel(Board::detail::map::adcChannel(0));

                for (int i = 0; i < 3; i++)
                    core::adc::read();    //few dummy reads to init ADC

                core::adc::enableInterrupt();
                core::adc::startConversion();
            }
#endif

            void timers()
            {
                //set timer0 to ctc, used for millis/led matrix
                //clear timer0 conf
                TCCR0A = 0;
                TCCR0B = 0;
                TIMSK0 = 0;
                TCCR0A |= (1 << WGM01);                 //CTC mode
                TCCR0B |= (1 << CS01) | (1 << CS00);    //prescaler 64
                OCR0A = 249;                            //1ms
                TIMSK0 |= (1 << OCIE0A);                //compare match interrupt

                //use timer1 for soft pwm
                TCCR1A = 0;
                TCCR1B = 0;
                TCCR1C = 0;

                TIMSK1 = 0;
                TCCR1B |= (1 << WGM12);                 //CTC mode
                TCCR1B |= (1 << CS11) | (1 << CS10);    //prescaler 64
                OCR1A = 124;                            //500us
                TIMSK1 |= (1 << OCIE1A);                //compare match interrupt
            }

            void io()
            {
#ifdef NUMBER_OF_IN_SR
                CORE_IO_CONFIG(SR_IN_DATA_PORT, SR_IN_DATA_PIN, core::io::pinMode_t::input);
                CORE_IO_CONFIG(SR_IN_CLK_PORT, SR_IN_CLK_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(SR_IN_LATCH_PORT, SR_IN_LATCH_PIN, core::io::pinMode_t::output);

                CORE_IO_SET_LOW(SR_IN_CLK_PORT, SR_IN_CLK_PIN);
                CORE_IO_SET_HIGH(SR_IN_LATCH_PORT, SR_IN_LATCH_PIN);
#else
                for (int i = 0; i < MAX_NUMBER_OF_BUTTONS; i++)
                {
                    core::io::mcuPin_t pin = detail::map::buttonPin(i);

                    CORE_IO_CONFIG(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), core::io::pinMode_t::input);

#ifndef BUTTONS_EXT_PULLUPS
                    CORE_IO_SET_HIGH(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin));
#endif
                }
#endif

#ifdef NUMBER_OF_BUTTON_COLUMNS
                CORE_IO_CONFIG(DEC_BM_PORT_A0, DEC_BM_PIN_A0, core::io::pinMode_t::output);
                CORE_IO_CONFIG(DEC_BM_PORT_A1, DEC_BM_PIN_A1, core::io::pinMode_t::output);
                CORE_IO_CONFIG(DEC_BM_PORT_A2, DEC_BM_PIN_A2, core::io::pinMode_t::output);

                CORE_IO_SET_LOW(DEC_BM_PORT_A0, DEC_BM_PIN_A0);
                CORE_IO_SET_LOW(DEC_BM_PORT_A1, DEC_BM_PIN_A1);
                CORE_IO_SET_LOW(DEC_BM_PORT_A2, DEC_BM_PIN_A2);
#endif

#ifdef NUMBER_OF_OUT_SR
                CORE_IO_CONFIG(SR_OUT_DATA_PORT, SR_OUT_DATA_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(SR_OUT_CLK_PORT, SR_OUT_CLK_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(SR_OUT_LATCH_PORT, SR_OUT_LATCH_PIN, core::io::pinMode_t::output);

#ifdef SR_OUT_OE_PORT
                CORE_IO_CONFIG(SR_OUT_OE_PORT, SR_OUT_OE_PIN, core::io::pinMode_t::output);
#endif

                //init all outputs on shift register
                CORE_IO_SET_LOW(SR_OUT_LATCH_PORT, SR_OUT_LATCH_PIN);

                for (int i = 0; i < MAX_NUMBER_OF_LEDS; i++)
                {
                    EXT_LED_OFF(SR_OUT_DATA_PORT, SR_OUT_DATA_PIN);
                    CORE_IO_SET_HIGH(SR_OUT_CLK_PORT, SR_OUT_CLK_PIN);
                    detail::io::sr595wait();
                    CORE_IO_SET_LOW(SR_OUT_CLK_PORT, SR_OUT_CLK_PIN);
                }

                CORE_IO_SET_HIGH(SR_OUT_LATCH_PORT, SR_OUT_LATCH_PIN);
#ifdef SR_OUT_OE_PORT
                CORE_IO_SET_LOW(SR_OUT_OE_PORT, SR_OUT_OE_PIN);
#endif
#else
#ifdef NUMBER_OF_LED_ROWS
                CORE_IO_CONFIG(DEC_LM_PORT_A0, DEC_LM_PIN_A0, core::io::pinMode_t::output);
                CORE_IO_CONFIG(DEC_LM_PORT_A1, DEC_LM_PIN_A1, core::io::pinMode_t::output);
                CORE_IO_CONFIG(DEC_LM_PORT_A2, DEC_LM_PIN_A2, core::io::pinMode_t::output);

                CORE_IO_SET_LOW(DEC_LM_PORT_A0, DEC_LM_PIN_A0);
                CORE_IO_SET_LOW(DEC_LM_PORT_A1, DEC_LM_PIN_A1);
                CORE_IO_SET_LOW(DEC_LM_PORT_A2, DEC_LM_PIN_A2);

                for (int i = 0; i < NUMBER_OF_LED_ROWS; i++)
#else
                for (int i = 0; i < MAX_NUMBER_OF_LEDS; i++)
#endif
                {
                    core::io::mcuPin_t pin = detail::map::ledPin(i);

                    CORE_IO_CONFIG(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), core::io::pinMode_t::output);
                    EXT_LED_OFF(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin));
                }
#endif

#if MAX_ADC_CHANNELS > 0
                for (int i = 0; i < MAX_ADC_CHANNELS; i++)
                {
                    core::io::mcuPin_t pin = detail::map::adcPin(i);

                    CORE_IO_CONFIG(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), core::io::pinMode_t::input);
                    CORE_IO_SET_LOW(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin));
                }
#endif

#ifdef NUMBER_OF_MUX
                CORE_IO_CONFIG(MUX_PORT_S0, MUX_PIN_S0, core::io::pinMode_t::output);
                CORE_IO_CONFIG(MUX_PORT_S1, MUX_PIN_S1, core::io::pinMode_t::output);
                CORE_IO_CONFIG(MUX_PORT_S2, MUX_PIN_S2, core::io::pinMode_t::output);
#ifdef MUX_PORT_S3
                CORE_IO_CONFIG(MUX_PORT_S3, MUX_PIN_S3, core::io::pinMode_t::output);
#endif
#endif

#ifdef BTLDR_BUTTON_PORT
                CORE_IO_CONFIG(BTLDR_BUTTON_PORT, BTLDR_BUTTON_PIN, core::io::pinMode_t::input);
                CORE_IO_SET_HIGH(BTLDR_BUTTON_PORT, BTLDR_BUTTON_PIN);
#endif

#ifdef LED_INDICATORS
                CORE_IO_CONFIG(LED_MIDI_IN_DIN_PORT, LED_MIDI_IN_DIN_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(LED_MIDI_OUT_DIN_PORT, LED_MIDI_OUT_DIN_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(LED_MIDI_IN_USB_PORT, LED_MIDI_IN_USB_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(LED_MIDI_OUT_USB_PORT, LED_MIDI_OUT_USB_PIN, core::io::pinMode_t::output);

                INT_LED_OFF(LED_MIDI_IN_DIN_PORT, LED_MIDI_IN_DIN_PIN);
                INT_LED_OFF(LED_MIDI_OUT_DIN_PORT, LED_MIDI_OUT_DIN_PIN);
                INT_LED_OFF(LED_MIDI_IN_USB_PORT, LED_MIDI_IN_USB_PIN);
                INT_LED_OFF(LED_MIDI_OUT_USB_PORT, LED_MIDI_OUT_USB_PIN);
#endif

#ifdef LED_BTLDR_PORT
                CORE_IO_CONFIG(LED_BTLDR_PORT, LED_BTLDR_PIN, core::io::pinMode_t::output);
                CORE_IO_SET_HIGH(LED_BTLDR_PORT, LED_BTLDR_PIN);
#endif

#ifdef TOTAL_UNUSED_IO
                for (int i = 0; i < TOTAL_UNUSED_IO; i++)
                {
                    core::io::mcuPin_t pin = detail::map::unusedPin(i);
                    CORE_IO_CONFIG(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), core::io::pinMode_t::output);
                    CORE_IO_SET_STATE(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), detail::map::unusedPinState(i));
                }
#endif
            }
        }    // namespace setup
    }        // namespace detail
}    // namespace Board<commit_msg>board/avr: enable pwm timer only when needed<commit_after>/*

Copyright 2015-2021 Igor Petrovic

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 <cstddef>
#include <stdio.h>
#include <stdlib.h>
#include <avr/power.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include "board/Board.h"
#include "board/Internal.h"
#include "board/common/io/Helpers.h"
#include "core/src/general/ADC.h"
#include "core/src/arch/avr/Misc.h"
#include "core/src/general/IO.h"
#include "core/src/general/Interrupt.h"
#include "core/src/general/Timing.h"
#include "Pins.h"

extern "C" void __cxa_pure_virtual()
{
    Board::detail::errorHandler();
}

void* operator new(std::size_t size)
{
    return malloc(size);
}

void operator delete(void* ptr)
{
}

namespace std
{
    void __throw_bad_function_call()
    {
        Board::detail::errorHandler();
    }

    void __throw_bad_alloc()
    {
        Board::detail::errorHandler();
    }
}    // namespace std

namespace Board
{
    namespace detail
    {
        namespace setup
        {
            void bootloader()
            {
                DISABLE_INTERRUPTS();

                //clear reset source
                MCUSR &= ~(1 << EXTRF);

                //disable watchdog
                MCUSR &= ~(1 << WDRF);
                wdt_disable();

                //disable clock division
                clock_prescale_set(clock_div_1);

                detail::setup::io();

                //relocate the interrupt vector table to the bootloader section
                MCUCR = (1 << IVCE);
                MCUCR = (1 << IVSEL);

                ENABLE_INTERRUPTS();

#if defined(USB_LINK_MCU) || !defined(USB_MIDI_SUPPORTED)
                Board::UART::init(UART_CHANNEL_USB_LINK, UART_BAUDRATE_MIDI_OD);
#endif
            }

            void application()
            {
                DISABLE_INTERRUPTS();

                //relocate the interrupt vector table to the application section
                MCUCR = (1 << IVCE);
                MCUCR = (0 << IVSEL);

                //clear reset source
                MCUSR &= ~(1 << EXTRF);

                //disable watchdog
                MCUSR &= ~(1 << WDRF);
                wdt_disable();

                //disable clock division
                clock_prescale_set(clock_div_1);

                detail::setup::io();
                detail::setup::adc();

#if defined(USB_LINK_MCU) || !defined(USB_MIDI_SUPPORTED)
                Board::UART::init(UART_CHANNEL_USB_LINK, UART_BAUDRATE_MIDI_OD);
#endif

                detail::setup::usb();
                detail::setup::timers();

                ENABLE_INTERRUPTS();

#ifndef USB_LINK_MCU
                //add some delay and remove initial readout of digital inputs
                core::timing::waitMs(10);
                detail::io::flushInputReadings();
#endif
            }

#ifdef ANALOG_SUPPORTED
            void adc()
            {
                core::adc::conf_t adcConfiguration;

                adcConfiguration.prescaler = core::adc::prescaler_t::p128;

#ifdef ADC_EXT_REF
                adcConfiguration.vref = core::adc::vRef_t::aref;
#else
                adcConfiguration.vref = core::adc::vRef_t::avcc;
#endif

                for (int i = 0; i < MAX_ADC_CHANNELS; i++)
                    core::adc::disconnectDigitalIn(Board::detail::map::adcChannel(i));

                core::adc::setup(adcConfiguration);
                core::adc::setChannel(Board::detail::map::adcChannel(0));

                for (int i = 0; i < 3; i++)
                    core::adc::read();    //few dummy reads to init ADC

                core::adc::enableInterrupt();
                core::adc::startConversion();
            }
#endif

            void timers()
            {
                //set timer0 to ctc, used for millis/led matrix
                //clear timer0 conf
                TCCR0A = 0;
                TCCR0B = 0;
                TIMSK0 = 0;
                TCCR0A |= (1 << WGM01);                 //CTC mode
                TCCR0B |= (1 << CS01) | (1 << CS00);    //prescaler 64
                OCR0A = 249;                            //1ms
                TIMSK0 |= (1 << OCIE0A);                //compare match interrupt

#ifdef FW_APP
#ifndef USB_LINK_MCU
#if MAX_NUMBER_OF_LEDS > 0
                //use timer1 for soft pwm
                TCCR1A = 0;
                TCCR1B = 0;
                TCCR1C = 0;

                TIMSK1 = 0;
                TCCR1B |= (1 << WGM12);                 //CTC mode
                TCCR1B |= (1 << CS11) | (1 << CS10);    //prescaler 64
                OCR1A = 124;                            //500us
                TIMSK1 |= (1 << OCIE1A);                //compare match interrupt
#endif
#endif
#endif
            }

            void io()
            {
#ifdef NUMBER_OF_IN_SR
                CORE_IO_CONFIG(SR_IN_DATA_PORT, SR_IN_DATA_PIN, core::io::pinMode_t::input);
                CORE_IO_CONFIG(SR_IN_CLK_PORT, SR_IN_CLK_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(SR_IN_LATCH_PORT, SR_IN_LATCH_PIN, core::io::pinMode_t::output);

                CORE_IO_SET_LOW(SR_IN_CLK_PORT, SR_IN_CLK_PIN);
                CORE_IO_SET_HIGH(SR_IN_LATCH_PORT, SR_IN_LATCH_PIN);
#else
                for (int i = 0; i < MAX_NUMBER_OF_BUTTONS; i++)
                {
                    core::io::mcuPin_t pin = detail::map::buttonPin(i);

                    CORE_IO_CONFIG(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), core::io::pinMode_t::input);

#ifndef BUTTONS_EXT_PULLUPS
                    CORE_IO_SET_HIGH(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin));
#endif
                }
#endif

#ifdef NUMBER_OF_BUTTON_COLUMNS
                CORE_IO_CONFIG(DEC_BM_PORT_A0, DEC_BM_PIN_A0, core::io::pinMode_t::output);
                CORE_IO_CONFIG(DEC_BM_PORT_A1, DEC_BM_PIN_A1, core::io::pinMode_t::output);
                CORE_IO_CONFIG(DEC_BM_PORT_A2, DEC_BM_PIN_A2, core::io::pinMode_t::output);

                CORE_IO_SET_LOW(DEC_BM_PORT_A0, DEC_BM_PIN_A0);
                CORE_IO_SET_LOW(DEC_BM_PORT_A1, DEC_BM_PIN_A1);
                CORE_IO_SET_LOW(DEC_BM_PORT_A2, DEC_BM_PIN_A2);
#endif

#ifdef NUMBER_OF_OUT_SR
                CORE_IO_CONFIG(SR_OUT_DATA_PORT, SR_OUT_DATA_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(SR_OUT_CLK_PORT, SR_OUT_CLK_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(SR_OUT_LATCH_PORT, SR_OUT_LATCH_PIN, core::io::pinMode_t::output);

#ifdef SR_OUT_OE_PORT
                CORE_IO_CONFIG(SR_OUT_OE_PORT, SR_OUT_OE_PIN, core::io::pinMode_t::output);
#endif

                //init all outputs on shift register
                CORE_IO_SET_LOW(SR_OUT_LATCH_PORT, SR_OUT_LATCH_PIN);

                for (int i = 0; i < MAX_NUMBER_OF_LEDS; i++)
                {
                    EXT_LED_OFF(SR_OUT_DATA_PORT, SR_OUT_DATA_PIN);
                    CORE_IO_SET_HIGH(SR_OUT_CLK_PORT, SR_OUT_CLK_PIN);
                    detail::io::sr595wait();
                    CORE_IO_SET_LOW(SR_OUT_CLK_PORT, SR_OUT_CLK_PIN);
                }

                CORE_IO_SET_HIGH(SR_OUT_LATCH_PORT, SR_OUT_LATCH_PIN);
#ifdef SR_OUT_OE_PORT
                CORE_IO_SET_LOW(SR_OUT_OE_PORT, SR_OUT_OE_PIN);
#endif
#else
#ifdef NUMBER_OF_LED_ROWS
                CORE_IO_CONFIG(DEC_LM_PORT_A0, DEC_LM_PIN_A0, core::io::pinMode_t::output);
                CORE_IO_CONFIG(DEC_LM_PORT_A1, DEC_LM_PIN_A1, core::io::pinMode_t::output);
                CORE_IO_CONFIG(DEC_LM_PORT_A2, DEC_LM_PIN_A2, core::io::pinMode_t::output);

                CORE_IO_SET_LOW(DEC_LM_PORT_A0, DEC_LM_PIN_A0);
                CORE_IO_SET_LOW(DEC_LM_PORT_A1, DEC_LM_PIN_A1);
                CORE_IO_SET_LOW(DEC_LM_PORT_A2, DEC_LM_PIN_A2);

                for (int i = 0; i < NUMBER_OF_LED_ROWS; i++)
#else
                for (int i = 0; i < MAX_NUMBER_OF_LEDS; i++)
#endif
                {
                    core::io::mcuPin_t pin = detail::map::ledPin(i);

                    CORE_IO_CONFIG(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), core::io::pinMode_t::output);
                    EXT_LED_OFF(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin));
                }
#endif

#if MAX_ADC_CHANNELS > 0
                for (int i = 0; i < MAX_ADC_CHANNELS; i++)
                {
                    core::io::mcuPin_t pin = detail::map::adcPin(i);

                    CORE_IO_CONFIG(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), core::io::pinMode_t::input);
                    CORE_IO_SET_LOW(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin));
                }
#endif

#ifdef NUMBER_OF_MUX
                CORE_IO_CONFIG(MUX_PORT_S0, MUX_PIN_S0, core::io::pinMode_t::output);
                CORE_IO_CONFIG(MUX_PORT_S1, MUX_PIN_S1, core::io::pinMode_t::output);
                CORE_IO_CONFIG(MUX_PORT_S2, MUX_PIN_S2, core::io::pinMode_t::output);
#ifdef MUX_PORT_S3
                CORE_IO_CONFIG(MUX_PORT_S3, MUX_PIN_S3, core::io::pinMode_t::output);
#endif
#endif

#ifdef BTLDR_BUTTON_PORT
                CORE_IO_CONFIG(BTLDR_BUTTON_PORT, BTLDR_BUTTON_PIN, core::io::pinMode_t::input);
                CORE_IO_SET_HIGH(BTLDR_BUTTON_PORT, BTLDR_BUTTON_PIN);
#endif

#ifdef LED_INDICATORS
                CORE_IO_CONFIG(LED_MIDI_IN_DIN_PORT, LED_MIDI_IN_DIN_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(LED_MIDI_OUT_DIN_PORT, LED_MIDI_OUT_DIN_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(LED_MIDI_IN_USB_PORT, LED_MIDI_IN_USB_PIN, core::io::pinMode_t::output);
                CORE_IO_CONFIG(LED_MIDI_OUT_USB_PORT, LED_MIDI_OUT_USB_PIN, core::io::pinMode_t::output);

                INT_LED_OFF(LED_MIDI_IN_DIN_PORT, LED_MIDI_IN_DIN_PIN);
                INT_LED_OFF(LED_MIDI_OUT_DIN_PORT, LED_MIDI_OUT_DIN_PIN);
                INT_LED_OFF(LED_MIDI_IN_USB_PORT, LED_MIDI_IN_USB_PIN);
                INT_LED_OFF(LED_MIDI_OUT_USB_PORT, LED_MIDI_OUT_USB_PIN);
#endif

#ifdef LED_BTLDR_PORT
                CORE_IO_CONFIG(LED_BTLDR_PORT, LED_BTLDR_PIN, core::io::pinMode_t::output);
                CORE_IO_SET_HIGH(LED_BTLDR_PORT, LED_BTLDR_PIN);
#endif

#ifdef TOTAL_UNUSED_IO
                for (int i = 0; i < TOTAL_UNUSED_IO; i++)
                {
                    core::io::mcuPin_t pin = detail::map::unusedPin(i);
                    CORE_IO_CONFIG(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), core::io::pinMode_t::output);
                    CORE_IO_SET_STATE(CORE_IO_MCU_PIN_PORT(pin), CORE_IO_MCU_PIN_INDEX(pin), detail::map::unusedPinState(i));
                }
#endif
            }
        }    // namespace setup
    }        // namespace detail
}    // namespace Board<|endoftext|>


<commit_before>// Copyright (c) 2008 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 "SkGraphicsContext.h"

#include "base/gfx/platform_canvas_mac.h"
#include "base/gfx/image_operations.h"
#include "base/gfx/skia_utils_mac.h"
#include "base/logging.h"
#include "GraphicsContextPrivate.h"
#include "SkBitmap.h"
#include "NativeImageSkia.h"
#include "SkiaUtils.h"

// These need to be moved
#include "ThemeData.h"

#define kSkiaOrientation  kHIThemeOrientationNormal

namespace {

// Draws the given bitmap to the given canvas. The subset of the source bitmap
// identified by src_rect is drawn to the given destination rect. The bitmap
// will be resampled to resample_width * resample_height (this is the size of
// the whole image, not the subset). See shouldResampleBitmap for more.
//
// This does a lot of computation to resample only the portion of the bitmap
// that will only be drawn. This is critical for performance since when we are
// scrolling, for example, we are only drawing a small strip of the image.
// Resampling the whole image every time is very slow, so this speeds up things
// dramatically.
void DrawResampledBitmap(SkCanvas& canvas,
                         SkPaint& paint,
                         const NativeImageSkia& bitmap,
                         const SkIRect& src_irect,
                         const SkRect& dest_rect) {
  // First get the subset we need. This is efficient and does not copy pixels.
  SkBitmap subset;
  bitmap.extractSubset(&subset, src_irect);
  SkRect src_rect;
  src_rect.set(src_irect);

  // Whether we're doing a subset or using the full source image.
  bool src_is_full = src_irect.fLeft == 0 && src_irect.fTop == 0 &&
      src_irect.width() == bitmap.width() &&
      src_irect.height() == bitmap.height();

  // We will always draw in integer sizes, so round the destination rect.
  SkIRect dest_rect_rounded;
  dest_rect.round(&dest_rect_rounded);
  SkIRect resized_image_rect;  // Represents the size of the resized image.
  resized_image_rect.set(0, 0,
                         dest_rect_rounded.width(), dest_rect_rounded.height());

  if (src_is_full &&
      bitmap.hasResizedBitmap(dest_rect_rounded.width(),
                              dest_rect_rounded.height())) {
    // Yay, this bitmap frame already has a resized version appropriate for us.
    SkBitmap resampled = bitmap.resizedBitmap(dest_rect_rounded.width(),
                                              dest_rect_rounded.height());
    canvas.drawBitmapRect(resampled, NULL, dest_rect, &paint);
    return;
  }

  // Compute the visible portion of our rect.
  SkRect dest_bitmap_subset_sk;
  ClipRectToCanvas(canvas, dest_rect, &dest_bitmap_subset_sk);
  dest_bitmap_subset_sk.offset(-dest_rect.fLeft, -dest_rect.fTop);

  // The matrix inverting, etc. could have introduced rounding error which
  // causes the bounds to be outside of the resized bitmap. We round outward so
  // we always lean toward it being larger rather than smaller than we need,
  // and then clamp to the bitmap bounds so we don't get any invalid data.
  SkIRect dest_bitmap_subset_sk_i;
  dest_bitmap_subset_sk.roundOut(&dest_bitmap_subset_sk_i);
  if (!dest_bitmap_subset_sk_i.intersect(resized_image_rect))
    return;  // Resized image does not intersect.

  if (src_is_full && bitmap.shouldCacheResampling(
          resized_image_rect.width(),
          resized_image_rect.height(),
          dest_bitmap_subset_sk_i.width(),
          dest_bitmap_subset_sk_i.height())) {
    // We're supposed to resize the entire image and cache it, even though we
    // don't need all of it.
    SkBitmap resampled = bitmap.resizedBitmap(dest_rect_rounded.width(),
                                              dest_rect_rounded.height());
    canvas.drawBitmapRect(resampled, NULL, dest_rect, &paint);
  } else {
    // We should only resize the exposed part of the bitmap to do the minimal
    // possible work.
    gfx::Rect dest_bitmap_subset(dest_bitmap_subset_sk_i.fLeft,
                                 dest_bitmap_subset_sk_i.fTop,
                                 dest_bitmap_subset_sk_i.width(),
                                 dest_bitmap_subset_sk_i.height());

    // Resample the needed part of the image.
    SkBitmap resampled = gfx::ImageOperations::Resize(subset,
        gfx::ImageOperations::RESIZE_LANCZOS3,
        gfx::Size(dest_rect_rounded.width(), dest_rect_rounded.height()),
        dest_bitmap_subset);

    // Compute where the new bitmap should be drawn. Since our new bitmap may be
    // smaller than the original, we have to shift it over by the same amount
    // that we cut off the top and left.
    SkRect offset_dest_rect = {
        dest_bitmap_subset.x() + dest_rect.fLeft,
        dest_bitmap_subset.y() + dest_rect.fTop,
        dest_bitmap_subset.right() + dest_rect.fLeft,
        dest_bitmap_subset.bottom() + dest_rect.fTop };

    canvas.drawBitmapRect(resampled, NULL, offset_dest_rect, &paint);
  }
}

}  // namespace

SkGraphicsContext::SkGraphicsContext(gfx::PlatformCanvas* canvas)
    : canvas_(canvas),
      paint_context_(NULL),
      own_canvas_(false) {
}

SkGraphicsContext::~SkGraphicsContext() {
  if (own_canvas_)
    delete canvas_;
}

const gfx::NativeTheme* SkGraphicsContext::nativeTheme() {
  // TODO(pinkerton): fix me
  return nil;
}

void SkGraphicsContext::paintIcon(CGImageRef icon, const SkIRect& rect) {
  CGContextRef context = canvas_->beginPlatformPaint();
  CGRect r = gfx::SkIRectToCGRect(rect);
  CGContextDrawImage(context, r, icon);
  canvas_->endPlatformPaint();
}

void SkGraphicsContext::paintButton(const SkIRect& widgetRect,
                                    const ThemeData& themeData) {
  CGContextRef context = canvas_->beginPlatformPaint();

  int state = themeData.m_state;
  CGRect rect(gfx::SkIRectToCGRect(widgetRect));
  HIThemeButtonDrawInfo button_draw_info = { 0 };
  button_draw_info.state = state;
  CGRect label_rect;

  HIThemeDrawButton(&rect, &button_draw_info, context,
                    kSkiaOrientation, &label_rect);

  canvas_->endPlatformPaint();
}

void SkGraphicsContext::paintTextField(const SkIRect& widgetRect,
                                       const ThemeData& themeData,
                                       SkColor c,
                                       bool drawEdges) {
  CGContextRef context = canvas_->beginPlatformPaint();

  int state = themeData.m_state;
  CGRect rect(gfx::SkIRectToCGRect(widgetRect));
  CGContextSaveGState(context);
  CGColorRef color = gfx::SkColorToCGColorRef(c);
  CGContextSetFillColorWithColor(context, color);
  CGContextFillRect(context, rect);
  CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);  // black border for now
  CGContextStrokeRect(context, rect);
  CGContextRestoreGState(context);
  CGColorRelease(color);
  canvas_->endPlatformPaint();
}

void SkGraphicsContext::paintMenuListArrowButton(const SkIRect& widgetRect,
                                                 unsigned state,
                                                 unsigned classic_state) {
  CGContextRef context = canvas_->beginPlatformPaint();

  CGRect rect(gfx::SkIRectToCGRect(widgetRect));
  HIThemePopupArrowDrawInfo arrow_draw_info = { 0 };
  arrow_draw_info.state = state;
  CGRect label_rect;

  HIThemeDrawPopupArrow(&rect, &arrow_draw_info, context, kSkiaOrientation);

  canvas_->endPlatformPaint();
}

void SkGraphicsContext::paintComplexText(UniscribeStateTextRun& state,
                                         const SkPoint& point,
                                         int from,
                                         int to,
                                         int ascent) {
  SkColor sk_color(paint_context_->fillColor());
  uint8 alpha = SkColorGetA(sk_color);
  // Skip 100% transparent text; no need to draw anything.
  if (!alpha)
    return;

  CGContextRef context = canvas_->beginPlatformPaint();
  CGContextSaveGState(context);
  CGColorRef color = gfx::SkColorToCGColorRef(sk_color);
  CGContextSetFillColorWithColor(context, color);

  //TODO: remove use of UniscribeStateTextRun; show placeholder to test other
  // code for the moment
  CGContextShowTextAtPoint(context, point.fX, point.fY, "complex", 7);
  CGContextRestoreGState(context);
  CGColorRelease(color);
  canvas_->endPlatformPaint();
}

bool SkGraphicsContext::paintText(FontHandle font,
                                  int number_glyph,
                                  const uint16* chars,
                                  const int* advances,
                                  const SkPoint& origin) {
  SkColor sk_color(paint_context_->fillColor());
  uint8 alpha = SkColorGetA(sk_color);
  // Skip 100% transparent text; no need to draw anything.
  if (!alpha)
    return true;

  bool success = false;
  CGContextRef context = canvas_->beginPlatformPaint();
  CGContextSaveGState(context);
  CGColorRef color = gfx::SkColorToCGColorRef(sk_color);
  CGContextSetFillColorWithColor(context, color);
  CGContextMoveToPoint(context, origin.fX, origin.fY);
  CGFontRef cg_font = CTFontCopyGraphicsFont(font, NULL);
  CGContextSetFont(context, cg_font);

  CGSize cg_advances[number_glyph];
  CGGlyph cg_glyphs[number_glyph];

  CTFontGetGlyphsForCharacters(font, chars, cg_glyphs, number_glyph);
  CGContextShowGlyphsAtPoint(context, origin.fX, origin.fY,
                             cg_glyphs, number_glyph);
  CGContextRestoreGState(context);
  CGColorRelease(color);
  CGFontRelease(cg_font);
  canvas_->endPlatformPaint();
  return success;
}

void SkGraphicsContext::paintSkPaint(const SkRect& rect,
                                     const SkPaint& paint) {
  canvas_->drawRect(rect, paint);
}

// Returns smallest multiple of two of the dest size that is more than a small
// multiple larger than src_size.
//
// Used to determine the size that source should be high-quality upsampled to,
// after which we use linear interpolation. Making sure that the linear
// interpolation is a factor of two reduces artifacts, and doing the lowest
// level of resampling
static int GetResamplingThreshold(int src_size, int dest_size) {
  int lower_bound = src_size * 3 / 2;  // Minimum size we'll resample to (1.5x).
  int cur = dest_size;

  // Find the largest multiple of two of the destination size less than our
  // threshold
  while (cur > lower_bound)
    cur /= 2;

  // We want the next size above that, or just the destination size if it's
  // smaller.
  cur *= 2;
  if (cur > dest_size)
    return dest_size;
  return cur;
}

// static
SkGraphicsContext::ResamplingMode SkGraphicsContext::computeResamplingMode(
    const NativeImageSkia& bitmap,
    int src_width, int src_height,
    float dest_width, float dest_height) {
  int dest_iwidth = static_cast<int>(dest_width);
  int dest_iheight = static_cast<int>(dest_height);

  // The percent change below which we will not resample. This usually means
  // an off-by-one error on the web page, and just doing nearest neighbor
  // sampling is usually good enough.
  const float kFractionalChangeThreshold = 0.025f;

  // Images smaller than this in either direction are considered "small" and
  // are not resampled ever (see below).
  const int kSmallImageSizeThreshold = 8;

  // The amount an image can be stretched in a single direction before we
  // say that it is being stretched so much that it must be a line or
  // background that doesn't need resampling.
  const float kLargeStretch = 3.0f;

  // Figure out if we should resample this image. We try to prune out some
  // common cases where resampling won't give us anything, since it is much
  // slower than drawing stretched.
  if (src_width == dest_iwidth && src_height == dest_iheight) {
    // We don't need to resample if the source and destination are the same.
    return RESAMPLE_NONE;
  }

  if (src_width <= kSmallImageSizeThreshold ||
    src_height <= kSmallImageSizeThreshold ||
    dest_width <= kSmallImageSizeThreshold ||
    dest_height <= kSmallImageSizeThreshold) {
    // Never resample small images. These are often used for borders and
    // rules (think 1x1 images used to make lines).
    return RESAMPLE_NONE;
  }

  if (src_height * kLargeStretch <= dest_height ||
    src_width * kLargeStretch <= dest_width) {
    // Large image detected.

    // Don't resample if it is being stretched a lot in only one direction.
    // This is trying to catch cases where somebody has created a border
    // (which might be large) and then is stretching it to fill some part
    // of the page.
    if (src_width == dest_width || src_height == dest_height)
      return RESAMPLE_NONE;

    // The image is growing a lot and in more than one direction. Resampling
    // is slow and doesn't give us very much when growing a lot.
    return RESAMPLE_LINEAR;
  }

  if ((fabs(dest_width - src_width) / src_width <
       kFractionalChangeThreshold) &&
     (fabs(dest_height - src_height) / src_height <
      kFractionalChangeThreshold)) {
    // It is disappointingly common on the web for image sizes to be off by
    // one or two pixels. We don't bother resampling if the size difference
    // is a small fraction of the original size.
    return RESAMPLE_NONE;
  }

  // When the image is not yet done loading, use linear. We don't cache the
  // partially resampled images, and as they come in incrementally, it causes
  // us to have to resample the whole thing every time.
  if (!bitmap.isDataComplete())
    return RESAMPLE_LINEAR;

  // Everything else gets resampled.
  return RESAMPLE_AWESOME;
}

void SkGraphicsContext::paintSkBitmap(const NativeImageSkia& bitmap,
                                      const SkIRect& src_rect,
                                      const SkRect& dest_rect,
                                      const SkPorterDuff::Mode& comp_op) {
  SkPaint paint;
  paint.setPorterDuffXfermode(comp_op);

  ResamplingMode resampling = IsPrinting() ? RESAMPLE_NONE :
      computeResamplingMode(bitmap, src_rect.width(), src_rect.height(),
                            SkScalarToFloat(dest_rect.width()),
                            SkScalarToFloat(dest_rect.height()));
  if (resampling == RESAMPLE_AWESOME) {
    paint.setFilterBitmap(false);
    DrawResampledBitmap(*canvas_, paint, bitmap, src_rect, dest_rect);
  } else {
    // No resampling necessary, we can just draw the bitmap.
    // Note: for serialization, we will want to subset the bitmap first so
    // we don't send extra pixels.
    paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
    canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint);
  }
}

void SkGraphicsContext::setDashPathEffect(SkDashPathEffect *dash) {
  paint_context_->setDashPathEffect(dash);
}

void SkGraphicsContext::setGradient(SkShader *gradient) {
  paint_context_->setGradient(gradient);
}

void SkGraphicsContext::setPattern(SkShader *pattern) {
  paint_context_->setPattern(pattern);
}

const SkBitmap* SkGraphicsContext::bitmap() const {
  return &canvas_->getDevice()->accessBitmap(false);
}

gfx::PlatformCanvas* SkGraphicsContext::canvas() const {
  return canvas_;
}

bool SkGraphicsContext::IsPrinting() {
  return canvas_->getTopPlatformDevice().IsVectorial();
}
<commit_msg>Update include headers for SkGraphicsContextMac.cpp<commit_after>// Copyright (c) 2008 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 "config.h"
#include "SkGraphicsContext.h"

#include "base/gfx/platform_canvas_mac.h"
#include "base/gfx/image_operations.h"
#include "base/gfx/skia_utils_mac.h"
#include "base/logging.h"
#include "GraphicsContextPlatformPrivate.h"
#include "SkBitmap.h"
#include "NativeImageSkia.h"
#include "SkiaUtils.h"

// These need to be moved
#include "ThemeData.h"

#define kSkiaOrientation  kHIThemeOrientationNormal

namespace {

// Draws the given bitmap to the given canvas. The subset of the source bitmap
// identified by src_rect is drawn to the given destination rect. The bitmap
// will be resampled to resample_width * resample_height (this is the size of
// the whole image, not the subset). See shouldResampleBitmap for more.
//
// This does a lot of computation to resample only the portion of the bitmap
// that will only be drawn. This is critical for performance since when we are
// scrolling, for example, we are only drawing a small strip of the image.
// Resampling the whole image every time is very slow, so this speeds up things
// dramatically.
void DrawResampledBitmap(SkCanvas& canvas,
                         SkPaint& paint,
                         const NativeImageSkia& bitmap,
                         const SkIRect& src_irect,
                         const SkRect& dest_rect) {
  // First get the subset we need. This is efficient and does not copy pixels.
  SkBitmap subset;
  bitmap.extractSubset(&subset, src_irect);
  SkRect src_rect;
  src_rect.set(src_irect);

  // Whether we're doing a subset or using the full source image.
  bool src_is_full = src_irect.fLeft == 0 && src_irect.fTop == 0 &&
      src_irect.width() == bitmap.width() &&
      src_irect.height() == bitmap.height();

  // We will always draw in integer sizes, so round the destination rect.
  SkIRect dest_rect_rounded;
  dest_rect.round(&dest_rect_rounded);
  SkIRect resized_image_rect;  // Represents the size of the resized image.
  resized_image_rect.set(0, 0,
                         dest_rect_rounded.width(), dest_rect_rounded.height());

  if (src_is_full &&
      bitmap.hasResizedBitmap(dest_rect_rounded.width(),
                              dest_rect_rounded.height())) {
    // Yay, this bitmap frame already has a resized version appropriate for us.
    SkBitmap resampled = bitmap.resizedBitmap(dest_rect_rounded.width(),
                                              dest_rect_rounded.height());
    canvas.drawBitmapRect(resampled, NULL, dest_rect, &paint);
    return;
  }

  // Compute the visible portion of our rect.
  SkRect dest_bitmap_subset_sk;
  ClipRectToCanvas(canvas, dest_rect, &dest_bitmap_subset_sk);
  dest_bitmap_subset_sk.offset(-dest_rect.fLeft, -dest_rect.fTop);

  // The matrix inverting, etc. could have introduced rounding error which
  // causes the bounds to be outside of the resized bitmap. We round outward so
  // we always lean toward it being larger rather than smaller than we need,
  // and then clamp to the bitmap bounds so we don't get any invalid data.
  SkIRect dest_bitmap_subset_sk_i;
  dest_bitmap_subset_sk.roundOut(&dest_bitmap_subset_sk_i);
  if (!dest_bitmap_subset_sk_i.intersect(resized_image_rect))
    return;  // Resized image does not intersect.

  if (src_is_full && bitmap.shouldCacheResampling(
          resized_image_rect.width(),
          resized_image_rect.height(),
          dest_bitmap_subset_sk_i.width(),
          dest_bitmap_subset_sk_i.height())) {
    // We're supposed to resize the entire image and cache it, even though we
    // don't need all of it.
    SkBitmap resampled = bitmap.resizedBitmap(dest_rect_rounded.width(),
                                              dest_rect_rounded.height());
    canvas.drawBitmapRect(resampled, NULL, dest_rect, &paint);
  } else {
    // We should only resize the exposed part of the bitmap to do the minimal
    // possible work.
    gfx::Rect dest_bitmap_subset(dest_bitmap_subset_sk_i.fLeft,
                                 dest_bitmap_subset_sk_i.fTop,
                                 dest_bitmap_subset_sk_i.width(),
                                 dest_bitmap_subset_sk_i.height());

    // Resample the needed part of the image.
    SkBitmap resampled = gfx::ImageOperations::Resize(subset,
        gfx::ImageOperations::RESIZE_LANCZOS3,
        gfx::Size(dest_rect_rounded.width(), dest_rect_rounded.height()),
        dest_bitmap_subset);

    // Compute where the new bitmap should be drawn. Since our new bitmap may be
    // smaller than the original, we have to shift it over by the same amount
    // that we cut off the top and left.
    SkRect offset_dest_rect = {
        dest_bitmap_subset.x() + dest_rect.fLeft,
        dest_bitmap_subset.y() + dest_rect.fTop,
        dest_bitmap_subset.right() + dest_rect.fLeft,
        dest_bitmap_subset.bottom() + dest_rect.fTop };

    canvas.drawBitmapRect(resampled, NULL, offset_dest_rect, &paint);
  }
}

}  // namespace

SkGraphicsContext::SkGraphicsContext(gfx::PlatformCanvas* canvas)
    : canvas_(canvas),
      paint_context_(NULL),
      own_canvas_(false) {
}

SkGraphicsContext::~SkGraphicsContext() {
  if (own_canvas_)
    delete canvas_;
}

const gfx::NativeTheme* SkGraphicsContext::nativeTheme() {
  // TODO(pinkerton): fix me
  return nil;
}

void SkGraphicsContext::paintIcon(CGImageRef icon, const SkIRect& rect) {
  CGContextRef context = canvas_->beginPlatformPaint();
  CGRect r = gfx::SkIRectToCGRect(rect);
  CGContextDrawImage(context, r, icon);
  canvas_->endPlatformPaint();
}

void SkGraphicsContext::paintButton(const SkIRect& widgetRect,
                                    const ThemeData& themeData) {
  CGContextRef context = canvas_->beginPlatformPaint();

  int state = themeData.m_state;
  CGRect rect(gfx::SkIRectToCGRect(widgetRect));
  HIThemeButtonDrawInfo button_draw_info = { 0 };
  button_draw_info.state = state;
  CGRect label_rect;

  HIThemeDrawButton(&rect, &button_draw_info, context,
                    kSkiaOrientation, &label_rect);

  canvas_->endPlatformPaint();
}

void SkGraphicsContext::paintTextField(const SkIRect& widgetRect,
                                       const ThemeData& themeData,
                                       SkColor c,
                                       bool drawEdges) {
  CGContextRef context = canvas_->beginPlatformPaint();

  int state = themeData.m_state;
  CGRect rect(gfx::SkIRectToCGRect(widgetRect));
  CGContextSaveGState(context);
  CGColorRef color = gfx::SkColorToCGColorRef(c);
  CGContextSetFillColorWithColor(context, color);
  CGContextFillRect(context, rect);
  CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);  // black border for now
  CGContextStrokeRect(context, rect);
  CGContextRestoreGState(context);
  CGColorRelease(color);
  canvas_->endPlatformPaint();
}

void SkGraphicsContext::paintMenuListArrowButton(const SkIRect& widgetRect,
                                                 unsigned state,
                                                 unsigned classic_state) {
  CGContextRef context = canvas_->beginPlatformPaint();

  CGRect rect(gfx::SkIRectToCGRect(widgetRect));
  HIThemePopupArrowDrawInfo arrow_draw_info = { 0 };
  arrow_draw_info.state = state;
  CGRect label_rect;

  HIThemeDrawPopupArrow(&rect, &arrow_draw_info, context, kSkiaOrientation);

  canvas_->endPlatformPaint();
}

void SkGraphicsContext::paintComplexText(UniscribeStateTextRun& state,
                                         const SkPoint& point,
                                         int from,
                                         int to,
                                         int ascent) {
  SkColor sk_color(paint_context_->fillColor());
  uint8 alpha = SkColorGetA(sk_color);
  // Skip 100% transparent text; no need to draw anything.
  if (!alpha)
    return;

  CGContextRef context = canvas_->beginPlatformPaint();
  CGContextSaveGState(context);
  CGColorRef color = gfx::SkColorToCGColorRef(sk_color);
  CGContextSetFillColorWithColor(context, color);

  //TODO: remove use of UniscribeStateTextRun; show placeholder to test other
  // code for the moment
  CGContextShowTextAtPoint(context, point.fX, point.fY, "complex", 7);
  CGContextRestoreGState(context);
  CGColorRelease(color);
  canvas_->endPlatformPaint();
}

bool SkGraphicsContext::paintText(FontHandle font,
                                  int number_glyph,
                                  const uint16* chars,
                                  const int* advances,
                                  const SkPoint& origin) {
  SkColor sk_color(paint_context_->fillColor());
  uint8 alpha = SkColorGetA(sk_color);
  // Skip 100% transparent text; no need to draw anything.
  if (!alpha)
    return true;

  bool success = false;
  CGContextRef context = canvas_->beginPlatformPaint();
  CGContextSaveGState(context);
  CGColorRef color = gfx::SkColorToCGColorRef(sk_color);
  CGContextSetFillColorWithColor(context, color);
  CGContextMoveToPoint(context, origin.fX, origin.fY);
  CGFontRef cg_font = CTFontCopyGraphicsFont(font, NULL);
  CGContextSetFont(context, cg_font);

  CGSize cg_advances[number_glyph];
  CGGlyph cg_glyphs[number_glyph];

  CTFontGetGlyphsForCharacters(font, chars, cg_glyphs, number_glyph);
  CGContextShowGlyphsAtPoint(context, origin.fX, origin.fY,
                             cg_glyphs, number_glyph);
  CGContextRestoreGState(context);
  CGColorRelease(color);
  CGFontRelease(cg_font);
  canvas_->endPlatformPaint();
  return success;
}

void SkGraphicsContext::paintSkPaint(const SkRect& rect,
                                     const SkPaint& paint) {
  canvas_->drawRect(rect, paint);
}

// Returns smallest multiple of two of the dest size that is more than a small
// multiple larger than src_size.
//
// Used to determine the size that source should be high-quality upsampled to,
// after which we use linear interpolation. Making sure that the linear
// interpolation is a factor of two reduces artifacts, and doing the lowest
// level of resampling
static int GetResamplingThreshold(int src_size, int dest_size) {
  int lower_bound = src_size * 3 / 2;  // Minimum size we'll resample to (1.5x).
  int cur = dest_size;

  // Find the largest multiple of two of the destination size less than our
  // threshold
  while (cur > lower_bound)
    cur /= 2;

  // We want the next size above that, or just the destination size if it's
  // smaller.
  cur *= 2;
  if (cur > dest_size)
    return dest_size;
  return cur;
}

// static
SkGraphicsContext::ResamplingMode SkGraphicsContext::computeResamplingMode(
    const NativeImageSkia& bitmap,
    int src_width, int src_height,
    float dest_width, float dest_height) {
  int dest_iwidth = static_cast<int>(dest_width);
  int dest_iheight = static_cast<int>(dest_height);

  // The percent change below which we will not resample. This usually means
  // an off-by-one error on the web page, and just doing nearest neighbor
  // sampling is usually good enough.
  const float kFractionalChangeThreshold = 0.025f;

  // Images smaller than this in either direction are considered "small" and
  // are not resampled ever (see below).
  const int kSmallImageSizeThreshold = 8;

  // The amount an image can be stretched in a single direction before we
  // say that it is being stretched so much that it must be a line or
  // background that doesn't need resampling.
  const float kLargeStretch = 3.0f;

  // Figure out if we should resample this image. We try to prune out some
  // common cases where resampling won't give us anything, since it is much
  // slower than drawing stretched.
  if (src_width == dest_iwidth && src_height == dest_iheight) {
    // We don't need to resample if the source and destination are the same.
    return RESAMPLE_NONE;
  }

  if (src_width <= kSmallImageSizeThreshold ||
    src_height <= kSmallImageSizeThreshold ||
    dest_width <= kSmallImageSizeThreshold ||
    dest_height <= kSmallImageSizeThreshold) {
    // Never resample small images. These are often used for borders and
    // rules (think 1x1 images used to make lines).
    return RESAMPLE_NONE;
  }

  if (src_height * kLargeStretch <= dest_height ||
    src_width * kLargeStretch <= dest_width) {
    // Large image detected.

    // Don't resample if it is being stretched a lot in only one direction.
    // This is trying to catch cases where somebody has created a border
    // (which might be large) and then is stretching it to fill some part
    // of the page.
    if (src_width == dest_width || src_height == dest_height)
      return RESAMPLE_NONE;

    // The image is growing a lot and in more than one direction. Resampling
    // is slow and doesn't give us very much when growing a lot.
    return RESAMPLE_LINEAR;
  }

  if ((fabs(dest_width - src_width) / src_width <
       kFractionalChangeThreshold) &&
     (fabs(dest_height - src_height) / src_height <
      kFractionalChangeThreshold)) {
    // It is disappointingly common on the web for image sizes to be off by
    // one or two pixels. We don't bother resampling if the size difference
    // is a small fraction of the original size.
    return RESAMPLE_NONE;
  }

  // When the image is not yet done loading, use linear. We don't cache the
  // partially resampled images, and as they come in incrementally, it causes
  // us to have to resample the whole thing every time.
  if (!bitmap.isDataComplete())
    return RESAMPLE_LINEAR;

  // Everything else gets resampled.
  return RESAMPLE_AWESOME;
}

void SkGraphicsContext::paintSkBitmap(const NativeImageSkia& bitmap,
                                      const SkIRect& src_rect,
                                      const SkRect& dest_rect,
                                      const SkPorterDuff::Mode& comp_op) {
  SkPaint paint;
  paint.setPorterDuffXfermode(comp_op);

  ResamplingMode resampling = IsPrinting() ? RESAMPLE_NONE :
      computeResamplingMode(bitmap, src_rect.width(), src_rect.height(),
                            SkScalarToFloat(dest_rect.width()),
                            SkScalarToFloat(dest_rect.height()));
  if (resampling == RESAMPLE_AWESOME) {
    paint.setFilterBitmap(false);
    DrawResampledBitmap(*canvas_, paint, bitmap, src_rect, dest_rect);
  } else {
    // No resampling necessary, we can just draw the bitmap.
    // Note: for serialization, we will want to subset the bitmap first so
    // we don't send extra pixels.
    paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
    canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint);
  }
}

void SkGraphicsContext::setDashPathEffect(SkDashPathEffect *dash) {
  paint_context_->setDashPathEffect(dash);
}

void SkGraphicsContext::setGradient(SkShader *gradient) {
  paint_context_->setGradient(gradient);
}

void SkGraphicsContext::setPattern(SkShader *pattern) {
  paint_context_->setPattern(pattern);
}

const SkBitmap* SkGraphicsContext::bitmap() const {
  return &canvas_->getDevice()->accessBitmap(false);
}

gfx::PlatformCanvas* SkGraphicsContext::canvas() const {
  return canvas_;
}

bool SkGraphicsContext::IsPrinting() {
  return canvas_->getTopPlatformDevice().IsVectorial();
}
<|endoftext|>


<commit_before>#include <eeros/core/PeriodicCounter.hpp>
#include <eeros/logger/Pretty.hpp>
using namespace eeros;

PeriodicCounter::PeriodicCounter(double period, unsigned logger_category) :
	reset_after(20), log(logger_category)
{
	setPeriod(period);
	start = clk::now();
	first = true;
}

void PeriodicCounter::setPeriod(double period) {
	counter_period = period;
	reset();
}

void PeriodicCounter::setResetTime(double sec) {
	reset_after = sec;
}

void PeriodicCounter::addDefaultMonitor(double tolerance) {
	PeriodicCounter::addDefaultMonitor(monitors, counter_period, tolerance);
}

void PeriodicCounter::tick() {
	last = start;
	start = clk::now();
}

void PeriodicCounter::tock() {
	if (first) {
		first = false;
		return;
	}

	time_point stop = clk::now();
	double new_period = std::chrono::duration<double>(start - last).count();
	double new_run = std::chrono::duration<double>(stop - start).count();
	double new_jitter = (new_period - counter_period);

	period.add(new_period);
	run.add(new_run);
	jitter.add(new_jitter);

	for (auto &func: monitors)
		func(*this, log);

/*	if (reset_counter <= 0) {
		*this >> log.trace();
		reset();
	}
	else {
		reset_counter--;
	}*/
}

void PeriodicCounter::reset() {
	period.reset();
	jitter.reset();
	run.reset();
	reset_counter = (int)(reset_after / counter_period);
}

void PeriodicCounter:: operator >> (eeros::logger::LogEntry &event) {
	using namespace eeros::logger;

	auto l = [](LogEntry &e, Statistics &x) -> decltype(e) {
		return e << pretty(x.mean) << "\t" << pretty(x.variance) << "\t" << pretty(x.min) << "\t" << pretty(x.max);
	};

	event << "stats:\t     mean\t variance\t      min\t      max" << endl;

	event << "period\t";
	l(event, period) << endl;

	event << "jitter\t";
	l(event, jitter) << endl;

	event << "run   \t";
	l(event, run) << endl;

	event << "count = " << period.count;
}

void PeriodicCounter:: operator >> (eeros::logger::LogEntry &&event) {
	*this >> event;
}

void PeriodicCounter::addDefaultMonitor(std::vector<MonitorFunc> &monitors, double period, double tolerance){
	double Tmin = period * (1 - tolerance);
	double Tmax = period * (1 + tolerance);

	monitors.push_back([Tmin, Tmax](PeriodicCounter& counter, Logger& log){
		double T = counter.period.last;
		if (T < Tmin || T > Tmax) {
			auto e = log.warn();
			e << "last period was " << T << eeros::logger::endl;
			counter >> e;
		}
	});

}
<commit_msg>Change run measurement, is now valid even after first run<commit_after>#include <eeros/core/PeriodicCounter.hpp>
#include <eeros/logger/Pretty.hpp>
using namespace eeros;

PeriodicCounter::PeriodicCounter(double period, unsigned logger_category) :
	reset_after(20), log(logger_category) {
	setPeriod(period);
	start = clk::now();
	first = true;
}

void PeriodicCounter::setPeriod(double period) {
	counter_period = period;
	reset();
}

void PeriodicCounter::setResetTime(double sec) {
	reset_after = sec;
}

void PeriodicCounter::addDefaultMonitor(double tolerance) {
	PeriodicCounter::addDefaultMonitor(monitors, counter_period, tolerance);
}

void PeriodicCounter::tick() {
	last = start;
	start = clk::now();
}

void PeriodicCounter::tock() {
	time_point stop = clk::now();
	double new_run = std::chrono::duration<double>(stop - start).count();
	run.add(new_run);

	if (first) {
		first = false;
		return;
	}

	double new_period = std::chrono::duration<double>(start - last).count();
	double new_jitter = (new_period - counter_period);

	period.add(new_period);
	jitter.add(new_jitter);

	for (auto &func: monitors) func(*this, log);
}

void PeriodicCounter::reset() {
	period.reset();
	jitter.reset();
	run.reset();
	reset_counter = (int)(reset_after / counter_period);
}

void PeriodicCounter:: operator >> (eeros::logger::LogEntry &event) {
	using namespace eeros::logger;

	auto l = [](LogEntry &e, Statistics &x) -> decltype(e) {
		return e << pretty(x.mean) << "\t" << pretty(x.variance) << "\t" << pretty(x.min) << "\t" << pretty(x.max);
	};

	event << "stats:\t     mean\t variance\t      min\t      max" << endl;

	event << "period\t";
	l(event, period) << endl;

	event << "jitter\t";
	l(event, jitter) << endl;

	event << "run   \t";
	l(event, run) << endl;

	event << "count = " << period.count;
}

void PeriodicCounter:: operator >> (eeros::logger::LogEntry &&event) {
	*this >> event;
}

void PeriodicCounter::addDefaultMonitor(std::vector<MonitorFunc> &monitors, double period, double tolerance){
	double Tmin = period * (1 - tolerance);
	double Tmax = period * (1 + tolerance);

	monitors.push_back([Tmin, Tmax](PeriodicCounter& counter, Logger& log){
		double T = counter.period.last;
		if (T < Tmin || T > Tmax) {
			auto e = log.warn();
			e << "last period was " << T << eeros::logger::endl;
			counter >> e;
		}
	});

}
<|endoftext|>


<commit_before>// Copyright 2014 MongoDB Inc.
//
// 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.

#pragma once

#include <bsoncxx/config/prelude.hpp>

#include <cstddef>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <type_traits>

#include <bsoncxx/document/element.hpp>
#include <bsoncxx/stdx/string_view.hpp>

namespace bsoncxx {
BSONCXX_INLINE_NAMESPACE_BEGIN
namespace document {

///
/// A read-only, non-owning view of a BSON document.
///
class BSONCXX_API view {

   public:
    class iterator;
    class const_iterator;

    ///
    /// @returns A const_iterator to the first element of the document.
    ///
    const_iterator cbegin() const;

    ///
    /// @returns A const_iterator to the past-the-end element of the document.
    ///
    const_iterator cend() const;

    ///
    /// @returns An iterator to the first element of the document.
    ///
    iterator begin() const;

    ///
    /// @returns An iterator to the past-the-end element of the document.
    ///
    iterator end() const;

    ///
    /// Finds the first element of the document with the provided key. If there is
    /// no such element, the past-the-end iterator will be returned. The runtime of
    /// find() is linear in the length of the document. This method only searches
    /// the top-level document, and will not recurse to any subdocuments.
    ///
    /// @remark In BSON, keys are not required to be unique. If there are multiple
    /// elements with a matching key in the document, the first matching element from
    /// the start will be returned.
    ///
    /// @param key
    ///   The key to search for.
    ///
    /// @return An iterator to the matching element, if found, or the past-the-end iterator.
    ///
    iterator find(stdx::string_view key) const;

    ///
    /// Finds the first element of the document with the provided key. If there is no
    /// such element, the invalid document::element will be returned. The runtime of operator[]
    /// is linear in the length of the document.
    ///
    /// @param key
    ///   The key to search for.
    ///
    /// @return The matching element, if found, or the invalid element.
    ///
    element operator[](stdx::string_view key) const;

    ///
    /// Default constructs a view. The resulting view will be initialized to point at
    /// an empty BSON document.
    ///
    view();

    ///
    /// Constructs a view from a buffer. The caller is responsible for ensuring that
    /// the lifetime of the resulting view is a subset of the buffer's.
    ///
    /// @param data
    ///   A buffer containing a valid BSON document.
    /// @param length
    ///   The size of the buffer, in bytes.
    ///
    view(const std::uint8_t* data, std::size_t length);

    ///
    /// Access the raw bytes of the underlying document.
    ///
    /// @return A (non-owning) pointer to the view's buffer.
    ///
    const std::uint8_t* data() const;

    ///
    /// Gets the length of the underlying buffer.
    ///
    /// @remark This is not the number of elements in the document.
    /// To compute the number of elements, use std::distance.
    ///
    /// @return The length of the document, in bytes.
    ///
    std::size_t length() const;

    friend BSONCXX_API bool operator==(view, view);
    friend BSONCXX_API bool operator!=(view, view);

   private:
    const std::uint8_t* _data;
    std::size_t _length;
};

class view::iterator : public std::iterator<std::forward_iterator_tag, element> {
   public:
    iterator();
    explicit iterator(const element& element);

    reference operator*();
    pointer operator->();

    iterator& operator++();
    iterator operator++(int);

    friend BSONCXX_API bool operator==(const iterator&, const iterator&);
    friend BSONCXX_API bool operator!=(const iterator&, const iterator&);

   private:
    element _element;
};

class view::const_iterator : public std::iterator<std::forward_iterator_tag, element, std::ptrdiff_t,
                                                  const element*, const element&> {
   public:
    const_iterator();
    explicit const_iterator(const element& element);

    reference operator*();
    pointer operator->();

    const_iterator& operator++();
    const_iterator operator++(int);

    friend BSONCXX_API bool operator==(const const_iterator&, const const_iterator&);
    friend BSONCXX_API bool operator!=(const const_iterator&, const const_iterator&);

   private:
    element _element;
};

}  // namespace document
BSONCXX_INLINE_NAMESPACE_END
}  // namespace bsoncxx

#include <bsoncxx/config/postlude.hpp>
<commit_msg>Move bson::document::view() constructor up<commit_after>// Copyright 2014 MongoDB Inc.
//
// 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.

#pragma once

#include <bsoncxx/config/prelude.hpp>

#include <cstddef>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <type_traits>

#include <bsoncxx/document/element.hpp>
#include <bsoncxx/stdx/string_view.hpp>

namespace bsoncxx {
BSONCXX_INLINE_NAMESPACE_BEGIN
namespace document {

///
/// A read-only, non-owning view of a BSON document.
///
class BSONCXX_API view {

   public:
    class iterator;
    class const_iterator;

    ///
    /// Default constructs a view. The resulting view will be initialized to point at
    /// an empty BSON document.
    ///
    view();

    ///
    /// Constructs a view from a buffer. The caller is responsible for ensuring that
    /// the lifetime of the resulting view is a subset of the buffer's.
    ///
    /// @param data
    ///   A buffer containing a valid BSON document.
    /// @param length
    ///   The size of the buffer, in bytes.
    ///
    view(const std::uint8_t* data, std::size_t length);

    ///
    /// @returns A const_iterator to the first element of the document.
    ///
    const_iterator cbegin() const;

    ///
    /// @returns A const_iterator to the past-the-end element of the document.
    ///
    const_iterator cend() const;

    ///
    /// @returns An iterator to the first element of the document.
    ///
    iterator begin() const;

    ///
    /// @returns An iterator to the past-the-end element of the document.
    ///
    iterator end() const;

    ///
    /// Finds the first element of the document with the provided key. If there is
    /// no such element, the past-the-end iterator will be returned. The runtime of
    /// find() is linear in the length of the document. This method only searches
    /// the top-level document, and will not recurse to any subdocuments.
    ///
    /// @remark In BSON, keys are not required to be unique. If there are multiple
    /// elements with a matching key in the document, the first matching element from
    /// the start will be returned.
    ///
    /// @param key
    ///   The key to search for.
    ///
    /// @return An iterator to the matching element, if found, or the past-the-end iterator.
    ///
    iterator find(stdx::string_view key) const;

    ///
    /// Finds the first element of the document with the provided key. If there is no
    /// such element, the invalid document::element will be returned. The runtime of operator[]
    /// is linear in the length of the document.
    ///
    /// @param key
    ///   The key to search for.
    ///
    /// @return The matching element, if found, or the invalid element.
    ///
    element operator[](stdx::string_view key) const;

    ///
    /// Access the raw bytes of the underlying document.
    ///
    /// @return A (non-owning) pointer to the view's buffer.
    ///
    const std::uint8_t* data() const;

    ///
    /// Gets the length of the underlying buffer.
    ///
    /// @remark This is not the number of elements in the document.
    /// To compute the number of elements, use std::distance.
    ///
    /// @return The length of the document, in bytes.
    ///
    std::size_t length() const;

    friend BSONCXX_API bool operator==(view, view);
    friend BSONCXX_API bool operator!=(view, view);

   private:
    const std::uint8_t* _data;
    std::size_t _length;
};

class view::iterator : public std::iterator<std::forward_iterator_tag, element> {
   public:
    iterator();
    explicit iterator(const element& element);

    reference operator*();
    pointer operator->();

    iterator& operator++();
    iterator operator++(int);

    friend BSONCXX_API bool operator==(const iterator&, const iterator&);
    friend BSONCXX_API bool operator!=(const iterator&, const iterator&);

   private:
    element _element;
};

class view::const_iterator : public std::iterator<std::forward_iterator_tag, element, std::ptrdiff_t,
                                                  const element*, const element&> {
   public:
    const_iterator();
    explicit const_iterator(const element& element);

    reference operator*();
    pointer operator->();

    const_iterator& operator++();
    const_iterator operator++(int);

    friend BSONCXX_API bool operator==(const const_iterator&, const const_iterator&);
    friend BSONCXX_API bool operator!=(const const_iterator&, const const_iterator&);

   private:
    element _element;
};

}  // namespace document
BSONCXX_INLINE_NAMESPACE_END
}  // namespace bsoncxx

#include <bsoncxx/config/postlude.hpp>
<|endoftext|>


<commit_before>#include "buffer_cache/buf_patch.hpp"

/* For now, we have to include all buf_patches files here to allow deserialization */
#include "btree/buf_patches.hpp"

#include <string.h>
#include "utils.hpp"
#include "logger.hpp"

patch_deserialization_error_t::patch_deserialization_error_t(const char *file, int line, const char *msg) {
    message = strprintf("Patch deserialization error%s%s (in %s:%d)",
                            msg[0] ? ": " : "", msg, file, line);
}

buf_patch_t *buf_patch_t::load_patch(const char *source) {
    try {
        uint16_t remaining_length = *reinterpret_cast<const uint16_t *>(source);
        source += sizeof(remaining_length);
        if (remaining_length == 0)
            return NULL;
        remaining_length -= sizeof(remaining_length);
        guarantee_patch_format(remaining_length >= sizeof(block_id_t) + sizeof(patch_counter_t) + sizeof(patch_operation_code_t));
        block_id_t block_id = *reinterpret_cast<const block_id_t *>(source);
        source += sizeof(block_id_t);
        remaining_length -= sizeof(block_id_t);
        patch_counter_t patch_counter = *reinterpret_cast<const patch_counter_t *>(source);
        source += sizeof(patch_counter_t);
        remaining_length -= sizeof(block_id_t);
        block_sequence_id_t applies_to_block_sequence_id = *reinterpret_cast<const block_sequence_id_t *>(source);
        source += sizeof(block_sequence_id_t);
        remaining_length -= sizeof(block_sequence_id_t);
        patch_operation_code_t operation_code = *reinterpret_cast<const patch_operation_code_t *>(source);
        source += sizeof(patch_operation_code_t);
        remaining_length -= sizeof(patch_operation_code_t);

        buf_patch_t* result = NULL;
        switch (operation_code) {
	case OPER_MEMCPY:
	    result = new memcpy_patch_t(block_id, patch_counter, source, remaining_length); break;
	case OPER_MEMMOVE:
	    result = new memmove_patch_t(block_id, patch_counter, source, remaining_length); break;
	case OPER_LEAF_INSERT:
	    result = new leaf_insert_patch_t(block_id, patch_counter, source, remaining_length); break;
	case OPER_LEAF_REMOVE:
	    result = new leaf_remove_patch_t(block_id, patch_counter, source, remaining_length); break;
	case OPER_LEAF_ERASE_PRESENCE:
	    result = new leaf_erase_presence_patch_t(block_id, patch_counter, source, remaining_length); break;
	default:
	    guarantee_patch_format(false, "Unsupported patch operation code");
	    return NULL;
        }
        result->set_block_sequence_id(applies_to_block_sequence_id);
        return result;
    } catch (patch_deserialization_error_t &e) {
        logERR("%s\n", e.c_str());
        throw e;
    }
}

void buf_patch_t::serialize(char* destination) const {
    uint16_t length = get_serialized_size();
    memcpy(destination, &length, sizeof(length));
    destination += sizeof(length);
    memcpy(destination, &block_id, sizeof(block_id));
    destination += sizeof(block_id);
    memcpy(destination, &patch_counter, sizeof(patch_counter));
    destination += sizeof(patch_counter);
    memcpy(destination, &applies_to_block_sequence_id, sizeof(applies_to_block_sequence_id));
    destination += sizeof(applies_to_block_sequence_id);
    memcpy(destination, &operation_code, sizeof(operation_code));
    destination += sizeof(operation_code);
    serialize_data(destination);
}

buf_patch_t::buf_patch_t(const block_id_t _block_id, const patch_counter_t _patch_counter, const patch_operation_code_t _operation_code) :
            block_id(_block_id),
            patch_counter(_patch_counter),
            applies_to_block_sequence_id(NULL_BLOCK_SEQUENCE_ID),
            operation_code(_operation_code) {
}

bool buf_patch_t::applies_before(const buf_patch_t *p) const {
    rassert(block_id == p->block_id, "Tried to compare incomparable patches");
    return applies_to_block_sequence_id < p->applies_to_block_sequence_id
        || (applies_to_block_sequence_id == p->applies_to_block_sequence_id && patch_counter < p->patch_counter);
}

memcpy_patch_t::memcpy_patch_t(const block_id_t block_id, const patch_counter_t patch_counter, const uint16_t _dest_offset, const char* src, const uint16_t _n) :
            buf_patch_t(block_id, patch_counter, buf_patch_t::OPER_MEMCPY),
            dest_offset(_dest_offset),
            n(_n) {
    src_buf = new char[n];
    memcpy(src_buf, src, n);
}
memcpy_patch_t::memcpy_patch_t(const block_id_t block_id, const patch_counter_t patch_counter, const char* data, const uint16_t data_length)  :
            buf_patch_t(block_id, patch_counter, buf_patch_t::OPER_MEMCPY) {
    guarantee_patch_format(data_length >= sizeof(dest_offset) + sizeof(n));
    dest_offset = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(dest_offset);
    n = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(n);
    guarantee_patch_format(data_length == sizeof(dest_offset) + sizeof(n) + n);
    src_buf = new char[n];
    memcpy(src_buf, data, n);
    data += n;
}

void memcpy_patch_t::serialize_data(char* destination) const {
    memcpy(destination, &dest_offset, sizeof(dest_offset));
    destination += sizeof(dest_offset);
    memcpy(destination, &n, sizeof(n));
    destination += sizeof(n);
    memcpy(destination, src_buf, n);
    destination += n;
}
uint16_t memcpy_patch_t::get_data_size() const {
    return sizeof(dest_offset) + sizeof(n) + n;
}

memcpy_patch_t::~memcpy_patch_t() {
    delete[] src_buf;
}

void memcpy_patch_t::apply_to_buf(char* buf_data, UNUSED block_size_t bs) {
    memcpy(buf_data + dest_offset, src_buf, n);
}

memmove_patch_t::memmove_patch_t(const block_id_t block_id, const patch_counter_t patch_counter, const uint16_t _dest_offset, const uint16_t _src_offset, const uint16_t _n) :
            buf_patch_t(block_id, patch_counter, buf_patch_t::OPER_MEMMOVE),
            dest_offset(_dest_offset),
            src_offset(_src_offset),
            n(_n) { }

memmove_patch_t::memmove_patch_t(const block_id_t block_id, const patch_counter_t patch_counter, const char* data, const uint16_t data_length)  :
            buf_patch_t(block_id, patch_counter, buf_patch_t::OPER_MEMMOVE) {
    guarantee_patch_format(data_length == get_data_size());
    dest_offset = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(dest_offset);
    src_offset = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(src_offset);
    n = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(n);
}

void memmove_patch_t::serialize_data(char* destination) const {
    memcpy(destination, &dest_offset, sizeof(dest_offset));
    destination += sizeof(dest_offset);
    memcpy(destination, &src_offset, sizeof(src_offset));
    destination += sizeof(src_offset);
    memcpy(destination, &n, sizeof(n));
    destination += sizeof(n);
}
uint16_t memmove_patch_t::get_data_size() const {
    return sizeof(dest_offset) + sizeof(src_offset) + sizeof(n);
}

void memmove_patch_t::apply_to_buf(char* buf_data, UNUSED block_size_t bs) {
    memmove(buf_data + dest_offset, buf_data + src_offset, n);
}

<commit_msg>Curly braces.<commit_after>#include "buffer_cache/buf_patch.hpp"

/* For now, we have to include all buf_patches files here to allow deserialization */
#include "btree/buf_patches.hpp"

#include <string.h>
#include "utils.hpp"
#include "logger.hpp"

patch_deserialization_error_t::patch_deserialization_error_t(const char *file, int line, const char *msg) {
    message = strprintf("Patch deserialization error%s%s (in %s:%d)",
                            msg[0] ? ": " : "", msg, file, line);
}

buf_patch_t *buf_patch_t::load_patch(const char *source) {
    try {
        uint16_t remaining_length = *reinterpret_cast<const uint16_t *>(source);
        source += sizeof(remaining_length);
        if (remaining_length == 0) {
            return NULL;
        }
        remaining_length -= sizeof(remaining_length);
        guarantee_patch_format(remaining_length >= sizeof(block_id_t) + sizeof(patch_counter_t) + sizeof(patch_operation_code_t));
        block_id_t block_id = *reinterpret_cast<const block_id_t *>(source);
        source += sizeof(block_id_t);
        remaining_length -= sizeof(block_id_t);
        patch_counter_t patch_counter = *reinterpret_cast<const patch_counter_t *>(source);
        source += sizeof(patch_counter_t);
        remaining_length -= sizeof(block_id_t);
        block_sequence_id_t applies_to_block_sequence_id = *reinterpret_cast<const block_sequence_id_t *>(source);
        source += sizeof(block_sequence_id_t);
        remaining_length -= sizeof(block_sequence_id_t);
        patch_operation_code_t operation_code = *reinterpret_cast<const patch_operation_code_t *>(source);
        source += sizeof(patch_operation_code_t);
        remaining_length -= sizeof(patch_operation_code_t);

        buf_patch_t* result = NULL;
        switch (operation_code) {
	case OPER_MEMCPY:
	    result = new memcpy_patch_t(block_id, patch_counter, source, remaining_length); break;
	case OPER_MEMMOVE:
	    result = new memmove_patch_t(block_id, patch_counter, source, remaining_length); break;
	case OPER_LEAF_INSERT:
	    result = new leaf_insert_patch_t(block_id, patch_counter, source, remaining_length); break;
	case OPER_LEAF_REMOVE:
	    result = new leaf_remove_patch_t(block_id, patch_counter, source, remaining_length); break;
	case OPER_LEAF_ERASE_PRESENCE:
	    result = new leaf_erase_presence_patch_t(block_id, patch_counter, source, remaining_length); break;
	default:
	    guarantee_patch_format(false, "Unsupported patch operation code");
	    return NULL;
        }
        result->set_block_sequence_id(applies_to_block_sequence_id);
        return result;
    } catch (patch_deserialization_error_t &e) {
        logERR("%s\n", e.c_str());
        throw e;
    }
}

void buf_patch_t::serialize(char* destination) const {
    uint16_t length = get_serialized_size();
    memcpy(destination, &length, sizeof(length));
    destination += sizeof(length);
    memcpy(destination, &block_id, sizeof(block_id));
    destination += sizeof(block_id);
    memcpy(destination, &patch_counter, sizeof(patch_counter));
    destination += sizeof(patch_counter);
    memcpy(destination, &applies_to_block_sequence_id, sizeof(applies_to_block_sequence_id));
    destination += sizeof(applies_to_block_sequence_id);
    memcpy(destination, &operation_code, sizeof(operation_code));
    destination += sizeof(operation_code);
    serialize_data(destination);
}

buf_patch_t::buf_patch_t(const block_id_t _block_id, const patch_counter_t _patch_counter, const patch_operation_code_t _operation_code) :
            block_id(_block_id),
            patch_counter(_patch_counter),
            applies_to_block_sequence_id(NULL_BLOCK_SEQUENCE_ID),
            operation_code(_operation_code) {
}

bool buf_patch_t::applies_before(const buf_patch_t *p) const {
    rassert(block_id == p->block_id, "Tried to compare incomparable patches");
    return applies_to_block_sequence_id < p->applies_to_block_sequence_id
        || (applies_to_block_sequence_id == p->applies_to_block_sequence_id && patch_counter < p->patch_counter);
}

memcpy_patch_t::memcpy_patch_t(const block_id_t block_id, const patch_counter_t patch_counter, const uint16_t _dest_offset, const char* src, const uint16_t _n) :
            buf_patch_t(block_id, patch_counter, buf_patch_t::OPER_MEMCPY),
            dest_offset(_dest_offset),
            n(_n) {
    src_buf = new char[n];
    memcpy(src_buf, src, n);
}
memcpy_patch_t::memcpy_patch_t(const block_id_t block_id, const patch_counter_t patch_counter, const char* data, const uint16_t data_length)  :
            buf_patch_t(block_id, patch_counter, buf_patch_t::OPER_MEMCPY) {
    guarantee_patch_format(data_length >= sizeof(dest_offset) + sizeof(n));
    dest_offset = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(dest_offset);
    n = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(n);
    guarantee_patch_format(data_length == sizeof(dest_offset) + sizeof(n) + n);
    src_buf = new char[n];
    memcpy(src_buf, data, n);
    data += n;
}

void memcpy_patch_t::serialize_data(char* destination) const {
    memcpy(destination, &dest_offset, sizeof(dest_offset));
    destination += sizeof(dest_offset);
    memcpy(destination, &n, sizeof(n));
    destination += sizeof(n);
    memcpy(destination, src_buf, n);
    destination += n;
}
uint16_t memcpy_patch_t::get_data_size() const {
    return sizeof(dest_offset) + sizeof(n) + n;
}

memcpy_patch_t::~memcpy_patch_t() {
    delete[] src_buf;
}

void memcpy_patch_t::apply_to_buf(char* buf_data, UNUSED block_size_t bs) {
    memcpy(buf_data + dest_offset, src_buf, n);
}

memmove_patch_t::memmove_patch_t(const block_id_t block_id, const patch_counter_t patch_counter, const uint16_t _dest_offset, const uint16_t _src_offset, const uint16_t _n) :
            buf_patch_t(block_id, patch_counter, buf_patch_t::OPER_MEMMOVE),
            dest_offset(_dest_offset),
            src_offset(_src_offset),
            n(_n) { }

memmove_patch_t::memmove_patch_t(const block_id_t block_id, const patch_counter_t patch_counter, const char* data, const uint16_t data_length)  :
            buf_patch_t(block_id, patch_counter, buf_patch_t::OPER_MEMMOVE) {
    guarantee_patch_format(data_length == get_data_size());
    dest_offset = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(dest_offset);
    src_offset = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(src_offset);
    n = *reinterpret_cast<const uint16_t *>(data);
    data += sizeof(n);
}

void memmove_patch_t::serialize_data(char* destination) const {
    memcpy(destination, &dest_offset, sizeof(dest_offset));
    destination += sizeof(dest_offset);
    memcpy(destination, &src_offset, sizeof(src_offset));
    destination += sizeof(src_offset);
    memcpy(destination, &n, sizeof(n));
    destination += sizeof(n);
}
uint16_t memmove_patch_t::get_data_size() const {
    return sizeof(dest_offset) + sizeof(src_offset) + sizeof(n);
}

void memmove_patch_t::apply_to_buf(char* buf_data, UNUSED block_size_t bs) {
    memmove(buf_data + dest_offset, buf_data + src_offset, n);
}

<|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <math.h>
#include <iostream>

#include "angle.hpp"
#include "global_config.hpp"
#include "error.hpp"

using namespace mocc;

// Hide all of these constants from the rest of the world
namespace {
    real_t mu_base[] = {0.577350269189626, 0.350021000000000,
        0.266636000000000, 0.218218218218218, 0.192450089729876,
        0.174077655955702, 0.161575000000000, 0.149071198499989};

    real_t w_unique[] = {
        1.0,
        1.0/3.0,
        0.1761262, 0.1572071,
        0.1209876, 0.0907408, 0.0925925,
        0.0893043, 0.0725281, 0.0450455, 0.0539274,
        0.0707734, 0.0558760, 0.0373436, 0.0502654, 0.0258553,
        0.0580031, 0.0488943, 0.0228095, 0.0393955, 0.0380920, 0.0258382, 0.0082759,
        0.0489967, 0.0413235, 0.0203158, 0.0265468, 0.0378883, 0.0135404, 0.0326129, 0.0103825
    };

    int w_offset[] = {0, 1, 2, 4, 7, 11, 16, 23};

    int w_map[] = {
        1,
        1, 1, 1,
        1, 2, 2, 1, 2, 1,
        1, 2, 2, 2, 3, 2, 1, 2, 2, 1,
        1, 2, 2, 3, 4, 3, 2, 4, 4, 2, 1, 2, 3, 2, 1,
        1, 2, 2, 3, 5, 3, 4, 6, 6, 4, 3, 6, 7, 6, 3, 2, 5, 6, 6, 5, 2, 1, 2, 3, 4, 3, 2, 1,
        1, 2, 2, 3, 5, 3, 4, 6, 6, 4, 4, 7, 8, 7, 4, 3, 6, 8, 8, 6, 3, 2, 5, 6, 7, 6, 5, 2, 1, 2, 3, 4, 4, 3, 2, 1
    };

    int w_map_offset[] = { 0, 1, 4, 10, 20, 35, 63 };
}

// Produce a vector of angles matching the level-symmetric quadrature of order
// 'order'
std::vector<Angle> GenSn( int order ){

    if( order%2 != 0 ) {
        throw EXCEPT("Sn quadrature order must be even.");
    }
    if( order > 16 ) {
        throw EXCEPT("Max supported Sn quadrature order is 16.");
    }

    // n is the number of base cosines to use
    const int n = order/2;

    // set up the list of base cosines
    VecF mu;
    mu.push_back(mu_base[n-1]);
    if( order > 2) {
        const real_t delta_mu = 2.0 * ( 1.0 -
                3.0*(mu[0]*mu[0]) ) / (real_t)(order-2);
        for (int i=1; i<n; i++) {
            mu.push_back( sqrt(mu[0]*mu[0] + i*delta_mu) );
        }
    }

    // Alias the w_unique array to get a slice for the order we are interested
    // in.
    real_t* weights = &w_unique[w_offset[n-1]];
    // Alias into the w_map to get our indices
    int* map = &w_map[w_map_offset[n-1]];

    // Apply the permutations of the base cosines to get actual angles. We will
    // do this once for the first octant, then reflect around.
    std::vector<Angle> angles;
    real_t wsum = 0.0;
    int k=0;
    for( int i=0; i<n; i++ ) {
        for( int j=0; j<=i; j++ ) {
            Angle angle( mu[i-j],
                         mu[j],
                         mu[n-i-1],
                         weights[map[k]-1]);

            angles.push_back(angle);
            wsum += angle.weight;
            k++;
        }
    }

    // One of these days, i should calculate the weights algorithmically, rather
    // than storing in a table. For now, make sure the angular integral comes
    // out to 4*PI. We defined the angles above for one octant, so make sure
    // that the weights sum to 1 to machine precision.
    for( auto &a: angles ) {
        a.weight /= wsum;
    }

    return angles;

}
<commit_msg>added Yamamoto quad set<commit_after>#pragma once

#include <vector>
#include <math.h>
#include <iostream>

#include "angle.hpp"
#include "global_config.hpp"
#include "error.hpp"

using namespace mocc;

// Hide all of these constants from the rest of the world
namespace {
    real_t mu_base[] = {0.577350269189626, 0.350021000000000,
        0.266636000000000, 0.218218218218218, 0.192450089729876,
        0.174077655955702, 0.161575000000000, 0.149071198499989};

    real_t w_unique[] = {
        1.0,
        1.0/3.0,
        0.1761262, 0.1572071,
        0.1209876, 0.0907408, 0.0925925,
        0.0893043, 0.0725281, 0.0450455, 0.0539274,
        0.0707734, 0.0558760, 0.0373436, 0.0502654, 0.0258553,
        0.0580031, 0.0488943, 0.0228095, 0.0393955, 0.0380920, 0.0258382, 0.0082759,
        0.0489967, 0.0413235, 0.0203158, 0.0265468, 0.0378883, 0.0135404, 0.0326129, 0.0103825
    };

    int w_offset[] = {0, 1, 2, 4, 7, 11, 16, 23};

    int w_map[] = {
        1,
        1, 1, 1,
        1, 2, 2, 1, 2, 1,
        1, 2, 2, 2, 3, 2, 1, 2, 2, 1,
        1, 2, 2, 3, 4, 3, 2, 4, 4, 2, 1, 2, 3, 2, 1,
        1, 2, 2, 3, 5, 3, 4, 6, 6, 4, 3, 6, 7, 6, 3, 2, 5, 6, 6, 5, 2, 1, 2, 3, 4, 3, 2, 1,
        1, 2, 2, 3, 5, 3, 4, 6, 6, 4, 4, 7, 8, 7, 4, 3, 6, 8, 8, 6, 3, 2, 5, 6, 7, 6, 5, 2, 1, 2, 3, 4, 4, 3, 2, 1
    };

    int w_map_offset[] = { 0, 1, 4, 10, 20, 35, 63 };
}

// Produce a vector of angles matching the level-symmetric quadrature of order
// 'order'
std::vector<Angle> GenSn( int order ){

    if( order%2 != 0 ) {
        throw EXCEPT("Sn quadrature order must be even.");
    }
    if( order > 16 ) {
        throw EXCEPT("Max supported Sn quadrature order is 16.");
    }

    // n is the number of base cosines to use
    const int n = order/2;

    // set up the list of base cosines
    VecF mu;
    mu.push_back(mu_base[n-1]);
    if( order > 2) {
        const real_t delta_mu = 2.0 * ( 1.0 -
                3.0*(mu[0]*mu[0]) ) / (real_t)(order-2);
        for (int i=1; i<n; i++) {
            mu.push_back( sqrt(mu[0]*mu[0] + i*delta_mu) );
        }
    }

    // Alias the w_unique array to get a slice for the order we are interested
    // in.
    real_t* weights = &w_unique[w_offset[n-1]];
    // Alias into the w_map to get our indices
    int* map = &w_map[w_map_offset[n-1]];

    // Apply the permutations of the base cosines to get actual angles. We will
    // do this once for the first octant, then reflect around.
    std::vector<Angle> angles;
    real_t wsum = 0.0;
    int k=0;
    for( int i=0; i<n; i++ ) {
        for( int j=0; j<=i; j++ ) {
            Angle angle( mu[i-j],
                         mu[j],
                         mu[n-i-1],
                         weights[map[k]-1]);

            angles.push_back(angle);
            wsum += angle.weight;
            k++;
        }
    }

    // One of these days, i should calculate the weights algorithmically, rather
    // than storing in a table. For now, make sure the angular integral comes
    // out to 4*PI. We defined the angles above for one octant, so make sure
    // that the weights sum to 1 to machine precision.
    for( auto &a: angles ) {
        a.weight /= wsum;
    }

    return angles;

}

// Produce a vector of pairs for Yamamoto quadrature set of order 'order'.
// Currently, only order 3 is supported. The first value in the pair is theta in
// range (0, PI/2) and the second value is the corresponding weight. All weights
// sum to 1.
vector<pair<real_t,real_t>> genYamamoto( int order){

    vector<pair<real_t,real_t>> thetaWeightPairVec;
    if ( order != 3 ) {
        throw EXCEPT("Only support Yamamoto quadrature of order 3");
    }
    thetaWeightPairVec.emplace_back(0.167429147795000,4.623300000000000E-002);
    thetaWeightPairVec.emplace_back(0.567715121084000,0.283619000000000);
    thetaWeightPairVec.emplace_back(1.20253314678900,0.670148000000000);
}

// Produce a vector of angles matching the Chebyshev-Gaussian quadrature of
// order 'azi-order' for azimuthal angles and 'polar-order' for polar
// angles.
std::vector<Angle> GenCG( int azi_order, int polar_order ){

}

// Produce a vector of angles matching the Chebyshev-Yamamoto quadrature of
// order 'azimuthal-order' for azimuthal angles and 'polar-order' for polar
// angles.
<|endoftext|>