blob: 15d4e46b06c76c17f3405139c6c979c1017b3696 [file] [log] [blame]
/*
* Copyright (C) 2011, 2014-2015 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. ``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
* 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 "PlatformCALayerWin.h"
#if USE(CA)
#include "AbstractCACFLayerTreeHost.h"
#include "FontCascade.h"
#include "GDIUtilities.h"
#include "GraphicsContext.h"
#include "PlatformCAAnimationWin.h"
#include "PlatformCALayerWinInternal.h"
#include "TextRun.h"
#include "TileController.h"
#include "WebTiledBackingLayerWin.h"
#include <QuartzCore/CoreAnimationCF.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
using namespace WebCore;
Ref<PlatformCALayer> PlatformCALayerWin::create(LayerType layerType, PlatformCALayerClient* owner)
{
return adoptRef(*new PlatformCALayerWin(layerType, nullptr, owner));
}
Ref<PlatformCALayer> PlatformCALayerWin::create(PlatformLayer* platformLayer, PlatformCALayerClient* owner)
{
return adoptRef(*new PlatformCALayerWin(LayerTypeCustom, platformLayer, owner));
}
static CFStringRef toCACFLayerType(PlatformCALayer::LayerType type)
{
return (type == PlatformCALayer::LayerTypeTransformLayer) ? kCACFTransformLayer : kCACFLayer;
}
static CFStringRef toCACFFilterType(PlatformCALayer::FilterType type)
{
switch (type) {
case PlatformCALayer::Linear: return kCACFFilterLinear;
case PlatformCALayer::Nearest: return kCACFFilterNearest;
case PlatformCALayer::Trilinear: return kCACFFilterTrilinear;
default: return nullptr;
}
}
static AbstractCACFLayerTreeHost* layerTreeHostForLayer(const PlatformCALayer* layer)
{
// We need the AbstractCACFLayerTreeHost associated with this layer, which is stored in the UserData of the CACFContext
void* userData = nullptr;
if (CACFContextRef context = CACFLayerGetContext(layer->platformLayer()))
userData = CACFContextGetUserData(context);
if (!userData)
return nullptr;
return static_cast<AbstractCACFLayerTreeHost*>(userData);
}
static PlatformCALayerWinInternal* intern(const PlatformCALayer* layer)
{
return static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(layer->platformLayer()));
}
static PlatformCALayerWinInternal* intern(void* layer)
{
return static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(static_cast<CACFLayerRef>(layer)));
}
PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
{
if (!platformLayer)
return nullptr;
PlatformCALayerWinInternal* layerIntern = intern(platformLayer);
return layerIntern ? layerIntern->owner() : nullptr;
}
PlatformCALayer::RepaintRectList PlatformCALayer::collectRectsToPaint(CGContextRef, PlatformCALayer*)
{
// FIXME: We should actually collect rects to use instead of defaulting to Windows'
// normal drawing path.
PlatformCALayer::RepaintRectList dirtyRects;
return dirtyRects;
}
void PlatformCALayer::drawLayerContents(CGContextRef context, WebCore::PlatformCALayer* platformCALayer, RepaintRectList&, GraphicsLayerPaintBehavior)
{
intern(platformCALayer)->displayCallback(platformCALayer->platformLayer(), context);
}
CGRect PlatformCALayer::frameForLayer(const PlatformLayer* tileLayer)
{
return CACFLayerGetFrame(static_cast<CACFLayerRef>(const_cast<PlatformLayer*>(tileLayer)));
}
static void displayCallback(CACFLayerRef caLayer, CGContextRef context)
{
ASSERT_ARG(caLayer, CACFLayerGetUserData(caLayer));
intern(caLayer)->displayCallback(caLayer, context);
}
static void layoutSublayersProc(CACFLayerRef caLayer)
{
PlatformCALayer* layer = PlatformCALayer::platformCALayer(caLayer);
if (layer && layer->owner())
layer->owner()->platformCALayerLayoutSublayersOfLayer(layer);
}
PlatformCALayerWin::PlatformCALayerWin(LayerType layerType, PlatformLayer* layer, PlatformCALayerClient* owner)
: PlatformCALayer(layer ? LayerTypeCustom : layerType, owner)
{
if (layer) {
m_layer = layer;
return;
}
m_layer = adoptCF(CACFLayerCreate(toCACFLayerType(layerType)));
#if HAVE(CACFLAYER_SETCONTENTSSCALE)
CACFLayerSetContentsScale(m_layer.get(), owner ? owner->platformCALayerDeviceScaleFactor() : deviceScaleFactorForWindow(nullptr));
#endif
// Create the PlatformCALayerWinInternal object and point to it in the userdata.
PlatformCALayerWinInternal* intern = nullptr;
if (usesTiledBackingLayer()) {
intern = new WebTiledBackingLayerWin(this);
TileController* tileController = reinterpret_cast<WebTiledBackingLayerWin*>(intern)->createTileController(this);
m_customSublayers = std::make_unique<PlatformCALayerList>(tileController->containerLayers());
} else
intern = new PlatformCALayerWinInternal(this);
CACFLayerSetUserData(m_layer.get(), intern);
// Set the display callback
CACFLayerSetDisplayCallback(m_layer.get(), displayCallback);
CACFLayerSetLayoutCallback(m_layer.get(), layoutSublayersProc);
}
PlatformCALayerWin::~PlatformCALayerWin()
{
// Toss all the kids
removeAllSublayers();
PlatformCALayerWinInternal* layerIntern = intern(this);
if (usesTiledBackingLayer())
reinterpret_cast<WebTiledBackingLayerWin*>(layerIntern)->invalidate();
// Get rid of the user data
CACFLayerSetUserData(m_layer.get(), nullptr);
CACFLayerRemoveFromSuperlayer(m_layer.get());
delete layerIntern;
}
Ref<PlatformCALayer> PlatformCALayerWin::clone(PlatformCALayerClient* owner) const
{
PlatformCALayer::LayerType type = (layerType() == PlatformCALayer::LayerTypeTransformLayer) ?
PlatformCALayer::LayerTypeTransformLayer : PlatformCALayer::LayerTypeLayer;
auto newLayer = PlatformCALayerWin::create(type, owner);
newLayer->setPosition(position());
newLayer->setBounds(bounds());
newLayer->setAnchorPoint(anchorPoint());
newLayer->setTransform(transform());
newLayer->setSublayerTransform(sublayerTransform());
newLayer->setContents(contents());
newLayer->setMasksToBounds(masksToBounds());
newLayer->setDoubleSided(isDoubleSided());
newLayer->setOpaque(isOpaque());
newLayer->setBackgroundColor(backgroundColor());
newLayer->setContentsScale(contentsScale());
newLayer->copyFiltersFrom(*this);
return newLayer;
}
PlatformCALayer* PlatformCALayerWin::rootLayer() const
{
AbstractCACFLayerTreeHost* host = layerTreeHostForLayer(this);
return host ? host->rootLayer() : nullptr;
}
void PlatformCALayerWin::animationStarted(const String& animationKey, MonotonicTime beginTime)
{
// Update start time for any animation not yet started
CFTimeInterval cacfBeginTime = currentTimeToMediaTime(beginTime);
HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator end = m_animations.end();
for (HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator it = m_animations.begin(); it != end; ++it)
it->value->setActualStartTimeIfNeeded(cacfBeginTime);
if (m_owner)
m_owner->platformCALayerAnimationStarted(animationKey, beginTime);
}
void PlatformCALayerWin::animationEnded(const String& animationKey)
{
if (m_owner)
m_owner->platformCALayerAnimationEnded(animationKey);
}
void PlatformCALayerWin::setNeedsDisplayInRect(const FloatRect& dirtyRect)
{
intern(this)->setNeedsDisplayInRect(dirtyRect);
}
void PlatformCALayerWin::setNeedsDisplay()
{
intern(this)->setNeedsDisplay();
}
void PlatformCALayerWin::setNeedsCommit()
{
AbstractCACFLayerTreeHost* host = layerTreeHostForLayer(this);
if (host)
host->layerTreeDidChange();
}
void PlatformCALayerWin::copyContentsFromLayer(PlatformCALayer* source)
{
if (source) {
RetainPtr<CFTypeRef> contents = CACFLayerGetContents(source->platformLayer());
CACFLayerSetContents(m_layer.get(), contents.get());
} else
CACFLayerSetContents(m_layer.get(), nullptr);
setNeedsCommit();
}
void PlatformCALayerWin::setNeedsLayout()
{
if (!m_owner || !m_owner->platformCALayerRespondsToLayoutChanges())
return;
CACFLayerSetNeedsLayout(m_layer.get());
setNeedsCommit();
}
PlatformCALayer* PlatformCALayerWin::superlayer() const
{
return platformCALayer(CACFLayerGetSuperlayer(m_layer.get()));
}
void PlatformCALayerWin::removeFromSuperlayer()
{
CACFLayerRemoveFromSuperlayer(m_layer.get());
setNeedsCommit();
}
void PlatformCALayerWin::setSublayers(const PlatformCALayerList& list)
{
intern(this)->setSublayers(list);
}
void PlatformCALayerWin::removeAllSublayers()
{
intern(this)->removeAllSublayers();
}
void PlatformCALayerWin::appendSublayer(PlatformCALayer& layer)
{
// This must be in terms of insertSublayer instead of a direct call so PlatformCALayerInternal can override.
insertSublayer(layer, intern(this)->sublayerCount());
}
void PlatformCALayerWin::insertSublayer(PlatformCALayer& layer, size_t index)
{
intern(this)->insertSublayer(layer, index);
}
void PlatformCALayerWin::replaceSublayer(PlatformCALayer& reference, PlatformCALayer& newLayer)
{
// This must not use direct calls to allow PlatformCALayerInternal to override.
ASSERT_ARG(reference, reference.superlayer() == this);
if (&reference == &newLayer)
return;
int referenceIndex = intern(this)->indexOfSublayer(&reference);
ASSERT(referenceIndex != -1);
if (referenceIndex == -1)
return;
reference.removeFromSuperlayer();
newLayer.removeFromSuperlayer();
insertSublayer(newLayer, referenceIndex);
}
void PlatformCALayerWin::adoptSublayers(PlatformCALayer& source)
{
PlatformCALayerList sublayers;
intern(&source)->getSublayers(sublayers);
// Use setSublayers() because it properly nulls out the superlayer pointers.
setSublayers(sublayers);
}
void PlatformCALayerWin::addAnimationForKey(const String& key, PlatformCAAnimation& animation)
{
// Add it to the animation list
m_animations.add(key, &animation);
CACFLayerAddAnimation(m_layer.get(), key.createCFString().get(), downcast<PlatformCAAnimationWin>(animation).platformAnimation());
setNeedsCommit();
// Tell the host about it so we can fire the start animation event
AbstractCACFLayerTreeHost* host = layerTreeHostForLayer(this);
if (host)
host->addPendingAnimatedLayer(*this);
}
void PlatformCALayerWin::removeAnimationForKey(const String& key)
{
// Remove it from the animation list
m_animations.remove(key);
CACFLayerRemoveAnimation(m_layer.get(), key.createCFString().get());
// We don't "remove" a layer from AbstractCACFLayerTreeHost when it loses an animation.
// There may be other active animations on the layer and if an animation
// callback is fired on a layer without any animations no harm is done.
setNeedsCommit();
}
RefPtr<PlatformCAAnimation> PlatformCALayerWin::animationForKey(const String& key)
{
HashMap<String, RefPtr<PlatformCAAnimation> >::iterator it = m_animations.find(key);
if (it == m_animations.end())
return nullptr;
return it->value;
}
void PlatformCALayerWin::setMask(PlatformCALayer* layer)
{
CACFLayerSetMask(m_layer.get(), layer ? layer->platformLayer() : 0);
setNeedsCommit();
}
bool PlatformCALayerWin::isOpaque() const
{
return intern(this)->isOpaque();
}
void PlatformCALayerWin::setOpaque(bool value)
{
intern(this)->setOpaque(value);
setNeedsCommit();
}
FloatRect PlatformCALayerWin::bounds() const
{
return CACFLayerGetBounds(m_layer.get());
}
void PlatformCALayerWin::setBounds(const FloatRect& value)
{
intern(this)->setBounds(value);
setNeedsLayout();
}
FloatPoint3D PlatformCALayerWin::position() const
{
CGPoint point = CACFLayerGetPosition(m_layer.get());
return FloatPoint3D(point.x, point.y, CACFLayerGetZPosition(m_layer.get()));
}
void PlatformCALayerWin::setPosition(const FloatPoint3D& value)
{
CACFLayerSetPosition(m_layer.get(), CGPointMake(value.x(), value.y()));
CACFLayerSetZPosition(m_layer.get(), value.z());
setNeedsCommit();
}
FloatPoint3D PlatformCALayerWin::anchorPoint() const
{
CGPoint point = CACFLayerGetAnchorPoint(m_layer.get());
float z = CACFLayerGetAnchorPointZ(m_layer.get());
return FloatPoint3D(point.x, point.y, z);
}
void PlatformCALayerWin::setAnchorPoint(const FloatPoint3D& value)
{
CACFLayerSetAnchorPoint(m_layer.get(), CGPointMake(value.x(), value.y()));
CACFLayerSetAnchorPointZ(m_layer.get(), value.z());
setNeedsCommit();
}
TransformationMatrix PlatformCALayerWin::transform() const
{
return CACFLayerGetTransform(m_layer.get());
}
void PlatformCALayerWin::setTransform(const TransformationMatrix& value)
{
CACFLayerSetTransform(m_layer.get(), value);
setNeedsCommit();
}
TransformationMatrix PlatformCALayerWin::sublayerTransform() const
{
return CACFLayerGetSublayerTransform(m_layer.get());
}
void PlatformCALayerWin::setSublayerTransform(const TransformationMatrix& value)
{
CACFLayerSetSublayerTransform(m_layer.get(), value);
setNeedsCommit();
}
bool PlatformCALayerWin::isHidden() const
{
return CACFLayerIsHidden(m_layer.get());
}
void PlatformCALayerWin::setHidden(bool value)
{
CACFLayerSetHidden(m_layer.get(), value);
setNeedsCommit();
}
bool PlatformCALayerWin::contentsHidden() const
{
return false;
}
void PlatformCALayerWin::setContentsHidden(bool)
{
}
void PlatformCALayerWin::setBackingStoreAttached(bool)
{
}
bool PlatformCALayerWin::backingStoreAttached() const
{
return true;
}
bool PlatformCALayerWin::userInteractionEnabled() const
{
return true;
}
void PlatformCALayerWin::setUserInteractionEnabled(bool)
{
}
bool PlatformCALayerWin::geometryFlipped() const
{
return CACFLayerIsGeometryFlipped(m_layer.get());
}
void PlatformCALayerWin::setGeometryFlipped(bool value)
{
CACFLayerSetGeometryFlipped(m_layer.get(), value);
setNeedsCommit();
}
bool PlatformCALayerWin::isDoubleSided() const
{
return CACFLayerIsDoubleSided(m_layer.get());
}
void PlatformCALayerWin::setDoubleSided(bool value)
{
CACFLayerSetDoubleSided(m_layer.get(), value);
setNeedsCommit();
}
bool PlatformCALayerWin::masksToBounds() const
{
return CACFLayerGetMasksToBounds(m_layer.get());
}
void PlatformCALayerWin::setMasksToBounds(bool value)
{
CACFLayerSetMasksToBounds(m_layer.get(), value);
setNeedsCommit();
}
bool PlatformCALayerWin::acceleratesDrawing() const
{
return false;
}
void PlatformCALayerWin::setAcceleratesDrawing(bool)
{
}
bool PlatformCALayerWin::wantsDeepColorBackingStore() const
{
return false;
}
void PlatformCALayerWin::setWantsDeepColorBackingStore(bool)
{
}
bool PlatformCALayerWin::supportsSubpixelAntialiasedText() const
{
return false;
}
void PlatformCALayerWin::setSupportsSubpixelAntialiasedText(bool)
{
}
bool PlatformCALayerWin::hasContents() const
{
return !!CACFLayerGetContents(m_layer.get());
}
CFTypeRef PlatformCALayerWin::contents() const
{
return CACFLayerGetContents(m_layer.get());
}
void PlatformCALayerWin::setContents(CFTypeRef value)
{
CACFLayerSetContents(m_layer.get(), value);
setNeedsCommit();
}
void PlatformCALayerWin::setContentsRect(const FloatRect& value)
{
CACFLayerSetContentsRect(m_layer.get(), value);
setNeedsCommit();
}
void PlatformCALayerWin::setMinificationFilter(FilterType value)
{
CACFLayerSetMinificationFilter(m_layer.get(), toCACFFilterType(value));
}
void PlatformCALayerWin::setMagnificationFilter(FilterType value)
{
CACFLayerSetMagnificationFilter(m_layer.get(), toCACFFilterType(value));
setNeedsCommit();
}
Color PlatformCALayerWin::backgroundColor() const
{
return CACFLayerGetBackgroundColor(m_layer.get());
}
void PlatformCALayerWin::setBackgroundColor(const Color& value)
{
CGFloat components[4];
value.getRGBA(components[0], components[1], components[2], components[3]);
RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
RetainPtr<CGColorRef> color = adoptCF(CGColorCreate(colorSpace.get(), components));
CACFLayerSetBackgroundColor(m_layer.get(), color.get());
setNeedsCommit();
}
void PlatformCALayerWin::setBorderWidth(float value)
{
intern(this)->setBorderWidth(value);
setNeedsCommit();
}
void PlatformCALayerWin::setBorderColor(const Color& value)
{
intern(this)->setBorderColor(value);
setNeedsCommit();
}
float PlatformCALayerWin::opacity() const
{
return CACFLayerGetOpacity(m_layer.get());
}
void PlatformCALayerWin::setOpacity(float value)
{
CACFLayerSetOpacity(m_layer.get(), value);
setNeedsCommit();
}
void PlatformCALayerWin::setFilters(const FilterOperations&)
{
}
void PlatformCALayerWin::copyFiltersFrom(const PlatformCALayer&)
{
}
void PlatformCALayerWin::setName(const String& value)
{
CACFLayerSetName(m_layer.get(), value.createCFString().get());
setNeedsCommit();
}
void PlatformCALayerWin::setSpeed(float value)
{
CACFLayerSetSpeed(m_layer.get(), value);
setNeedsCommit();
}
void PlatformCALayerWin::setTimeOffset(CFTimeInterval value)
{
CACFLayerSetTimeOffset(m_layer.get(), value);
setNeedsCommit();
}
void PlatformCALayerWin::setEdgeAntialiasingMask(unsigned mask)
{
CACFLayerSetEdgeAntialiasingMask(m_layer.get(), mask);
setNeedsCommit();
}
float PlatformCALayerWin::contentsScale() const
{
return intern(this)->contentsScale();
}
void PlatformCALayerWin::setContentsScale(float scaleFactor)
{
intern(this)->setContentsScale(scaleFactor);
setNeedsCommit();
}
float PlatformCALayerWin::cornerRadius() const
{
return 0; // FIXME: implement.
}
void PlatformCALayerWin::setCornerRadius(float value)
{
// FIXME: implement.
}
FloatRoundedRect PlatformCALayerWin::shapeRoundedRect() const
{
// FIXME: implement.
return FloatRoundedRect();
}
void PlatformCALayerWin::setShapeRoundedRect(const FloatRoundedRect&)
{
// FIXME: implement.
}
WindRule PlatformCALayerWin::shapeWindRule() const
{
// FIXME: implement.
return WindRule::NonZero;
}
void PlatformCALayerWin::setShapeWindRule(WindRule)
{
// FIXME: implement.
}
Path PlatformCALayerWin::shapePath() const
{
// FIXME: implement.
return Path();
}
void PlatformCALayerWin::setShapePath(const Path&)
{
// FIXME: implement.
}
static void printIndent(StringBuilder& builder, int indent)
{
for ( ; indent > 0; --indent)
builder.append(" ");
}
static void printTransform(StringBuilder& builder, const CATransform3D& transform)
{
builder.append('[');
builder.appendFixedPrecisionNumber(transform.m11);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m12);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m13);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m14);
builder.append("; ");
builder.appendFixedPrecisionNumber(transform.m21);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m22);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m23);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m24);
builder.append("; ");
builder.appendFixedPrecisionNumber(transform.m31);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m32);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m33);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m34);
builder.append("; ");
builder.appendFixedPrecisionNumber(transform.m41);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m42);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m43);
builder.append(' ');
builder.appendFixedPrecisionNumber(transform.m44);
builder.append(']');
}
static void printColor(StringBuilder& builder, int indent, const String& label, CGColorRef color)
{
Color layerColor(color);
if (!layerColor.isValid())
return;
builder.append('\n');
printIndent(builder, indent);
builder.append('(');
builder.append(label);
builder.append(' ');
builder.append(layerColor.nameForRenderTreeAsText());
builder.append(')');
}
static void printLayer(StringBuilder& builder, const PlatformCALayer* layer, int indent)
{
FloatPoint3D layerPosition = layer->position();
FloatPoint3D layerAnchorPoint = layer->anchorPoint();
FloatRect layerBounds = layer->bounds();
builder.append('\n');
printIndent(builder, indent);
char* layerTypeName = nullptr;
switch (layer->layerType()) {
case PlatformCALayer::LayerTypeLayer: layerTypeName = "layer"; break;
case PlatformCALayer::LayerTypeEditableImageLayer:
case PlatformCALayer::LayerTypeWebLayer: layerTypeName = "web-layer"; break;
case PlatformCALayer::LayerTypeSimpleLayer: layerTypeName = "simple-layer"; break;
case PlatformCALayer::LayerTypeTransformLayer: layerTypeName = "transform-layer"; break;
case PlatformCALayer::LayerTypeTiledBackingLayer: layerTypeName = "tiled-backing-layer"; break;
case PlatformCALayer::LayerTypePageTiledBackingLayer: layerTypeName = "page-tiled-backing-layer"; break;
case PlatformCALayer::LayerTypeTiledBackingTileLayer: layerTypeName = "tiled-backing-tile-layer"; break;
case PlatformCALayer::LayerTypeRootLayer: layerTypeName = "root-layer"; break;
case PlatformCALayer::LayerTypeAVPlayerLayer: layerTypeName = "avplayer-layer"; break;
case PlatformCALayer::LayerTypeContentsProvidedLayer: layerTypeName = "contents-provided-layer"; break;
case PlatformCALayer::LayerTypeBackdropLayer: layerTypeName = "backdrop-layer"; break;
case PlatformCALayer::LayerTypeShapeLayer: layerTypeName = "shape-layer"; break;
case PlatformCALayer::LayerTypeLightSystemBackdropLayer: layerTypeName = "light-system-backdrop-layer"; break;
case PlatformCALayer::LayerTypeDarkSystemBackdropLayer: layerTypeName = "dark-system-backdrop-layer"; break;
case PlatformCALayer::LayerTypeScrollContainerLayer: layerTypeName = "scroll-container-layer"; break;
case PlatformCALayer::LayerTypeCustom: layerTypeName = "custom-layer"; break;
}
builder.append("(");
builder.append(layerTypeName);
builder.append(" [");
builder.appendFixedPrecisionNumber(layerPosition.x());
builder.append(' ');
builder.appendFixedPrecisionNumber(layerPosition.y());
builder.append(' ');
builder.appendFixedPrecisionNumber(layerPosition.z());
builder.append("] [");
builder.appendFixedPrecisionNumber(layerBounds.x());
builder.append(' ');
builder.appendFixedPrecisionNumber(layerBounds.y());
builder.append(' ');
builder.appendFixedPrecisionNumber(layerBounds.width());
builder.append(' ');
builder.appendFixedPrecisionNumber(layerBounds.height());
builder.append("] [");
builder.appendFixedPrecisionNumber(layerAnchorPoint.x());
builder.append(' ');
builder.appendFixedPrecisionNumber(layerAnchorPoint.y());
builder.append(' ');
builder.appendFixedPrecisionNumber(layerAnchorPoint.z());
builder.append("] superlayer=");
builder.appendNumber(reinterpret_cast<unsigned long long>(layer->superlayer()));
// Print name if needed
String layerName = CACFLayerGetName(layer->platformLayer());
if (!layerName.isEmpty()) {
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(name \"");
builder.append(layerName);
builder.append("\")");
}
// Print borderWidth if needed
if (CGFloat borderWidth = CACFLayerGetBorderWidth(layer->platformLayer())) {
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(borderWidth ");
builder.appendFixedPrecisionNumber(borderWidth);
builder.append(')');
}
// Print backgroundColor if needed
printColor(builder, indent + 1, "backgroundColor", CACFLayerGetBackgroundColor(layer->platformLayer()));
// Print borderColor if needed
printColor(builder, indent + 1, "borderColor", CACFLayerGetBorderColor(layer->platformLayer()));
// Print masksToBounds if needed
if (bool layerMasksToBounds = layer->masksToBounds()) {
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(masksToBounds true)");
}
if (bool geometryFlipped = layer->geometryFlipped()) {
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(geometryFlipped true)");
}
// Print opacity if needed
float layerOpacity = layer->opacity();
if (layerOpacity != 1) {
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(opacity ");
builder.appendFixedPrecisionNumber(layerOpacity);
builder.append(')');
}
// Print sublayerTransform if needed
TransformationMatrix layerTransform = layer->sublayerTransform();
if (!layerTransform.isIdentity()) {
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(sublayerTransform ");
printTransform(builder, layerTransform);
builder.append(')');
}
// Print transform if needed
layerTransform = layer->transform();
if (!layerTransform.isIdentity()) {
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(transform ");
printTransform(builder, layerTransform);
builder.append(')');
}
// Print contents if needed
if (CFTypeRef layerContents = layer->contents()) {
if (CFGetTypeID(layerContents) == CGImageGetTypeID()) {
CGImageRef imageContents = static_cast<CGImageRef>(const_cast<void*>(layerContents));
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(contents (image [");
builder.appendNumber(CGImageGetWidth(imageContents));
builder.append(' ');
builder.appendNumber(CGImageGetHeight(imageContents));
builder.append("]))");
}
if (CFGetTypeID(layerContents) == CABackingStoreGetTypeID()) {
CABackingStoreRef backingStore = static_cast<CABackingStoreRef>(const_cast<void*>(layerContents));
CGImageRef imageContents = CABackingStoreGetCGImage(backingStore);
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(contents (backing-store [");
builder.appendNumber(CGImageGetWidth(imageContents));
builder.append(' ');
builder.appendNumber(CGImageGetHeight(imageContents));
builder.append("]))");
}
}
// Print sublayers if needed
int n = intern(layer)->sublayerCount();
if (n > 0) {
builder.append('\n');
printIndent(builder, indent + 1);
builder.append("(sublayers");
PlatformCALayerList sublayers;
intern(layer)->getSublayers(sublayers);
ASSERT(n == sublayers.size());
for (int i = 0; i < n; ++i)
printLayer(builder, sublayers[i].get(), indent + 2);
builder.append(')');
}
builder.append(')');
}
String PlatformCALayerWin::layerTreeAsString() const
{
// Print heading info
CGRect rootBounds = bounds();
StringBuilder builder;
builder.append("\n\n** Render tree at time ");
builder.appendFixedPrecisionNumber(MonotonicTime::now().secondsSinceEpoch().seconds());
builder.append(" (bounds ");
builder.appendFixedPrecisionNumber(rootBounds.origin.x);
builder.append(", ");
builder.appendFixedPrecisionNumber(rootBounds.origin.y);
builder.append(' ');
builder.appendFixedPrecisionNumber(rootBounds.size.width);
builder.append('x');
builder.appendFixedPrecisionNumber(rootBounds.size.height);
builder.append(") **\n\n");
// Print layer tree from the root
printLayer(builder, this, 0);
return builder.toString();
}
Ref<PlatformCALayer> PlatformCALayerWin::createCompatibleLayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* client) const
{
return PlatformCALayerWin::create(layerType, client);
}
GraphicsLayer::EmbeddedViewID PlatformCALayerWin::embeddedViewID() const
{
ASSERT_NOT_REACHED();
return 0;
}
TiledBacking* PlatformCALayerWin::tiledBacking()
{
if (!usesTiledBackingLayer())
return nullptr;
return reinterpret_cast<WebTiledBackingLayerWin*>(intern(this))->tiledBacking();
}
void PlatformCALayerWin::drawTextAtPoint(CGContextRef context, CGFloat x, CGFloat y, CGSize scale, CGFloat fontSize, const char* message, size_t length, CGFloat, Color) const
{
String text(message, length);
FontCascadeDescription desc;
NONCLIENTMETRICS metrics;
metrics.cbSize = sizeof(metrics);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
desc.setOneFamily(metrics.lfSmCaptionFont.lfFaceName);
desc.setComputedSize(scale.width * fontSize);
FontCascade font = FontCascade(WTFMove(desc), 0, 0);
font.update(nullptr);
GraphicsContext cg(context);
cg.setFillColor(Color::black);
cg.drawText(font, TextRun(text), IntPoint(x, y));
}
#endif