<commit_before>// Copyright (c) 2012 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/spellchecker/spelling_service_client.h"

#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/spellcheck_result.h"
#include "google_apis/google_api_keys.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "third_party/icu/public/common/unicode/uloc.h"

namespace {

// Constants for the spellcheck field trial.
const char kSpellcheckFieldTrialName[] = "Spellcheck";
const char kSpellcheckFieldTrialSuggestionsGroupName[] = "Suggestions";

// The URL for requesting spell checking and sending user feedback.
const char kSpellingServiceURL[] = "https://www.googleapis.com/rpc";

// Gets the ISO codes for the language and country of this |locale|. The
// |locale| is an ISO locale ID that may not include a country ID, e.g., "fr" or
// "de". This method converts the UI locale to a full locale ID and converts the
// full locale ID to an ISO language code and an ISO3 country code.
void GetISOLanguageCountryCodeFromLocale(
    const std::string& locale,
    std::string* language_code,
    std::string* country_code) {
  DCHECK(language_code);
  DCHECK(country_code);
  char language[ULOC_LANG_CAPACITY] = ULOC_ENGLISH;
  const char* country = "USA";
  if (!locale.empty()) {
    UErrorCode error = U_ZERO_ERROR;
    char id[ULOC_LANG_CAPACITY + ULOC_SCRIPT_CAPACITY + ULOC_COUNTRY_CAPACITY];
    uloc_addLikelySubtags(locale.c_str(), id, arraysize(id), &error);
    error = U_ZERO_ERROR;
    uloc_getLanguage(id, language, arraysize(language), &error);
    country = uloc_getISO3Country(id);
  }
  *language_code = std::string(language);
  *country_code = std::string(country);
}

}  // namespace

SpellingServiceClient::SpellingServiceClient() {
}

SpellingServiceClient::~SpellingServiceClient() {
  STLDeleteContainerPairPointers(spellcheck_fetchers_.begin(),
                                 spellcheck_fetchers_.end());
}

bool SpellingServiceClient::RequestTextCheck(
    Profile* profile,
    ServiceType type,
    const string16& text,
    const TextCheckCompleteCallback& callback) {
  DCHECK(type == SUGGEST || type == SPELLCHECK);
  if (!profile || !IsAvailable(profile, type)) {
    callback.Run(false, text, std::vector<SpellCheckResult>());
    return false;
  }

  std::string language_code;
  std::string country_code;
  GetISOLanguageCountryCodeFromLocale(
      profile->GetPrefs()->GetString(prefs::kSpellCheckDictionary),
      &language_code,
      &country_code);

  // Format the JSON request to be sent to the Spelling service.
  std::string encoded_text;
  base::JsonDoubleQuote(text, false, &encoded_text);

  static const char kSpellingRequest[] =
      "{"
      "\"method\":\"spelling.check\","
      "\"apiVersion\":\"v%d\","
      "\"params\":{"
      "\"text\":\"%s\","
      "\"language\":\"%s\","
      "\"originCountry\":\"%s\","
      "\"key\":%s"
      "}"
      "}";
  std::string api_key = base::GetDoubleQuotedJson(google_apis::GetAPIKey());
  std::string request = base::StringPrintf(
      kSpellingRequest,
      type,
      encoded_text.c_str(),
      language_code.c_str(),
      country_code.c_str(),
      api_key.c_str());

  GURL url = GURL(kSpellingServiceURL);
  net::URLFetcher* fetcher = CreateURLFetcher(url);
  fetcher->SetRequestContext(profile->GetRequestContext());
  fetcher->SetUploadData("application/json", request);
  fetcher->SetLoadFlags(
      net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
  spellcheck_fetchers_[fetcher] = new TextCheckCallbackData(callback, text);
  fetcher->Start();
  return true;
}

bool SpellingServiceClient::IsAvailable(Profile* profile, ServiceType type) {
  const PrefService* pref = profile->GetPrefs();
  // If prefs don't allow spellchecking or if the profile is off the record,
  // the spelling service should be unavailable.
  if (!pref->GetBoolean(prefs::kEnableContinuousSpellcheck) ||
      !pref->GetBoolean(prefs::kSpellCheckUseSpellingService) ||
      profile->IsOffTheRecord())
    return false;

  // If the locale for spelling has not been set, the user has not decided to
  // use spellcheck so we don't do anything remote (suggest or spelling).
  std::string locale = pref->GetString(prefs::kSpellCheckDictionary);
  if (locale.empty())
    return false;

  // If we do not have the spelling service enabled, then we are only available
  // for SUGGEST.
  const CommandLine* command_line = CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kUseSpellingSuggestions))
    return type == SUGGEST;

  // Finally, if all options are available, we only enable only SUGGEST
  // if SPELLCHECK is not available for our language because SPELLCHECK results
  // are a superset of SUGGEST results.
  // TODO(rlp): Only available for English right now. Fix this line to include
  // all languages SPELLCHECK covers.
  bool language_available = !locale.compare(0, 2, "en");
  if (language_available) {
    // Either SUGGEST or SPELLCHECK are normally allowed.
    // Run the field trial for users who would normally have the service
    // available.
    if (base::FieldTrialList::FindFullName(kSpellcheckFieldTrialName) ==
        kSpellcheckFieldTrialSuggestionsGroupName) {
      return type == SUGGEST;
    } else {
      return type == SPELLCHECK;
    }
  } else {
    // Only SUGGEST is allowed.
    return type == SUGGEST;
  }
}

SpellingServiceClient::TextCheckCallbackData::TextCheckCallbackData(
    TextCheckCompleteCallback callback,
    string16 text)
      : callback(callback),
        text(text) {
}

SpellingServiceClient::TextCheckCallbackData::~TextCheckCallbackData() {
}

void SpellingServiceClient::OnURLFetchComplete(
    const net::URLFetcher* source) {
  DCHECK(spellcheck_fetchers_[source]);
  scoped_ptr<const net::URLFetcher> fetcher(source);
  scoped_ptr<TextCheckCallbackData>
      callback_data(spellcheck_fetchers_[fetcher.get()]);
  bool success = false;
  std::vector<SpellCheckResult> results;
  if (fetcher->GetResponseCode() / 100 == 2) {
    std::string data;
    fetcher->GetResponseAsString(&data);
    success = ParseResponse(data, &results);
  }
  callback_data->callback.Run(success, callback_data->text, results);
  spellcheck_fetchers_.erase(fetcher.get());
}

net::URLFetcher* SpellingServiceClient::CreateURLFetcher(const GURL& url) {
  return net::URLFetcher::Create(url, net::URLFetcher::POST, this);
}

bool SpellingServiceClient::ParseResponse(
    const std::string& data,
    std::vector<SpellCheckResult>* results) {
  // When this JSON-RPC call finishes successfully, the Spelling service returns
  // an JSON object listed below.
  // * result - an envelope object representing the result from the APIARY
  //   server, which is the JSON-API front-end for the Spelling service. This
  //   object consists of the following variable:
  //   - spellingCheckResponse (SpellingCheckResponse).
  // * SpellingCheckResponse - an object representing the result from the
  //   Spelling service. This object consists of the following variable:
  //   - misspellings (optional array of Misspelling)
  // * Misspelling - an object representing a misspelling region and its
  //   suggestions. This object consists of the following variables:
  //   - charStart (number) - the beginning of the misspelled region;
  //   - charLength (number) - the length of the misspelled region;
  //   - suggestions (array of string) - the suggestions for the misspelling
  //     text, and;
  //   - canAutoCorrect (optional boolean) - whether we can use the first
  //     suggestion for auto-correction.
  // For example, the Spelling service returns the following JSON when we send a
  // spelling request for "duck goes quisk" as of 16 August, 2011.
  // {
  //   "result": {
  //     "spellingCheckResponse": {
  //       "misspellings": [{
  //           "charStart": 10,
  //           "charLength": 5,
  //           "suggestions": [{ "suggestion": "quack" }],
  //           "canAutoCorrect": false
  //       }]
  //     }
  //   }
  // }
  scoped_ptr<DictionaryValue> value(
      static_cast<DictionaryValue*>(
          base::JSONReader::Read(data, base::JSON_ALLOW_TRAILING_COMMAS)));
  if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY))
    return false;

  // Retrieve the array of Misspelling objects. When the input text does not
  // have misspelled words, it returns an empty JSON. (In this case, its HTTP
  // status is 200.) We just return true for this case.
  ListValue* misspellings = NULL;
  const char kMisspellings[] = "result.spellingCheckResponse.misspellings";
  if (!value->GetList(kMisspellings, &misspellings))
    return true;

  for (size_t i = 0; i < misspellings->GetSize(); ++i) {
    // Retrieve the i-th misspelling region and put it to the given vector. When
    // the Spelling service sends two or more suggestions, we read only the
    // first one because SpellCheckResult can store only one suggestion.
    DictionaryValue* misspelling = NULL;
    if (!misspellings->GetDictionary(i, &misspelling))
      return false;

    int start = 0;
    int length = 0;
    ListValue* suggestions = NULL;
    if (!misspelling->GetInteger("charStart", &start) ||
        !misspelling->GetInteger("charLength", &length) ||
        !misspelling->GetList("suggestions", &suggestions)) {
      return false;
    }

    DictionaryValue* suggestion = NULL;
    string16 replacement;
    if (!suggestions->GetDictionary(0, &suggestion) ||
        !suggestion->GetString("suggestion", &replacement)) {
      return false;
    }
    SpellCheckResult result(
        SpellCheckResult::SPELLING, start, length, replacement);
    results->push_back(result);
  }
  return true;
}
<commit_msg>[Spellcheck] Removing the field trial. We've launched!<commit_after>// Copyright (c) 2012 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/spellchecker/spelling_service_client.h"

#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/spellcheck_result.h"
#include "google_apis/google_api_keys.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "third_party/icu/public/common/unicode/uloc.h"

namespace {

// The URL for requesting spell checking and sending user feedback.
const char kSpellingServiceURL[] = "https://www.googleapis.com/rpc";

// Gets the ISO codes for the language and country of this |locale|. The
// |locale| is an ISO locale ID that may not include a country ID, e.g., "fr" or
// "de". This method converts the UI locale to a full locale ID and converts the
// full locale ID to an ISO language code and an ISO3 country code.
void GetISOLanguageCountryCodeFromLocale(
    const std::string& locale,
    std::string* language_code,
    std::string* country_code) {
  DCHECK(language_code);
  DCHECK(country_code);
  char language[ULOC_LANG_CAPACITY] = ULOC_ENGLISH;
  const char* country = "USA";
  if (!locale.empty()) {
    UErrorCode error = U_ZERO_ERROR;
    char id[ULOC_LANG_CAPACITY + ULOC_SCRIPT_CAPACITY + ULOC_COUNTRY_CAPACITY];
    uloc_addLikelySubtags(locale.c_str(), id, arraysize(id), &error);
    error = U_ZERO_ERROR;
    uloc_getLanguage(id, language, arraysize(language), &error);
    country = uloc_getISO3Country(id);
  }
  *language_code = std::string(language);
  *country_code = std::string(country);
}

}  // namespace

SpellingServiceClient::SpellingServiceClient() {
}

SpellingServiceClient::~SpellingServiceClient() {
  STLDeleteContainerPairPointers(spellcheck_fetchers_.begin(),
                                 spellcheck_fetchers_.end());
}

bool SpellingServiceClient::RequestTextCheck(
    Profile* profile,
    ServiceType type,
    const string16& text,
    const TextCheckCompleteCallback& callback) {
  DCHECK(type == SUGGEST || type == SPELLCHECK);
  if (!profile || !IsAvailable(profile, type)) {
    callback.Run(false, text, std::vector<SpellCheckResult>());
    return false;
  }

  std::string language_code;
  std::string country_code;
  GetISOLanguageCountryCodeFromLocale(
      profile->GetPrefs()->GetString(prefs::kSpellCheckDictionary),
      &language_code,
      &country_code);

  // Format the JSON request to be sent to the Spelling service.
  std::string encoded_text;
  base::JsonDoubleQuote(text, false, &encoded_text);

  static const char kSpellingRequest[] =
      "{"
      "\"method\":\"spelling.check\","
      "\"apiVersion\":\"v%d\","
      "\"params\":{"
      "\"text\":\"%s\","
      "\"language\":\"%s\","
      "\"originCountry\":\"%s\","
      "\"key\":%s"
      "}"
      "}";
  std::string api_key = base::GetDoubleQuotedJson(google_apis::GetAPIKey());
  std::string request = base::StringPrintf(
      kSpellingRequest,
      type,
      encoded_text.c_str(),
      language_code.c_str(),
      country_code.c_str(),
      api_key.c_str());

  GURL url = GURL(kSpellingServiceURL);
  net::URLFetcher* fetcher = CreateURLFetcher(url);
  fetcher->SetRequestContext(profile->GetRequestContext());
  fetcher->SetUploadData("application/json", request);
  fetcher->SetLoadFlags(
      net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
  spellcheck_fetchers_[fetcher] = new TextCheckCallbackData(callback, text);
  fetcher->Start();
  return true;
}

bool SpellingServiceClient::IsAvailable(Profile* profile, ServiceType type) {
  const PrefService* pref = profile->GetPrefs();
  // If prefs don't allow spellchecking or if the profile is off the record,
  // the spelling service should be unavailable.
  if (!pref->GetBoolean(prefs::kEnableContinuousSpellcheck) ||
      !pref->GetBoolean(prefs::kSpellCheckUseSpellingService) ||
      profile->IsOffTheRecord())
    return false;

  // If the locale for spelling has not been set, the user has not decided to
  // use spellcheck so we don't do anything remote (suggest or spelling).
  std::string locale = pref->GetString(prefs::kSpellCheckDictionary);
  if (locale.empty())
    return false;

  // If we do not have the spelling service enabled, then we are only available
  // for SUGGEST.
  const CommandLine* command_line = CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kUseSpellingSuggestions))
    return type == SUGGEST;

  // Finally, if all options are available, we only enable only SUGGEST
  // if SPELLCHECK is not available for our language because SPELLCHECK results
  // are a superset of SUGGEST results.
  // TODO(rlp): Only available for English right now. Fix this line to include
  // all languages SPELLCHECK covers.
  bool language_available = !locale.compare(0, 2, "en");
  if (language_available) {
    return type == SPELLCHECK;
  } else {
    // Only SUGGEST is allowed.
    return type == SUGGEST;
  }
}

SpellingServiceClient::TextCheckCallbackData::TextCheckCallbackData(
    TextCheckCompleteCallback callback,
    string16 text)
      : callback(callback),
        text(text) {
}

SpellingServiceClient::TextCheckCallbackData::~TextCheckCallbackData() {
}

void SpellingServiceClient::OnURLFetchComplete(
    const net::URLFetcher* source) {
  DCHECK(spellcheck_fetchers_[source]);
  scoped_ptr<const net::URLFetcher> fetcher(source);
  scoped_ptr<TextCheckCallbackData>
      callback_data(spellcheck_fetchers_[fetcher.get()]);
  bool success = false;
  std::vector<SpellCheckResult> results;
  if (fetcher->GetResponseCode() / 100 == 2) {
    std::string data;
    fetcher->GetResponseAsString(&data);
    success = ParseResponse(data, &results);
  }
  callback_data->callback.Run(success, callback_data->text, results);
  spellcheck_fetchers_.erase(fetcher.get());
}

net::URLFetcher* SpellingServiceClient::CreateURLFetcher(const GURL& url) {
  return net::URLFetcher::Create(url, net::URLFetcher::POST, this);
}

bool SpellingServiceClient::ParseResponse(
    const std::string& data,
    std::vector<SpellCheckResult>* results) {
  // When this JSON-RPC call finishes successfully, the Spelling service returns
  // an JSON object listed below.
  // * result - an envelope object representing the result from the APIARY
  //   server, which is the JSON-API front-end for the Spelling service. This
  //   object consists of the following variable:
  //   - spellingCheckResponse (SpellingCheckResponse).
  // * SpellingCheckResponse - an object representing the result from the
  //   Spelling service. This object consists of the following variable:
  //   - misspellings (optional array of Misspelling)
  // * Misspelling - an object representing a misspelling region and its
  //   suggestions. This object consists of the following variables:
  //   - charStart (number) - the beginning of the misspelled region;
  //   - charLength (number) - the length of the misspelled region;
  //   - suggestions (array of string) - the suggestions for the misspelling
  //     text, and;
  //   - canAutoCorrect (optional boolean) - whether we can use the first
  //     suggestion for auto-correction.
  // For example, the Spelling service returns the following JSON when we send a
  // spelling request for "duck goes quisk" as of 16 August, 2011.
  // {
  //   "result": {
  //     "spellingCheckResponse": {
  //       "misspellings": [{
  //           "charStart": 10,
  //           "charLength": 5,
  //           "suggestions": [{ "suggestion": "quack" }],
  //           "canAutoCorrect": false
  //       }]
  //     }
  //   }
  // }
  scoped_ptr<DictionaryValue> value(
      static_cast<DictionaryValue*>(
          base::JSONReader::Read(data, base::JSON_ALLOW_TRAILING_COMMAS)));
  if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY))
    return false;

  // Retrieve the array of Misspelling objects. When the input text does not
  // have misspelled words, it returns an empty JSON. (In this case, its HTTP
  // status is 200.) We just return true for this case.
  ListValue* misspellings = NULL;
  const char kMisspellings[] = "result.spellingCheckResponse.misspellings";
  if (!value->GetList(kMisspellings, &misspellings))
    return true;

  for (size_t i = 0; i < misspellings->GetSize(); ++i) {
    // Retrieve the i-th misspelling region and put it to the given vector. When
    // the Spelling service sends two or more suggestions, we read only the
    // first one because SpellCheckResult can store only one suggestion.
    DictionaryValue* misspelling = NULL;
    if (!misspellings->GetDictionary(i, &misspelling))
      return false;

    int start = 0;
    int length = 0;
    ListValue* suggestions = NULL;
    if (!misspelling->GetInteger("charStart", &start) ||
        !misspelling->GetInteger("charLength", &length) ||
        !misspelling->GetList("suggestions", &suggestions)) {
      return false;
    }

    DictionaryValue* suggestion = NULL;
    string16 replacement;
    if (!suggestions->GetDictionary(0, &suggestion) ||
        !suggestion->GetString("suggestion", &replacement)) {
      return false;
    }
    SpellCheckResult result(
        SpellCheckResult::SPELLING, start, length, replacement);
    results->push_back(result);
  }
  return true;
}
<|endoftext|>


<commit_before>#include <Python.h>
#include <listobject.h>
#include <structmember.h>

#include "util.h"
#include "AWDMeshData.h"
#include "AWDSubMesh.h"
#include "AWDAttrBlock.h"

#include <awd/libawd.h>

/**
 * free()
*/
void
pyawd_AWDMeshData_dealloc(pyawd_AWDMeshData *self)
{
    Py_TYPE(self)->tp_free((PyObject*)self);
}

/**
 * AWDMeshData();
*/
PyObject *
pyawd_AWDMeshData_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    pyawd_AWDMeshData *self;

    self = (pyawd_AWDMeshData *)type->tp_alloc(type, 0);
    if (self) {
        self->next = NULL;
        self->skeleton = NULL;
        self->first_sub_mesh = NULL;
        self->last_sub_mesh = NULL;
        self->num_sub_meshes = 0;
        self->ob_data = new AWDMeshData();
    }

    return (PyObject *)self;
}

/**
 * AWDMeshData.__init__();
*/
int
pyawd_AWDMeshData_init(pyawd_AWDMeshData *self, PyObject *args, PyObject *kwds)
{
    // Superclass __init__
    pyawd_AWDAttrBlock_init((pyawd_AWDAttrBlock *)self, args, kwds);

    return 0;
}

/**
 * AWDMeshData.add_sub_mesh()
*/
PyObject *
pyawd_AWDMeshData_add_sub_mesh(pyawd_AWDMeshData *self, PyObject *args, PyObject *kwds)
{
    int tris_len;
    int verts_len;
    awd_bool wide;

    PyObject *sub_arg;
    pyawd_AWDSubMesh *sub;

    if (!PyArg_ParseTuple(args, "O!", &pyawd_AWDSubMeshType, &sub_arg))
        return NULL;

    sub = (pyawd_AWDSubMesh *)sub_arg;
    self->ob_data->add_sub_mesh(sub->ob_sub);

    if (self->first_sub_mesh == NULL) {
        self->first_sub_mesh = sub;
    }
    else {
        self->last_sub_mesh->next = sub;
    }

    self->last_sub_mesh = sub;
    self->last_sub_mesh->next = NULL;
    self->num_sub_meshes++;

    Py_RETURN_NONE;
}

/**
 * AWDMeshData[] (sub-meshes through subscripting)
*/
static PyObject *
pyawd_AWDMeshData_mp_subscript(pyawd_AWDMeshData *self, PyObject *key)
{
    if (PyInt_Check(key)) {
        long idx;
        idx = PyInt_AsLong(key);
        if (idx < self->num_sub_meshes) {
            long cur_idx;
            pyawd_AWDSubMesh *cur;

            cur_idx = 0;
            cur = self->first_sub_mesh;
            while (cur) {
                if (cur_idx == idx)
                    return (PyObject *)cur;

                cur = cur->next;
                cur_idx++;
            }

        }
        else {
            // TODO: Set exception
            return NULL;
        }
    }
    else {
        // TODO: Set exception
        return NULL;
    }
}

/**
 * len(AWDMeshData)
*/
static int
pyawd_AWDMeshData_mp_length(pyawd_AWDMeshData *self)
{
    return self->num_sub_meshes;
}

/**
 * AWDMeshData.skeleton (setter)
*/
static int
pyawd_AWDMeshData_set_skeleton(pyawd_AWDMeshData *self, PyObject *value, void *closure)
{
    if (PyObject_IsInstance(value, (PyObject *)&pyawd_AWDSkeletonType)) {
        self->skeleton = (pyawd_AWDSkeleton *)value;
        self->ob_data->set_skeleton(self->skeleton->ob_skeleton);
        return 0;
    }
    else {
        return -1;
    }
}

/**
 * AWDMeshData.skeleton (getter)
*/
static PyObject *
pyawd_AWDMeshData_get_skeleton(pyawd_AWDMeshData *self, void *closure)
{
    if (self->skeleton != NULL)
        return (PyObject *)self->skeleton;

    Py_RETURN_NONE;
}

/**
 * Method dictionary
*/
PyMethodDef pyawd_AWDMeshData_methods[] = {
    { "add_sub_mesh", (PyCFunction)pyawd_AWDMeshData_add_sub_mesh, METH_VARARGS | METH_KEYWORDS,
        "Add a sub-mesh (geometry) to a mesh data block." },

    { NULL }
};

/**
 * Getter/setter dictionary
*/
PyGetSetDef pyawd_AWDMeshData_getset[] = {
    { "skeleton",
        (getter)pyawd_AWDMeshData_get_skeleton,
        (setter)pyawd_AWDMeshData_set_skeleton,
        "Defines the skeleton that this mesh is bound to (if any)",
        NULL },
    { NULL }
};

/**
 * Mapping protocol dictionary
*/
PyMappingMethods pyawd_AWDMeshDataMapping = {
    (lenfunc)pyawd_AWDMeshData_mp_length,   /* mp_length */
    (binaryfunc)pyawd_AWDMeshData_mp_subscript,/* mp_subscript */
};

/**
 * Type object
*/
PyTypeObject pyawd_AWDMeshDataType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "pyawd.AWDMeshData",                    /* tp_name */
    sizeof(pyawd_AWDMeshData),              /* tp_basicsize */
    0,                                      /* tp_itemsize */
    (destructor)pyawd_AWDMeshData_dealloc,  /* tp_dealloc */
    0,                                      /* tp_print */
    0,                                      /* tp_getattr */
    0,                                      /* tp_setattr */
    0,                                      /* tp_reserved */
    0,                                      /* tp_repr */
    0,                                      /* tp_as_number */
    0,                                      /* tp_as_sequence */
    &pyawd_AWDMeshDataMapping,               /* tp_as_mapping */
    0,                                      /* tp_hash  */
    0,                                      /* tp_call */
    0,                                      /* tp_str */
    0,                                      /* tp_getattro */
    0,                                      /* tp_setattro */
    0,                                      /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT |
        Py_TPFLAGS_BASETYPE,                /* tp_flags */
    "AWD mesh representation.",             /* tp_doc */
    0,                                      /* tp_traverse */
    0,                                      /* tp_clear */
    0,                                      /* tp_richcompare */
    0,                                      /* tp_weaklistoffset */
    0,                                      /* tp_iter */
    0,                                      /* tp_iternext */
    pyawd_AWDMeshData_methods,              /* tp_methods */
    0,                                      /* tp_members */
    pyawd_AWDMeshData_getset,               /* tp_getset */
    &pyawd_AWDAttrBlockType,                /* tp_base */
    0,                                      /* tp_dict */
    0,                                      /* tp_descr_get */
    0,                                      /* tp_descr_set */
    0,                                      /* tp_dictoffset */
    (initproc)pyawd_AWDMeshData_init,       /* tp_init */
    0,                                      /* tp_alloc */
    pyawd_AWDMeshData_new,                  /* tp_new */
};

<commit_msg>Fixed bug in pyawd.AWDMeshData where the sub meshes would be deallocated as the refcount was not increased. - Similar bugs most likely exists in other places as well, and will need to be amended throughout pyawd<commit_after>#include <Python.h>
#include <listobject.h>
#include <structmember.h>

#include "util.h"
#include "AWDMeshData.h"
#include "AWDSubMesh.h"
#include "AWDAttrBlock.h"

#include <awd/libawd.h>

/**
 * free()
*/
void
pyawd_AWDMeshData_dealloc(pyawd_AWDMeshData *self)
{
    Py_TYPE(self)->tp_free((PyObject*)self);
}

/**
 * AWDMeshData();
*/
PyObject *
pyawd_AWDMeshData_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    pyawd_AWDMeshData *self;

    self = (pyawd_AWDMeshData *)type->tp_alloc(type, 0);
    if (self) {
        self->next = NULL;
        self->skeleton = NULL;
        self->first_sub_mesh = NULL;
        self->last_sub_mesh = NULL;
        self->num_sub_meshes = 0;
        self->ob_data = new AWDMeshData();
    }

    return (PyObject *)self;
}

/**
 * AWDMeshData.__init__();
*/
int
pyawd_AWDMeshData_init(pyawd_AWDMeshData *self, PyObject *args, PyObject *kwds)
{
    // Superclass __init__
    pyawd_AWDAttrBlock_init((pyawd_AWDAttrBlock *)self, args, kwds);

    return 0;
}

/**
 * AWDMeshData.add_sub_mesh()
*/
PyObject *
pyawd_AWDMeshData_add_sub_mesh(pyawd_AWDMeshData *self, PyObject *args, PyObject *kwds)
{
    int tris_len;
    int verts_len;
    awd_bool wide;

    PyObject *sub_arg;
    pyawd_AWDSubMesh *sub;

    if (!PyArg_ParseTuple(args, "O!", &pyawd_AWDSubMeshType, &sub_arg))
        return NULL;

    sub = (pyawd_AWDSubMesh *)sub_arg;
    self->ob_data->add_sub_mesh(sub->ob_sub);

    if (self->first_sub_mesh == NULL) {
        self->first_sub_mesh = sub;
    }
    else {
        self->last_sub_mesh->next = sub;
    }

    self->last_sub_mesh = sub;
    self->last_sub_mesh->next = NULL;
    self->num_sub_meshes++;

    // Protect from GC
    Py_INCREF(sub);

    Py_RETURN_NONE;
}

/**
 * AWDMeshData[] (sub-meshes through subscripting)
*/
static PyObject *
pyawd_AWDMeshData_mp_subscript(pyawd_AWDMeshData *self, PyObject *key)
{
    if (PyInt_Check(key)) {
        long idx;
        idx = PyInt_AsLong(key);
        if (idx < self->num_sub_meshes) {
            long cur_idx;
            pyawd_AWDSubMesh *cur;

            cur_idx = 0;
            cur = self->first_sub_mesh;
            while (cur) {
                if (cur_idx == idx)
                    return (PyObject *)cur;

                cur = cur->next;
                cur_idx++;
            }

        }
        else {
            // TODO: Set exception
            return NULL;
        }
    }
    else {
        // TODO: Set exception
        return NULL;
    }
}

/**
 * len(AWDMeshData)
*/
static int
pyawd_AWDMeshData_mp_length(pyawd_AWDMeshData *self)
{
    return self->num_sub_meshes;
}

/**
 * AWDMeshData.skeleton (setter)
*/
static int
pyawd_AWDMeshData_set_skeleton(pyawd_AWDMeshData *self, PyObject *value, void *closure)
{
    if (PyObject_IsInstance(value, (PyObject *)&pyawd_AWDSkeletonType)) {
        self->skeleton = (pyawd_AWDSkeleton *)value;
        self->ob_data->set_skeleton(self->skeleton->ob_skeleton);
        return 0;
    }
    else {
        return -1;
    }
}

/**
 * AWDMeshData.skeleton (getter)
*/
static PyObject *
pyawd_AWDMeshData_get_skeleton(pyawd_AWDMeshData *self, void *closure)
{
    if (self->skeleton != NULL)
        return (PyObject *)self->skeleton;

    Py_RETURN_NONE;
}

/**
 * Method dictionary
*/
PyMethodDef pyawd_AWDMeshData_methods[] = {
    { "add_sub_mesh", (PyCFunction)pyawd_AWDMeshData_add_sub_mesh, METH_VARARGS | METH_KEYWORDS,
        "Add a sub-mesh (geometry) to a mesh data block." },

    { NULL }
};

/**
 * Getter/setter dictionary
*/
PyGetSetDef pyawd_AWDMeshData_getset[] = {
    { "skeleton",
        (getter)pyawd_AWDMeshData_get_skeleton,
        (setter)pyawd_AWDMeshData_set_skeleton,
        "Defines the skeleton that this mesh is bound to (if any)",
        NULL },
    { NULL }
};

/**
 * Mapping protocol dictionary
*/
PyMappingMethods pyawd_AWDMeshDataMapping = {
    (lenfunc)pyawd_AWDMeshData_mp_length,   /* mp_length */
    (binaryfunc)pyawd_AWDMeshData_mp_subscript,/* mp_subscript */
};

/**
 * Type object
*/
PyTypeObject pyawd_AWDMeshDataType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "pyawd.AWDMeshData",                    /* tp_name */
    sizeof(pyawd_AWDMeshData),              /* tp_basicsize */
    0,                                      /* tp_itemsize */
    (destructor)pyawd_AWDMeshData_dealloc,  /* tp_dealloc */
    0,                                      /* tp_print */
    0,                                      /* tp_getattr */
    0,                                      /* tp_setattr */
    0,                                      /* tp_reserved */
    0,                                      /* tp_repr */
    0,                                      /* tp_as_number */
    0,                                      /* tp_as_sequence */
    &pyawd_AWDMeshDataMapping,               /* tp_as_mapping */
    0,                                      /* tp_hash  */
    0,                                      /* tp_call */
    0,                                      /* tp_str */
    0,                                      /* tp_getattro */
    0,                                      /* tp_setattro */
    0,                                      /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT |
        Py_TPFLAGS_BASETYPE,                /* tp_flags */
    "AWD mesh representation.",             /* tp_doc */
    0,                                      /* tp_traverse */
    0,                                      /* tp_clear */
    0,                                      /* tp_richcompare */
    0,                                      /* tp_weaklistoffset */
    0,                                      /* tp_iter */
    0,                                      /* tp_iternext */
    pyawd_AWDMeshData_methods,              /* tp_methods */
    0,                                      /* tp_members */
    pyawd_AWDMeshData_getset,               /* tp_getset */
    &pyawd_AWDAttrBlockType,                /* tp_base */
    0,                                      /* tp_dict */
    0,                                      /* tp_descr_get */
    0,                                      /* tp_descr_set */
    0,                                      /* tp_dictoffset */
    (initproc)pyawd_AWDMeshData_init,       /* tp_init */
    0,                                      /* tp_alloc */
    pyawd_AWDMeshData_new,                  /* tp_new */
};

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <cppunit/plugin/TestPlugIn.h>

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>graphite2 consolidated patch<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <cppunit/plugin/TestPlugIn.h>

// CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/TextBox.h"

#include "core/selection.h"
#include "project/entity.h"
#include "project/project.h"
#include "project/property.h"
#include "project/record.h"
#include "project/schema.h"
#include "view/ui/property/propertyPanel.h"
#include "core.h"
#include "view.h"

using namespace pixeleditor;

static const int ATOM_PADDING = 5;
static const int ATOM_WIDTH = 200;
static const int ATOM_HEIGHT = 25;
static const int STRUCT_INDENT = 20;

PropertyPanel::PropertyPanel(Gwen::Controls::Base* parent)
    : Gwen::Controls::ScrollControl(parent)
    , _Pinned(false)
{
    Core::Instance()->GetSelection().selectionChanged.Connect(this, &PropertyPanel::OnSelectionChanged);
}

PropertyPanel::~PropertyPanel()
{

}

void PropertyPanel::SetPinned(bool pinned)
{
    _Pinned = pinned;
}

void PropertyPanel::SetStruct(Struct* item, const std::string& focusPath)
{
    RemoveAllChildren();

    if (item)
    {
        AddStruct(glm::vec2(0,0), item->GetType(), item, "/");
    }
}

glm::vec2 PropertyPanel::AddStruct(glm::vec2 offset, const SchemaStruct* schemaStruct, Struct* item, const std::string& path)
{
    for (SchemaStruct::PropertyMap::const_iterator it = schemaStruct->GetProperties().begin(); it != schemaStruct->GetProperties().end(); ++it)
    {
        std::string propertyPath = path + it->first + "/";

        Gwen::Controls::Label* label = new Gwen::Controls::Label(this);
        label->SetText(it->second->GetName());
        label->SetPos(offset.x, offset.y);

        offset += glm::vec2(0,20);

        switch (it->second->GetPropertyType())
        {
            case SchemaProperty::kSchemaPropertyAtom:
            {
                offset = AddAtom(offset, static_cast<SchemaPropertyAtom*>(it->second), item, propertyPath);
                break;
            }
            case SchemaProperty::kSchemaPropertyPointer:
                break;
            case SchemaProperty::kSchemaPropertyStruct:
            {
                SchemaPropertyStruct* schemaPropertyStruct = static_cast<SchemaPropertyStruct*>(it->second);

                offset = AddStruct(offset + glm::vec2(STRUCT_INDENT,0), schemaPropertyStruct->GetSchemaStruct(), item, propertyPath) - glm::vec2(STRUCT_INDENT,0);
                break;
            }
            case SchemaProperty::kSchemaPropertyArray:
                break;
        }
    }

    return offset;
}

glm::vec2 PropertyPanel::AddAtom(glm::vec2 offset, SchemaPropertyAtom* atom, Struct* item, const std::string& path)
{
    const Property* property = item->GetProperty(path);
    const PropertyAtom* propertyAtom = property ? property->AsAtom() : 0;

    Gwen::Controls::TextBox* textBox = new Gwen::Controls::TextBox(this);
    textBox->SetText(propertyAtom ? propertyAtom->GetStringValue() : "");
    textBox->SetPos(offset.x, offset.y);
    textBox->SetSize(ATOM_WIDTH, ATOM_HEIGHT);
    textBox->UserData.Set("struct", item);
    textBox->UserData.Set("path", path);
    textBox->onTextChanged.Add(this, &PropertyPanel::OnAtomChanged);

    return offset + glm::vec2(0, ATOM_HEIGHT + ATOM_PADDING);
}

void PropertyPanel::OnSelectionChanged(const pixeleditor::Selection* selection)
{
    if (!_Pinned)
    {
        Selection::Entities::const_reverse_iterator entityIt = selection->GetSelection().rbegin();

        if (entityIt == selection->GetSelection().rend())
        {
            SetStruct(View::Instance()->GetRecord());
            return;
        }

        Entity* entity = Core::Instance()->GetProject()->GetEntity(entityIt->first);

        SetStruct(entity, "");
    }
}

void PropertyPanel::OnAtomChanged(Gwen::Controls::Base* input)
{
    Struct* structItem = input->UserData.Get<Struct*>("struct");
    std::string path = input->UserData.Get<std::string>("path");

    PropertyAtom* atom = structItem->AcquireAtom(path);
    atom->SetStringValue(input->GetValue());
}
<commit_msg>Correctly reset property panel<commit_after>#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/TextBox.h"

#include "core/selection.h"
#include "project/entity.h"
#include "project/project.h"
#include "project/property.h"
#include "project/record.h"
#include "project/schema.h"
#include "view/ui/property/propertyPanel.h"
#include "core.h"
#include "view.h"

using namespace pixeleditor;

static const int ATOM_PADDING = 5;
static const int ATOM_WIDTH = 200;
static const int ATOM_HEIGHT = 25;
static const int STRUCT_INDENT = 20;

PropertyPanel::PropertyPanel(Gwen::Controls::Base* parent)
    : Gwen::Controls::ScrollControl(parent)
    , _Pinned(false)
{
    Core::Instance()->GetSelection().selectionChanged.Connect(this, &PropertyPanel::OnSelectionChanged);
}

PropertyPanel::~PropertyPanel()
{

}

void PropertyPanel::SetPinned(bool pinned)
{
    _Pinned = pinned;
}

void PropertyPanel::SetStruct(Struct* item, const std::string& focusPath)
{
    for (int i=0; i<NumChildren(); i++)
    {
        GetChild(i)->DelayedDelete();
    }

    if (item)
    {
        AddStruct(glm::vec2(0,0), item->GetType(), item, "/");
    }
}

glm::vec2 PropertyPanel::AddStruct(glm::vec2 offset, const SchemaStruct* schemaStruct, Struct* item, const std::string& path)
{
    for (SchemaStruct::PropertyMap::const_iterator it = schemaStruct->GetProperties().begin(); it != schemaStruct->GetProperties().end(); ++it)
    {
        std::string propertyPath = path + it->first + "/";

        Gwen::Controls::Label* label = new Gwen::Controls::Label(this);
        label->SetText(it->second->GetName());
        label->SetPos(offset.x, offset.y);

        offset += glm::vec2(0,20);

        switch (it->second->GetPropertyType())
        {
            case SchemaProperty::kSchemaPropertyAtom:
            {
                offset = AddAtom(offset, static_cast<SchemaPropertyAtom*>(it->second), item, propertyPath);
                break;
            }
            case SchemaProperty::kSchemaPropertyPointer:
                break;
            case SchemaProperty::kSchemaPropertyStruct:
            {
                SchemaPropertyStruct* schemaPropertyStruct = static_cast<SchemaPropertyStruct*>(it->second);

                offset = AddStruct(offset + glm::vec2(STRUCT_INDENT,0), schemaPropertyStruct->GetSchemaStruct(), item, propertyPath) - glm::vec2(STRUCT_INDENT,0);
                break;
            }
            case SchemaProperty::kSchemaPropertyArray:
                break;
        }
    }

    return offset;
}

glm::vec2 PropertyPanel::AddAtom(glm::vec2 offset, SchemaPropertyAtom* atom, Struct* item, const std::string& path)
{
    const Property* property = item->GetProperty(path);
    const PropertyAtom* propertyAtom = property ? property->AsAtom() : 0;

    Gwen::Controls::TextBox* textBox = new Gwen::Controls::TextBox(this);
    textBox->SetText(propertyAtom ? propertyAtom->GetStringValue() : "");
    textBox->SetPos(offset.x, offset.y);
    textBox->SetSize(ATOM_WIDTH, ATOM_HEIGHT);
    textBox->UserData.Set("struct", item);
    textBox->UserData.Set("path", path);
    textBox->onTextChanged.Add(this, &PropertyPanel::OnAtomChanged);

    return offset + glm::vec2(0, ATOM_HEIGHT + ATOM_PADDING);
}

void PropertyPanel::OnSelectionChanged(const pixeleditor::Selection* selection)
{
    if (!_Pinned)
    {
        Selection::Entities::const_reverse_iterator entityIt = selection->GetSelection().rbegin();

        if (entityIt == selection->GetSelection().rend())
        {
            SetStruct(View::Instance()->GetRecord());
            return;
        }

        Entity* entity = Core::Instance()->GetProject()->GetEntity(entityIt->first);

        SetStruct(entity, "");
    }
}

void PropertyPanel::OnAtomChanged(Gwen::Controls::Base* input)
{
    Struct* structItem = input->UserData.Get<Struct*>("struct");
    std::string path = input->UserData.Get<std::string>("path");

    PropertyAtom* atom = structItem->AcquireAtom(path);
    atom->SetStringValue(input->GetValue());
}
<|endoftext|>


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

// This is a file for random testcases that we run into that at one point or
// another have crashed the program.

#include "chrome/test/ui/ui_test.h"

#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/platform_thread.h"
#include "chrome/common/chrome_switches.h"

class GoogleTest : public UITest {
 protected:
  GoogleTest() : UITest() {
    FilePath test_file(test_data_directory_);
    test_file = test_file.AppendASCII("google");
    test_file = test_file.AppendASCII("google.html");
    homepage_ = test_file.ToWStringHack();
  }
};

TEST_F(GoogleTest, Crash) {
  std::wstring page_title = L"Google";

  // Make sure the navigation succeeded.
  EXPECT_EQ(page_title, GetActiveTabTitle());

  // UITest will check if this crashed.
}

class ColumnLayout : public UITest {
 protected:
  ColumnLayout() : UITest() {
    FilePath test_file(test_data_directory_);
    test_file = test_file.AppendASCII("columns.html");
    homepage_ = test_file.ToWStringHack();
  }
};

TEST_F(ColumnLayout, Crash) {
  std::wstring page_title = L"Column test";

  // Make sure the navigation succeeded.
  EXPECT_EQ(page_title, GetActiveTabTitle());

  // UITest will check if this crashed.
}

// By passing kTryChromeAgain with a magic value > 10000 we cause chrome
// to exit fairly early. This was the cause of crashes. See bug 34799.
class EarlyReturnTest : public UITest {
 public:
  EarlyReturnTest() {
    wait_for_initial_loads_ = false;
    // We don't depend on these timeouts, they are set to the minimum so
    // the automation server waits the minimun amount possible for the
    // handshake that will never come.
    set_command_execution_timeout_ms(1);
    set_action_timeout_ms(1);
    launch_arguments_.AppendSwitchWithValue(switches::kTryChromeAgain, "10001");
  }
};

// Flaky: http://crbug.com/45115
TEST_F(EarlyReturnTest, FLAKEY_ToastCrasher) {
  // UITest will check if this crashed.
}
<commit_msg>spelling error FLAKEY->FLAKY. EarlyReturnTest.ToastCrasher<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is a file for random testcases that we run into that at one point or
// another have crashed the program.

#include "chrome/test/ui/ui_test.h"

#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/platform_thread.h"
#include "chrome/common/chrome_switches.h"

class GoogleTest : public UITest {
 protected:
  GoogleTest() : UITest() {
    FilePath test_file(test_data_directory_);
    test_file = test_file.AppendASCII("google");
    test_file = test_file.AppendASCII("google.html");
    homepage_ = test_file.ToWStringHack();
  }
};

TEST_F(GoogleTest, Crash) {
  std::wstring page_title = L"Google";

  // Make sure the navigation succeeded.
  EXPECT_EQ(page_title, GetActiveTabTitle());

  // UITest will check if this crashed.
}

class ColumnLayout : public UITest {
 protected:
  ColumnLayout() : UITest() {
    FilePath test_file(test_data_directory_);
    test_file = test_file.AppendASCII("columns.html");
    homepage_ = test_file.ToWStringHack();
  }
};

TEST_F(ColumnLayout, Crash) {
  std::wstring page_title = L"Column test";

  // Make sure the navigation succeeded.
  EXPECT_EQ(page_title, GetActiveTabTitle());

  // UITest will check if this crashed.
}

// By passing kTryChromeAgain with a magic value > 10000 we cause chrome
// to exit fairly early. This was the cause of crashes. See bug 34799.
class EarlyReturnTest : public UITest {
 public:
  EarlyReturnTest() {
    wait_for_initial_loads_ = false;
    // We don't depend on these timeouts, they are set to the minimum so
    // the automation server waits the minimun amount possible for the
    // handshake that will never come.
    set_command_execution_timeout_ms(1);
    set_action_timeout_ms(1);
    launch_arguments_.AppendSwitchWithValue(switches::kTryChromeAgain, "10001");
  }
};

// Flaky: http://crbug.com/45115
TEST_F(EarlyReturnTest, FLAKY_ToastCrasher) {
  // UITest will check if this crashed.
}
<|endoftext|>


<commit_before>#pragma once

class Solution {
public:
  vector<int> twoSum(vector<int>& nums, int target) {

  }
};
<commit_msg>get headers ready for solution<commit_after>#pragma once

#include <vector>
#include <unordered_map>

using std::vector;
using std::unordered_map;

class Solution {
public:
  vector<int> twoSum(vector<int>& nums, int target) {

  }
};
<|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 "content/renderer/render_widget_fullscreen_pepper.h"

#include "base/message_loop.h"
#include "chrome/renderer/render_thread.h"
#include "content/renderer/renderer_gl_context.h"
#include "content/renderer/gpu_channel_host.h"
#include "content/renderer/pepper_platform_context_3d_impl.h"
#include "content/common/view_messages.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
#include "webkit/plugins/ppapi/plugin_delegate.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"

using WebKit::WebCanvas;
using WebKit::WebCompositionUnderline;
using WebKit::WebCursorInfo;
using WebKit::WebInputEvent;
using WebKit::WebRect;
using WebKit::WebSize;
using WebKit::WebString;
using WebKit::WebTextDirection;
using WebKit::WebTextInputType;
using WebKit::WebVector;
using WebKit::WebWidget;

namespace {

// WebWidget that simply wraps the pepper plugin.
class PepperWidget : public WebWidget {
 public:
  PepperWidget(webkit::ppapi::PluginInstance* plugin,
               RenderWidgetFullscreenPepper* widget)
      : plugin_(plugin),
        widget_(widget),
        cursor_(WebCursorInfo::TypePointer) {
  }

  // WebWidget API
  virtual void close() {
    delete this;
  }

  virtual WebSize size() {
    return size_;
  }

  virtual void resize(const WebSize& size) {
    size_ = size;
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    plugin_->ViewChanged(plugin_rect, plugin_rect);
    widget_->Invalidate();
  }

  virtual void animate() {
  }

  virtual void layout() {
  }

  virtual void paint(WebCanvas* canvas, const WebRect& rect) {
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    plugin_->Paint(canvas, plugin_rect, rect);
  }

  virtual void composite(bool finish) {
    RendererGLContext* context = widget_->context();
    DCHECK(context);
    gpu::gles2::GLES2Implementation* gl = context->GetImplementation();
    unsigned int texture = plugin_->GetBackingTextureId();
    gl->BindTexture(GL_TEXTURE_2D, texture);
    gl->DrawArrays(GL_TRIANGLES, 0, 3);
    context->SwapBuffers();
  }

  virtual void themeChanged() {
    NOTIMPLEMENTED();
  }

  virtual bool handleInputEvent(const WebInputEvent& event) {
    return plugin_->HandleInputEvent(event, &cursor_);
  }

  virtual void mouseCaptureLost() {
    NOTIMPLEMENTED();
  }

  virtual void setFocus(bool focus) {
    NOTIMPLEMENTED();
  }

  // TODO(piman): figure out IME and implement these if necessary.
  virtual bool setComposition(
      const WebString& text,
      const WebVector<WebCompositionUnderline>& underlines,
      int selectionStart,
      int selectionEnd) {
    return false;
  }

  virtual bool confirmComposition() {
    return false;
  }

  virtual bool confirmComposition(const WebString& text) {
    return false;
  }

  virtual WebTextInputType textInputType() {
    return WebKit::WebTextInputTypeNone;
  }

  virtual WebRect caretOrSelectionBounds() {
    return WebRect();
  }

  virtual void setTextDirection(WebTextDirection) {
  }

  virtual bool isAcceleratedCompositingActive() const {
    return widget_->context() && (plugin_->GetBackingTextureId() != 0);
  }

 private:
  scoped_refptr<webkit::ppapi::PluginInstance> plugin_;
  RenderWidgetFullscreenPepper* widget_;
  WebSize size_;
  WebCursorInfo cursor_;

  DISALLOW_COPY_AND_ASSIGN(PepperWidget);
};

void DestroyContext(RendererGLContext* context, GLuint program, GLuint buffer) {
  DCHECK(context);
  gpu::gles2::GLES2Implementation* gl = context->GetImplementation();
  if (program)
    gl->DeleteProgram(program);
  if (buffer)
    gl->DeleteBuffers(1, &buffer);
  delete context;
}

}  // anonymous namespace

// static
RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
    int32 opener_id, RenderThreadBase* render_thread,
    webkit::ppapi::PluginInstance* plugin,
    const GURL& active_url) {
  DCHECK_NE(MSG_ROUTING_NONE, opener_id);
  scoped_refptr<RenderWidgetFullscreenPepper> widget(
      new RenderWidgetFullscreenPepper(render_thread, plugin, active_url));
  widget->Init(opener_id);
  return widget.release();
}

RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
    RenderThreadBase* render_thread,
    webkit::ppapi::PluginInstance* plugin,
    const GURL& active_url)
    : RenderWidgetFullscreen(render_thread),
      active_url_(active_url),
      plugin_(plugin),
      context_(NULL),
      buffer_(0),
      program_(0) {
}

RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
  if (context_)
    DestroyContext(context_, program_, buffer_);
}

void RenderWidgetFullscreenPepper::Invalidate() {
  InvalidateRect(gfx::Rect(size_.width(), size_.height()));
}

void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) {
  if (CheckCompositing()) {
    scheduleComposite();
  } else {
    didInvalidateRect(rect);
  }
}

void RenderWidgetFullscreenPepper::ScrollRect(
    int dx, int dy, const WebKit::WebRect& rect) {
  if (CheckCompositing()) {
    scheduleComposite();
  } else {
    didScrollRect(dx, dy, rect);
  }
}

void RenderWidgetFullscreenPepper::Destroy() {
  // This function is called by the plugin instance as it's going away, so reset
  // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close().
  plugin_ = NULL;
  Send(new ViewHostMsg_Close(routing_id_));
}

webkit::ppapi::PluginDelegate::PlatformContext3D*
RenderWidgetFullscreenPepper::CreateContext3D() {
  if (!context_) {
    CreateContext();
  }
  if (!context_)
    return NULL;
  return new PlatformContext3DImpl(context_);
}

void RenderWidgetFullscreenPepper::DidInitiatePaint() {
  if (plugin_)
    plugin_->ViewInitiatedPaint();
}

void RenderWidgetFullscreenPepper::DidFlushPaint() {
  if (plugin_)
    plugin_->ViewFlushedPaint();
}

void RenderWidgetFullscreenPepper::Close() {
  // If the fullscreen window is closed (e.g. user pressed escape), reset to
  // normal mode.
  if (plugin_)
    plugin_->SetFullscreen(false, false);
}

webkit::ppapi::PluginInstance*
RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint(
    const gfx::Rect& paint_bounds,
    TransportDIB** dib,
    gfx::Rect* location,
    gfx::Rect* clip) {
  if (plugin_ &&
      plugin_->GetBitmapForOptimizedPluginPaint(paint_bounds, dib,
                                                location, clip))
    return plugin_;
  return NULL;
}

void RenderWidgetFullscreenPepper::OnResize(const gfx::Size& size,
                                            const gfx::Rect& resizer_rect) {
  if (context_) {
    gpu::gles2::GLES2Implementation* gl = context_->GetImplementation();
#if defined(OS_MACOSX)
    context_->ResizeOnscreen(size);
#else
    gl->ResizeCHROMIUM(size.width(), size.height());
#endif
    gl->Viewport(0, 0, size.width(), size.height());
  }
  RenderWidget::OnResize(size, resizer_rect);
}

WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
  return new PepperWidget(plugin_, this);
}

void RenderWidgetFullscreenPepper::CreateContext() {
  DCHECK(!context_);
  RenderThread* render_thread = RenderThread::current();
  DCHECK(render_thread);
  GpuChannelHost* host = render_thread->EstablishGpuChannelSync(
    content::CAUSE_FOR_GPU_LAUNCH_RENDERWIDGETFULLSCREENPEPPER_CREATECONTEXT);
  if (!host)
    return;
  const int32 attribs[] = {
    RendererGLContext::ALPHA_SIZE, 8,
    RendererGLContext::DEPTH_SIZE, 0,
    RendererGLContext::STENCIL_SIZE, 0,
    RendererGLContext::SAMPLES, 0,
    RendererGLContext::SAMPLE_BUFFERS, 0,
    RendererGLContext::NONE,
  };
  context_ = RendererGLContext::CreateViewContext(
      host,
      routing_id(),
      "GL_OES_packed_depth_stencil GL_OES_depth24",
      attribs,
      active_url_);
  if (!context_)
    return;

  if (!InitContext()) {
    DestroyContext(context_, program_, buffer_);
    context_ = NULL;
    return;
  }
  context_->SetSwapBuffersCallback(
      NewCallback(this, &RenderWidgetFullscreenPepper::DidFlushPaint));
  context_->SetContextLostCallback(
      NewCallback(this, &RenderWidgetFullscreenPepper::OnLostContext));
}

namespace {

const char kVertexShader[] =
    "attribute vec2 in_tex_coord;\n"
    "varying vec2 tex_coord;\n"
    "void main() {\n"
    "  gl_Position = vec4(in_tex_coord.x * 2. - 1.,\n"
    "                     in_tex_coord.y * 2. - 1.,\n"
    "                     0.,\n"
    "                     1.);\n"
    "  tex_coord = vec2(in_tex_coord.x, in_tex_coord.y);\n"
    "}\n";

const char kFragmentShader[] =
    "precision mediump float;\n"
    "varying vec2 tex_coord;\n"
    "uniform sampler2D in_texture;\n"
    "void main() {\n"
    "  gl_FragColor = texture2D(in_texture, tex_coord);\n"
    "}\n";

GLuint CreateShaderFromSource(gpu::gles2::GLES2Implementation* gl,
                              GLenum type,
                              const char* source) {
    GLuint shader = gl->CreateShader(type);
    gl->ShaderSource(shader, 1, &source, NULL);
    gl->CompileShader(shader);
    int status;
    gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (!status) {
        int size = 0;
        gl->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
        scoped_array<char> log(new char[size]);
        gl->GetShaderInfoLog(shader, size, NULL, log.get());
        DLOG(ERROR) << "Compilation failed: " << log.get();
        gl->DeleteShader(shader);
        shader = 0;
    }
    return shader;
}

const float kTexCoords[] = {
    0.f, 0.f,
    0.f, 2.f,
    2.f, 0.f,
};

}  // anonymous namespace

bool RenderWidgetFullscreenPepper::InitContext() {
  gpu::gles2::GLES2Implementation* gl = context_->GetImplementation();
  program_ = gl->CreateProgram();

  GLuint vertex_shader =
      CreateShaderFromSource(gl, GL_VERTEX_SHADER, kVertexShader);
  if (!vertex_shader)
    return false;
  gl->AttachShader(program_, vertex_shader);
  gl->DeleteShader(vertex_shader);

  GLuint fragment_shader =
      CreateShaderFromSource(gl, GL_FRAGMENT_SHADER, kFragmentShader);
  if (!fragment_shader)
    return false;
  gl->AttachShader(program_, fragment_shader);
  gl->DeleteShader(fragment_shader);

  gl->BindAttribLocation(program_, 0, "in_tex_coord");
  gl->LinkProgram(program_);
  int status;
  gl->GetProgramiv(program_, GL_LINK_STATUS, &status);
  if (!status) {
    int size = 0;
    gl->GetProgramiv(program_, GL_INFO_LOG_LENGTH, &size);
    scoped_array<char> log(new char[size]);
    gl->GetProgramInfoLog(program_, size, NULL, log.get());
    DLOG(ERROR) << "Link failed: " << log.get();
    return false;
  }
  gl->UseProgram(program_);
  int texture_location = gl->GetUniformLocation(program_, "in_texture");
  gl->Uniform1i(texture_location, 0);

  gl->GenBuffers(1, &buffer_);
  gl->BindBuffer(GL_ARRAY_BUFFER, buffer_);
  gl->BufferData(GL_ARRAY_BUFFER,
                 sizeof(kTexCoords),
                 kTexCoords,
                 GL_STATIC_DRAW);
  gl->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  gl->EnableVertexAttribArray(0);
  return true;
}

bool RenderWidgetFullscreenPepper::CheckCompositing() {
  bool compositing = webwidget_->isAcceleratedCompositingActive();
  if (compositing != is_accelerated_compositing_active_) {
    didActivateAcceleratedCompositing(compositing);
  }
  return compositing;
}

void RenderWidgetFullscreenPepper::OnLostContext() {
  if (!context_)
    return;
  // Destroy the context later, in case we got called from InitContext for
  // example. We still need to reset context_ now so that a new context gets
  // created when the plugin recreates its own.
  MessageLoop::current()->PostTask(
      FROM_HERE,
      NewRunnableFunction(DestroyContext, context_, program_, buffer_));
  context_ = NULL;
  program_ = 0;
  buffer_ = 0;
}
<commit_msg>PepperWidget needs implementation of new method added in WebWidget.<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 "content/renderer/render_widget_fullscreen_pepper.h"

#include "base/message_loop.h"
#include "chrome/renderer/render_thread.h"
#include "content/renderer/renderer_gl_context.h"
#include "content/renderer/gpu_channel_host.h"
#include "content/renderer/pepper_platform_context_3d_impl.h"
#include "content/common/view_messages.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
#include "webkit/plugins/ppapi/plugin_delegate.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"

using WebKit::WebCanvas;
using WebKit::WebCompositionUnderline;
using WebKit::WebCursorInfo;
using WebKit::WebInputEvent;
using WebKit::WebPoint;
using WebKit::WebRect;
using WebKit::WebSize;
using WebKit::WebString;
using WebKit::WebTextDirection;
using WebKit::WebTextInputType;
using WebKit::WebVector;
using WebKit::WebWidget;

namespace {

// WebWidget that simply wraps the pepper plugin.
class PepperWidget : public WebWidget {
 public:
  PepperWidget(webkit::ppapi::PluginInstance* plugin,
               RenderWidgetFullscreenPepper* widget)
      : plugin_(plugin),
        widget_(widget),
        cursor_(WebCursorInfo::TypePointer) {
  }

  // WebWidget API
  virtual void close() {
    delete this;
  }

  virtual WebSize size() {
    return size_;
  }

  virtual void resize(const WebSize& size) {
    size_ = size;
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    plugin_->ViewChanged(plugin_rect, plugin_rect);
    widget_->Invalidate();
  }

  virtual void animate() {
  }

  virtual void layout() {
  }

  virtual void paint(WebCanvas* canvas, const WebRect& rect) {
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    plugin_->Paint(canvas, plugin_rect, rect);
  }

  virtual void composite(bool finish) {
    RendererGLContext* context = widget_->context();
    DCHECK(context);
    gpu::gles2::GLES2Implementation* gl = context->GetImplementation();
    unsigned int texture = plugin_->GetBackingTextureId();
    gl->BindTexture(GL_TEXTURE_2D, texture);
    gl->DrawArrays(GL_TRIANGLES, 0, 3);
    context->SwapBuffers();
  }

  virtual void themeChanged() {
    NOTIMPLEMENTED();
  }

  virtual bool handleInputEvent(const WebInputEvent& event) {
    return plugin_->HandleInputEvent(event, &cursor_);
  }

  virtual void mouseCaptureLost() {
    NOTIMPLEMENTED();
  }

  virtual void setFocus(bool focus) {
    NOTIMPLEMENTED();
  }

  // TODO(piman): figure out IME and implement these if necessary.
  virtual bool setComposition(
      const WebString& text,
      const WebVector<WebCompositionUnderline>& underlines,
      int selectionStart,
      int selectionEnd) {
    return false;
  }

  virtual bool confirmComposition() {
    return false;
  }

  virtual bool confirmComposition(const WebString& text) {
    return false;
  }

  virtual WebTextInputType textInputType() {
    return WebKit::WebTextInputTypeNone;
  }

  virtual WebRect caretOrSelectionBounds() {
    return WebRect();
  }

  virtual bool selectionRange(WebPoint& start, WebPoint& end) const {
    return false;
  }

  virtual void setTextDirection(WebTextDirection) {
  }

  virtual bool isAcceleratedCompositingActive() const {
    return widget_->context() && (plugin_->GetBackingTextureId() != 0);
  }

 private:
  scoped_refptr<webkit::ppapi::PluginInstance> plugin_;
  RenderWidgetFullscreenPepper* widget_;
  WebSize size_;
  WebCursorInfo cursor_;

  DISALLOW_COPY_AND_ASSIGN(PepperWidget);
};

void DestroyContext(RendererGLContext* context, GLuint program, GLuint buffer) {
  DCHECK(context);
  gpu::gles2::GLES2Implementation* gl = context->GetImplementation();
  if (program)
    gl->DeleteProgram(program);
  if (buffer)
    gl->DeleteBuffers(1, &buffer);
  delete context;
}

}  // anonymous namespace

// static
RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
    int32 opener_id, RenderThreadBase* render_thread,
    webkit::ppapi::PluginInstance* plugin,
    const GURL& active_url) {
  DCHECK_NE(MSG_ROUTING_NONE, opener_id);
  scoped_refptr<RenderWidgetFullscreenPepper> widget(
      new RenderWidgetFullscreenPepper(render_thread, plugin, active_url));
  widget->Init(opener_id);
  return widget.release();
}

RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
    RenderThreadBase* render_thread,
    webkit::ppapi::PluginInstance* plugin,
    const GURL& active_url)
    : RenderWidgetFullscreen(render_thread),
      active_url_(active_url),
      plugin_(plugin),
      context_(NULL),
      buffer_(0),
      program_(0) {
}

RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
  if (context_)
    DestroyContext(context_, program_, buffer_);
}

void RenderWidgetFullscreenPepper::Invalidate() {
  InvalidateRect(gfx::Rect(size_.width(), size_.height()));
}

void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) {
  if (CheckCompositing()) {
    scheduleComposite();
  } else {
    didInvalidateRect(rect);
  }
}

void RenderWidgetFullscreenPepper::ScrollRect(
    int dx, int dy, const WebKit::WebRect& rect) {
  if (CheckCompositing()) {
    scheduleComposite();
  } else {
    didScrollRect(dx, dy, rect);
  }
}

void RenderWidgetFullscreenPepper::Destroy() {
  // This function is called by the plugin instance as it's going away, so reset
  // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close().
  plugin_ = NULL;
  Send(new ViewHostMsg_Close(routing_id_));
}

webkit::ppapi::PluginDelegate::PlatformContext3D*
RenderWidgetFullscreenPepper::CreateContext3D() {
  if (!context_) {
    CreateContext();
  }
  if (!context_)
    return NULL;
  return new PlatformContext3DImpl(context_);
}

void RenderWidgetFullscreenPepper::DidInitiatePaint() {
  if (plugin_)
    plugin_->ViewInitiatedPaint();
}

void RenderWidgetFullscreenPepper::DidFlushPaint() {
  if (plugin_)
    plugin_->ViewFlushedPaint();
}

void RenderWidgetFullscreenPepper::Close() {
  // If the fullscreen window is closed (e.g. user pressed escape), reset to
  // normal mode.
  if (plugin_)
    plugin_->SetFullscreen(false, false);
}

webkit::ppapi::PluginInstance*
RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint(
    const gfx::Rect& paint_bounds,
    TransportDIB** dib,
    gfx::Rect* location,
    gfx::Rect* clip) {
  if (plugin_ &&
      plugin_->GetBitmapForOptimizedPluginPaint(paint_bounds, dib,
                                                location, clip))
    return plugin_;
  return NULL;
}

void RenderWidgetFullscreenPepper::OnResize(const gfx::Size& size,
                                            const gfx::Rect& resizer_rect) {
  if (context_) {
    gpu::gles2::GLES2Implementation* gl = context_->GetImplementation();
#if defined(OS_MACOSX)
    context_->ResizeOnscreen(size);
#else
    gl->ResizeCHROMIUM(size.width(), size.height());
#endif
    gl->Viewport(0, 0, size.width(), size.height());
  }
  RenderWidget::OnResize(size, resizer_rect);
}

WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
  return new PepperWidget(plugin_, this);
}

void RenderWidgetFullscreenPepper::CreateContext() {
  DCHECK(!context_);
  RenderThread* render_thread = RenderThread::current();
  DCHECK(render_thread);
  GpuChannelHost* host = render_thread->EstablishGpuChannelSync(
    content::CAUSE_FOR_GPU_LAUNCH_RENDERWIDGETFULLSCREENPEPPER_CREATECONTEXT);
  if (!host)
    return;
  const int32 attribs[] = {
    RendererGLContext::ALPHA_SIZE, 8,
    RendererGLContext::DEPTH_SIZE, 0,
    RendererGLContext::STENCIL_SIZE, 0,
    RendererGLContext::SAMPLES, 0,
    RendererGLContext::SAMPLE_BUFFERS, 0,
    RendererGLContext::NONE,
  };
  context_ = RendererGLContext::CreateViewContext(
      host,
      routing_id(),
      "GL_OES_packed_depth_stencil GL_OES_depth24",
      attribs,
      active_url_);
  if (!context_)
    return;

  if (!InitContext()) {
    DestroyContext(context_, program_, buffer_);
    context_ = NULL;
    return;
  }
  context_->SetSwapBuffersCallback(
      NewCallback(this, &RenderWidgetFullscreenPepper::DidFlushPaint));
  context_->SetContextLostCallback(
      NewCallback(this, &RenderWidgetFullscreenPepper::OnLostContext));
}

namespace {

const char kVertexShader[] =
    "attribute vec2 in_tex_coord;\n"
    "varying vec2 tex_coord;\n"
    "void main() {\n"
    "  gl_Position = vec4(in_tex_coord.x * 2. - 1.,\n"
    "                     in_tex_coord.y * 2. - 1.,\n"
    "                     0.,\n"
    "                     1.);\n"
    "  tex_coord = vec2(in_tex_coord.x, in_tex_coord.y);\n"
    "}\n";

const char kFragmentShader[] =
    "precision mediump float;\n"
    "varying vec2 tex_coord;\n"
    "uniform sampler2D in_texture;\n"
    "void main() {\n"
    "  gl_FragColor = texture2D(in_texture, tex_coord);\n"
    "}\n";

GLuint CreateShaderFromSource(gpu::gles2::GLES2Implementation* gl,
                              GLenum type,
                              const char* source) {
    GLuint shader = gl->CreateShader(type);
    gl->ShaderSource(shader, 1, &source, NULL);
    gl->CompileShader(shader);
    int status;
    gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (!status) {
        int size = 0;
        gl->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
        scoped_array<char> log(new char[size]);
        gl->GetShaderInfoLog(shader, size, NULL, log.get());
        DLOG(ERROR) << "Compilation failed: " << log.get();
        gl->DeleteShader(shader);
        shader = 0;
    }
    return shader;
}

const float kTexCoords[] = {
    0.f, 0.f,
    0.f, 2.f,
    2.f, 0.f,
};

}  // anonymous namespace

bool RenderWidgetFullscreenPepper::InitContext() {
  gpu::gles2::GLES2Implementation* gl = context_->GetImplementation();
  program_ = gl->CreateProgram();

  GLuint vertex_shader =
      CreateShaderFromSource(gl, GL_VERTEX_SHADER, kVertexShader);
  if (!vertex_shader)
    return false;
  gl->AttachShader(program_, vertex_shader);
  gl->DeleteShader(vertex_shader);

  GLuint fragment_shader =
      CreateShaderFromSource(gl, GL_FRAGMENT_SHADER, kFragmentShader);
  if (!fragment_shader)
    return false;
  gl->AttachShader(program_, fragment_shader);
  gl->DeleteShader(fragment_shader);

  gl->BindAttribLocation(program_, 0, "in_tex_coord");
  gl->LinkProgram(program_);
  int status;
  gl->GetProgramiv(program_, GL_LINK_STATUS, &status);
  if (!status) {
    int size = 0;
    gl->GetProgramiv(program_, GL_INFO_LOG_LENGTH, &size);
    scoped_array<char> log(new char[size]);
    gl->GetProgramInfoLog(program_, size, NULL, log.get());
    DLOG(ERROR) << "Link failed: " << log.get();
    return false;
  }
  gl->UseProgram(program_);
  int texture_location = gl->GetUniformLocation(program_, "in_texture");
  gl->Uniform1i(texture_location, 0);

  gl->GenBuffers(1, &buffer_);
  gl->BindBuffer(GL_ARRAY_BUFFER, buffer_);
  gl->BufferData(GL_ARRAY_BUFFER,
                 sizeof(kTexCoords),
                 kTexCoords,
                 GL_STATIC_DRAW);
  gl->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  gl->EnableVertexAttribArray(0);
  return true;
}

bool RenderWidgetFullscreenPepper::CheckCompositing() {
  bool compositing = webwidget_->isAcceleratedCompositingActive();
  if (compositing != is_accelerated_compositing_active_) {
    didActivateAcceleratedCompositing(compositing);
  }
  return compositing;
}

void RenderWidgetFullscreenPepper::OnLostContext() {
  if (!context_)
    return;
  // Destroy the context later, in case we got called from InitContext for
  // example. We still need to reset context_ now so that a new context gets
  // created when the plugin recreates its own.
  MessageLoop::current()->PostTask(
      FROM_HERE,
      NewRunnableFunction(DestroyContext, context_, program_, buffer_));
  context_ = NULL;
  program_ = 0;
  buffer_ = 0;
}
<|endoftext|>


<commit_before>
/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Test.h"
#include "SkRandom.h"
#include "SkTSort.h"

bool anderson_darling_test(double p[32]) {
    // Min and max Anderson-Darling values allowable for k=32
    const double kADMin32 = 0.202;        // p-value of ~0.1
    const double kADMax32 = 3.89;         // p-value of ~0.99

    // sort p values
    SkTQSort<double>(p, p + 31);

    // and compute Anderson-Darling statistic to ensure these are uniform
    double s = 0.0;
    for(int k = 0; k < 32; k++) {
        double v = p[k]*(1.0 - p[31-k]);
        if (v < 1.0e-30) {
           v = 1.0e-30;
        }
        s += (2.0*(k+1)-1.0)*log(v);
    }
    double a2 = -32.0 - 0.03125*s;

    return (kADMin32 < a2 && a2 < kADMax32);
}

bool chi_square_test(int bins[256], int e) {
    // Min and max chisquare values allowable
    const double kChiSqMin256 = 206.3179;        // probability of chance = 0.99 with k=256
    const double kChiSqMax256 = 311.5603;        // probability of chance = 0.01 with k=256

    // compute chi-square
    double chi2 = 0.0;
    for (int j = 0; j < 256; ++j) {
        double delta = bins[j] - e;
        chi2 += delta*delta/e;
    }

    return (kChiSqMin256 < chi2 && chi2 < kChiSqMax256);
}

// Approximation to the normal distribution CDF
// From Waissi and Rossin, 1996
double normal_cdf(double z) {
    double t = ((-0.0004406*z*z* + 0.0418198)*z*z + 0.9)*z;
    t *= -1.77245385091;  // -sqrt(PI)
    double p = 1.0/(1.0 + exp(t));

    return p;
}

void test_random_byte(skiatest::Reporter* reporter, int shift) {
    int bins[256];
    memset(bins, 0, sizeof(int)*256);

    SkMWCRandom rand;
    for (int i = 0; i < 256*10000; ++i) {
        bins[(rand.nextU() >> shift) & 0xff]++;
    }

    REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));
}

void test_random_float(skiatest::Reporter* reporter) {
    int bins[256];
    memset(bins, 0, sizeof(int)*256);

    SkMWCRandom rand;
    for (int i = 0; i < 256*10000; ++i) {
        float f = rand.nextF();
        REPORTER_ASSERT(reporter, 0.0f <= f && f < 1.0f);
        bins[(int)(f*256.f)]++;
    }
    REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));

    double p[32];
    for (int j = 0; j < 32; ++j) {
        float f = rand.nextF();
        REPORTER_ASSERT(reporter, 0.0f <= f && f < 1.0f);
        p[j] = f;
    }
    REPORTER_ASSERT(reporter, anderson_darling_test(p));
}

// This is a test taken from tuftests by Marsaglia and Tsang. The idea here is that
// we are using the random bit generated from a single shift position to generate
// "strings" of 16 bits in length, shifting the string and adding a new bit with each
// iteration. We track the numbers generated. The ones that we don't generate will
// have a normal distribution with mean ~24108 and standard deviation ~127. By
// creating a z-score (# of deviations from the mean) for one iteration of this step
// we can determine its probability.
//
// The original test used 26 bit strings, but is somewhat slow. This version uses 16
// bits which is less rigorous but much faster to generate.
double test_single_gorilla(skiatest::Reporter* reporter, int shift) {
    const int kWordWidth = 16;
    const double kMean = 24108.0;
    const double kStandardDeviation = 127.0;
    const int kN = (1 << kWordWidth);
    const int kNumEntries = kN >> 5;  // dividing by 32
    unsigned int entries[kNumEntries];

    SkMWCRandom rand;
    memset(entries, 0, sizeof(unsigned int)*kNumEntries);
    // pre-seed our string value
    int value = 0;
    for (int i = 0; i < kWordWidth-1; ++i) {
        value <<= 1;
        unsigned int rnd = rand.nextU();
        value |= ((rnd >> shift) & 0x1);
    }

    // now make some strings and track them
    for (int i = 0; i < kN; ++i) {
        value <<= 1;
        unsigned int rnd = rand.nextU();
        value |= ((rnd >> shift) & 0x1);

        int index = value & (kNumEntries-1);
        SkASSERT(index < kNumEntries);
        int entry_shift = (value >> (kWordWidth-5)) & 0x3f;
        entries[index] |= (0x1 << entry_shift);
    }

    // count entries
    int total = 0;
    for (int i = 0; i < kNumEntries; ++i) {
        unsigned int entry = entries[i];
        while (entry) {
            total += (entry & 0x1);
            entry >>= 1;
        }
    }

    // convert counts to normal distribution z-score
    double z = ((kN-total)-kMean)/kStandardDeviation;

    // compute probability from normal distibution CDF
    double p = normal_cdf(z);

    REPORTER_ASSERT(reporter, 0.01 < p && p < 0.99);
    return p;
}

void test_gorilla(skiatest::Reporter* reporter) {

    double p[32];
    for (int bit_position = 0; bit_position < 32; ++bit_position) {
        p[bit_position] = test_single_gorilla(reporter, bit_position);
    }

    REPORTER_ASSERT(reporter, anderson_darling_test(p));
}

void test_range(skiatest::Reporter* reporter) {
    SkMWCRandom rand;

    // just to make sure we don't crash in this case
    (void) rand.nextRangeU(0, 0xffffffff);

    // check a case to see if it's uniform
    int bins[256];
    memset(bins, 0, sizeof(int)*256);
    for (int i = 0; i < 256*10000; ++i) {
        unsigned int u = rand.nextRangeU(17, 17+255);
        REPORTER_ASSERT(reporter, 17 <= u && u <= 17+255);
        bins[u - 17]++;
    }

    REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));
}

static void TestRandom(skiatest::Reporter* reporter) {
    // check uniform distributions of each byte in 32-bit word
    test_random_byte(reporter, 0);
    test_random_byte(reporter, 8);
    test_random_byte(reporter, 16);
    test_random_byte(reporter, 24);

    test_random_float(reporter);

    test_gorilla(reporter);

    test_range(reporter);
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("Random", RandomTestClass, TestRandom)
<commit_msg>Fix for Mac compile warnings. Temporarily removed random gorilla test.<commit_after>
/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Test.h"
#include "SkRandom.h"
#include "SkTSort.h"

static bool anderson_darling_test(double p[32]) {
    // Min and max Anderson-Darling values allowable for k=32
    const double kADMin32 = 0.202;        // p-value of ~0.1
    const double kADMax32 = 3.89;         // p-value of ~0.99

    // sort p values
    SkTQSort<double>(p, p + 31);

    // and compute Anderson-Darling statistic to ensure these are uniform
    double s = 0.0;
    for(int k = 0; k < 32; k++) {
        double v = p[k]*(1.0 - p[31-k]);
        if (v < 1.0e-30) {
           v = 1.0e-30;
        }
        s += (2.0*(k+1)-1.0)*log(v);
    }
    double a2 = -32.0 - 0.03125*s;

    return (kADMin32 < a2 && a2 < kADMax32);
}

static bool chi_square_test(int bins[256], int e) {
    // Min and max chisquare values allowable
    const double kChiSqMin256 = 206.3179;        // probability of chance = 0.99 with k=256
    const double kChiSqMax256 = 311.5603;        // probability of chance = 0.01 with k=256

    // compute chi-square
    double chi2 = 0.0;
    for (int j = 0; j < 256; ++j) {
        double delta = bins[j] - e;
        chi2 += delta*delta/e;
    }

    return (kChiSqMin256 < chi2 && chi2 < kChiSqMax256);
}

// Approximation to the normal distribution CDF
// From Waissi and Rossin, 1996
static double normal_cdf(double z) {
    double t = ((-0.0004406*z*z* + 0.0418198)*z*z + 0.9)*z;
    t *= -1.77245385091;  // -sqrt(PI)
    double p = 1.0/(1.0 + exp(t));

    return p;
}

static void test_random_byte(skiatest::Reporter* reporter, int shift) {
    int bins[256];
    memset(bins, 0, sizeof(int)*256);

    SkMWCRandom rand;
    for (int i = 0; i < 256*10000; ++i) {
        bins[(rand.nextU() >> shift) & 0xff]++;
    }

    REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));
}

static void test_random_float(skiatest::Reporter* reporter) {
    int bins[256];
    memset(bins, 0, sizeof(int)*256);

    SkMWCRandom rand;
    for (int i = 0; i < 256*10000; ++i) {
        float f = rand.nextF();
        REPORTER_ASSERT(reporter, 0.0f <= f && f < 1.0f);
        bins[(int)(f*256.f)]++;
    }
    REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));

    double p[32];
    for (int j = 0; j < 32; ++j) {
        float f = rand.nextF();
        REPORTER_ASSERT(reporter, 0.0f <= f && f < 1.0f);
        p[j] = f;
    }
    REPORTER_ASSERT(reporter, anderson_darling_test(p));
}

// This is a test taken from tuftests by Marsaglia and Tsang. The idea here is that
// we are using the random bit generated from a single shift position to generate
// "strings" of 16 bits in length, shifting the string and adding a new bit with each
// iteration. We track the numbers generated. The ones that we don't generate will
// have a normal distribution with mean ~24108 and standard deviation ~127. By
// creating a z-score (# of deviations from the mean) for one iteration of this step
// we can determine its probability.
//
// The original test used 26 bit strings, but is somewhat slow. This version uses 16
// bits which is less rigorous but much faster to generate.
static double test_single_gorilla(skiatest::Reporter* reporter, int shift) {
    const int kWordWidth = 16;
    const double kMean = 24108.0;
    const double kStandardDeviation = 127.0;
    const int kN = (1 << kWordWidth);
    const int kNumEntries = kN >> 5;  // dividing by 32
    unsigned int entries[kNumEntries];

    SkMWCRandom rand;
    memset(entries, 0, sizeof(unsigned int)*kNumEntries);
    // pre-seed our string value
    int value = 0;
    for (int i = 0; i < kWordWidth-1; ++i) {
        value <<= 1;
        unsigned int rnd = rand.nextU();
        value |= ((rnd >> shift) & 0x1);
    }

    // now make some strings and track them
    for (int i = 0; i < kN; ++i) {
        value <<= 1;
        unsigned int rnd = rand.nextU();
        value |= ((rnd >> shift) & 0x1);

        int index = value & (kNumEntries-1);
        SkASSERT(index < kNumEntries);
        int entry_shift = (value >> (kWordWidth-5)) & 0x3f;
        entries[index] |= (0x1 << entry_shift);
    }

    // count entries
    int total = 0;
    for (int i = 0; i < kNumEntries; ++i) {
        unsigned int entry = entries[i];
        while (entry) {
            total += (entry & 0x1);
            entry >>= 1;
        }
    }

    // convert counts to normal distribution z-score
    double z = ((kN-total)-kMean)/kStandardDeviation;

    // compute probability from normal distibution CDF
    double p = normal_cdf(z);

    REPORTER_ASSERT(reporter, 0.01 < p && p < 0.99);
    return p;
}

static void test_gorilla(skiatest::Reporter* reporter) {

    double p[32];
    for (int bit_position = 0; bit_position < 32; ++bit_position) {
        p[bit_position] = test_single_gorilla(reporter, bit_position);
    }

    REPORTER_ASSERT(reporter, anderson_darling_test(p));
}

static void test_range(skiatest::Reporter* reporter) {
    SkMWCRandom rand;

    // just to make sure we don't crash in this case
    (void) rand.nextRangeU(0, 0xffffffff);

    // check a case to see if it's uniform
    int bins[256];
    memset(bins, 0, sizeof(int)*256);
    for (int i = 0; i < 256*10000; ++i) {
        unsigned int u = rand.nextRangeU(17, 17+255);
        REPORTER_ASSERT(reporter, 17 <= u && u <= 17+255);
        bins[u - 17]++;
    }

    REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));
}

static void TestRandom(skiatest::Reporter* reporter) {
    // check uniform distributions of each byte in 32-bit word
    test_random_byte(reporter, 0);
    test_random_byte(reporter, 8);
    test_random_byte(reporter, 16);
    test_random_byte(reporter, 24);

    test_random_float(reporter);

//    test_gorilla(reporter);

    test_range(reporter);
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("Random", RandomTestClass, TestRandom)
<|endoftext|>