<commit_before>//*******************************************************************
//glfont2.cpp -- glFont Version 2.0 implementation
//Copyright (c) 1998-2002 Brad Fish
//See glfont.html for terms of use
//May 14, 2002
//*******************************************************************

//STL headers
#include <string>
#include <utility>
#include <iostream>
#include <fstream>
using namespace std;

//OpenGL headers
#ifdef _WINDOWS
#include <windows.h>
#endif
#include <GL/gl.h>

//glFont header
#include "glfont2.h"
using namespace glfont;

//*******************************************************************
//GLFont Class Implementation
//*******************************************************************
GLFont::GLFont ()
{
	//Initialize header to safe state
	header.tex = -1;
	header.tex_width = 0;
	header.tex_height = 0;
	header.start_char = 0;
	header.end_char = 0;
	header.chars = NULL;
}
//*******************************************************************
GLFont::~GLFont ()
{
	//Destroy the font
	Destroy();
}
//*******************************************************************
bool GLFont::Create (const char *file_name, int tex)
{
	ifstream input;
	int num_chars, num_tex_bytes;
	char *tex_bytes;

	//Destroy the old font if there was one, just to be safe
	Destroy();

	//Open input file
	input.open(file_name, ios::in | ios::binary);
	if (!input)
		return false;

	//Read the header from file
	//There is 4 byte space between the header data and the beginning of the
	//characters. this presumably was used to account for the 4 bytes taken
	//up by the pointer to the character array
	//on 64-bit the sizeof(header) is no longer correct and it reads to many
	//bytes
	input.read((char *)&header, sizeof(header) - (sizeof(void*) - 4));
	header.tex = tex;

	//Allocate space for character array
	num_chars = header.end_char - header.start_char + 1;
	if ((header.chars = new GLFontChar[num_chars]) == NULL)
		return false;

	//Read character array
	for(int i=0; i < num_chars; i++)
		input.read((char *)&header.chars[i], sizeof(GLFontChar));

	//Read texture pixel data
	num_tex_bytes = header.tex_width * header.tex_height * 2;
	tex_bytes = new char[num_tex_bytes];
	input.read(tex_bytes, num_tex_bytes);

	//Create OpenGL texture
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glTexImage2D(GL_TEXTURE_2D, 0, 2, header.tex_width,
		header.tex_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
		(void *)tex_bytes);

	//Free texture pixels memory
	delete[] tex_bytes;

	//Close input file
	input.close();

	//Return successfully

	//Uncomment to print out the data structure. Useful for finding differences between systems

/*	cout << "Start: " << header.start_char << ", End: " << header.end_char << ", Chars: " << header.chars << endl;
	cout << "Height: " << header.tex_height << ", Width: " << header.tex_width << endl;
	//Read character array
	for(int i=header.start_char; i < header.end_char; i++)
	{
		GLFontChar c = header.chars[i - header.start_char];
		cout << "Char: " << i << ", dx: " << c.dx << ", dy: " << c.dy << endl;
		cout << "ty1: " << c.ty1 << ", ty2: " << c.ty2 << ", tx1: " << c.tx1 << ", tx2: " << c.tx2 << endl;
	}*/

	return true;
}
//*******************************************************************
bool GLFont::Create (const std::string &file_name, int tex)
{
	return Create(file_name.c_str(), tex);
}
//*******************************************************************
void GLFont::Destroy (void)
{
	//Delete the character array if necessary
	if (header.chars)
	{
		delete[] header.chars;
		header.chars = NULL;
	}
}
//*******************************************************************
void GLFont::GetTexSize (std::pair<int, int> *size)
{
	//Retrieve texture size
	size->first = header.tex_width;
	size->second = header.tex_height;
}
//*******************************************************************
int GLFont::GetTexWidth (void)
{
	//Return texture width
	return header.tex_width;
}
//*******************************************************************
int GLFont::GetTexHeight (void)
{
	//Return texture height
	return header.tex_height;
}
//*******************************************************************
void GLFont::GetCharInterval (std::pair<int, int> *interval)
{
	//Retrieve character interval
	interval->first = header.start_char;
	interval->second = header.end_char;
}
//*******************************************************************
int GLFont::GetStartChar (void)
{
	//Return start character
	return header.start_char;
}
//*******************************************************************
int GLFont::GetEndChar (void)
{
	//Return end character
	return header.end_char;
}
//*******************************************************************
void GLFont::GetCharSize (int c, std::pair<int, int> *size)
{
	//Make sure character is in range
	if (c < header.start_char || c > header.end_char)
	{
		//Not a valid character, so it obviously has no size
		size->first = 0;
		size->second = 0;
	}
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character size
		glfont_char = &header.chars[c - header.start_char];
		size->first = (int)(glfont_char->dx * header.tex_width);
		size->second = (int)(glfont_char->dy *
			header.tex_height);
	}
}
//*******************************************************************
int GLFont::GetCharWidth (int c)
{
	//Make sure in range
	if (c < header.start_char || c > header.end_char)
		return 0;
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character width
		glfont_char = &header.chars[c - header.start_char];
		return (int)(glfont_char->dx * header.tex_width);
	}
}
//*******************************************************************
int GLFont::GetCharHeight (int c)
{
	//Make sure in range
	if (c < header.start_char || c > header.end_char)
		return 0;
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character height
		glfont_char = &header.chars[c - header.start_char];
		return (int)(glfont_char->dy * header.tex_height);
	}
}
//*******************************************************************
void GLFont::Begin (void)
{
	//Bind to font texture
	glBindTexture(GL_TEXTURE_2D, header.tex);
}
//*******************************************************************

//End of file

<commit_msg>I made a change for Torsten to fix "endianess problem with gl fonts", for an OSX build.<commit_after>//*******************************************************************
//glfont2.cpp -- glFont Version 2.0 implementation
//Copyright (c) 1998-2002 Brad Fish
//See glfont.html for terms of use
//May 14, 2002
//*******************************************************************

//STL headers
#include <string>
#include <utility>
#include <iostream>
#include <fstream>
using namespace std;

//OpenGL headers
#ifdef _WINDOWS
#include <windows.h>
#endif
#include <GL/gl.h>

//glFont header
#include "glfont2.h"
using namespace glfont;

#ifdef __BIG_ENDIAN__
inline void endian_swap(int& x)
{
    x = (x>>24) |
        ((x<<8) & 0x00FF0000) |
        ((x>>8) & 0x0000FF00) |
        (x<<24);
}
#endif

//*******************************************************************
//GLFont Class Implementation
//*******************************************************************
GLFont::GLFont ()
{
	//Initialize header to safe state
	header.tex = -1;
	header.tex_width = 0;
	header.tex_height = 0;
	header.start_char = 0;
	header.end_char = 0;
	header.chars = NULL;
}
//*******************************************************************
GLFont::~GLFont ()
{
	//Destroy the font
	Destroy();
}
//*******************************************************************
bool GLFont::Create (const char *file_name, int tex)
{
	ifstream input;
	int num_chars, num_tex_bytes;
	char *tex_bytes;

	//Destroy the old font if there was one, just to be safe
	Destroy();

	//Open input file
	input.open(file_name, ios::in | ios::binary);
	if (!input)
		return false;

	//Read the header from file
	//There is 4 byte space between the header data and the beginning of the
	//characters. this presumably was used to account for the 4 bytes taken
	//up by the pointer to the character array
	//on 64-bit the sizeof(header) is no longer correct and it reads to many
	//bytes
	input.read((char *)&header, sizeof(header) - (sizeof(void*) - 4));
	header.tex = tex;

	//Allocate space for character array
#ifdef __BIG_ENDIAN__
	endian_swap(header.end_char);
	endian_swap(header.start_char);
#endif
	num_chars = header.end_char - header.start_char + 1;
	if ((header.chars = new GLFontChar[num_chars]) == NULL)
		return false;

	//Read character array
	for(int i=0; i < num_chars; i++)
		input.read((char *)&header.chars[i], sizeof(GLFontChar));

	//Read texture pixel data
	num_tex_bytes = header.tex_width * header.tex_height * 2;
	tex_bytes = new char[num_tex_bytes];
	input.read(tex_bytes, num_tex_bytes);

	//Create OpenGL texture
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glTexImage2D(GL_TEXTURE_2D, 0, 2, header.tex_width,
		header.tex_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
		(void *)tex_bytes);

	//Free texture pixels memory
	delete[] tex_bytes;

	//Close input file
	input.close();

	//Return successfully

	//Uncomment to print out the data structure. Useful for finding differences between systems

/*	cout << "Start: " << header.start_char << ", End: " << header.end_char << ", Chars: " << header.chars << endl;
	cout << "Height: " << header.tex_height << ", Width: " << header.tex_width << endl;
	//Read character array
	for(int i=header.start_char; i < header.end_char; i++)
	{
		GLFontChar c = header.chars[i - header.start_char];
		cout << "Char: " << i << ", dx: " << c.dx << ", dy: " << c.dy << endl;
		cout << "ty1: " << c.ty1 << ", ty2: " << c.ty2 << ", tx1: " << c.tx1 << ", tx2: " << c.tx2 << endl;
	}*/

	return true;
}
//*******************************************************************
bool GLFont::Create (const std::string &file_name, int tex)
{
	return Create(file_name.c_str(), tex);
}
//*******************************************************************
void GLFont::Destroy (void)
{
	//Delete the character array if necessary
	if (header.chars)
	{
		delete[] header.chars;
		header.chars = NULL;
	}
}
//*******************************************************************
void GLFont::GetTexSize (std::pair<int, int> *size)
{
	//Retrieve texture size
	size->first = header.tex_width;
	size->second = header.tex_height;
}
//*******************************************************************
int GLFont::GetTexWidth (void)
{
	//Return texture width
	return header.tex_width;
}
//*******************************************************************
int GLFont::GetTexHeight (void)
{
	//Return texture height
	return header.tex_height;
}
//*******************************************************************
void GLFont::GetCharInterval (std::pair<int, int> *interval)
{
	//Retrieve character interval
	interval->first = header.start_char;
	interval->second = header.end_char;
}
//*******************************************************************
int GLFont::GetStartChar (void)
{
	//Return start character
	return header.start_char;
}
//*******************************************************************
int GLFont::GetEndChar (void)
{
	//Return end character
	return header.end_char;
}
//*******************************************************************
void GLFont::GetCharSize (int c, std::pair<int, int> *size)
{
	//Make sure character is in range
	if (c < header.start_char || c > header.end_char)
	{
		//Not a valid character, so it obviously has no size
		size->first = 0;
		size->second = 0;
	}
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character size
		glfont_char = &header.chars[c - header.start_char];
		size->first = (int)(glfont_char->dx * header.tex_width);
		size->second = (int)(glfont_char->dy *
			header.tex_height);
	}
}
//*******************************************************************
int GLFont::GetCharWidth (int c)
{
	//Make sure in range
	if (c < header.start_char || c > header.end_char)
		return 0;
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character width
		glfont_char = &header.chars[c - header.start_char];
		return (int)(glfont_char->dx * header.tex_width);
	}
}
//*******************************************************************
int GLFont::GetCharHeight (int c)
{
	//Make sure in range
	if (c < header.start_char || c > header.end_char)
		return 0;
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character height
		glfont_char = &header.chars[c - header.start_char];
		return (int)(glfont_char->dy * header.tex_height);
	}
}
//*******************************************************************
void GLFont::Begin (void)
{
	//Bind to font texture
	glBindTexture(GL_TEXTURE_2D, header.tex);
}
//*******************************************************************

//End of file

<|endoftext|>


<commit_before>#include <aery32/all.h>
#include "board.h"

#define LED AVR32_PIN_PC04

volatile bool pa00 = false;

using namespace aery;

void isrhandler_group2(void)
{
	pa00 = gpio_read_pin(AVR32_PIN_PA00);
	delay_ms(10);
	if (gpio_read_pin(AVR32_PIN_PA00) == pa00) { /* Still connected? */
		gpio_toggle_pin(LED);
	}
	porta->ifrc = (1 << 0); /* Remember to clear the interrupt */
}

int main(void)
{
	/*
	 * Put your application initialization sequence here. The default
	 * board initializer defines all pins as input and sets the CPU clock
	 * speed to 66 MHz.
	 */
	board::init();
	gpio_init_pin(LED, GPIO_OUTPUT|GPIO_HIGH);

	/* GPIO pins 0-13 can be "wired" to int group 2, see datasheet p. 42 */
	gpio_init_pin(AVR32_PIN_PA00, GPIO_INPUT|GPIO_PULLUP|GPIO_INT_PIN_CHANGE);

	/* Init interrupt controller */
	intc_init();
	intc_register_isrhandler(
		&isrhandler_group2, /* Function pointer to the ISR handler */
		2, /* Interrupt group number */
		0  /* Priority level */
	);

	/* Enable interrupts globally */
	intc_enable_globally();

	for(;;) {
		/*
		 * Now try to connect PA00 to GND and then disconnecting it
		 * to let the pull-up to set the pin state high again. The LED
		 * should toggle on the pin change.
		 */

	}

	return 0;
}
<commit_msg>Update gpio_extint_pin_change.cpp<commit_after>#include <aery32/all.h>
#include "board.h"

#define LED AVR32_PIN_PC04

volatile bool pa00 = false;

using namespace aery;

void isrhandler_group2(void)
{
	pa00 = gpio_read_pin(AVR32_PIN_PA00);
	delay_ms(100);
	if (gpio_read_pin(AVR32_PIN_PA00) == pa00) { /* State remains? */
		gpio_toggle_pin(LED);
	}
	porta->ifrc = (1 << 0); /* Remember to clear the interrupt */
}

int main(void)
{
	/*
	 * Put your application initialization sequence here. The default
	 * board initializer defines all pins as input and sets the CPU clock
	 * speed to 66 MHz.
	 */
	board::init();
	gpio_init_pin(LED, GPIO_OUTPUT|GPIO_HIGH);

	/* GPIO pins 0-13 can be "wired" to int group 2, see datasheet p. 42 */
	gpio_init_pin(AVR32_PIN_PA00, GPIO_INPUT|GPIO_PULLUP|GPIO_INT_PIN_CHANGE);

	/* Init interrupt controller */
	intc_init();
	intc_register_isrhandler(
		&isrhandler_group2, /* Function pointer to the ISR handler */
		2, /* Interrupt group number */
		0  /* Priority level */
	);

	/* Enable interrupts globally */
	intc_enable_globally();

	for(;;) {
		/*
		 * Now try to connect PA00 to GND and then disconnecting it
		 * to let the pull-up to set the pin state high again. The LED
		 * should toggle on the pin change.
		 */

	}

	return 0;
}
<|endoftext|>


<commit_before>#include <act-common/common.h>

// ========================================================================
// ===================== Critical Macrodefinitions ========================
// ========================================================================

/*
 * FOSC = 1MHz is confugured via Flash Fuses CKSEL=1 and SUT=2.
 */

#define BAUD_RATE    4800    // 4.8kbps
#define FOSC         1000000 // 1MHz
#define TC2_PRESCALE 1       // no Timer/Counter2 prescale

#include <act-photo/usart.h>
#include <act-photo/pwm.h>

#define REMUX(c) ADMUX = (3<<REFS0)|(1<<ADLAR)|(c<<MUX0)

// ========================================================================
// ===================== Initialization ===================================
// ========================================================================

inline __monitor void init()
{
    /* USART initialization */
    usart_init();
    /* Timer/Counter2 initialization */
    init_tc2_wg();
    /* ADC initialization (1/8 prescaling,
       1st channel, internal Vref, left alignment) */
    REMUX(0);
    ADCSR = (1<<ADEN)|(3<<ADPS0);

    /* Pin configuration */
    PORTB = (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2)|
            (0<<PORTB3)|(1<<PORTB4)|(1<<PORTB5)|
            (1<<PORTB6)|(1<<PORTB7);
    DDRB = (0<<DDB0)|(0<<DDB1)|(0<<DDB2)|
           (1<<DDB3)|(0<<DDB4)|(0<<DDB5)|
           (0<<DDB6)|(0<<DDB7);
    PORTC = (0<<PORTC0)|(0<<PORTC1)|(1<<PORTC2)|
            (1<<PORTC3)|(1<<PORTC4)|(1<<PORTC5)|
            (1<<PORTC6);
    DDRC = (0<<DDC0)|(0<<DDC1)|(0<<DDC2)|
           (0<<DDC3)|(0<<DDC4)|(0<<DDC5)|
           (0<<DDC6);
    PORTD = (0<<PORTD0)|(0<<PORTD1)|(1<<PORTD2)|
            (1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5)|
            (1<<PORTD6)|(1<<PORTD7);
    DDRD = (0<<DDD0)|(1<<DDD1)|(0<<DDD2)|
           (0<<DDD3)|(0<<DDD4)|(0<<DDD5)|
           (0<<DDD6)|(0<<DDD7);
}

// ========================================================================
// ===================== Common Variables =================================
// ========================================================================

/*
 * #40 <bug> <enchancement>
 *
 *     Modify coefficient format.
 *
 * Let C = one of { KP KI KS }.
 *
 *     C * x = (M * x) >> d
 *
 * Since ATMega8 does not support floating point operations,
 * and just (x << d) or (x >> d) cannot provide precise regulation.
 */

unsigned int kp_m = 0; byte kp_d = 0;   /* proportional factor */
unsigned int ki_m = 0; byte ki_d = 0;   /* integral factor     */
unsigned int ks_m = 0; byte ks_d = 0;   /* scale factor        */

#define COEF(c, x) (((long) x) * (c##_m)) >> (c##_d)

bool  pause  = false; /* paused state                          */
bool  sync   = false; /* USART async/sync transmit operation   */

byte  adc1, adc2;     /* ADC 1st and 2nd channel               */

int   int_err = 0;    /* integral error                        */
int   cur_err = 0;    /* current error                         */
int   pwm     = 0;    /* PWM                                   */

// ========================================================================
// ===================== Message Loop Variables ===========================
// ========================================================================

/*
 * #33 <enchancement>
 *
 *     Simplify IO protocol.
 *
 * The new protocol is user-friendly and quite simple.
 * The typical command starts with `METHOD`
 * (1 byte: `SET`, `GET`, `ECHO`, etc.). The next byte is
 * method-dependent. E.g. `VARIABLE` for `SET` and `GET`.
 * `SET` method also requires the variable value (1..any bytes)
 * to be set.
 *
 * COMMAND = METHOD [CONTENT]
 * METHOD = `SET` | `GET` | `ECHO` | BYTE
 * CONTENT = {
 *     METHOD=`SET`  => VARIABLE [DATA],
 *     METHOD=`GET`  => VARIABLE,
 *     METHOD=`ECHO` => BYTE,
 *     METHOD=BYTE   => any
 * }
 * VARIABLE = BYTE
 * DATA = any
 *
 * BYTE = 1 any byte
 * any = any bytes
 */

byte command_method;
bool command_present = false;
byte command_variable;
bool command_variable_present = false;

/*
 * #47 <enchancement>
 *
 *     Add `COEFS` variable and `PACKET` output format
 *     to support controller-gui tool.
 *
 * Data packet GET format is:
 *     <0 ADC1 ADC2 CUR_ERR INT_ERR PWM OCR2>
 * Coefficient packet SET format is:
 *     <KP KI KS>
 */

#define METHOD_GET     (byte) 0
#define METHOD_SET     (byte) 1
#define METHOD_ECHO    (byte) 2

// SET
#define VAR_PAUSE      (byte) 0
#define VAR_SYNC_USART (byte) 1
#define VAR_KP         (byte) 2
#define VAR_KI         (byte) 3
#define VAR_KS         (byte) 4
#define VAR_COEFS      (byte) 5

// GET
#define NO_OUTPUT      (byte) 0
#define VAR_ADC1       (byte) 1
#define VAR_ADC2       (byte) 2
#define VAR_INT_ERR    (byte) 3
#define VAR_CUR_ERR    (byte) 4
#define VAR_PWM        (byte) 5
#define VAR_OCR2       (byte) 6
#define VAR_PACKET     (byte) 7

byte output_mode = NO_OUTPUT;

// ========================================================================
// ===================== Utility Functions ================================
// ========================================================================

void send_all(byte *data, byte size)
{
    if (!sync)
    {
        transmit_all(data, size);
    }
    else
    {
        while (!transmit_all(data, size)) // wait in sync mode
            ;
    }
}

void send_byte(byte data)
{
    send_all(&data, 1);
}

void send_int(unsigned int data)
{
    byte hi_lo[2] = { (byte) (data >> 8), (byte) (data & 0xff) };
    send_all(hi_lo, 2);
}

void send_packet(/* byte adc1, byte adc2, int cur_err, int int_err, int pwm, byte OCR2 */)
{
    /*
     * #53 <enchancement>
     *     Review the packet format.
     *
     * The new packet format is < delimiter | data | checksum >,
     * where checksum is calculated as delimiter ^ adc1 ^ (cerr & 0xff) ^ ocr2.
     */

    byte packet[11] = {
       103,
       adc1,
       adc2,
       ((unsigned int) cur_err) >> 8, cur_err & 0xff,
       ((unsigned int) int_err) >> 8, int_err & 0xff,
       ((unsigned int) pwm) >> 8,     pwm     & 0xff,
       OCR2
    };
    packet[10] = packet[0] ^ packet[1] ^ packet[4] ^ packet[9];
    send_all(packet, 11);
}

// ========================================================================
// ===================== Command Processors ===============================
// ========================================================================

bool process_set_variable()
{
    byte packet[9];
    switch(command_variable)
    {
    case VAR_PAUSE:
        if (!receive(&packet[0])) return false; // wait for the value
        pause = packet[0];
        break;
    case VAR_SYNC_USART:
        if (!receive(packet)) return false; // wait for the value
        sync = packet[0];
        break;
    case VAR_KP:
        if (!receive_all(packet, 3)) return false; // wait for the value
        kp_m = (((unsigned int) packet[0]) << 8) | (packet[1]);
        kp_d = packet[2];
        break;
    case VAR_KI:
        if (!receive_all(packet, 3)) return false; // wait for the value
        ki_m = (((unsigned int) packet[0]) << 8) | (packet[1]);
        ki_d = packet[2];
        break;
    case VAR_KS:
        if (!receive_all(packet, 3)) return false; // wait for the value
        ks_m = (((unsigned int) packet[0]) << 8) | (packet[1]);
        ks_d = packet[2];
        break;
    case VAR_COEFS:
        if (!receive_all(packet, 9)) return false; // wait for the value
        kp_m = (((unsigned int) packet[0]) << 8) | (packet[1]);
        kp_d = packet[2];
        ki_m = (((unsigned int) packet[3]) << 8) | (packet[4]);
        ki_d = packet[5];
        ks_m = (((unsigned int) packet[6]) << 8) | (packet[7]);
        ks_d = packet[8];
        break;
    }
    return true;
}

void process_command()
{
    byte echo_value;
    switch(command_method)
    {
    case METHOD_ECHO:
        if (!receive(&echo_value)) return; // wait for the value to send back
        send_byte(echo_value);
        break;
    case METHOD_GET:
        if (!receive(&output_mode)) return; // wait for the variable
        break;
    case METHOD_SET:
        // wait for the variable
        if (!command_variable_present)
        {
            if (!(command_variable_present = receive(&command_variable))) return;
        }
        if (!process_set_variable()) return; // wait for the argument(s)
        break;
    }
    command_present = false;
    command_variable_present = false;
}

// ========================================================================
// ===================== Program Logic ====================================
// ========================================================================

void do_computations()
{
    /* Read ADC input */

    REMUX(0);                       /* 1st ADC channel                    */
    ADCSR |= (1 << ADSC);           /* Initialize single-ended conversion */
    while(!(ADCSR & (1 << ADIF)))   /* Wait for the end of the conversion */
      ;
    adc1 = ADCH;                    /* Read the 8-bit conversion result   */
    ADCSR &= ~(1 << ADIF);          /* Clear Conversion Complete flag     */

    REMUX(1);                       /* 2nd ADC channel                    */
    ADCSR |= (1 << ADSC);           /* Initialize single-ended conversion */
    while(!(ADCSR & (1 << ADIF)))   /* Wait for the end of the conversion */
      ;
    adc2 = ADCH;                    /* Read the 8-bit conversion result   */
    ADCSR &= ~(1 << ADIF);          /* Clear Conversion Complete flag     */

    /* Calculate PWM width */

    /*
     * pwm = KP * e + KI * err
     */

    cur_err = ((int)(adc2) - (int)(adc1));

    long p = COEF(kp, cur_err), q = COEF(ki, int_err);
    if (ABS(p) > INT_MAX) p = ((p < 0) ? (INT_MIN) : (INT_MAX));
    if (ABS(q) > INT_MAX) q = ((q < 0) ? (INT_MIN) : (INT_MAX));
    pwm = safe_add((int) p, (int) q);

    int_err = safe_add(int_err, cur_err);

    /* Setup PWM width */

    long t = COEF(ks, pwm) + INT_MAX;
    if (ABS(t) > INT_MAX) t = ((p < 0) ? (INT_MIN) : (INT_MAX));

    OCR2 = (((unsigned int) t) + INT_MAX) >> 8;

    /* Report back */

    switch(output_mode)
    {
    case NO_OUTPUT:
        break;
    case VAR_ADC1:
        send_byte(adc1);
        break;
    case VAR_ADC2:
        send_byte(adc2);
        break;
    case VAR_INT_ERR:
        send_int(int_err);
        break;
    case VAR_CUR_ERR:
        send_int(cur_err);
        break;
    case VAR_PWM:
        send_int(pwm);
        break;
    case VAR_OCR2:
        send_byte(OCR2);
        break;
    case VAR_PACKET:
        send_packet();
        break;
    }
}

// ========================================================================
// ===================== Program Entry Point ==============================
// ========================================================================

int main()
{

    /* Initialization here */

    init();

    __enable_interrupt();

    /* Program Loop */

    for(;;)
    {

        /* Message Loop */

        if (command_present)
        {
            process_command();
        }
        else
        {
            command_present = receive(&command_method);
        }

        /* Program Body */

        if (!pause)
        {
            do_computations();
        }

    }

    return 0;
}
<commit_msg>/mc/controller adaptation to use new usart.h<commit_after>#include <act-common/common.h>

// ========================================================================
// ===================== Critical Macrodefinitions ========================
// ========================================================================

/*
 * FOSC = 1MHz is confugured via Flash Fuses CKSEL=1 and SUT=2.
 */

#define BAUD_RATE    4800    // 4.8kbps
#define FOSC         1000000 // 1MHz
#define TC2_PRESCALE 1       // no Timer/Counter2 prescale

#include <act-photo/usart.h>
#include <act-photo/pwm.h>

#define REMUX(c) ADMUX = (3<<REFS0)|(1<<ADLAR)|(c<<MUX0)

// ========================================================================
// ===================== Initialization ===================================
// ========================================================================

inline __monitor void init()
{
    /* USART initialization */
    usart_init();
    /* Timer/Counter2 initialization */
    init_tc2_wg();
    /* ADC initialization (1/8 prescaling,
       1st channel, internal Vref, left alignment) */
    REMUX(0);
    ADCSR = (1<<ADEN)|(3<<ADPS0);

    /* Pin configuration */
    PORTB = (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2)|
            (0<<PORTB3)|(1<<PORTB4)|(1<<PORTB5)|
            (1<<PORTB6)|(1<<PORTB7);
    DDRB = (0<<DDB0)|(0<<DDB1)|(0<<DDB2)|
           (1<<DDB3)|(0<<DDB4)|(0<<DDB5)|
           (0<<DDB6)|(0<<DDB7);
    PORTC = (0<<PORTC0)|(0<<PORTC1)|(1<<PORTC2)|
            (1<<PORTC3)|(1<<PORTC4)|(1<<PORTC5)|
            (1<<PORTC6);
    DDRC = (0<<DDC0)|(0<<DDC1)|(0<<DDC2)|
           (0<<DDC3)|(0<<DDC4)|(0<<DDC5)|
           (0<<DDC6);
    PORTD = (0<<PORTD0)|(0<<PORTD1)|(1<<PORTD2)|
            (1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5)|
            (1<<PORTD6)|(1<<PORTD7);
    DDRD = (0<<DDD0)|(1<<DDD1)|(0<<DDD2)|
           (0<<DDD3)|(0<<DDD4)|(0<<DDD5)|
           (0<<DDD6)|(0<<DDD7);
}

// ========================================================================
// ===================== Common Variables =================================
// ========================================================================

/*
 * #40 <bug> <enchancement>
 *
 *     Modify coefficient format.
 *
 * Let C = one of { KP KI KS }.
 *
 *     C * x = (M * x) >> d
 *
 * Since ATMega8 does not support floating point operations,
 * and just (x << d) or (x >> d) cannot provide precise regulation.
 */

unsigned int kp_m = 0; byte kp_d = 0;   /* proportional factor */
unsigned int ki_m = 0; byte ki_d = 0;   /* integral factor     */
unsigned int ks_m = 0; byte ks_d = 0;   /* scale factor        */

#define COEF(c, x) (((long) x) * (c##_m)) >> (c##_d)

bool  pause  = false; /* paused state                          */
bool  sync   = false; /* USART async/sync transmit operation   */

byte  adc1, adc2;     /* ADC 1st and 2nd channel               */

int   int_err = 0;    /* integral error                        */
int   cur_err = 0;    /* current error                         */
int   pwm     = 0;    /* PWM                                   */

// ========================================================================
// ===================== Message Loop Variables ===========================
// ========================================================================

/*
 * #33 <enchancement>
 *
 *     Simplify IO protocol.
 *
 * The new protocol is user-friendly and quite simple.
 * The typical command starts with `METHOD`
 * (1 byte: `SET`, `GET`, `ECHO`, etc.). The next byte is
 * method-dependent. E.g. `VARIABLE` for `SET` and `GET`.
 * `SET` method also requires the variable value (1..any bytes)
 * to be set.
 *
 * COMMAND = METHOD [CONTENT]
 * METHOD = `SET` | `GET` | `ECHO` | BYTE
 * CONTENT = {
 *     METHOD=`SET`  => VARIABLE [DATA],
 *     METHOD=`GET`  => VARIABLE,
 *     METHOD=`ECHO` => BYTE,
 *     METHOD=BYTE   => any
 * }
 * VARIABLE = BYTE
 * DATA = any
 *
 * BYTE = 1 any byte
 * any = any bytes
 */

byte command_method;
bool command_present = false;
byte command_variable;
bool command_variable_present = false;

/*
 * #47 <enchancement>
 *
 *     Add `COEFS` variable and `PACKET` output format
 *     to support controller-gui tool.
 *
 * Data packet GET format is:
 *     <0 ADC1 ADC2 CUR_ERR INT_ERR PWM OCR2>
 * Coefficient packet SET format is:
 *     <KP KI KS>
 */

#define METHOD_GET     (byte) 0
#define METHOD_SET     (byte) 1
#define METHOD_ECHO    (byte) 2

// SET
#define VAR_PAUSE      (byte) 0
#define VAR_SYNC_USART (byte) 1
#define VAR_KP         (byte) 2
#define VAR_KI         (byte) 3
#define VAR_KS         (byte) 4
#define VAR_COEFS      (byte) 5

// GET
#define NO_OUTPUT      (byte) 0
#define VAR_ADC1       (byte) 1
#define VAR_ADC2       (byte) 2
#define VAR_INT_ERR    (byte) 3
#define VAR_CUR_ERR    (byte) 4
#define VAR_PWM        (byte) 5
#define VAR_OCR2       (byte) 6
#define VAR_PACKET     (byte) 7

byte output_mode = NO_OUTPUT;

// ========================================================================
// ===================== Utility Functions ================================
// ========================================================================

inline byte transmit_all(byte * src, byte length)
{
    return iobuf_write < sp_process_full, lp_use_lock > (usart_obuf, src, length);
}

inline byte receive_all(byte * dst, byte length)
{
    return iobuf_read < sp_process_full, lp_use_lock > (dst, usart_ibuf, length);
}

inline byte receive(byte * dst)
{
    return iobuf_read < lp_use_lock > (*dst, usart_ibuf);
}

void send_all(byte *data, byte size)
{
    if (!sync)
    {
        transmit_all(data, size);
    }
    else
    {
        while (!transmit_all(data, size)) // wait in sync mode
            ;
    }
}

void send_byte(byte data)
{
    send_all(&data, 1);
}

void send_int(unsigned int data)
{
    byte hi_lo[2] = { (byte) (data >> 8), (byte) (data & 0xff) };
    send_all(hi_lo, 2);
}

void send_packet(/* byte adc1, byte adc2, int cur_err, int int_err, int pwm, byte OCR2 */)
{
    /*
     * #53 <enchancement>
     *     Review the packet format.
     *
     * The new packet format is < delimiter | data | checksum >,
     * where checksum is calculated as delimiter ^ adc1 ^ (cerr & 0xff) ^ ocr2.
     */

    byte packet[11] = {
       103,
       adc1,
       adc2,
       ((unsigned int) cur_err) >> 8, cur_err & 0xff,
       ((unsigned int) int_err) >> 8, int_err & 0xff,
       ((unsigned int) pwm) >> 8,     pwm     & 0xff,
       OCR2
    };
    packet[10] = packet[0] ^ packet[1] ^ packet[4] ^ packet[9];
    send_all(packet, 11);
}

// ========================================================================
// ===================== Command Processors ===============================
// ========================================================================

bool process_set_variable()
{
    byte packet[9];
    switch(command_variable)
    {
    case VAR_PAUSE:
        if (!receive(&packet[0])) return false; // wait for the value
        pause = packet[0];
        break;
    case VAR_SYNC_USART:
        if (!receive(packet)) return false; // wait for the value
        sync = packet[0];
        break;
    case VAR_KP:
        if (!receive_all(packet, 3)) return false; // wait for the value
        kp_m = (((unsigned int) packet[0]) << 8) | (packet[1]);
        kp_d = packet[2];
        break;
    case VAR_KI:
        if (!receive_all(packet, 3)) return false; // wait for the value
        ki_m = (((unsigned int) packet[0]) << 8) | (packet[1]);
        ki_d = packet[2];
        break;
    case VAR_KS:
        if (!receive_all(packet, 3)) return false; // wait for the value
        ks_m = (((unsigned int) packet[0]) << 8) | (packet[1]);
        ks_d = packet[2];
        break;
    case VAR_COEFS:
        if (!receive_all(packet, 9)) return false; // wait for the value
        kp_m = (((unsigned int) packet[0]) << 8) | (packet[1]);
        kp_d = packet[2];
        ki_m = (((unsigned int) packet[3]) << 8) | (packet[4]);
        ki_d = packet[5];
        ks_m = (((unsigned int) packet[6]) << 8) | (packet[7]);
        ks_d = packet[8];
        break;
    }
    return true;
}

void process_command()
{
    byte echo_value;
    switch(command_method)
    {
    case METHOD_ECHO:
        if (!receive(&echo_value)) return; // wait for the value to send back
        send_byte(echo_value);
        break;
    case METHOD_GET:
        if (!receive(&output_mode)) return; // wait for the variable
        break;
    case METHOD_SET:
        // wait for the variable
        if (!command_variable_present)
        {
            if (!(command_variable_present = receive(&command_variable))) return;
        }
        if (!process_set_variable()) return; // wait for the argument(s)
        break;
    }
    command_present = false;
    command_variable_present = false;
}

// ========================================================================
// ===================== Program Logic ====================================
// ========================================================================

void do_computations()
{
    /* Read ADC input */

    REMUX(0);                       /* 1st ADC channel                    */
    ADCSR |= (1 << ADSC);           /* Initialize single-ended conversion */
    while(!(ADCSR & (1 << ADIF)))   /* Wait for the end of the conversion */
      ;
    adc1 = ADCH;                    /* Read the 8-bit conversion result   */
    ADCSR &= ~(1 << ADIF);          /* Clear Conversion Complete flag     */

    REMUX(1);                       /* 2nd ADC channel                    */
    ADCSR |= (1 << ADSC);           /* Initialize single-ended conversion */
    while(!(ADCSR & (1 << ADIF)))   /* Wait for the end of the conversion */
      ;
    adc2 = ADCH;                    /* Read the 8-bit conversion result   */
    ADCSR &= ~(1 << ADIF);          /* Clear Conversion Complete flag     */

    /* Calculate PWM width */

    /*
     * pwm = KP * e + KI * err
     */

    cur_err = ((int)(adc2) - (int)(adc1));

    long p = COEF(kp, cur_err), q = COEF(ki, int_err);
    if (ABS(p) > INT_MAX) p = ((p < 0) ? (INT_MIN) : (INT_MAX));
    if (ABS(q) > INT_MAX) q = ((q < 0) ? (INT_MIN) : (INT_MAX));
    pwm = safe_add((int) p, (int) q);

    int_err = safe_add(int_err, cur_err);

    /* Setup PWM width */

    long t = COEF(ks, pwm) + INT_MAX;
    if (ABS(t) > INT_MAX) t = ((p < 0) ? (INT_MIN) : (INT_MAX));

    OCR2 = (((unsigned int) t) + INT_MAX) >> 8;

    /* Report back */

    switch(output_mode)
    {
    case NO_OUTPUT:
        break;
    case VAR_ADC1:
        send_byte(adc1);
        break;
    case VAR_ADC2:
        send_byte(adc2);
        break;
    case VAR_INT_ERR:
        send_int(int_err);
        break;
    case VAR_CUR_ERR:
        send_int(cur_err);
        break;
    case VAR_PWM:
        send_int(pwm);
        break;
    case VAR_OCR2:
        send_byte(OCR2);
        break;
    case VAR_PACKET:
        send_packet();
        break;
    }
}

// ========================================================================
// ===================== Program Entry Point ==============================
// ========================================================================

int main()
{

    /* Initialization here */

    init();

    __enable_interrupt();

    /* Program Loop */

    for(;;)
    {

        /* Message Loop */

        if (command_present)
        {
            process_command();
        }
        else
        {
            command_present = receive(&command_method);
        }

        /* Program Body */

        if (!pause)
        {
            do_computations();
        }

    }

    return 0;
}
<|endoftext|>


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

#include "chrome/browser/chromeos/options/network_config_view.h"

#include <algorithm>

#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/options/vpn_config_view.h"
#include "chrome/browser/chromeos/options/wifi_config_view.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/rect.h"
#include "views/controls/button/native_button.h"
#include "views/layout/grid_layout.h"
#include "views/layout/layout_constants.h"
#include "views/widget/widget.h"
#include "views/window/window.h"

namespace chromeos {

// static
const int ChildNetworkConfigView::kPassphraseWidth = 150;

NetworkConfigView::NetworkConfigView(Network* network)
    : delegate_(NULL),
      advanced_button_(NULL),
      advanced_button_container_(NULL) {
  if (network->type() == TYPE_WIFI) {
    child_config_view_ =
        new WifiConfigView(this, static_cast<WifiNetwork*>(network));
  } else if (network->type() == TYPE_VPN) {
    child_config_view_ =
        new VPNConfigView(this, static_cast<VirtualNetwork*>(network));
  } else {
    NOTREACHED();
    child_config_view_ = NULL;
  }
}

NetworkConfigView::NetworkConfigView(ConnectionType type)
    : delegate_(NULL),
      advanced_button_(NULL),
      advanced_button_container_(NULL) {
  if (type == TYPE_WIFI) {
    child_config_view_ = new WifiConfigView(this, false /* show_8021x */);
    CreateAdvancedButton();
  } else if (type == TYPE_VPN) {
    child_config_view_ = new VPNConfigView(this);
  } else {
    NOTREACHED();
    child_config_view_ = NULL;
  }
}

gfx::NativeWindow NetworkConfigView::GetNativeWindow() const {
  return GetWidget()->GetNativeWindow();
}

std::wstring NetworkConfigView::GetDialogButtonLabel(
    MessageBoxFlags::DialogButton button) const {
  if (button == MessageBoxFlags::DIALOGBUTTON_OK)
    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONNECT));
  return std::wstring();
}

bool NetworkConfigView::IsDialogButtonEnabled(
    MessageBoxFlags::DialogButton button) const {
  // Disable connect button if cannot login.
  if (button == MessageBoxFlags::DIALOGBUTTON_OK)
    return child_config_view_->CanLogin();
  return true;
}

bool NetworkConfigView::Cancel() {
  if (delegate_)
    delegate_->OnDialogCancelled();
  child_config_view_->Cancel();
  return true;
}

bool NetworkConfigView::Accept() {
  // Do not attempt login if it is guaranteed to fail, keep the dialog open.
  if (!child_config_view_->CanLogin())
    return false;
  bool result = child_config_view_->Login();
  if (result && delegate_)
    delegate_->OnDialogAccepted();
  return result;
}

views::View* NetworkConfigView::GetExtraView() {
  return advanced_button_container_;
}

bool NetworkConfigView::IsModal() const {
  return true;
}

views::View* NetworkConfigView::GetContentsView() {
  return this;
}

std::wstring NetworkConfigView::GetWindowTitle() const {
  return UTF16ToWide(child_config_view_->GetTitle());
}

void NetworkConfigView::GetAccessibleState(ui::AccessibleViewState* state) {
  state->name =
      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS);
  state->role = ui::AccessibilityTypes::ROLE_DIALOG;
}

void NetworkConfigView::ButtonPressed(views::Button* sender,
                                      const views::Event& event) {
  if (advanced_button_ && sender == advanced_button_) {
    advanced_button_->SetVisible(false);
    ShowAdvancedView();
  }
}

void NetworkConfigView::ShowAdvancedView() {
  // Clear out the old widgets and build new ones.
  RemoveChildView(child_config_view_);
  delete child_config_view_;
  // For now, there is only an advanced view for Wi-Fi 802.1X.
  child_config_view_ = new WifiConfigView(this, true /* show_8021x */);
  AddChildView(child_config_view_);
  // Resize the window to be able to hold the new widgets.
  gfx::Size size = views::Window::GetLocalizedContentsSize(
      IDS_JOIN_WIFI_NETWORK_DIALOG_WIDTH_CHARS,
      IDS_JOIN_WIFI_NETWORK_DIALOG_ADVANCED_MINIMUM_HEIGHT_LINES);
  gfx::Rect bounds(size.width(), size.height());
  // Window is automatically centered.
  window()->SetWindowBounds(bounds, GetNativeWindow());
  Layout();
  child_config_view_->InitFocus();
}

void NetworkConfigView::Layout() {
  child_config_view_->SetBounds(0, 0, width(), height());
}

gfx::Size NetworkConfigView::GetPreferredSize() {
  gfx::Size result(views::Window::GetLocalizedContentsSize(
      IDS_JOIN_WIFI_NETWORK_DIALOG_WIDTH_CHARS,
      IDS_JOIN_WIFI_NETWORK_DIALOG_MINIMUM_HEIGHT_LINES));
  gfx::Size size = child_config_view_->GetPreferredSize();
  result.set_height(size.height());
  if (size.width() > result.width())
    result.set_width(size.width());
  return result;
}

void NetworkConfigView::ViewHierarchyChanged(
    bool is_add, views::View* parent, views::View* child) {
  // Can't init before we're inserted into a Container, because we require
  // a HWND to parent native child controls to.
  if (is_add && child == this) {
    AddChildView(child_config_view_);
    child_config_view_->InitFocus();
  }
}

void NetworkConfigView::CreateAdvancedButton() {
  advanced_button_ = new views::NativeButton(this, UTF16ToWide(
      l10n_util::GetStringUTF16(
          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADVANCED_BUTTON)));

  // Wrap the advanced button in a grid layout in order to left-align it.
  advanced_button_container_ = new views::View();
  views::GridLayout* layout = new views::GridLayout(advanced_button_container_);
  advanced_button_container_->SetLayoutManager(layout);

  int column_set_id = 0;
  views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
                        0, views::GridLayout::USE_PREF, 0, 0);
  layout->StartRow(0, column_set_id);
  layout->AddView(advanced_button_);
}

}  // namespace chromeos
<commit_msg>[ChromeOS] Ensure advanced network config dialog is centered.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/options/network_config_view.h"

#include <algorithm>

#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/options/vpn_config_view.h"
#include "chrome/browser/chromeos/options/wifi_config_view.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/rect.h"
#include "views/controls/button/native_button.h"
#include "views/layout/grid_layout.h"
#include "views/layout/layout_constants.h"
#include "views/widget/widget.h"
#include "views/window/window.h"

namespace chromeos {

// static
const int ChildNetworkConfigView::kPassphraseWidth = 150;

NetworkConfigView::NetworkConfigView(Network* network)
    : delegate_(NULL),
      advanced_button_(NULL),
      advanced_button_container_(NULL) {
  if (network->type() == TYPE_WIFI) {
    child_config_view_ =
        new WifiConfigView(this, static_cast<WifiNetwork*>(network));
  } else if (network->type() == TYPE_VPN) {
    child_config_view_ =
        new VPNConfigView(this, static_cast<VirtualNetwork*>(network));
  } else {
    NOTREACHED();
    child_config_view_ = NULL;
  }
}

NetworkConfigView::NetworkConfigView(ConnectionType type)
    : delegate_(NULL),
      advanced_button_(NULL),
      advanced_button_container_(NULL) {
  if (type == TYPE_WIFI) {
    child_config_view_ = new WifiConfigView(this, false /* show_8021x */);
    CreateAdvancedButton();
  } else if (type == TYPE_VPN) {
    child_config_view_ = new VPNConfigView(this);
  } else {
    NOTREACHED();
    child_config_view_ = NULL;
  }
}

gfx::NativeWindow NetworkConfigView::GetNativeWindow() const {
  return GetWidget()->GetNativeWindow();
}

std::wstring NetworkConfigView::GetDialogButtonLabel(
    MessageBoxFlags::DialogButton button) const {
  if (button == MessageBoxFlags::DIALOGBUTTON_OK)
    return UTF16ToWide(l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONNECT));
  return std::wstring();
}

bool NetworkConfigView::IsDialogButtonEnabled(
    MessageBoxFlags::DialogButton button) const {
  // Disable connect button if cannot login.
  if (button == MessageBoxFlags::DIALOGBUTTON_OK)
    return child_config_view_->CanLogin();
  return true;
}

bool NetworkConfigView::Cancel() {
  if (delegate_)
    delegate_->OnDialogCancelled();
  child_config_view_->Cancel();
  return true;
}

bool NetworkConfigView::Accept() {
  // Do not attempt login if it is guaranteed to fail, keep the dialog open.
  if (!child_config_view_->CanLogin())
    return false;
  bool result = child_config_view_->Login();
  if (result && delegate_)
    delegate_->OnDialogAccepted();
  return result;
}

views::View* NetworkConfigView::GetExtraView() {
  return advanced_button_container_;
}

bool NetworkConfigView::IsModal() const {
  return true;
}

views::View* NetworkConfigView::GetContentsView() {
  return this;
}

std::wstring NetworkConfigView::GetWindowTitle() const {
  return UTF16ToWide(child_config_view_->GetTitle());
}

void NetworkConfigView::GetAccessibleState(ui::AccessibleViewState* state) {
  state->name =
      l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS);
  state->role = ui::AccessibilityTypes::ROLE_DIALOG;
}

void NetworkConfigView::ButtonPressed(views::Button* sender,
                                      const views::Event& event) {
  if (advanced_button_ && sender == advanced_button_) {
    advanced_button_->SetVisible(false);
    ShowAdvancedView();
  }
}

void NetworkConfigView::ShowAdvancedView() {
  // Clear out the old widgets and build new ones.
  RemoveChildView(child_config_view_);
  delete child_config_view_;
  // For now, there is only an advanced view for Wi-Fi 802.1X.
  child_config_view_ = new WifiConfigView(this, true /* show_8021x */);
  AddChildView(child_config_view_);
  // Resize the window to be able to hold the new widgets.
  gfx::Size size = views::Window::GetLocalizedContentsSize(
      IDS_JOIN_WIFI_NETWORK_DIALOG_WIDTH_CHARS,
      IDS_JOIN_WIFI_NETWORK_DIALOG_ADVANCED_MINIMUM_HEIGHT_LINES);
  // Get the new bounds with desired size at the same center point.
  gfx::Rect bounds = window()->GetBounds();
  int horiz_padding = bounds.width() - size.width();
  int vert_padding = bounds.height() - size.height();
  bounds.Inset(horiz_padding / 2, vert_padding / 2,
               horiz_padding / 2, vert_padding / 2);
  window()->SetWindowBounds(bounds, GetNativeWindow());
  Layout();
  child_config_view_->InitFocus();
}

void NetworkConfigView::Layout() {
  child_config_view_->SetBounds(0, 0, width(), height());
}

gfx::Size NetworkConfigView::GetPreferredSize() {
  gfx::Size result(views::Window::GetLocalizedContentsSize(
      IDS_JOIN_WIFI_NETWORK_DIALOG_WIDTH_CHARS,
      IDS_JOIN_WIFI_NETWORK_DIALOG_MINIMUM_HEIGHT_LINES));
  gfx::Size size = child_config_view_->GetPreferredSize();
  result.set_height(size.height());
  if (size.width() > result.width())
    result.set_width(size.width());
  return result;
}

void NetworkConfigView::ViewHierarchyChanged(
    bool is_add, views::View* parent, views::View* child) {
  // Can't init before we're inserted into a Container, because we require
  // a HWND to parent native child controls to.
  if (is_add && child == this) {
    AddChildView(child_config_view_);
    child_config_view_->InitFocus();
  }
}

void NetworkConfigView::CreateAdvancedButton() {
  advanced_button_ = new views::NativeButton(this, UTF16ToWide(
      l10n_util::GetStringUTF16(
          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADVANCED_BUTTON)));

  // Wrap the advanced button in a grid layout in order to left-align it.
  advanced_button_container_ = new views::View();
  views::GridLayout* layout = new views::GridLayout(advanced_button_container_);
  advanced_button_container_->SetLayoutManager(layout);

  int column_set_id = 0;
  views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
                        0, views::GridLayout::USE_PREF, 0, 0);
  layout->StartRow(0, column_set_id);
  layout->AddView(advanced_button_);
}

}  // namespace chromeos
<|endoftext|>


<commit_before>//
// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
//

#include "config.h"
#include "util.h"

#include "../src/charls.h"

#include <iostream>
#include <vector>

using namespace charls;

void Triplet2Planar(std::vector<BYTE>& rgbyte, Size size)
{
    std::vector<BYTE> rgbytePlanar(rgbyte.size());

    int cbytePlane = size.cx * size.cy;
    for (int index = 0; index < cbytePlane; index++)
    {
        rgbytePlanar[index]                 = rgbyte[index * 3 + 0];
        rgbytePlanar[index + 1*cbytePlane]  = rgbyte[index * 3 + 1];
        rgbytePlanar[index + 2*cbytePlane]  = rgbyte[index * 3 + 2];
    }
    std::swap(rgbyte, rgbytePlanar);
}

void Triplet2Line(std::vector<BYTE>& rgbyte, Size size)
{
    std::vector<BYTE> rgbyteInterleaved(rgbyte.size());

    int cbyteLine = size.cx;

    for (int line = 0; line < size.cy; ++line)
    {
        const BYTE* pbyteLineIn = &rgbyte[line * size.cx * 3];
        BYTE* pbyteLineOut = &rgbyteInterleaved[line * size.cx * 3];

        for (int index = 0; index < cbyteLine; index++)
        {
            pbyteLineOut[index]                 = pbyteLineIn[index * 3 + 0];
            pbyteLineOut[index + 1*cbyteLine]   = pbyteLineIn[index * 3 + 1];
            pbyteLineOut[index + 2*cbyteLine]   = pbyteLineIn[index * 3 + 2];
        }
    }
    std::swap(rgbyte, rgbyteInterleaved);
}

void TestCompliance(const BYTE* compressedBytes, size_t compressedLength, const BYTE* rgbyteRaw, size_t cbyteRaw, bool bcheckEncode)
{
    JlsParameters info = JlsParameters();
    auto err = JpegLsReadHeader(compressedBytes, compressedLength, &info, nullptr);
    Assert::IsTrue(err == ApiResult::OK);

    if (bcheckEncode)
    {
        err = JpegLsVerifyEncode(&rgbyteRaw[0], cbyteRaw, compressedBytes, compressedLength, nullptr);
        Assert::IsTrue(err == ApiResult::OK);
    }

    std::vector<BYTE> rgbyteCompressed(info.height *info.width* 4);

    std::vector<BYTE> rgbyteOut(info.height *info.width * ((info.bitspersample + 7) / 8) * info.components);

    err = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), compressedBytes, compressedLength, nullptr, nullptr);
    Assert::IsTrue(err == ApiResult::OK);

    if (info.allowedlossyerror == 0)
    {
        BYTE* pbyteOut = &rgbyteOut[0];
        for (size_t i = 0; i < cbyteRaw; ++i)
        {
            if (rgbyteRaw[i] != pbyteOut[i])
            {
                Assert::IsTrue(false);
                break;
            }
        }
    }
}

void DecompressFile(SZC strNameEncoded, SZC strNameRaw, int ioffs, bool bcheckEncode)
{
    std::cout << "Conformance test:" << strNameEncoded << "\n\r";
    std::vector<BYTE> rgbyteFile;
    if (!ReadFile(strNameEncoded, &rgbyteFile))
        return;

    JlsParameters metadata;
    if (JpegLsReadHeader(&rgbyteFile[0], rgbyteFile.size(), &metadata, nullptr) != ApiResult::OK)
    {
        Assert::IsTrue(false);
        return;
    }

    std::vector<BYTE> rgbyteRaw;
    if (!ReadFile(strNameRaw, &rgbyteRaw, ioffs))
        return;

    if (metadata.bitspersample > 8)
    {
        FixEndian(&rgbyteRaw, false);
    }

    Size size = Size(metadata.width, metadata.height);

    if (metadata.ilv == InterleaveMode::None && metadata.components == 3)
    {
        Triplet2Planar(rgbyteRaw, Size(metadata.width, metadata.height));
    }

    TestCompliance(&rgbyteFile[0], rgbyteFile.size(), &rgbyteRaw[0], rgbyteRaw.size(), bcheckEncode);
}

BYTE palettisedDataH10[] = {
    0xFF, 0xD8, //Start of image (SOI) marker
    0xFF, 0xF7, //Start of JPEG-LS frame (SOF 55) marker  marker segment follows
    0x00, 0x0B, //Length of marker segment = 11 bytes including the length field
    0x02, //P = Precision = 2 bits per sample
    0x00, 0x04, //Y = Number of lines = 4
    0x00, 0x03, //X = Number of columns = 3
    0x01, //Nf = Number of components in the frame = 1
    0x01, //C1  = Component ID = 1 (first and only component)
    0x11, //Sub-sampling: H1 = 1, V1 = 1
    0x00, //Tq1 = 0 (this field is always 0)

    0xFF, 0xF8, //LSE  JPEG-LS preset parameters marker
    0x00, 0x11, //Length of marker segment = 17 bytes including the length field
    0x02, //ID = 2, mapping table
    0x05, //TID = 5 Table identifier (arbitrary)
    0x03, //Wt = 3 Width of table entry
    0xFF, 0xFF, 0xFF, //Entry for index 0
    0xFF, 0x00, 0x00, //Entry for index 1
    0x00, 0xFF, 0x00, //Entry for index 2
    0x00, 0x00, 0xFF, //Entry for index 3

    0xFF, 0xDA, //Start of scan (SOS) marker
    0x00, 0x08, //Length of marker segment = 8 bytes including the length field
    0x01, //Ns = Number of components for this scan = 1
    0x01, //C1 = Component ID = 1
    0x05, //Tm 1  = Mapping table identifier = 5
    0x00, //NEAR = 0 (near-lossless max error)
    0x00, //ILV = 0 (interleave mode = non-interleaved)
    0x00, //Al = 0, Ah = 0 (no point transform)
    0xDB, 0x95, 0xF0, //3 bytes of compressed image data
    0xFF, 0xD9 //End of image (EOI) marker
};

const BYTE rgbyte[] = { 0,   0,  90,  74,
68,  50,  43, 205,
64, 145, 145, 145,
100, 145, 145, 145};
const BYTE rgbyteComp[] =   {   0xFF, 0xD8, 0xFF, 0xF7, 0x00, 0x0B, 0x08, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x11, 0x00, 0xFF, 0xDA, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x00, 0x00, 0x6C, 0x80, 0x20, 0x8E,
0x01, 0xC0, 0x00, 0x00, 0x57, 0x40, 0x00, 0x00, 0x6E, 0xE6, 0x00, 0x00, 0x01, 0xBC, 0x18, 0x00,
0x00, 0x05, 0xD8, 0x00, 0x00, 0x91, 0x60, 0xFF, 0xD9};

void TestSampleAnnexH3()
{
    Size size = Size(4,4);
    std::vector<BYTE> vecRaw(16);
    memcpy(&vecRaw[0], rgbyte, 16);
    //  TestJls(vecRaw, size, 8, 1, ILV_NONE, rgbyteComp, sizeof(rgbyteComp), false);
}

void TestColorTransforms_HpImages()
{
    DecompressFile("test/jlsimage/banny_normal.jls", "test/jlsimage/banny.ppm",38, false);
    DecompressFile("test/jlsimage/banny_Hp1.jls", "test/jlsimage/banny.ppm",38, false);
    DecompressFile("test/jlsimage/banny_Hp2.jls", "test/jlsimage/banny.ppm",38, false);
    DecompressFile("test/jlsimage/banny_Hp3.jls", "test/jlsimage/banny.ppm",38, false);
}

void TestConformance()
{
    // Test 1
    DecompressFile("test/conformance/T8C0E0.JLS", "test/conformance/TEST8.PPM",15);

    // Test 2
    DecompressFile("test/conformance/T8C1E0.JLS", "test/conformance/TEST8.PPM",15);

    // Test 3
    DecompressFile("test/conformance/T8C2E0.JLS", "test/conformance/TEST8.PPM", 15);

    // Test 4
    DecompressFile("test/conformance/T8C0E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 5
    DecompressFile("test/conformance/T8C1E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 6
    DecompressFile("test/conformance/T8C2E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 7
    // Test 8

    // Test 9
    DecompressFile("test/conformance/T8NDE0.JLS", "test/conformance/TEST8BS2.PGM",15);

    // Test 10
    DecompressFile("test/conformance/T8NDE3.JLS", "test/conformance/TEST8BS2.PGM",15);

    // Test 11
    DecompressFile("test/conformance/T16E0.JLS", "test/conformance/TEST16.PGM",16);

    // Test 12
    DecompressFile("test/conformance/T16E3.JLS", "test/conformance/TEST16.PGM",16);

    // additional, Lena compressed with other codec (UBC?), vfy with CharLS
    DecompressFile("test/lena8b.jls", "test/lena8b.raw",0);
}

<commit_msg>Added include file for memcpy<commit_after>//
// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
//

#include "config.h"
#include "util.h"

#include "../src/charls.h"

#include <iostream>
#include <vector>
#include <cstring>

using namespace charls;

void Triplet2Planar(std::vector<BYTE>& rgbyte, Size size)
{
    std::vector<BYTE> rgbytePlanar(rgbyte.size());

    int cbytePlane = size.cx * size.cy;
    for (int index = 0; index < cbytePlane; index++)
    {
        rgbytePlanar[index]                 = rgbyte[index * 3 + 0];
        rgbytePlanar[index + 1*cbytePlane]  = rgbyte[index * 3 + 1];
        rgbytePlanar[index + 2*cbytePlane]  = rgbyte[index * 3 + 2];
    }
    std::swap(rgbyte, rgbytePlanar);
}

void Triplet2Line(std::vector<BYTE>& rgbyte, Size size)
{
    std::vector<BYTE> rgbyteInterleaved(rgbyte.size());

    int cbyteLine = size.cx;

    for (int line = 0; line < size.cy; ++line)
    {
        const BYTE* pbyteLineIn = &rgbyte[line * size.cx * 3];
        BYTE* pbyteLineOut = &rgbyteInterleaved[line * size.cx * 3];

        for (int index = 0; index < cbyteLine; index++)
        {
            pbyteLineOut[index]                 = pbyteLineIn[index * 3 + 0];
            pbyteLineOut[index + 1*cbyteLine]   = pbyteLineIn[index * 3 + 1];
            pbyteLineOut[index + 2*cbyteLine]   = pbyteLineIn[index * 3 + 2];
        }
    }
    std::swap(rgbyte, rgbyteInterleaved);
}

void TestCompliance(const BYTE* compressedBytes, size_t compressedLength, const BYTE* rgbyteRaw, size_t cbyteRaw, bool bcheckEncode)
{
    JlsParameters info = JlsParameters();
    auto err = JpegLsReadHeader(compressedBytes, compressedLength, &info, nullptr);
    Assert::IsTrue(err == ApiResult::OK);

    if (bcheckEncode)
    {
        err = JpegLsVerifyEncode(&rgbyteRaw[0], cbyteRaw, compressedBytes, compressedLength, nullptr);
        Assert::IsTrue(err == ApiResult::OK);
    }

    std::vector<BYTE> rgbyteCompressed(info.height *info.width* 4);

    std::vector<BYTE> rgbyteOut(info.height *info.width * ((info.bitspersample + 7) / 8) * info.components);

    err = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), compressedBytes, compressedLength, nullptr, nullptr);
    Assert::IsTrue(err == ApiResult::OK);

    if (info.allowedlossyerror == 0)
    {
        BYTE* pbyteOut = &rgbyteOut[0];
        for (size_t i = 0; i < cbyteRaw; ++i)
        {
            if (rgbyteRaw[i] != pbyteOut[i])
            {
                Assert::IsTrue(false);
                break;
            }
        }
    }
}

void DecompressFile(SZC strNameEncoded, SZC strNameRaw, int ioffs, bool bcheckEncode)
{
    std::cout << "Conformance test:" << strNameEncoded << "\n\r";
    std::vector<BYTE> rgbyteFile;
    if (!ReadFile(strNameEncoded, &rgbyteFile))
        return;

    JlsParameters metadata;
    if (JpegLsReadHeader(&rgbyteFile[0], rgbyteFile.size(), &metadata, nullptr) != ApiResult::OK)
    {
        Assert::IsTrue(false);
        return;
    }

    std::vector<BYTE> rgbyteRaw;
    if (!ReadFile(strNameRaw, &rgbyteRaw, ioffs))
        return;

    if (metadata.bitspersample > 8)
    {
        FixEndian(&rgbyteRaw, false);
    }

    Size size = Size(metadata.width, metadata.height);

    if (metadata.ilv == InterleaveMode::None && metadata.components == 3)
    {
        Triplet2Planar(rgbyteRaw, Size(metadata.width, metadata.height));
    }

    TestCompliance(&rgbyteFile[0], rgbyteFile.size(), &rgbyteRaw[0], rgbyteRaw.size(), bcheckEncode);
}

BYTE palettisedDataH10[] = {
    0xFF, 0xD8, //Start of image (SOI) marker
    0xFF, 0xF7, //Start of JPEG-LS frame (SOF 55) marker  marker segment follows
    0x00, 0x0B, //Length of marker segment = 11 bytes including the length field
    0x02, //P = Precision = 2 bits per sample
    0x00, 0x04, //Y = Number of lines = 4
    0x00, 0x03, //X = Number of columns = 3
    0x01, //Nf = Number of components in the frame = 1
    0x01, //C1  = Component ID = 1 (first and only component)
    0x11, //Sub-sampling: H1 = 1, V1 = 1
    0x00, //Tq1 = 0 (this field is always 0)

    0xFF, 0xF8, //LSE  JPEG-LS preset parameters marker
    0x00, 0x11, //Length of marker segment = 17 bytes including the length field
    0x02, //ID = 2, mapping table
    0x05, //TID = 5 Table identifier (arbitrary)
    0x03, //Wt = 3 Width of table entry
    0xFF, 0xFF, 0xFF, //Entry for index 0
    0xFF, 0x00, 0x00, //Entry for index 1
    0x00, 0xFF, 0x00, //Entry for index 2
    0x00, 0x00, 0xFF, //Entry for index 3

    0xFF, 0xDA, //Start of scan (SOS) marker
    0x00, 0x08, //Length of marker segment = 8 bytes including the length field
    0x01, //Ns = Number of components for this scan = 1
    0x01, //C1 = Component ID = 1
    0x05, //Tm 1  = Mapping table identifier = 5
    0x00, //NEAR = 0 (near-lossless max error)
    0x00, //ILV = 0 (interleave mode = non-interleaved)
    0x00, //Al = 0, Ah = 0 (no point transform)
    0xDB, 0x95, 0xF0, //3 bytes of compressed image data
    0xFF, 0xD9 //End of image (EOI) marker
};

const BYTE rgbyte[] = { 0,   0,  90,  74,
68,  50,  43, 205,
64, 145, 145, 145,
100, 145, 145, 145};
const BYTE rgbyteComp[] =   {   0xFF, 0xD8, 0xFF, 0xF7, 0x00, 0x0B, 0x08, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x11, 0x00, 0xFF, 0xDA, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x00, 0x00, 0x6C, 0x80, 0x20, 0x8E,
0x01, 0xC0, 0x00, 0x00, 0x57, 0x40, 0x00, 0x00, 0x6E, 0xE6, 0x00, 0x00, 0x01, 0xBC, 0x18, 0x00,
0x00, 0x05, 0xD8, 0x00, 0x00, 0x91, 0x60, 0xFF, 0xD9};

void TestSampleAnnexH3()
{
    Size size = Size(4,4);
    std::vector<BYTE> vecRaw(16);
    memcpy(&vecRaw[0], rgbyte, 16);
    //  TestJls(vecRaw, size, 8, 1, ILV_NONE, rgbyteComp, sizeof(rgbyteComp), false);
}

void TestColorTransforms_HpImages()
{
    DecompressFile("test/jlsimage/banny_normal.jls", "test/jlsimage/banny.ppm",38, false);
    DecompressFile("test/jlsimage/banny_Hp1.jls", "test/jlsimage/banny.ppm",38, false);
    DecompressFile("test/jlsimage/banny_Hp2.jls", "test/jlsimage/banny.ppm",38, false);
    DecompressFile("test/jlsimage/banny_Hp3.jls", "test/jlsimage/banny.ppm",38, false);
}

void TestConformance()
{
    // Test 1
    DecompressFile("test/conformance/T8C0E0.JLS", "test/conformance/TEST8.PPM",15);

    // Test 2
    DecompressFile("test/conformance/T8C1E0.JLS", "test/conformance/TEST8.PPM",15);

    // Test 3
    DecompressFile("test/conformance/T8C2E0.JLS", "test/conformance/TEST8.PPM", 15);

    // Test 4
    DecompressFile("test/conformance/T8C0E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 5
    DecompressFile("test/conformance/T8C1E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 6
    DecompressFile("test/conformance/T8C2E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 7
    // Test 8

    // Test 9
    DecompressFile("test/conformance/T8NDE0.JLS", "test/conformance/TEST8BS2.PGM",15);

    // Test 10
    DecompressFile("test/conformance/T8NDE3.JLS", "test/conformance/TEST8BS2.PGM",15);

    // Test 11
    DecompressFile("test/conformance/T16E0.JLS", "test/conformance/TEST16.PGM",16);

    // Test 12
    DecompressFile("test/conformance/T16E3.JLS", "test/conformance/TEST16.PGM",16);

    // additional, Lena compressed with other codec (UBC?), vfy with CharLS
    DecompressFile("test/lena8b.jls", "test/lena8b.raw",0);
}

<|endoftext|>


<commit_before>#ifndef DEDICATED_ONLY

#include "CViewport.h"

#include "gusgame.h"
#include "sound/sfx.h"
#include "gfx.h"
#include "gusanos/allegro.h"
#include "game/CWorm.h"
#include "game/WormInputHandler.h"
#include "CWormHuman.h"
#include "LuaCallbacks.h"
#include "lua/bindings-gfx.h"
#include "blitters/blitters.h"
#include "culling.h"
#include "game/CMap.h"
#include "game/Game.h"
#include "FlagInfo.h"
#include <list>

#include "sprite_set.h" // TEMP
#include "sprite.h" // TEMP
#include "CGameScript.h"

#include <iostream>

LuaReference CViewport::metaTable;

using namespace std;

void CViewport::gusInit()
{
	dest = 0;
	fadeBuffer = 0;
}

void CViewport::gusReset()
{
	destroy_bitmap(dest); dest = 0;
	destroy_bitmap(fadeBuffer); fadeBuffer = 0;
}

struct TestCuller : public Culler<TestCuller>
{
	TestCuller(ALLEGRO_BITMAP* dest_, ALLEGRO_BITMAP* src_, int scrOffX_, int scrOffY_, int destOffX_, int destOffY_, Rect const& rect)
			: Culler<TestCuller>(rect), dest(dest_), src(src_),
			scrOffX(scrOffX_), scrOffY(scrOffY_), destOffX(destOffX_), destOffY(destOffY_)
	{
	}

	bool block(int x, int y)
	{
		// doubleRes to singleRes coords
		return !game.gameMap()->unsafeGetMaterial(x/2, y/2).worm_pass;
	}

	void line(int y, int x1, int x2)
	{
		//hline_add(dest, x1 + scrOffX, y + scrOffY, x2 + scrOffX + 1, makecol(50, 50, 50), 255);

		drawSpriteLine_add(
		    dest,
		    src,
		    x1 + scrOffX,
		    y + scrOffY,
		    x1 + destOffX,
		    y + destOffY,
		    x2 + destOffX + 1,
		    255);
	}

	ALLEGRO_BITMAP* dest;
	ALLEGRO_BITMAP* src;

	int scrOffX;
	int scrOffY;
	int destOffX;
	int destOffY;
};

static Sprite* testLight = 0;

void CViewport::setDestination(int width, int height)
{
	destroy_bitmap(dest);
	dest = create_bitmap(width, height);

	destroy_bitmap(fadeBuffer);
	fadeBuffer = create_bitmap_ex(8, width, height);
}

void CViewport::drawLight(IVec const& v)
{
	ALLEGRO_BITMAP* renderBitmap = testLight->m_bitmap;
	IVec off = getPos() * 2;
	IVec loff(v*2 - IVec(testLight->m_xPivot, testLight->m_yPivot));

	Rect r(0, 0, game.gameMap()->GetWidth()*2 - 1, game.gameMap()->GetHeight()*2 - 1);
	r &= Rect(renderBitmap) + loff;

	// we use drawSpriteLine_add which requires the same bit depths
	assert(renderBitmap->surf->format->BitsPerPixel == 8);
	TestCuller testCuller(fadeBuffer, renderBitmap, -off.x, -off.y, -loff.x, -loff.y, r);

	testCuller.cullOmni(v.x*2, v.y*2);
}

void CViewport::gusRender(SDL_Surface* bmpDest)
{
	{
		int destw = Width*2;
		int desth = Height*2;
		bool needDestReset = false;
		if(!dest || !fadeBuffer || !testLight)
			needDestReset = true;
		else if(dest->w != destw || dest->h != desth )
			needDestReset = true;

		if(needDestReset)
			setDestination(destw, desth);
	}

	{
		int r = game.darkMode_wormLightRadius;
		if(r < 1) r = 1;
		if(r > 500) r = 500; // sane maximum. dont crash OLX

		bool needLightReset = false;
		if(!testLight)
			needLightReset = true;
		else if(testLight->m_xPivot != r * 2 /*doubleRes*/)
			needLightReset = true;

		if(needLightReset)
			testLight = genLight(r);
	}

	int offX = static_cast<int>(WorldX);
	int offY = static_cast<int>(WorldY);

	game.gameMap()->gusDraw(dest, offX, offY);

	if ( game.isLevelDarkMode() && game.gameMap()->lightmap )
		blit( game.gameMap()->lightmap, fadeBuffer, offX*2,offY*2, 0, 0, fadeBuffer->w, fadeBuffer->h );

	if (game.state == Game::S_Playing)  {
		// for this scope as a small hack ...
		SDL_Surface* bmpDest = dest->surf.get();
		CViewport _v;
		_v.Height = this->Height;
		_v.Width = this->Width;
		_v.VirtHeight = this->VirtHeight;
		_v.VirtWidth = this->VirtWidth;
		_v.WorldX = this->WorldX;
		_v.WorldY = this->WorldY;
		CViewport* v = &_v;

		// update the drawing position
		for_each_iterator(CWorm*, w, game.aliveWorms())
			w->get()->UpdateDrawPos();

		if( tLXOptions->bShadows ) {
			// Draw the projectile shadows
			cClient->DrawProjectileShadows(bmpDest, v);

			// Draw the worm shadows
			for_each_iterator(CWorm*, w, game.aliveWorms())
				w->get()->DrawShadow(bmpDest, v);
		}

		// Draw the entities
		DrawEntities(bmpDest, v);

		// Draw the projectiles
		cClient->DrawProjectiles(bmpDest, v);

		// Draw the bonuses
		cClient->DrawBonuses(bmpDest, v);

		// draw unattached flags and flag spawnpoints
		cClient->flagInfo()->draw(bmpDest, v);

		// draw worms
		for_each_iterator(CWorm*, w, game.aliveWorms())
			w->get()->Draw(bmpDest, v);
	}

	for ( Grid::iterator iter = game.objects.beginAll(); iter; ++iter)
		iter->draw(this);

	if(game.isLevelDarkMode() && pcTargetWorm) {
		if(pcTargetWorm->isActive())
			drawLight(pcTargetWorm->pos().get());
	}

	if(game.isLevelDarkMode())
		drawSprite_mult_8(dest, fadeBuffer, 0, 0);

	// only use the player/worm specific drawings in gus mods
	if(game.gameScript()->gusEngineUsed()) {
		CWormInputHandler* player = pcTargetWorm ? pcTargetWorm->inputHandler() : NULL;

		// Note that we only process worms in the Lua callbacks which have a player set.
		// Most Lua code depends on this assumption so it would break otherwise.

		for(vector<CWormInputHandler*>::iterator playerIter = game.players.begin(); playerIter != game.players.end(); ++playerIter) {
			CWorm* worm = (*playerIter)->getWorm();
			if( worm && worm->isActive() && worm->inputHandler() ) {
				IVec renderPos( worm->getRenderPos() );
				int x = renderPos.x - offX;
				int y = renderPos.y - offY;
				LuaReferenceLazy ownerRef;

				if ( player )
					ownerRef = player->getLuaReference();

				LUACALLBACK(wormRender).call()((lua_Number)x)((lua_Number)y)(worm->getLuaReference())(getLuaReference())(ownerRef)();
			}
		}

		// draw viewport specific stuff only for human worms
		if(pcTargetWorm && dynamic_cast<CWormHumanInputHandler*>(pcTargetWorm->inputHandler()) != NULL) {
			LUACALLBACK(viewportRender).call()(getLuaReference())(pcTargetWorm->getLuaReference())();
		}
	}

	DrawImage(bmpDest, dest->surf, this->GetLeft()/2, this->GetTop()/2);
}

#endif
<commit_msg>small fix for worm drawing<commit_after>#ifndef DEDICATED_ONLY

#include "CViewport.h"

#include "gusgame.h"
#include "sound/sfx.h"
#include "gfx.h"
#include "gusanos/allegro.h"
#include "game/CWorm.h"
#include "game/WormInputHandler.h"
#include "CWormHuman.h"
#include "LuaCallbacks.h"
#include "lua/bindings-gfx.h"
#include "blitters/blitters.h"
#include "culling.h"
#include "game/CMap.h"
#include "game/Game.h"
#include "FlagInfo.h"
#include <list>

#include "sprite_set.h" // TEMP
#include "sprite.h" // TEMP
#include "CGameScript.h"

#include <iostream>

LuaReference CViewport::metaTable;

using namespace std;

void CViewport::gusInit()
{
	dest = 0;
	fadeBuffer = 0;
}

void CViewport::gusReset()
{
	destroy_bitmap(dest); dest = 0;
	destroy_bitmap(fadeBuffer); fadeBuffer = 0;
}

struct TestCuller : public Culler<TestCuller>
{
	TestCuller(ALLEGRO_BITMAP* dest_, ALLEGRO_BITMAP* src_, int scrOffX_, int scrOffY_, int destOffX_, int destOffY_, Rect const& rect)
			: Culler<TestCuller>(rect), dest(dest_), src(src_),
			scrOffX(scrOffX_), scrOffY(scrOffY_), destOffX(destOffX_), destOffY(destOffY_)
	{
	}

	bool block(int x, int y)
	{
		// doubleRes to singleRes coords
		return !game.gameMap()->unsafeGetMaterial(x/2, y/2).worm_pass;
	}

	void line(int y, int x1, int x2)
	{
		//hline_add(dest, x1 + scrOffX, y + scrOffY, x2 + scrOffX + 1, makecol(50, 50, 50), 255);

		drawSpriteLine_add(
		    dest,
		    src,
		    x1 + scrOffX,
		    y + scrOffY,
		    x1 + destOffX,
		    y + destOffY,
		    x2 + destOffX + 1,
		    255);
	}

	ALLEGRO_BITMAP* dest;
	ALLEGRO_BITMAP* src;

	int scrOffX;
	int scrOffY;
	int destOffX;
	int destOffY;
};

static Sprite* testLight = 0;

void CViewport::setDestination(int width, int height)
{
	destroy_bitmap(dest);
	dest = create_bitmap(width, height);

	destroy_bitmap(fadeBuffer);
	fadeBuffer = create_bitmap_ex(8, width, height);
}

void CViewport::drawLight(IVec const& v)
{
	ALLEGRO_BITMAP* renderBitmap = testLight->m_bitmap;
	IVec off = getPos() * 2;
	IVec loff(v*2 - IVec(testLight->m_xPivot, testLight->m_yPivot));

	Rect r(0, 0, game.gameMap()->GetWidth()*2 - 1, game.gameMap()->GetHeight()*2 - 1);
	r &= Rect(renderBitmap) + loff;

	// we use drawSpriteLine_add which requires the same bit depths
	assert(renderBitmap->surf->format->BitsPerPixel == 8);
	TestCuller testCuller(fadeBuffer, renderBitmap, -off.x, -off.y, -loff.x, -loff.y, r);

	testCuller.cullOmni(v.x*2, v.y*2);
}

void CViewport::gusRender(SDL_Surface* bmpDest)
{
	{
		int destw = Width*2;
		int desth = Height*2;
		bool needDestReset = false;
		if(!dest || !fadeBuffer || !testLight)
			needDestReset = true;
		else if(dest->w != destw || dest->h != desth )
			needDestReset = true;

		if(needDestReset)
			setDestination(destw, desth);
	}

	{
		int r = game.darkMode_wormLightRadius;
		if(r < 1) r = 1;
		if(r > 500) r = 500; // sane maximum. dont crash OLX

		bool needLightReset = false;
		if(!testLight)
			needLightReset = true;
		else if(testLight->m_xPivot != r * 2 /*doubleRes*/)
			needLightReset = true;

		if(needLightReset)
			testLight = genLight(r);
	}

	int offX = static_cast<int>(WorldX);
	int offY = static_cast<int>(WorldY);

	game.gameMap()->gusDraw(dest, offX, offY);

	if ( game.isLevelDarkMode() && game.gameMap()->lightmap )
		blit( game.gameMap()->lightmap, fadeBuffer, offX*2,offY*2, 0, 0, fadeBuffer->w, fadeBuffer->h );

	if (game.state == Game::S_Playing)  {
		// for this scope as a small hack ...
		SDL_Surface* bmpDest = dest->surf.get();
		CViewport _v;
		_v.Height = this->Height;
		_v.Width = this->Width;
		_v.VirtHeight = this->VirtHeight;
		_v.VirtWidth = this->VirtWidth;
		_v.WorldX = this->WorldX;
		_v.WorldY = this->WorldY;
		_v.pcTargetWorm = this->pcTargetWorm;
		CViewport* v = &_v;

		// update the drawing position
		for_each_iterator(CWorm*, w, game.aliveWorms())
			w->get()->UpdateDrawPos();

		if( tLXOptions->bShadows ) {
			// Draw the projectile shadows
			cClient->DrawProjectileShadows(bmpDest, v);

			// Draw the worm shadows
			for_each_iterator(CWorm*, w, game.aliveWorms())
				w->get()->DrawShadow(bmpDest, v);
		}

		// Draw the entities
		DrawEntities(bmpDest, v);

		// Draw the projectiles
		cClient->DrawProjectiles(bmpDest, v);

		// Draw the bonuses
		cClient->DrawBonuses(bmpDest, v);

		// draw unattached flags and flag spawnpoints
		cClient->flagInfo()->draw(bmpDest, v);

		// draw worms
		for_each_iterator(CWorm*, w, game.aliveWorms())
			w->get()->Draw(bmpDest, v);
	}

	for ( Grid::iterator iter = game.objects.beginAll(); iter; ++iter)
		iter->draw(this);

	if(game.isLevelDarkMode() && pcTargetWorm) {
		if(pcTargetWorm->isActive())
			drawLight(pcTargetWorm->pos().get());
	}

	if(game.isLevelDarkMode())
		drawSprite_mult_8(dest, fadeBuffer, 0, 0);

	// only use the player/worm specific drawings in gus mods
	if(game.gameScript()->gusEngineUsed()) {
		CWormInputHandler* player = pcTargetWorm ? pcTargetWorm->inputHandler() : NULL;

		// Note that we only process worms in the Lua callbacks which have a player set.
		// Most Lua code depends on this assumption so it would break otherwise.

		for(vector<CWormInputHandler*>::iterator playerIter = game.players.begin(); playerIter != game.players.end(); ++playerIter) {
			CWorm* worm = (*playerIter)->getWorm();
			if( worm && worm->isActive() && worm->inputHandler() ) {
				IVec renderPos( worm->getRenderPos() );
				int x = renderPos.x - offX;
				int y = renderPos.y - offY;
				LuaReferenceLazy ownerRef;

				if ( player )
					ownerRef = player->getLuaReference();

				LUACALLBACK(wormRender).call()((lua_Number)x)((lua_Number)y)(worm->getLuaReference())(getLuaReference())(ownerRef)();
			}
		}

		// draw viewport specific stuff only for human worms
		if(pcTargetWorm && dynamic_cast<CWormHumanInputHandler*>(pcTargetWorm->inputHandler()) != NULL) {
			LUACALLBACK(viewportRender).call()(getLuaReference())(pcTargetWorm->getLuaReference())();
		}
	}

	DrawImage(bmpDest, dest->surf, this->GetLeft()/2, this->GetTop()/2);
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2010 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/renderer_host/async_resource_handler.h"

#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/process.h"
#include "base/shared_memory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/load_timing_observer.h"
#include "chrome/browser/renderer_host/global_request_id.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/common/render_messages.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_log.h"
#include "webkit/glue/resource_loader_bridge.h"

using base::Time;
using base::TimeTicks;

namespace {

// When reading, we don't know if we are going to get EOF (0 bytes read), so
// we typically have a buffer that we allocated but did not use.  We keep
// this buffer around for the next read as a small optimization.
SharedIOBuffer* g_spare_read_buffer = NULL;

// The initial size of the shared memory buffer. (32 kilobytes).
const int kInitialReadBufSize = 32768;

// The maximum size of the shared memory buffer. (512 kilobytes).
const int kMaxReadBufSize = 524288;

}  // namespace

// Our version of IOBuffer that uses shared memory.
class SharedIOBuffer : public net::IOBuffer {
 public:
  explicit SharedIOBuffer(int buffer_size)
      : net::IOBuffer(),
        ok_(false),
        buffer_size_(buffer_size) {}

  bool Init() {
    if (shared_memory_.Create(std::wstring(), false, false, buffer_size_) &&
        shared_memory_.Map(buffer_size_)) {
      data_ = reinterpret_cast<char*>(shared_memory_.memory());
      // TODO(hawk): Remove after debugging bug 16371.
      CHECK(data_);
      ok_ = true;
    }
    return ok_;
  }

  base::SharedMemory* shared_memory() { return &shared_memory_; }
  bool ok() { return ok_; }
  int buffer_size() { return buffer_size_; }

 private:
  ~SharedIOBuffer() {
    // TODO(willchan): Remove after debugging bug 16371.
    CHECK(g_spare_read_buffer != this);
    data_ = NULL;
  }

  base::SharedMemory shared_memory_;
  bool ok_;
  int buffer_size_;
};

AsyncResourceHandler::AsyncResourceHandler(
    ResourceDispatcherHost::Receiver* receiver,
    int process_id,
    int routing_id,
    base::ProcessHandle process_handle,
    const GURL& url,
    ResourceDispatcherHost* resource_dispatcher_host)
    : receiver_(receiver),
      process_id_(process_id),
      routing_id_(routing_id),
      process_handle_(process_handle),
      rdh_(resource_dispatcher_host),
      next_buffer_size_(kInitialReadBufSize) {
}

AsyncResourceHandler::~AsyncResourceHandler() {
}

void AsyncResourceHandler::PopulateTimingInfo(URLRequest* request,
                                              ResourceResponse* response) {
  if (!(request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING))
    return;

  ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>(
      request->net_log().net_log());
  if (chrome_net_log == NULL)
    return;

  uint32 source_id = request->net_log().source().id;
  LoadTimingObserver* observer = chrome_net_log->load_timing_observer();
  LoadTimingObserver::URLRequestRecord* record =
      observer->GetURLRequestRecord(source_id);
  if (record) {
    response->response_head.connection_id = record->socket_log_id;
    response->response_head.connection_reused = record->socket_reused;
    response->response_head.load_timing = record->timing;
  }
}

bool AsyncResourceHandler::OnUploadProgress(int request_id,
                                            uint64 position,
                                            uint64 size) {
  return receiver_->Send(new ViewMsg_Resource_UploadProgress(routing_id_,
                                                             request_id,
                                                             position, size));
}

bool AsyncResourceHandler::OnRequestRedirected(int request_id,
                                               const GURL& new_url,
                                               ResourceResponse* response,
                                               bool* defer) {
  *defer = true;
  URLRequest* request = rdh_->GetURLRequest(
      GlobalRequestID(process_id_, request_id));
  PopulateTimingInfo(request, response);
  return receiver_->Send(new ViewMsg_Resource_ReceivedRedirect(
      routing_id_, request_id, new_url, response->response_head));
}

bool AsyncResourceHandler::OnResponseStarted(int request_id,
                                             ResourceResponse* response) {
  // For changes to the main frame, inform the renderer of the new URL's
  // per-host settings before the request actually commits.  This way the
  // renderer will be able to set these precisely at the time the
  // request commits, avoiding the possibility of e.g. zooming the old content
  // or of having to layout the new content twice.
  URLRequest* request = rdh_->GetURLRequest(
      GlobalRequestID(process_id_, request_id));

  PopulateTimingInfo(request, response);

  ResourceDispatcherHostRequestInfo* info = rdh_->InfoForRequest(request);
  if (info->resource_type() == ResourceType::MAIN_FRAME) {
    GURL request_url(request->url());
    ChromeURLRequestContext* context =
        static_cast<ChromeURLRequestContext*>(request->context());
    if (context) {
      receiver_->Send(new ViewMsg_SetContentSettingsForLoadingURL(
          info->route_id(), request_url,
          context->host_content_settings_map()->GetContentSettings(
              request_url)));
      receiver_->Send(new ViewMsg_SetZoomLevelForLoadingURL(info->route_id(),
          request_url, context->host_zoom_map()->GetZoomLevel(request_url)));
    }
  }

  receiver_->Send(new ViewMsg_Resource_ReceivedResponse(
      routing_id_, request_id, response->response_head));

  if (request->response_info().metadata) {
    std::vector<char> copy(request->response_info().metadata->data(),
                           request->response_info().metadata->data() +
                           request->response_info().metadata->size());
    receiver_->Send(new ViewMsg_Resource_ReceivedCachedMetadata(
        routing_id_, request_id, copy));
  }

  return true;
}

bool AsyncResourceHandler::OnWillStart(int request_id,
                                       const GURL& url,
                                       bool* defer) {
  return true;
}

bool AsyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
                                      int* buf_size, int min_size) {
  DCHECK(min_size == -1);

  if (g_spare_read_buffer) {
    DCHECK(!read_buffer_);
    read_buffer_.swap(&g_spare_read_buffer);
    // TODO(willchan): Remove after debugging bug 16371.
    CHECK(read_buffer_->data());

    *buf = read_buffer_.get();
    *buf_size = read_buffer_->buffer_size();
  } else {
    read_buffer_ = new SharedIOBuffer(next_buffer_size_);
    if (!read_buffer_->Init()) {
      DLOG(ERROR) << "Couldn't allocate shared io buffer";
      read_buffer_ = NULL;
      return false;
    }
    // TODO(willchan): Remove after debugging bug 16371.
    CHECK(read_buffer_->data());
    *buf = read_buffer_.get();
    *buf_size = next_buffer_size_;
  }

  return true;
}

bool AsyncResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
  if (!*bytes_read)
    return true;
  DCHECK(read_buffer_.get());

  if (read_buffer_->buffer_size() == *bytes_read) {
    // The network layer has saturated our buffer. Next time, we should give it
    // a bigger buffer for it to fill, to minimize the number of round trips we
    // do with the renderer process.
    next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize);
  }

  if (!rdh_->WillSendData(process_id_, request_id)) {
    // We should not send this data now, we have too many pending requests.
    return true;
  }

  base::SharedMemoryHandle handle;
  if (!read_buffer_->shared_memory()->GiveToProcess(process_handle_, &handle)) {
    // We wrongfully incremented the pending data count. Fake an ACK message
    // to fix this. We can't move this call above the WillSendData because
    // it's killing our read_buffer_, and we don't want that when we pause
    // the request.
    rdh_->DataReceivedACK(process_id_, request_id);
    // We just unmapped the memory.
    read_buffer_ = NULL;
    return false;
  }
  // We just unmapped the memory.
  read_buffer_ = NULL;

  receiver_->Send(new ViewMsg_Resource_DataReceived(
      routing_id_, request_id, handle, *bytes_read));

  return true;
}

bool AsyncResourceHandler::OnResponseCompleted(
    int request_id,
    const URLRequestStatus& status,
    const std::string& security_info) {
  receiver_->Send(new ViewMsg_Resource_RequestComplete(routing_id_,
                                                       request_id,
                                                       status,
                                                       security_info));

  // If we still have a read buffer, then see about caching it for later...
  if (g_spare_read_buffer) {
    read_buffer_ = NULL;
  } else if (read_buffer_.get()) {
    // TODO(willchan): Remove after debugging bug 16371.
    CHECK(read_buffer_->data());
    read_buffer_.swap(&g_spare_read_buffer);
  }
  return true;
}

void AsyncResourceHandler::OnRequestClosed() {
}

// static
void AsyncResourceHandler::GlobalCleanup() {
  if (g_spare_read_buffer) {
    // Avoid the CHECK in SharedIOBuffer::~SharedIOBuffer().
    SharedIOBuffer* tmp = g_spare_read_buffer;
    g_spare_read_buffer = NULL;
    tmp->Release();
  }
}
<commit_msg>AsyncResourceHandler: When a URLRequest is canceled, the network code may complete the request with a CANCELED status but hold on to the actual buffer that was used for the operation (that's the whole point about using IOBuffers instead of a plain, non-refcounted buffer).<commit_after>// Copyright (c) 2010 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/renderer_host/async_resource_handler.h"

#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/process.h"
#include "base/shared_memory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/load_timing_observer.h"
#include "chrome/browser/renderer_host/global_request_id.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/common/render_messages.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_log.h"
#include "webkit/glue/resource_loader_bridge.h"

using base::Time;
using base::TimeTicks;

namespace {

// When reading, we don't know if we are going to get EOF (0 bytes read), so
// we typically have a buffer that we allocated but did not use.  We keep
// this buffer around for the next read as a small optimization.
SharedIOBuffer* g_spare_read_buffer = NULL;

// The initial size of the shared memory buffer. (32 kilobytes).
const int kInitialReadBufSize = 32768;

// The maximum size of the shared memory buffer. (512 kilobytes).
const int kMaxReadBufSize = 524288;

}  // namespace

// Our version of IOBuffer that uses shared memory.
class SharedIOBuffer : public net::IOBuffer {
 public:
  explicit SharedIOBuffer(int buffer_size)
      : net::IOBuffer(),
        ok_(false),
        buffer_size_(buffer_size) {}

  bool Init() {
    if (shared_memory_.Create(std::wstring(), false, false, buffer_size_) &&
        shared_memory_.Map(buffer_size_)) {
      data_ = reinterpret_cast<char*>(shared_memory_.memory());
      DCHECK(data_);
      ok_ = true;
    }
    return ok_;
  }

  base::SharedMemory* shared_memory() { return &shared_memory_; }
  bool ok() { return ok_; }
  int buffer_size() { return buffer_size_; }

 private:
  ~SharedIOBuffer() {
    DCHECK(g_spare_read_buffer != this);
    data_ = NULL;
  }

  base::SharedMemory shared_memory_;
  bool ok_;
  int buffer_size_;
};

AsyncResourceHandler::AsyncResourceHandler(
    ResourceDispatcherHost::Receiver* receiver,
    int process_id,
    int routing_id,
    base::ProcessHandle process_handle,
    const GURL& url,
    ResourceDispatcherHost* resource_dispatcher_host)
    : receiver_(receiver),
      process_id_(process_id),
      routing_id_(routing_id),
      process_handle_(process_handle),
      rdh_(resource_dispatcher_host),
      next_buffer_size_(kInitialReadBufSize) {
}

AsyncResourceHandler::~AsyncResourceHandler() {
}

void AsyncResourceHandler::PopulateTimingInfo(URLRequest* request,
                                              ResourceResponse* response) {
  if (!(request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING))
    return;

  ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>(
      request->net_log().net_log());
  if (chrome_net_log == NULL)
    return;

  uint32 source_id = request->net_log().source().id;
  LoadTimingObserver* observer = chrome_net_log->load_timing_observer();
  LoadTimingObserver::URLRequestRecord* record =
      observer->GetURLRequestRecord(source_id);
  if (record) {
    response->response_head.connection_id = record->socket_log_id;
    response->response_head.connection_reused = record->socket_reused;
    response->response_head.load_timing = record->timing;
  }
}

bool AsyncResourceHandler::OnUploadProgress(int request_id,
                                            uint64 position,
                                            uint64 size) {
  return receiver_->Send(new ViewMsg_Resource_UploadProgress(routing_id_,
                                                             request_id,
                                                             position, size));
}

bool AsyncResourceHandler::OnRequestRedirected(int request_id,
                                               const GURL& new_url,
                                               ResourceResponse* response,
                                               bool* defer) {
  *defer = true;
  URLRequest* request = rdh_->GetURLRequest(
      GlobalRequestID(process_id_, request_id));
  PopulateTimingInfo(request, response);
  return receiver_->Send(new ViewMsg_Resource_ReceivedRedirect(
      routing_id_, request_id, new_url, response->response_head));
}

bool AsyncResourceHandler::OnResponseStarted(int request_id,
                                             ResourceResponse* response) {
  // For changes to the main frame, inform the renderer of the new URL's
  // per-host settings before the request actually commits.  This way the
  // renderer will be able to set these precisely at the time the
  // request commits, avoiding the possibility of e.g. zooming the old content
  // or of having to layout the new content twice.
  URLRequest* request = rdh_->GetURLRequest(
      GlobalRequestID(process_id_, request_id));

  PopulateTimingInfo(request, response);

  ResourceDispatcherHostRequestInfo* info = rdh_->InfoForRequest(request);
  if (info->resource_type() == ResourceType::MAIN_FRAME) {
    GURL request_url(request->url());
    ChromeURLRequestContext* context =
        static_cast<ChromeURLRequestContext*>(request->context());
    if (context) {
      receiver_->Send(new ViewMsg_SetContentSettingsForLoadingURL(
          info->route_id(), request_url,
          context->host_content_settings_map()->GetContentSettings(
              request_url)));
      receiver_->Send(new ViewMsg_SetZoomLevelForLoadingURL(info->route_id(),
          request_url, context->host_zoom_map()->GetZoomLevel(request_url)));
    }
  }

  receiver_->Send(new ViewMsg_Resource_ReceivedResponse(
      routing_id_, request_id, response->response_head));

  if (request->response_info().metadata) {
    std::vector<char> copy(request->response_info().metadata->data(),
                           request->response_info().metadata->data() +
                           request->response_info().metadata->size());
    receiver_->Send(new ViewMsg_Resource_ReceivedCachedMetadata(
        routing_id_, request_id, copy));
  }

  return true;
}

bool AsyncResourceHandler::OnWillStart(int request_id,
                                       const GURL& url,
                                       bool* defer) {
  return true;
}

bool AsyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
                                      int* buf_size, int min_size) {
  DCHECK_EQ(-1, min_size);

  if (g_spare_read_buffer) {
    DCHECK(!read_buffer_);
    read_buffer_.swap(&g_spare_read_buffer);
    DCHECK(read_buffer_->data());

    *buf = read_buffer_.get();
    *buf_size = read_buffer_->buffer_size();
  } else {
    read_buffer_ = new SharedIOBuffer(next_buffer_size_);
    if (!read_buffer_->Init()) {
      DLOG(ERROR) << "Couldn't allocate shared io buffer";
      read_buffer_ = NULL;
      return false;
    }
    DCHECK(read_buffer_->data());
    *buf = read_buffer_.get();
    *buf_size = next_buffer_size_;
  }

  return true;
}

bool AsyncResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
  if (!*bytes_read)
    return true;
  DCHECK(read_buffer_.get());

  if (read_buffer_->buffer_size() == *bytes_read) {
    // The network layer has saturated our buffer. Next time, we should give it
    // a bigger buffer for it to fill, to minimize the number of round trips we
    // do with the renderer process.
    next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize);
  }

  if (!rdh_->WillSendData(process_id_, request_id)) {
    // We should not send this data now, we have too many pending requests.
    return true;
  }

  base::SharedMemoryHandle handle;
  if (!read_buffer_->shared_memory()->GiveToProcess(process_handle_, &handle)) {
    // We wrongfully incremented the pending data count. Fake an ACK message
    // to fix this. We can't move this call above the WillSendData because
    // it's killing our read_buffer_, and we don't want that when we pause
    // the request.
    rdh_->DataReceivedACK(process_id_, request_id);
    // We just unmapped the memory.
    read_buffer_ = NULL;
    return false;
  }
  // We just unmapped the memory.
  read_buffer_ = NULL;

  receiver_->Send(new ViewMsg_Resource_DataReceived(
      routing_id_, request_id, handle, *bytes_read));

  return true;
}

bool AsyncResourceHandler::OnResponseCompleted(
    int request_id,
    const URLRequestStatus& status,
    const std::string& security_info) {
  receiver_->Send(new ViewMsg_Resource_RequestComplete(routing_id_,
                                                       request_id,
                                                       status,
                                                       security_info));

  // If we still have a read buffer, then see about caching it for later...
  // Note that we have to make sure the buffer is not still being used, so we
  // have to perform an explicit check on the status code.
  if (g_spare_read_buffer || URLRequestStatus::SUCCESS != status.status()) {
    read_buffer_ = NULL;
  } else if (read_buffer_.get()) {
    DCHECK(read_buffer_->data());
    read_buffer_.swap(&g_spare_read_buffer);
  }
  return true;
}

void AsyncResourceHandler::OnRequestClosed() {
}

// static
void AsyncResourceHandler::GlobalCleanup() {
  if (g_spare_read_buffer) {
    // Avoid the CHECK in SharedIOBuffer::~SharedIOBuffer().
    SharedIOBuffer* tmp = g_spare_read_buffer;
    g_spare_read_buffer = NULL;
    tmp->Release();
  }
}
<|endoftext|>