// 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 "ui/display/display.h"

#include <algorithm>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/icc_profile.h"

namespace display {
namespace {

constexpr int DEFAULT_BITS_PER_PIXEL = 24;
constexpr int DEFAULT_BITS_PER_COMPONENT = 8;

constexpr int HDR_BITS_PER_PIXEL = 48;
constexpr int HDR_BITS_PER_COMPONENT = 16;

// This variable tracks whether the forced device scale factor switch needs to
// be read from the command line, i.e. if it is set to -1 then the command line
// is checked.
int g_has_forced_device_scale_factor = -1;

// This variable caches the forced device scale factor value which is read off
// the command line. If the cache is invalidated by setting this variable to
// -1.0, we read the forced device scale factor again.
float g_forced_device_scale_factor = -1.0;

bool HasForceDeviceScaleFactorImpl() {
  return base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kForceDeviceScaleFactor);
}

float GetForcedDeviceScaleFactorImpl() {
  double scale_in_double = 1.0;
  if (HasForceDeviceScaleFactorImpl()) {
    std::string value =
        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kForceDeviceScaleFactor);
    if (!base::StringToDouble(value, &scale_in_double)) {
      LOG(ERROR) << "Failed to parse the default device scale factor:" << value;
      scale_in_double = 1.0;
    }
  }
  return static_cast<float>(scale_in_double);
}

int64_t internal_display_id_ = -1;

gfx::ColorSpace ForcedColorProfileStringToColorSpace(const std::string& value) {
  if (value == "srgb")
    return gfx::ColorSpace::CreateSRGB();
  if (value == "display-p3-d65")
    return gfx::ColorSpace::CreateDisplayP3D65();
  if (value == "scrgb-linear")
    return gfx::ColorSpace::CreateSCRGBLinear();
  if (value == "extended-srgb")
    return gfx::ColorSpace::CreateExtendedSRGB();
  if (value == "generic-rgb") {
    return gfx::ColorSpace(gfx::ColorSpace::PrimaryID::APPLE_GENERIC_RGB,
                           gfx::ColorSpace::TransferID::GAMMA18);
  }
  if (value == "color-spin-gamma24") {
    // Run this color profile through an ICC profile. The resulting color space
    // is slightly different from the input color space, and removing the ICC
    // profile would require rebaselineing many layout tests.
    gfx::ColorSpace color_space(
        gfx::ColorSpace::PrimaryID::WIDE_GAMUT_COLOR_SPIN,
        gfx::ColorSpace::TransferID::GAMMA24);
    return gfx::ICCProfile::FromParametricColorSpace(color_space)
        .GetColorSpace();
  }
  LOG(ERROR) << "Invalid forced color profile: \"" << value << "\"";
  return gfx::ColorSpace::CreateSRGB();
}

}  // namespace

bool CompareDisplayIds(int64_t id1, int64_t id2) {
  if (id1 == id2)
    return false;
  // Output index is stored in the first 8 bits. See GetDisplayIdFromEDID
  // in edid_parser.cc.
  int index_1 = id1 & 0xFF;
  int index_2 = id2 & 0xFF;
  DCHECK_NE(index_1, index_2) << id1 << " and " << id2;
  return Display::IsInternalDisplayId(id1) ||
         (index_1 < index_2 && !Display::IsInternalDisplayId(id2));
}

// static
float Display::GetForcedDeviceScaleFactor() {
  if (g_forced_device_scale_factor < 0)
    g_forced_device_scale_factor = GetForcedDeviceScaleFactorImpl();
  return g_forced_device_scale_factor;
}

// static
bool Display::HasForceDeviceScaleFactor() {
  if (g_has_forced_device_scale_factor == -1)
    g_has_forced_device_scale_factor = HasForceDeviceScaleFactorImpl();
  return !!g_has_forced_device_scale_factor;
}

// static
void Display::ResetForceDeviceScaleFactorForTesting() {
  g_has_forced_device_scale_factor = -1;
  g_forced_device_scale_factor = -1.0;
}

// static
void Display::SetForceDeviceScaleFactor(double dsf) {
  // Reset any previously set values and unset the flag.
  g_has_forced_device_scale_factor = -1;
  g_forced_device_scale_factor = -1.0;

  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
      switches::kForceDeviceScaleFactor, base::StringPrintf("%.2f", dsf));
}

// static
gfx::ColorSpace Display::GetForcedDisplayColorProfile() {
  DCHECK(HasForceDisplayColorProfile());
  std::string value =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kForceDisplayColorProfile);
  return ForcedColorProfileStringToColorSpace(value);
}

// static
bool Display::HasForceDisplayColorProfile() {
  return base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kForceDisplayColorProfile);
}

// static
gfx::ColorSpace Display::GetForcedRasterColorProfile() {
  DCHECK(HasForceRasterColorProfile());
  std::string value =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kForceRasterColorProfile);
  return ForcedColorProfileStringToColorSpace(value);
}

// static
bool Display::HasForceRasterColorProfile() {
  return base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kForceRasterColorProfile);
}

// static
bool Display::HasEnsureForcedColorProfile() {
  static bool has_ensure_forced_color_profile =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnsureForcedColorProfile);
  return has_ensure_forced_color_profile;
}

// static
display::Display::Rotation Display::DegreesToRotation(int degrees) {
  if (degrees == 0)
    return display::Display::ROTATE_0;
  if (degrees == 90)
    return display::Display::ROTATE_90;
  if (degrees == 180)
    return display::Display::ROTATE_180;
  if (degrees == 270)
    return display::Display::ROTATE_270;
  NOTREACHED();
  return display::Display::ROTATE_0;
}

// static
int Display::RotationToDegrees(display::Display::Rotation rotation) {
  switch (rotation) {
    case display::Display::ROTATE_0:
      return 0;
    case display::Display::ROTATE_90:
      return 90;
    case display::Display::ROTATE_180:
      return 180;
    case display::Display::ROTATE_270:
      return 270;
  }
  NOTREACHED();
  return 0;
}

// static
bool Display::IsValidRotation(int degrees) {
  return degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270;
}

Display::Display() : Display(kInvalidDisplayId) {}

Display::Display(int64_t id) : Display(id, gfx::Rect()) {}

Display::Display(int64_t id, const gfx::Rect& bounds)
    : id_(id),
      bounds_(bounds),
      work_area_(bounds),
      device_scale_factor_(GetForcedDeviceScaleFactor()),
      color_space_(gfx::ColorSpace::CreateSRGB()),
      color_depth_(DEFAULT_BITS_PER_PIXEL),
      depth_per_component_(DEFAULT_BITS_PER_COMPONENT) {
  if (HasForceDisplayColorProfile())
    SetColorSpaceAndDepth(GetForcedDisplayColorProfile());
#if defined(USE_AURA)
  SetScaleAndBounds(device_scale_factor_, bounds);
#endif
}

Display::Display(const Display& other) = default;

Display::~Display() {}

// static
Display Display::GetDefaultDisplay() {
  return Display(kDefaultDisplayId, gfx::Rect(0, 0, 1920, 1080));
}

int Display::RotationAsDegree() const {
  switch (rotation_) {
    case ROTATE_0:
      return 0;
    case ROTATE_90:
      return 90;
    case ROTATE_180:
      return 180;
    case ROTATE_270:
      return 270;
  }
  NOTREACHED();
  return 0;
}

void Display::SetRotationAsDegree(int rotation) {
  switch (rotation) {
    case 0:
      rotation_ = ROTATE_0;
      break;
    case 90:
      rotation_ = ROTATE_90;
      break;
    case 180:
      rotation_ = ROTATE_180;
      break;
    case 270:
      rotation_ = ROTATE_270;
      break;
    default:
      // We should not reach that but we will just ignore the call if we do.
      NOTREACHED();
  }
}

gfx::Insets Display::GetWorkAreaInsets() const {
  return gfx::Insets(work_area_.y() - bounds_.y(), work_area_.x() - bounds_.x(),
                     bounds_.bottom() - work_area_.bottom(),
                     bounds_.right() - work_area_.right());
}

void Display::SetScaleAndBounds(float device_scale_factor,
                                const gfx::Rect& bounds_in_pixel) {
  gfx::Insets insets = bounds_.InsetsFrom(work_area_);
  if (!HasForceDeviceScaleFactor()) {
#if defined(OS_MACOSX)
    // Unless an explicit scale factor was provided for testing, ensure the
    // scale is integral.
    device_scale_factor = static_cast<int>(device_scale_factor);
#endif
    device_scale_factor_ = device_scale_factor;
  }
  device_scale_factor_ = std::max(0.5f, device_scale_factor_);
  bounds_ = gfx::Rect(gfx::ScaleToFlooredPoint(bounds_in_pixel.origin(),
                                               1.0f / device_scale_factor_),
                      gfx::ScaleToFlooredSize(bounds_in_pixel.size(),
                                              1.0f / device_scale_factor_));
  size_in_pixels_ = bounds_in_pixel.size();
  UpdateWorkAreaFromInsets(insets);
}

void Display::SetSize(const gfx::Size& size_in_pixel) {
  gfx::Point origin = bounds_.origin();
#if defined(USE_AURA)
  origin = gfx::ScaleToFlooredPoint(origin, device_scale_factor_);
#endif
  SetScaleAndBounds(device_scale_factor_, gfx::Rect(origin, size_in_pixel));
}

void Display::SetColorSpaceAndDepth(const gfx::ColorSpace& color_space) {
  color_space_ = color_space;
  if (color_space_.IsHDR()) {
    color_depth_ = HDR_BITS_PER_PIXEL;
    depth_per_component_ = HDR_BITS_PER_COMPONENT;
  } else {
    color_depth_ = DEFAULT_BITS_PER_PIXEL;
    depth_per_component_ = DEFAULT_BITS_PER_COMPONENT;
  }
}

void Display::UpdateWorkAreaFromInsets(const gfx::Insets& insets) {
  work_area_ = bounds_;
  work_area_.Inset(insets);
}

gfx::Size Display::GetSizeInPixel() const {
  if (!size_in_pixels_.IsEmpty())
    return size_in_pixels_;
  return gfx::ScaleToFlooredSize(size(), device_scale_factor_);
}

std::string Display::ToString() const {
  return base::StringPrintf(
      "Display[%lld] bounds=[%s], workarea=[%s], scale=%g, %s.",
      static_cast<long long int>(id_), bounds_.ToString().c_str(),
      work_area_.ToString().c_str(), device_scale_factor_,
      IsInternal() ? "internal" : "external");
}

bool Display::IsInternal() const {
  return is_valid() && (id_ == internal_display_id_);
}

// static
int64_t Display::InternalDisplayId() {
  DCHECK_NE(kInvalidDisplayId, internal_display_id_);
  return internal_display_id_;
}

// static
void Display::SetInternalDisplayId(int64_t internal_display_id) {
  internal_display_id_ = internal_display_id;
}

// static
bool Display::IsInternalDisplayId(int64_t display_id) {
  DCHECK_NE(kInvalidDisplayId, display_id);
  return HasInternalDisplay() && internal_display_id_ == display_id;
}

// static
bool Display::HasInternalDisplay() {
  return internal_display_id_ != kInvalidDisplayId;
}

bool Display::operator==(const Display& rhs) const {
  return id_ == rhs.id_ && bounds_ == rhs.bounds_ &&
         size_in_pixels_ == rhs.size_in_pixels_ &&
         work_area_ == rhs.work_area_ &&
         device_scale_factor_ == rhs.device_scale_factor_ &&
         rotation_ == rhs.rotation_ && touch_support_ == rhs.touch_support_ &&
         accelerometer_support_ == rhs.accelerometer_support_ &&
         maximum_cursor_size_ == rhs.maximum_cursor_size_ &&
         color_space_ == rhs.color_space_ && color_depth_ == rhs.color_depth_ &&
         depth_per_component_ == rhs.depth_per_component_ &&
         is_monochrome_ == rhs.is_monochrome_;
}

}  // namespace display
