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)
41typedef struct CGContext PlatformGraphicsContext;
42#elif USE(DIRECT2D)
43interface ID2D1DCRenderTarget;
44interface ID2D1RenderTarget;
45interface ID2D1Factory;
46interface ID2D1SolidColorBrush;
47typedef ID2D1RenderTarget PlatformGraphicsContext;
48#elif USE(CAIRO)
49namespace WebCore {
50class PlatformContextCairo;
51}
52typedef WebCore::PlatformContextCairo PlatformGraphicsContext;
53#elif USE(WINGDI)
54typedef struct HDC__ PlatformGraphicsContext;
55#else
56typedef void PlatformGraphicsContext;
57#endif
58
59#if PLATFORM(WIN)
60#include "DIBPixelData.h"
61typedef struct HDC__* HDC;
62#if !USE(CG)
63// UInt8 is defined in CoreFoundation/CFBase.h
64typedef 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
74namespace WebCore {
75
76#if USE(WINGDI)
77class SharedBitmap;
78class Font;
79class GlyphBuffer;
80#endif
81
82class AffineTransform;
83class FloatRoundedRect;
84class Gradient;
85class GraphicsContextImpl;
86class GraphicsContextPlatformPrivate;
87class ImageBuffer;
88class IntRect;
89class RoundedRect;
90class GraphicsContext3D;
91class Path;
92class TextRun;
93class TransformationMatrix;
94
95enum TextDrawingMode {
96 TextModeFill = 1 << 0,
97 TextModeStroke = 1 << 1,
98#if ENABLE(LETTERPRESS)
99 TextModeLetterpress = 1 << 2,
100#endif
101};
102typedef unsigned TextDrawingModeFlags;
103
104enum StrokeStyle {
105 NoStroke,
106 SolidStroke,
107 DottedStroke,
108 DashedStroke,
109 DoubleStroke,
110 WavyStroke,
111};
112
113struct 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
124namespace DisplayList {
125class Recorder;
126}
127
128struct 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
210struct 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
247struct 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
266WTF::TextStream& operator<<(WTF::TextStream&, const GraphicsContextStateChange&);
267
268
269class GraphicsContext {
270 WTF_MAKE_NONCOPYABLE(GraphicsContext); WTF_MAKE_FAST_ALLOCATED;
271public:
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
598private:
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
662class GraphicsContextStateSaver {
663 WTF_MAKE_FAST_ALLOCATED;
664public:
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
695private:
696 GraphicsContext& m_context;
697 bool m_saveAndRestore;
698};
699
700class InterpolationQualityMaintainer {
701public:
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
722private:
723 GraphicsContext& m_graphicsContext;
724 InterpolationQuality m_currentInterpolationQuality;
725 bool m_interpolationQualityChanged;
726};
727
728} // namespace WebCore
729