27ceed2e7117d81dc085419c739ecf8a2c9ea212
[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/StringExtras.h>
37 #include <wtf/text/TextStream.h>
38
39 #if PLATFORM(WIN)
40 #include <pal/spi/win/CoreTextSPIWin.h>
41 #endif
42
43 namespace WebCore {
44
45 static GraphicsLayer::PlatformLayerID generateLayerID()
46 {
47     static GraphicsLayer::PlatformLayerID layerID;
48     return ++layerID;
49 }
50
51 #if COMPILER(MSVC)
52 const float PlatformCALayer::webLayerWastedSpaceThreshold = 0.75f;
53 #endif
54
55 PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformCALayerClient* owner)
56     : m_layerType(layerType)
57     , m_layerID(generateLayerID())
58     , m_owner(owner)
59 {
60 }
61
62 PlatformCALayer::~PlatformCALayer()
63 {
64     // Clear the owner, which also clears it in the delegate to prevent attempts
65     // to use the GraphicsLayerCA after it has been destroyed.
66     setOwner(nullptr);
67 }
68
69 bool PlatformCALayer::canHaveBackingStore() const
70 {
71     return m_layerType == LayerType::LayerTypeWebLayer
72         || m_layerType == LayerType::LayerTypeTiledBackingLayer
73         || m_layerType == LayerType::LayerTypePageTiledBackingLayer
74         || m_layerType == LayerType::LayerTypeTiledBackingTileLayer;
75 }
76
77 void PlatformCALayer::drawRepaintIndicator(CGContextRef context, PlatformCALayer* platformCALayer, int repaintCount, CGColorRef customBackgroundColor)
78 {
79     char text[16]; // that's a lot of repaints
80     snprintf(text, sizeof(text), "%d", repaintCount);
81     
82     FloatRect indicatorBox = platformCALayer->bounds();\
83     indicatorBox.setLocation( { 1, 1 } );
84     indicatorBox.setSize(FloatSize(12 + 10 * strlen(text), 27));
85
86     CGContextStateSaver stateSaver(context);
87     
88     CGContextSetAlpha(context, 0.5f);
89     CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0);
90     
91     if (customBackgroundColor)
92         CGContextSetFillColorWithColor(context, customBackgroundColor);
93     else
94         CGContextSetRGBFillColor(context, 0, 0.5f, 0.25f, 1);
95     
96     if (platformCALayer->isOpaque())
97         CGContextFillRect(context, indicatorBox);
98     else {
99         Path boundsPath;
100         boundsPath.moveTo(indicatorBox.maxXMinYCorner());
101         boundsPath.addLineTo(indicatorBox.maxXMaxYCorner());
102         boundsPath.addLineTo(indicatorBox.minXMaxYCorner());
103
104         const float cornerChunk = 8;
105         boundsPath.addLineTo(FloatPoint(indicatorBox.x(), indicatorBox.y() + cornerChunk));
106         boundsPath.addLineTo(FloatPoint(indicatorBox.x() + cornerChunk, indicatorBox.y()));
107         boundsPath.closeSubpath();
108
109         CGContextAddPath(context, boundsPath.platformPath());
110         CGContextFillPath(context);
111     }
112
113     if (platformCALayer->owner()->isUsingDisplayListDrawing(platformCALayer)) {
114         CGContextSetRGBStrokeColor(context, 0, 0, 0, 0.65);
115         CGContextSetLineWidth(context, 2);
116         CGContextStrokeRect(context, indicatorBox);
117     }
118
119     CGFloat strokeWidthAsPercentageOfFontSize = 0;
120     Color strokeColor;
121
122     if (!platformCALayer->isOpaque() && platformCALayer->supportsSubpixelAntialiasedText() && platformCALayer->acceleratesDrawing()) {
123         strokeColor = Color(0, 0, 0, 200);
124         strokeWidthAsPercentageOfFontSize = -4.5; // Negative means "stroke and fill"; see docs for kCTStrokeWidthAttributeName.
125     }
126
127     if (platformCALayer->acceleratesDrawing())
128         CGContextSetRGBFillColor(context, 1, 0, 0, 1);
129     else
130         CGContextSetRGBFillColor(context, 1, 1, 1, 1);
131     
132     platformCALayer->drawTextAtPoint(context, indicatorBox.x() + 5, indicatorBox.y() + 22, CGSizeMake(1, -1), 22, text, strlen(text), strokeWidthAsPercentageOfFontSize, strokeColor);
133     
134     CGContextEndTransparencyLayer(context);
135 }
136
137 void PlatformCALayer::flipContext(CGContextRef context, CGFloat height)
138 {
139     CGContextScaleCTM(context, 1, -1);
140     CGContextTranslateCTM(context, 0, -height);
141 }
142
143 void PlatformCALayer::drawTextAtPoint(CGContextRef context, CGFloat x, CGFloat y, CGSize scale, CGFloat fontSize, const char* text, size_t length, CGFloat strokeWidthAsPercentageOfFontSize, Color strokeColor) const
144 {
145     auto matrix = CGAffineTransformMakeScale(scale.width, scale.height);
146     auto font = adoptCF(CTFontCreateWithName(CFSTR("Helvetica"), fontSize, &matrix));
147     auto strokeWidthNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &strokeWidthAsPercentageOfFontSize));
148
149     CFTypeRef keys[] = {
150         kCTFontAttributeName,
151         kCTForegroundColorFromContextAttributeName,
152         kCTStrokeWidthAttributeName,
153         kCTStrokeColorAttributeName,
154     };
155     CFTypeRef values[] = {
156         font.get(),
157         kCFBooleanTrue,
158         strokeWidthNumber.get(),
159         cachedCGColor(strokeColor),
160     };
161
162     auto attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
163     auto string = adoptCF(CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(text), length, kCFStringEncodingUTF8, false, kCFAllocatorNull));
164     auto attributedString = adoptCF(CFAttributedStringCreate(kCFAllocatorDefault, string.get(), attributes.get()));
165     auto line = adoptCF(CTLineCreateWithAttributedString(attributedString.get()));
166     CGContextSetTextPosition(context, x, y);
167     CTLineDraw(line.get(), context);
168 }
169
170 Ref<PlatformCALayer> PlatformCALayer::createCompatibleLayerOrTakeFromPool(PlatformCALayer::LayerType layerType, PlatformCALayerClient* client, IntSize size)
171 {
172     if (auto layerFromPool = layerPool().takeLayerWithSize(size)) {
173         layerFromPool->setOwner(client);
174         return layerFromPool.releaseNonNull();
175     }
176
177     auto layer = createCompatibleLayer(layerType, client);
178     layer->setBounds(FloatRect(FloatPoint(), size));
179     return layer;
180 }
181
182 void PlatformCALayer::moveToLayerPool()
183 {
184     ASSERT(!superlayer());
185     layerPool().addLayer(this);
186 }
187
188 LayerPool& PlatformCALayer::layerPool()
189 {
190     static LayerPool* sharedPool = new LayerPool;
191     return *sharedPool;
192 }
193
194 TextStream& operator<<(TextStream& ts, PlatformCALayer::LayerType layerType)
195 {
196     switch (layerType) {
197     case PlatformCALayer::LayerTypeLayer:
198     case PlatformCALayer::LayerTypeWebLayer:
199     case PlatformCALayer::LayerTypeSimpleLayer:
200         ts << "layer";
201         break;
202     case PlatformCALayer::LayerTypeTransformLayer:
203         ts << "transform-layer";
204         break;
205     case PlatformCALayer::LayerTypeTiledBackingLayer:
206         ts << "tiled-backing-layer";
207         break;
208     case PlatformCALayer::LayerTypePageTiledBackingLayer:
209         ts << "page-tiled-backing-layer";
210         break;
211     case PlatformCALayer::LayerTypeTiledBackingTileLayer:
212         ts << "tiled-backing-tile";
213         break;
214     case PlatformCALayer::LayerTypeRootLayer:
215         ts << "root-layer";
216         break;
217     case PlatformCALayer::LayerTypeBackdropLayer:
218         ts << "backdrop-layer";
219         break;
220     case PlatformCALayer::LayerTypeAVPlayerLayer:
221         ts << "av-player-layer";
222         break;
223     case PlatformCALayer::LayerTypeContentsProvidedLayer:
224         ts << "contents-provided-layer";
225         break;
226     case PlatformCALayer::LayerTypeShapeLayer:
227         ts << "shape-layer";
228         break;
229     case PlatformCALayer::LayerTypeScrollingLayer:
230         ts << "scrolling-layer";
231         break;
232     case PlatformCALayer::LayerTypeCustom:
233         ts << "custom-layer";
234         break;
235     case PlatformCALayer::LayerTypeLightSystemBackdropLayer:
236         ts << "light-system-backdrop-layer";
237         break;
238     case PlatformCALayer::LayerTypeDarkSystemBackdropLayer:
239         ts << "dark-system-backdrop-layer";
240         break;
241     }
242     return ts;
243 }
244
245 TextStream& operator<<(TextStream& ts, PlatformCALayer::FilterType filterType)
246 {
247     switch (filterType) {
248     case PlatformCALayer::Linear:
249         ts << "linear";
250         break;
251     case PlatformCALayer::Nearest:
252         ts << "nearest";
253         break;
254     case PlatformCALayer::Trilinear:
255         ts << "trilinear";
256         break;
257     default:
258         ASSERT_NOT_REACHED();
259         break;
260     }
261     return ts;
262 }
263
264 }
265
266 #endif // USE(CA)