1 | /* |
2 | * Copyright (C) 2003-2017 Apple Inc. All rights reserved. |
3 | * Copyright (C) 2008-2009 Torch Mobile, Inc. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * |
14 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
15 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ |
26 | |
27 | #pragma once |
28 | |
29 | #include "DashArray.h" |
30 | #include "FloatRect.h" |
31 | #include "FontCascade.h" |
32 | #include "Gradient.h" |
33 | #include "GraphicsTypes.h" |
34 | #include "Image.h" |
35 | #include "ImageOrientation.h" |
36 | #include "Pattern.h" |
37 | #include <wtf/Function.h> |
38 | #include <wtf/Noncopyable.h> |
39 | |
40 | #if USE(CG) |
41 | typedef struct CGContext PlatformGraphicsContext; |
42 | #elif USE(DIRECT2D) |
43 | interface ID2D1DCRenderTarget; |
44 | interface ID2D1RenderTarget; |
45 | interface ID2D1Factory; |
46 | interface ID2D1SolidColorBrush; |
47 | typedef ID2D1RenderTarget PlatformGraphicsContext; |
48 | #elif USE(CAIRO) |
49 | namespace WebCore { |
50 | class PlatformContextCairo; |
51 | } |
52 | typedef WebCore::PlatformContextCairo PlatformGraphicsContext; |
53 | #elif USE(WINGDI) |
54 | typedef struct HDC__ PlatformGraphicsContext; |
55 | #else |
56 | typedef void PlatformGraphicsContext; |
57 | #endif |
58 | |
59 | #if PLATFORM(WIN) |
60 | #include "DIBPixelData.h" |
61 | typedef struct HDC__* HDC; |
62 | #if !USE(CG) |
63 | // UInt8 is defined in CoreFoundation/CFBase.h |
64 | typedef unsigned char UInt8; |
65 | #endif |
66 | #endif |
67 | |
68 | // X11 header defines "None" as constant in macro and breakes the PaintInvalidationReasons enum's "None". |
69 | // As a workaround, we explicitly undef X11's None here. |
70 | #if defined(None) |
71 | #undef None |
72 | #endif |
73 | |
74 | namespace WebCore { |
75 | |
76 | #if USE(WINGDI) |
77 | class SharedBitmap; |
78 | class Font; |
79 | class GlyphBuffer; |
80 | #endif |
81 | |
82 | class AffineTransform; |
83 | class FloatRoundedRect; |
84 | class Gradient; |
85 | class GraphicsContextImpl; |
86 | class GraphicsContextPlatformPrivate; |
87 | class ImageBuffer; |
88 | class IntRect; |
89 | class RoundedRect; |
90 | class GraphicsContext3D; |
91 | class Path; |
92 | class TextRun; |
93 | class TransformationMatrix; |
94 | |
95 | enum TextDrawingMode { |
96 | TextModeFill = 1 << 0, |
97 | TextModeStroke = 1 << 1, |
98 | #if ENABLE(LETTERPRESS) |
99 | TextModeLetterpress = 1 << 2, |
100 | #endif |
101 | }; |
102 | typedef unsigned TextDrawingModeFlags; |
103 | |
104 | enum StrokeStyle { |
105 | NoStroke, |
106 | SolidStroke, |
107 | DottedStroke, |
108 | DashedStroke, |
109 | DoubleStroke, |
110 | WavyStroke, |
111 | }; |
112 | |
113 | struct DocumentMarkerLineStyle { |
114 | enum class Mode : uint8_t { |
115 | TextCheckingDictationPhraseWithAlternatives, |
116 | Spelling, |
117 | Grammar, |
118 | AutocorrectionReplacement, |
119 | DictationAlternatives |
120 | } mode; |
121 | bool shouldUseDarkAppearance { false }; |
122 | }; |
123 | |
124 | namespace DisplayList { |
125 | class Recorder; |
126 | } |
127 | |
128 | struct GraphicsContextState { |
129 | GraphicsContextState() |
130 | : shouldAntialias(true) |
131 | , shouldSmoothFonts(true) |
132 | , shouldSubpixelQuantizeFonts(true) |
133 | , shadowsIgnoreTransforms(false) |
134 | #if USE(CG) |
135 | // Core Graphics incorrectly renders shadows with radius > 8px (<rdar://problem/8103442>), |
136 | // but we need to preserve this buggy behavior for canvas and -webkit-box-shadow. |
137 | , shadowsUseLegacyRadius(false) |
138 | #endif |
139 | , drawLuminanceMask(false) |
140 | { |
141 | } |
142 | |
143 | enum Change : uint32_t { |
144 | NoChange = 0, |
145 | StrokeGradientChange = 1 << 1, |
146 | StrokePatternChange = 1 << 2, |
147 | FillGradientChange = 1 << 3, |
148 | FillPatternChange = 1 << 4, |
149 | StrokeThicknessChange = 1 << 5, |
150 | StrokeColorChange = 1 << 6, |
151 | StrokeStyleChange = 1 << 7, |
152 | FillColorChange = 1 << 8, |
153 | FillRuleChange = 1 << 9, |
154 | ShadowChange = 1 << 10, |
155 | ShadowColorChange = 1 << 11, |
156 | ShadowsIgnoreTransformsChange = 1 << 12, |
157 | AlphaChange = 1 << 13, |
158 | CompositeOperationChange = 1 << 14, |
159 | BlendModeChange = 1 << 15, |
160 | TextDrawingModeChange = 1 << 16, |
161 | ShouldAntialiasChange = 1 << 17, |
162 | ShouldSmoothFontsChange = 1 << 18, |
163 | ShouldSubpixelQuantizeFontsChange = 1 << 19, |
164 | DrawLuminanceMaskChange = 1 << 20, |
165 | ImageInterpolationQualityChange = 1 << 21, |
166 | #if HAVE(OS_DARK_MODE_SUPPORT) |
167 | UseDarkAppearanceChange = 1 << 22, |
168 | #endif |
169 | }; |
170 | typedef uint32_t StateChangeFlags; |
171 | |
172 | RefPtr<Gradient> strokeGradient; |
173 | RefPtr<Pattern> strokePattern; |
174 | |
175 | RefPtr<Gradient> fillGradient; |
176 | RefPtr<Pattern> fillPattern; |
177 | |
178 | FloatSize shadowOffset; |
179 | |
180 | float strokeThickness { 0 }; |
181 | float shadowBlur { 0 }; |
182 | |
183 | TextDrawingModeFlags textDrawingMode { TextModeFill }; |
184 | |
185 | Color strokeColor { Color::black }; |
186 | Color fillColor { Color::black }; |
187 | Color shadowColor; |
188 | |
189 | StrokeStyle strokeStyle { SolidStroke }; |
190 | WindRule fillRule { WindRule::NonZero }; |
191 | |
192 | float alpha { 1 }; |
193 | CompositeOperator compositeOperator { CompositeSourceOver }; |
194 | BlendMode blendMode { BlendMode::Normal }; |
195 | InterpolationQuality imageInterpolationQuality { InterpolationDefault }; |
196 | |
197 | bool shouldAntialias : 1; |
198 | bool shouldSmoothFonts : 1; |
199 | bool shouldSubpixelQuantizeFonts : 1; |
200 | bool shadowsIgnoreTransforms : 1; |
201 | #if USE(CG) |
202 | bool shadowsUseLegacyRadius : 1; |
203 | #endif |
204 | bool drawLuminanceMask : 1; |
205 | #if HAVE(OS_DARK_MODE_SUPPORT) |
206 | bool useDarkAppearance : 1; |
207 | #endif |
208 | }; |
209 | |
210 | struct ImagePaintingOptions { |
211 | ImagePaintingOptions(CompositeOperator compositeOperator = CompositeSourceOver, BlendMode blendMode = BlendMode::Normal, DecodingMode decodingMode = DecodingMode::Synchronous, ImageOrientationDescription orientationDescription = ImageOrientationDescription(), InterpolationQuality interpolationQuality = InterpolationDefault) |
212 | : m_compositeOperator(compositeOperator) |
213 | , m_blendMode(blendMode) |
214 | , m_decodingMode(decodingMode) |
215 | , m_orientationDescription(orientationDescription) |
216 | , m_interpolationQuality(interpolationQuality) |
217 | { |
218 | } |
219 | |
220 | ImagePaintingOptions(ImageOrientationDescription orientationDescription, InterpolationQuality interpolationQuality = InterpolationDefault, CompositeOperator compositeOperator = CompositeSourceOver, BlendMode blendMode = BlendMode::Normal, DecodingMode decodingMode = DecodingMode::Synchronous) |
221 | : m_compositeOperator(compositeOperator) |
222 | , m_blendMode(blendMode) |
223 | , m_decodingMode(decodingMode) |
224 | , m_orientationDescription(orientationDescription) |
225 | , m_interpolationQuality(interpolationQuality) |
226 | { |
227 | } |
228 | |
229 | ImagePaintingOptions(InterpolationQuality interpolationQuality, ImageOrientationDescription orientationDescription = ImageOrientationDescription(), CompositeOperator compositeOperator = CompositeSourceOver, BlendMode blendMode = BlendMode::Normal, DecodingMode decodingMode = DecodingMode::Synchronous) |
230 | : m_compositeOperator(compositeOperator) |
231 | , m_blendMode(blendMode) |
232 | , m_decodingMode(decodingMode) |
233 | , m_orientationDescription(orientationDescription) |
234 | , m_interpolationQuality(interpolationQuality) |
235 | { |
236 | } |
237 | |
238 | bool usesDefaultInterpolation() const { return m_interpolationQuality == InterpolationDefault; } |
239 | |
240 | CompositeOperator m_compositeOperator; |
241 | BlendMode m_blendMode; |
242 | DecodingMode m_decodingMode; |
243 | ImageOrientationDescription m_orientationDescription; |
244 | InterpolationQuality m_interpolationQuality; |
245 | }; |
246 | |
247 | struct GraphicsContextStateChange { |
248 | GraphicsContextStateChange() = default; |
249 | GraphicsContextStateChange(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags) |
250 | : m_state(state) |
251 | , m_changeFlags(flags) |
252 | { |
253 | } |
254 | |
255 | GraphicsContextState::StateChangeFlags changesFromState(const GraphicsContextState&) const; |
256 | |
257 | void accumulate(const GraphicsContextState&, GraphicsContextState::StateChangeFlags); |
258 | void apply(GraphicsContext&) const; |
259 | |
260 | void dump(WTF::TextStream&) const; |
261 | |
262 | GraphicsContextState m_state; |
263 | GraphicsContextState::StateChangeFlags m_changeFlags { GraphicsContextState::NoChange }; |
264 | }; |
265 | |
266 | WTF::TextStream& operator<<(WTF::TextStream&, const GraphicsContextStateChange&); |
267 | |
268 | |
269 | class GraphicsContext { |
270 | WTF_MAKE_NONCOPYABLE(GraphicsContext); WTF_MAKE_FAST_ALLOCATED; |
271 | public: |
272 | WEBCORE_EXPORT GraphicsContext(PlatformGraphicsContext*); |
273 | |
274 | using GraphicsContextImplFactory = WTF::Function<std::unique_ptr<GraphicsContextImpl>(GraphicsContext&)>; |
275 | WEBCORE_EXPORT GraphicsContext(const GraphicsContextImplFactory&); |
276 | |
277 | GraphicsContext() = default; |
278 | WEBCORE_EXPORT ~GraphicsContext(); |
279 | |
280 | enum class PaintInvalidationReasons : uint8_t { |
281 | None, |
282 | InvalidatingControlTints, |
283 | InvalidatingImagesWithAsyncDecodes |
284 | }; |
285 | GraphicsContext(PaintInvalidationReasons); |
286 | |
287 | WEBCORE_EXPORT bool hasPlatformContext() const; |
288 | WEBCORE_EXPORT PlatformGraphicsContext* platformContext() const; |
289 | |
290 | bool paintingDisabled() const { return !m_data && !m_impl; } |
291 | bool performingPaintInvalidation() const { return m_paintInvalidationReasons != PaintInvalidationReasons::None; } |
292 | bool invalidatingControlTints() const { return m_paintInvalidationReasons == PaintInvalidationReasons::InvalidatingControlTints; } |
293 | bool invalidatingImagesWithAsyncDecodes() const { return m_paintInvalidationReasons == PaintInvalidationReasons::InvalidatingImagesWithAsyncDecodes; } |
294 | |
295 | WEBCORE_EXPORT void setStrokeThickness(float); |
296 | float strokeThickness() const { return m_state.strokeThickness; } |
297 | |
298 | void setStrokeStyle(StrokeStyle); |
299 | StrokeStyle strokeStyle() const { return m_state.strokeStyle; } |
300 | |
301 | WEBCORE_EXPORT void setStrokeColor(const Color&); |
302 | const Color& strokeColor() const { return m_state.strokeColor; } |
303 | |
304 | void setStrokePattern(Ref<Pattern>&&); |
305 | Pattern* strokePattern() const { return m_state.strokePattern.get(); } |
306 | |
307 | void setStrokeGradient(Ref<Gradient>&&); |
308 | RefPtr<Gradient> strokeGradient() const { return m_state.strokeGradient; } |
309 | |
310 | void setFillRule(WindRule); |
311 | WindRule fillRule() const { return m_state.fillRule; } |
312 | |
313 | WEBCORE_EXPORT void setFillColor(const Color&); |
314 | const Color& fillColor() const { return m_state.fillColor; } |
315 | |
316 | void setFillPattern(Ref<Pattern>&&); |
317 | Pattern* fillPattern() const { return m_state.fillPattern.get(); } |
318 | |
319 | WEBCORE_EXPORT void setFillGradient(Ref<Gradient>&&); |
320 | RefPtr<Gradient> fillGradient() const { return m_state.fillGradient; } |
321 | |
322 | void setShadowsIgnoreTransforms(bool); |
323 | bool shadowsIgnoreTransforms() const { return m_state.shadowsIgnoreTransforms; } |
324 | |
325 | WEBCORE_EXPORT void setShouldAntialias(bool); |
326 | bool shouldAntialias() const { return m_state.shouldAntialias; } |
327 | |
328 | WEBCORE_EXPORT void setShouldSmoothFonts(bool); |
329 | bool shouldSmoothFonts() const { return m_state.shouldSmoothFonts; } |
330 | |
331 | // Normally CG enables subpixel-quantization because it improves the performance of aligning glyphs. |
332 | // In some cases we have to disable to to ensure a high-quality output of the glyphs. |
333 | void setShouldSubpixelQuantizeFonts(bool); |
334 | bool shouldSubpixelQuantizeFonts() const { return m_state.shouldSubpixelQuantizeFonts; } |
335 | |
336 | const GraphicsContextState& state() const { return m_state; } |
337 | |
338 | #if USE(CG) || USE(DIRECT2D) || USE(CAIRO) |
339 | WEBCORE_EXPORT void drawNativeImage(const NativeImagePtr&, const FloatSize& selfSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, BlendMode = BlendMode::Normal, ImageOrientation = ImageOrientation()); |
340 | #endif |
341 | |
342 | #if USE(CG) || USE(DIRECT2D) |
343 | void applyStrokePattern(); |
344 | void applyFillPattern(); |
345 | void drawPath(const Path&); |
346 | |
347 | WEBCORE_EXPORT void setIsCALayerContext(bool); |
348 | bool isCALayerContext() const; |
349 | |
350 | WEBCORE_EXPORT void setIsAcceleratedContext(bool); |
351 | #endif |
352 | bool isAcceleratedContext() const; |
353 | RenderingMode renderingMode() const { return isAcceleratedContext() ? Accelerated : Unaccelerated; } |
354 | |
355 | WEBCORE_EXPORT void save(); |
356 | WEBCORE_EXPORT void restore(); |
357 | |
358 | // These draw methods will do both stroking and filling. |
359 | // FIXME: ...except drawRect(), which fills properly but always strokes |
360 | // using a 1-pixel stroke inset from the rect borders (of the correct |
361 | // stroke color). |
362 | void drawRect(const FloatRect&, float borderThickness = 1); |
363 | void drawLine(const FloatPoint&, const FloatPoint&); |
364 | |
365 | void drawEllipse(const FloatRect&); |
366 | void drawRaisedEllipse(const FloatRect&, const Color& ellipseColor, const Color& shadowColor); |
367 | |
368 | WEBCORE_EXPORT void fillPath(const Path&); |
369 | WEBCORE_EXPORT void strokePath(const Path&); |
370 | |
371 | void fillEllipse(const FloatRect&); |
372 | void strokeEllipse(const FloatRect&); |
373 | |
374 | WEBCORE_EXPORT void fillRect(const FloatRect&); |
375 | WEBCORE_EXPORT void fillRect(const FloatRect&, const Color&); |
376 | void fillRect(const FloatRect&, Gradient&); |
377 | void fillRect(const FloatRect&, const Color&, CompositeOperator, BlendMode = BlendMode::Normal); |
378 | void fillRoundedRect(const FloatRoundedRect&, const Color&, BlendMode = BlendMode::Normal); |
379 | void fillRectWithRoundedHole(const FloatRect&, const FloatRoundedRect& roundedHoleRect, const Color&); |
380 | |
381 | WEBCORE_EXPORT void clearRect(const FloatRect&); |
382 | |
383 | WEBCORE_EXPORT void strokeRect(const FloatRect&, float lineWidth); |
384 | |
385 | WEBCORE_EXPORT ImageDrawResult drawImage(Image&, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
386 | WEBCORE_EXPORT ImageDrawResult drawImage(Image&, const FloatRect& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
387 | ImageDrawResult drawImage(Image&, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& = ImagePaintingOptions()); |
388 | |
389 | ImageDrawResult drawTiledImage(Image&, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& = ImagePaintingOptions()); |
390 | ImageDrawResult drawTiledImage(Image&, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor, |
391 | Image::TileRule, Image::TileRule, const ImagePaintingOptions& = ImagePaintingOptions()); |
392 | |
393 | WEBCORE_EXPORT void drawImageBuffer(ImageBuffer&, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
394 | void drawImageBuffer(ImageBuffer&, const FloatRect& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
395 | void drawImageBuffer(ImageBuffer&, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& = ImagePaintingOptions()); |
396 | |
397 | void drawPattern(Image&, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform&, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode = BlendMode::Normal); |
398 | |
399 | WEBCORE_EXPORT void drawConsumingImageBuffer(std::unique_ptr<ImageBuffer>, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
400 | void drawConsumingImageBuffer(std::unique_ptr<ImageBuffer>, const FloatRect& destination, const ImagePaintingOptions& = ImagePaintingOptions()); |
401 | void drawConsumingImageBuffer(std::unique_ptr<ImageBuffer>, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& = ImagePaintingOptions()); |
402 | |
403 | WEBCORE_EXPORT void setImageInterpolationQuality(InterpolationQuality); |
404 | InterpolationQuality imageInterpolationQuality() const { return m_state.imageInterpolationQuality; } |
405 | |
406 | WEBCORE_EXPORT void clip(const FloatRect&); |
407 | void clipRoundedRect(const FloatRoundedRect&); |
408 | |
409 | void clipOut(const FloatRect&); |
410 | void clipOutRoundedRect(const FloatRoundedRect&); |
411 | void clipPath(const Path&, WindRule = WindRule::EvenOdd); |
412 | void clipToImageBuffer(ImageBuffer&, const FloatRect&); |
413 | |
414 | IntRect clipBounds() const; |
415 | |
416 | void setTextDrawingMode(TextDrawingModeFlags); |
417 | TextDrawingModeFlags textDrawingMode() const { return m_state.textDrawingMode; } |
418 | |
419 | #if HAVE(OS_DARK_MODE_SUPPORT) |
420 | void setUseDarkAppearance(bool); |
421 | bool useDarkAppearance() const { return m_state.useDarkAppearance; } |
422 | #endif |
423 | |
424 | float drawText(const FontCascade&, const TextRun&, const FloatPoint&, unsigned from = 0, Optional<unsigned> to = WTF::nullopt); |
425 | void drawGlyphs(const Font&, const GlyphBuffer&, unsigned from, unsigned numGlyphs, const FloatPoint&, FontSmoothingMode); |
426 | void drawEmphasisMarks(const FontCascade&, const TextRun&, const AtomString& mark, const FloatPoint&, unsigned from = 0, Optional<unsigned> to = WTF::nullopt); |
427 | void drawBidiText(const FontCascade&, const TextRun&, const FloatPoint&, FontCascade::CustomFontNotReadyAction = FontCascade::DoNotPaintIfFontNotReady); |
428 | |
429 | void applyState(const GraphicsContextState&); |
430 | |
431 | enum RoundingMode { |
432 | RoundAllSides, |
433 | RoundOriginAndDimensions |
434 | }; |
435 | FloatRect roundToDevicePixels(const FloatRect&, RoundingMode = RoundAllSides); |
436 | |
437 | FloatRect computeUnderlineBoundsForText(const FloatRect&, bool printing); |
438 | WEBCORE_EXPORT void drawLineForText(const FloatRect&, bool printing, bool doubleLines = false, StrokeStyle = SolidStroke); |
439 | void drawLinesForText(const FloatPoint&, float thickness, const DashArray& widths, bool printing, bool doubleLines = false, StrokeStyle = SolidStroke); |
440 | void drawDotsForDocumentMarker(const FloatRect&, DocumentMarkerLineStyle); |
441 | |
442 | WEBCORE_EXPORT void beginTransparencyLayer(float opacity); |
443 | WEBCORE_EXPORT void endTransparencyLayer(); |
444 | bool isInTransparencyLayer() const { return (m_transparencyCount > 0) && supportsTransparencyLayers(); } |
445 | |
446 | WEBCORE_EXPORT void setShadow(const FloatSize&, float blur, const Color&); |
447 | // Legacy shadow blur radius is used for canvas, and -webkit-box-shadow. |
448 | // It has different treatment of radii > 8px. |
449 | void setLegacyShadow(const FloatSize&, float blur, const Color&); |
450 | |
451 | WEBCORE_EXPORT void clearShadow(); |
452 | bool getShadow(FloatSize&, float&, Color&) const; |
453 | |
454 | bool hasVisibleShadow() const { return m_state.shadowColor.isVisible(); } |
455 | bool hasShadow() const { return hasVisibleShadow() && (m_state.shadowBlur || m_state.shadowOffset.width() || m_state.shadowOffset.height()); } |
456 | bool hasBlurredShadow() const { return hasVisibleShadow() && m_state.shadowBlur; } |
457 | |
458 | void drawFocusRing(const Vector<FloatRect>&, float width, float offset, const Color&); |
459 | void drawFocusRing(const Path&, float width, float offset, const Color&); |
460 | #if PLATFORM(MAC) |
461 | void drawFocusRing(const Path&, double timeOffset, bool& needsRedraw, const Color&); |
462 | void drawFocusRing(const Vector<FloatRect>&, double timeOffset, bool& needsRedraw, const Color&); |
463 | #endif |
464 | |
465 | void setLineCap(LineCap); |
466 | void setLineDash(const DashArray&, float dashOffset); |
467 | void setLineJoin(LineJoin); |
468 | void setMiterLimit(float); |
469 | |
470 | void setAlpha(float); |
471 | float alpha() const { return m_state.alpha; } |
472 | |
473 | WEBCORE_EXPORT void setCompositeOperation(CompositeOperator, BlendMode = BlendMode::Normal); |
474 | CompositeOperator compositeOperation() const { return m_state.compositeOperator; } |
475 | BlendMode blendModeOperation() const { return m_state.blendMode; } |
476 | |
477 | void setDrawLuminanceMask(bool); |
478 | bool drawLuminanceMask() const { return m_state.drawLuminanceMask; } |
479 | |
480 | // This clip function is used only by <canvas> code. It allows |
481 | // implementations to handle clipping on the canvas differently since |
482 | // the discipline is different. |
483 | void canvasClip(const Path&, WindRule = WindRule::EvenOdd); |
484 | void clipOut(const Path&); |
485 | |
486 | void scale(float s) |
487 | { |
488 | scale({ s, s }); |
489 | } |
490 | WEBCORE_EXPORT void scale(const FloatSize&); |
491 | void rotate(float angleInRadians); |
492 | void translate(const FloatSize& size) { translate(size.width(), size.height()); } |
493 | void translate(const FloatPoint& p) { translate(p.x(), p.y()); } |
494 | WEBCORE_EXPORT void translate(float x, float y); |
495 | |
496 | void setURLForRect(const URL&, const FloatRect&); |
497 | |
498 | void setDestinationForRect(const String& name, const FloatRect&); |
499 | void addDestinationAtPoint(const String& name, const FloatPoint&); |
500 | |
501 | void concatCTM(const AffineTransform&); |
502 | void setCTM(const AffineTransform&); |
503 | |
504 | enum IncludeDeviceScale { DefinitelyIncludeDeviceScale, PossiblyIncludeDeviceScale }; |
505 | AffineTransform getCTM(IncludeDeviceScale includeScale = PossiblyIncludeDeviceScale) const; |
506 | |
507 | // This function applies the device scale factor to the context, making the context capable of |
508 | // acting as a base-level context for a HiDPI environment. |
509 | WEBCORE_EXPORT void applyDeviceScaleFactor(float); |
510 | void platformApplyDeviceScaleFactor(float); |
511 | FloatSize scaleFactor() const; |
512 | FloatSize scaleFactorForDrawing(const FloatRect& destRect, const FloatRect& srcRect) const; |
513 | |
514 | #if OS(WINDOWS) |
515 | HDC getWindowsContext(const IntRect&, bool supportAlphaBlend); // The passed in rect is used to create a bitmap for compositing inside transparency layers. |
516 | void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend); // The passed in HDC should be the one handed back by getWindowsContext. |
517 | HDC hdc() const; |
518 | #if PLATFORM(WIN) |
519 | #if USE(WINGDI) |
520 | const AffineTransform& affineTransform() const; |
521 | AffineTransform& affineTransform(); |
522 | void resetAffineTransform(); |
523 | void fillRect(const FloatRect&, const Gradient*); |
524 | void drawText(const Font&, const GlyphBuffer&, int from, int numGlyphs, const FloatPoint&); |
525 | void drawFrameControl(const IntRect& rect, unsigned type, unsigned state); |
526 | void drawFocusRect(const IntRect& rect); |
527 | void paintTextField(const IntRect& rect, unsigned state); |
528 | void drawBitmap(SharedBitmap*, const IntRect& dstRect, const IntRect& srcRect, CompositeOperator, BlendMode); |
529 | void drawBitmapPattern(SharedBitmap*, const FloatRect& tileRectIn, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& destRect, const IntSize& origSourceSize); |
530 | void drawIcon(HICON icon, const IntRect& dstRect, UINT flags); |
531 | void drawRoundCorner(bool newClip, RECT clipRect, RECT rectWin, HDC dc, int width, int height); |
532 | #else |
533 | GraphicsContext(HDC, bool hasAlpha = false); // FIXME: To be removed. |
534 | |
535 | // When set to true, child windows should be rendered into this context |
536 | // rather than allowing them just to render to the screen. Defaults to |
537 | // false. |
538 | // FIXME: This is a layering violation. GraphicsContext shouldn't know |
539 | // what a "window" is. It would be much more appropriate for this flag |
540 | // to be passed as a parameter alongside the GraphicsContext, but doing |
541 | // that would require lots of changes in cross-platform code that we |
542 | // aren't sure we want to make. |
543 | void setShouldIncludeChildWindows(bool); |
544 | bool shouldIncludeChildWindows() const; |
545 | |
546 | class WindowsBitmap { |
547 | WTF_MAKE_NONCOPYABLE(WindowsBitmap); |
548 | public: |
549 | WindowsBitmap(HDC, const IntSize&); |
550 | ~WindowsBitmap(); |
551 | |
552 | HDC hdc() const { return m_hdc; } |
553 | UInt8* buffer() const { return m_pixelData.buffer(); } |
554 | unsigned bufferLength() const { return m_pixelData.bufferLength(); } |
555 | const IntSize& size() const { return m_pixelData.size(); } |
556 | unsigned bytesPerRow() const { return m_pixelData.bytesPerRow(); } |
557 | unsigned short bitsPerPixel() const { return m_pixelData.bitsPerPixel(); } |
558 | const DIBPixelData& windowsDIB() const { return m_pixelData; } |
559 | |
560 | private: |
561 | HDC m_hdc; |
562 | HBITMAP m_bitmap; |
563 | DIBPixelData m_pixelData; |
564 | }; |
565 | |
566 | std::unique_ptr<WindowsBitmap> createWindowsBitmap(const IntSize&); |
567 | // The bitmap should be non-premultiplied. |
568 | void drawWindowsBitmap(WindowsBitmap*, const IntPoint&); |
569 | #endif |
570 | #if USE(DIRECT2D) |
571 | GraphicsContext(HDC, ID2D1DCRenderTarget**, RECT, bool hasAlpha = false); // FIXME: To be removed. |
572 | |
573 | WEBCORE_EXPORT static ID2D1Factory* systemFactory(); |
574 | WEBCORE_EXPORT static ID2D1RenderTarget* defaultRenderTarget(); |
575 | |
576 | WEBCORE_EXPORT void beginDraw(); |
577 | D2D1_COLOR_F colorWithGlobalAlpha(const Color&) const; |
578 | WEBCORE_EXPORT void endDraw(); |
579 | void flush(); |
580 | |
581 | ID2D1Brush* solidStrokeBrush() const; |
582 | ID2D1Brush* solidFillBrush() const; |
583 | ID2D1Brush* patternStrokeBrush() const; |
584 | ID2D1Brush* patternFillBrush() const; |
585 | ID2D1StrokeStyle* platformStrokeStyle() const; |
586 | |
587 | ID2D1SolidColorBrush* brushWithColor(const Color&); |
588 | #endif |
589 | #else // PLATFORM(WIN) |
590 | bool shouldIncludeChildWindows() const { return false; } |
591 | #endif // PLATFORM(WIN) |
592 | #endif // OS(WINDOWS) |
593 | |
594 | static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle); |
595 | |
596 | bool supportsInternalLinks() const; |
597 | |
598 | private: |
599 | void platformInit(PlatformGraphicsContext*); |
600 | void platformDestroy(); |
601 | |
602 | #if PLATFORM(WIN) && !USE(WINGDI) |
603 | void platformInit(HDC, bool hasAlpha = false); |
604 | #endif |
605 | |
606 | #if USE(DIRECT2D) |
607 | void platformInit(HDC, ID2D1RenderTarget**, RECT, bool hasAlpha = false); |
608 | void drawWithoutShadow(const FloatRect& boundingRect, const WTF::Function<void(ID2D1RenderTarget*)>&); |
609 | void drawWithShadow(const FloatRect& boundingRect, const WTF::Function<void(ID2D1RenderTarget*)>&); |
610 | #endif |
611 | |
612 | void savePlatformState(); |
613 | void restorePlatformState(); |
614 | |
615 | void setPlatformTextDrawingMode(TextDrawingModeFlags); |
616 | |
617 | void setPlatformStrokeColor(const Color&); |
618 | void setPlatformStrokeStyle(StrokeStyle); |
619 | void setPlatformStrokeThickness(float); |
620 | |
621 | void setPlatformFillColor(const Color&); |
622 | |
623 | void setPlatformShouldAntialias(bool); |
624 | void setPlatformShouldSmoothFonts(bool); |
625 | void setPlatformImageInterpolationQuality(InterpolationQuality); |
626 | |
627 | void setPlatformShadow(const FloatSize&, float blur, const Color&); |
628 | void clearPlatformShadow(); |
629 | |
630 | void setPlatformAlpha(float); |
631 | void setPlatformCompositeOperation(CompositeOperator, BlendMode = BlendMode::Normal); |
632 | |
633 | void beginPlatformTransparencyLayer(float opacity); |
634 | void endPlatformTransparencyLayer(); |
635 | static bool supportsTransparencyLayers(); |
636 | |
637 | void fillEllipseAsPath(const FloatRect&); |
638 | void strokeEllipseAsPath(const FloatRect&); |
639 | |
640 | void platformFillEllipse(const FloatRect&); |
641 | void platformStrokeEllipse(const FloatRect&); |
642 | |
643 | void platformFillRoundedRect(const FloatRoundedRect&, const Color&); |
644 | |
645 | FloatRect computeLineBoundsAndAntialiasingModeForText(const FloatRect&, bool printing, Color&); |
646 | |
647 | float dashedLineCornerWidthForStrokeWidth(float) const; |
648 | float dashedLinePatternWidthForStrokeWidth(float) const; |
649 | float dashedLinePatternOffsetForPatternAndStrokeWidth(float patternWidth, float strokeWidth) const; |
650 | Vector<FloatPoint> centerLineAndCutOffCorners(bool isVerticalLine, float cornerWidth, FloatPoint point1, FloatPoint point2) const; |
651 | |
652 | GraphicsContextPlatformPrivate* m_data { nullptr }; |
653 | std::unique_ptr<GraphicsContextImpl> m_impl; |
654 | |
655 | GraphicsContextState m_state; |
656 | Vector<GraphicsContextState, 1> m_stack; |
657 | |
658 | const PaintInvalidationReasons m_paintInvalidationReasons { PaintInvalidationReasons::None }; |
659 | unsigned m_transparencyCount { 0 }; |
660 | }; |
661 | |
662 | class GraphicsContextStateSaver { |
663 | WTF_MAKE_FAST_ALLOCATED; |
664 | public: |
665 | GraphicsContextStateSaver(GraphicsContext& context, bool saveAndRestore = true) |
666 | : m_context(context) |
667 | , m_saveAndRestore(saveAndRestore) |
668 | { |
669 | if (m_saveAndRestore) |
670 | m_context.save(); |
671 | } |
672 | |
673 | ~GraphicsContextStateSaver() |
674 | { |
675 | if (m_saveAndRestore) |
676 | m_context.restore(); |
677 | } |
678 | |
679 | void save() |
680 | { |
681 | ASSERT(!m_saveAndRestore); |
682 | m_context.save(); |
683 | m_saveAndRestore = true; |
684 | } |
685 | |
686 | void restore() |
687 | { |
688 | ASSERT(m_saveAndRestore); |
689 | m_context.restore(); |
690 | m_saveAndRestore = false; |
691 | } |
692 | |
693 | GraphicsContext* context() const { return &m_context; } |
694 | |
695 | private: |
696 | GraphicsContext& m_context; |
697 | bool m_saveAndRestore; |
698 | }; |
699 | |
700 | class InterpolationQualityMaintainer { |
701 | public: |
702 | explicit InterpolationQualityMaintainer(GraphicsContext& graphicsContext, InterpolationQuality interpolationQualityToUse) |
703 | : m_graphicsContext(graphicsContext) |
704 | , m_currentInterpolationQuality(graphicsContext.imageInterpolationQuality()) |
705 | , m_interpolationQualityChanged(interpolationQualityToUse != InterpolationDefault && m_currentInterpolationQuality != interpolationQualityToUse) |
706 | { |
707 | if (m_interpolationQualityChanged) |
708 | m_graphicsContext.setImageInterpolationQuality(interpolationQualityToUse); |
709 | } |
710 | |
711 | explicit InterpolationQualityMaintainer(GraphicsContext& graphicsContext, Optional<InterpolationQuality> interpolationQuality) |
712 | : InterpolationQualityMaintainer(graphicsContext, interpolationQuality ? interpolationQuality.value() : graphicsContext.imageInterpolationQuality()) |
713 | { |
714 | } |
715 | |
716 | ~InterpolationQualityMaintainer() |
717 | { |
718 | if (m_interpolationQualityChanged) |
719 | m_graphicsContext.setImageInterpolationQuality(m_currentInterpolationQuality); |
720 | } |
721 | |
722 | private: |
723 | GraphicsContext& m_graphicsContext; |
724 | InterpolationQuality m_currentInterpolationQuality; |
725 | bool m_interpolationQualityChanged; |
726 | }; |
727 | |
728 | } // namespace WebCore |
729 | |