15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/dip_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "cc/layers/layer.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/compositor.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/compositor_switches.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/display.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/gfx/geometry/safe_integer_conversions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/point.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/point_conversions.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect_conversions.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size_conversions.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if DCHECK_IS_ON
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/compositor/layer_animator.h"
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float GetDeviceScaleFactor(const Layer* layer) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return layer->device_scale_factor();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point ConvertPointToDIP(const Layer* layer,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const gfx::Point& point_in_pixel) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::ToFlooredPoint(
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::ScalePoint(point_in_pixel, 1.0f / GetDeviceScaleFactor(layer)));
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::PointF ConvertPointToDIP(const Layer* layer,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const gfx::PointF& point_in_pixel) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::ScalePoint(point_in_pixel, 1.0f / GetDeviceScaleFactor(layer));
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size ConvertSizeToDIP(const Layer* layer,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const gfx::Size& size_in_pixel) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::ToFlooredSize(
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::ScaleSize(size_in_pixel, 1.0f / GetDeviceScaleFactor(layer)));
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect ConvertRectToDIP(const Layer* layer,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const gfx::Rect& rect_in_pixel) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float scale = 1.0f / GetDeviceScaleFactor(layer);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::ToFlooredRectDeprecated(gfx::ScaleRect(rect_in_pixel, scale));
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point ConvertPointToPixel(const Layer* layer,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Point& point_in_dip) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::ToFlooredPoint(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::ScalePoint(point_in_dip, GetDeviceScaleFactor(layer)));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size ConvertSizeToPixel(const Layer* layer,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const gfx::Size& size_in_dip) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::ToFlooredSize(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::ScaleSize(size_in_dip, GetDeviceScaleFactor(layer)));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect ConvertRectToPixel(const Layer* layer,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const gfx::Rect& rect_in_dip) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float scale = GetDeviceScaleFactor(layer);
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Use ToEnclosingRect() to ensure we paint all the possible pixels
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // touched. ToEnclosingRect() floors the origin, and ceils the max
710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // coordinate. To do otherwise (such as flooring the size) potentially
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // results in rounding down and not drawing all the pixels that are
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // touched.
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return gfx::ToEnclosingRect(
750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      gfx::RectF(gfx::ScalePoint(rect_in_dip.origin(), scale),
760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                 gfx::ScaleSize(rect_in_dip.size(), scale)));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if DCHECK_IS_ON
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace {
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid CheckSnapped(float snapped_position) {
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const float kEplison = 0.0001f;
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  float diff = std::abs(snapped_position - gfx::ToRoundedInt(snapped_position));
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_LT(diff, kEplison);
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SnapLayerToPhysicalPixelBoundary(ui::Layer* snapped_layer,
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                      ui::Layer* layer_to_snap) {
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_NE(snapped_layer, layer_to_snap);
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(snapped_layer);
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(snapped_layer->Contains(layer_to_snap));
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gfx::Point view_offset_dips = layer_to_snap->GetTargetBounds().origin();
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::Layer::ConvertPointToLayer(
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      layer_to_snap->parent(), snapped_layer, &view_offset_dips);
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gfx::PointF view_offset = view_offset_dips;
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  float scale_factor = GetDeviceScaleFactor(layer_to_snap);
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  view_offset.Scale(scale_factor);
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gfx::PointF view_offset_snapped(gfx::ToRoundedInt(view_offset.x()),
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                  gfx::ToRoundedInt(view_offset.y()));
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gfx::Vector2dF fudge = view_offset_snapped - view_offset;
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  fudge.Scale(1.0 / scale_factor);
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  layer_to_snap->SetSubpixelPositionOffset(fudge);
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if DCHECK_IS_ON
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Point layer_offset;
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::PointF origin;
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Layer::ConvertPointToLayer(
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      layer_to_snap->parent(), snapped_layer, &layer_offset);
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (layer_to_snap->GetAnimator()->is_animating()) {
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    origin = layer_to_snap->GetTargetBounds().origin() +
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             layer_to_snap->subpixel_position_offset();
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cc::Layer* cc_layer = layer_to_snap->cc_layer();
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    origin = cc_layer->position();
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CheckSnapped((layer_offset.x() + origin.x()) * scale_factor);
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CheckSnapped((layer_offset.y() + origin.y()) * scale_factor);
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
128