/*
 * 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.appendNumber(transform.m11);
    builder.append(' ');
    builder.appendNumber(transform.m12);
    builder.append(' ');
    builder.appendNumber(transform.m13);
    builder.append(' ');
    builder.appendNumber(transform.m14);
    builder.append("; ");
    builder.appendNumber(transform.m21);
    builder.append(' ');
    builder.appendNumber(transform.m22);
    builder.append(' ');
    builder.appendNumber(transform.m23);
    builder.append(' ');
    builder.appendNumber(transform.m24);
    builder.append("; ");
    builder.appendNumber(transform.m31);
    builder.append(' ');
    builder.appendNumber(transform.m32);
    builder.append(' ');
    builder.appendNumber(transform.m33);
    builder.append(' ');
    builder.appendNumber(transform.m34);
    builder.append("; ");
    builder.appendNumber(transform.m41);
    builder.append(' ');
    builder.appendNumber(transform.m42);
    builder.append(' ');
    builder.appendNumber(transform.m43);
    builder.append(' ');
    builder.appendNumber(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.appendNumber(layerPosition.x());
    builder.append(' ');
    builder.appendNumber(layerPosition.y());
    builder.append(' ');
    builder.appendNumber(layerPosition.z());
    builder.append("] [");
    builder.appendNumber(layerBounds.x());
    builder.append(' ');
    builder.appendNumber(layerBounds.y());
    builder.append(' ');
    builder.appendNumber(layerBounds.width());
    builder.append(' ');
    builder.appendNumber(layerBounds.height());
    builder.append("] [");
    builder.appendNumber(layerAnchorPoint.x());
    builder.append(' ');
    builder.appendNumber(layerAnchorPoint.y());
    builder.append(' ');
    builder.appendNumber(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.appendNumber(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.appendNumber(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.appendNumber(MonotonicTime::now().secondsSinceEpoch().seconds());
    builder.append(" (bounds ");
    builder.appendNumber(rootBounds.origin.x);
    builder.append(", ");
    builder.appendNumber(rootBounds.origin.y);
    builder.append(' ');
    builder.appendNumber(rootBounds.size.width);
    builder.append('x');
    builder.appendNumber(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
