blob: f54fc9907704a216ef6bb4744eed55ce1faa693f [file] [log] [blame]
/*
* Copyright (C) 2011-2014 Apple 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:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
#include "TileCoverageMap.h"
#include "GraphicsContext.h"
#include "TileController.h"
#include "TileGrid.h"
namespace WebCore {
TileCoverageMap::TileCoverageMap(const TileController& controller)
: m_controller(controller)
, m_updateTimer(*this, &TileCoverageMap::updateTimerFired)
, m_layer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeSimpleLayer, this))
, m_visibleViewportIndicatorLayer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
, m_layoutViewportIndicatorLayer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
, m_coverageRectIndicatorLayer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
, m_position(FloatPoint(0, controller.topContentInset()))
{
m_layer.get().setOpacity(0.75);
m_layer.get().setAnchorPoint(FloatPoint3D());
m_layer.get().setBorderColor(Color::black);
m_layer.get().setBorderWidth(1);
m_layer.get().setPosition(FloatPoint(2, 2));
m_layer.get().setContentsScale(m_controller.deviceScaleFactor());
m_visibleViewportIndicatorLayer.get().setName("visible viewport indicator");
m_visibleViewportIndicatorLayer.get().setBorderWidth(2);
m_visibleViewportIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
m_visibleViewportIndicatorLayer.get().setBorderColor(Color(255, 0, 0, 200));
m_layoutViewportIndicatorLayer.get().setName("layout viewport indicator");
m_layoutViewportIndicatorLayer.get().setBorderWidth(2);
m_layoutViewportIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
m_layoutViewportIndicatorLayer.get().setBorderColor(Color(0, 128, 128, 200));
m_coverageRectIndicatorLayer.get().setName("coverage indicator");
m_coverageRectIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
m_coverageRectIndicatorLayer.get().setBackgroundColor(Color(64, 64, 64, 50));
m_layer.get().appendSublayer(m_coverageRectIndicatorLayer);
m_layer.get().appendSublayer(m_visibleViewportIndicatorLayer);
if (m_controller.layoutViewportRect())
m_layer.get().appendSublayer(m_layoutViewportIndicatorLayer);
update();
}
TileCoverageMap::~TileCoverageMap()
{
m_layer.get().setOwner(nullptr);
}
void TileCoverageMap::setNeedsUpdate()
{
if (!m_updateTimer.isActive())
m_updateTimer.startOneShot(0_s);
}
void TileCoverageMap::updateTimerFired()
{
update();
}
void TileCoverageMap::update()
{
FloatRect containerBounds = m_controller.bounds();
FloatRect visibleRect = m_controller.visibleRect();
FloatRect coverageRect = m_controller.coverageRect();
visibleRect.contract(4, 4); // Layer is positioned 2px from top and left edges.
float widthScale = 1;
float scale = 1;
if (!containerBounds.isEmpty()) {
widthScale = std::min<float>(visibleRect.width() / containerBounds.width(), 0.1);
float visibleHeight = visibleRect.height() - std::min(m_controller.topContentInset(), visibleRect.y());
scale = std::min(widthScale, visibleHeight / containerBounds.height());
}
float indicatorScale = scale * m_controller.tileGrid().scale();
FloatRect mapBounds = containerBounds;
mapBounds.scale(indicatorScale);
m_layer.get().setPosition(m_position + FloatPoint(2, 2));
m_layer.get().setBounds(mapBounds);
m_layer.get().setNeedsDisplay();
visibleRect.scale(indicatorScale);
visibleRect.expand(2, 2);
m_visibleViewportIndicatorLayer->setPosition(visibleRect.location());
m_visibleViewportIndicatorLayer->setBounds(FloatRect(FloatPoint(), visibleRect.size()));
if (auto layoutViewportRect = m_controller.layoutViewportRect()) {
FloatRect layoutRect = layoutViewportRect.value();
layoutRect.scale(indicatorScale);
layoutRect.expand(2, 2);
m_layoutViewportIndicatorLayer->setPosition(layoutRect.location());
m_layoutViewportIndicatorLayer->setBounds(FloatRect(FloatPoint(), layoutRect.size()));
if (!m_layoutViewportIndicatorLayer->superlayer())
m_layer.get().appendSublayer(m_layoutViewportIndicatorLayer);
} else if (m_layoutViewportIndicatorLayer->superlayer())
m_layoutViewportIndicatorLayer->removeFromSuperlayer();
coverageRect.scale(indicatorScale);
coverageRect.expand(2, 2);
m_coverageRectIndicatorLayer->setPosition(coverageRect.location());
m_coverageRectIndicatorLayer->setBounds(FloatRect(FloatPoint(), coverageRect.size()));
Color visibleRectIndicatorColor;
switch (m_controller.indicatorMode()) {
case SynchronousScrollingBecauseOfLackOfScrollingCoordinatorIndication:
visibleRectIndicatorColor = Color(200, 80, 255);
break;
case SynchronousScrollingBecauseOfStyleIndication:
visibleRectIndicatorColor = Color(255, 0, 0);
break;
case SynchronousScrollingBecauseOfEventHandlersIndication:
visibleRectIndicatorColor = Color(255, 255, 0);
break;
case AsyncScrollingIndication:
visibleRectIndicatorColor = Color(0, 200, 0);
break;
}
m_visibleViewportIndicatorLayer.get().setBorderColor(visibleRectIndicatorColor);
}
void TileCoverageMap::platformCALayerPaintContents(PlatformCALayer* platformCALayer, GraphicsContext& context, const FloatRect&, GraphicsLayerPaintBehavior)
{
ASSERT_UNUSED(platformCALayer, platformCALayer == m_layer.ptr());
m_controller.tileGrid().drawTileMapContents(context.platformContext(), m_layer.get().bounds());
}
float TileCoverageMap::platformCALayerDeviceScaleFactor() const
{
return m_controller.rootLayer().owner()->platformCALayerDeviceScaleFactor();
}
void TileCoverageMap::setDeviceScaleFactor(float deviceScaleFactor)
{
m_layer.get().setContentsScale(deviceScaleFactor);
}
}