7a91900cdf112ff00a1766243c9d0bc6eec23ffe
[WebKit-https.git] / Source / WebCore / platform / graphics / ca / PlatformCALayer.cpp
1 /*
2  * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "PlatformCALayer.h"
28
29 #if USE(CA)
30
31 #include "GraphicsContextCG.h"
32 #include "LayerPool.h"
33 #include "PlatformCALayerClient.h"
34 #include <CoreFoundation/CoreFoundation.h>
35 #include <CoreText/CoreText.h>
36 #include <wtf/text/TextStream.h>
37
38 #if PLATFORM(WIN)
39 #include <pal/spi/win/CoreTextSPIWin.h>
40 #endif
41
42 namespace WebCore {
43
44 static GraphicsLayer::PlatformLayerID generateLayerID()
45 {
46     static GraphicsLayer::PlatformLayerID layerID;
47     return ++layerID;
48 }
49
50 #if COMPILER(MSVC)
51 const float PlatformCALayer::webLayerWastedSpaceThreshold = 0.75f;
52 #endif
53
54 PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformCALayerClient* owner)
55     : m_layerType(layerType)
56     , m_layerID(generateLayerID())
57     , m_owner(owner)
58 {
59 }
60
61 PlatformCALayer::~PlatformCALayer()
62 {
63     // Clear the owner, which also clears it in the delegate to prevent attempts
64     // to use the GraphicsLayerCA after it has been destroyed.
65     setOwner(nullptr);
66 }
67
68 bool PlatformCALayer::canHaveBackingStore() const
69 {
70     return m_layerType == LayerType::LayerTypeWebLayer
71         || m_layerType == LayerType::LayerTypeTiledBackingLayer
72         || m_layerType == LayerType::LayerTypePageTiledBackingLayer
73         || m_layerType == LayerType::LayerTypeTiledBackingTileLayer;
74 }
75
76 void PlatformCALayer::drawRepaintIndicator(CGContextRef context, PlatformCALayer* platformCALayer, int repaintCount, CGColorRef customBackgroundColor)
77 {
78     char text[16]; // that's a lot of repaints
79     snprintf(text, sizeof(text), "%d", repaintCount);
80     
81     FloatRect indicatorBox = platformCALayer->bounds();\
82     indicatorBox.setLocation( { 1, 1 } );
83     indicatorBox.setSize(FloatSize(12 + 10 * strlen(text), 27));
84
85     CGContextStateSaver stateSaver(context);
86     
87     CGContextSetAlpha(context, 0.5f);
88     CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0);
89     
90     if (customBackgroundColor)
91         CGContextSetFillColorWithColor(context, customBackgroundColor);
92     else
93         CGContextSetRGBFillColor(context, 0, 0.5f, 0.25f, 1);
94     
95     if (platformCALayer->isOpaque())
96         CGContextFillRect(context, indicatorBox);
97     else {
98         Path boundsPath;
99         boundsPath.moveTo(indicatorBox.maxXMinYCorner());
100         boundsPath.addLineTo(indicatorBox.maxXMaxYCorner());
101         boundsPath.addLineTo(indicatorBox.minXMaxYCorner());
102
103         const float cornerChunk = 8;
104         boundsPath.addLineTo(FloatPoint(indicatorBox.x(), indicatorBox.y() + cornerChunk));
105         boundsPath.addLineTo(FloatPoint(indicatorBox.x() + cornerChunk, indicatorBox.y()));
106         boundsPath.closeSubpath();
107
108         CGContextAddPath(context, boundsPath.platformPath());
109         CGContextFillPath(context);
110     }
111
112     if (platformCALayer->owner()->isUsingDisplayListDrawing(platformCALayer)) {
113         CGContextSetRGBStrokeColor(context, 0, 0, 0, 0.65);
114         CGContextSetLineWidth(context, 2);
115         CGContextStrokeRect(context, indicatorBox);
116     }
117
118     CGFloat strokeWidthAsPercentageOfFontSize = 0;
119     Color strokeColor;
120
121     if (!platformCALayer->isOpaque() && platformCALayer->supportsSubpixelAntialiasedText() && platformCALayer->acceleratesDrawing()) {
122         strokeColor = Color(0, 0, 0, 200);
123         strokeWidthAsPercentageOfFontSize = -4.5; // Negative means "stroke and fill"; see docs for kCTStrokeWidthAttributeName.
124     }
125
126     if (platformCALayer->acceleratesDrawing())
127         CGContextSetRGBFillColor(context, 1, 0, 0, 1);
128     else
129         CGContextSetRGBFillColor(context, 1, 1, 1, 1);
130     
131     platformCALayer->drawTextAtPoint(context, indicatorBox.x() + 5, indicatorBox.y() + 22, CGSizeMake(1, -1), 22, text, strlen(text), strokeWidthAsPercentageOfFontSize, strokeColor);
132     
133     CGContextEndTransparencyLayer(context);
134 }
135
136 void PlatformCALayer::flipContext(CGContextRef context, CGFloat height)
137 {
138     CGContextScaleCTM(context, 1, -1);
139     CGContextTranslateCTM(context, 0, -height);
140 }
141
142 void PlatformCALayer::drawTextAtPoint(CGContextRef context, CGFloat x, CGFloat y, CGSize scale, CGFloat fontSize, const char* text, size_t length, CGFloat strokeWidthAsPercentageOfFontSize, Color strokeColor) const
143 {
144     auto matrix = CGAffineTransformMakeScale(scale.width, scale.height);
145     auto font = adoptCF(CTFontCreateWithName(CFSTR("Helvetica"), fontSize, &matrix));
146     auto strokeWidthNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &strokeWidthAsPercentageOfFontSize));
147
148     CFTypeRef keys[] = {
149         kCTFontAttributeName,
150         kCTForegroundColorFromContextAttributeName,
151         kCTStrokeWidthAttributeName,
152         kCTStrokeColorAttributeName,
153     };
154     CFTypeRef values[] = {
155         font.get(),
156         kCFBooleanTrue,
157         strokeWidthNumber.get(),
158         cachedCGColor(strokeColor),
159     };
160
161     auto attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
162     auto string = adoptCF(CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(text), length, kCFStringEncodingUTF8, false, kCFAllocatorNull));
163     auto attributedString = adoptCF(CFAttributedStringCreate(kCFAllocatorDefault, string.get(), attributes.get()));
164     auto line = adoptCF(CTLineCreateWithAttributedString(attributedString.get()));
165     CGContextSetTextPosition(context, x, y);
166     CTLineDraw(line.get(), context);
167 }
168
169 Ref<PlatformCALayer> PlatformCALayer::createCompatibleLayerOrTakeFromPool(PlatformCALayer::LayerType layerType, PlatformCALayerClient* client, IntSize size)
170 {
171     if (auto layerFromPool = layerPool().takeLayerWithSize(size)) {
172         layerFromPool->setOwner(client);
173         return layerFromPool.releaseNonNull();
174     }
175
176     auto layer = createCompatibleLayer(layerType, client);
177     layer->setBounds(FloatRect(FloatPoint(), size));
178     return layer;
179 }
180
181 void PlatformCALayer::moveToLayerPool()
182 {
183     ASSERT(!superlayer());
184     layerPool().addLayer(this);
185 }
186
187 LayerPool& PlatformCALayer::layerPool()
188 {
189     static LayerPool* sharedPool = new LayerPool;
190     return *sharedPool;
191 }
192
193 TextStream& operator<<(TextStream& ts, PlatformCALayer::LayerType layerType)
194 {
195     switch (layerType) {
196     case PlatformCALayer::LayerTypeLayer:
197     case PlatformCALayer::LayerTypeWebLayer:
198     case PlatformCALayer::LayerTypeSimpleLayer:
199         ts << "layer";
200         break;
201     case PlatformCALayer::LayerTypeTransformLayer:
202         ts << "transform-layer";
203         break;
204     case PlatformCALayer::LayerTypeTiledBackingLayer:
205         ts << "tiled-backing-layer";
206         break;
207     case PlatformCALayer::LayerTypePageTiledBackingLayer:
208         ts << "page-tiled-backing-layer";
209         break;
210     case PlatformCALayer::LayerTypeTiledBackingTileLayer:
211         ts << "tiled-backing-tile";
212         break;
213     case PlatformCALayer::LayerTypeRootLayer:
214         ts << "root-layer";
215         break;
216     case PlatformCALayer::LayerTypeEditableImageLayer:
217         ts << "editable-image";
218         break;
219     case PlatformCALayer::LayerTypeBackdropLayer:
220         ts << "backdrop-layer";
221         break;
222     case PlatformCALayer::LayerTypeAVPlayerLayer:
223         ts << "av-player-layer";
224         break;
225     case PlatformCALayer::LayerTypeContentsProvidedLayer:
226         ts << "contents-provided-layer";
227         break;
228     case PlatformCALayer::LayerTypeShapeLayer:
229         ts << "shape-layer";
230         break;
231     case PlatformCALayer::LayerTypeScrollContainerLayer:
232         ts << "scroll-container-layer";
233         break;
234     case PlatformCALayer::LayerTypeCustom:
235         ts << "custom-layer";
236         break;
237     case PlatformCALayer::LayerTypeLightSystemBackdropLayer:
238         ts << "light-system-backdrop-layer";
239         break;
240     case PlatformCALayer::LayerTypeDarkSystemBackdropLayer:
241         ts << "dark-system-backdrop-layer";
242         break;
243     }
244     return ts;
245 }
246
247 TextStream& operator<<(TextStream& ts, PlatformCALayer::FilterType filterType)
248 {
249     switch (filterType) {
250     case PlatformCALayer::Linear:
251         ts << "linear";
252         break;
253     case PlatformCALayer::Nearest:
254         ts << "nearest";
255         break;
256     case PlatformCALayer::Trilinear:
257         ts << "trilinear";
258         break;
259     default:
260         ASSERT_NOT_REACHED();
261         break;
262     }
263     return ts;
264 }
265
266 }
267
268 #endif // USE(CA)