<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/ui/webui/sync_promo/sync_promo_ui.h"

#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/strings/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/webui/options/core_options_handler.h"
#include "chrome/browser/ui/webui/sync_promo/sync_promo_handler.h"
#include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
#include "chrome/browser/ui/webui/theme_source.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/net/url_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "google_apis/gaia/gaia_urls.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/escape.h"
#include "net/base/network_change_notifier.h"
#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"

using content::WebContents;

namespace {

const char kStringsJsFile[] = "strings.js";
const char kSyncPromoJsFile[] = "sync_promo.js";

const char kSyncPromoQueryKeyAutoClose[] = "auto_close";
const char kSyncPromoQueryKeyContinue[] = "continue";
const char kSyncPromoQueryKeyNextPage[] = "next_page";
const char kSyncPromoQueryKeySource[] = "source";

// Gaia cannot support about:blank as a continue URL, so using a hosted blank
// page instead.
const char kContinueUrl[] =
    "https://www.google.com/intl/%s/chrome/blank.html?%s=%d";

// The maximum number of times we want to show the sync promo at startup.
const int kSyncPromoShowAtStartupMaximum = 10;

// Forces the web based signin flow when set.
bool g_force_web_based_signin_flow = false;

// Checks we want to show the sync promo for the given brand.
bool AllowPromoAtStartupForCurrentBrand() {
  std::string brand;
  google_util::GetBrand(&brand);

  if (brand.empty())
    return true;

  if (google_util::IsInternetCafeBrandCode(brand))
    return false;

  // Enable for both organic and distribution.
  return true;
}

content::WebUIDataSource* CreateSyncUIHTMLSource(content::WebUI* web_ui) {
  content::WebUIDataSource* html_source =
      content::WebUIDataSource::Create(chrome::kChromeUISyncPromoHost);
  DictionaryValue localized_strings;
  options::CoreOptionsHandler::GetStaticLocalizedValues(&localized_strings);
  SyncSetupHandler::GetStaticLocalizedValues(&localized_strings, web_ui);
  html_source->AddLocalizedStrings(localized_strings);
  html_source->SetJsonPath(kStringsJsFile);
  html_source->AddResourcePath(kSyncPromoJsFile, IDR_SYNC_PROMO_JS);
  html_source->SetDefaultResource(IDR_SYNC_PROMO_HTML);
  html_source->SetUseJsonJSFormatV2();
  return html_source;
}

}  // namespace

SyncPromoUI::SyncPromoUI(content::WebUI* web_ui) : WebUIController(web_ui) {
  SyncPromoHandler* handler = new SyncPromoHandler(
      g_browser_process->profile_manager());
  web_ui->AddMessageHandler(handler);

  // Set up the chrome://theme/ source.
  Profile* profile = Profile::FromWebUI(web_ui);
  ThemeSource* theme = new ThemeSource(profile);
  content::URLDataSource::Add(profile, theme);

  // Set up the sync promo source.
  content::WebUIDataSource::Add(profile, CreateSyncUIHTMLSource(web_ui));

  sync_promo_trial::RecordUserShownPromo(web_ui);
}

// static
bool SyncPromoUI::HasShownPromoAtStartup(Profile* profile) {
  return profile->GetPrefs()->HasPrefPath(prefs::kSyncPromoStartupCount);
}

// static
bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) {
#if defined(OS_CHROMEOS)
  // There's no need to show the sync promo on cros since cros users are logged
  // into sync already.
  return false;
#else

  // Don't bother if we don't have any kind of network connection.
  if (net::NetworkChangeNotifier::IsOffline())
    return false;

  // Display the signin promo if the user is not signed in.
  SigninManager* signin = SigninManagerFactory::GetForProfile(
      profile->GetOriginalProfile());
  return !signin->AuthInProgress() && signin->IsSigninAllowed() &&
      signin->GetAuthenticatedUsername().empty();
#endif
}

// static
void SyncPromoUI::RegisterUserPrefs(PrefRegistrySyncable* registry) {
  registry->RegisterIntegerPref(prefs::kSyncPromoStartupCount, 0,
                                PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterBooleanPref(prefs::kSyncPromoUserSkipped, false,
                                PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterBooleanPref(prefs::kSyncPromoShowOnFirstRunAllowed, true,
                                PrefRegistrySyncable::UNSYNCABLE_PREF);

  SyncPromoHandler::RegisterUserPrefs(registry);
}

// static
bool SyncPromoUI::ShouldShowSyncPromoAtStartup(Profile* profile,
                                               bool is_new_profile) {
  DCHECK(profile);

  if (!ShouldShowSyncPromo(profile))
    return false;

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kNoFirstRun))
    is_new_profile = false;

  if (!is_new_profile) {
    if (!HasShownPromoAtStartup(profile))
      return false;
  }

  if (HasUserSkippedSyncPromo(profile))
    return false;

  // For Chinese users skip the sync promo.
  if (g_browser_process->GetApplicationLocale() == "zh-CN")
    return false;

  PrefService* prefs = profile->GetPrefs();
  int show_count = prefs->GetInteger(prefs::kSyncPromoStartupCount);
  if (show_count >= kSyncPromoShowAtStartupMaximum)
    return false;

  // This pref can be set in the master preferences file to allow or disallow
  // showing the sync promo at startup.
  if (prefs->HasPrefPath(prefs::kSyncPromoShowOnFirstRunAllowed))
    return prefs->GetBoolean(prefs::kSyncPromoShowOnFirstRunAllowed);

  // For now don't show the promo for some brands.
  if (!AllowPromoAtStartupForCurrentBrand())
    return false;

  // Default to show the promo for Google Chrome builds.
#if defined(GOOGLE_CHROME_BUILD)
  return true;
#else
  return false;
#endif
}

void SyncPromoUI::DidShowSyncPromoAtStartup(Profile* profile) {
  int show_count = profile->GetPrefs()->GetInteger(
      prefs::kSyncPromoStartupCount);
  show_count++;
  profile->GetPrefs()->SetInteger(prefs::kSyncPromoStartupCount, show_count);
}

bool SyncPromoUI::HasUserSkippedSyncPromo(Profile* profile) {
  return profile->GetPrefs()->GetBoolean(prefs::kSyncPromoUserSkipped);
}

void SyncPromoUI::SetUserSkippedSyncPromo(Profile* profile) {
  profile->GetPrefs()->SetBoolean(prefs::kSyncPromoUserSkipped, true);
}

// static
GURL SyncPromoUI::GetSyncPromoURL(const GURL& next_page,
                                  Source source,
                                  bool auto_close) {
  DCHECK_NE(SOURCE_UNKNOWN, source);

  std::string url_string;

  if (UseWebBasedSigninFlow()) {
    // Build a Gaia-based URL that can be used to sign the user into chrome.
    // There are required request parameters:
    //
    //  - tell Gaia which service the user is signing into.  In this case,
    //    a chrome sign in uses the service "chromiumsync"
    //  - provide a continue URL.  This is the URL that Gaia will redirect to
    //    once the sign is complete.
    //
    // The continue URL includes a source parameter that can be extracted using
    // the function GetSourceForSyncPromoURL() below.  This is used to know
    // which of the chrome sign in access points was used to sign the userr in.
    // See OneClickSigninHelper for details.
    url_string = GaiaUrls::GetInstance()->service_login_url();
    url_string.append("?service=chromiumsync&sarp=1&rm=hide");

    const std::string& locale = g_browser_process->GetApplicationLocale();
    std::string continue_url = base::StringPrintf(kContinueUrl, locale.c_str(),
        kSyncPromoQueryKeySource, static_cast<int>(source));

    base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyContinue,
                        net::EscapeQueryParamValue(
                            continue_url, false).c_str());
  } else {
    url_string = base::StringPrintf("%s?%s=%d", chrome::kChromeUISyncPromoURL,
                                    kSyncPromoQueryKeySource,
                                    static_cast<int>(source));

    if (auto_close)
      base::StringAppendF(&url_string, "&%s=1", kSyncPromoQueryKeyAutoClose);

    if (!next_page.spec().empty()) {
      base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyNextPage,
                          net::EscapeQueryParamValue(next_page.spec(),
                                                     false).c_str());
    }
  }

  return GURL(url_string);
}

// static
GURL SyncPromoUI::GetNextPageURLForSyncPromoURL(const GURL& url) {
  const char* key_name = UseWebBasedSigninFlow() ? kSyncPromoQueryKeyContinue :
      kSyncPromoQueryKeyNextPage;
  std::string value;
  if (net::GetValueForKeyInQuery(url, key_name, &value)) {
    return GURL(value);
  }
  return GURL();
}

// static
SyncPromoUI::Source SyncPromoUI::GetSourceForSyncPromoURL(const GURL& url) {
  std::string value;
  if (net::GetValueForKeyInQuery(url, kSyncPromoQueryKeySource, &value)) {
    int source = 0;
    if (base::StringToInt(value, &source) && source >= SOURCE_START_PAGE &&
        source < SOURCE_UNKNOWN) {
      return static_cast<Source>(source);
    }
  }
  return SOURCE_UNKNOWN;
}

// static
bool SyncPromoUI::GetAutoCloseForSyncPromoURL(const GURL& url) {
  std::string value;
  if (net::GetValueForKeyInQuery(url, kSyncPromoQueryKeyAutoClose, &value)) {
    int source = 0;
    base::StringToInt(value, &source);
    return (source == 1);
  }
  return false;
}

// static
bool SyncPromoUI::UseWebBasedSigninFlow() {
#if defined(ENABLE_ONE_CLICK_SIGNIN)
  return !CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kUseClientLoginSigninFlow) ||
      g_force_web_based_signin_flow;
#else
  return false;
#endif
}

// static
void SyncPromoUI::ForceWebBasedSigninFlowForTesting(bool force) {
  g_force_web_based_signin_flow = force;
}
<commit_msg>Adding a check to not show sync promo for incognito profiles. <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/ui/webui/sync_promo/sync_promo_ui.h"

#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/strings/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/webui/options/core_options_handler.h"
#include "chrome/browser/ui/webui/sync_promo/sync_promo_handler.h"
#include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
#include "chrome/browser/ui/webui/theme_source.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/net/url_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "google_apis/gaia/gaia_urls.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/escape.h"
#include "net/base/network_change_notifier.h"
#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"

using content::WebContents;

namespace {

const char kStringsJsFile[] = "strings.js";
const char kSyncPromoJsFile[] = "sync_promo.js";

const char kSyncPromoQueryKeyAutoClose[] = "auto_close";
const char kSyncPromoQueryKeyContinue[] = "continue";
const char kSyncPromoQueryKeyNextPage[] = "next_page";
const char kSyncPromoQueryKeySource[] = "source";

// Gaia cannot support about:blank as a continue URL, so using a hosted blank
// page instead.
const char kContinueUrl[] =
    "https://www.google.com/intl/%s/chrome/blank.html?%s=%d";

// The maximum number of times we want to show the sync promo at startup.
const int kSyncPromoShowAtStartupMaximum = 10;

// Forces the web based signin flow when set.
bool g_force_web_based_signin_flow = false;

// Checks we want to show the sync promo for the given brand.
bool AllowPromoAtStartupForCurrentBrand() {
  std::string brand;
  google_util::GetBrand(&brand);

  if (brand.empty())
    return true;

  if (google_util::IsInternetCafeBrandCode(brand))
    return false;

  // Enable for both organic and distribution.
  return true;
}

content::WebUIDataSource* CreateSyncUIHTMLSource(content::WebUI* web_ui) {
  content::WebUIDataSource* html_source =
      content::WebUIDataSource::Create(chrome::kChromeUISyncPromoHost);
  DictionaryValue localized_strings;
  options::CoreOptionsHandler::GetStaticLocalizedValues(&localized_strings);
  SyncSetupHandler::GetStaticLocalizedValues(&localized_strings, web_ui);
  html_source->AddLocalizedStrings(localized_strings);
  html_source->SetJsonPath(kStringsJsFile);
  html_source->AddResourcePath(kSyncPromoJsFile, IDR_SYNC_PROMO_JS);
  html_source->SetDefaultResource(IDR_SYNC_PROMO_HTML);
  html_source->SetUseJsonJSFormatV2();
  return html_source;
}

}  // namespace

SyncPromoUI::SyncPromoUI(content::WebUI* web_ui) : WebUIController(web_ui) {
  SyncPromoHandler* handler = new SyncPromoHandler(
      g_browser_process->profile_manager());
  web_ui->AddMessageHandler(handler);

  // Set up the chrome://theme/ source.
  Profile* profile = Profile::FromWebUI(web_ui);
  ThemeSource* theme = new ThemeSource(profile);
  content::URLDataSource::Add(profile, theme);

  // Set up the sync promo source.
  content::WebUIDataSource::Add(profile, CreateSyncUIHTMLSource(web_ui));

  sync_promo_trial::RecordUserShownPromo(web_ui);
}

// static
bool SyncPromoUI::HasShownPromoAtStartup(Profile* profile) {
  return profile->GetPrefs()->HasPrefPath(prefs::kSyncPromoStartupCount);
}

// static
bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) {
#if defined(OS_CHROMEOS)
  // There's no need to show the sync promo on cros since cros users are logged
  // into sync already.
  return false;
#else

  // Don't bother if we don't have any kind of network connection.
  if (net::NetworkChangeNotifier::IsOffline())
    return false;

  // Don't show if the profile is an incognito.
  if (profile->IsOffTheRecord())
    return false;

  // Display the signin promo if the user is not signed in.
  SigninManager* signin = SigninManagerFactory::GetForProfile(
      profile->GetOriginalProfile());
  return !signin->AuthInProgress() && signin->IsSigninAllowed() &&
      signin->GetAuthenticatedUsername().empty();
#endif
}

// static
void SyncPromoUI::RegisterUserPrefs(PrefRegistrySyncable* registry) {
  registry->RegisterIntegerPref(prefs::kSyncPromoStartupCount, 0,
                                PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterBooleanPref(prefs::kSyncPromoUserSkipped, false,
                                PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterBooleanPref(prefs::kSyncPromoShowOnFirstRunAllowed, true,
                                PrefRegistrySyncable::UNSYNCABLE_PREF);

  SyncPromoHandler::RegisterUserPrefs(registry);
}

// static
bool SyncPromoUI::ShouldShowSyncPromoAtStartup(Profile* profile,
                                               bool is_new_profile) {
  DCHECK(profile);

  if (!ShouldShowSyncPromo(profile))
    return false;

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kNoFirstRun))
    is_new_profile = false;

  if (!is_new_profile) {
    if (!HasShownPromoAtStartup(profile))
      return false;
  }

  if (HasUserSkippedSyncPromo(profile))
    return false;

  // For Chinese users skip the sync promo.
  if (g_browser_process->GetApplicationLocale() == "zh-CN")
    return false;

  PrefService* prefs = profile->GetPrefs();
  int show_count = prefs->GetInteger(prefs::kSyncPromoStartupCount);
  if (show_count >= kSyncPromoShowAtStartupMaximum)
    return false;

  // This pref can be set in the master preferences file to allow or disallow
  // showing the sync promo at startup.
  if (prefs->HasPrefPath(prefs::kSyncPromoShowOnFirstRunAllowed))
    return prefs->GetBoolean(prefs::kSyncPromoShowOnFirstRunAllowed);

  // For now don't show the promo for some brands.
  if (!AllowPromoAtStartupForCurrentBrand())
    return false;

  // Default to show the promo for Google Chrome builds.
#if defined(GOOGLE_CHROME_BUILD)
  return true;
#else
  return false;
#endif
}

void SyncPromoUI::DidShowSyncPromoAtStartup(Profile* profile) {
  int show_count = profile->GetPrefs()->GetInteger(
      prefs::kSyncPromoStartupCount);
  show_count++;
  profile->GetPrefs()->SetInteger(prefs::kSyncPromoStartupCount, show_count);
}

bool SyncPromoUI::HasUserSkippedSyncPromo(Profile* profile) {
  return profile->GetPrefs()->GetBoolean(prefs::kSyncPromoUserSkipped);
}

void SyncPromoUI::SetUserSkippedSyncPromo(Profile* profile) {
  profile->GetPrefs()->SetBoolean(prefs::kSyncPromoUserSkipped, true);
}

// static
GURL SyncPromoUI::GetSyncPromoURL(const GURL& next_page,
                                  Source source,
                                  bool auto_close) {
  DCHECK_NE(SOURCE_UNKNOWN, source);

  std::string url_string;

  if (UseWebBasedSigninFlow()) {
    // Build a Gaia-based URL that can be used to sign the user into chrome.
    // There are required request parameters:
    //
    //  - tell Gaia which service the user is signing into.  In this case,
    //    a chrome sign in uses the service "chromiumsync"
    //  - provide a continue URL.  This is the URL that Gaia will redirect to
    //    once the sign is complete.
    //
    // The continue URL includes a source parameter that can be extracted using
    // the function GetSourceForSyncPromoURL() below.  This is used to know
    // which of the chrome sign in access points was used to sign the userr in.
    // See OneClickSigninHelper for details.
    url_string = GaiaUrls::GetInstance()->service_login_url();
    url_string.append("?service=chromiumsync&sarp=1&rm=hide");

    const std::string& locale = g_browser_process->GetApplicationLocale();
    std::string continue_url = base::StringPrintf(kContinueUrl, locale.c_str(),
        kSyncPromoQueryKeySource, static_cast<int>(source));

    base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyContinue,
                        net::EscapeQueryParamValue(
                            continue_url, false).c_str());
  } else {
    url_string = base::StringPrintf("%s?%s=%d", chrome::kChromeUISyncPromoURL,
                                    kSyncPromoQueryKeySource,
                                    static_cast<int>(source));

    if (auto_close)
      base::StringAppendF(&url_string, "&%s=1", kSyncPromoQueryKeyAutoClose);

    if (!next_page.spec().empty()) {
      base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyNextPage,
                          net::EscapeQueryParamValue(next_page.spec(),
                                                     false).c_str());
    }
  }

  return GURL(url_string);
}

// static
GURL SyncPromoUI::GetNextPageURLForSyncPromoURL(const GURL& url) {
  const char* key_name = UseWebBasedSigninFlow() ? kSyncPromoQueryKeyContinue :
      kSyncPromoQueryKeyNextPage;
  std::string value;
  if (net::GetValueForKeyInQuery(url, key_name, &value)) {
    return GURL(value);
  }
  return GURL();
}

// static
SyncPromoUI::Source SyncPromoUI::GetSourceForSyncPromoURL(const GURL& url) {
  std::string value;
  if (net::GetValueForKeyInQuery(url, kSyncPromoQueryKeySource, &value)) {
    int source = 0;
    if (base::StringToInt(value, &source) && source >= SOURCE_START_PAGE &&
        source < SOURCE_UNKNOWN) {
      return static_cast<Source>(source);
    }
  }
  return SOURCE_UNKNOWN;
}

// static
bool SyncPromoUI::GetAutoCloseForSyncPromoURL(const GURL& url) {
  std::string value;
  if (net::GetValueForKeyInQuery(url, kSyncPromoQueryKeyAutoClose, &value)) {
    int source = 0;
    base::StringToInt(value, &source);
    return (source == 1);
  }
  return false;
}

// static
bool SyncPromoUI::UseWebBasedSigninFlow() {
#if defined(ENABLE_ONE_CLICK_SIGNIN)
  return !CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kUseClientLoginSigninFlow) ||
      g_force_web_based_signin_flow;
#else
  return false;
#endif
}

// static
void SyncPromoUI::ForceWebBasedSigninFlowForTesting(bool force) {
  g_force_web_based_signin_flow = force;
}
<|endoftext|>


<commit_before><commit_msg>gpl: optimizations and documentation of area scaling<commit_after><|endoftext|>


<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/ui/webui/sync_promo/sync_promo_ui.h"

#include "base/command_line.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
#include "chrome/browser/ui/webui/options/core_options_handler.h"
#include "chrome/browser/ui/webui/sync_promo/sync_promo_handler.h"
#include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
#include "chrome/browser/ui/webui/theme_source.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/net/url_util.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "google_apis/gaia/gaia_urls.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/escape.h"
#include "ui/base/l10n/l10n_util.h"

using content::WebContents;

namespace {

const char kStringsJsFile[] = "strings.js";
const char kSyncPromoJsFile[] = "sync_promo.js";

const char kSyncPromoQueryKeyAutoClose[] = "auto_close";
const char kSyncPromoQueryKeyContinue[] = "continue";
const char kSyncPromoQueryKeyNextPage[] = "next_page";
const char kSyncPromoQueryKeySource[] = "source";

// TODO(rogerta): It would be better to use about:blank, but until that is
// supported by Gaia this blank continue URL will be used.
const char kContinueUrl[] = "http://www.google.com/gen_204";

// The maximum number of times we want to show the sync promo at startup.
const int kSyncPromoShowAtStartupMaximum = 10;

// Checks we want to show the sync promo for the given brand.
bool AllowPromoAtStartupForCurrentBrand() {
  std::string brand;
  google_util::GetBrand(&brand);

  if (brand.empty())
    return true;

  if (google_util::IsInternetCafeBrandCode(brand))
    return false;

  // Enable for both organic and distribution.
  return true;
}

// The Web UI data source for the sync promo page.
class SyncPromoUIHTMLSource : public ChromeWebUIDataSource {
 public:
  explicit SyncPromoUIHTMLSource(content::WebUI* web_ui);

 private:
  ~SyncPromoUIHTMLSource() {}
  DISALLOW_COPY_AND_ASSIGN(SyncPromoUIHTMLSource);
};

SyncPromoUIHTMLSource::SyncPromoUIHTMLSource(content::WebUI* web_ui)
    : ChromeWebUIDataSource(chrome::kChromeUISyncPromoHost) {
  DictionaryValue localized_strings;
  options::CoreOptionsHandler::GetStaticLocalizedValues(&localized_strings);
  SyncSetupHandler::GetStaticLocalizedValues(&localized_strings, web_ui);
  AddLocalizedStrings(localized_strings);
}

}  // namespace

SyncPromoUI::SyncPromoUI(content::WebUI* web_ui) : WebUIController(web_ui) {
  SyncPromoHandler* handler = new SyncPromoHandler(
      g_browser_process->profile_manager());
  web_ui->AddMessageHandler(handler);

  // Set up the chrome://theme/ source.
  Profile* profile = Profile::FromWebUI(web_ui);
  ThemeSource* theme = new ThemeSource(profile);
  ChromeURLDataManager::AddDataSource(profile, theme);

  // Set up the sync promo source.
  SyncPromoUIHTMLSource* html_source = new SyncPromoUIHTMLSource(web_ui);
  html_source->set_json_path(kStringsJsFile);
  html_source->add_resource_path(kSyncPromoJsFile, IDR_SYNC_PROMO_JS);
  html_source->set_default_resource(IDR_SYNC_PROMO_HTML);
  html_source->set_use_json_js_format_v2();
  ChromeURLDataManager::AddDataSource(profile, html_source);

  sync_promo_trial::RecordUserShownPromo(web_ui);
}

// static
bool SyncPromoUI::HasShownPromoAtStartup(Profile* profile) {
  return profile->GetPrefs()->HasPrefPath(prefs::kSyncPromoStartupCount);
}

// static
bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) {
#if defined(OS_CHROMEOS)
  // There's no need to show the sync promo on cros since cros users are logged
  // into sync already.
  return false;
#endif

  // Honor the sync policies.
  if (!profile->GetOriginalProfile()->IsSyncAccessible())
    return false;

  // If the user is already signed into sync then don't show the promo.
  ProfileSyncService* service =
      ProfileSyncServiceFactory::GetInstance()->GetForProfile(
          profile->GetOriginalProfile());
  if (!service || service->HasSyncSetupCompleted())
    return false;

  // Default to allow the promo.
  return true;
}

// static
void SyncPromoUI::RegisterUserPrefs(PrefService* prefs) {
  prefs->RegisterIntegerPref(
      prefs::kSyncPromoStartupCount, 0, PrefService::UNSYNCABLE_PREF);
  prefs->RegisterBooleanPref(
      prefs::kSyncPromoUserSkipped, false, PrefService::UNSYNCABLE_PREF);
  prefs->RegisterBooleanPref(prefs::kSyncPromoShowOnFirstRunAllowed, true,
      PrefService::UNSYNCABLE_PREF);

  SyncPromoHandler::RegisterUserPrefs(prefs);
}

// static
bool SyncPromoUI::ShouldShowSyncPromoAtStartup(Profile* profile,
                                               bool is_new_profile) {
  DCHECK(profile);

  if (!ShouldShowSyncPromo(profile))
    return false;

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kNoFirstRun))
    is_new_profile = false;

  if (!is_new_profile) {
    if (!HasShownPromoAtStartup(profile))
      return false;
  }

  if (HasUserSkippedSyncPromo(profile))
    return false;

  // For Chinese users skip the sync promo.
  if (g_browser_process->GetApplicationLocale() == "zh-CN")
    return false;

  PrefService* prefs = profile->GetPrefs();
  int show_count = prefs->GetInteger(prefs::kSyncPromoStartupCount);
  if (show_count >= kSyncPromoShowAtStartupMaximum)
    return false;

  // This pref can be set in the master preferences file to allow or disallow
  // showing the sync promo at startup.
  if (prefs->HasPrefPath(prefs::kSyncPromoShowOnFirstRunAllowed))
    return prefs->GetBoolean(prefs::kSyncPromoShowOnFirstRunAllowed);

  // For now don't show the promo for some brands.
  if (!AllowPromoAtStartupForCurrentBrand())
    return false;

  // Default to show the promo for Google Chrome builds.
#if defined(GOOGLE_CHROME_BUILD)
  return true;
#else
  return false;
#endif
}

void SyncPromoUI::DidShowSyncPromoAtStartup(Profile* profile) {
  int show_count = profile->GetPrefs()->GetInteger(
      prefs::kSyncPromoStartupCount);
  show_count++;
  profile->GetPrefs()->SetInteger(prefs::kSyncPromoStartupCount, show_count);
}

bool SyncPromoUI::HasUserSkippedSyncPromo(Profile* profile) {
  return profile->GetPrefs()->GetBoolean(prefs::kSyncPromoUserSkipped);
}

void SyncPromoUI::SetUserSkippedSyncPromo(Profile* profile) {
  profile->GetPrefs()->SetBoolean(prefs::kSyncPromoUserSkipped, true);
}

// static
GURL SyncPromoUI::GetSyncPromoURL(const GURL& next_page,
                                  Source source,
                                  bool auto_close) {
  DCHECK_NE(SOURCE_UNKNOWN, source);

  std::string url_string;

  if (UseWebBasedSigninFlow()) {
    // Build a Gaia-based URL that can be used to sign the user into chrome.
    // There are required request parameters:
    //
    //  - tell Gaia which service the user is signing into.  In this case,
    //    a chrome sign in uses the service "chromiumsync"
    //  - provide a continue URL.  This is the URL that Gaia will redirect to
    //    once the sign is complete.
    //
    // The continue URL includes a source parameter that can be extracted using
    // the function GetSourceForSyncPromoURL() below.  This is used to know
    // which of the chrome sign in access points was used to sign the userr in.
    // See OneClickSigninHelper for details.
    url_string = GaiaUrls::GetInstance()->service_login_url();
    url_string.append("?service=chromiumsync");

    std::string continue_url = base::StringPrintf("%s?%s=%d",
        kContinueUrl, kSyncPromoQueryKeySource, static_cast<int>(source));

    base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyContinue,
                        net::EscapeQueryParamValue(
                            continue_url, false).c_str());
  } else {
    url_string = base::StringPrintf("%s?%s=%d", chrome::kChromeUISyncPromoURL,
                                    kSyncPromoQueryKeySource,
                                    static_cast<int>(source));

    if (auto_close)
      base::StringAppendF(&url_string, "&%s=1", kSyncPromoQueryKeyAutoClose);

    if (!next_page.spec().empty()) {
      base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyNextPage,
                          net::EscapeQueryParamValue(next_page.spec(),
                                                     false).c_str());
    }
  }

  return GURL(url_string);
}

// static
GURL SyncPromoUI::GetNextPageURLForSyncPromoURL(const GURL& url) {
  std::string value;
  if (chrome_common_net::GetValueForKeyInQuery(
          url, kSyncPromoQueryKeyNextPage, &value)) {
    return GURL(value);
  }
  return GURL();
}

// static
SyncPromoUI::Source SyncPromoUI::GetSourceForSyncPromoURL(const GURL& url) {
  std::string value;
  if (chrome_common_net::GetValueForKeyInQuery(
          url, kSyncPromoQueryKeySource, &value)) {
    int source = 0;
    if (base::StringToInt(value, &source) && source >= SOURCE_START_PAGE &&
        source < SOURCE_UNKNOWN) {
      return static_cast<Source>(source);
    }
  }
  return SOURCE_UNKNOWN;
}

// static
bool SyncPromoUI::GetAutoCloseForSyncPromoURL(const GURL& url) {
  std::string value;
  if (chrome_common_net::GetValueForKeyInQuery(
          url, kSyncPromoQueryKeyAutoClose, &value)) {
    int source = 0;
    base::StringToInt(value, &source);
    return (source == 1);
  }
  return false;
}

// static
bool SyncPromoUI::UseWebBasedSigninFlow() {
#if defined(ENABLE_ONE_CLICK_SIGNIN)
  return !CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kUseClientLoginSigninFlow);
#else
  return false;
#endif
}
<commit_msg>Don't show Sync promo if we have zero network connectivity.<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/ui/webui/sync_promo/sync_promo_ui.h"

#include "base/command_line.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
#include "chrome/browser/ui/webui/options/core_options_handler.h"
#include "chrome/browser/ui/webui/sync_promo/sync_promo_handler.h"
#include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
#include "chrome/browser/ui/webui/theme_source.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/net/url_util.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "google_apis/gaia/gaia_urls.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/escape.h"
#include "net/base/network_change_notifier.h"
#include "ui/base/l10n/l10n_util.h"

using content::WebContents;

namespace {

const char kStringsJsFile[] = "strings.js";
const char kSyncPromoJsFile[] = "sync_promo.js";

const char kSyncPromoQueryKeyAutoClose[] = "auto_close";
const char kSyncPromoQueryKeyContinue[] = "continue";
const char kSyncPromoQueryKeyNextPage[] = "next_page";
const char kSyncPromoQueryKeySource[] = "source";

// TODO(rogerta): It would be better to use about:blank, but until that is
// supported by Gaia this blank continue URL will be used.
const char kContinueUrl[] = "http://www.google.com/gen_204";

// The maximum number of times we want to show the sync promo at startup.
const int kSyncPromoShowAtStartupMaximum = 10;

// Checks we want to show the sync promo for the given brand.
bool AllowPromoAtStartupForCurrentBrand() {
  std::string brand;
  google_util::GetBrand(&brand);

  if (brand.empty())
    return true;

  if (google_util::IsInternetCafeBrandCode(brand))
    return false;

  // Enable for both organic and distribution.
  return true;
}

// The Web UI data source for the sync promo page.
class SyncPromoUIHTMLSource : public ChromeWebUIDataSource {
 public:
  explicit SyncPromoUIHTMLSource(content::WebUI* web_ui);

 private:
  ~SyncPromoUIHTMLSource() {}
  DISALLOW_COPY_AND_ASSIGN(SyncPromoUIHTMLSource);
};

SyncPromoUIHTMLSource::SyncPromoUIHTMLSource(content::WebUI* web_ui)
    : ChromeWebUIDataSource(chrome::kChromeUISyncPromoHost) {
  DictionaryValue localized_strings;
  options::CoreOptionsHandler::GetStaticLocalizedValues(&localized_strings);
  SyncSetupHandler::GetStaticLocalizedValues(&localized_strings, web_ui);
  AddLocalizedStrings(localized_strings);
}

}  // namespace

SyncPromoUI::SyncPromoUI(content::WebUI* web_ui) : WebUIController(web_ui) {
  SyncPromoHandler* handler = new SyncPromoHandler(
      g_browser_process->profile_manager());
  web_ui->AddMessageHandler(handler);

  // Set up the chrome://theme/ source.
  Profile* profile = Profile::FromWebUI(web_ui);
  ThemeSource* theme = new ThemeSource(profile);
  ChromeURLDataManager::AddDataSource(profile, theme);

  // Set up the sync promo source.
  SyncPromoUIHTMLSource* html_source = new SyncPromoUIHTMLSource(web_ui);
  html_source->set_json_path(kStringsJsFile);
  html_source->add_resource_path(kSyncPromoJsFile, IDR_SYNC_PROMO_JS);
  html_source->set_default_resource(IDR_SYNC_PROMO_HTML);
  html_source->set_use_json_js_format_v2();
  ChromeURLDataManager::AddDataSource(profile, html_source);

  sync_promo_trial::RecordUserShownPromo(web_ui);
}

// static
bool SyncPromoUI::HasShownPromoAtStartup(Profile* profile) {
  return profile->GetPrefs()->HasPrefPath(prefs::kSyncPromoStartupCount);
}

// static
bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) {
#if defined(OS_CHROMEOS)
  // There's no need to show the sync promo on cros since cros users are logged
  // into sync already.
  return false;
#endif

  // Don't bother if we don't have any kind of network connection.
  if (net::NetworkChangeNotifier::IsOffline())
    return false;

  // Honor the sync policies.
  if (!profile->GetOriginalProfile()->IsSyncAccessible())
    return false;

  // If the user is already signed into sync then don't show the promo.
  ProfileSyncService* service =
      ProfileSyncServiceFactory::GetInstance()->GetForProfile(
          profile->GetOriginalProfile());
  if (!service || service->HasSyncSetupCompleted())
    return false;

  // Default to allow the promo.
  return true;
}

// static
void SyncPromoUI::RegisterUserPrefs(PrefService* prefs) {
  prefs->RegisterIntegerPref(
      prefs::kSyncPromoStartupCount, 0, PrefService::UNSYNCABLE_PREF);
  prefs->RegisterBooleanPref(
      prefs::kSyncPromoUserSkipped, false, PrefService::UNSYNCABLE_PREF);
  prefs->RegisterBooleanPref(prefs::kSyncPromoShowOnFirstRunAllowed, true,
      PrefService::UNSYNCABLE_PREF);

  SyncPromoHandler::RegisterUserPrefs(prefs);
}

// static
bool SyncPromoUI::ShouldShowSyncPromoAtStartup(Profile* profile,
                                               bool is_new_profile) {
  DCHECK(profile);

  if (!ShouldShowSyncPromo(profile))
    return false;

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kNoFirstRun))
    is_new_profile = false;

  if (!is_new_profile) {
    if (!HasShownPromoAtStartup(profile))
      return false;
  }

  if (HasUserSkippedSyncPromo(profile))
    return false;

  // For Chinese users skip the sync promo.
  if (g_browser_process->GetApplicationLocale() == "zh-CN")
    return false;

  PrefService* prefs = profile->GetPrefs();
  int show_count = prefs->GetInteger(prefs::kSyncPromoStartupCount);
  if (show_count >= kSyncPromoShowAtStartupMaximum)
    return false;

  // This pref can be set in the master preferences file to allow or disallow
  // showing the sync promo at startup.
  if (prefs->HasPrefPath(prefs::kSyncPromoShowOnFirstRunAllowed))
    return prefs->GetBoolean(prefs::kSyncPromoShowOnFirstRunAllowed);

  // For now don't show the promo for some brands.
  if (!AllowPromoAtStartupForCurrentBrand())
    return false;

  // Default to show the promo for Google Chrome builds.
#if defined(GOOGLE_CHROME_BUILD)
  return true;
#else
  return false;
#endif
}

void SyncPromoUI::DidShowSyncPromoAtStartup(Profile* profile) {
  int show_count = profile->GetPrefs()->GetInteger(
      prefs::kSyncPromoStartupCount);
  show_count++;
  profile->GetPrefs()->SetInteger(prefs::kSyncPromoStartupCount, show_count);
}

bool SyncPromoUI::HasUserSkippedSyncPromo(Profile* profile) {
  return profile->GetPrefs()->GetBoolean(prefs::kSyncPromoUserSkipped);
}

void SyncPromoUI::SetUserSkippedSyncPromo(Profile* profile) {
  profile->GetPrefs()->SetBoolean(prefs::kSyncPromoUserSkipped, true);
}

// static
GURL SyncPromoUI::GetSyncPromoURL(const GURL& next_page,
                                  Source source,
                                  bool auto_close) {
  DCHECK_NE(SOURCE_UNKNOWN, source);

  std::string url_string;

  if (UseWebBasedSigninFlow()) {
    // Build a Gaia-based URL that can be used to sign the user into chrome.
    // There are required request parameters:
    //
    //  - tell Gaia which service the user is signing into.  In this case,
    //    a chrome sign in uses the service "chromiumsync"
    //  - provide a continue URL.  This is the URL that Gaia will redirect to
    //    once the sign is complete.
    //
    // The continue URL includes a source parameter that can be extracted using
    // the function GetSourceForSyncPromoURL() below.  This is used to know
    // which of the chrome sign in access points was used to sign the userr in.
    // See OneClickSigninHelper for details.
    url_string = GaiaUrls::GetInstance()->service_login_url();
    url_string.append("?service=chromiumsync");

    std::string continue_url = base::StringPrintf("%s?%s=%d",
        kContinueUrl, kSyncPromoQueryKeySource, static_cast<int>(source));

    base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyContinue,
                        net::EscapeQueryParamValue(
                            continue_url, false).c_str());
  } else {
    url_string = base::StringPrintf("%s?%s=%d", chrome::kChromeUISyncPromoURL,
                                    kSyncPromoQueryKeySource,
                                    static_cast<int>(source));

    if (auto_close)
      base::StringAppendF(&url_string, "&%s=1", kSyncPromoQueryKeyAutoClose);

    if (!next_page.spec().empty()) {
      base::StringAppendF(&url_string, "&%s=%s", kSyncPromoQueryKeyNextPage,
                          net::EscapeQueryParamValue(next_page.spec(),
                                                     false).c_str());
    }
  }

  return GURL(url_string);
}

// static
GURL SyncPromoUI::GetNextPageURLForSyncPromoURL(const GURL& url) {
  std::string value;
  if (chrome_common_net::GetValueForKeyInQuery(
          url, kSyncPromoQueryKeyNextPage, &value)) {
    return GURL(value);
  }
  return GURL();
}

// static
SyncPromoUI::Source SyncPromoUI::GetSourceForSyncPromoURL(const GURL& url) {
  std::string value;
  if (chrome_common_net::GetValueForKeyInQuery(
          url, kSyncPromoQueryKeySource, &value)) {
    int source = 0;
    if (base::StringToInt(value, &source) && source >= SOURCE_START_PAGE &&
        source < SOURCE_UNKNOWN) {
      return static_cast<Source>(source);
    }
  }
  return SOURCE_UNKNOWN;
}

// static
bool SyncPromoUI::GetAutoCloseForSyncPromoURL(const GURL& url) {
  std::string value;
  if (chrome_common_net::GetValueForKeyInQuery(
          url, kSyncPromoQueryKeyAutoClose, &value)) {
    int source = 0;
    base::StringToInt(value, &source);
    return (source == 1);
  }
  return false;
}

// static
bool SyncPromoUI::UseWebBasedSigninFlow() {
#if defined(ENABLE_ONE_CLICK_SIGNIN)
  return !CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kUseClientLoginSigninFlow);
#else
  return false;
#endif
}
<|endoftext|>


<commit_before>/*
 * slicerenderer.cpp
 *
 *  Created on: 09.05.2012
 *      Author: Ralph
 */
#include "../../glew/include/glew.h"

#include <QtOpenGL/QGLShaderProgram>
#include <QtGui/QVector3D>
#include <QtGui/QMatrix4x4>

#include "glfunctions.h"

#include "slicerenderer.h"

SliceRenderer::SliceRenderer() :
    ObjectRenderer(),
    vboIds( new GLuint[ 4 ] ),
    m_x( 0. ),
    m_y( 0. ),
    m_z( 0. ),
    m_xb( 0. ),
    m_yb( 0. ),
    m_zb( 0. ),
    m_xOld( -1 ),
    m_yOld( -1 ),
    m_zOld( -1 ),
    m_xbOld( -1 ),
    m_ybOld( -1 ),
    m_zbOld( -1 )
{
}

SliceRenderer::~SliceRenderer()
{
    glDeleteBuffers( 4, vboIds );
    delete[] vboIds;
}

void SliceRenderer::init()
{
    initShader();
    glGenBuffers( 4, vboIds );

    GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
    // Transfer index data to VBO 0
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIds[ 0 ] );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), indices, GL_STATIC_DRAW );

    initGeometry();
}

void SliceRenderer::initShader()
{
    m_program = GLFunctions::initShader( "slice" );
}

void SliceRenderer::initGeometry()
{
    m_x = model()->data( model()->index( 0, 100 ), Qt::UserRole ).toFloat();
    m_y = model()->data( model()->index( 0, 101 ), Qt::UserRole ).toFloat();
    m_z = model()->data( model()->index( 0, 102 ), Qt::UserRole ).toFloat();
    int xi = model()->data( model()->index( 0, 100 ), Qt::UserRole ).toInt();
    int yi = model()->data( model()->index( 0, 101 ), Qt::UserRole ).toInt();
    int zi = model()->data( model()->index( 0, 102 ), Qt::UserRole ).toInt();
    m_xb = model()->data( model()->index( 0, 103 ), Qt::UserRole ).toFloat();
    m_yb = model()->data( model()->index( 0, 104 ), Qt::UserRole ).toFloat();
    m_zb = model()->data( model()->index( 0, 105 ), Qt::UserRole ).toFloat();
    int xbi = model()->data( model()->index( 0, 103 ), Qt::UserRole ).toInt();
    int ybi = model()->data( model()->index( 0, 104 ), Qt::UserRole ).toInt();
    int zbi = model()->data( model()->index( 0, 105 ), Qt::UserRole ).toInt();

    float dx = model()->data( model()->index( 0, 106 ), Qt::UserRole ).toFloat();
    float dy = model()->data( model()->index( 0, 107 ), Qt::UserRole ).toFloat();
    float dz = model()->data( model()->index( 0, 108 ), Qt::UserRole ).toFloat();

    m_x *= dx;
    m_y *= dy;
    m_z *= dz;
    m_xb *= dx;
    m_yb *= dy;
    m_zb *= dz;

    if ( zi != m_zOld || zbi != m_zbOld )
    {
        VertexData verticesAxial[] =
        {
            { QVector3D( 0.0,  0.0,  m_z ), QVector3D( 0.0, 0.0, m_z/m_zb ) },
            { QVector3D( m_xb, 0.0,  m_z ), QVector3D( 1.0, 0.0, m_z/m_zb ) },
            { QVector3D( m_xb, m_yb, m_z ), QVector3D( 1.0, 1.0, m_z/m_zb ) },
            { QVector3D( 0.0,  m_yb, m_z ), QVector3D( 0.0, 1.0, m_z/m_zb ) }
        };
        // Transfer vertex data to VBO 1
        glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 1 ] );
        glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verticesAxial, GL_STATIC_DRAW );
    }

    if ( yi != m_yOld || ybi != m_ybOld )
    {
        VertexData verticesCoronal[] =
        {
            { QVector3D( 0.0,  m_y, 0.0  ), QVector3D( 0.0, m_y/m_yb, 0.0 ) },
            { QVector3D( m_xb, m_y, 0.0  ), QVector3D( 1.0, m_y/m_yb, 0.0 ) },
            { QVector3D( m_xb, m_y, m_zb ), QVector3D( 1.0, m_y/m_yb, 1.0 ) },
            { QVector3D( 0.0,  m_y, m_zb ), QVector3D( 0.0, m_y/m_yb, 1.0 ) }
        };

        // Transfer vertex data to VBO 2
        glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 2 ] );
        glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verticesCoronal, GL_STATIC_DRAW );
    }

    if ( xi != m_xOld  || xbi != m_xbOld )
    {
        VertexData verticesSagittal[] =
        {
            { QVector3D( m_x, 0.0,  0.0  ), QVector3D( m_x/m_xb, 0.0, 0.0 ) },
            { QVector3D( m_x, m_yb, 0.0  ), QVector3D( m_x/m_xb, 1.0, 0.0 ) },
            { QVector3D( m_x, m_yb, m_zb ), QVector3D( m_x/m_xb, 1.0, 1.0 ) },
            { QVector3D( m_x, 0.0,  m_zb ), QVector3D( m_x/m_xb, 0.0, 1.0 ) }
        };
        // Transfer vertex data to VBO 3
        glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 3 ] );
        glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verticesSagittal, GL_STATIC_DRAW );
    }

    m_xOld = xi;
    m_yOld = yi;
    m_zOld = zi;
    m_xbOld = xbi;
    m_ybOld = ybi;
    m_zbOld = zbi;
}

void SliceRenderer::setupTextures()
{
    GLFunctions::setupTextures( model() );
}

void SliceRenderer::setShaderVars()
{
    GLFunctions::setSliceShaderVars( m_program, model() );
}

void SliceRenderer::draw( QMatrix4x4 mvp_matrix )
{
    //qDebug() << "main gl draw";
    setupTextures();

    glColor4f( 0.0, 0.0, 0.0, 1.0 );

    // Set modelview-projection matrix
    m_program->setUniformValue( "mvp_matrix", mvp_matrix );

    initGeometry();

    drawAxial();
    drawCoronal();
    drawSagittal();
}

void SliceRenderer::drawAxial()
{
    // Tell OpenGL which VBOs to use
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIds[ 0 ] );
    glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 1 ] );
    setShaderVars();

    // Draw cube geometry using indices from VBO 0
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
}

void SliceRenderer::drawCoronal()
{
    // Tell OpenGL which VBOs to use
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIds[ 0 ] );
    glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 2 ] );
    setShaderVars();
    // Draw cube geometry using indices from VBO 0
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
}

void SliceRenderer::drawSagittal()
{
    // Tell OpenGL which VBOs to use
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIds[ 0 ] );
    glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 3 ] );
    setShaderVars();
    // Draw cube geometry using indices from VBO 0
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
}
<commit_msg>render slice in the middle of voxels<commit_after>/*
 * slicerenderer.cpp
 *
 *  Created on: 09.05.2012
 *      Author: Ralph
 */
#include "../../glew/include/glew.h"

#include <QtOpenGL/QGLShaderProgram>
#include <QtGui/QVector3D>
#include <QtGui/QMatrix4x4>

#include "glfunctions.h"

#include "slicerenderer.h"

SliceRenderer::SliceRenderer() :
    ObjectRenderer(),
    vboIds( new GLuint[ 4 ] ),
    m_x( 0. ),
    m_y( 0. ),
    m_z( 0. ),
    m_xb( 0. ),
    m_yb( 0. ),
    m_zb( 0. ),
    m_xOld( -1 ),
    m_yOld( -1 ),
    m_zOld( -1 ),
    m_xbOld( -1 ),
    m_ybOld( -1 ),
    m_zbOld( -1 )
{
}

SliceRenderer::~SliceRenderer()
{
    glDeleteBuffers( 4, vboIds );
    delete[] vboIds;
}

void SliceRenderer::init()
{
    initShader();
    glGenBuffers( 4, vboIds );

    GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
    // Transfer index data to VBO 0
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIds[ 0 ] );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), indices, GL_STATIC_DRAW );

    initGeometry();
}

void SliceRenderer::initShader()
{
    m_program = GLFunctions::initShader( "slice" );
}

void SliceRenderer::initGeometry()
{
    m_x = model()->data( model()->index( 0, 100 ), Qt::UserRole ).toFloat();
    m_y = model()->data( model()->index( 0, 101 ), Qt::UserRole ).toFloat();
    m_z = model()->data( model()->index( 0, 102 ), Qt::UserRole ).toFloat();
    int xi = model()->data( model()->index( 0, 100 ), Qt::UserRole ).toInt();
    int yi = model()->data( model()->index( 0, 101 ), Qt::UserRole ).toInt();
    int zi = model()->data( model()->index( 0, 102 ), Qt::UserRole ).toInt();
    m_xb = model()->data( model()->index( 0, 103 ), Qt::UserRole ).toFloat();
    m_yb = model()->data( model()->index( 0, 104 ), Qt::UserRole ).toFloat();
    m_zb = model()->data( model()->index( 0, 105 ), Qt::UserRole ).toFloat();
    int xbi = model()->data( model()->index( 0, 103 ), Qt::UserRole ).toInt();
    int ybi = model()->data( model()->index( 0, 104 ), Qt::UserRole ).toInt();
    int zbi = model()->data( model()->index( 0, 105 ), Qt::UserRole ).toInt();

    float dx = model()->data( model()->index( 0, 106 ), Qt::UserRole ).toFloat();
    float dy = model()->data( model()->index( 0, 107 ), Qt::UserRole ).toFloat();
    float dz = model()->data( model()->index( 0, 108 ), Qt::UserRole ).toFloat();

    float x = m_x * dx + dx / 2.;
    float y = m_y * dy + dy / 2.;
    float z = m_z * dz + dz / 2.;
    float xb = m_xb * dx;
    float yb = m_yb * dy;
    float zb = m_zb * dz;

    if ( zi != m_zOld || zbi != m_zbOld )
    {
        VertexData verticesAxial[] =
        {
            { QVector3D( 0.0, 0.0, z ), QVector3D( 0.0, 0.0, z / zb ) },
            { QVector3D( xb,  0.0, z ), QVector3D( 1.0, 0.0, z / zb ) },
            { QVector3D( xb,  yb,  z ), QVector3D( 1.0, 1.0, z / zb ) },
            { QVector3D( 0.0, yb,  z ), QVector3D( 0.0, 1.0, z / zb ) }
        };
        // Transfer vertex data to VBO 1
        glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 1 ] );
        glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verticesAxial, GL_STATIC_DRAW );
    }

    if ( yi != m_yOld || ybi != m_ybOld )
    {
        VertexData verticesCoronal[] =
        {
            { QVector3D( 0.0, y, 0.0 ), QVector3D( 0.0, y / yb, 0.0 ) },
            { QVector3D( xb,  y, 0.0 ), QVector3D( 1.0, y / yb, 0.0 ) },
            { QVector3D( xb,  y, zb  ), QVector3D( 1.0, y / yb, 1.0 ) },
            { QVector3D( 0.0, y, zb  ), QVector3D( 0.0, y / yb, 1.0 ) }
        };

        // Transfer vertex data to VBO 2
        glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 2 ] );
        glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verticesCoronal, GL_STATIC_DRAW );
    }

    if ( xi != m_xOld  || xbi != m_xbOld )
    {
        VertexData verticesSagittal[] =
        {
            { QVector3D( x, 0.0, 0.0 ), QVector3D( x / xb, 0.0, 0.0 ) },
            { QVector3D( x, yb,  0.0 ), QVector3D( x / xb, 1.0, 0.0 ) },
            { QVector3D( x, yb,  zb  ), QVector3D( x / xb, 1.0, 1.0 ) },
            { QVector3D( x, 0.0, zb  ), QVector3D( x / xb, 0.0, 1.0 ) }
        };
        // Transfer vertex data to VBO 3
        glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 3 ] );
        glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verticesSagittal, GL_STATIC_DRAW );
    }

    m_xOld = xi;
    m_yOld = yi;
    m_zOld = zi;
    m_xbOld = xbi;
    m_ybOld = ybi;
    m_zbOld = zbi;
}

void SliceRenderer::setupTextures()
{
    GLFunctions::setupTextures( model() );
}

void SliceRenderer::setShaderVars()
{
    GLFunctions::setSliceShaderVars( m_program, model() );
}

void SliceRenderer::draw( QMatrix4x4 mvp_matrix )
{
    //qDebug() << "main gl draw";
    setupTextures();

    glColor4f( 0.0, 0.0, 0.0, 1.0 );

    // Set modelview-projection matrix
    m_program->setUniformValue( "mvp_matrix", mvp_matrix );

    initGeometry();

    drawAxial();
    drawCoronal();
    drawSagittal();
}

void SliceRenderer::drawAxial()
{
    // Tell OpenGL which VBOs to use
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIds[ 0 ] );
    glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 1 ] );
    setShaderVars();

    // Draw cube geometry using indices from VBO 0
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
}

void SliceRenderer::drawCoronal()
{
    // Tell OpenGL which VBOs to use
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIds[ 0 ] );
    glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 2 ] );
    setShaderVars();
    // Draw cube geometry using indices from VBO 0
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
}

void SliceRenderer::drawSagittal()
{
    // Tell OpenGL which VBOs to use
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIds[ 0 ] );
    glBindBuffer( GL_ARRAY_BUFFER, vboIds[ 3 ] );
    setShaderVars();
    // Draw cube geometry using indices from VBO 0
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2017, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "GafferUI/PlugAdder.h"
#include "GafferUI/SpacerGadget.h"
#include "GafferUI/StandardNodeGadget.h"
#include "GafferUI/TextGadget.h"

#include "Gaffer/BoxIO.h"
#include "Gaffer/Metadata.h"
#include "Gaffer/ScriptNode.h"
#include "Gaffer/StringPlug.h"
#include "Gaffer/UndoScope.h"

#include "boost/algorithm/string/replace.hpp"
#include "boost/bind.hpp"

using namespace IECore;
using namespace Gaffer;
using namespace GafferUI;

//////////////////////////////////////////////////////////////////////////
// PlugAdder
//////////////////////////////////////////////////////////////////////////

namespace
{

class BoxIOPlugAdder : public PlugAdder
{

	public :

		BoxIOPlugAdder( BoxIOPtr boxIO )
			:	m_boxIO( boxIO )
		{
			m_boxIO->childAddedSignal().connect( boost::bind( &BoxIOPlugAdder::childAdded, this ) );
			m_boxIO->childRemovedSignal().connect( boost::bind( &BoxIOPlugAdder::childRemoved, this ) );
			updateVisibility();
		}

	protected :

		bool canCreateConnection( const Plug *endpoint ) const override
		{
			if( !PlugAdder::canCreateConnection( endpoint ) )
			{
				return false;
			}

			return endpoint->direction() == m_boxIO->direction();
		}

		void createConnection( Plug *endpoint ) override
		{
			std::string name = endpoint->relativeName( endpoint->node() );
			boost::replace_all( name, ".", "_" );
			m_boxIO->namePlug()->setValue( name );

			m_boxIO->setup( endpoint );

			applyEdgeMetadata( m_boxIO->plug() );
			if( m_boxIO->promotedPlug() )
			{
				applyEdgeMetadata( m_boxIO->promotedPlug(), /* opposite = */ true );
			}

			if( m_boxIO->direction() == Plug::In )
			{
				endpoint->setInput( m_boxIO->plug() );
			}
			else
			{
				m_boxIO->plug()->setInput( endpoint );
			}
		}

	private :

		void childAdded()
		{
			updateVisibility();
		}

		void childRemoved()
		{
			updateVisibility();
		}

		void updateVisibility()
		{
			setVisible( !m_boxIO->plug() );
		}

		BoxIOPtr m_boxIO;

};

} // namespace

//////////////////////////////////////////////////////////////////////////
// StringPlugValueGadget
//////////////////////////////////////////////////////////////////////////

namespace
{

class NameGadget : public TextGadget
{

	public :

		NameGadget( BoxIOPtr boxIO )
			:	TextGadget( boxIO->namePlug()->getValue() ), m_boxIO( boxIO )
		{
			boxIO->plugSetSignal().connect( boost::bind( &NameGadget::plugSet, this, ::_1 ) );
		}

	private :

		void plugSet( const Plug *plug )
		{
			if( plug == m_boxIO->namePlug() )
			{
				setText( m_boxIO->namePlug()->getValue() );
			}
		}

		BoxIOPtr m_boxIO;

};

} // namespace

//////////////////////////////////////////////////////////////////////////
// NodeGadget
//////////////////////////////////////////////////////////////////////////

namespace
{

struct BoxIONodeGadgetCreator
{

	BoxIONodeGadgetCreator()
	{
		NodeGadget::registerNodeGadget( BoxIO::staticTypeId(), *this );
	}

	NodeGadgetPtr operator()( NodePtr node )
	{
		BoxIOPtr boxIO = runTimeCast<BoxIO>( node );
		if( !boxIO )
		{
			throw Exception( "Expected a BoxIO node" );
		}
		StandardNodeGadgetPtr result = new StandardNodeGadget( node );
		result->setEdgeGadget( StandardNodeGadget::LeftEdge, new BoxIOPlugAdder( boxIO ) );
		result->setEdgeGadget( StandardNodeGadget::RightEdge, new BoxIOPlugAdder( boxIO ) );
		result->setEdgeGadget( StandardNodeGadget::BottomEdge, new BoxIOPlugAdder( boxIO ) );
		result->setEdgeGadget( StandardNodeGadget::TopEdge, new BoxIOPlugAdder( boxIO ) );
		result->setContents( new NameGadget( boxIO ) );
		return result;
	}

};

BoxIONodeGadgetCreator g_boxIONodeGadgetCreator;

} // namespace
<commit_msg>BoxIONodeGadget : Apply edge metadata to passThrough plug<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2017, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "GafferUI/PlugAdder.h"
#include "GafferUI/SpacerGadget.h"
#include "GafferUI/StandardNodeGadget.h"
#include "GafferUI/TextGadget.h"

#include "Gaffer/BoxIO.h"
#include "Gaffer/BoxOut.h"
#include "Gaffer/Metadata.h"
#include "Gaffer/ScriptNode.h"
#include "Gaffer/StringPlug.h"
#include "Gaffer/UndoScope.h"

#include "boost/algorithm/string/replace.hpp"
#include "boost/bind.hpp"

using namespace IECore;
using namespace Gaffer;
using namespace GafferUI;

//////////////////////////////////////////////////////////////////////////
// PlugAdder
//////////////////////////////////////////////////////////////////////////

namespace
{

class BoxIOPlugAdder : public PlugAdder
{

	public :

		BoxIOPlugAdder( BoxIOPtr boxIO )
			:	m_boxIO( boxIO )
		{
			m_boxIO->childAddedSignal().connect( boost::bind( &BoxIOPlugAdder::childAdded, this ) );
			m_boxIO->childRemovedSignal().connect( boost::bind( &BoxIOPlugAdder::childRemoved, this ) );
			updateVisibility();
		}

	protected :

		bool canCreateConnection( const Plug *endpoint ) const override
		{
			if( !PlugAdder::canCreateConnection( endpoint ) )
			{
				return false;
			}

			return endpoint->direction() == m_boxIO->direction();
		}

		void createConnection( Plug *endpoint ) override
		{
			std::string name = endpoint->relativeName( endpoint->node() );
			boost::replace_all( name, ".", "_" );
			m_boxIO->namePlug()->setValue( name );

			m_boxIO->setup( endpoint );

			applyEdgeMetadata( m_boxIO->plug() );
			if( BoxOut *boxOut = runTimeCast<BoxOut>( m_boxIO.get() ) )
			{
				applyEdgeMetadata( boxOut->passThroughPlug() );
			}
			if( m_boxIO->promotedPlug() )
			{
				applyEdgeMetadata( m_boxIO->promotedPlug(), /* opposite = */ true );
			}

			if( m_boxIO->direction() == Plug::In )
			{
				endpoint->setInput( m_boxIO->plug() );
			}
			else
			{
				m_boxIO->plug()->setInput( endpoint );
			}
		}

	private :

		void childAdded()
		{
			updateVisibility();
		}

		void childRemoved()
		{
			updateVisibility();
		}

		void updateVisibility()
		{
			setVisible( !m_boxIO->plug() );
		}

		BoxIOPtr m_boxIO;

};

} // namespace

//////////////////////////////////////////////////////////////////////////
// StringPlugValueGadget
//////////////////////////////////////////////////////////////////////////

namespace
{

class NameGadget : public TextGadget
{

	public :

		NameGadget( BoxIOPtr boxIO )
			:	TextGadget( boxIO->namePlug()->getValue() ), m_boxIO( boxIO )
		{
			boxIO->plugSetSignal().connect( boost::bind( &NameGadget::plugSet, this, ::_1 ) );
		}

	private :

		void plugSet( const Plug *plug )
		{
			if( plug == m_boxIO->namePlug() )
			{
				setText( m_boxIO->namePlug()->getValue() );
			}
		}

		BoxIOPtr m_boxIO;

};

} // namespace

//////////////////////////////////////////////////////////////////////////
// NodeGadget
//////////////////////////////////////////////////////////////////////////

namespace
{

struct BoxIONodeGadgetCreator
{

	BoxIONodeGadgetCreator()
	{
		NodeGadget::registerNodeGadget( BoxIO::staticTypeId(), *this );
	}

	NodeGadgetPtr operator()( NodePtr node )
	{
		BoxIOPtr boxIO = runTimeCast<BoxIO>( node );
		if( !boxIO )
		{
			throw Exception( "Expected a BoxIO node" );
		}
		StandardNodeGadgetPtr result = new StandardNodeGadget( node );
		result->setEdgeGadget( StandardNodeGadget::LeftEdge, new BoxIOPlugAdder( boxIO ) );
		result->setEdgeGadget( StandardNodeGadget::RightEdge, new BoxIOPlugAdder( boxIO ) );
		result->setEdgeGadget( StandardNodeGadget::BottomEdge, new BoxIOPlugAdder( boxIO ) );
		result->setEdgeGadget( StandardNodeGadget::TopEdge, new BoxIOPlugAdder( boxIO ) );
		result->setContents( new NameGadget( boxIO ) );
		return result;
	}

};

BoxIONodeGadgetCreator g_boxIONodeGadgetCreator;

} // namespace
<|endoftext|>


<commit_before>//===-- X86ShuffleDecodeConstantPool.cpp - X86 shuffle decode -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Define several functions to decode x86 specific shuffle semantics using
// constants from the constant pool.
//
//===----------------------------------------------------------------------===//

#include "X86ShuffleDecodeConstantPool.h"
#include "Utils/X86ShuffleDecode.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/IR/Constants.h"

//===----------------------------------------------------------------------===//
//  Vector Mask Decoding
//===----------------------------------------------------------------------===//

namespace llvm {

void DecodePSHUFBMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  // It is not an error for the PSHUFB mask to not be a vector of i8 because the
  // constant pool uniques constants by their bit representation.
  // e.g. the following take up the same space in the constant pool:
  //   i128 -170141183420855150465331762880109871104
  //
  //   <2 x i64> <i64 -9223372034707292160, i64 -9223372034707292160>
  //
  //   <4 x i32> <i32 -2147483648, i32 -2147483648,
  //              i32 -2147483648, i32 -2147483648>

#ifndef NDEBUG
  unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
  assert(MaskTySize == 128 || MaskTySize == 256 || MaskTySize == 512);
#endif

  if (!MaskTy->isVectorTy())
    return;
  int NumElts = MaskTy->getVectorNumElements();

  Type *EltTy = MaskTy->getVectorElementType();
  if (!EltTy->isIntegerTy())
    return;

  // The shuffle mask requires a byte vector - decode cases with
  // wider elements as well.
  unsigned BitWidth = cast<IntegerType>(EltTy)->getBitWidth();
  if ((BitWidth % 8) != 0)
    return;

  int Scale = BitWidth / 8;
  int NumBytes = NumElts * Scale;
  ShuffleMask.reserve(NumBytes);

  for (int i = 0; i != NumElts; ++i) {
    Constant *COp = C->getAggregateElement(i);
    if (!COp) {
      ShuffleMask.clear();
      return;
    } else if (isa<UndefValue>(COp)) {
      ShuffleMask.append(Scale, SM_SentinelUndef);
      continue;
    }

    APInt APElt = cast<ConstantInt>(COp)->getValue();
    for (int j = 0; j != Scale; ++j) {
      // For AVX vectors with 32 bytes the base of the shuffle is the 16-byte
      // lane of the vector we're inside.
      int Base = ((i * Scale) + j) & ~0xf;

      uint64_t Element = APElt.getLoBits(8).getZExtValue();
      APElt = APElt.lshr(8);

      // If the high bit (7) of the byte is set, the element is zeroed.
      if (Element & (1 << 7))
        ShuffleMask.push_back(SM_SentinelZero);
      else {
        // Only the least significant 4 bits of the byte are used.
        int Index = Base + (Element & 0xf);
        ShuffleMask.push_back(Index);
      }
    }
  }

  assert(NumBytes == (int)ShuffleMask.size() && "Unexpected shuffle mask size");
}

void DecodeVPERMILPMask(const Constant *C, unsigned ElSize,
                        SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  // It is not an error for the PSHUFB mask to not be a vector of i8 because the
  // constant pool uniques constants by their bit representation.
  // e.g. the following take up the same space in the constant pool:
  //   i128 -170141183420855150465331762880109871104
  //
  //   <2 x i64> <i64 -9223372034707292160, i64 -9223372034707292160>
  //
  //   <4 x i32> <i32 -2147483648, i32 -2147483648,
  //              i32 -2147483648, i32 -2147483648>

  if (ElSize != 32 && ElSize != 64)
    return;

  unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
  if (MaskTySize != 128 && MaskTySize != 256 && MaskTySize != 512)
    return;

  // Only support vector types.
  if (!MaskTy->isVectorTy())
    return;

  // Make sure its an integer type.
  Type *VecEltTy = MaskTy->getVectorElementType();
  if (!VecEltTy->isIntegerTy())
    return;

  // Support any element type from byte up to element size.
  // This is necessary primarily because 64-bit elements get split to 32-bit
  // in the constant pool on 32-bit target.
  unsigned EltTySize = VecEltTy->getIntegerBitWidth();
  if (EltTySize < 8 || EltTySize > ElSize)
    return;

  unsigned NumElements = MaskTySize / ElSize;
  assert((NumElements == 2 || NumElements == 4 || NumElements == 8 ||
          NumElements == 16) &&
         "Unexpected number of vector elements.");
  ShuffleMask.reserve(NumElements);
  unsigned NumElementsPerLane = 128 / ElSize;
  unsigned Factor = ElSize / EltTySize;

  for (unsigned i = 0; i < NumElements; ++i) {
    Constant *COp = C->getAggregateElement(i * Factor);
    if (!COp) {
      ShuffleMask.clear();
      return;
    } else if (isa<UndefValue>(COp)) {
      ShuffleMask.push_back(SM_SentinelUndef);
      continue;
    }
    int Index = i & ~(NumElementsPerLane - 1);
    uint64_t Element = cast<ConstantInt>(COp)->getZExtValue();
    if (ElSize == 64)
      Index += (Element >> 1) & 0x1;
    else
      Index += Element & 0x3;
    ShuffleMask.push_back(Index);
  }

  // TODO: Handle funny-looking vectors too.
}

void DecodeVPERMIL2PMask(const Constant *C, unsigned M2Z, unsigned ElSize,
                         SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();

  unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
  if (MaskTySize != 128 && MaskTySize != 256)
    return;

  // Only support vector types.
  if (!MaskTy->isVectorTy())
    return;

  // Make sure its an integer type.
  Type *VecEltTy = MaskTy->getVectorElementType();
  if (!VecEltTy->isIntegerTy())
    return;

  // Support any element type from byte up to element size.
  // This is necessary primarily because 64-bit elements get split to 32-bit
  // in the constant pool on 32-bit target.
  unsigned EltTySize = VecEltTy->getIntegerBitWidth();
  if (EltTySize < 8 || EltTySize > ElSize)
    return;

  unsigned NumElements = MaskTySize / ElSize;
  assert((NumElements == 2 || NumElements == 4 || NumElements == 8) &&
         "Unexpected number of vector elements.");
  ShuffleMask.reserve(NumElements);
  unsigned NumElementsPerLane = 128 / ElSize;
  unsigned Factor = ElSize / EltTySize;

  for (unsigned i = 0; i < NumElements; ++i) {
    Constant *COp = C->getAggregateElement(i * Factor);
    if (!COp) {
      ShuffleMask.clear();
      return;
    } else if (isa<UndefValue>(COp)) {
      ShuffleMask.push_back(SM_SentinelUndef);
      continue;
    }

    // VPERMIL2 Operation.
    // Bits[3] - Match Bit.
    // Bits[2:1] - (Per Lane) PD Shuffle Mask.
    // Bits[2:0] - (Per Lane) PS Shuffle Mask.
    uint64_t Selector = cast<ConstantInt>(COp)->getZExtValue();
    unsigned MatchBit = (Selector >> 3) & 0x1;

    // M2Z[0:1]     MatchBit
    //   0Xb           X        Source selected by Selector index.
    //   10b           0        Source selected by Selector index.
    //   10b           1        Zero.
    //   11b           0        Zero.
    //   11b           1        Source selected by Selector index.
    if ((M2Z & 0x2) != 0u && MatchBit != (M2Z & 0x1)) {
      ShuffleMask.push_back(SM_SentinelZero);
      continue;
    }

    int Index = i & ~(NumElementsPerLane - 1);
    if (ElSize == 64)
      Index += (Selector >> 1) & 0x1;
    else
      Index += Selector & 0x3;

    int Src = (Selector >> 2) & 0x1;
    Index += Src * NumElements;
    ShuffleMask.push_back(Index);
  }

  // TODO: Handle funny-looking vectors too.
}

void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  assert(MaskTy->getPrimitiveSizeInBits() == 128);

  // Only support vector types.
  if (!MaskTy->isVectorTy())
    return;

  // Make sure its an integer type.
  Type *VecEltTy = MaskTy->getVectorElementType();
  if (!VecEltTy->isIntegerTy())
    return;

  // The shuffle mask requires a byte vector - decode cases with
  // wider elements as well.
  unsigned BitWidth = cast<IntegerType>(VecEltTy)->getBitWidth();
  if ((BitWidth % 8) != 0)
    return;

  int NumElts = MaskTy->getVectorNumElements();
  int Scale = BitWidth / 8;
  int NumBytes = NumElts * Scale;
  ShuffleMask.reserve(NumBytes);

  for (int i = 0; i != NumElts; ++i) {
    Constant *COp = C->getAggregateElement(i);
    if (!COp) {
      ShuffleMask.clear();
      return;
    } else if (isa<UndefValue>(COp)) {
      ShuffleMask.append(Scale, SM_SentinelUndef);
      continue;
    }

    // VPPERM Operation
    // Bits[4:0] - Byte Index (0 - 31)
    // Bits[7:5] - Permute Operation
    //
    // Permute Operation:
    // 0 - Source byte (no logical operation).
    // 1 - Invert source byte.
    // 2 - Bit reverse of source byte.
    // 3 - Bit reverse of inverted source byte.
    // 4 - 00h (zero - fill).
    // 5 - FFh (ones - fill).
    // 6 - Most significant bit of source byte replicated in all bit positions.
    // 7 - Invert most significant bit of source byte and replicate in all bit positions.
    APInt MaskElt = cast<ConstantInt>(COp)->getValue();
    for (int j = 0; j != Scale; ++j) {
      APInt Index = MaskElt.getLoBits(5);
      APInt PermuteOp = MaskElt.lshr(5).getLoBits(3);
      MaskElt = MaskElt.lshr(8);

      if (PermuteOp == 4) {
        ShuffleMask.push_back(SM_SentinelZero);
        continue;
      }
      if (PermuteOp != 0) {
        ShuffleMask.clear();
        return;
      }
      ShuffleMask.push_back((int)Index.getZExtValue());
    }
  }

  assert(NumBytes == (int)ShuffleMask.size() && "Unexpected shuffle mask size");
}

void DecodeVPERMVMask(const Constant *C, MVT VT,
                      SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  if (MaskTy->isVectorTy()) {
    unsigned NumElements = MaskTy->getVectorNumElements();
    if (NumElements == VT.getVectorNumElements()) {
      unsigned EltMaskSize = Log2_64(NumElements);
      for (unsigned i = 0; i < NumElements; ++i) {
        Constant *COp = C->getAggregateElement(i);
        if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp))) {
          ShuffleMask.clear();
          return;
        }
        if (isa<UndefValue>(COp))
          ShuffleMask.push_back(SM_SentinelUndef);
        else {
          APInt Element = cast<ConstantInt>(COp)->getValue();
          Element = Element.getLoBits(EltMaskSize);
          ShuffleMask.push_back(Element.getZExtValue());
        }
      }
    }
    return;
  }
  // Scalar value; just broadcast it
  if (!isa<ConstantInt>(C))
    return;
  uint64_t Element = cast<ConstantInt>(C)->getZExtValue();
  int NumElements = VT.getVectorNumElements();
  Element &= (1 << NumElements) - 1;
  for (int i = 0; i < NumElements; ++i)
    ShuffleMask.push_back(Element);
}

void DecodeVPERMV3Mask(const Constant *C, MVT VT,
                       SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  unsigned NumElements = MaskTy->getVectorNumElements();
  if (NumElements == VT.getVectorNumElements()) {
    unsigned EltMaskSize = Log2_64(NumElements * 2);
    for (unsigned i = 0; i < NumElements; ++i) {
      Constant *COp = C->getAggregateElement(i);
      if (!COp) {
        ShuffleMask.clear();
        return;
      }
      if (isa<UndefValue>(COp))
        ShuffleMask.push_back(SM_SentinelUndef);
      else {
        APInt Element = cast<ConstantInt>(COp)->getValue();
        Element = Element.getLoBits(EltMaskSize);
        ShuffleMask.push_back(Element.getZExtValue());
      }
    }
  }
}
} // llvm namespace
<commit_msg>[X86][SSE] Added common helper for shuffle mask constant pool decodes.<commit_after>//===-- X86ShuffleDecodeConstantPool.cpp - X86 shuffle decode -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Define several functions to decode x86 specific shuffle semantics using
// constants from the constant pool.
//
//===----------------------------------------------------------------------===//

#include "X86ShuffleDecodeConstantPool.h"
#include "Utils/X86ShuffleDecode.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/IR/Constants.h"

//===----------------------------------------------------------------------===//
//  Vector Mask Decoding
//===----------------------------------------------------------------------===//

namespace llvm {

static bool extractConstantMask(const Constant *C, unsigned MaskEltSizeInBits,
                                SmallBitVector &UndefElts,
                                SmallVectorImpl<uint64_t> &RawMask) {
  // It is not an error for shuffle masks to not be a vector of
  // MaskEltSizeInBits because the constant pool uniques constants by their
  // bit representation.
  // e.g. the following take up the same space in the constant pool:
  //   i128 -170141183420855150465331762880109871104
  //
  //   <2 x i64> <i64 -9223372034707292160, i64 -9223372034707292160>
  //
  //   <4 x i32> <i32 -2147483648, i32 -2147483648,
  //              i32 -2147483648, i32 -2147483648>
  Type *CstTy = C->getType();
  if (!CstTy->isVectorTy())
    return false;

  Type *CstEltTy = CstTy->getVectorElementType();
  if (!CstEltTy->isIntegerTy())
    return false;

  unsigned CstSizeInBits = CstTy->getPrimitiveSizeInBits();
  unsigned CstEltSizeInBits = CstTy->getScalarSizeInBits();
  unsigned NumCstElts = CstTy->getVectorNumElements();

  // Extract all the undef/constant element data and pack into single bitsets.
  APInt UndefBits(CstSizeInBits, 0);
  APInt MaskBits(CstSizeInBits, 0);
  for (unsigned i = 0; i != NumCstElts; ++i) {
    Constant *COp = C->getAggregateElement(i);
    if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp)))
      return false;

    if (isa<UndefValue>(COp)) {
      APInt EltUndef = APInt::getLowBitsSet(CstSizeInBits, CstEltSizeInBits);
      UndefBits |= EltUndef.shl(i * CstEltSizeInBits);
      continue;
    }

    APInt EltBits = cast<ConstantInt>(COp)->getValue();
    EltBits = EltBits.zextOrTrunc(CstSizeInBits);
    MaskBits |= EltBits.shl(i * CstEltSizeInBits);
  }

  // Now extract the undef/constant bit data into the raw shuffle masks.
  assert((CstSizeInBits % MaskEltSizeInBits) == 0 && "");
  unsigned NumMaskElts = CstSizeInBits / MaskEltSizeInBits;

  UndefElts = SmallBitVector(NumMaskElts, false);
  RawMask.resize(NumMaskElts, 0);

  for (unsigned i = 0; i != NumMaskElts; ++i) {
    APInt EltUndef = UndefBits.lshr(i * MaskEltSizeInBits);
    EltUndef = EltUndef.zextOrTrunc(MaskEltSizeInBits);

    // Only treat the element as UNDEF if all bits are UNDEF, otherwise
    // treat it as zero.
    if (EltUndef.countPopulation() == MaskEltSizeInBits) {
      UndefElts[i] = true;
      RawMask[i] = 0;
      continue;
    }

    APInt EltBits = MaskBits.lshr(i * MaskEltSizeInBits);
    EltBits = EltBits.zextOrTrunc(MaskEltSizeInBits);
    RawMask[i] = EltBits.getZExtValue();
  }

  return true;
}

void DecodePSHUFBMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
  assert(MaskTySize == 128 || MaskTySize == 256 || MaskTySize == 512);

  // The shuffle mask requires a byte vector.
  SmallBitVector UndefElts;
  SmallVector<uint64_t, 32> RawMask;
  if (!extractConstantMask(C, 8, UndefElts, RawMask))
    return;

  unsigned NumElts = RawMask.size();
  assert((NumElts == 16 || NumElts == 32 || NumElts == 64) &&
         "Unexpected number of vector elements.");

  for (unsigned i = 0; i != NumElts; ++i) {
    if (UndefElts[i]) {
      ShuffleMask.push_back(SM_SentinelUndef);
      continue;
    }

    uint64_t Element = RawMask[i];
    // If the high bit (7) of the byte is set, the element is zeroed.
    if (Element & (1 << 7))
      ShuffleMask.push_back(SM_SentinelZero);
    else {
      // For AVX vectors with 32 bytes the base of the shuffle is the 16-byte
      // lane of the vector we're inside.
      unsigned Base = i & ~0xf;

      // Only the least significant 4 bits of the byte are used.
      int Index = Base + (Element & 0xf);
      ShuffleMask.push_back(Index);
    }
  }
}

void DecodeVPERMILPMask(const Constant *C, unsigned ElSize,
                        SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
  assert(MaskTySize == 128 || MaskTySize == 256 || MaskTySize == 512);
  assert(ElSize == 32 || ElSize == 64);

  // The shuffle mask requires elements the same size as the target.
  SmallBitVector UndefElts;
  SmallVector<uint64_t, 8> RawMask;
  if (!extractConstantMask(C, ElSize, UndefElts, RawMask))
    return;

  unsigned NumElts = RawMask.size();
  unsigned NumEltsPerLane = 128 / ElSize;
  assert((NumElts == 2 || NumElts == 4 || NumElts == 8 || NumElts == 16) &&
         "Unexpected number of vector elements.");

  for (unsigned i = 0; i != NumElts; ++i) {
    if (UndefElts[i]) {
      ShuffleMask.push_back(SM_SentinelUndef);
      continue;
    }

    int Index = i & ~(NumEltsPerLane - 1);
    uint64_t Element = RawMask[i];
    if (ElSize == 64)
      Index += (Element >> 1) & 0x1;
    else
      Index += Element & 0x3;

    ShuffleMask.push_back(Index);
  }
}

void DecodeVPERMIL2PMask(const Constant *C, unsigned M2Z, unsigned ElSize,
                         SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  unsigned MaskTySize = MaskTy->getPrimitiveSizeInBits();
  assert(MaskTySize == 128 || MaskTySize == 256);

  // The shuffle mask requires elements the same size as the target.
  SmallBitVector UndefElts;
  SmallVector<uint64_t, 8> RawMask;
  if (!extractConstantMask(C, ElSize, UndefElts, RawMask))
    return;

  unsigned NumElts = RawMask.size();
  unsigned NumEltsPerLane = 128 / ElSize;
  assert((NumElts == 2 || NumElts == 4 || NumElts == 8) &&
         "Unexpected number of vector elements.");

  for (unsigned i = 0; i != NumElts; ++i) {
    if (UndefElts[i]) {
      ShuffleMask.push_back(SM_SentinelUndef);
      continue;
    }

    // VPERMIL2 Operation.
    // Bits[3] - Match Bit.
    // Bits[2:1] - (Per Lane) PD Shuffle Mask.
    // Bits[2:0] - (Per Lane) PS Shuffle Mask.
    uint64_t Selector = RawMask[i];
    unsigned MatchBit = (Selector >> 3) & 0x1;

    // M2Z[0:1]     MatchBit
    //   0Xb           X        Source selected by Selector index.
    //   10b           0        Source selected by Selector index.
    //   10b           1        Zero.
    //   11b           0        Zero.
    //   11b           1        Source selected by Selector index.
    if ((M2Z & 0x2) != 0u && MatchBit != (M2Z & 0x1)) {
      ShuffleMask.push_back(SM_SentinelZero);
      continue;
    }

    int Index = i & ~(NumEltsPerLane - 1);
    if (ElSize == 64)
      Index += (Selector >> 1) & 0x1;
    else
      Index += Selector & 0x3;

    int Src = (Selector >> 2) & 0x1;
    Index += Src * NumElts;
    ShuffleMask.push_back(Index);
  }
}

void DecodeVPPERMMask(const Constant *C, SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  assert(MaskTy->getPrimitiveSizeInBits() == 128);

  // The shuffle mask requires a byte vector.
  SmallBitVector UndefElts;
  SmallVector<uint64_t, 32> RawMask;
  if (!extractConstantMask(C, 8, UndefElts, RawMask))
    return;

  unsigned NumElts = RawMask.size();
  assert(NumElts == 16 && "Unexpected number of vector elements.");

  for (unsigned i = 0; i != NumElts; ++i) {
    if (UndefElts[i]) {
      ShuffleMask.push_back(SM_SentinelUndef);
      continue;
    }

    // VPPERM Operation
    // Bits[4:0] - Byte Index (0 - 31)
    // Bits[7:5] - Permute Operation
    //
    // Permute Operation:
    // 0 - Source byte (no logical operation).
    // 1 - Invert source byte.
    // 2 - Bit reverse of source byte.
    // 3 - Bit reverse of inverted source byte.
    // 4 - 00h (zero - fill).
    // 5 - FFh (ones - fill).
    // 6 - Most significant bit of source byte replicated in all bit positions.
    // 7 - Invert most significant bit of source byte and replicate in all bit
    // positions.
    uint64_t Element = RawMask[i];
    uint64_t Index = Element & 0x1F;
    uint64_t PermuteOp = (Element >> 5) & 0x7;

    if (PermuteOp == 4) {
      ShuffleMask.push_back(SM_SentinelZero);
      continue;
    }
    if (PermuteOp != 0) {
      ShuffleMask.clear();
      return;
    }
    ShuffleMask.push_back((int)Index);
  }
}

void DecodeVPERMVMask(const Constant *C, MVT VT,
                      SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  if (MaskTy->isVectorTy()) {
    unsigned NumElements = MaskTy->getVectorNumElements();
    if (NumElements == VT.getVectorNumElements()) {
      unsigned EltMaskSize = Log2_64(NumElements);
      for (unsigned i = 0; i < NumElements; ++i) {
        Constant *COp = C->getAggregateElement(i);
        if (!COp || (!isa<UndefValue>(COp) && !isa<ConstantInt>(COp))) {
          ShuffleMask.clear();
          return;
        }
        if (isa<UndefValue>(COp))
          ShuffleMask.push_back(SM_SentinelUndef);
        else {
          APInt Element = cast<ConstantInt>(COp)->getValue();
          Element = Element.getLoBits(EltMaskSize);
          ShuffleMask.push_back(Element.getZExtValue());
        }
      }
    }
    return;
  }
  // Scalar value; just broadcast it
  if (!isa<ConstantInt>(C))
    return;
  uint64_t Element = cast<ConstantInt>(C)->getZExtValue();
  int NumElements = VT.getVectorNumElements();
  Element &= (1 << NumElements) - 1;
  for (int i = 0; i < NumElements; ++i)
    ShuffleMask.push_back(Element);
}

void DecodeVPERMV3Mask(const Constant *C, MVT VT,
                       SmallVectorImpl<int> &ShuffleMask) {
  Type *MaskTy = C->getType();
  unsigned NumElements = MaskTy->getVectorNumElements();
  if (NumElements == VT.getVectorNumElements()) {
    unsigned EltMaskSize = Log2_64(NumElements * 2);
    for (unsigned i = 0; i < NumElements; ++i) {
      Constant *COp = C->getAggregateElement(i);
      if (!COp) {
        ShuffleMask.clear();
        return;
      }
      if (isa<UndefValue>(COp))
        ShuffleMask.push_back(SM_SentinelUndef);
      else {
        APInt Element = cast<ConstantInt>(COp)->getValue();
        Element = Element.getLoBits(EltMaskSize);
        ShuffleMask.push_back(Element.getZExtValue());
      }
    }
  }
}
} // llvm namespace
<|endoftext|>