Home | History | Annotate | Download | only in compositor
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/compositor/dip_util.h"
      6 
      7 #include "base/command_line.h"
      8 #include "cc/layers/layer.h"
      9 #include "ui/compositor/compositor.h"
     10 #include "ui/compositor/compositor_switches.h"
     11 #include "ui/compositor/layer.h"
     12 #include "ui/gfx/display.h"
     13 #include "ui/gfx/geometry/safe_integer_conversions.h"
     14 #include "ui/gfx/point.h"
     15 #include "ui/gfx/point_conversions.h"
     16 #include "ui/gfx/rect.h"
     17 #include "ui/gfx/rect_conversions.h"
     18 #include "ui/gfx/size.h"
     19 #include "ui/gfx/size_conversions.h"
     20 
     21 #if DCHECK_IS_ON
     22 #include "ui/compositor/layer_animator.h"
     23 #endif
     24 
     25 namespace ui {
     26 
     27 float GetDeviceScaleFactor(const Layer* layer) {
     28   return layer->device_scale_factor();
     29 }
     30 
     31 gfx::Point ConvertPointToDIP(const Layer* layer,
     32                              const gfx::Point& point_in_pixel) {
     33   return gfx::ToFlooredPoint(
     34       gfx::ScalePoint(point_in_pixel, 1.0f / GetDeviceScaleFactor(layer)));
     35 }
     36 
     37 gfx::PointF ConvertPointToDIP(const Layer* layer,
     38                               const gfx::PointF& point_in_pixel) {
     39   return gfx::ScalePoint(point_in_pixel, 1.0f / GetDeviceScaleFactor(layer));
     40 }
     41 
     42 gfx::Size ConvertSizeToDIP(const Layer* layer,
     43                            const gfx::Size& size_in_pixel) {
     44   return gfx::ToFlooredSize(
     45       gfx::ScaleSize(size_in_pixel, 1.0f / GetDeviceScaleFactor(layer)));
     46 }
     47 
     48 gfx::Rect ConvertRectToDIP(const Layer* layer,
     49                            const gfx::Rect& rect_in_pixel) {
     50   float scale = 1.0f / GetDeviceScaleFactor(layer);
     51   return gfx::ToFlooredRectDeprecated(gfx::ScaleRect(rect_in_pixel, scale));
     52 }
     53 
     54 gfx::Point ConvertPointToPixel(const Layer* layer,
     55                                const gfx::Point& point_in_dip) {
     56   return gfx::ToFlooredPoint(
     57       gfx::ScalePoint(point_in_dip, GetDeviceScaleFactor(layer)));
     58 }
     59 
     60 gfx::Size ConvertSizeToPixel(const Layer* layer,
     61                              const gfx::Size& size_in_dip) {
     62   return gfx::ToFlooredSize(
     63       gfx::ScaleSize(size_in_dip, GetDeviceScaleFactor(layer)));
     64 }
     65 
     66 gfx::Rect ConvertRectToPixel(const Layer* layer,
     67                              const gfx::Rect& rect_in_dip) {
     68   float scale = GetDeviceScaleFactor(layer);
     69   // Use ToEnclosingRect() to ensure we paint all the possible pixels
     70   // touched. ToEnclosingRect() floors the origin, and ceils the max
     71   // coordinate. To do otherwise (such as flooring the size) potentially
     72   // results in rounding down and not drawing all the pixels that are
     73   // touched.
     74   return gfx::ToEnclosingRect(
     75       gfx::RectF(gfx::ScalePoint(rect_in_dip.origin(), scale),
     76                  gfx::ScaleSize(rect_in_dip.size(), scale)));
     77 }
     78 
     79 #if DCHECK_IS_ON
     80 namespace {
     81 
     82 void CheckSnapped(float snapped_position) {
     83   const float kEplison = 0.0001f;
     84   float diff = std::abs(snapped_position - gfx::ToRoundedInt(snapped_position));
     85   DCHECK_LT(diff, kEplison);
     86 }
     87 
     88 }  // namespace
     89 #endif
     90 
     91 void SnapLayerToPhysicalPixelBoundary(ui::Layer* snapped_layer,
     92                                       ui::Layer* layer_to_snap) {
     93   DCHECK_NE(snapped_layer, layer_to_snap);
     94   DCHECK(snapped_layer);
     95   DCHECK(snapped_layer->Contains(layer_to_snap));
     96 
     97   gfx::Point view_offset_dips = layer_to_snap->GetTargetBounds().origin();
     98   ui::Layer::ConvertPointToLayer(
     99       layer_to_snap->parent(), snapped_layer, &view_offset_dips);
    100   gfx::PointF view_offset = view_offset_dips;
    101 
    102   float scale_factor = GetDeviceScaleFactor(layer_to_snap);
    103   view_offset.Scale(scale_factor);
    104   gfx::PointF view_offset_snapped(gfx::ToRoundedInt(view_offset.x()),
    105                                   gfx::ToRoundedInt(view_offset.y()));
    106 
    107   gfx::Vector2dF fudge = view_offset_snapped - view_offset;
    108   fudge.Scale(1.0 / scale_factor);
    109   layer_to_snap->SetSubpixelPositionOffset(fudge);
    110 #if DCHECK_IS_ON
    111   gfx::Point layer_offset;
    112   gfx::PointF origin;
    113   Layer::ConvertPointToLayer(
    114       layer_to_snap->parent(), snapped_layer, &layer_offset);
    115   if (layer_to_snap->GetAnimator()->is_animating()) {
    116     origin = layer_to_snap->GetTargetBounds().origin() +
    117              layer_to_snap->subpixel_position_offset();
    118   } else {
    119     cc::Layer* cc_layer = layer_to_snap->cc_layer();
    120     origin = cc_layer->position();
    121   }
    122   CheckSnapped((layer_offset.x() + origin.x()) * scale_factor);
    123   CheckSnapped((layer_offset.y() + origin.y()) * scale_factor);
    124 #endif
    125 }
    126 
    127 }  // namespace ui
    128